Author: jbellis
Date: Tue Jan 11 16:45:26 2011
New Revision: 1057723

URL: http://svn.apache.org/viewvc?rev=1057723&view=rev
Log:
allow specifying specific SSTables to compact from JMX
patch by slebresne; reviewed by jbellis for CASSANDRA-1963

Modified:
    cassandra/branches/cassandra-0.7/CHANGES.txt
    
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManager.java
    
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManagerMBean.java
    
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/sstable/Descriptor.java

Modified: cassandra/branches/cassandra-0.7/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/CHANGES.txt?rev=1057723&r1=1057722&r2=1057723&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.7/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.7/CHANGES.txt Tue Jan 11 16:45:26 2011
@@ -17,6 +17,7 @@
  * optimize supercolumn deserialization (CASSANDRA-1891)
  * fix CFMetaData.apply to only compare objects of the same class 
    (CASSANDRA-1962)
+ * allow specifying specific SSTables to compact from JMX (CASSANDRA-1963)
 
 
 0.7.0-dev

Modified: 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManager.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManager.java?rev=1057723&r1=1057722&r2=1057723&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManager.java
 (original)
+++ 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManager.java
 Tue Jan 11 16:45:26 2011
@@ -225,6 +225,102 @@ public class CompactionManager implement
         return executor.submit(callable);
     }
 
+    public void forceUserDefinedCompaction(String ksname, String dataFiles)
+    {
+        if (!DatabaseDescriptor.getTables().contains(ksname))
+            throw new IllegalArgumentException("Unknown keyspace " + ksname);
+
+        File directory = new File(ksname);
+        String[] filenames = dataFiles.split(",");
+        Collection<Descriptor> descriptors = new 
ArrayList<Descriptor>(filenames.length);
+
+        String cfname = null;
+        for (String filename : filenames)
+        {
+            Pair<Descriptor, String> p = Descriptor.fromFilename(directory, 
filename.trim());
+            if (!p.right.equals(Component.DATA.name()))
+            {
+                throw new IllegalArgumentException(filename + " does not 
appear to be a data file");
+            }
+            if (cfname == null)
+            {
+                cfname = p.left.cfname;
+            }
+            else if (!cfname.equals(p.left.cfname))
+            {
+                throw new IllegalArgumentException("All provided sstables 
should be for the same column family");
+            }
+
+            descriptors.add(p.left);
+        }
+
+        ColumnFamilyStore cfs = 
Table.open(ksname).getColumnFamilyStore(cfname);
+        submitUserDefined(cfs, descriptors, (int) (System.currentTimeMillis() 
/ 1000) - cfs.metadata.getGcGraceSeconds());
+    }
+
+    private Future<Object> submitUserDefined(final ColumnFamilyStore cfs, 
final Collection<Descriptor> dataFiles, final int gcBefore)
+    {
+        Callable<Object> callable = new Callable<Object>()
+        {
+            public Object call() throws IOException
+            {
+                compactionLock.lock();
+                try
+                {
+                    if (cfs.isInvalid())
+                        return this;
+
+                    // look up the sstables now that we're on the compaction 
executor, so we don't try to re-compact
+                    // something that was already being compacted earlier.
+                    Collection<SSTableReader> sstables = new 
ArrayList<SSTableReader>();
+                    for (Descriptor desc : dataFiles)
+                    {
+                        // inefficient but not in a performance sensitive path
+                        SSTableReader sstable = lookupSSTable(cfs, desc);
+                        if (sstable == null)
+                        {
+                            logger.info("Will not compact {}: it is not an 
active sstable", desc);
+                        }
+                        else
+                        {
+                            sstables.add(sstable);
+                        }
+                    }
+
+                    if (sstables.isEmpty())
+                    {
+                        logger.error("No file to compact for user defined 
compaction");
+                    }
+                    else
+                    {
+                        doCompaction(cfs, sstables, gcBefore);
+                    }
+
+                    return this;
+                }
+                finally
+                {
+                    compactionLock.unlock();
+                }
+            }
+        };
+        return executor.submit(callable);
+    }
+
+    private SSTableReader lookupSSTable(final ColumnFamilyStore cfs, 
Descriptor descriptor)
+    {
+        for (SSTableReader sstable : cfs.getSSTables())
+        {
+            // .equals() with no other changes won't work because in 
sstable.descriptor, the directory is an absolute path.
+            // We could construct descriptor with an absolute path too but I 
haven't found any satisfying way to do that
+            // (DB.getDataFileLocationForTable() may not return the right path 
if you have multiple volumes). Hence the
+            // endsWith.
+            if (sstable.descriptor.toString().endsWith(descriptor.toString()))
+                return sstable;
+        }
+        return null;
+    }
+
     public Future<Object> submitValidation(final ColumnFamilyStore cfStore, 
final AntiEntropyService.Validator validator)
     {
         Callable<Object> callable = new Callable<Object>()

Modified: 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManagerMBean.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManagerMBean.java?rev=1057723&r1=1057722&r2=1057723&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManagerMBean.java
 (original)
+++ 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/CompactionManagerMBean.java
 Tue Jan 11 16:45:26 2011
@@ -50,4 +50,12 @@ public interface CompactionManagerMBean
      * @return number of completed compactions since server [re]start
      */
     public long getCompletedTasks();
+
+    /**
+     * Triggers the compaction of user specified sstables.
+     *
+     * @param ksname the keyspace for the sstables to compact
+     * @param dataFiles a comma separated list of sstable filename to compact
+     */
+    public void forceUserDefinedCompaction(String ksname, String dataFiles);
 }

Modified: 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/sstable/Descriptor.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/sstable/Descriptor.java?rev=1057723&r1=1057722&r2=1057723&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/sstable/Descriptor.java
 (original)
+++ 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/sstable/Descriptor.java
 Tue Jan 11 16:45:26 2011
@@ -123,7 +123,7 @@ public class Descriptor
      * Filename of the form 
"<ksname>/<cfname>-[tmp-][<version>-]<gen>-<component>"
      * @return A Descriptor for the SSTable, and the Component remainder.
      */
-    static Pair<Descriptor,String> fromFilename(File directory, String name)
+    public static Pair<Descriptor,String> fromFilename(File directory, String 
name)
     {
         // name of parent directory is keyspace name
         String ksname = directory.getName();


Reply via email to