You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2012/12/07 10:14:03 UTC

[3/3] git commit: Don't generate UUID based on other nodes' address

Don't generate UUID based on other nodes' address

patch by slebresne; reviewed by jbellis for CASSANDRA-5002


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

Branch: refs/heads/cassandra-1.2
Commit: 7442fc02098c468447a4610d84023336f57545a4
Parents: b4f3693
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Fri Dec 7 10:07:57 2012 +0100
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Fri Dec 7 10:09:25 2012 +0100

----------------------------------------------------------------------
 CHANGES.txt                                        |    1 +
 src/java/org/apache/cassandra/db/RowMutation.java  |    2 +-
 .../org/apache/cassandra/db/marshal/UUIDType.java  |    2 +-
 .../cassandra/hadoop/ColumnFamilyRecordReader.java |   14 +--
 .../cassandra/service/AntiEntropyService.java      |    2 +-
 .../cassandra/streaming/StreamInSession.java       |    2 +-
 .../cassandra/streaming/StreamOutSession.java      |    2 +-
 .../cassandra/streaming/StreamingRepairTask.java   |    2 +-
 .../apache/cassandra/thrift/CassandraServer.java   |    2 +-
 .../org/apache/cassandra/tracing/TraceState.java   |    2 +-
 .../transport/messages/ExecuteMessage.java         |    2 +-
 .../transport/messages/PrepareMessage.java         |    2 +-
 .../cassandra/transport/messages/QueryMessage.java |    2 +-
 src/java/org/apache/cassandra/utils/CounterId.java |    2 +-
 .../org/apache/cassandra/utils/FBUtilities.java    |   21 +++
 src/java/org/apache/cassandra/utils/UUIDGen.java   |   99 +++++++--------
 .../apache/cassandra/cql/jdbc/ClientUtilsTest.java |    2 +-
 .../cassandra/db/marshal/CompositeTypeTest.java    |    2 +-
 .../db/marshal/DynamicCompositeTypeTest.java       |    2 +-
 .../apache/cassandra/db/marshal/RoundTripTest.java |    4 +-
 .../cassandra/db/marshal/TimeUUIDTypeTest.java     |   14 +-
 .../apache/cassandra/db/marshal/UUIDTypeTest.java  |   31 ++----
 .../cassandra/io/LazilyCompactedRowTest.java       |    2 +-
 .../cassandra/streaming/SerializationsTest.java    |    6 +-
 .../unit/org/apache/cassandra/utils/UUIDTests.java |   14 +-
 .../cassandra/stress/operations/CqlInserter.java   |    2 +-
 .../apache/cassandra/stress/util/Operation.java    |    2 +-
 27 files changed, 116 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 385dca6..2ffaee5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,7 @@
  * Fix preparing insert queries (CASSANDRA-5016)
  * Fix preparing queries with counter increment (CASSANDRA-5022)
  * Fix preparing updates with collections (CASSANDRA-5017)
+ * Don't generate UUID based on other node address (CASSANDRA-5002)
 Merged from 1.1
  * Improve schema propagation performance (CASSANDRA-5025)
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/db/RowMutation.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/RowMutation.java b/src/java/org/apache/cassandra/db/RowMutation.java
index 4fcee8a..a8e845d 100644
--- a/src/java/org/apache/cassandra/db/RowMutation.java
+++ b/src/java/org/apache/cassandra/db/RowMutation.java
@@ -105,7 +105,7 @@ public class RowMutation implements IMutation
     public static RowMutation hintFor(RowMutation mutation, UUID targetId) throws IOException
     {
         RowMutation rm = new RowMutation(Table.SYSTEM_KS, UUIDType.instance.decompose(targetId));
-        UUID hintId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+        UUID hintId = UUIDGen.getTimeUUID();
 
         // determine the TTL for the RowMutation
         // this is set at the smallest GCGraceSeconds for any of the CFs in the RM

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/db/marshal/UUIDType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/UUIDType.java b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
index 53f87d2..cef7b00 100644
--- a/src/java/org/apache/cassandra/db/marshal/UUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
@@ -212,7 +212,7 @@ public class UUIDType extends AbstractType<UUID>
         }
         else if (source.toLowerCase().equals("now"))
         {
-            idBytes = ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress())));
+            idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
         }
         // Milliseconds since epoch?
         else if (source.matches("^\\d+$"))

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordReader.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordReader.java b/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordReader.java
index f8134b9..07a5460 100644
--- a/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordReader.java
+++ b/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordReader.java
@@ -19,8 +19,6 @@ package org.apache.cassandra.hadoop;
 
 import java.io.IOException;
 import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.util.*;
