Updated Branches: refs/heads/cassandra-1.0 5a3d4c14b -> fbdf7b03c
ensure that directory is selected for compaction patch by Aaron Morton; reviewed by Pavel Yaskevich for CASSANDRA-3985 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/fbdf7b03 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/fbdf7b03 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/fbdf7b03 Branch: refs/heads/cassandra-1.0 Commit: fbdf7b03c7a8138ae9621bf9bacaada906a2530d Parents: 5a3d4c1 Author: Pavel Yaskevich <xe...@apache.org> Authored: Thu Mar 22 15:40:29 2012 +0300 Committer: Pavel Yaskevich <xe...@apache.org> Committed: Thu Mar 22 15:57:13 2012 +0300 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/config/DatabaseDescriptor.java | 72 ++++++++------- src/java/org/apache/cassandra/db/Table.java | 9 ++- .../cassandra/db/compaction/CompactionTask.java | 27 +++-- 4 files changed, 64 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/fbdf7b03/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 925a4a9..c1e1cfe 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -10,6 +10,7 @@ * don't change manifest level for cleanup, scrub, and upgradesstables operations under LeveledCompactionStrategy (CASSANDRA-3989) * fix race leading to super columns assertion failure (CASSANDRA-3957) + * ensure that directory is selected for compaction (CASSANDRA-3985) 1.0.8 http://git-wip-us.apache.org/repos/asf/cassandra/blob/fbdf7b03/src/java/org/apache/cassandra/config/DatabaseDescriptor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 5aa59e4..f981adf 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -63,8 +63,6 @@ public class DatabaseDescriptor private static InetAddress broadcastAddress; private static InetAddress rpcAddress; private static SeedProvider seedProvider; - /* Current index into the above list of directories */ - private static int currentIndex = 0; /* Hashing strategy Random or OPHF */ private static IPartitioner partitioner; @@ -741,12 +739,6 @@ public class DatabaseDescriptor return tableLocations; } - public synchronized static String getNextAvailableDataLocation() - { - String dataFileDirectory = conf.data_file_directories[currentIndex]; - currentIndex = (currentIndex + 1) % conf.data_file_directories.length; - return dataFileDirectory; - } public static String getCommitLogLocation() { @@ -763,41 +755,57 @@ public class DatabaseDescriptor return Collections.unmodifiableSet(new HashSet(seedProvider.getSeeds())); } + public synchronized static String getDataFileLocationForTable(String table, long expectedCompactedFileSize) + { + return getDataFileLocationForTable(table, expectedCompactedFileSize, true); + } + /* * Loop through all the disks to see which disk has the max free space * return the disk with max free space for compactions. If the size of the expected * compacted file is greater than the max disk space available return null, we cannot * do compaction in this case. + * + * @param table name of the table. + * @param expectedCompactedSize expected file size in bytes. + * @param ensureFreeSpace Flag if the function should ensure enough free space exists for the expected file size. + * If False and there is not enough free space a warning is logged, and the dir with the most space is returned. */ - public static String getDataFileLocationForTable(String table, long expectedCompactedFileSize) + public synchronized static String getDataFileLocationForTable(String table, long expectedCompactedFileSize, boolean ensureFreeSpace) { - long maxFreeDisk = 0; - int maxDiskIndex = 0; - String dataFileDirectory = null; - String[] dataDirectoryForTable = getAllDataFileLocationsForTable(table); + long maxFreeDisk = 0; + int maxDiskIndex = 0; + String dataFileDirectory = null; + String[] dataDirectoryForTable = getAllDataFileLocationsForTable(table); - for ( int i = 0 ; i < dataDirectoryForTable.length ; i++ ) - { - File f = new File(dataDirectoryForTable[i]); - if( maxFreeDisk < f.getUsableSpace()) + for (int i = 0; i < dataDirectoryForTable.length; i++) { - maxFreeDisk = f.getUsableSpace(); - maxDiskIndex = i; + File f = new File(dataDirectoryForTable[i]); + + if (maxFreeDisk < f.getUsableSpace()) + { + maxFreeDisk = f.getUsableSpace(); + maxDiskIndex = i; + } } - } + logger.debug("expected data files size is {}; largest free partition has {} bytes free", - expectedCompactedFileSize, maxFreeDisk); - // Load factor of 0.9 we do not want to use the entire disk that is too risky. - maxFreeDisk = (long)(0.9 * maxFreeDisk); - if( expectedCompactedFileSize < maxFreeDisk ) - { - dataFileDirectory = dataDirectoryForTable[maxDiskIndex]; - currentIndex = (maxDiskIndex + 1 )%dataDirectoryForTable.length ; - } - else - { - currentIndex = maxDiskIndex; - } + expectedCompactedFileSize, + maxFreeDisk); + + // Load factor of 0.9 we do not want to use the entire disk that is too risky. + maxFreeDisk = (long) (0.9 * maxFreeDisk); + if (!ensureFreeSpace || expectedCompactedFileSize < maxFreeDisk) + { + dataFileDirectory = dataDirectoryForTable[maxDiskIndex]; + + if (expectedCompactedFileSize >= maxFreeDisk) + logger.warn(String.format("Data file location %s only has %d free, expected size is %d", + dataFileDirectory, + maxFreeDisk, + expectedCompactedFileSize)); + } + return dataFileDirectory; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/fbdf7b03/src/java/org/apache/cassandra/db/Table.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/Table.java b/src/java/org/apache/cassandra/db/Table.java index f954fbc..4c14f0f 100644 --- a/src/java/org/apache/cassandra/db/Table.java +++ b/src/java/org/apache/cassandra/db/Table.java @@ -556,7 +556,12 @@ public class Table public String getDataFileLocation(long expectedSize) { - String path = DatabaseDescriptor.getDataFileLocationForTable(name, expectedSize); + return getDataFileLocation(expectedSize, true); + } + + public String getDataFileLocation(long expectedSize, boolean ensureFreeSpace) + { + String path = DatabaseDescriptor.getDataFileLocationForTable(name, expectedSize, ensureFreeSpace); // Requesting GC has a chance to free space only if we're using mmap and a non SUN jvm if (path == null && (DatabaseDescriptor.getDiskAccessMode() == Config.DiskAccessMode.mmap || DatabaseDescriptor.getIndexAccessMode() == Config.DiskAccessMode.mmap) @@ -574,7 +579,7 @@ public class Table { throw new AssertionError(e); } - path = DatabaseDescriptor.getDataFileLocationForTable(name, expectedSize); + path = DatabaseDescriptor.getDataFileLocationForTable(name, expectedSize, ensureFreeSpace); } return path; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/fbdf7b03/src/java/org/apache/cassandra/db/compaction/CompactionTask.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionTask.java b/src/java/org/apache/cassandra/db/compaction/CompactionTask.java index 5847bf7..7f389bd 100644 --- a/src/java/org/apache/cassandra/db/compaction/CompactionTask.java +++ b/src/java/org/apache/cassandra/db/compaction/CompactionTask.java @@ -77,21 +77,20 @@ public class CompactionTask extends AbstractCompactionTask return 0; if (compactionFileLocation == null) - compactionFileLocation = cfs.table.getDataFileLocation(cfs.getExpectedCompactedFileSize(toCompact)); - if (partialCompactionsAcceptable()) + compactionFileLocation = cfs.table.getDataFileLocation(cfs.getExpectedCompactedFileSize(toCompact), ensureFreeSpace()); + + if (compactionFileLocation == null && partialCompactionsAcceptable()) { // If the compaction file path is null that means we have no space left for this compaction. // Try again w/o the largest one. - if (compactionFileLocation == null) + while (compactionFileLocation == null && toCompact.size() > 1) { - while (compactionFileLocation == null && toCompact.size() > 1) - { - logger.warn("insufficient space to compact all requested files " + StringUtils.join(toCompact, ", ")); - // Note that we have removed files that are still marked as compacting. This suboptimal but ok since the caller will unmark all - // the sstables at the end. - toCompact.remove(cfs.getMaxSizeFile(toCompact)); - compactionFileLocation = cfs.table.getDataFileLocation(cfs.getExpectedCompactedFileSize(toCompact)); - } + logger.warn("insufficient space to compact all requested files " + StringUtils.join(toCompact, ", ")); + // Note that we have removed files that are still marked as compacting. + // This suboptimal but ok since the caller will unmark all the sstables at the end. + toCompact.remove(cfs.getMaxSizeFile(toCompact)); + compactionFileLocation = cfs.table.getDataFileLocation(cfs.getExpectedCompactedFileSize(toCompact), + ensureFreeSpace()); } if (compactionFileLocation == null) @@ -100,6 +99,7 @@ public class CompactionTask extends AbstractCompactionTask return 0; } } + assert compactionFileLocation != null; if (DatabaseDescriptor.isSnapshotBeforeCompaction()) cfs.snapshotWithoutFlush(System.currentTimeMillis() + "-" + "compact-" + cfs.columnFamily); @@ -231,6 +231,11 @@ public class CompactionTask extends AbstractCompactionTask return !isUserDefined; } + protected boolean ensureFreeSpace() + { + return !isUserDefined; + } + //extensibility point for other strategies that may want to limit the upper bounds of the sstable segment size protected boolean newSSTableSegmentThresholdReached(SSTableWriter writer, long position) {