@@ -55,6 +55,13 @@ public long millis() {
5555return lastTimestamp .toEpochMilli ();
5656}
5757
58+ /**
59+ * Sub-miliseconds part of timestamp (micro- and nanoseconds) mapped to 12 bit integral value.
60+ * Calculated as nanos / 1000000 * 4096
61+ *
62+ * @param timestamp
63+ * @return
64+ */
5865private static long nanos (Instant timestamp ) {
5966return (long ) ((timestamp .getNano () % 1_000_000L ) * 0.004096 );
6067}
@@ -65,17 +72,24 @@ public State getNextState() {
6572lastTimestamp .toEpochMilli () == now .toEpochMilli () && nanos < nanos ( now ) ) {
6673return new State ( now , randomSequence () );
6774}
68- final long nextSequence = lastSequence + Holder .numberGenerator .nextLong ( 0xFFFF_FFFFL );
69- if ( nextSequence > MAX_RANDOM_SEQUENCE ) {
70- return new State ( lastTimestamp .plusNanos ( 250 ), randomSequence () );
71- }
7275else {
73- return new State ( lastTimestamp , nextSequence );
76+ final long nextSequence = randomSequence ();
77+ /*
78+ * If next random sequence is less or equal to last one sub-millisecond part
79+ * should be incremented to preserve monotonicity of generated UUIDs.
80+ * To do this smallest number of nanoseconds that will always increase
81+ * sub-millisecond part mapped to 12 bits is
82+ * 1_000_000 (nanons per milli) / 4096 (12 bits) = 244.14...
83+ * So 245 is used as smallest integer larger than this value.
84+ */
85+ return lastSequence >= nextSequence
86+ ? new State ( lastTimestamp .plusNanos ( 245 ), nextSequence )
87+ : new State ( lastTimestamp , nextSequence );
7488}
7589}
7690
7791private static long randomSequence () {
78- return Holder .numberGenerator .nextLong ( MAX_RANDOM_SEQUENCE );
92+ return Holder .numberGenerator .nextLong ( MAX_RANDOM_SEQUENCE + 1 );
7993}
8094}
8195
@@ -117,7 +131,7 @@ public UUID generateUuid(final SharedSessionContractImplementor session) {
117131| state .nanos () & 0xFFFL ,
118132// LSB bits 0-1 - variant = 4
1191330x8000_0000_0000_0000L
120- // LSB bits 2-15 - pseudorandom counter
134+ // LSB bits 2-63 - pseudorandom counter
121135| state .lastSequence
122136);
123137}
0 commit comments