cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jbel...@apache.org
Subject svn commit: r1003060 - in /cassandra/trunk: CHANGES.txt src/java/org/apache/cassandra/db/SystemTable.java src/java/org/apache/cassandra/service/StorageService.java test/unit/org/apache/cassandra/db/SystemTableTest.java
Date Thu, 30 Sep 2010 13:35:26 GMT
Author: jbellis
Date: Thu Sep 30 13:35:26 2010
New Revision: 1003060

URL: http://svn.apache.org/viewvc?rev=1003060&view=rev
Log:
log warning when using randomly generated token.
patch by jbellis; reviewed by gdusbabek for CASSANDRA-1552

Removed:
    cassandra/trunk/test/unit/org/apache/cassandra/db/SystemTableTest.java
Modified:
    cassandra/trunk/CHANGES.txt
    cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java
    cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java

Modified: cassandra/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=1003060&r1=1003059&r2=1003060&view=diff
==============================================================================
--- cassandra/trunk/CHANGES.txt (original)
+++ cassandra/trunk/CHANGES.txt Thu Sep 30 13:35:26 2010
@@ -1,5 +1,6 @@
 dev
  * add strategy options to describe_keyspace output (CASSANDRA-1560)
+ * log warning when using randomly generated token (CASSANDRA-1552)
 
 
 0.7-beta2

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java?rev=1003060&r1=1003059&r2=1003060&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/SystemTable.java Thu Sep 30 13:35:26
2010
@@ -59,7 +59,6 @@ public class SystemTable
     private static final byte[] GENERATION = "Generation".getBytes(UTF_8);
     private static final byte[] CLUSTERNAME = "ClusterName".getBytes(UTF_8);
     private static final byte[] PARTITIONER = "Partioner".getBytes(UTF_8);
-    private static StorageMetadata metadata;
 
     private static DecoratedKey decorate(byte[] key)
     {
@@ -110,7 +109,6 @@ public class SystemTable
     */
     public static synchronized void updateToken(Token token)
     {
-        assert metadata != null;
         IPartitioner p = StorageService.getPartitioner();
         ColumnFamily cf = ColumnFamily.create(Table.SYSTEM_TABLE, STATUS_CF);
         cf.addColumn(new Column(SystemTable.TOKEN, p.getTokenFactory().toByteArray(token),
new TimestampClock(System.currentTimeMillis())));
@@ -124,7 +122,6 @@ public class SystemTable
         {
             throw new IOError(e);
         }
-        metadata.setToken(token);
     }
 
     /**
@@ -134,7 +131,7 @@ public class SystemTable
      * 3. files are present but you can't read them: bad (suspect that the partitioner was
changed).
      * @throws ConfigurationException
      */
-    public static void checkHealth() throws ConfigurationException
+    public static void checkHealth() throws ConfigurationException, IOException
     {
         Table table = null;
         try
@@ -150,9 +147,8 @@ public class SystemTable
         }
         
         SortedSet<byte[]> cols = new TreeSet<byte[]>(BytesType.instance);
-        cols.add(TOKEN);
-        cols.add(GENERATION);
         cols.add(PARTITIONER);
+        cols.add(CLUSTERNAME);
         QueryFilter filter = QueryFilter.getNamesFilter(decorate(LOCATION_KEY), new QueryPath(STATUS_CF),
cols);
         ColumnFamily cf = table.getColumnFamilyStore(STATUS_CF).getColumnFamily(filter);
         
@@ -170,129 +166,62 @@ public class SystemTable
                 }); 
                 if (dbContents.length > 0)
                     throw new ConfigurationException("Found system table files, but they
couldn't be loaded. Did you change the partitioner?");
-            }   
-            // no system files. data is either in the commit log or this is a new node.
+            }
+
+            // no system files.  this is a new node.
+            RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, LOCATION_KEY);
+            cf = ColumnFamily.create(Table.SYSTEM_TABLE, SystemTable.STATUS_CF);
+            cf.addColumn(new Column(PARTITIONER, DatabaseDescriptor.getPartitioner().getClass().getName().getBytes(UTF_8),
new TimestampClock(FBUtilities.timestampMicros())));
+            cf.addColumn(new Column(CLUSTERNAME, DatabaseDescriptor.getClusterName().getBytes(),
new TimestampClock(FBUtilities.timestampMicros())));
+            rm.add(cf);
+            rm.apply();
+
             return;
         }
         
         
