Class UUIDTimer

java.lang.Object
com.fasterxml.uuid.UUIDTimer

public class UUIDTimer extends Object
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

    Fields
    Modifier and Type
    Field
    Description
    protected final UUIDClock
    Clock used to get the time when a timestamp is requested.
    private int
    Counter used to compensate inadequate resolution of JDK system timer.
    private int
    Additional state information used to protect against anomalous cases (clock time going backwards, node id getting mixed up).
    private long
    First timestamp that can NOT be used without synchronizing using synchronization object (_syncer).
    private long
    Last physical timestamp value System.currentTimeMillis() returned: used to catch (and report) cases where system clock goes backwards.
    private long
    Timestamp value last used for generating a UUID (along with _clockCounter.
    private final LoggerFacade
     
    protected final Random
    Random number generator used to generate additional information to further reduce probability of collisions.
    protected final TimestampSynchronizer
    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).
    private static final int
    Also, instead of getting time in units of 100nsecs, we get something with max resolution of 1 msec...
    private static final long
     
    private static final long
    Since 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 long
    Let'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

    Constructors
    Constructor
    Description
     
     
  • Method Summary

    Modifier and Type
    Method
    Description
    protected final void
    getAndSetTimestamp(byte[] uuidBytes)
     
    int
     
    long
    Method that constructs unique timestamp suitable for use for constructing UUIDs.
    private void
     
    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.
    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)

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • _logger

      private final LoggerFacade _logger
    • kClockOffset

      private static final long kClockOffset
      Since 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 kClockMultiplier
      Also, 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 kMaxClockAdvance
      Let's allow "virtual" system time to advance at most 100 milliseconds beyond actual physical system time, before adding delays.
      See Also:
    • _syncer

      protected final TimestampSynchronizer _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 TimestampSynchronizer for details.

    • _random

      protected final Random _random
      Random number generator used to generate additional information to further reduce probability of collisions.
    • _clock

      protected final UUIDClock _clock
      Clock used to get the time when a timestamp is requested.
      Since:
      3.3
    • _clockSequence

      private int _clockSequence
      Additional 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 _lastSystemTimestamp
      Last physical timestamp value System.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 _lastUsedTimestamp
      Timestamp 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
      First timestamp that can NOT be used without synchronizing using synchronization object (_syncer). Only used when external timestamp synchronization (and persistence) is used, ie. when _syncer is not null.
    • _clockCounter

      private int _clockCounter
      Counter used to compensate inadequate resolution of JDK system timer.
    • MAX_WAIT_COUNT

      private static final int MAX_WAIT_COUNT
      See Also:
  • Constructor Details

  • Method Details

    • initCounters

      private void initCounters(Random rnd)
    • 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