@@ -54,6 +54,13 @@ public long millis() {
5454return lastTimestamp .toEpochMilli ();
5555}
5656
57+ /**
58+ * Sub-miliseconds part of timestamp (micro- and nanoseconds) mapped to 12 bit integral value.
59+ * Calculated as nanos / 1000000 * 4096
60+ *
61+ * @param timestamp
62+ * @return
63+ */
5764private static long nanos (Instant timestamp ) {
5865return (long ) ((timestamp .getNano () % 1_000_000L ) * 0.004096 );
5966}
@@ -64,9 +71,17 @@ public State getNextState() {
6471return new State ( now , randomSequence () );
6572}
6673else {
67- final long nextSequence = lastSequence + Holder .numberGenerator .nextLong ( 0xFFFF_FFFFL );
68- return nextSequence > MAX_RANDOM_SEQUENCE
69- ? new State ( lastTimestamp .plusNanos ( 250 ), randomSequence () )
74+ final long nextSequence = randomSequence ();
75+ /*
76+ * If next random sequence is less or equal to last one sub-millisecond part
77+ * should be incremented to preserve monotonicity of generated UUIDs.
78+ * To do this smallest number of nanoseconds that will always increase
79+ * sub-millisecond part mapped to 12 bits is
80+ * 1_000_000 (nanons per milli) / 4096 (12 bits) = 244.14...
81+ * So 245 is used as smallest integer larger than this value.
82+ */
83+ return lastSequence >= nextSequence
84+ ? new State ( lastTimestamp .plusNanos ( 245 ), nextSequence )
7085: new State ( lastTimestamp , nextSequence );
7186}
7287}
@@ -77,7 +92,7 @@ private boolean lastTimestampEarlierThan(Instant now) {
7792}
7893
7994private static long randomSequence () {
80- return Holder .numberGenerator .nextLong ( MAX_RANDOM_SEQUENCE );
95+ return Holder .numberGenerator .nextLong ( MAX_RANDOM_SEQUENCE + 1 );
8196}
8297}
8398
@@ -118,7 +133,7 @@ public UUID generateUuid(final SharedSessionContractImplementor session) {
118133| state .nanos () & 0xFFFL ,
119134// LSB bits 0-1 - variant = 4
1201350x8000_0000_0000_0000L
121- // LSB bits 2-15 - pseudorandom counter
136+ // LSB bits 2-63 - pseudorandom counter
122137| state .lastSequence
123138);
124139}
0 commit comments