UUID Generation Code

Source: Internet
Author: User
UUID Reference Implementation
/*
** Copyright (c) 1990-1993,199 6 Open Software Foundation, Inc.
** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca .&
** Digital Equipment Corporation, Maynard, Mass.
** To anyone who acknowledges that this file is provided "as is"
** Without any express or implied warranty: permission to use, copy,
** Modify, and distribute this file for any purpose is hereby
** Granted without tables, provided that the above copyright notices and
** This notice appears in all source code copies, and that none
** The names of Open Software Foundation, Inc., Hewlett-Packard
** Company, or Digital Equipment Corporation be used in advertising
** Or publicity pertaining to distribution of the software
** Specific, written prior permission. Neither Open Software
** Foundation, Inc., Hewlett-Packard Company, nor Digital Equipment
** Corporation makes any representations about the suitability
** This software for any purpose.
*/
# Include
# Include

Typedef unsigned long unsigned32;
Typedef unsigned short unsigned16;
Typedef unsigned char unsigned8;
Typedef unsigned char byte;

# Define CLOCK_SEQ_LAST 0x3FFF
# Define RAND_MASK CLOCK_SEQ_LAST

Typedef struct _ uuid_t {
Unsigned32 time_low;
Unsigned16 time_mid;
Unsigned16 time_hi_and_version;
Unsigned8 clock_seq_hi_and_reserved;
Unsigned8 clock_seq_low;
Byte node [6];
} Uuid_t;

Typedef struct _ unsigned64_t {
Unsigned32 lo;
Unsigned32 hi;
} Unsigned64_t;

/*
** Add two unsigned 64-bit long integers.
*/
# Define ADD_64b_2_64b (A, B, sum )/
{/
If (! (A)-> lo & 0x80000000UL) ^ (B)-> lo & 0x80000000UL ))){/
If (A)-> lo & 0x80000000UL )){/
(Sum)-> lo = (A)-> lo + (B)-> lo ;/
(Sum)-> hi = (A)-> hi + (B)-> hi + 1 ;/
}/
Else {/
(Sum)-> lo = (A)-> lo + (B)-> lo ;/
(Sum)-> hi = (A)-> hi + (B)-> hi ;/
}/
}/
Else {/
(Sum)-> lo = (A)-> lo + (B)-> lo ;/
(Sum)-> hi = (A)-> hi + (B)-> hi ;/
If (! (Sum)-> lo & 0x80000000UL) (sum)-> hi ++ ;/
}/
}

/*
** Add a 16-bit unsigned integer to a 64-bit unsigned integer.
*/
# Define ADD_16b_2_64b (A, B, sum )/
{/
(Sum)-> hi = (B)-> hi ;/
If (B)-> lo & 0x80000000UL ){/
(Sum)-> lo = (* A) + (B)-> lo ;/
If (! (Sum)-> lo & 0x80000000UL) (sum)-> hi ++ ;/
}/
Else/
(Sum)-> lo = (* A) + (B)-> lo ;/
}

/*
** Global variables.
*/
Static unsigned64_t time_last;
Static unsigned16 clock_seq;

Static void
Mult32 (unsigned32 u, unsigned32 v, unsigned64_t * result)
{
/* Following the notation in Knuth, Vol. 2 .*/
Unsigned32 uuid1, uuid2, v1, v2, temp;

Uuid1 = u> 16;
Uuid2 = u & 0 xFFFF;
V1 = v> 16;
V2 = v & 0 xFFFF;
Temp = uuid2 * v2;
Result-> lo = temp & 0 xFFFF;
Temp = uuid1 * v2 + (temp> 16 );
Result-> hi = temp> 16;
Temp = uuid2 * v1 + (temp & 0 xFFFF );
Result-> lo + = (temp & 0 xFFFF) hi + = uuid1 * v1 + (temp> 16 );
}

Static void
Get_system_time (unsigned64_t * uuid_time)
{
Struct timeval tp;
Unsigned64_t utc, usecs, OS _basetime_diff;

Gettimeofday (& tp, (struct timezone *) 0 );
Mult32 (long) tp. TV _sec, 10000000, & utc );
Mult32 (long) tp. TV _usec, 10, & usecs );
ADD_64b_2_64b (& usecs, & utc, & utc );

