X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.api.uuid%2Fsrc%2Forg%2Fargeo%2Fapi%2Fuuid%2FAbstractAsyncUuidFactory.java;h=fc1c931ff6b4945a09dadec175811bf9854ace73;hb=52964c9b7edf437ca3eec0aa7a0baa32bc6dafd6;hp=2cdb59f77f08b5d4ff2eeaedfe548e2107c3d51d;hpb=580e8ff2af47001eb3e0947488395b48773be469;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.api.uuid/src/org/argeo/api/uuid/AbstractAsyncUuidFactory.java b/org.argeo.api.uuid/src/org/argeo/api/uuid/AbstractAsyncUuidFactory.java index 2cdb59f77..fc1c931ff 100644 --- a/org.argeo.api.uuid/src/org/argeo/api/uuid/AbstractAsyncUuidFactory.java +++ b/org.argeo.api.uuid/src/org/argeo/api/uuid/AbstractAsyncUuidFactory.java @@ -1,6 +1,9 @@ package org.argeo.api.uuid; +import java.security.DrbgParameters; +import java.security.DrbgParameters.Capability; import java.security.SecureRandom; +import java.security.SecureRandomParameters; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; @@ -20,31 +23,86 @@ import java.util.concurrent.ThreadLocalRandom; */ public abstract class AbstractAsyncUuidFactory extends AbstractUuidFactory implements AsyncUuidFactory { private SecureRandom secureRandom; - protected TimeUuidState timeUuidState; + protected ConcurrentTimeUuidState timeUuidState; + + private NodeIdSupplier nodeIdSupplier; + private long currentClockSequenceRange = 0; public AbstractAsyncUuidFactory() { - secureRandom = newSecureRandom(); + secureRandom = createSecureRandom(); timeUuidState = new ConcurrentTimeUuidState(secureRandom, null); } /* * ABSTRACT METHODS */ - protected abstract UUID newTimeUUID(); + protected abstract SecureRandom createSecureRandom(); + + /* + * STATE + */ + public void reset() { + if (nodeIdSupplier == null) + throw new IllegalStateException("No node id supplier available"); + long nodeIdBase = nodeIdSupplier.get(); + timeUuidState.reset(nodeIdBase, currentClockSequenceRange); + } - protected abstract UUID newTimeUUIDwithMacAddress(); + public void setNodeIdSupplier(NodeIdSupplier nodeIdSupplier) { + this.nodeIdSupplier = nodeIdSupplier; + reset(); + } - protected abstract SecureRandom newSecureRandom(); + public void setNodeIdSupplier(NodeIdSupplier nodeIdSupplier, long range) { + this.currentClockSequenceRange = range >= 0 ? range & 0x3F00 : range; + setNodeIdSupplier(nodeIdSupplier); + } + + protected NodeIdSupplier getNodeIdSupplier() { + return nodeIdSupplier; + } + + /** + * If positive, only clock_hi is taken from the argument (range amp; 0x3F00), if + * negative, the full range of possible values is used. + */ + public void setCurrentClockSequenceRange(long range) { + this.currentClockSequenceRange = range >= 0 ? range & 0x3F00 : range; + reset(); + } /* * SYNC OPERATIONS */ - protected UUID newRandomUUIDStrong() { - return newRandomUUID(secureRandom); + protected UUID createRandomUUIDStrong() { + SecureRandomParameters parameters = secureRandom.getParameters(); + if (parameters != null) { + if (parameters instanceof DrbgParameters.Instantiation) { + Capability capability = ((DrbgParameters.Instantiation) parameters).getCapability(); + if (capability.equals(DrbgParameters.Capability.PR_AND_RESEED) + || capability.equals(DrbgParameters.Capability.RESEED_ONLY)) { + secureRandom.reseed(); + } + } + } + return createRandomUUID(secureRandom); } public UUID randomUUIDWeak() { - return newRandomUUID(ThreadLocalRandom.current()); + return createRandomUUID(ThreadLocalRandom.current()); + } + + protected UUID createTimeUUID() { + if (nodeIdSupplier == null) + throw new IllegalStateException("No node id supplier available"); + UUID uuid = new UUID(timeUuidState.getMostSignificantBits(), timeUuidState.getLeastSignificantBits()); + + assert uuid.version() == 1; + assert uuid.variant() == 2; + assert uuid.timestamp() == timeUuidState.getLastTimestamp(); + assert uuid.clockSequence() == timeUuidState.getClockSequence(); + + return uuid; } /* @@ -74,11 +132,6 @@ public abstract class AbstractAsyncUuidFactory extends AbstractUuidFactory imple return request(futureTimeUUID()); } - @Override - public CompletionStage requestTimeUUIDwithMacAddress() { - return request(futureTimeUUIDwithMacAddress()); - } - /* * ASYNC OPERATIONS (light) */ @@ -88,43 +141,21 @@ public abstract class AbstractAsyncUuidFactory extends AbstractUuidFactory imple @Override public ForkJoinTask futureNameUUIDv5(UUID namespace, byte[] data) { - return submit(() -> newNameUUIDv5(namespace, data)); + return submit(() -> createNameUUIDv5(namespace, data)); } @Override public ForkJoinTask futureNameUUIDv3(UUID namespace, byte[] data) { - return submit(() -> newNameUUIDv3(namespace, data)); + return submit(() -> createNameUUIDv3(namespace, data)); } @Override public ForkJoinTask futureRandomUUIDStrong() { - return submit(this::newRandomUUIDStrong); + return submit(this::createRandomUUIDStrong); } @Override public ForkJoinTask futureTimeUUID() { - return submit(this::newTimeUUID); + return submit(this::createTimeUUID); } - - @Override - public ForkJoinTask futureTimeUUIDwithMacAddress() { - return submit(this::newTimeUUIDwithMacAddress); - } - -// @Override -// public UUID timeUUID() { -// if (ConcurrentTimeUuidState.isTimeUuidThread.get()) -// return newTimeUUID(); -// else -// return futureTimeUUID().join(); -// } -// -// @Override -// public UUID timeUUIDwithMacAddress() { -// if (ConcurrentTimeUuidState.isTimeUuidThread.get()) -// return newTimeUUIDwithMacAddress(); -// else -// return futureTimeUUIDwithMacAddress().join(); -// } - }