-        // token and generation should *always* be there. If either are missing, we can assume
that the partitioner has
-        // been switched.
-        if (cf.getColumnCount() > 0 && (cf.getColumn(GENERATION) == null || cf.getColumn(TOKEN)
== null))
-            throw new ConfigurationException("Couldn't read system generation or token. Did
you change the partitioner?");
         IColumn partitionerCol = cf.getColumn(PARTITIONER);
-        if (partitionerCol != null && !DatabaseDescriptor.getPartitioner().getClass().getName().equals(new
String(partitionerCol.value(), UTF_8)))
+        IColumn clusterCol = cf.getColumn(CLUSTERNAME);
+        assert partitionerCol != null;
+        assert clusterCol != null;
+        if (!DatabaseDescriptor.getPartitioner().getClass().getName().equals(new String(partitionerCol.value(),
UTF_8)))
             throw new ConfigurationException("Detected partitioner mismatch! Did you change
the partitioner?");
-        if (partitionerCol == null)
-            logger.info("Did not see a partitioner in system storage.");
+        if (!DatabaseDescriptor.getClusterName().equals(new String(clusterCol.value())));
+            throw new ConfigurationException("Saved cluster name " + new String(clusterCol.value())
+ " != configured name " + DatabaseDescriptor.getClusterName());
     }
-    
-    /*
-     * This method reads the system table and retrieves the metadata
-     * associated with this storage instance. Currently we store the
-     * metadata in a Column Family called LocatioInfo which has two
-     * columns namely "Token" and "Generation". This is the token that
-     * gets gossiped around and the generation info is used for FD.
-     * We also store whether we're in bootstrap mode in a third column
-    */
-    public static synchronized StorageMetadata initMetadata() throws IOException
+
+    public static Token getSavedToken()
     {
-        if (metadata != null)  // guard to protect against being called twice
-            return metadata;
+        Table table = Table.open(Table.SYSTEM_TABLE);
+        QueryFilter filter = QueryFilter.getNamesFilter(decorate(LOCATION_KEY), new QueryPath(STATUS_CF),
TOKEN);
+        ColumnFamily cf = table.getColumnFamilyStore(STATUS_CF).getColumnFamily(filter);
+        return cf == null ? null : StorageService.getPartitioner().getTokenFactory().fromByteArray(cf.getColumn(TOKEN).value());
+    }
 
-        /* Read the system table to retrieve the storage ID and the generation */
-        IPartitioner p = StorageService.getPartitioner();
+    public static int incrementAndGetGeneration() throws IOException
+    {
         Table table = Table.open(Table.SYSTEM_TABLE);
-        SortedSet<byte[]> columns = new TreeSet<byte[]>(BytesType.instance);
-        columns.add(TOKEN);
-        columns.add(GENERATION);
-        columns.add(CLUSTERNAME);
-        QueryFilter filter = QueryFilter.getNamesFilter(decorate(LOCATION_KEY), new QueryPath(STATUS_CF),
columns);
+        QueryFilter filter = QueryFilter.getNamesFilter(decorate(LOCATION_KEY), new QueryPath(STATUS_CF),
TOKEN);
         ColumnFamily cf = table.getColumnFamilyStore(STATUS_CF).getColumnFamily(filter);
-        String partitioner = DatabaseDescriptor.getPartitioner().getClass().getName();
 
+        int generation;
         if (cf == null)
         {
-            Token token;
-            String initialToken = DatabaseDescriptor.getInitialToken();
-            if (initialToken == null)
-                token = p.getRandomToken();
-            else
-                token = p.getTokenFactory().fromString(initialToken);
-
-            logger.info("Saved Token not found. Using " + token);
             // seconds-since-epoch isn't a foolproof new generation
             // (where foolproof is "guaranteed to be larger than the last one seen at this
ip address"),
             // but it's as close as sanely possible
-            int generation = (int) (System.currentTimeMillis() / 1000);
-
-            logger.info("Saved ClusterName not found. Using " + DatabaseDescriptor.getClusterName());
-
-            RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, LOCATION_KEY);
-            cf = ColumnFamily.create(Table.SYSTEM_TABLE, SystemTable.STATUS_CF);
-            cf.addColumn(new Column(TOKEN, p.getTokenFactory().toByteArray(token), TimestampClock.ZERO_VALUE));
-            cf.addColumn(new Column(GENERATION, FBUtilities.toByteArray(generation), TimestampClock.ZERO_VALUE));
-            cf.addColumn(new Column(CLUSTERNAME, DatabaseDescriptor.getClusterName().getBytes(),
TimestampClock.ZERO_VALUE));
-            cf.addColumn(new Column(PARTITIONER, partitioner.getBytes(UTF_8), TimestampClock.ZERO_VALUE));
-            rm.add(cf);
-            rm.apply();
-            try
-            {
-                table.getColumnFamilyStore(SystemTable.STATUS_CF).forceBlockingFlush();
-            }
-            catch (ExecutionException e)
-            {
-                throw new RuntimeException(e);
-            }
-            catch (InterruptedException e)
-            {
-                throw new RuntimeException(e);
-            }
-            metadata = new StorageMetadata(token, generation, DatabaseDescriptor.getClusterName().getBytes());
-            return metadata;
-        }
-
-        if (cf.getColumnCount() < 2)
-            throw new RuntimeException("Expected both token and generation columns; found
" + cf);
-        /* we crashed and came back up: make sure new generation is greater than old */
-        IColumn tokenColumn = cf.getColumn(TOKEN);
-        assert tokenColumn != null : cf;
-        Token token = p.getTokenFactory().fromByteArray(tokenColumn.value());
-        logger.info("Saved Token found: " + token);
-
-        IColumn generation = cf.getColumn(GENERATION);
-        assert generation != null : cf;
-        int gen = Math.max(FBUtilities.byteArrayToInt(generation.value()) + 1, (int) (System.currentTimeMillis()
/ 1000));
-
-        IColumn cluster = cf.getColumn(CLUSTERNAME);
-        IColumn partitionerColumn = cf.getColumn(PARTITIONER);
-
-        RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, LOCATION_KEY);
-        cf = ColumnFamily.create(Table.SYSTEM_TABLE, SystemTable.STATUS_CF);
-        TimestampClock genClock = new TimestampClock(((TimestampClock)generation.clock()).timestamp()
+ 1);
-        Column generation2 = new Column(GENERATION, FBUtilities.toByteArray(gen), genClock);
-        cf.addColumn(generation2);
-        byte[] cname;
-        if (cluster != null)
-        {
-            logger.info("Saved ClusterName found: " + new String(cluster.value()));
-            cname = cluster.value();
+            generation = (int) (System.currentTimeMillis() / 1000);
         }
         else
         {
-            Column clustername = new Column(CLUSTERNAME, DatabaseDescriptor.getClusterName().getBytes(),
TimestampClock.ZERO_VALUE);
-            cf.addColumn(clustername);
-            cname = DatabaseDescriptor.getClusterName().getBytes();
-            logger.info("Saved ClusterName not found. Using " + DatabaseDescriptor.getClusterName());
-        }
-        
-        if (partitionerColumn == null)
-        {
-            Column c = new Column(PARTITIONER, partitioner.getBytes(UTF_8), TimestampClock.ZERO_VALUE);
-            cf.addColumn(c);
-            logger.info("Saved partitioner not found. Using " + partitioner);
+            generation = Math.max(FBUtilities.byteArrayToInt(cf.getColumn(GENERATION).value())
+ 1,
+                                  (int) (System.currentTimeMillis() / 1000));
         }
-        
+
+        RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, LOCATION_KEY);
+        cf = ColumnFamily.create(Table.SYSTEM_TABLE, SystemTable.STATUS_CF);
+        TimestampClock genClock = new TimestampClock(FBUtilities.timestampMicros());
+        cf.addColumn(new Column(GENERATION, FBUtilities.toByteArray(generation), genClock));
         rm.add(cf);
         rm.apply();
         try