@@ -197,17 +195,7 @@ public class ColumnFamilyRecordReader extends RecordReader<ByteBuffer, SortedMap
     // not necessarily on Cassandra machines, too.  This should be adequate for single-DC clusters, at least.
     private String getLocation()
     {
-        ArrayList<InetAddress> localAddresses = new ArrayList<InetAddress>();
-        try
-        {
-            Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
-            while (nets.hasMoreElements())
-                localAddresses.addAll(Collections.list(nets.nextElement().getInetAddresses()));
-        }
-        catch (SocketException e)
-        {
-            throw new AssertionError(e);
-        }
+        Collection<InetAddress> localAddresses = FBUtilities.getAllLocalAddresses();
 
         for (InetAddress address : localAddresses)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/service/AntiEntropyService.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/AntiEntropyService.java b/src/java/org/apache/cassandra/service/AntiEntropyService.java
index 9f97f95..a04402f 100644
--- a/src/java/org/apache/cassandra/service/AntiEntropyService.java
+++ b/src/java/org/apache/cassandra/service/AntiEntropyService.java
@@ -603,7 +603,7 @@ public class AntiEntropyService
 
         public RepairSession(Range<Token> range, String tablename, boolean isSequential, boolean isLocal, String... cfnames)
         {
-            this(UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress()).toString(), range, tablename, isSequential, isLocal, cfnames);
+            this(UUIDGen.getTimeUUID().toString(), range, tablename, isSequential, isLocal, cfnames);
         }
 
         private RepairSession(String id, Range<Token> range, String tablename, boolean isSequential, boolean isLocal, String[] cfnames)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/streaming/StreamInSession.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/streaming/StreamInSession.java b/src/java/org/apache/cassandra/streaming/StreamInSession.java
