Skip to content

Commit 2f03f0c

Browse files
authored
Remove random_label in favor of uuid. (#4709)
The random label work broke the python tests because it can generate the same URI under certain conditions. --- TYPE: NO_HISTORY DESC: Remove random_label in favor of uuid.
1 parent 17bcc85 commit 2f03f0c

File tree

12 files changed

+388
-10
lines changed

12 files changed

+388
-10
lines changed

tiledb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ set(TILEDB_CORE_SOURCES
236236
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/misc/tdb_time.cc
237237
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/misc/types.cc
238238
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/misc/utils.cc
239+
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/misc/uuid.cc
239240
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/misc/win_constants.cc
240241
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/ast/query_ast.cc
241242
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/deletes_and_updates/deletes_and_updates.cc

tiledb/sm/array/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ commence(object_library array)
3737
baseline
3838
fragment
3939
generic_tile_io
40+
uuid
4041
vfs
4142
)
4243
if(TILEDB_STATS)

tiledb/sm/array_schema/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ commence(object_library attribute)
3838
constants
3939
filter_pipeline
4040
range
41-
stringx)
41+
stringx
42+
uuid)
4243
conclude(object_library)
4344

4445
#
@@ -62,7 +63,7 @@ conclude(object_library)
6263
#
6364
commence(object_library enumeration)
6465
this_target_sources(enumeration.cc)
65-
this_target_object_libraries(buffer constants seedable_global_PRNG)
66+
this_target_object_libraries(buffer constants uuid)
6667
conclude(object_library)
6768

6869
#

tiledb/sm/array_schema/enumeration.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include <iostream>
3434
#include <sstream>
3535

36-
#include "tiledb/common/random/random_label.h"
36+
#include "tiledb/sm/misc/uuid.h"
3737

3838
#include "enumeration.h"
3939

@@ -71,8 +71,10 @@ Enumeration::Enumeration(
7171
}
7272

7373
if (path_name_.empty()) {
74-
path_name_ = "__" + tiledb::common::random_label() + "_" +
75-
std::to_string(constants::enumerations_version);
74+
std::string tmp_uuid;
75+
throw_if_not_ok(uuid::generate_uuid(&tmp_uuid, false));
76+
path_name_ =
77+
"__" + tmp_uuid + "_" + std::to_string(constants::enumerations_version);
7678
}
7779

7880
if (path_name.find("/") != std::string::npos) {

tiledb/sm/misc/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ commence(object_library time)
7171
this_target_sources(tdb_time.cc)
7272
conclude(object_library)
7373

74+
#
75+
# `uuid` object library
76+
#
77+
commence(object_library uuid)
78+
this_target_sources(uuid.cc)
79+
this_target_object_libraries(baseline)
80+
if(WIN32)
81+
this_target_link_libraries(rpcrt4)
82+
else()
83+
find_package(OpenSSL_EP REQUIRED)
84+
this_target_link_libraries(OpenSSL::Crypto)
85+
endif()
86+
conclude(object_library)
87+
88+
add_test_subdirectory()
89+
7490
#
7591
# `mgc_dict.*` tests are declared in this directory for the moment.
7692
#

tiledb/sm/misc/test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
include(unit_test)
2727

2828
commence(unit_test misc)
29-
this_target_object_libraries(math)
29+
this_target_object_libraries(math uuid)
3030
this_target_link_libraries(tiledb_test_support_lib)
3131
# change to `this_target_include_directories` when available
3232
target_include_directories(unit_misc PRIVATE "${CMAKE_SOURCE_DIR}")
@@ -36,5 +36,6 @@ commence(unit_test misc)
3636
unit_hilbert.cc
3737
unit_integral_type_casts.cc
3838
unit_math.cc
39+
unit_uuid.cc
3940
)
4041
conclude(unit_test)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @file compile_uuid_main.cc
3+
*
4+
* @section LICENSE
5+
*
6+
* The MIT License
7+
*
8+
* @copyright Copyright (c) 2021 TileDB, Inc.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*/
28+
29+
#include "../uuid.h"
30+
31+
int main() {
32+
(void)tiledb::sm::uuid::generate_uuid(nullptr, false);
33+
return 0;
34+
}

