Skip to content

Commit 2aa3e47

Browse files
cigalymbellade
authored andcommitted
HHH-19935 Make sure that increment to current sequence can not be zero
1 parent 727e44f commit 2aa3e47

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

hibernate-core/src/main/java/org/hibernate/id/uuid/UuidVersion7Strategy.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ public long millis() {
5555
return 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+
*/
5865
private static long nanos(Instant timestamp) {
5966
return (long) ((timestamp.getNano() % 1_000_000L) * 0.004096);
6067
}
@@ -65,17 +72,24 @@ public State getNextState() {
6572
lastTimestamp.toEpochMilli() == now.toEpochMilli() && nanos < nanos( now ) ) {
6673
return 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-
}
7275
else {
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

7791
private 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
119133
0x8000_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

Comments
 (0)