From 5300caadf686eca66dc96228d100de9e76d14728 Mon Sep 17 00:00:00 2001 From: Tomasz Grabiec Date: Fri, 3 Apr 2015 17:49:02 +0200 Subject: [PATCH] utils: Fix UUID::get_time_UUID() creating conflicting UUIDs in SMP UUID_gen::create_time_safe() does not synchronize across cores. The comment says that it assumes it runs on a single core. This is no longer true, we can run urchin on many cores. This easily leads to UUID conflicts with more than one core. Fix by adding a per-core unique number to the node part of the UUID. --- utils/UUID_gen.cc | 12 +++++++++--- utils/UUID_gen.hh | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/utils/UUID_gen.cc b/utils/UUID_gen.cc index 00c92b07b2..c9fa9af212 100644 --- a/utils/UUID_gen.cc +++ b/utils/UUID_gen.cc @@ -22,6 +22,7 @@ #include "UUID_gen.hh" #include +#include namespace utils { @@ -76,9 +77,14 @@ static int64_t make_node() static int64_t make_node() { - // FIXME: don't leave this constant zero! See the above commented-out code + // FIXME: Mix-in node's address. See the above commented-out code // which is what Cassandra's UUIDGen.java did. We can also get the MAC address. - return 0; + + // We should take current core number under consideration + // because create_time_safe() doesn't synchronize across cores and + // it's easy to get duplicates. + static std::atomic core_counter; + return core_counter.fetch_add(1); } @@ -98,7 +104,7 @@ static int64_t make_clock_seq_and_node() return lsb; } -const int64_t UUID_gen::clock_seq_and_node = make_clock_seq_and_node(); +const thread_local int64_t UUID_gen::clock_seq_and_node = make_clock_seq_and_node(); thread_local const std::unique_ptr UUID_gen::instance (new UUID_gen()); diff --git a/utils/UUID_gen.hh b/utils/UUID_gen.hh index d8506e80a0..141247f232 100644 --- a/utils/UUID_gen.hh +++ b/utils/UUID_gen.hh @@ -39,7 +39,7 @@ class UUID_gen private: // A grand day! millis at 00:00:00.000 15 Oct 1582. static constexpr int64_t START_EPOCH = -12219292800000L; - static const int64_t clock_seq_and_node; + static thread_local const int64_t clock_seq_and_node; /* * The min and max possible lsb for a UUID.