merge from 1.1
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/f223f548 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/f223f548 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/f223f548 Branch: refs/heads/trunk Commit: f223f5485aa4edcd7d7781f37c63dbba570748d2 Parents: 3d23188 0819ad1 Author: Jonathan Ellis <jbel...@apache.org> Authored: Sat Jul 28 09:42:40 2012 -0500 Committer: Jonathan Ellis <jbel...@apache.org> Committed: Sat Jul 28 09:42:40 2012 -0500 ---------------------------------------------------------------------- CHANGES.txt | 1 + src/java/org/apache/cassandra/config/Schema.java | 32 ++++----- .../org/apache/cassandra/gms/VersionedValue.java | 2 +- .../apache/cassandra/service/MigrationManager.java | 2 +- .../apache/cassandra/service/StorageService.java | 52 ++++++++++----- 5 files changed, 53 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/f223f548/CHANGES.txt ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/f223f548/src/java/org/apache/cassandra/config/Schema.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/config/Schema.java index c36ee77,95d092f..0c710e5 --- a/src/java/org/apache/cassandra/config/Schema.java +++ b/src/java/org/apache/cassandra/config/Schema.java @@@ -17,9 -18,12 +17,10 @@@ */ package org.apache.cassandra.config; -import java.io.IOError; import java.nio.ByteBuffer; import java.security.MessageDigest; + import java.security.NoSuchAlgorithmException; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@@ -61,13 -67,23 +62,25 @@@ public class Schem private final Map<String, Table> tableInstances = new NonBlockingHashMap<String, Table>(); /* metadata map for faster ColumnFamily lookup */ - private final BiMap<Pair<String, String>, Integer> cfIdMap = HashBiMap.create(); + private final BiMap<Pair<String, String>, UUID> cfIdMap = HashBiMap.create(); + // mapping from old ColumnFamily Id (Integer) to a new version which is UUID + private final BiMap<Integer, UUID> oldCfIdMap = HashBiMap.create(); private volatile UUID version; - private final ReadWriteLock versionLock = new ReentrantReadWriteLock(); + public static final UUID emptyVersion; + + static + { + try + { + emptyVersion = UUID.nameUUIDFromBytes(MessageDigest.getInstance("MD5").digest()); + } + catch (NoSuchAlgorithmException e) + { + throw new AssertionError(); + } + } /** * Initialize empty schema object http://git-wip-us.apache.org/repos/asf/cassandra/blob/f223f548/src/java/org/apache/cassandra/gms/VersionedValue.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/f223f548/src/java/org/apache/cassandra/service/MigrationManager.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/f223f548/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/service/StorageService.java index 9246716,5591488..1e73567 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@@ -510,30 -557,47 +510,47 @@@ public class StorageService implements HintedHandOffManager.instance.start(); - if (DatabaseDescriptor.isAutoBootstrap() - && DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress()) - && !SystemTable.bootstrapComplete()) - logger.info("This node will not auto bootstrap because it is configured to be a seed node."); + boolean schemaPresent = false; + if (DatabaseDescriptor.isAutoBootstrap() && !SystemTable.bootstrapComplete() && delay > 0) + { + // wait a couple gossip rounds so our schema check has something to go by + FBUtilities.sleep(2 * Gossiper.intervalInMillis); + } - for (Entry<InetAddress, EndpointState> entry : Gossiper.instance.getEndpointStates()) ++ for (Map.Entry<InetAddress, EndpointState> entry : Gossiper.instance.getEndpointStates()) + { + if (entry.getKey().equals(FBUtilities.getBroadcastAddress())) + { + // skip ourselves to avoid confusing the tests, which always load a schema first thing + continue; + } + + if (!entry.getValue().getApplicationState(ApplicationState.SCHEMA).value.equals(Schema.emptyVersion.toString())) + { + schemaPresent = true; + break; + } + } + // We can bootstrap at startup, or if we detect a previous attempt that failed. Either way, if the user + // manually sets auto_bootstrap to false, we'll skip streaming data from other nodes and jump directly + // into the ring. + // + // The one exception is if after the above sleep we still have no schema information, we'll assume + // we're part of a fresh cluster start, and also skip bootstrap. This is less confusing for new users, + // as well as avoiding the nonsensical state of trying to stream from cluster with no active peers. - Token<?> token; - InetAddress current = null; - logger_.debug("Bootstrap variables: %s %s %s %s", + Set<InetAddress> current = new HashSet<InetAddress>(); + Collection<Token> tokens; - // 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) ++ logger.debug("Bootstrap variables: %s %s %s %s", + new Object[] {DatabaseDescriptor.isAutoBootstrap(), SystemTable.bootstrapInProgress(), SystemTable.bootstrapComplete(), schemaPresent}); if (DatabaseDescriptor.isAutoBootstrap() - && !(SystemTable.bootstrapComplete() || DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress()) || !Schema.instance.getNonSystemTables().isEmpty()) - || SystemTable.bootstrapInProgress()) + && (SystemTable.bootstrapInProgress() || (!SystemTable.bootstrapComplete() && schemaPresent))) { if (SystemTable.bootstrapInProgress()) - logger_.warn("Detected previous bootstrap failure; retrying"); + 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 + setMode(Mode.JOINING, "waiting for ring information", true); + // first sleep the delay to make sure we see all our peers try { Thread.sleep(delay); @@@ -583,26 -648,15 +601,26 @@@ { throw new AssertionError(e); } - token = StorageService.getPartitioner().getTokenFactory().fromString(DatabaseDescriptor.getReplaceToken()); + tokens = new ArrayList<Token>(); + for (String token : DatabaseDescriptor.getReplaceTokens()) + tokens.add(StorageService.getPartitioner().getTokenFactory().fromString(token)); + // check for operator errors... - current = tokenMetadata_.getEndpoint(token); - if (null != current && Gossiper.instance.getEndpointStateForEndpoint(current).getUpdateTimestamp() > (System.currentTimeMillis() - delay)) - throw new UnsupportedOperationException("Cannnot replace a token for a Live node... "); - setMode(Mode.JOINING, "Replacing a node with token: " + token, true); + for (Token token : tokens) + { + InetAddress existing = tokenMetadata.getEndpoint(token); - if (null != existing) ++ if (existing != null) + { + if (Gossiper.instance.getEndpointStateForEndpoint(existing).getUpdateTimestamp() > (System.currentTimeMillis() - delay)) + throw new UnsupportedOperationException("Cannnot replace a token for a Live node... "); + current.add(existing); + } + } + + setMode(Mode.JOINING, "Replacing a node with token: " + tokens, true); } - bootstrap(token); + bootstrap(tokens); assert !isBootstrapMode; // bootstrap will block until finished } else