@@ -305,13 +234,12 @@ public class SystemTable
         }
         catch (InterruptedException e)
         {
-            throw new RuntimeException(e);
+            throw new AssertionError(e);
         }
 
-        metadata = new StorageMetadata(token, gen, cname);
-        return metadata;
+        return generation;
     }
-
+    
     public static boolean isBootstrapped()
     {
         Table table = Table.open(Table.SYSTEM_TABLE);
@@ -362,38 +290,4 @@ public class SystemTable
             throw new IOError(e);
         }
     }
-
-    public static class StorageMetadata
-    {
-        private Token token;
-        private int generation;
-        private byte[] cluster;
-
-        StorageMetadata(Token storageId, int generation, byte[] clustername)
-        {
-            token = storageId;
-            this.generation = generation;
-            cluster = clustername;
-        }
-
-        public Token getToken()
-        {
-            return token;
-        }
-
-        public void setToken(Token storageId)
-        {
-            token = storageId;
-        }
-
-        public int getGeneration()
-        {
-            return generation;
-        }
-
-        public byte[] getClusterName()
-        {
-            return cluster;
-        }
-    }
 }

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=1003060&r1=1003059&r2=1003060&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java Thu Sep 30 13:35:26
2010
@@ -50,7 +50,6 @@ import org.apache.cassandra.dht.Range;
 import org.apache.cassandra.dht.Token;
 import org.apache.cassandra.gms.*;
 import org.apache.cassandra.io.DeletionService;
