com.fasterxml.uuid.impl.TimeBasedReorderedGenerator Maven / Gradle / Ivy
Show all versions of java-uuid-generator Show documentation
package com.fasterxml.uuid.impl;
import java.util.UUID;
import com.fasterxml.uuid.*;
/**
* Implementation of UUID generator that uses time/location based generation
* method field compatible with UUIDv1, reorderd for improved DB locality.
* This is usually referred to as "Version 6".
*
* As all JUG provided implementations, this generator is fully thread-safe.
* Additionally it can also be made externally synchronized with other instances
* (even ones running on other JVMs); to do this, use
* {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer} (or
* equivalent).
*
* @since 4.1
*/
public class TimeBasedReorderedGenerator extends NoArgGenerator
{
public static int BYTE_OFFSET_TIME_HIGH = 0;
public static int BYTE_OFFSET_TIME_MID = 4;
public static int BYTE_OFFSET_TIME_LOW = 7;
/*
/**********************************************************************
/* Configuration
/**********************************************************************
*/
protected final EthernetAddress _ethernetAddress;
/**
* Object used for synchronizing access to timestamps, to guarantee
* that timestamps produced by this generator are unique and monotonically increasings.
* Some implementations offer even stronger guarantees, for example that
* same guarantee holds between instances running on different JVMs (or
* with native code).
*/
protected final UUIDTimer _timer;
/**
* Base values for the second long (last 8 bytes) of UUID to construct
*/
protected final long _uuidL2;
/*
/**********************************************************************
/* Construction
/**********************************************************************
*/
/**
* @param ethAddr Hardware address (802.1) to use for generating
* spatially unique part of UUID. If system has more than one NIC,
*/
public TimeBasedReorderedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
{
byte[] uuidBytes = new byte[16];
if (ethAddr == null) {
ethAddr = EthernetAddress.constructMulticastAddress();
}
// initialize baseline with MAC address info
_ethernetAddress = ethAddr;
_ethernetAddress.toByteArray(uuidBytes, 10);
// and add clock sequence
int clockSeq = timer.getClockSequence();
uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
_uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
_timer = timer;
}
/*
/**********************************************************************
/* Access to config
/**********************************************************************
*/
@Override
public UUIDType getType() { return UUIDType.TIME_BASED_REORDERED; }
public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
/*
/**********************************************************************
/* UUID generation
/**********************************************************************
*/
@Override
public UUID generate()
{
// Ok, get 60-bit timestamp (4 MSB are ignored)
return construct(_timer.getTimestamp());
}
/**
* Method that will construct actual {@link UUID} instance for given
* timestamp: called by {@link #generate()} but may alternatively be
* called directly to construct an instance with known timestamp.
* NOTE: calling this method directly does NOT guarantee uniqueness of resulting
* {@link UUID} (caller has to guarantee uniqueness)
*
* @param rawTimestamp Timestamp usually obtained from {@link UUIDTimer#getTimestamp()},
* used for constructing UUID instance
*
* @return unix Time-based, Reordered UUID constructed for given timestamp
*
* @since 4.3
*/
public UUID construct(long rawTimestamp)
{
// First: discard 4 MSB, next 32 bits (top of 60-bit timestamp) form the
// highest 32-bit segments
final long timestampHigh = (rawTimestamp >>> 28) << 32;
// and then bottom 28 bits split into mid (16 bits), low (12 bits)
final int timestampLow = (int) rawTimestamp;
// and then low part gets mixed with variant identifier
final int timeBottom = (((timestampLow >> 12) & 0xFFFF) << 16)
// and final 12 bits mixed with variant identifier
| 0x6000 | (timestampLow & 0xFFF);
long timeBottomL = (long) timeBottom;
timeBottomL = ((timeBottomL << 32) >>> 32); // to get rid of sign extension
// and reconstruct
long l1 = timestampHigh | timeBottomL;
return new UUID(l1, _uuidL2);
}
}