Skip to content

Commit

Permalink
fix: applied spotless for #2851
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Kronegg committed Feb 22, 2024
1 parent 607cc4d commit 036325d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,17 @@ public class IncrementingUuidGenerator implements UuidGenerator {

/**
* Classloader identifier (MSB). The identifier is a pseudo-random number on
* 12 bits.
*
* Since we use a random value (and cut it to 12 bits), there is a small
* probability that two classloaders generate the same 12 bits random
* 12 bits. Since we use a random value (and cut it to 12 bits), there is a
* small probability that two classloaders generate the same 12 bits random
* number. This could lead to UUID collisions if the UUID parts (epoch-time,
* session counter and counter) are the same.
*
* The default `classloaderId` (random number cut to 12 bits) has a
* collision rate of less than 1% when using 10 classloaders (which leads
* to a much smaller UUID probability thanks to the other dynamic parts
* of the UUID like epoch-time and counters).
* If you use multiple classloaders and want to ensure a collision-free UUID
* generation, you need to provide the `classloaderId` by yourself. You
* can do so using the {@link #setClassloaderId(int)} method.
*
* Note: there is no need to save the Random because it's static.
* session counter and counter) are the same. The default `classloaderId`
* (random number cut to 12 bits) has a collision rate of less than 1% when
* using 10 classloaders (which leads to a much smaller UUID probability
* thanks to the other dynamic parts of the UUID like epoch-time and
* counters). If you use multiple classloaders and want to ensure a
* collision-free UUID generation, you need to provide the `classloaderId`
* by yourself. You can do so using the {@link #setClassloaderId(int)}
* method. Note: there is no need to save the Random because it's static.
*/
@SuppressWarnings("java:S2119")
static long classloaderId = new Random().nextInt() & 0x0fff;
Expand All @@ -80,21 +75,19 @@ public class IncrementingUuidGenerator implements UuidGenerator {
*/
final AtomicLong counter = new AtomicLong(-1);


/**
* Defines a new classloaderId for the class.
* This only affects instances created after the call (the
* instances created before the call keep their classloaderId).
*
* This method should be called to specify a classloaderId if
* you are using more than one class loader, and you want to
* guarantee a collision-free UUID generation (instead of
* the default random classloaderId which produces about
* 1% collision rate on the classloaderId, and thus can have
* UUID collision if the epoch-time, session counter and
* counter have the same values).
* @param classloaderId the new classloaderId (only the least significant 12 bits are used)
* @see IncrementingUuidGenerator#classloaderId
* Defines a new classloaderId for the class. This only affects instances
* created after the call (the instances created before the call keep their
* classloaderId). This method should be called to specify a classloaderId
* if you are using more than one class loader, and you want to guarantee a
* collision-free UUID generation (instead of the default random
* classloaderId which produces about 1% collision rate on the
* classloaderId, and thus can have UUID collision if the epoch-time,
* session counter and counter have the same values).
*
* @param classloaderId the new classloaderId (only the least significant 12
* bits are used)
* @see IncrementingUuidGenerator#classloaderId
*/
public static void setClassloaderId(int classloaderId) {
IncrementingUuidGenerator.classloaderId = classloaderId & 0xfff;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,32 +168,36 @@ private static UUID removeClassloaderId(UUID uuid) {
}

/**
* Create a copy of the UUID without the epoch-time part to allow comparison.
* Create a copy of the UUID without the epoch-time part to allow
* comparison.
*/
private static UUID removeEpochTime(UUID uuid) {
return new UUID(uuid.getMostSignificantBits() & 0x0ffffffL, uuid.getLeastSignificantBits());
}

/**
* Check that classloaderId collision rate is lower than a given threshold when using multiple classloaders.
* This should not be mistaken with the UUID collision rate.
* Note: this test takes about 20 seconds.
* Check that classloaderId collision rate is lower than a given threshold
* when using multiple classloaders. This should not be mistaken with the
* UUID collision rate. Note: this test takes about 20 seconds.
*/
@Test
void classloaderid_collision_rate_lower_than_two_percents_with_ten_classloaders() throws NoSuchFieldException, IllegalAccessException {
// When I compute the classloaderId collision rate with multiple classloaders
void classloaderid_collision_rate_lower_than_two_percents_with_ten_classloaders()
throws NoSuchFieldException, IllegalAccessException {
// When I compute the classloaderId collision rate with multiple
// classloaders
Set<Long> classloaderIds = new HashSet<>();
List<Integer> stats = new ArrayList<>();
while (stats.size()<100) {
while (stats.size() < 100) {
if (!classloaderIds.add(getStaticFieldValue(getUuidGeneratorFromOtherClassloader(null), "classloaderId"))) {
stats.add(classloaderIds.size()+1);
stats.add(classloaderIds.size() + 1);
classloaderIds.clear();
}
}

// Then the classloaderId collision rate for 10 classloaders is less than 2%
// Then the classloaderId collision rate for 10 classloaders is less
// than 2%
double collisionRateWhenUsingTenClassloaders = stats.stream()
.filter(x -> x<10).count() * 100 / (double) stats.size();
.filter(x -> x < 10).count() * 100 / (double) stats.size();
assertTrue(collisionRateWhenUsingTenClassloaders <= 2);
}

Expand Down Expand Up @@ -246,13 +250,16 @@ private static void setClassloaderId(Class<?> generatorClass, int value)
}

/**
* Create a fresh new IncrementingUuidGenerator from a fresh new classloader, and return a new instance.
* @param classloaderId the classloader unique identifier, or null if the default classloader id generator must be used
* @return a new IncrementingUuidGenerator instance
* Create a fresh new IncrementingUuidGenerator from a fresh new
* classloader, and return a new instance.
*
* @param classloaderId the classloader unique identifier, or null if the
* default classloader id generator must be used
* @return a new IncrementingUuidGenerator instance
*/
private static UuidGenerator getUuidGeneratorFromOtherClassloader(Integer classloaderId) {
try {
Class<?> aClass = new NonCachingClassLoader().findClass(IncrementingUuidGenerator.class.getName());
Class<?> aClass = new NonCachingClassLoader().findClass(IncrementingUuidGenerator.class.getName());
if (classloaderId != null) {
setClassloaderId(aClass, classloaderId);
}
Expand Down

0 comments on commit 036325d

Please sign in to comment.