index a29acc7..96c31da 100644
--- a/src/java/org/apache/cassandra/streaming/StreamInSession.java
+++ b/src/java/org/apache/cassandra/streaming/StreamInSession.java
@@ -59,7 +59,7 @@ public class StreamInSession extends AbstractStreamSession
 
     public static StreamInSession create(InetAddress host, IStreamCallback callback)
     {
-        StreamInSession session = new StreamInSession(host, UUIDGen.makeType1UUIDFromHost(host), callback);
+        StreamInSession session = new StreamInSession(host, UUIDGen.getTimeUUID(), callback);
         sessions.put(session.getSessionId(), session);
         return session;
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/streaming/StreamOutSession.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/streaming/StreamOutSession.java b/src/java/org/apache/cassandra/streaming/StreamOutSession.java
index ad312ff..dbdbad9 100644
--- a/src/java/org/apache/cassandra/streaming/StreamOutSession.java
+++ b/src/java/org/apache/cassandra/streaming/StreamOutSession.java
@@ -44,7 +44,7 @@ public class StreamOutSession extends AbstractStreamSession
 
     public static StreamOutSession create(String table, InetAddress host, IStreamCallback callback)
     {
-        return create(table, host, UUIDGen.makeType1UUIDFromHost(host), callback);
+        return create(table, host, UUIDGen.getTimeUUID(), callback);
     }
 
     public static StreamOutSession create(String table, InetAddress host, UUID sessionId)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/streaming/StreamingRepairTask.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/streaming/StreamingRepairTask.java b/src/java/org/apache/cassandra/streaming/StreamingRepairTask.java
index 33c3f39..5d456a6 100644
--- a/src/java/org/apache/cassandra/streaming/StreamingRepairTask.java
+++ b/src/java/org/apache/cassandra/streaming/StreamingRepairTask.java
@@ -90,7 +90,7 @@ public class StreamingRepairTask implements Runnable
     public static StreamingRepairTask create(InetAddress ep1, InetAddress ep2, String tableName, String cfName, Collection<Range<Token>> ranges, Runnable callback)
     {
         InetAddress local = FBUtilities.getBroadcastAddress();
-        UUID id = UUIDGen.makeType1UUIDFromHost(local);
+        UUID id = UUIDGen.getTimeUUID();
         // We can take anyone of the node as source or destination, however if one is localhost, we put at source to avoid a forwarding
         InetAddress src = ep2.equals(local) ? ep2 : ep1;
         InetAddress dst = ep2.equals(local) ? ep1 : ep2;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/thrift/CassandraServer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java
index 5f05057..4255742 100644
--- a/src/java/org/apache/cassandra/thrift/CassandraServer.java
+++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java
@@ -1817,7 +1817,7 @@ public class CassandraServer implements Cassandra.Iface
 
     public ByteBuffer trace_next_query() throws TException
     {
-        UUID sessionId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+        UUID sessionId = UUIDGen.getTimeUUID();
         state().getQueryState().prepareTracingSession(sessionId);
         return TimeUUIDType.instance.decompose(sessionId);
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/tracing/TraceState.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tracing/TraceState.java b/src/java/org/apache/cassandra/tracing/TraceState.java
index e60998f..8fb3119 100644
--- a/src/java/org/apache/cassandra/tracing/TraceState.java
+++ b/src/java/org/apache/cassandra/tracing/TraceState.java
@@ -85,7 +85,7 @@ public class TraceState
     public void trace(final String message)
     {
         final int elapsed = elapsed();
-        final ByteBuffer eventId = ByteBufferUtil.bytes(UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress()));
+        final ByteBuffer eventId = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
 
         final String threadName = Thread.currentThread().getName();
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java b/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java
index ccddbc7..3aca4c5 100644
--- a/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java
+++ b/src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java
@@ -108,7 +108,7 @@ public class ExecuteMessage extends Message.Request
             UUID tracingId = null;
             if (isTracingRequested())
             {
-                tracingId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+                tracingId = UUIDGen.getTimeUUID();
                 state.prepareTracingSession(tracingId);
             }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/transport/messages/PrepareMessage.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/messages/PrepareMessage.java b/src/java/org/apache/cassandra/transport/messages/PrepareMessage.java
index 06f25bf..5c1d1b9 100644
--- a/src/java/org/apache/cassandra/transport/messages/PrepareMessage.java
+++ b/src/java/org/apache/cassandra/transport/messages/PrepareMessage.java
@@ -65,7 +65,7 @@ public class PrepareMessage extends Message.Request
             UUID tracingId = null;
             if (isTracingRequested())
             {
-                tracingId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+                tracingId = UUIDGen.getTimeUUID();
                 state.prepareTracingSession(tracingId);
             }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/transport/messages/QueryMessage.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/messages/QueryMessage.java b/src/java/org/apache/cassandra/transport/messages/QueryMessage.java
index 872782d..7b80470 100644
--- a/src/java/org/apache/cassandra/transport/messages/QueryMessage.java
+++ b/src/java/org/apache/cassandra/transport/messages/QueryMessage.java
@@ -75,7 +75,7 @@ public class QueryMessage extends Message.Request
             UUID tracingId = null;
             if (isTracingRequested())
             {
-                tracingId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+                tracingId = UUIDGen.getTimeUUID();
                 state.prepareTracingSession(tracingId);
             }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/utils/CounterId.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/CounterId.java b/src/java/org/apache/cassandra/utils/CounterId.java
index 2520d9f..f37c396 100644
--- a/src/java/org/apache/cassandra/utils/CounterId.java
+++ b/src/java/org/apache/cassandra/utils/CounterId.java
@@ -117,7 +117,7 @@ public class CounterId implements Comparable<CounterId>
 
     public static CounterId generate()
     {
-        return new CounterId(ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress()))));
+        return new CounterId(ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes()));
     }
 
     /*

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/utils/FBUtilities.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/FBUtilities.java b/src/java/org/apache/cassandra/utils/FBUtilities.java
index 783ce48..fd3ad4c 100644
--- a/src/java/org/apache/cassandra/utils/FBUtilities.java
+++ b/src/java/org/apache/cassandra/utils/FBUtilities.java
@@ -22,6 +22,8 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.math.BigInteger;
 import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
 import java.net.URL;
 import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
@@ -154,6 +156,25 @@ public class FBUtilities
         return broadcastInetAddress;
     }
 
+    public static Collection<InetAddress> getAllLocalAddresses()
+    {
+        Set<InetAddress> localAddresses = new HashSet<InetAddress>();
+        try
+        {
+            Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
+            if (nets != null)
+            {
+                while (nets.hasMoreElements())
+                    localAddresses.addAll(Collections.list(nets.nextElement().getInetAddresses()));
+            }
+        }
+        catch (SocketException e)
+        {
+            throw new AssertionError(e);
+        }
+        return localAddresses;
+    }
+
     /**
      * Given two bit arrays represented as BigIntegers, containing the given
      * number of significant bits, calculate a midpoint.

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/src/java/org/apache/cassandra/utils/UUIDGen.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/UUIDGen.java b/src/java/org/apache/cassandra/utils/UUIDGen.java
index e207c20..7da9b5b 100644
--- a/src/java/org/apache/cassandra/utils/UUIDGen.java
+++ b/src/java/org/apache/cassandra/utils/UUIDGen.java
@@ -18,11 +18,14 @@
 package org.apache.cassandra.utils;
 
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.Random;
 import java.util.UUID;
 
@@ -34,54 +37,27 @@ public class UUIDGen
 {
     // A grand day! millis at 00:00:00.000 15 Oct 1582.
     private static final long START_EPOCH = -12219292800000L;
-    private static final long clock = new Random(System.currentTimeMillis()).nextLong();
+    private static final long clockSeqAndNode = makeClockSeqAndNode();
 
     // placement of this singleton is important.  It needs to be instantiated *AFTER* the other statics.
     private static final UUIDGen instance = new UUIDGen();
 
     private long lastNanos;
-    private final Map<InetAddress, Long> nodeCache = new HashMap<InetAddress, Long>();
-
-    private static final ThreadLocal<MessageDigest> localMD5Digest = new ThreadLocal<MessageDigest>()
-    {
-        @Override
-        protected MessageDigest initialValue()
-        {
-            try
-            {
-                return MessageDigest.getInstance("MD5");
-            }
-            catch (NoSuchAlgorithmException nsae)
-            {
-                throw new RuntimeException("MD5 digest algorithm is not available", nsae);
-            }
-        }
-
-        @Override
-        public MessageDigest get()
-        {
-            MessageDigest digest = super.get();
-            digest.reset();
-            return digest;
-        }
-    };
 
     private UUIDGen()
     {
-        // make sure someone didn't whack the clock by changing the order of instantiation.
-        if (clock == 0) throw new RuntimeException("singleton instantiation is misplaced.");
+        // make sure someone didn't whack the clockSeqAndNode by changing the order of instantiation.
+        if (clockSeqAndNode == 0) throw new RuntimeException("singleton instantiation is misplaced.");
     }
 
     /**
-     * Creates a type 1 UUID (time-based UUID) that substitutes a hash of
-     * an IP address in place of the MAC (unavailable to Java).
+     * Creates a type 1 UUID (time-based UUID).
      *
-     * @param addr the host address to use
      * @return a UUID instance
      */