tiledb/sm/misc/test/unit_uuid.cc

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* @file unit_uuid.cc
3+
*
4+
* @section LICENSE
5+
*
6+
* The MIT License
7+
*
8+
* @copyright Copyright (c) 2018-2022 TileDB, Inc.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*
28+
* @section DESCRIPTION
29+
*
30+
* Tests the UUID utility functions.
31+
*/
32+
33+
#include <test/support/tdb_catch.h>
34+
#include <set>
35+
#include <thread>
36+
#include <vector>
37+
38+
#include "tiledb/sm/global_state/global_state.h"
39+
#include "tiledb/sm/misc/uuid.h"
40+
41+
using namespace tiledb::sm;
42+
43+
std::mutex catch2_macro_mutex;
44+
45+
// A thread-safe variant of the REQUIRE macro.
46+
#define REQUIRE_SAFE(a) \
47+
{ \
48+
std::lock_guard<std::mutex> lock(catch2_macro_mutex); \
49+
REQUIRE(a); \
50+
}
51+
52+
void cancel_all_tasks(StorageManager*) {
53+
}
54+
55+
TEST_CASE("UUID: Test generate", "[uuid]") {
56+
SECTION("- Serial") {
57+
std::string uuid0, uuid1, uuid2;
58+
REQUIRE(uuid::generate_uuid(&uuid0).ok());
59+
REQUIRE(uuid0.length() == 36);
60+
REQUIRE(uuid::generate_uuid(&uuid1).ok());
61+
REQUIRE(uuid1.length() == 36);
62+
REQUIRE(uuid0 != uuid1);
63+
64+
REQUIRE(uuid::generate_uuid(&uuid2, false).ok());
65+
REQUIRE(uuid2.length() == 32);
66+
}
67+
68+
SECTION("- Threaded") {
69+
const unsigned nthreads = 20;
70+
std::vector<std::string> uuids(nthreads);
71+
std::vector<std::thread> threads;
72+
for (unsigned i = 0; i < nthreads; i++) {
73+
threads.emplace_back([&uuids, i]() {
74+
std::string& uuid = uuids[i];
75+
REQUIRE_SAFE(uuid::generate_uuid(&uuid).ok());
76+
REQUIRE_SAFE(uuid.length() == 36);
77+
});
78+
}
79+
for (auto& t : threads) {
80+
t.join();
81+
}
82+
// Check uniqueness
83+
std::set<std::string> uuid_set;
84+
uuid_set.insert(uuids.begin(), uuids.end());
85+
REQUIRE(uuid_set.size() == uuids.size());
86+
}
87+
}

