You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by xe...@apache.org on 2012/03/22 15:06:06 UTC

[2/2] git commit: ensure that directory is selected for compaction patch by Aaron Morton; reviewed by Pavel Yaskevich for CASSANDRA-3985

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.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)
     {