X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=org.argeo.api.uuid%2Fsrc%2Forg%2Fargeo%2Fapi%2Fuuid%2FConcurrentTimeUuidState.java;h=61f5b8304d3710713a500fa2fc7347ec81ae07c6;hb=e846ef84146b66ae543c29c5f17b2991ff0f5973;hp=1529a3a5deac63d83b9d3264f74e9b99330bcef9;hpb=e491ed1cde076e741062de5db37cdb02cacd6fbe;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentTimeUuidState.java b/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentTimeUuidState.java index 1529a3a5d..61f5b8304 100644 --- a/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentTimeUuidState.java +++ b/org.argeo.api.uuid/src/org/argeo/api/uuid/ConcurrentTimeUuidState.java @@ -8,10 +8,12 @@ import java.security.SecureRandom; import java.time.Clock; import java.time.Duration; import java.time.Instant; +import java.util.Collections; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; /** * A simple base implementation of {@link TimeUuidState}, which maintains @@ -33,6 +35,8 @@ public class ConcurrentTimeUuidState implements TimeUuidState { private final Clock clock; private final boolean useClockForMeasurement; + private long nodeIdBase; + public ConcurrentTimeUuidState(SecureRandom secureRandom, Clock clock) { useClockForMeasurement = clock != null; this.clock = clock != null ? clock : Clock.systemUTC(); @@ -54,7 +58,7 @@ public class ConcurrentTimeUuidState implements TimeUuidState { protected ConcurrentTimeUuidState.Holder initialValue() { ConcurrentTimeUuidState.Holder value = new ConcurrentTimeUuidState.Holder(); value.threadId = Thread.currentThread().getId(); - value.lastTimestamp = startTimeStamp; + value.lastTimestamp = 0; clockSequenceProvider.newClockSequence(value); return value; } @@ -113,14 +117,48 @@ public class ConcurrentTimeUuidState implements TimeUuidState { @Override public long getClockSequence() { - return (long) currentHolder.get().clockSequence; + return currentHolder.get().clockSequence; } - private static class Holder { + @Override + public long getLastTimestamp() { + return currentHolder.get().lastTimestamp; + } + + public void reset(long nodeIdBase) { + synchronized (clockSequenceProvider) { + this.nodeIdBase = nodeIdBase; + clockSequenceProvider.reset(); + clockSequenceProvider.notifyAll(); + } + } + + @Override + public long getLeastSignificantBits() { + return currentHolder.get().leastSig; + } + + @Override + public long getMostSignificantBits() { + long timestamp = useTimestamp(); + long mostSig = MOST_SIG_VERSION1 // base for version 1 UUID + | ((timestamp & 0xFFFFFFFFL) << 32) // time_low + | (((timestamp >> 32) & 0xFFFFL) << 16) // time_mid + | ((timestamp >> 48) & 0x0FFFL);// time_hi_and_version + return mostSig; + } + + /* + * INTERNAL CLASSSES + */ + + private class Holder { private long lastTimestamp; - private int clockSequence; + private long clockSequence; private long threadId; + private long leastSig; + @Override public boolean equals(Object obj) { boolean isItself = this == obj; @@ -129,8 +167,13 @@ public class ConcurrentTimeUuidState implements TimeUuidState { return isItself; } - private synchronized void setClockSequence(int clockSequence) { + private void setClockSequence(long clockSequence) { this.clockSequence = clockSequence; +// if (nodeIdBase == null) +// throw new IllegalStateException("Node id base is not initialised"); + this.leastSig = nodeIdBase // already computed node base + | (((clockSequence & 0x3F00) >> 8) << 56) // clk_seq_hi_res + | ((clockSequence & 0xFF) << 48); // clk_seq_low } @Override @@ -144,11 +187,11 @@ public class ConcurrentTimeUuidState implements TimeUuidState { private int rangeSize = 256; private volatile int min; private volatile int max; - private final AtomicInteger counter = new AtomicInteger(-1); + private final AtomicLong counter = new AtomicLong(-1); private final SecureRandom secureRandom; - private final WeakHashMap activeHolders = new WeakHashMap<>(); + private final Map activeHolders = Collections.synchronizedMap(new WeakHashMap<>()); ClockSequenceProvider(SecureRandom secureRandom) { this.secureRandom = secureRandom; @@ -185,11 +228,8 @@ public class ConcurrentTimeUuidState implements TimeUuidState { } private synchronized void newClockSequence(Holder holder) { -// int activeCount = activeHolders.size(); + // Too many holders, we will remove the oldes ones while (activeHolders.size() > rangeSize) { -// throw new IllegalStateException( -// "There are too many holders for range [" + min + "," + max + "] : " + activeCount); - // remove oldest long oldestTimeStamp = -1; Holder holderToRemove = null; holders: for (Holder h : activeHolders.keySet()) { @@ -214,7 +254,7 @@ public class ConcurrentTimeUuidState implements TimeUuidState { logger.log(WARNING, "Removed " + holderToRemove + ", oldClockSequence=" + oldClockSequence); } - int newClockSequence = -1; + long newClockSequence = -1; int tryCount = 0;// an explicit exit condition do { tryCount++;