Skip to content

Commit 645b494

Browse files
cigalybeikov
authored andcommitted
HHH-19935 Make sure that increment to current sequence can not be zero
1 parent 82d913d commit 645b494

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ public long millis() {
5454
return 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+
*/
5764
private static long nanos(Instant timestamp) {
5865
return (long) ((timestamp.getNano() % 1_000_000L) * 0.004096);
5966
}
@@ -64,9 +71,17 @@ public State getNextState() {
6471
return new State( now, randomSequence() );
6572
}
6673
else {
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

7994
private 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
120135
0x8000_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

Comments
 (0)