/* Offset between UUID formatted times and Unix formatted times.
* Uuid utc base time is October 15,158 2.
* Unix base time is January 1, 1970 .*/
OS _basetime_diff.lo = 0x13814000;
OS _basetime_diff.hi = 0x01B21DD2;
ADD_64b_2_64b (& utc, & OS _basetime_diff, uuid_time );
}

/*
** See "The Multiple Prime Random Number Generator" by Alexander
** Hass pp. 368-381, ACM Transactions on Mathematical Software,
** 12/87.
*/
Static unsigned32 rand_m;
Static unsigned32 rand_ia;
Static unsigned32 rand_ib;
Static unsigned32 rand_irand;

Static void
True_random_init (void)
{
Unsigned64_t;
Unsigned16 seed;

/* Generating our 'seed' value Start with the current time,,
* Since the resolution of clocks is system hardware dependent and
* Most likely coarser than our resolution (10 usec) we 'mixup'
* Bits by xor 'ing all the bits together. This will have the effect
* Of involving all of the bits in the determination of the seed
* Value while remaining system independent. Then for good measure
* To ensure a unique seed when there are multiple processes
* Creating uuuids on a system, we add in the PID.
*/
Rand_m = 971;
Rand_ia = 11113;
Rand_ib = 104322;
Rand_irand = 4181;
Get_system_time (& t );
Seed = t. lo & 0 xFFFF;
Seed ^ = (t. lo> 16) & 0 xFFFF;
Seed ^ = t. hi & 0 xFFFF;
Seed ^ = (t. hi> 16) & 0 xFFFF;
Rand_irand + = seed + getpid ();
}

Static unsigned16
True_random (void)
{
If (rand_m + = 7) & gt; = 9973)
Rand_m-= 9871;
If (rand_ia + = 1907)> = 99991)
Rand_ia-= 89989;
If (rand_ib + = 73939)> = 224729)
Rand_ib-= 96233;
Rand_irand = (rand_irand * rand_m) + rand_ia + rand_ib;
Return (rand_irand> 16) ^ (rand_irand & RAND_MASK );
}

/*
** Startup initialization routine for the UUID module.
*/
Void
Uuid_init (void)
{
True_random_init ();
Get_system_time (& time_last );
# Ifdef NONVOLATILE_CLOCK
Clock_seq = read_clock ();
# Else
Clock_seq = true_random ();
# Endif
}

Static int
Time_cmp (unsigned64_t * time1, unsigned64_t * time2)
{
If (time1-> hi) return-1;
If (time1-> hi> time2-> hi) return 1;
If (time1-> lo) return-1;
If (time1-> lo> time2-> lo) return 1;
Return 0;
}

Static void new_clock_seq (void)
{
Clock_seq = (clock_seq + 1) % (CLOCK_SEQ_LAST + 1 );
If (clock_seq = 0) clock_seq = 1;
# Ifdef NONVOLATILE_CLOCK
Write_clock (clock_seq );
# Endif
}

Void uuid_create (uuid_t * uuid)
{
Static unsigned64_t time_now;
Static unsigned16 time_adjust;
Byte eaddr [6];
Int got_no_time = 0;

Get_ieee_node_identifier (& eaddr);/* to be provided */

Do {
Get_system_time (& time_now );
Switch (time_cmp (& time_now, & time_last )){
Case-1:
/* Time went backwards .*/
New_clock_seq ();
Time_adjust = 0;
Break;
Case 1:
Time_adjust = 0;
Break;
Default:
If (time_adjust = 0x7FFF)
/* We're going too fast for our clock; spin .*/
Got_no_time = 1;
Else
Time_adjust ++;
Break;
}
} While (got_no_time );

Time_last.lo = time_now.lo;
Time_last.hi = time_no1_hi;

If (time_adjust! = 0 ){
ADD_16b_2_64b (& time_adjust, & time_now, & time_now );
}

/* Construct a uuid with the information we 've ve gathered
* Plus a few constants .*/
Uuid-> time_low = time_now.lo;
Uuid-> time_mid = time_no1_hi & 0x0000FFFF;
Uuid-> time_hi_and_version = (time_no1_hi & 0x0FFF0000)> 16;
Uuid-> time_hi_and_version | = (1 clock_seq_low = clock_seq & 0xFF;
Uuid-> clock_seq_hi_and_reserved = (clock_seq & 0x3F00)> 8;
Uuid-> clock_seq_hi_and_reserved | = 0x80;
Memcpy (uuid-> node, & eaddr, sizeof uuid-> node );
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.