Updated Branches: refs/heads/cassandra-1.1 4a002a579 -> ff1ba8707
Convert bootstrap state from boolean to 3-way value; detect and retry partial bootstraps on restart. Patch by brandonwilliams, reviewed by jbellis for CASSANDRA-4427 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/ff1ba870 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/ff1ba870 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/ff1ba870 Branch: refs/heads/cassandra-1.1 Commit: ff1ba870726d9c0de24ff8dad3e23aa96465290e Parents: 4a002a5 Author: Brandon Williams <[email protected]> Authored: Mon Jul 16 16:13:53 2012 -0500 Committer: Brandon Williams <[email protected]> Committed: Mon Jul 16 16:18:55 2012 -0500 ---------------------------------------------------------------------- src/java/org/apache/cassandra/db/SystemTable.java | 27 ++++++++++++--- .../apache/cassandra/service/StorageService.java | 25 +++++++++---- 2 files changed, 39 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/ff1ba870/src/java/org/apache/cassandra/db/SystemTable.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/SystemTable.java b/src/java/org/apache/cassandra/db/SystemTable.java index f673ecf..af07156 100644 --- a/src/java/org/apache/cassandra/db/SystemTable.java +++ b/src/java/org/apache/cassandra/db/SystemTable.java @@ -69,6 +69,13 @@ public class SystemTable private static final ByteBuffer CURRENT_LOCAL_NODE_ID_KEY = ByteBufferUtil.bytes("CurrentLocal"); private static final ByteBuffer ALL_LOCAL_NODE_ID_KEY = ByteBufferUtil.bytes("Local"); + public enum BootstrapState + { + NEEDS_BOOTSTRAP, // ordered for boolean backward compatibility, false + COMPLETED, // true + IN_PROGRESS + } + private static DecoratedKey decorate(ByteBuffer key) { return StorageService.getPartitioner().decorateKey(key); @@ -352,7 +359,7 @@ public class SystemTable return generation; } - public static boolean isBootstrapped() + public static BootstrapState getBootstrapState() { Table table = Table.open(Table.SYSTEM_TABLE); QueryFilter filter = QueryFilter.getNamesFilter(decorate(BOOTSTRAP_KEY), @@ -360,16 +367,26 @@ public class SystemTable BOOTSTRAP); ColumnFamily cf = table.getColumnFamilyStore(STATUS_CF).getColumnFamily(filter); if (cf == null) - return false; + return BootstrapState.NEEDS_BOOTSTRAP; IColumn c = cf.getColumn(BOOTSTRAP); - return c.value().get(c.value().position()) == 1; + return BootstrapState.values()[c.value().get(c.value().position())]; + } + + public static boolean bootstrapComplete() + { + return getBootstrapState() == BootstrapState.COMPLETED; + } + + public static boolean bootstrapInProgress() + { + return getBootstrapState() == BootstrapState.IN_PROGRESS; } - public static void setBootstrapped(boolean isBootstrapped) + public static void setBootstrapState(BootstrapState state) { ColumnFamily cf = ColumnFamily.create(Table.SYSTEM_TABLE, STATUS_CF); cf.addColumn(new Column(BOOTSTRAP, - ByteBuffer.wrap(new byte[] { (byte) (isBootstrapped ? 1 : 0) }), + ByteBuffer.wrap(new byte[] { (byte) (state.ordinal()) }), FBUtilities.timestampMicros())); RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, BOOTSTRAP_KEY); rm.add(cf); http://git-wip-us.apache.org/repos/asf/cassandra/blob/ff1ba870/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 9d9690a..28a3551 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -559,17 +559,26 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe if (DatabaseDescriptor.isAutoBootstrap() && DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress()) - && !SystemTable.isBootstrapped()) + && !SystemTable.bootstrapComplete()) logger_.info("This node will not auto bootstrap because it is configured to be a seed node."); InetAddress current = null; - // first startup is only chance to bootstrap + // we can bootstrap at startup, or if we detect a previous attempt that failed, which is to say: + // DD.isAutoBootstrap must be true AND: + // bootstrap is not recorded as complete, OR + // DD.getSeeds does not contain our BCA, OR + // we do not have non-system tables already + // OR: + // we detect that we were previously trying to bootstrap (ST.bootstrapInProgress is true) Token<?> token; if (DatabaseDescriptor.isAutoBootstrap() - && !(SystemTable.isBootstrapped() - || DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress()) - || !Schema.instance.getNonSystemTables().isEmpty())) + && !(SystemTable.bootstrapComplete() || DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress()) || !Schema.instance.getNonSystemTables().isEmpty()) + || SystemTable.bootstrapInProgress()) { + if (SystemTable.bootstrapInProgress()) + logger_.warn("Detected previous bootstrap failure; retrying"); + else + SystemTable.setBootstrapState(SystemTable.BootstrapState.IN_PROGRESS); setMode(Mode.JOINING, "waiting for ring and schema information", true); // first sleep the delay to make sure we see the schema try @@ -658,7 +667,7 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe if (!isSurveyMode) { // start participating in the ring. - SystemTable.setBootstrapped(true); + SystemTable.setBootstrapState(SystemTable.BootstrapState.COMPLETED); setToken(token); // remove the existing info about the replaced node. if (current != null) @@ -682,7 +691,7 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe else if (isSurveyMode) { setToken(SystemTable.getSavedToken()); - SystemTable.setBootstrapped(true); + SystemTable.setBootstrapState(SystemTable.BootstrapState.COMPLETED); isSurveyMode = false; logger_.info("Leaving write survey mode and joining ring at operator request"); assert tokenMetadata_.sortedTokens().size() > 0; @@ -2273,7 +2282,7 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe private void leaveRing() { - SystemTable.setBootstrapped(false); + SystemTable.setBootstrapState(SystemTable.BootstrapState.NEEDS_BOOTSTRAP); tokenMetadata_.removeEndpoint(FBUtilities.getBroadcastAddress()); calculatePendingRanges();
