(lazily )create and persist a host ID if none exists

Patch by eevans; reviewed by Brandon Williams for CASSANDRA-4120


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/712ffeb4
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/712ffeb4
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/712ffeb4

Branch: refs/heads/trunk
Commit: 712ffeb4a518e1758c127da80beb3a6b1cb9928d
Parents: bfe2dfb
Author: Eric Evans <eev...@sym-link.com>
Authored: Wed May 2 18:45:36 2012 -0500
Committer: Eric Evans <eev...@sym-link.com>
Committed: Wed May 2 18:45:36 2012 -0500

----------------------------------------------------------------------
 .../org/apache/cassandra/config/CFMetaData.java    |    2 +
 .../cassandra/config/DatabaseDescriptor.java       |    1 +
 .../org/apache/cassandra/config/KSMetaData.java    |    3 +-
 src/java/org/apache/cassandra/db/SystemTable.java  |   47 +++++++++++++++
 .../unit/org/apache/cassandra/config/DefsTest.java |    1 +
 .../org/apache/cassandra/db/SystemTableTest.java   |    9 +++
 6 files changed, 62 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/712ffeb4/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java 
b/src/java/org/apache/cassandra/config/CFMetaData.java
index 08702e7..bca6984 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -156,6 +156,8 @@ public final class CFMetaData
                                           
ColumnDefinition.ascii("component_index", 2));
     }
 
