java.lang.Object
com.fasterxml.uuid.UUIDTimer
UUIDTimer produces the time stamps required for time-based UUIDs.
It works as outlined in the UUID specification, with following
implementation:
- Java classes can only product time stamps with maximum resolution of one millisecond (at least before JDK 1.5). To compensate, an additional counter is used, so that more than one UUID can be generated between java clock updates. Counter may be used to generate up to 10000 UUIDs for each distinct java clock value.
- Due to even lower clock resolution on some platforms (older Windows versions use 55 msec resolution), timestamp value can also advanced ahead of physical value within limits (by default, up 100 millisecond ahead of reported), if necessary (ie. 10000 instances created before clock time advances).
- As an additional precaution, counter is initialized not to 0 but to a random 8-bit number, and each time clock changes, lowest 8-bits of counter are preserved. The purpose it to make likelyhood of multi-JVM multi-instance generators to collide, without significantly reducing max. UUID generation speed. Note though that using more than one generator (from separate JVMs) is strongly discouraged, so hopefully this enhancement isn't needed. This 8-bit offset has to be reduced from total max. UUID count to preserve ordering property of UUIDs (ie. one can see which UUID was generated first for given UUID generator); the resulting 9500 UUIDs isn't much different from the optimal choice.
- Finally, as of version 2.0 and onwards, optional external timestamp synchronization can be done. This is done similar to the way UUID specification suggests; except that since there is no way to lock the whole system, file-based locking is used. This works between multiple JVMs and Jug instances.
Some additional assumptions about calculating the timestamp:
- System.currentTimeMillis() is assumed to give time offset in UTC, or at least close enough thing to get correct timestamps. The alternate route would have to go through calendar object, use TimeZone offset to get to UTC, and then modify. Using currentTimeMillis should be much faster to allow rapid UUID creation.
- Similarly, the constant used for time offset between 1.1.1970 and start of Gregorian calendar is assumed to be correct (which seems to be the case when testing with Java calendars).
Note about synchronization: main synchronization point (as of version
3.1.1 and above) is getTimestamp(), so caller need not
synchronize access explicitly.
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final UUIDClockClock used to get the time when a timestamp is requested.private intCounter used to compensate inadequate resolution of JDK system timer.private intAdditional state information used to protect against anomalous cases (clock time going backwards, node id getting mixed up).private longFirst timestamp that can NOT be used without synchronizing using synchronization object (_syncer).private longLast physical timestamp valueSystem.currentTimeMillis()returned: used to catch (and report) cases where system clock goes backwards.private longTimestamp value last used for generating a UUID (along with_clockCounter.private final LoggerFacadeprotected final RandomRandom number generator used to generate additional information to further reduce probability of collisions.protected final TimestampSynchronizerObject used to reliably ensure that no multiple JVMs generate UUIDs, and also that the time stamp value used for generating time-based UUIDs is monotonically increasing even if system clock moves backwards over a reboot (usually due to some system level problem).private static final intAlso, instead of getting time in units of 100nsecs, we get something with max resolution of 1 msec...private static final longprivate static final longSince System.longTimeMillis() returns time from january 1st 1970, and UUIDs need time from the beginning of gregorian calendar (15-oct-1582), need to apply the offset:private static final longLet's allow "virtual" system time to advance at most 100 milliseconds beyond actual physical system time, before adding delays.private static final int -
Constructor Summary
ConstructorsConstructorDescriptionUUIDTimer(Random rnd, TimestampSynchronizer sync) UUIDTimer(Random rnd, TimestampSynchronizer sync, UUIDClock clock) -
Method Summary
Modifier and TypeMethodDescriptionprotected final voidgetAndSetTimestamp(byte[] uuidBytes) intlongMethod that constructs unique timestamp suitable for use for constructing UUIDs.private voidinitCounters(Random rnd) protected voidslowDown(long startTime, long actDiff) Simple utility method to use to wait for couple of milliseconds, to let system clock hopefully advance closer to the virtual timestamps used.static longtimestampToEpoch(long timestamp) Converts a UUID v1 or v6 timestamp (where unit is 100 nanoseconds), to Unix epoch timestamp (milliseconds since 01-Jan-1970 UTC)
-
Field Details
-
_logger
-
kClockOffset
private static final long kClockOffsetSince System.longTimeMillis() returns time from january 1st 1970, and UUIDs need time from the beginning of gregorian calendar (15-oct-1582), need to apply the offset:- See Also:
-
kClockMultiplier
private static final int kClockMultiplierAlso, instead of getting time in units of 100nsecs, we get something with max resolution of 1 msec... and need the multiplier as well- See Also:
-
kClockMultiplierL
private static final long kClockMultiplierL- See Also:
-
kMaxClockAdvance
private static final long kMaxClockAdvanceLet's allow "virtual" system time to advance at most 100 milliseconds beyond actual physical system time, before adding delays.- See Also:
-
_syncer
Object used to reliably ensure that no multiple JVMs generate UUIDs, and also that the time stamp value used for generating time-based UUIDs is monotonically increasing even if system clock moves backwards over a reboot (usually due to some system level problem).See
TimestampSynchronizerfor details. -
_random
Random number generator used to generate additional information to further reduce probability of collisions. -
_clock
Clock used to get the time when a timestamp is requested.- Since:
- 3.3
-
_clockSequence
private int _clockSequenceAdditional state information used to protect against anomalous cases (clock time going backwards, node id getting mixed up). Third byte is actually used for seeding counter on counter overflow. Note that only lowermost 16 bits are actually used as sequence -
_lastSystemTimestamp
private long _lastSystemTimestampLast physical timestamp valueSystem.currentTimeMillis()returned: used to catch (and report) cases where system clock goes backwards. Is also used to limit "drifting", that is, amount timestamps used can differ from the system time value. This value is not guaranteed to be monotonically increasing. -
_lastUsedTimestamp
private long _lastUsedTimestampTimestamp value last used for generating a UUID (along with_clockCounter. Usually the same as_lastSystemTimestamp, but not always (system clock moved backwards). Note that this value is guaranteed to be monotonically increasing; that is, at given absolute time points t1 and t2 (where t2 is after t1), t1 invalid input: '<'= t2 will always hold true. -
_firstUnsafeTimestamp
private long _firstUnsafeTimestamp -
_clockCounter
private int _clockCounterCounter used to compensate inadequate resolution of JDK system timer. -
MAX_WAIT_COUNT
private static final int MAX_WAIT_COUNT- See Also:
-
-
Constructor Details
-
UUIDTimer
- Throws:
IOException
-
UUIDTimer
- Parameters:
rnd- Random-number generator to usesync- Synchronizer needed for multi-threaded timestamp accessclock- Provider for milli-second resolution timestamp- Throws:
IOException- if initialization ofsyncfails due to problem related to reading of persisted last-used timestamp- Since:
- 3.3
-
-
Method Details
-
initCounters
-
getClockSequence
public int getClockSequence() -
getTimestamp
public long getTimestamp()Method that constructs unique timestamp suitable for use for constructing UUIDs. Default implementation is fully synchronized; sub-classes may choose to implement alternate strategies but due to existing usage and expectations should also be synchronized unless usage is specifically known not to require it.- Returns:
- 64-bit timestamp to use for constructing UUID
-
timestampToEpoch
public static long timestampToEpoch(long timestamp) Converts a UUID v1 or v6 timestamp (where unit is 100 nanoseconds), to Unix epoch timestamp (milliseconds since 01-Jan-1970 UTC)- Parameters:
timestamp- Timestamp used to create UUID versions 1 and 6- Returns:
- Unix epoch timestamp
- Since:
- 5.1
-
getAndSetTimestamp
protected final void getAndSetTimestamp(byte[] uuidBytes) -
slowDown
protected void slowDown(long startTime, long actDiff) Simple utility method to use to wait for couple of milliseconds, to let system clock hopefully advance closer to the virtual timestamps used. Delay is kept to just a millisecond or two, to prevent excessive blocking; but that should be enough to eventually synchronize physical clock with virtual clock values used for UUIDs.- Parameters:
actDiff- Number of milliseconds to wait for from current time point, to catch up
-