Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions core/base/inc/TUUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,21 @@ class TUUID {
void GetRandomInfo(UChar_t seed[16]);
void SetFromString(const char *uuid_str);

struct TIndeterminedMarker {};
/// Create a UUID whose content is indetermined. Used by the UUIDv4 factory method.
explicit TUUID(TIndeterminedMarker) {}

public:
TUUID();
TUUID(const char *uuid_str);
virtual ~TUUID();

// Create a UUID version 4 (variant 1) UUID according to RFC 4122.
// The UUIDv4 also has 16 octets but all but the version and variant information is random.
// This leaves 122 random bits, which are filled by the system's cryptographic random number generator.
// For all intents and purposes, the resulting UUIDs are actually globally unique.
static TUUID UUIDv4();

const char *AsString() const;
Int_t Compare(const TUUID &u) const;
UShort_t Hash() const;
Expand Down Expand Up @@ -100,5 +110,9 @@ inline Bool_t operator==(const TUUID &u1, const TUUID &u2)
inline Bool_t operator!=(const TUUID &u1, const TUUID &u2)
{ return !(u1 == u2); }

inline Bool_t operator<(const TUUID &u1, const TUUID &u2)
{
return u1.Compare(u2) == -1;
}

#endif
8 changes: 8 additions & 0 deletions core/base/src/TDirectory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ Describe directory structure in memory.

TDirectory::TDirectory() : TNamed()
{
// In the context of rootcling, we don't have gSystem
if (gSystem)
Comment on lines +55 to +56
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// In the context of rootcling, we don't have gSystem
if (gSystem)
// Fallback to the default constructed TUUID if we
// get here before gSystem is initialized.
if (gSystem)

fUUID = TUUID::UUIDv4();

// MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
std::atomic_flag_clear( &fSpinLock );
}
Expand All @@ -72,6 +76,10 @@ TDirectory::TDirectory() : TNamed()
TDirectory::TDirectory(const char *name, const char *title, Option_t * /*classname*/, TDirectory* initMotherDir)
: TNamed(name, title)
{
// In the context of rootcling, we don't have gSystem
if (gSystem)
fUUID = TUUID::UUIDv4();

// MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
std::atomic_flag_clear( &fSpinLock );

Expand Down
26 changes: 25 additions & 1 deletion core/base/src/TUUID.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ system clock catches up.
#include "Bytes.h"
#include "TVirtualMutex.h"
#include "ThreadLocalStorage.h"
#include <cassert>
#include <cstring>
#include <cstdlib>
#ifdef R__WIN32
Expand All @@ -145,6 +146,29 @@ system clock catches up.
#endif
#include <chrono>

////////////////////////////////////////////////////////////////////////////////
/// Create a v4 UUID.

TUUID TUUID::UUIDv4()
{
TUUID uuid{TIndeterminedMarker()};

// Ensure we can treat the memory starting at uuid.fTimeLow as an array of 16 octets
assert(&uuid.fNode[5] - reinterpret_cast<unsigned char *>(&uuid.fTimeLow) + 1 == 16);

R__ASSERT(gSystem);
const auto rv = gSystem->GetCryptoRandom(&uuid.fTimeLow, 16);
R__ASSERT(rv == 16);
// Fix up variant
uuid.fClockSeqHiAndReserved = (uuid.fClockSeqHiAndReserved & 0x3F) | (2 << 6);
// Fix up version
uuid.fTimeHiAndVersion = (uuid.fTimeHiAndVersion & 0x0FFF) | (4 << 12);

// TODO(jblomer): we do what the default constructor does but is this still used? Can it be deprecated?
uuid.fUUIDIndex = 1 << 30;

return uuid;
}

////////////////////////////////////////////////////////////////////////////////
/// Create a UUID.
Expand Down Expand Up @@ -569,7 +593,7 @@ void TUUID::Print() const

const char *TUUID::AsString() const
{
static char uuid[40];
TTHREAD_TLS(char) uuid[40];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we use thread_local?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what it resolves to. I can use thread_local but this file uses TTHREAD_TLS in other places so I used this for consistency.


snprintf(uuid,40, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
fTimeLow, fTimeMid, fTimeHiAndVersion, fClockSeqHiAndReserved,
Expand Down
2 changes: 2 additions & 0 deletions core/base/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,5 @@ endif()

configure_file(Foo.C Foo.C COPYONLY)
ROOT_ADD_GTEST(IncludePathTest IncludePathTest.cxx LIBRARIES Core)

ROOT_ADD_GTEST(UUIDTest UUIDTest.cxx LIBRARIES Core)
22 changes: 22 additions & 0 deletions core/base/test/UUIDTest.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "gtest/gtest.h"

#include "TUUID.h"

#include <set>
#include <string>

TEST(TUUID, UUIDv4)
{
std::set<TUUID> uuids;
for (int i = 0; i < 10000; ++i) {
uuids.insert(TUUID::UUIDv4());
}
EXPECT_EQ(10000u, uuids.size());

TUUID u;
EXPECT_EQ('1', u.AsString()[14]);
u = TUUID::UUIDv4();
std::string str = u.AsString();
EXPECT_EQ('4', str[14]);
EXPECT_TRUE(str[19] == '8' || str[19] == '9' || str[19] == 'a' || str[19] == 'b');
}
5 changes: 5 additions & 0 deletions io/io/test/TFileTests.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,8 @@ TEST(TFile, PersistTObjectStdArray)
gSystem->Unlink(filename);
}

TEST(TFile, UUID)
{
TMemFile f("uuidtest.root", "RECREATE");
EXPECT_EQ('4', f.GetUUID().AsString()[14]);
}
2 changes: 1 addition & 1 deletion tree/ntuple/src/RMiniFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ struct RTFUUID {

RTFUUID()
{
TUUID uuid;
TUUID uuid{TUUID::UUIDv4()};
char *buffer = reinterpret_cast<char *>(this);
uuid.FillBuffer(buffer);
assert(reinterpret_cast<RTFUUID *>(buffer) <= (this + 1));
Expand Down
1 change: 1 addition & 0 deletions tree/ntuple/test/ntuple_minifile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ TEST(MiniFile, UUID)
TUUID uuid;
uuid.SetUUID("00000000-0000-0000-0000-000000000000");
EXPECT_NE(uuid, f->GetUUID());
EXPECT_EQ('4', f->GetUUID().AsString()[14]);
}

TEST(MiniFile, FreeSlots)
Expand Down
Loading