+    public static final CFMetaData HostIdCf = 
newSystemMetadata(SystemTable.HOST_ID_CF, 11, "Host Identifier", 
UUIDType.instance, null);
+
     public enum Caching
     {
         ALL, KEYS_ONLY, ROWS_ONLY, NONE;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/712ffeb4/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java 
b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 8816733..afe2242 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -446,6 +446,7 @@ public class DatabaseDescriptor
             Schema.instance.load(CFMetaData.SchemaKeyspacesCf);
             Schema.instance.load(CFMetaData.SchemaColumnFamiliesCf);
             Schema.instance.load(CFMetaData.SchemaColumnsCf);
+            Schema.instance.load(CFMetaData.HostIdCf);
 
             Schema.instance.addSystemTable(systemMeta);
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/712ffeb4/src/java/org/apache/cassandra/config/KSMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/KSMetaData.java 
b/src/java/org/apache/cassandra/config/KSMetaData.java
index 611b2d9..0fd5461 100644
--- a/src/java/org/apache/cassandra/config/KSMetaData.java
+++ b/src/java/org/apache/cassandra/config/KSMetaData.java
@@ -84,7 +84,8 @@ public final class KSMetaData
                                                 CFMetaData.VersionCf,
                                                 CFMetaData.SchemaKeyspacesCf,
                                                 
CFMetaData.SchemaColumnFamiliesCf,
-                                                CFMetaData.SchemaColumnsCf);
+                                                CFMetaData.SchemaColumnsCf,
+                                                CFMetaData.HostIdCf);
         return new KSMetaData(Table.SYSTEM_TABLE, LocalStrategy.class, 
optsWithRF(1), true, cfDefs);
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/712ffeb4/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 69afbcd..335cf19 100644
--- a/src/java/org/apache/cassandra/db/SystemTable.java
+++ b/src/java/org/apache/cassandra/db/SystemTable.java
@@ -44,6 +44,7 @@ import org.apache.cassandra.thrift.Constants;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.NodeId;
+import org.apache.cassandra.utils.UUIDGen;
 
 public class SystemTable
 {
@@ -52,6 +53,7 @@ public class SystemTable
     public static final String INDEX_CF = "IndexInfo";
     public static final String NODE_ID_CF = "NodeIdInfo";
     public static final String VERSION_CF = "Versions";
+    public static final String HOST_ID_CF = "HostUUID";
     // see layout description in the DefsTable class header
     public static final String SCHEMA_KEYSPACES_CF = "schema_keyspaces";
     public static final String SCHEMA_COLUMNFAMILIES_CF = 
"schema_columnfamilies";
@@ -67,6 +69,7 @@ public class SystemTable
     private static final ByteBuffer CLUSTERNAME = 
ByteBufferUtil.bytes("ClusterName");
     private static final ByteBuffer CURRENT_LOCAL_NODE_ID_KEY = 
ByteBufferUtil.bytes("CurrentLocal");
     private static final ByteBuffer ALL_LOCAL_NODE_ID_KEY = 
ByteBufferUtil.bytes("Local");
+    private static final ByteBuffer HOST_ID_KEY = ByteBufferUtil.bytes("Id");
 
     private static DecoratedKey decorate(ByteBuffer key)
     {
@@ -426,6 +429,50 @@ public class SystemTable
     }
 
     /**
+     * Read the host ID from the system table, creating (and storing) one if
+     * none exists.
+     */
+    public static UUID getLocalHostId()
+    {
+        UUID hostId = null;
+
+        // Look up the Host UUID (return it if found)
+        Table table = Table.open(Table.SYSTEM_TABLE);
+        QueryFilter filter = 
QueryFilter.getIdentityFilter(decorate(HOST_ID_KEY), new QueryPath(HOST_ID_CF));
+        ColumnFamily cf = 
table.getColumnFamilyStore(HOST_ID_CF).getColumnFamily(filter);
+
+        if (cf != null)
+        {
+            cf = ColumnFamilyStore.removeDeleted(cf, 0);
+            assert cf.getColumnCount() <= 1;
+            if (cf.getColumnCount() > 0)
+                return UUIDGen.getUUID(cf.iterator().next().name());
+        }
+
+        // ID not found, generate a new one, persist, and then return it.
+        hostId = UUID.randomUUID();
+        long now = FBUtilities.timestampMicros();
+
+        logger.warn("No host ID found, created {} (Note: This should happen 
exactly once per node).", hostId);
+
+        cf = ColumnFamily.create(Table.SYSTEM_TABLE, HOST_ID_CF);
+        cf.addColumn(new Column(ByteBuffer.wrap(UUIDGen.decompose(hostId)), 
ByteBufferUtil.bytes(now), now));
+
+        RowMutation rm = new RowMutation(Table.SYSTEM_TABLE, HOST_ID_KEY);
+        rm.add(cf);
+        try
+        {
+            rm.apply();
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+
+        return hostId;
+    }
+
+    /**
      * Read the current local node id from the system table or null if no
      * such node id is recorded.
      */

http://git-wip-us.apache.org/repos/asf/cassandra/blob/712ffeb4/test/unit/org/apache/cassandra/config/DefsTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/config/DefsTest.java 
b/test/unit/org/apache/cassandra/config/DefsTest.java
index 69db1f6..b32f2dd 100644
--- a/test/unit/org/apache/cassandra/config/DefsTest.java
+++ b/test/unit/org/apache/cassandra/config/DefsTest.java
@@ -55,6 +55,7 @@ public class DefsTest extends SchemaLoader
         assert CFMetaData.HintsCf.cfId == 1;
         assert CFMetaData.MigrationsCf.cfId == 2;
         assert CFMetaData.SchemaCf.cfId == 3;
+        assert CFMetaData.HostIdCf.cfId == 11;
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cassandra/blob/712ffeb4/test/unit/org/apache/cassandra/db/SystemTableTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/SystemTableTest.java 
b/test/unit/org/apache/cassandra/db/SystemTableTest.java
index e4f3d74..0c7b8a3 100644
--- a/test/unit/org/apache/cassandra/db/SystemTableTest.java
+++ b/test/unit/org/apache/cassandra/db/SystemTableTest.java
@@ -23,6 +23,7 @@ package org.apache.cassandra.db;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.UUID;
 
 import com.google.common.base.Charsets;
 import org.junit.Test;
@@ -52,4 +53,12 @@ public class SystemTableTest
         SystemTable.removeToken(token);
         assert !SystemTable.loadTokens().containsKey(token);
     }
+
+    @Test
+    public void testLocalHostID()
+    {
+        UUID firstId = SystemTable.getLocalHostId();
+        UUID secondId = SystemTable.getLocalHostId();
+        assert firstId.equals(secondId) : String.format("%s != %s%n", 
firstId.toString(), secondId.toString());
+    }
 }

Reply via email to