You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2009/05/12 21:11:27 UTC

svn commit: r774024 - in /incubator/cassandra/trunk: src/java/org/apache/cassandra/db/ColumnFamilyStore.java src/java/org/apache/cassandra/db/Table.java test/unit/org/apache/cassandra/db/OneCompactionTest.java

Author: jbellis
Date: Tue May 12 19:11:27 2009
New Revision: 774024

URL: http://svn.apache.org/viewvc?rev=774024&view=rev
Log:
test to more reliably reproduce CME during range.  fix by locking out compact during range query.
patch by jbellis; reviewed by Eric Evans for CASSANDRA-161

Modified:
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
    incubator/cassandra/trunk/test/unit/org/apache/cassandra/db/OneCompactionTest.java

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=774024&r1=774023&r2=774024&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Tue May 12 19:11:27 2009
@@ -1526,11 +1526,17 @@
         return memtable_.get();
     }
 
+    /** not threadsafe.  caller must have lock_ acquired. */
     public Set<String> getSSTableFilenames()
     {
         return Collections.unmodifiableSet(ssTables_);
     }
 
+    public ReentrantReadWriteLock.ReadLock getReadLock()
+    {
+        return lock_.readLock();
+    }
+
     public int getReadCount()
     {
         return readStats_.size();

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=774024&r1=774023&r2=774024&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Tue May 12 19:11:27 2009
@@ -395,7 +395,7 @@
     /* The AnalyticsSource instance which keeps track of statistics reported to Ganglia. */
     private DBAnalyticsSource dbAnalyticsSource_;
     // cache application CFs since Range queries ask for them a _lot_
-    private Set<String> applicationColumnFamilies_;
+    private SortedSet<String> applicationColumnFamilies_;
 
     public static Table open(String table)
     {
@@ -849,11 +849,11 @@
         dbAnalyticsSource_.updateWriteStatistics(timeTaken);
     }
 
-    public Set<String> getApplicationColumnFamilies()
+    public SortedSet<String> getApplicationColumnFamilies()
     {
         if (applicationColumnFamilies_ == null)
         {
-            applicationColumnFamilies_ = new HashSet<String>();
+            applicationColumnFamilies_ = new TreeSet<String>();
             for (String cfName : getColumnFamilies())
             {
                 if (DatabaseDescriptor.isApplicationColumnFamily(cfName))
@@ -873,6 +873,26 @@
      */
     public List<String> getKeyRange(final String startWith, final String stopAt, int maxResults) throws IOException, ExecutionException, InterruptedException
     {
+        // TODO we need a better way to keep compactions from stomping on reads than One Big Lock per CF.
+        for (String cfName : getApplicationColumnFamilies())
+        {
+            getColumnFamilyStore(cfName).getReadLock().lock();
+        }
+        try
+        {
+            return getKeyRangeUnsafe(startWith, stopAt, maxResults);
+        }
+        finally
+        {
+            for (String cfName : getApplicationColumnFamilies())
+            {
+                getColumnFamilyStore(cfName).getReadLock().unlock();
+            }
+        }
+    }
+
+    private List<String> getKeyRangeUnsafe(final String startWith, final String stopAt, int maxResults) throws IOException, ExecutionException, InterruptedException
+    {
         // (OPP key decoration is a no-op so using the "decorated" comparator against raw keys is fine)
         final Comparator<String> comparator = StorageService.getPartitioner().getDecoratedKeyComparator();
 

Modified: incubator/cassandra/trunk/test/unit/org/apache/cassandra/db/OneCompactionTest.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/test/unit/org/apache/cassandra/db/OneCompactionTest.java?rev=774024&r1=774023&r2=774024&view=diff
==============================================================================
--- incubator/cassandra/trunk/test/unit/org/apache/cassandra/db/OneCompactionTest.java (original)
+++ incubator/cassandra/trunk/test/unit/org/apache/cassandra/db/OneCompactionTest.java Tue May 12 19:11:27 2009
@@ -11,17 +11,16 @@
 
 public class OneCompactionTest
 {
-    @Test
-    public void testOneCompaction() throws IOException, ExecutionException, InterruptedException
+    private void testCompaction(String columnFamilyName, int insertsPerTable) throws IOException, ExecutionException, InterruptedException
     {
         Table table = Table.open("Table1");
-        ColumnFamilyStore store = table.getColumnFamilyStore("Standard1");
+        ColumnFamilyStore store = table.getColumnFamilyStore(columnFamilyName);
 
         Set<String> inserted = new HashSet<String>();
-        for (int j = 0; j < 2; j++) {
+        for (int j = 0; j < insertsPerTable; j++) {
             String key = "0";
             RowMutation rm = new RowMutation("Table1", key);
-            rm.add("Standard1:0", new byte[0], j);
+            rm.add(columnFamilyName + ":0", new byte[0], j);
             rm.apply();
             inserted.add(key);
             store.forceBlockingFlush();
@@ -30,4 +29,16 @@
         store.doCompaction(2);
         assertEquals(table.getKeyRange("", "", 10000).size(), inserted.size());
     }
+
+    @Test
+    public void testCompaction1() throws IOException, ExecutionException, InterruptedException
+    {
+        testCompaction("Standard1", 1);
+    }
+
+    @Test
+    public void testCompaction2() throws IOException, ExecutionException, InterruptedException
+    {
+        testCompaction("Standard2", 500);
+    }
 }