Test
|
UUIDs (aka GUIDs - Globally Unique Identifiers) are 128 bit long and are unique in time and space, either guaranteed or with a statistically insignificant likelihood of collisions (in the order of 2^-120). The IETF defines four versions of UUIDs that are either based on the MAC address and a timestamp, a hashed name, or randomly generated. To simplify Notifier message routing, we also add a custom type.
UUIDs with all bits 0 are called NULL UUIDs. Default constructed Uuid instances are NULL and the is_null
method can be used to check whether a UUID is NULL.
IETF Format
The IETF UUIDs comprise of four components. We store them as a 16 byte array in the layout shown below. Note that in the case of the random or name-based UUIDs, the timestamp, sequence, and node address are either random or generated from a hash. Note: In addition to Notifier based UUIDs (see below), we allow to associate custom flags with a randomly generated UUID (create_random
).
7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ 0 | |
Field Size[bits] Octet Note ----------------------------------------------------------------------- time_low 32 0-3 The low field of the timestamp in little-endian.
time_mid 16 4-5 The middle field of the timestamp in little-endian.
time_high 16 6-7 The high field of the timestamp multiplexed with the version number in little-endian representation.
clock_seq_high_and_var 8 8 The high field of the clock sequence iant multiplexed with the variant
clock_seq_low 8 9 The low field of the clock sequence
node 48 10-15 The spatially unique node identifier (MAC address).
IMPORTANT: RFC4122 implies that time_low, time_mid, and time_high are big-endian (network byte order). However, Microsoft seems to assume they are little-endian when converting GUIDs to byte representations. Specifically, System.Guid.ToByteArray()
clearly returns the fields in a little-endian format. Also, the Mono project explicitly emulates this behavior by performing endian conversions on big-endian platforms to ensure compatibility. Thus, to ensure compatibility with Windows (and to avoid confusion in the debugger and when interoperating with .NET, we stipulate that in the binary representation of the UUID, the timestamp is little-endian and the remaining fields are big-endian!
As the variant is always bit7=1 and bit6=0 (other than for legacy and some MSFT specific stuff, we assume the following simplified format:
7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ 0 | |
Field Size[bits] Octet Note ----------------------------------------------------------------------- timestamp 60 0-7 The timestamp (little-endian)
version 4 7 UUID version in bit 4 to 7 of octet 7
sequence 14 8-9 The clock sequence number as 14 bit big-endian integer
node 48 10-15 The spatially unique node identifier.
Custom Data Field
This UUID class allows associating 8 bits of custom flags/data with a randomly generated or Notifier based UUIDs (note: custom data is not supported with sequential UUIDs). This can be very convenient to allow applications to type UUIDs it generates, but they have to beware that the custom flags cannot be modified once the UUID has been created.
As UUIDs are not strongly typed, applications have to beware that the UUID may not have been generated by it. It thus must be able to validate the UUID against a separate store before interpreting the custom flags (i.e. it should be sure that it actually generated the UUID).
IMPORTANT: Never make security relevant decisions based on the value of the custom flags unless the UUID has been validated on the application boundaries.
Random UUID Format
7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ 0 | |
Field Size[bits] Octet Note ----------------------------------------------------------------------- custom_low 4 6 Low 4 bits of the 8-bit custom field in bit 4 to 7 of octet 6
custom_high 4 7 High 4 bits of the 8-bit custom field in bit 0 to 3 of octet 7
Note: The custom field is random unless explicitly specified by application when creating the UUID (create_random).
Name-based UUID Format
UUID is unique within a "namespace" for a particular sequence of bytes. This is achieved by hashing he namespace and data with MD-5. See RFC#4122 for details.
To avoid i3core being dependent on OpenSSL for crypto primitives, UUIDs of this type are created with i3crypto::create_name_based_uuid.
7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ 0 | |
Sequential UUID Format
7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ 0 | |
Field Size[bits] Octet Note ----------------------------------------------------------------------- timestamp 56 0-6 The timestamp (big-endian).
version 4 7 The UUID version (eVersion_Sequential) in bits 4-7.
zeroVal 4 7 A '0000' constant value in bits 0-3.
variant 2 8 A '10' constant value in bits 7 and 6.
dbms type 2 8 A '00' constant value in bits 5 and 4 by default for binary/oracle. i3db::create_sequential_with_db_collation may change it to 01 for sql server
random1 12 8-9 A random number that only generated once (the first timecreate_sequential()
is called).
random2 & 32 10-13 A random number that is usually counterHi only generated once; however, it will be incremented (as a big-endian integer) if counterLo ever overflows.
counterLo 16 14-15 The primary counter (big-endian).
Legacy Interaction Id UUID Format
7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ 0 | |
Field Size[bits] Octet Note ----------------------------------------------------------------------- random 74 0-9 74 random bits. All-zeroes if unresolved ID.
flags 8 10 Custom flags for use by issuer of legacy UUID. Zero by default to have leading zeroes in interaction ID.
digit9 4 11 The binary representation of the most significant decimal digit of the ten digit interaction ID.
digit8 4 11 The binary representation of the second most significant decimal digit of the ten digit interaction ID.
...
digit0 4 15 The binary representation of the least significant decimal digit of the ten digit interaction ID.
Note: When converted to a string representation using the Uuid::as_string() method, this format will result in the 12 character segment at the end of the UUID representing the decimal interaction ID for easy readability in logs. A decimal interaction ID of 1234567890 will thus have a string representation of:
xxxxxxxx-xxxx-cxxx-xxxx-001234567890
By default, there will be two leading zero digits before the digits of the interaction ID. The issuer of the UUID has the option to use the octet of these leading two characters as flags (the nibbles in the octet can of course use the full hex value range).
Components that need to communicate a legacy interaction to the issuer of the UUID can create an "unresolved" UUID by setting the 'random' field to all zeroes.
Notifier Format
To simplify message routing and handling of instance identifiers in Notifier, we also introduce Notifier based UUIDs. Not only do they guarantee uniqueness within the context of ION, but they also encode the Notifier server and local connection. Notifier instance identifiers represent Notifier based UUIDs and thus allow a Notifier server to directly route messages sent to instances without having to maintain maps or server-side registrations.
7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ 0 | |
+ 15 | | +—+—+—+—+—+—+—+—+
|
Field Size[bits] Octet Note ----------------------------------------------------------------------- instance_sequence 52 0-6 Instance sequence number (unique for each connection_id/node_address pair. See note below for details.
custom_low 4 6 Low 4 bits of the 8-bit custom field in bit 4 to 7 of octet 6
custom_high 4 7 High 4 bits of the 8-bit custom field in bit 0 to 3 of octet 7
connection_id 14 8-9 Local connection identifier as 14-bit big-endian integer
node_address 48 10-15 The spatially unique node identifier (MAC address as Notifier ID).
Note: To ensure temporal uniqueness of a Notifier UUID created for a particularnode_address/connection_id
pair, a createdinstance_sequence
value must be greater than the number of microseconds since2000-01-01T00:00:00Z
at the time when Notifier associated theconnection_id
with thatnode_address
. It also must be less than the number of microsoeconds since2000-01-01T00:00:00Z
at the time when the UUID is generated.