-    public static UUID makeType1UUIDFromHost(InetAddress addr)
+    public static UUID getTimeUUID()
     {
-        return new UUID(instance.createTimeSafe(), instance.getClockSeqAndNode(addr));
+        return new UUID(instance.createTimeSafe(), clockSeqAndNode);
     }
 
     /** creates a type 1 uuid from raw bytes. */
@@ -151,7 +127,7 @@ public class UUIDGen
 
     private static byte[] createTimeUUIDBytes(long msb)
     {
-        long lsb = instance.getClockSeqAndNode(FBUtilities.getLocalAddress());
+        long lsb = clockSeqAndNode;
         byte[] uuidBytes = new byte[16];
 
         for (int i = 0; i < 8; i++)
@@ -177,13 +153,14 @@ public class UUIDGen
         return (uuid.timestamp() / 10000) + START_EPOCH;
     }
 
-    // todo: could cache value if we assume node doesn't change.
-    private long getClockSeqAndNode(InetAddress addr)
+    private static long makeClockSeqAndNode()
     {
+        long clock = new Random(System.currentTimeMillis()).nextLong();
+
         long lsb = 0;
         lsb |= 0x8000000000000000L;                 // variant (2 bits)
         lsb |= (clock & 0x0000000000003FFFL) << 48; // clock sequence (14 bits)
-        lsb |= makeNode(addr);                      // 6 bytes
+        lsb |= makeNode();                          // 6 bytes
         return lsb;
     }
 
@@ -221,31 +198,49 @@ public class UUIDGen
         return msb;
     }
 
