summaryrefslogtreecommitdiffstats
path: root/server/src/trace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/trace.cpp')
-rw-r--r--server/src/trace.cpp77
1 files changed, 51 insertions, 26 deletions
diff --git a/server/src/trace.cpp b/server/src/trace.cpp
index e7c00d0..f2935a9 100644
--- a/server/src/trace.cpp
+++ b/server/src/trace.cpp
@@ -10,6 +10,26 @@ import :trace;
10 10
11namespace routemon::trace { 11namespace routemon::trace {
12 12
13class psrng
14{
15 mutable std::default_random_engine e_ = {};
16 mutable std::uniform_int_distribution<std::uint64_t> distr_ = {};
17 mutable std::mutex mut_ = {};
18
19public:
20 auto next() const -> std::uint64_t
21 {
22 auto lock = std::lock_guard{mut_};
23 return distr_(e_);
24 }
25
26 static auto instance() -> psrng const&
27 {
28 static auto const inst = psrng{};
29 return inst;
30 }
31};
32
13uuid7::uuid7() 33uuid7::uuid7()
14{ 34{
15 namespace chrono = std::chrono; 35 namespace chrono = std::chrono;
@@ -23,46 +43,51 @@ uuid7::uuid7()
23 if (std::countl_zero(unix_time_ms) < 16) 43 if (std::countl_zero(unix_time_ms) < 16)
24 throw std::runtime_error{"system time too great"}; 44 throw std::runtime_error{"system time too great"};
25 45
26 auto rand = std::array<unsigned char, 10>{}; 46 auto const& rng = psrng::instance();
27 int s = RAND_bytes(rand.data(), static_cast<int>(rand.size())); 47 auto const rand1 = rng.next();
28 if (s != 1) 48 auto const rand2 = rng.next();
29 {
30 unsigned long e = ERR_get_error();
31 throw std::runtime_error{std::format(
32 "failed to generate UUID(v7): {} ({}, code {})",
33 ERR_reason_error_string(e), ERR_lib_error_string(e), e)};
34 }
35 49
36 auto version = std::uint64_t{0b0111}; 50 auto version = std::uint64_t{0b0111};
37 auto variant = std::uint64_t{0b10}; 51 auto variant = std::uint64_t{0b10};
38 52
39 hi_ |= unix_time_ms << 16; 53 hi_ = unix_time_ms << 16;
40 hi_ |= version << 12; 54 hi_ |= version << 12;
41 hi_ |= std::uint64_t{rand[0]} << 4; 55 hi_ |= rand1 & 0x0000'0000'0000'0fff;
42 hi_ |= std::uint64_t{rand[1]}; 56 lo_ = variant << 62;
43 lo_ |= variant << 62; 57 lo_ |= rand2 >> 2;
44 lo_ |= std::uint64_t{rand[2]} << 54;
45 lo_ |= std::uint64_t{rand[3]} << 48;
46 lo_ |= std::uint64_t{rand[4]} << 40;
47 lo_ |= std::uint64_t{rand[5]} << 32;
48 lo_ |= std::uint64_t{rand[6]} << 24;
49 lo_ |= std::uint64_t{rand[7]} << 16;
50 lo_ |= std::uint64_t{rand[8]} << 8;
51 lo_ |= std::uint64_t{rand[9]};
52} 58}
53 59
54auto uuid7::format(std::array<char, 37>& target) -> void 60auto uuid7::format(std::span<char, 37> target) -> void
55{ 61{
62 auto hexnibs =
63 []<std::size_t n>(std::uint64_t v, std::span<char, n> s) -> void
64 {
65 for (auto i = 0uz; i < n; i++)
66 {
67 static char const hextab[16] = {
68 '0', '1', '2', '3', '4', '5', '6', '7',
69 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
70 };
71 s[i] = hextab[(v >> 4 * (n - 1 - i)) & 0xf];
72 }
73 };
74
56 auto p____hi_hi = (hi_ & 0xffff'ffff'0000'0000) >> 32; 75 auto p____hi_hi = (hi_ & 0xffff'ffff'0000'0000) >> 32;
57 auto p_hi_lo_hi = (hi_ & 0x0000'0000'ffff'0000) >> 16; 76 auto p_hi_lo_hi = (hi_ & 0x0000'0000'ffff'0000) >> 16;
58 auto p_lo_lo_hi = (hi_ & 0x0000'0000'0000'ffff) >> 0; 77 auto p_lo_lo_hi = (hi_ & 0x0000'0000'0000'ffff) >> 0;
59 auto p____hi_lo = (lo_ & 0xffff'0000'0000'0000) >> 48; 78 auto p____hi_lo = (lo_ & 0xffff'0000'0000'0000) >> 48;
60 auto p____lo_lo = (lo_ & 0x0000'ffff'ffff'ffff) >> 0; 79 auto p____lo_lo = (lo_ & 0x0000'ffff'ffff'ffff) >> 0;
61 80
62 std::format_to( 81 hexnibs(p____hi_hi, target.subspan<0, 8>());
63 target.begin(), "{:0>8x}-{:0>4x}-{:0>4x}-{:0>4x}-{:0>12x}", p____hi_hi, 82 target[8] = '-';
64 p_hi_lo_hi, p_lo_lo_hi, p____hi_lo, p____lo_lo); 83 hexnibs(p_hi_lo_hi, target.subspan<9, 4>());
65 target.back() = '\0'; 84 target[13] = '-';
85 hexnibs(p_lo_lo_hi, target.subspan<14, 4>());
86 target[18] = '-';
87 hexnibs(p____hi_lo, target.subspan<19, 4>());
88 target[23] = '-';
89 hexnibs(p____lo_lo, target.subspan<24, 12>());
90 target[36] = '\0';
66} 91}
67 92
68id::id() { uuid7{}.format(chars_); } 93id::id() { uuid7{}.format(chars_); }