tiledb/sm/misc/uuid.cc

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/**
2+
* @file uuid.cc
3+
*
4+
* @section LICENSE
5+
*
6+
* The MIT License
7+
*
8+
* @copyright Copyright (c) 2018-2023 TileDB, Inc.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*
28+
* @section DESCRIPTION
29+
*
30+
* This file defines a platform-independent UUID generator.
31+
*/
32+
33+
#include <mutex>
34+
#include <vector>
35+
36+
#include "tiledb/sm/misc/uuid.h"
37+
38+
#ifdef _WIN32
39+
#include <Rpc.h>
40+
#else
41+
#include <openssl/err.h>
42+
#include <openssl/rand.h>
43+
#include <cstdio>
44+
#endif
45+
46+
using namespace tiledb::common;
47+
48+
namespace tiledb::sm::uuid {
49+
50+
/** Mutex to guard UUID generation. */
51+
static std::mutex uuid_mtx;
52+
53+
#ifdef _WIN32
54+
55+
/**
56+
* Generate a UUID using Win32 RPC API.
57+
*/
58+
Status generate_uuid_win32(std::string* uuid_str) {
59+
if (uuid_str == nullptr)
60+
return Status_UtilsError("Null UUID string argument");
61+
62+
UUID uuid;
63+
RPC_STATUS rc = UuidCreate(&uuid);
64+
if (rc != RPC_S_OK)
65+
return Status_UtilsError("Unable to generate Win32 UUID: creation error");
66+
67+
char* buf = nullptr;
68+
rc = UuidToStringA(&uuid, reinterpret_cast<RPC_CSTR*>(&buf));
69+
if (rc != RPC_S_OK)
70+
return Status_UtilsError(
71+
"Unable to generate Win32 UUID: string conversion error");
72+
73+
*uuid_str = std::string(buf);
74+
75+
rc = RpcStringFreeA(reinterpret_cast<RPC_CSTR*>(&buf));
76+
if (rc != RPC_S_OK)
77+
return Status_UtilsError("Unable to generate Win32 UUID: free error");
78+
79+
return Status::Ok();
80+
}
81+
82+
#else
83+
84+
/**
85+
* Generate a UUID using OpenSSL.
86+
*
87+
* Initially from: https://gist.github.com/kvelakur/9069c9896577c3040030
88+
* "Generating a Version 4 UUID using OpenSSL"
89+
*/
90+
Status generate_uuid_openssl(std::string* uuid_str) {
91+
if (uuid_str == nullptr)
92+
return Status_UtilsError("Null UUID string argument");
93+
94+
union {
95+
struct {
96+
uint32_t time_low;
97+
uint16_t time_mid;
98+
uint16_t time_hi_and_version;
99+
uint8_t clk_seq_hi_res;
100+
uint8_t clk_seq_low;
101+
uint8_t node[6];
102+
};
103+
uint8_t __rnd[16];
104+
} uuid;
105+
106+
int rc = RAND_bytes(uuid.__rnd, sizeof(uuid));
107+
if (rc < 1) {
108+
char err_msg[256];
109+
ERR_error_string_n(ERR_get_error(), err_msg, sizeof(err_msg));
110+
return Status_UtilsError(
111+
"Cannot generate random bytes with OpenSSL: " + std::string(err_msg));
112+
}
113+
114+
// Refer Section 4.2 of RFC-4122
115+
// https://tools.ietf.org/html/rfc4122#section-4.2
116+
uuid.clk_seq_hi_res = (uint8_t)((uuid.clk_seq_hi_res & 0x3F) | 0x80);
117+
uuid.time_hi_and_version =
118+
(uint16_t)((uuid.time_hi_and_version & 0x0FFF) | 0x4000);
119+
120+
// Format the UUID as a string.
121+
char buf[128];
122+
rc = snprintf(
123+
buf,
124+
sizeof(buf),
125+
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
126+
uuid.time_low,
127+
uuid.time_mid,
128+
uuid.time_hi_and_version,
129+
uuid.clk_seq_hi_res,
130+
uuid.clk_seq_low,
131+
uuid.node[0],
132+
uuid.node[1],
133+
uuid.node[2],
134+
uuid.node[3],
135+
uuid.node[4],
136+
uuid.node[5]);
137+
138+
if (rc < 0)
139+
return Status_UtilsError("Error formatting UUID string");
140+
141+
*uuid_str = std::string(buf);
142+
143+
return Status::Ok();
144+
}
145+
146+
#endif
147+
148+
Status generate_uuid(std::string* uuid, bool hyphenate) {
149+
if (uuid == nullptr)
150+
return Status_UtilsError("Null UUID string argument");
151+
152+
std::string uuid_str;
153+
{
154+
// OpenSSL is not threadsafe, so grab a lock here. We are locking in the
155+
// Windows case as well just to be careful.
156+
std::unique_lock<std::mutex> lck(uuid_mtx);
157+
#ifdef _WIN32
158+
RETURN_NOT_OK(generate_uuid_win32(&uuid_str));
159+
#else
160+
RETURN_NOT_OK(generate_uuid_openssl(&uuid_str));
161+
#endif
162+
}
163+
164+
uuid->clear();
165+
for (unsigned i = 0; i < uuid_str.length(); i++) {
166+
if (uuid_str[i] == '-' && !hyphenate)
167+
continue;
168+
uuid->push_back(uuid_str[i]);
169+
}
170+
171+
return Status::Ok();
172+
}
173+
174+
} // namespace tiledb::sm::uuid

0 commit comments

Comments
 (0)