This is an automated email from the ASF dual-hosted git repository.
dlmarion pushed a commit to branch 2.1
in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/2.1 by this push:
new 88abe226fd Log warning when durability not sync for root and meta
tables (#5988)
88abe226fd is described below
commit 88abe226fd9ca3d04d27d12a0b160b0c09d0f542
Author: Dave Marion <[email protected]>
AuthorDate: Fri Dec 5 11:10:31 2025 -0500
Log warning when durability not sync for root and meta tables (#5988)
Related to #4455
---
.../org/apache/accumulo/core/conf/Property.java | 17 ++++++---
.../apache/accumulo/core/file/FileOperations.java | 40 ++++++++++++++++------
.../accumulo/core/file/rfile/RFileOperations.java | 17 +++++++++
.../accumulo/server/compaction/FileCompactor.java | 2 +-
.../server/init/FileSystemInitializer.java | 9 ++---
.../accumulo/tserver/TabletClientHandler.java | 12 +++++--
6 files changed, 75 insertions(+), 22 deletions(-)
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/Property.java
b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
index 81e5a87532..9cd510fbd0 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/Property.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
@@ -1283,10 +1283,19 @@ public enum Property {
+ " when the tablet metadata distance is above the supplied value.",
"2.1.4"),
TABLE_DURABILITY("table.durability", "sync", PropertyType.DURABILITY,
- "The durability used to write to the write-ahead log. Legal values are:"
- + " none, which skips the write-ahead log; log, which sends the data
to the"
- + " write-ahead log, but does nothing to make it durable; flush,
which pushes"
- + " data to the file system; and sync, which ensures the data is
written to disk.",
+ "The durability of writes to tables includes ensuring that mutations
written"
+ + " by clients are persisted in the write-ahead log and that files
written"
+ + " during a compaction are persisted to disk successfully. This
property only"
+ + " configures the durability used to write to the write-ahead log.
Legal"
+ + " values are: none, which skips the write-ahead log; log, which
sends the"
+ + " data to the write-ahead log, but does nothing to make it
durable; flush,"
+ + " which pushes data out of the JVM (likely to page cache); and
sync, which"
+ + " ensures that each mutation is written to the physical disk. To
configure"
+ + " the durability of files written during minor and major
compactions, set the"
+ + " Hadoop property \"dfs.datanode.synconclose\" to \"true\". This
will ensure"
+ + " that the blocks of the files in HDFS are written to the physical
disk as"
+ + " the compaction output files are written (Note that this may only
apply"
+ + " to replicated files in HDFS).",
"1.7.0"),
TABLE_FAILURES_IGNORE("table.failures.ignore", "false", PropertyType.BOOLEAN,
diff --git
a/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java
b/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java
index f83d202b2f..ce5c392fdc 100644
--- a/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java
+++ b/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java
@@ -29,6 +29,7 @@ import org.apache.accumulo.core.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.data.ByteSequence;
import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.TableId;
import org.apache.accumulo.core.file.blockfile.impl.CacheProvider;
import org.apache.accumulo.core.file.rfile.RFile;
import org.apache.accumulo.core.spi.crypto.CryptoService;
@@ -176,6 +177,7 @@ public abstract class FileOperations {
public final Configuration fsConf;
public final RateLimiter rateLimiter;
// writer only objects
+ private final TableId tableId;
public final String compression;
public final FSDataOutputStream outputStream;
public final boolean enableAccumuloStart;
@@ -190,11 +192,12 @@ public abstract class FileOperations {
public final boolean inclusive;
public final boolean dropCacheBehind;
- public FileOptions(AccumuloConfiguration tableConfiguration, String
filename, FileSystem fs,
- Configuration fsConf, RateLimiter rateLimiter, String compression,
+ public FileOptions(TableId tableId, AccumuloConfiguration
tableConfiguration, String filename,
+ FileSystem fs, Configuration fsConf, RateLimiter rateLimiter, String
compression,
FSDataOutputStream outputStream, boolean enableAccumuloStart,
CacheProvider cacheProvider,
Cache<String,Long> fileLenCache, boolean seekToBeginning,
CryptoService cryptoService,
Range range, Set<ByteSequence> columnFamilies, boolean inclusive,
boolean dropCacheBehind) {
+ this.tableId = tableId;
this.tableConfiguration = tableConfiguration;
this.filename = filename;
this.fs = fs;
@@ -213,6 +216,10 @@ public abstract class FileOperations {
this.dropCacheBehind = dropCacheBehind;
}
+ public TableId getTableId() {
+ return tableId;
+ }
+
public AccumuloConfiguration getTableConfiguration() {
return tableConfiguration;
}
@@ -278,6 +285,7 @@ public abstract class FileOperations {
* Helper class extended by both writers and readers.
*/
public static class FileHelper {
+ private TableId tableId;
private AccumuloConfiguration tableConfiguration;
private String filename;
private FileSystem fs;
@@ -286,6 +294,11 @@ public abstract class FileOperations {
private CryptoService cryptoService;
private boolean dropCacheBehind = false;
+ protected FileHelper table(TableId tid) {
+ this.tableId = tid;
+ return this;
+ }
+
protected FileHelper fs(FileSystem fs) {
this.fs = Objects.requireNonNull(fs);
return this;
@@ -323,28 +336,28 @@ public abstract class FileOperations {
protected FileOptions toWriterBuilderOptions(String compression,
FSDataOutputStream outputStream, boolean startEnabled) {
- return new FileOptions(tableConfiguration, filename, fs, fsConf,
rateLimiter, compression,
- outputStream, startEnabled, NULL_PROVIDER, null, false,
cryptoService, null, null, true,
- dropCacheBehind);
+ return new FileOptions(tableId, tableConfiguration, filename, fs,
fsConf, rateLimiter,
+ compression, outputStream, startEnabled, NULL_PROVIDER, null, false,
cryptoService, null,
+ null, true, dropCacheBehind);
}
protected FileOptions toReaderBuilderOptions(CacheProvider cacheProvider,
Cache<String,Long> fileLenCache, boolean seekToBeginning) {
- return new FileOptions(tableConfiguration, filename, fs, fsConf,
rateLimiter, null, null,
- false, cacheProvider == null ? NULL_PROVIDER : cacheProvider,
fileLenCache,
+ return new FileOptions(tableId, tableConfiguration, filename, fs,
fsConf, rateLimiter, null,
+ null, false, cacheProvider == null ? NULL_PROVIDER : cacheProvider,
fileLenCache,
seekToBeginning, cryptoService, null, null, true, dropCacheBehind);
}
protected FileOptions toIndexReaderBuilderOptions(Cache<String,Long>
fileLenCache) {
- return new FileOptions(tableConfiguration, filename, fs, fsConf,
rateLimiter, null, null,
- false, NULL_PROVIDER, fileLenCache, false, cryptoService, null,
null, true,
+ return new FileOptions(tableId, tableConfiguration, filename, fs,
fsConf, rateLimiter, null,
+ null, false, NULL_PROVIDER, fileLenCache, false, cryptoService,
null, null, true,
dropCacheBehind);
}
protected FileOptions toScanReaderBuilderOptions(Range range,
Set<ByteSequence> columnFamilies,
boolean inclusive) {
- return new FileOptions(tableConfiguration, filename, fs, fsConf,
rateLimiter, null, null,
- false, NULL_PROVIDER, null, false, cryptoService, range,
columnFamilies, inclusive,
+ return new FileOptions(tableId, tableConfiguration, filename, fs,
fsConf, rateLimiter, null,
+ null, false, NULL_PROVIDER, null, false, cryptoService, range,
columnFamilies, inclusive,
dropCacheBehind);
}
@@ -374,6 +387,11 @@ public abstract class FileOperations {
return this;
}
+ public WriterBuilder forTable(TableId tid) {
+ table(tid);
+ return this;
+ }
+
@Override
public WriterBuilder withTableConfiguration(AccumuloConfiguration
tableConfiguration) {
tableConfiguration(tableConfiguration);
diff --git
a/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java
b/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java
index 19b020a3d1..c87b071642 100644
---
a/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java
+++
b/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.accumulo.core.client.sample.Sampler;
import org.apache.accumulo.core.conf.AccumuloConfiguration;
@@ -29,11 +30,14 @@ import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.data.ByteSequence;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.TableId;
import org.apache.accumulo.core.file.FileOperations;
import org.apache.accumulo.core.file.FileSKVIterator;
import org.apache.accumulo.core.file.FileSKVWriter;
import
org.apache.accumulo.core.file.blockfile.impl.CachableBlockFile.CachableBuilder;
import org.apache.accumulo.core.file.rfile.bcfile.BCFile;
+import org.apache.accumulo.core.metadata.MetadataTable;
+import org.apache.accumulo.core.metadata.RootTable;
import org.apache.accumulo.core.sample.impl.SamplerConfigurationImpl;
import org.apache.accumulo.core.sample.impl.SamplerFactory;
import org.apache.hadoop.conf.Configuration;
@@ -41,6 +45,7 @@ import org.apache.hadoop.fs.CreateFlag;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.StreamCapabilities;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.slf4j.Logger;
@@ -53,6 +58,7 @@ public class RFileOperations extends FileOperations {
private static final Logger LOG =
LoggerFactory.getLogger(RFileOperations.class);
private static final Collection<ByteSequence> EMPTY_CF_SET =
Collections.emptySet();
+ private static final AtomicBoolean SYNC_CAPABILITY_LOGGED = new
AtomicBoolean(false);
private static RFile.Reader getReader(FileOptions options) throws
IOException {
CachableBuilder cb = new CachableBuilder()
@@ -194,6 +200,17 @@ public class RFileOperations extends FileOperations {
e.getMessage());
}
}
+
+ TableId tid = options.getTableId();
+ if (tid != null && !SYNC_CAPABILITY_LOGGED.get()
+ && (RootTable.ID.equals(tid) || MetadataTable.ID.equals(tid))) {
+ if (!outputStream.hasCapability(StreamCapabilities.HSYNC)) {
+ SYNC_CAPABILITY_LOGGED.set(true);
+ LOG.warn("File created for table {} does not support hsync. If
dfs.datanode.synconclose"
+ + " is configured, then it may not work.
dfs.datanode.synconclose is recommended for the"
+ + " root and metadata tables.", tid);
+ }
+ }
}
BCFile.Writer _cbw = new BCFile.Writer(outputStream,
options.getRateLimiter(), compression,
diff --git
a/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java
b/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java
index c9352473db..0d48f26799 100644
---
a/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java
+++
b/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java
@@ -359,7 +359,7 @@ public class FileCompactor implements
Callable<CompactionStats> {
&& ((isMinC &&
acuTableConf.getBoolean(Property.TABLE_MINC_OUTPUT_DROP_CACHE))
|| (!isMinC &&
acuTableConf.getBoolean(Property.TABLE_MAJC_OUTPUT_DROP_CACHE)));
- WriterBuilder outBuilder = fileFactory.newWriterBuilder()
+ WriterBuilder outBuilder =
fileFactory.newWriterBuilder().forTable(this.extent.tableId())
.forFile(outputFile.getMetaInsert(), ns, ns.getConf(), cryptoService)
.withTableConfiguration(acuTableConf).withRateLimiter(env.getWriteLimiter());
if (dropCacheBehindOutput) {
diff --git
a/server/base/src/main/java/org/apache/accumulo/server/init/FileSystemInitializer.java
b/server/base/src/main/java/org/apache/accumulo/server/init/FileSystemInitializer.java
index 7e99f13bf9..873ea84347 100644
---
a/server/base/src/main/java/org/apache/accumulo/server/init/FileSystemInitializer.java
+++
b/server/base/src/main/java/org/apache/accumulo/server/init/FileSystemInitializer.java
@@ -127,14 +127,15 @@ class FileSystemInitializer {
String metadataFileName = tableMetadataTabletDirUri + Path.SEPARATOR +
"0_1." + ext;
Tablet replicationTablet =
new Tablet(REPL_TABLE_ID, replicationTableDefaultTabletDirName, null,
null);
- createMetadataFile(fs, metadataFileName, siteConfig, replicationTablet);
+ createMetadataFile(fs, metadataFileName, siteConfig, REPL_TABLE_ID,
replicationTablet);
// populate the root tablet with info about the metadata table's two
initial tablets
Tablet tablesTablet = new Tablet(MetadataTable.ID,
tableMetadataTabletDirName, null, splitPoint,
metadataFileName);
Tablet defaultTablet =
new Tablet(MetadataTable.ID, defaultMetadataTabletDirName, splitPoint,
null);
- createMetadataFile(fs, rootTabletFileUri, siteConfig, tablesTablet,
defaultTablet);
+ createMetadataFile(fs, rootTabletFileUri, siteConfig, MetadataTable.ID,
tablesTablet,
+ defaultTablet);
}
private void createDirectories(VolumeManager fs, String... dirs) throws
IOException {
@@ -177,7 +178,7 @@ class FileSystemInitializer {
}
private void createMetadataFile(VolumeManager volmanager, String fileName,
- AccumuloConfiguration conf, Tablet... tablets) throws IOException {
+ AccumuloConfiguration conf, TableId tid, Tablet... tablets) throws
IOException {
// sort file contents in memory, then play back to the file
TreeMap<Key,Value> sorted = new TreeMap<>();
for (Tablet tablet : tablets) {
@@ -187,7 +188,7 @@ class FileSystemInitializer {
CryptoService cs = CryptoFactoryLoader.getServiceForServer(conf);
- FileSKVWriter tabletWriter =
FileOperations.getInstance().newWriterBuilder()
+ FileSKVWriter tabletWriter =
FileOperations.getInstance().newWriterBuilder().forTable(tid)
.forFile(fileName, fs, fs.getConf(),
cs).withTableConfiguration(conf).build();
tabletWriter.startDefaultLocalityGroup();
diff --git
a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletClientHandler.java
b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletClientHandler.java
index 571acb5a3f..3644f6146c 100644
---
a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletClientHandler.java
+++
b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletClientHandler.java
@@ -426,6 +426,7 @@ public class TabletClientHandler implements
TabletClientService.Iface {
Tablet tablet = entry.getKey();
Durability durability =
DurabilityImpl.resolveDurabilty(us.durability,
tablet.getDurability());
+ logDurabilityWarning(tablet, durability);
List<Mutation> mutations = entry.getValue();
if (!mutations.isEmpty()) {
try {
@@ -704,7 +705,7 @@ public class TabletClientHandler implements
TabletClientService.Iface {
CommitSession session = prepared.getCommitSession();
Durability durability = DurabilityImpl
.resolveDurabilty(DurabilityImpl.fromThrift(tdurability),
tabletDurability);
-
+ logDurabilityWarning(tablet, durability);
// Instead of always looping on true, skip completely when durability
is NONE.
while (durability != Durability.NONE) {
try {
@@ -814,7 +815,7 @@ public class TabletClientHandler implements
TabletClientService.Iface {
} else {
final Durability durability =
DurabilityImpl.resolveDurabilty(sess.durability,
tablet.getDurability());
-
+ logDurabilityWarning(tablet, durability);
List<Mutation> mutations =
Collections.unmodifiableList(entry.getValue());
if (!mutations.isEmpty()) {
@@ -1635,4 +1636,11 @@ public class TabletClientHandler implements
TabletClientService.Iface {
return handleTimeout(sessionId);
}
}
+
+ private void logDurabilityWarning(Tablet tablet, Durability durability) {
+ if (tablet.getExtent().isMeta() && durability != Durability.SYNC) {
+ log.warn("Property {} is not set to 'sync' for table {}",
Property.TABLE_DURABILITY.getKey(),
+ tablet.getExtent().tableId());
+ }
+ }
}