-    // Lazily create node hashes, and cache them for later
-    private long makeNode(InetAddress addr)
+    private static long makeNode()
     {
-        if (nodeCache.containsKey(addr))
-            return nodeCache.get(addr);
+       /*
+        * We don't have access to the MAC address but need to generate a node part
+        * that identify this host as uniquely as possible.
+        * The spec says that one option is to take as many source that identify
+        * this node as possible and hash them together. That's what we do here by
+        * gathering all the ip of this host.
+        * Note that FBUtilities.getBroadcastAddress() should be enough to uniquely
+        * identify the node *in the cluster* but it triggers DatabaseDescriptor
+        * instanciation and the UUID generator is used in Stress for instance,
+        * where we don't want to require the yaml.
+        */
+        Collection<InetAddress> localAddresses = FBUtilities.getAllLocalAddresses();
+        if (localAddresses.isEmpty())
+            throw new RuntimeException("Cannot generate the node component of the UUID because cannot retrieve any IP addresses.");
 
         // ideally, we'd use the MAC address, but java doesn't expose that.
-        byte[] hash = hash(addr.toString());
+        byte[] hash = hash(localAddresses);
         long node = 0;
         for (int i = 0; i < Math.min(6, hash.length); i++)
             node |= (0x00000000000000ff & (long)hash[i]) << (5-i)*8;
         assert (0xff00000000000000L & node) == 0;
 
-        nodeCache.put(addr, node);
-
-        return node;
+        // Since we don't use the mac address, the spec says that multicast
+        // bit (least significant bit of the first octet of the node ID) must be 1.
+        return node | 0x0000010000000000L;
     }
 
-    private static byte[] hash(String... data)
+    private static byte[] hash(Collection<InetAddress> data)
     {
-        MessageDigest messageDigest = localMD5Digest.get();
-        for(String block : data)
-            messageDigest.update(block.getBytes());
+        try
+        {
+            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
+            for(InetAddress addr : data)
+                messageDigest.update(addr.getAddress());
 
-        return messageDigest.digest();
+            return messageDigest.digest();
+        }
+        catch (NoSuchAlgorithmException nsae)
+        {
+            throw new RuntimeException("MD5 digest algorithm is not available", nsae);
+        }
     }
 }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java b/test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java
index 76362bf..b584d1e 100644
--- a/test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java
+++ b/test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java
@@ -56,7 +56,7 @@ public class ClientUtilsTest
         JdbcUTF8.instance.compose(JdbcUTF8.instance.decompose("string"));
 
         // UUIDGen
-        UUID uuid = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
+        UUID uuid = UUIDGen.getTimeUUID();
         JdbcTimeUUID.instance.compose(JdbcTimeUUID.instance.decompose(uuid));
         JdbcUUID.instance.compose(JdbcUUID.instance.decompose(uuid));
         JdbcLexicalUUID.instance.compose(JdbcLexicalUUID.instance.decompose(uuid));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java