-import org.apache.cassandra.io.sstable.SSTableReader;
 import org.apache.cassandra.io.util.FileUtils;
 import org.apache.cassandra.locator.AbstractReplicationStrategy;
 import org.apache.cassandra.locator.IEndpointSnitch;
@@ -159,7 +158,6 @@ public class StorageService implements I
 
     /* This abstraction maintains the token/endpoint metadata information */
     private TokenMetadata tokenMetadata_ = new TokenMetadata();
-    private SystemTable.StorageMetadata storageMetadata_;
 
     /* This thread pool does consistency checks when the client doesn't care about consistency
*/
     private ExecutorService consistencyManager_ = new JMXEnabledThreadPoolExecutor(DatabaseDescriptor.getConsistencyThreads(),
@@ -340,15 +338,6 @@ public class StorageService implements I
         }
         initialized = true;
         isClientMode = false;
-        storageMetadata_ = SystemTable.initMetadata();
-
-        // be certain that the recorded clustername matches what the user specified
-        if (!(Arrays.equals(storageMetadata_.getClusterName(),DatabaseDescriptor.getClusterName().getBytes())))
-        {
-            logger_.error("ClusterName mismatch: " + new String(storageMetadata_.getClusterName())
+ " != " +
-                    DatabaseDescriptor.getClusterName());
-            System.exit(3);
-        }
 
         DatabaseDescriptor.createAllDirectories();
 
@@ -368,7 +357,7 @@ public class StorageService implements I
         // (we won't be part of the storage ring though until we add a nodeId to our state,
below.)
         Gossiper.instance.register(this);
         Gossiper.instance.register(migrationManager);
-        Gossiper.instance.start(FBUtilities.getLocalAddress(), storageMetadata_.getGeneration());
// needed for node-ring gathering.
+        Gossiper.instance.start(FBUtilities.getLocalAddress(), SystemTable.incrementAndGetGeneration());
// needed for node-ring gathering.
 
         MessagingService.instance.listen(FBUtilities.getLocalAddress());
         StorageLoadBalancer.instance.startBroadcasting();
@@ -419,8 +408,23 @@ public class StorageService implements I
         }
         else
         {
+            Token token = SystemTable.getSavedToken();
+            if (token == null)
+            {
+                String initialToken = DatabaseDescriptor.getInitialToken();
+                if (initialToken == null)
+                {
+                    token = partitioner_.getRandomToken();
+                    logger_.warn("Generated random token " + token + ". Random tokens will
result in an unbalanced ring; see http://wiki.apache.org/cassandra/Operations");
+                }
+                else
+                {
+                    token = partitioner_.getTokenFactory().fromString(initialToken);
+                    logger_.info("Saved Token not found. Using " + token + " from configuration");
+                }
+                SystemTable.updateToken(token);
+            }
             SystemTable.setBootstrapped(true);
-            Token token = storageMetadata_.getToken();
             tokenMetadata_.updateNormalToken(token, FBUtilities.getLocalAddress());
             Gossiper.instance.addLocalApplicationState(ApplicationState.STATUS, valueFactory.normal(token));
             setMode("Normal", false);
@@ -1109,7 +1113,9 @@ public class StorageService implements I
 
     public Token getLocalToken()
     {
-        return storageMetadata_.getToken();
+        Token token = SystemTable.getSavedToken();
+        assert token != null; // should not be called before initServer sets this
+        return token;
     }
 
     /* These methods belong to the MBean interface */



Mime
View raw message