diff --git a/CHANGES.txt b/CHANGES.txt index 74cbbf9b00..e7a38914fb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,6 +5,7 @@ 5.0-rc2 + * Fix direct IO support always being evaluated to false upon the first start of a node (CASSANDRA-19779) 5.0-rc1 diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 61d4a44adb..388b4b7f30 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -17,6 +17,7 @@ */ package org.apache.cassandra.config; +import java.io.IOError; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; @@ -1456,7 +1457,18 @@ public class DatabaseDescriptor boolean directIOSupported = false; try { - directIOSupported = FileUtils.getBlockSize(new File(getCommitLogLocation())) > 0; + String commitLogLocation = getCommitLogLocation(); + + if (commitLogLocation == null) + throw new ConfigurationException("commitlog_directory must be specified", false); + + File commitLogLocationDir = new File(commitLogLocation); + PathUtils.createDirectoriesIfNotExists(commitLogLocationDir.toPath()); + directIOSupported = FileUtils.getBlockSize(commitLogLocationDir) > 0; + } + catch (IOError | ConfigurationException ex) + { + throw ex; } catch (RuntimeException e) { @@ -2844,6 +2856,7 @@ public class DatabaseDescriptor @VisibleForTesting public static void setCommitLogWriteDiskAccessMode(DiskAccessMode diskAccessMode) { + commitLogWriteDiskAccessMode = diskAccessMode; conf.commitlog_disk_access_mode = diskAccessMode; } diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java index bc51e73601..b624698bd6 100644 --- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java +++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java @@ -38,9 +38,12 @@ import org.junit.Test; import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.distributed.shared.WithProperties; import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.cassandra.io.util.FileUtils; +import org.apache.cassandra.io.util.PathUtils; import org.apache.cassandra.security.EncryptionContext; import org.apache.cassandra.security.EncryptionContextGenerator; import org.assertj.core.api.Assertions; +import org.mockito.MockedStatic; import static org.apache.cassandra.config.CassandraRelevantProperties.ALLOW_UNLIMITED_CONCURRENT_VALIDATIONS; import static org.apache.cassandra.config.CassandraRelevantProperties.CONFIG_LOADER; @@ -52,6 +55,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; public class DatabaseDescriptorTest { @@ -849,31 +854,36 @@ public class DatabaseDescriptorTest assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); // block size not available - DatabaseDescriptor.setCommitLogLocation(null); + try (MockedStatic fileUtilsMock = mockStatic(FileUtils.class); + MockedStatic pathUtilsMock = mockStatic(PathUtils.class)) + { + pathUtilsMock.when(() -> PathUtils.createDirectoriesIfNotExists(any())).thenAnswer(invocation -> null); + fileUtilsMock.when(() -> FileUtils.getBlockSize(any())).thenThrow(new RuntimeException("unable to get block size")); - // no encryption or compression - DatabaseDescriptor.setCommitLogCompression(null); - DatabaseDescriptor.setEncryptionContext(null); - DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.spinning; - assertCommitLogDiskAccessModes(Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.direct); - DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.ssd; - assertCommitLogDiskAccessModes(Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.direct); + // no encryption or compression + DatabaseDescriptor.setCommitLogCompression(null); + DatabaseDescriptor.setEncryptionContext(null); + DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.spinning; + assertCommitLogDiskAccessModes(Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.direct); + DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.ssd; + assertCommitLogDiskAccessModes(Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.mmap, Config.DiskAccessMode.direct); - // compression enabled - DatabaseDescriptor.setCommitLogCompression(new ParameterizedClass("LZ4Compressor", null)); - DatabaseDescriptor.setEncryptionContext(null); - DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.spinning; - assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); - DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.ssd; - assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); + // compression enabled + DatabaseDescriptor.setCommitLogCompression(new ParameterizedClass("LZ4Compressor", null)); + DatabaseDescriptor.setEncryptionContext(null); + DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.spinning; + assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); + DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.ssd; + assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); - // encryption enabled - DatabaseDescriptor.setCommitLogCompression(null); - DatabaseDescriptor.setEncryptionContext(new EncryptionContext(EncryptionContextGenerator.createEncryptionOptions())); - DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.spinning; - assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); - DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.ssd; - assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); + // encryption enabled + DatabaseDescriptor.setCommitLogCompression(null); + DatabaseDescriptor.setEncryptionContext(new EncryptionContext(EncryptionContextGenerator.createEncryptionOptions())); + DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.spinning; + assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); + DatabaseDescriptor.getRawConfig().disk_optimization_strategy = Config.DiskOptimizationStrategy.ssd; + assertCommitLogDiskAccessModes(Config.DiskAccessMode.standard, Config.DiskAccessMode.standard, Config.DiskAccessMode.standard); + } } finally { diff --git a/test/unit/org/apache/cassandra/repair/FuzzTestBase.java b/test/unit/org/apache/cassandra/repair/FuzzTestBase.java index b389231c68..1644c6fb74 100644 --- a/test/unit/org/apache/cassandra/repair/FuzzTestBase.java +++ b/test/unit/org/apache/cassandra/repair/FuzzTestBase.java @@ -70,6 +70,7 @@ import org.apache.cassandra.concurrent.ScheduledExecutorPlus; import org.apache.cassandra.concurrent.SequentialExecutorPlus; import org.apache.cassandra.concurrent.SimulatedExecutorFactory; import org.apache.cassandra.concurrent.Stage; +import org.apache.cassandra.config.Config; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.UnitConfigOverride; import org.apache.cassandra.cql3.CQLTester; @@ -182,6 +183,8 @@ public abstract class FuzzTestBase extends CQLTester.InMemory UnitConfigOverride.maybeOverrideConfig(); DatabaseDescriptor.daemonInitialization(); + DatabaseDescriptor.setCommitLogWriteDiskAccessMode(Config.DiskAccessMode.mmap); + DatabaseDescriptor.setPartitionerUnsafe(Murmur3Partitioner.instance); // TOOD (coverage): random select DatabaseDescriptor.setLocalDataCenter("test"); StreamingChannel.Factory.Global.unsafeSet(new StreamingChannel.Factory()