Move time UUID nodeid back to the factory
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 23 Jan 2022 05:38:12 +0000 (06:38 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 23 Jan 2022 05:38:12 +0000 (06:38 +0100)
org.argeo.api.acr/src/org/argeo/api/acr/uuid/ConcurrentTimeUuidState.java
org.argeo.api.acr/src/org/argeo/api/acr/uuid/SimpleUuidFactory.java
org.argeo.api.acr/src/org/argeo/api/acr/uuid/TimeUuidState.java

index bf4039678564ab38bc15813e213ac43e8da066b5..d83356b5cd3240629f9ae358c172bab93c0d0c8f 100644 (file)
@@ -1,6 +1,5 @@
 package org.argeo.api.acr.uuid;
 
-import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.time.Clock;
 import java.time.Duration;
@@ -15,10 +14,10 @@ public class ConcurrentTimeUuidState implements TimeUuidState {
        /** The maximum possible value of the clocksequence. */
        private final static int MAX_CLOCKSEQUENCE = 16384;
 
-       private final byte[] nodeId = new byte[6];
        private final ThreadLocal<Holder> holder;
 
        private final Instant startInstant;
+       /** A start timestamp to which {@link System#nanoTime()}/100 can be added. */
        private final long startTimeStamp;
 
        private final Clock clock;
@@ -26,22 +25,12 @@ public class ConcurrentTimeUuidState implements TimeUuidState {
 
        private final SecureRandom secureRandom;
 
-       public ConcurrentTimeUuidState(byte[] nodeId, int offset, SecureRandom secureRandom, Clock clock) {
+       public ConcurrentTimeUuidState(SecureRandom secureRandom, Clock clock) {
                useClockForMeasurement = clock != null;
                this.clock = clock != null ? clock : Clock.systemUTC();
 
                Objects.requireNonNull(secureRandom);
                this.secureRandom = secureRandom;
-               if (nodeId != null) {
-                       // copy array in case it should change in the future
-                       if (offset + 6 > nodeId.length)
-                               throw new IllegalArgumentException(
-                                               "Node id array is too small: " + nodeId.length + ", offset=" + offset);
-                       System.arraycopy(nodeId, offset, this.nodeId, 0, 6);
-               } else {
-                       this.secureRandom.nextBytes(this.nodeId);
-                       assert TimeUuidState.isNoMacAddressNodeId(this.nodeId);
-               }
 
                // compute the start reference
                startInstant = Instant.now(this.clock);
@@ -57,7 +46,6 @@ public class ConcurrentTimeUuidState implements TimeUuidState {
                                Holder value = new Holder();
                                value.lastTimestamp = startTimeStamp;
                                value.clockSequence = newClockSequence();
-                               System.arraycopy(ConcurrentTimeUuidState.this.nodeId, 0, value.nodeId, 0, 6);
                                return value;
                        }
                };
@@ -116,16 +104,6 @@ public class ConcurrentTimeUuidState implements TimeUuidState {
                return (duration.getSeconds() * 10000000 + duration.getNano() / 100);
        }
 
-       protected SecureRandom initSecureRandom() {
-               SecureRandom secureRandom;
-               try {
-                       secureRandom = SecureRandom.getInstanceStrong();
-               } catch (NoSuchAlgorithmException e) {
-                       secureRandom = new SecureRandom();
-               }
-               return secureRandom;
-       }
-
        /*
         * STATE OPERATIONS
         */
@@ -138,16 +116,15 @@ public class ConcurrentTimeUuidState implements TimeUuidState {
         * ACCESSORS
         */
 
-       @Override
-       public byte[] getNodeId() {
-               byte[] arr = new byte[6];
-               System.arraycopy(holder.get().nodeId, 0, arr, 0, 6);
-               return arr;
-       }
+//     @Override
+//     public byte[] getNodeId() {
+//             byte[] arr = new byte[6];
+//             System.arraycopy(holder.get().nodeId, 0, arr, 0, 6);
+//             return arr;
+//     }
 
        @Override
        public long getClockSequence() {
                return holder.get().clockSequence;
        }
-
 }
index 9e86b0bd2f130f553ea3dd45d8aa6b5f59ed84c2..9339704f4ea946fd99d1d1aefb6f84fbe3beb90d 100644 (file)
@@ -28,19 +28,14 @@ import java.util.UUID;
 public class SimpleUuidFactory implements UuidFactory {
        private final static Logger logger = System.getLogger(SimpleUuidFactory.class.getName());
        public final static UuidFactory DEFAULT = new SimpleUuidFactory(null, -1, null);
-//     private final static int MAX_CLOCKSEQUENCE = 16384;
 
        private SecureRandom secureRandom;
-       private final byte[] hardwareAddress;
-
-//     private final AtomicInteger clockSequence;
-
-       /** A start timestamp to which {@link System#nanoTime()}/100 can be added. */
-//     private final long startTimeStamp;
-
-       private final TimeUuidState macAddressTimeUuidState;
-       private final TimeUuidState defaultTimeUuidState;
+       private final TimeUuidState timeUuidState;
 
+//     private NodeId macAddressNodeId;
+//     private NodeId defaultNodeId;
+       private byte[] macAddressNodeId;
+       private byte[] defaultNodeId;
 
        public SimpleUuidFactory(byte[] nodeId, int offset, Clock clock) {
                try {
@@ -56,21 +51,16 @@ public class SimpleUuidFactory implements UuidFactory {
                        }
                }
 
-//             clockSequence = new AtomicInteger(secureRandom.nextInt(MAX_CLOCKSEQUENCE));
-               hardwareAddress = getHardwareAddress();
-
-               macAddressTimeUuidState = hardwareAddress != null
-                               ? new ConcurrentTimeUuidState(hardwareAddress, 0, secureRandom, clock)
-                               : null;
-               defaultTimeUuidState = nodeId != null ? new ConcurrentTimeUuidState(nodeId, offset, secureRandom, clock)
-                               : macAddressTimeUuidState != null ? macAddressTimeUuidState
-                                               // we use random as a last resort
-                                               : new ConcurrentTimeUuidState(null, -1, secureRandom, clock);
-
-               // GREGORIAN_START = ZonedDateTime.of(1582, 10, 15, 0, 0, 0, 0, ZoneOffset.UTC);
-//             Duration duration = Duration.between(TimeUuidState.GREGORIAN_START, Instant.now());
-//             long nowVm = System.nanoTime() / 100;
-//             startTimeStamp = (duration.getSeconds() * 10000000 + duration.getNano() / 100) - nowVm;
+               byte[] hardwareAddress = getHardwareAddress();
+//             macAddressNodeId = hardwareAddress != null ? new NodeId(hardwareAddress, 0) : null;
+               macAddressNodeId = toNodeId(hardwareAddress, 0);
+
+//             defaultNodeId = nodeId != null ? new NodeId(nodeId, offset) : macAddressNodeId;
+               defaultNodeId = nodeId != null ? toNodeId(nodeId, offset) : toNodeId(macAddressNodeId, 0);
+               if (defaultNodeId == null)
+                       throw new IllegalStateException("No default node id specified");
+
+               timeUuidState = new ConcurrentTimeUuidState(secureRandom, clock);
        }
 
        /*
@@ -103,7 +93,7 @@ public class SimpleUuidFactory implements UuidFactory {
 
                // tests
 //             assert uuid.node() == BitSet.valueOf(node).toLongArray()[0];
-               //assert uuid.node() == longFromBytes(node);
+               // assert uuid.node() == longFromBytes(node);
                assert uuid.timestamp() == timestamp;
                assert uuid.clockSequence() == clockSequence
                                : "uuid.clockSequence()=" + uuid.clockSequence() + " clockSequence=" + clockSequence;
@@ -114,46 +104,16 @@ public class SimpleUuidFactory implements UuidFactory {
 
        @Override
        public UUID timeUUIDwithMacAddress() {
-               if (macAddressTimeUuidState == null)
+               if (macAddressNodeId == null)
                        throw new UnsupportedOperationException("No MAC address is available");
-//             long timestamp = startTimeStamp + System.nanoTime() / 100;
-               return timeUUID(macAddressTimeUuidState.useTimestamp(), macAddressTimeUuidState.getClockSequence(),
-                               macAddressTimeUuidState.getNodeId(), 0);
+               return timeUUID(timeUuidState.useTimestamp(), timeUuidState.getClockSequence(), macAddressNodeId, 0);
        }
 
-//     public UUID timeUUID(long timestamp, Random random) {
-//             byte[] node = new byte[6];
-//             random.nextBytes(node);
-//             node[0] = (byte) (node[0] | 1);
-////           long clockSequence = nextClockSequence();
-//             return timeUUID(timestamp, macAddressTimeUuidState.getClockSequence(), node, 0);
-//     }
-
        @Override
        public UUID timeUUID() {
-//             long timestamp = startTimeStamp + System.nanoTime() / 100;
-//             return timeUUID(timeUuidState.useTimestamp());
-//     }
-//
-//     public UUID timeUUID(long timestamp) {
-//             if (hardwareAddress == null)
-//                     return timeUUID(timestamp, secureRandom);
-//             long clockSequence = nextClockSequence();
-               return timeUUID(defaultTimeUuidState.useTimestamp(), defaultTimeUuidState.getClockSequence(),
-                               defaultTimeUuidState.getNodeId(), 0);
+               return timeUUID(timeUuidState.useTimestamp(), timeUuidState.getClockSequence(), defaultNodeId, 0);
        }
 
-//     public UUID timeUUID(long timestamp, NetworkInterface nic) {
-//             byte[] node;
-//             try {
-//                     node = nic.getHardwareAddress();
-//             } catch (SocketException e) {
-//                     throw new IllegalStateException("Cannot get hardware address", e);
-//             }
-////           long clockSequence = nextClockSequence();
-//             return timeUUID(timestamp, macAddressTimeUuidState.getClockSequence(), node, 0);
-//     }
-
        public UUID timeUUID(Temporal time, long clockSequence, byte[] node) {
                Duration duration = Duration.between(TimeUuidState.GREGORIAN_START, time);
                // Number of 100 ns intervals in one second: 1000000000 / 100 = 10000000
@@ -176,16 +136,6 @@ public class SimpleUuidFactory implements UuidFactory {
                }
 
        }
-
-//     private synchronized long nextClockSequence() {
-//             int i = clockSequence.incrementAndGet();
-//             while (i < 0 || i >= MAX_CLOCKSEQUENCE) {
-//                     clockSequence.set(secureRandom.nextInt(MAX_CLOCKSEQUENCE));
-//                     i = clockSequence.incrementAndGet();
-//             }
-//             return (long) i;
-//     }
-
        /*
         * NAME BASED (version 3 and 5)
         */
@@ -247,7 +197,6 @@ public class SimpleUuidFactory implements UuidFactory {
        @Override
        public UUID randomUUID() {
                return randomUUID(secureRandom);
-               // return UuidFactory.super.randomUUID();
        }
 
        /*
@@ -397,4 +346,35 @@ public class SimpleUuidFactory implements UuidFactory {
                }
                return new String(hexChars);
        }
+
+       private byte[] toNodeId(byte[] source, int offset) {
+               if (source == null)
+                       return null;
+               if (offset < 0 || offset + 6 > source.length)
+                       throw new ArrayIndexOutOfBoundsException(offset);
+               byte[] nodeId = new byte[6];
+               System.arraycopy(source, offset, nodeId, 0, 6);
+               return nodeId;
+       }
+
+//     static class NodeId extends ThreadLocal<byte[]> {
+//             private byte[] source;
+//             private int offset;
+//
+//             public NodeId(byte[] source, int offset) {
+//                     Objects.requireNonNull(source);
+//                     this.source = source;
+//                     this.offset = offset;
+//                     if (offset < 0 || offset + 6 > source.length)
+//                             throw new ArrayIndexOutOfBoundsException(offset);
+//             }
+//
+//             @Override
+//             protected byte[] initialValue() {
+//                     byte[] value = new byte[6];
+//                     System.arraycopy(source, offset, value, 0, 6);
+//                     return value;
+//             }
+//
+//     }
 }
index d883b8d8585ccc9d88b60f4f8de2d3b7fd0b37e6..74e6b698012ff4de2f2a562f1072296db7cf9021 100644 (file)
@@ -15,8 +15,6 @@ public interface TimeUuidState {
        /** Start of the Gregorian time, used by time-based UUID (v1). */
        final static Instant GREGORIAN_START = ZonedDateTime.of(1582, 10, 15, 0, 0, 0, 0, ZoneOffset.UTC).toInstant();
 
-       byte[] getNodeId();
-
        long useTimestamp();
 
        long getClockSequence();
@@ -26,18 +24,9 @@ public interface TimeUuidState {
        }
 
        static class Holder {
-               byte[] nodeId = new byte[6];
                long lastTimestamp;
                long clockSequence;
 
-               public byte[] getNodeId() {
-                       return nodeId;
-               }
-
-               public void setNodeId(byte[] nodeId) {
-                       this.nodeId = nodeId;
-               }
-
                public long getLastTimestamp() {
                        return lastTimestamp;
                }