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 2010/10/22 01:14:59 UTC
svn commit: r1026177 - in /cassandra/trunk: ./
src/java/org/apache/cassandra/db/ src/java/org/apache/cassandra/db/commitlog/
src/java/org/apache/cassandra/service/ test/unit/org/apache/cassandra/
test/unit/org/apache/cassandra/db/
Author: jbellis
Date: Thu Oct 21 23:14:59 2010
New Revision: 1026177
URL: http://svn.apache.org/viewvc?rev=1026177&view=rev
Log:
fix commitlog recovery deleting the newly-created segment as well as the old ones
patch by jbellis; reviewed by gdusbabek for CASSANDRA-1644
Modified:
cassandra/trunk/CHANGES.txt
cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/BatchCommitLogExecutorService.java
cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java
cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java
cassandra/trunk/test/unit/org/apache/cassandra/CleanupHelper.java
cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager2Test.java
cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager3Test.java
cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManagerTest.java
Modified: cassandra/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/CHANGES.txt (original)
+++ cassandra/trunk/CHANGES.txt Thu Oct 21 23:14:59 2010
@@ -54,6 +54,8 @@ dev
* cli --file option (CASSANDRA-1616)
* reduce automatically chosen memtable sizes by 50% (CASSANDRA-1641)
* move endpoint cache from snitch to strategy (CASSANDRA-1643)
+ * fix commitlog recovery deleting the newly-created segment as well as
+ the old ones (CASSANDRA-1644)
0.7-beta2
@@ -95,8 +97,6 @@ dev
* Add CfDef.default_validation_class (CASSANDRA-891)
* fix EstimatedHistogram.max (CASSANDRA-1413)
* quorum read optimization (CASSANDRA-1622)
-
-
* handle zero-length (or missing) rows during HH paging (CASSANDRA-1432)
* include secondary indexes during schema migrations (CASSANDRA-1406)
* fix commitlog header race during schema change (CASSANDRA-1435)
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Thu Oct 21 23:14:59 2010
@@ -575,7 +575,7 @@ public class ColumnFamilyStore implement
assert memtable == oldMemtable;
memtable.freeze();
- final CommitLogSegment.CommitLogContext ctx = writeCommitLog ? CommitLog.instance().getContext() : null;
+ final CommitLogSegment.CommitLogContext ctx = writeCommitLog ? CommitLog.instance.getContext() : null;
logger.info("switching in a fresh Memtable for " + columnFamily + " at " + ctx);
// submit the memtable for any indexed sub-cfses, and our own.
@@ -605,7 +605,7 @@ public class ColumnFamilyStore implement
{
// if we're not writing to the commit log, we are replaying the log, so marking
// the log header with "you can discard anything written before the context" is not valid
- CommitLog.instance().discardCompletedSegments(metadata.cfId, ctx);
+ CommitLog.instance.discardCompletedSegments(metadata.cfId, ctx);
}
}
});
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/Table.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Thu Oct 21 23:14:59 2010
@@ -62,9 +62,8 @@ public class Table
*/
static final ReentrantReadWriteLock flusherLock = new ReentrantReadWriteLock(true);
- // This is a result of pushing down the point in time when storage directories get created. It used to happen in
- // CassandraDaemon, but it is possible to call Table.open without a running daemon, so it made sense to ensure
- // proper directories here.
+ // It is possible to call Table.open without a running daemon, so it makes sense to ensure
+ // proper directories here as well as in CassandraDaemon.
static
{
try
@@ -73,7 +72,7 @@ public class Table
}
catch (IOException ex)
{
- throw new RuntimeException(ex);
+ throw new IOError(ex);
}
}
@@ -350,7 +349,7 @@ public class Table
try
{
if (writeCommitLog)
- CommitLog.instance().add(mutation, serializedMutation);
+ CommitLog.instance.add(mutation, serializedMutation);
DecoratedKey key = StorageService.getPartitioner().decorateKey(mutation.key());
for (ColumnFamily cf : mutation.getColumnFamilies())
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/BatchCommitLogExecutorService.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/BatchCommitLogExecutorService.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/BatchCommitLogExecutorService.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/BatchCommitLogExecutorService.java Thu Oct 21 23:14:59 2010
@@ -95,7 +95,7 @@ class BatchCommitLogExecutorService exte
// now sync and set the tasks' values (which allows thread calling get() to proceed)
try
{
- CommitLog.instance().sync();
+ CommitLog.instance.sync();
}
catch (IOException e)
{
Modified: cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java Thu Oct 21 23:14:59 2010
@@ -80,15 +80,7 @@ public class CommitLog
static final Logger logger = LoggerFactory.getLogger(CommitLog.class);
- public static CommitLog instance()
- {
- return CLHandle.instance;
- }
-
- private static class CLHandle
- {
- public static final CommitLog instance = new CommitLog();
- }
+ public static final CommitLog instance = new CommitLog();
private final Deque<CommitLogSegment> segments = new ArrayDeque<CommitLogSegment>();
@@ -97,11 +89,6 @@ public class CommitLog
SEGMENT_SIZE = size;
}
- public int getSegmentCount()
- {
- return segments.size();
- }
-
private final ICommitLogExecutorService executor;
/**
@@ -112,10 +99,19 @@ public class CommitLog
*/
private CommitLog()
{
+ try
+ {
+ DatabaseDescriptor.createAllDirectories();
+ }
+ catch (IOException e)
+ {
+ throw new IOError(e);
+ }
+
// all old segments are recovered and deleted before CommitLog is instantiated.
// All we need to do is create a new one.
segments.add(new CommitLogSegment());
-
+
if (DatabaseDescriptor.getCommitLogSync() == Config.CommitLogSync.periodic)
{
executor = new PeriodicCommitLogExecutorService();
@@ -157,6 +153,22 @@ public class CommitLog
}
}
+ public void resetUnsafe()
+ {
+ segments.clear();
+ segments.add(new CommitLogSegment());
+ }
+
+ private boolean manages(String name)
+ {
+ for (CommitLogSegment segment : segments)
+ {
+ if (segment.getPath().endsWith(name))
+ return true;
+ }
+ return false;
+ }
+
public static void recover() throws IOException
{
String directory = DatabaseDescriptor.getCommitLogLocation();
@@ -164,11 +176,17 @@ public class CommitLog
{
public boolean accept(File dir, String name)
{
- return CommitLogSegment.possibleCommitLogFile(name);
+ // we used to try to avoid instantiating commitlog (thus creating an empty segment ready for writes)
+ // until after recover was finished. this turns out to be fragile; it is less error-prone to go
+ // ahead and allow writes before recover(), and just skip active segments when we do.
+ return CommitLogSegment.possibleCommitLogFile(name) && !instance.manages(name);
}
});
if (files.length == 0)
+ {
+ logger.info("No commitlog files found; skipping replay");
return;
+ }
Arrays.sort(files, new FileUtils.FileComparator());
logger.info("Replaying " + StringUtils.join(files, ", "));
Modified: cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java Thu Oct 21 23:14:59 2010
@@ -339,8 +339,6 @@ public class StorageService implements I
initialized = true;
isClientMode = false;
- DatabaseDescriptor.createAllDirectories();
-
try
{
GCInspector.instance.start();
Modified: cassandra/trunk/test/unit/org/apache/cassandra/CleanupHelper.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/CleanupHelper.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/CleanupHelper.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/CleanupHelper.java Thu Oct 21 23:14:59 2010
@@ -24,6 +24,7 @@ import java.io.IOException;
import org.junit.BeforeClass;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.io.util.FileUtils;
import org.slf4j.Logger;
@@ -39,6 +40,7 @@ public class CleanupHelper extends Schem
mkdirs();
cleanup();
mkdirs();
+ CommitLog.instance.resetUnsafe(); // cleanup screws w/ CommitLog, this brings it back to safe state
}
public static void cleanup() throws IOException
Modified: cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager2Test.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager2Test.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager2Test.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager2Test.java Thu Oct 21 23:14:59 2010
@@ -62,6 +62,7 @@ public class RecoveryManager2Test extend
logger.debug("begin manual replay");
// replay the commit log (nothing should be replayed since everything was flushed)
+ CommitLog.instance.resetUnsafe();
CommitLog.recover();
// since everything that was flushed was removed (i.e. clearUnsafe)
Modified: cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager3Test.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager3Test.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager3Test.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager3Test.java Thu Oct 21 23:14:59 2010
@@ -31,6 +31,7 @@ import org.apache.cassandra.CleanupHelpe
import org.apache.cassandra.Util;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.commitlog.CommitLog;
+import org.apache.cassandra.io.util.FileUtils;
import static org.apache.cassandra.Util.column;
import static org.apache.cassandra.db.TableTest.assertColumns;
@@ -66,10 +67,10 @@ public class RecoveryManager3Test extend
for (File file : new File(DatabaseDescriptor.getCommitLogLocation()).listFiles())
{
if (file.getName().endsWith(".header"))
- if (!file.delete())
- throw new AssertionError();
+ FileUtils.deleteWithConfirm(file);
}
+ CommitLog.instance.resetUnsafe(); // disassociate segments from live CL
CommitLog.recover();
assertColumns(Util.getColumnFamily(table1, dk, "Standard1"), "col1");
Modified: cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManagerTest.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManagerTest.java?rev=1026177&r1=1026176&r2=1026177&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManagerTest.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManagerTest.java Thu Oct 21 23:14:59 2010
@@ -63,6 +63,7 @@ public class RecoveryManagerTest extends
table1.getColumnFamilyStore("Standard1").clearUnsafe();
table2.getColumnFamilyStore("Standard3").clearUnsafe();
+ CommitLog.instance.resetUnsafe(); // disassociate segments from live CL
CommitLog.recover();
assertColumns(Util.getColumnFamily(table1, dk, "Standard1"), "col1");