index d6c2e4f..2ed715e 100644
--- a/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java
+++ b/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java
@@ -56,7 +56,7 @@ public class CompositeTypeTest extends SchemaLoader
     static
     {
         for (int i = 0; i < UUID_COUNT; ++i)
-            uuids[i] = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+            uuids[i] = UUIDGen.getTimeUUID();
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java
index 08f772f..af9e85a 100644
--- a/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java
+++ b/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java
@@ -52,7 +52,7 @@ public class DynamicCompositeTypeTest extends SchemaLoader
     static
     {
         for (int i = 0; i < UUID_COUNT; ++i)
-            uuids[i] = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+            uuids[i] = UUIDGen.getTimeUUID();
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java b/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java
index 9cb761c..ef34ac5 100644
--- a/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java
+++ b/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java
@@ -97,7 +97,7 @@ public class RoundTripTest
     @Test
     public void testLexicalUUID()
     {
-        UUID uuid = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+        UUID uuid = UUIDGen.getTimeUUID();
         assert JdbcLexicalUUID.instance.getString(LexicalUUIDType.instance.fromString(uuid.toString()))
                 .equals(uuid.toString());
         assert LexicalUUIDType.instance.fromString(LexicalUUIDType.instance.getString(ByteBuffer.wrap(UUIDGen.decompose(uuid))))
@@ -109,7 +109,7 @@ public class RoundTripTest
     @Test
     public void testTimeUUID()
     {
-        UUID uuid = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
+        UUID uuid = UUIDGen.getTimeUUID();
         assert TimeUUIDType.instance.getString(TimeUUIDType.instance.fromString(uuid.toString()))
                 .equals(uuid.toString());
         assert TimeUUIDType.instance.fromString(TimeUUIDType.instance.getString(ByteBuffer.wrap(UUIDGen.decompose(uuid))))

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java
index 256fba4..e6c0393 100644
--- a/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java
+++ b/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java
@@ -37,7 +37,7 @@ public class TimeUUIDTypeTest
     @Test
     public void testEquality() throws UnknownHostException
     {
-        UUID a = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
+        UUID a = UUIDGen.getTimeUUID();
         UUID b = new UUID(a.getMostSignificantBits(), a.getLeastSignificantBits());
 
         timeUUIDType.validate(ByteBuffer.wrap(UUIDGen.decompose(a)));
@@ -48,9 +48,9 @@ public class TimeUUIDTypeTest
     @Test
     public void testSmaller() throws UnknownHostException
     {
-        UUID a = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
-        UUID b = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
-        UUID c = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
+        UUID a = UUIDGen.getTimeUUID();
+        UUID b = UUIDGen.getTimeUUID();
+        UUID c = UUIDGen.getTimeUUID();
 
         timeUUIDType.validate(ByteBuffer.wrap(UUIDGen.decompose(a)));
         timeUUIDType.validate(ByteBuffer.wrap(UUIDGen.decompose(b)));
@@ -64,9 +64,9 @@ public class TimeUUIDTypeTest
     @Test
     public void testBigger() throws UnknownHostException
     {
-        UUID a = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
-        UUID b = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
-        UUID c = UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
+        UUID a = UUIDGen.getTimeUUID();
+        UUID b = UUIDGen.getTimeUUID();
+        UUID c = UUIDGen.getTimeUUID();
 
         timeUUIDType.validate(ByteBuffer.wrap(UUIDGen.decompose(a)));
         timeUUIDType.validate(ByteBuffer.wrap(UUIDGen.decompose(b)));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/db/marshal/UUIDTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/marshal/UUIDTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/UUIDTypeTest.java
index 0f75d2a..3d6d5aa 100644
--- a/test/unit/org/apache/cassandra/db/marshal/UUIDTypeTest.java
+++ b/test/unit/org/apache/cassandra/db/marshal/UUIDTypeTest.java
@@ -23,8 +23,6 @@ package org.apache.cassandra.db.marshal;
 
 import static org.junit.Assert.assertEquals;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Random;
@@ -46,8 +44,8 @@ public class UUIDTypeTest
     public void testCompare()
     {
 
-        UUID t1 = newTimeBasedUUID();
-        UUID t2 = newTimeBasedUUID();
+        UUID t1 = UUIDGen.getTimeUUID();
+        UUID t2 = UUIDGen.getTimeUUID();
 
         testCompare(null, t2, -1);
         testCompare(t1, null, 1);
@@ -76,17 +74,6 @@ public class UUIDTypeTest
         }
     }
 
-    public UUID newTimeBasedUUID()
-    {
-        try
-        {
-            return UUIDGen.makeType1UUIDFromHost(InetAddress.getLocalHost());
-        } catch (UnknownHostException e)
-        {
-            throw new RuntimeException(e);
-        }
-    }
-
     public static int compareUnsigned(long n1, long n2)
     {
         if (n1 == n2)
@@ -181,7 +168,7 @@ public class UUIDTypeTest
     @Test
     public void testTimeEquality()
     {
-        UUID a = newTimeBasedUUID();
+        UUID a = UUIDGen.getTimeUUID();
         UUID b = new UUID(a.getMostSignificantBits(),
                 a.getLeastSignificantBits());
 
@@ -191,9 +178,9 @@ public class UUIDTypeTest
     @Test
     public void testTimeSmaller()
     {
-        UUID a = newTimeBasedUUID();
-        UUID b = newTimeBasedUUID();
-        UUID c = newTimeBasedUUID();
+        UUID a = UUIDGen.getTimeUUID();
+        UUID b = UUIDGen.getTimeUUID();
+        UUID c = UUIDGen.getTimeUUID();
 
         assert uuidType.compare(bytebuffer(a), bytebuffer(b)) < 0;
         assert uuidType.compare(bytebuffer(b), bytebuffer(c)) < 0;
@@ -203,9 +190,9 @@ public class UUIDTypeTest
     @Test
     public void testTimeBigger()
     {
-        UUID a = newTimeBasedUUID();
-        UUID b = newTimeBasedUUID();
-        UUID c = newTimeBasedUUID();
+        UUID a = UUIDGen.getTimeUUID();
+        UUID b = UUIDGen.getTimeUUID();
+        UUID c = UUIDGen.getTimeUUID();
 
         assert uuidType.compare(bytebuffer(c), bytebuffer(b)) > 0;
         assert uuidType.compare(bytebuffer(b), bytebuffer(a)) > 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/io/LazilyCompactedRowTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/io/LazilyCompactedRowTest.java b/test/unit/org/apache/cassandra/io/LazilyCompactedRowTest.java
index 0608366..1a289e8 100644
--- a/test/unit/org/apache/cassandra/io/LazilyCompactedRowTest.java
+++ b/test/unit/org/apache/cassandra/io/LazilyCompactedRowTest.java
@@ -304,7 +304,7 @@ public class LazilyCompactedRowTest extends SchemaLoader
 
         ByteBuffer key = ByteBufferUtil.bytes("k");
         RowMutation rm = new RowMutation("Keyspace4", key);
-        ByteBuffer scKey = ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress())));
+        ByteBuffer scKey = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
         rm.add(new QueryPath("Super5", scKey , ByteBufferUtil.bytes("c")), ByteBufferUtil.EMPTY_BYTE_BUFFER, 0);
         rm.apply();
         cfs.forceBlockingFlush();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/streaming/SerializationsTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/streaming/SerializationsTest.java b/test/unit/org/apache/cassandra/streaming/SerializationsTest.java
index 47990ab..be6f2dd 100644
--- a/test/unit/org/apache/cassandra/streaming/SerializationsTest.java
+++ b/test/unit/org/apache/cassandra/streaming/SerializationsTest.java
@@ -82,7 +82,7 @@ public class SerializationsTest extends AbstractSerializationsTester
 
     private void testStreamHeaderWrite() throws IOException
     {
-        UUID sessionId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getLocalAddress());
+        UUID sessionId = UUIDGen.getTimeUUID();
         StreamHeader sh0 = new StreamHeader("Keyspace1", sessionId, makePendingFile(true, 100, OperationType.BOOTSTRAP));
         StreamHeader sh1 = new StreamHeader("Keyspace1", sessionId, makePendingFile(false, 100, OperationType.BOOTSTRAP));
         Collection<PendingFile> files = new ArrayList<PendingFile>();
@@ -125,7 +125,7 @@ public class SerializationsTest extends AbstractSerializationsTester
 
     private void testStreamReplyWrite() throws IOException
     {
-        UUID sessionId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getLocalAddress());
+        UUID sessionId = UUIDGen.getTimeUUID();
         StreamReply rep = new StreamReply("this is a file", sessionId, StreamReply.Status.FILE_FINISHED);
         DataOutputStream out = getOutput("streaming.StreamReply.bin");
         StreamReply.serializer.serialize(rep, out, getVersion());
@@ -159,7 +159,7 @@ public class SerializationsTest extends AbstractSerializationsTester
 
     private void testStreamRequestMessageWrite() throws IOException
     {
-        UUID sessionId = UUIDGen.makeType1UUIDFromHost(FBUtilities.getLocalAddress());
+        UUID sessionId = UUIDGen.getTimeUUID();
         Collection<Range<Token>> ranges = new ArrayList<Range<Token>>();
         for (int i = 0; i < 5; i++)
             ranges.add(new Range<Token>(new BytesToken(ByteBufferUtil.bytes(Integer.toString(10*i))), new BytesToken(ByteBufferUtil.bytes(Integer.toString(10*i+5)))));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/test/unit/org/apache/cassandra/utils/UUIDTests.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/utils/UUIDTests.java b/test/unit/org/apache/cassandra/utils/UUIDTests.java
index 6cf96d0..970c753 100644
--- a/test/unit/org/apache/cassandra/utils/UUIDTests.java
+++ b/test/unit/org/apache/cassandra/utils/UUIDTests.java
@@ -37,15 +37,15 @@ public class UUIDTests
     public void verifyType1() throws UnknownHostException
     {
 
-        UUID uuid = UUIDGen.makeType1UUIDFromHost(InetAddress.getByName("127.0.0.1"));
+        UUID uuid = UUIDGen.getTimeUUID();
         assert uuid.version() == 1;
     }
 
     @Test
     public void verifyOrdering1() throws UnknownHostException
     {
-        UUID one = UUIDGen.makeType1UUIDFromHost(InetAddress.getByName("127.0.0.1"));
-        UUID two = UUIDGen.makeType1UUIDFromHost(InetAddress.getByName("127.0.0.2"));
+        UUID one = UUIDGen.getTimeUUID();
+        UUID two = UUIDGen.getTimeUUID();
         assert one.timestamp() < two.timestamp();
     }
 
@@ -53,7 +53,7 @@ public class UUIDTests
     @Test
     public void testDecomposeAndRaw() throws UnknownHostException
     {
-        UUID a = UUIDGen.makeType1UUIDFromHost(InetAddress.getByName("127.0.0.1"));
+        UUID a = UUIDGen.getTimeUUID();
         byte[] decomposed = UUIDGen.decompose(a);
         UUID b = UUIDGen.getUUID(ByteBuffer.wrap(decomposed));
         assert a.equals(b);
@@ -63,8 +63,8 @@ public class UUIDTests
     public void testTimeUUIDType() throws UnknownHostException
     {
         TimeUUIDType comp = TimeUUIDType.instance;
-        ByteBuffer first = ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.makeType1UUIDFromHost(InetAddress.getByName("127.0.0.1"))));
-        ByteBuffer second = ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.makeType1UUIDFromHost(InetAddress.getByName("127.0.0.1"))));
+        ByteBuffer first = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
+        ByteBuffer second = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
         assert comp.compare(first, second) < 0;
         assert comp.compare(second, first) > 0;
         ByteBuffer sameAsFirst = ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.getUUID(first)));
@@ -76,7 +76,7 @@ public class UUIDTests
     {
         InetAddress addr = InetAddress.getByName("127.0.0.1");
         long now = System.currentTimeMillis();
-        UUID uuid = UUIDGen.makeType1UUIDFromHost(addr);
+        UUID uuid = UUIDGen.getTimeUUID();
         long tstamp = UUIDGen.getAdjustedTimestamp(uuid);
 
         // I'll be damn is the uuid timestamp is more than 10ms after now

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/tools/stress/src/org/apache/cassandra/stress/operations/CqlInserter.java
----------------------------------------------------------------------
diff --git a/tools/stress/src/org/apache/cassandra/stress/operations/CqlInserter.java b/tools/stress/src/org/apache/cassandra/stress/operations/CqlInserter.java
index aedf2de..47e51a4 100644
--- a/tools/stress/src/org/apache/cassandra/stress/operations/CqlInserter.java
+++ b/tools/stress/src/org/apache/cassandra/stress/operations/CqlInserter.java
@@ -71,7 +71,7 @@ public class CqlInserter extends Operation
                     if (session.cqlVersion.startsWith("3"))
                         throw new UnsupportedOperationException("Cannot use UUIDs in column names with CQL3");
 
-                    query.append(wrapInQuotesIfRequired(UUIDGen.makeType1UUIDFromHost(Session.getLocalAddress()).toString()))
+                    query.append(wrapInQuotesIfRequired(UUIDGen.getTimeUUID().toString()))
                          .append(" = ?");
                 }
                 else

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7442fc02/tools/stress/src/org/apache/cassandra/stress/util/Operation.java
----------------------------------------------------------------------
diff --git a/tools/stress/src/org/apache/cassandra/stress/util/Operation.java b/tools/stress/src/org/apache/cassandra/stress/util/Operation.java
index 4737692..43e10b3 100644
--- a/tools/stress/src/org/apache/cassandra/stress/util/Operation.java
+++ b/tools/stress/src/org/apache/cassandra/stress/util/Operation.java
@@ -211,7 +211,7 @@ public abstract class Operation
     protected ByteBuffer columnName(int index, boolean timeUUIDComparator)
     {
         return timeUUIDComparator
-                ? TimeUUIDType.instance.decompose(UUIDGen.makeType1UUIDFromHost(Session.getLocalAddress()))
+                ? TimeUUIDType.instance.decompose(UUIDGen.getTimeUUID())
                 : ByteBufferUtil.bytes(String.format("C%d", index));
     }