2504
DCE 1.1: Remote Procedure Call,
2505
Open Group Technical Standard Document Number C706, October 1997,
2506
(supersedes C309 DCE: Remote Procedure Call 8/1994,
2507
which was basis for ISO/IEC 11578:1996 specification)
2510
static struct rand_struct uuid_rand;
2511
static uint32_t nanoseq;
2512
static uint64_t uuid_time=0;
2513
static char clock_seq_and_node_str[]="-0000-000000000000";
2516
number of 100-nanosecond intervals between
2517
1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00.
2519
#define UUID_TIME_OFFSET ((uint64_t) 141427 * 24 * 60 * 60 * 1000 * 10 )
2521
#define UUID_VERSION 0x1000
2522
#define UUID_VARIANT 0x8000
2524
static void tohex(char *to, uint32_t from, uint32_t len)
2529
*--to= _dig_vec_lower[from & 15];
2534
static void set_clock_seq_str()
2536
uint16_t clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT;
2537
tohex(clock_seq_and_node_str+1, clock_seq, 4);
2541
2505
String *Item_func_uuid::val_str(String *str)
2545
Session *session= current_session;
2547
pthread_mutex_lock(&LOCK_uuid_generator);
2548
if (! uuid_time) /* first UUID() call. initializing data */
2550
ulong tmp= sql_rnd();
2551
unsigned char mac[6];
2553
const Query_id& query_id= Query_id::get_query_id();
2554
if (my_gethwaddr(mac))
2556
/* purecov: begin inspected */
2558
generating random "hardware addr"
2559
and because specs explicitly specify that it should NOT correlate
2560
with a clock_seq value (initialized random below), we use a separate
2563
randominit(&uuid_rand, tmp + (ulong) session, tmp + query_id.value());
2564
for (i=0; i < (int)sizeof(mac); i++)
2565
mac[i]=(unsigned char)(my_rnd(&uuid_rand)*255);
2568
s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
2569
for (i=sizeof(mac)-1 ; i>=0 ; i--)
2571
*--s=_dig_vec_lower[mac[i] & 15];
2572
*--s=_dig_vec_lower[mac[i] >> 4];
2574
randominit(&uuid_rand, tmp + (ulong) server_start_time,
2575
tmp + (ulong) session->status_var.bytes_sent);
2576
set_clock_seq_str();
2579
uint64_t tv=my_getsystime() + UUID_TIME_OFFSET + nanoseq;
2580
if (unlikely(tv < uuid_time))
2581
set_clock_seq_str();
2582
else if (unlikely(tv == uuid_time))
2584
/* special protection from low-res system clocks */
2595
assert(tv > uuid_time);
2598
pthread_mutex_unlock(&LOCK_uuid_generator);
2600
uint32_t time_low= (uint32_t) (tv & 0xFFFFFFFF);
2601
uint16_t time_mid= (uint16_t) ((tv >> 32) & 0xFFFF);
2602
uint16_t time_hi_and_version= (uint16_t) ((tv >> 48) | UUID_VERSION);
2604
str->realloc(UUID_LENGTH+1);
2605
str->length(UUID_LENGTH);
2510
/* 36 characters for uuid string +1 for NULL */
2606
2513
str->set_charset(system_charset_info);
2607
s=(char *) str->ptr();
2609
tohex(s, time_low, 8);
2610
tohex(s+9, time_mid, 4);
2611
tohex(s+14, time_hi_and_version, 4);
2612
my_stpcpy(s+18, clock_seq_and_node_str);
2514
uuid_string= (char *) str->ptr();
2515
uuid_generate_time(uu);
2516
uuid_unparse(uu, uuid_string);