You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pr@cassandra.apache.org by GitBox <gi...@apache.org> on 2023/01/11 17:00:56 UTC

[GitHub] [cassandra-accord] belliottsmith commented on a diff in pull request #22: TxnId should be more succinct and more useful

belliottsmith commented on code in PR #22:
URL: https://github.com/apache/cassandra-accord/pull/22#discussion_r1067241613


##########
accord-core/src/main/java/accord/primitives/Timestamp.java:
##########
@@ -19,62 +19,126 @@
 package accord.primitives;
 
 import accord.local.Node.Id;
+import accord.utils.Invariants;
 
 public class Timestamp implements Comparable<Timestamp>
 {
+    public static Timestamp fromBits(long msb, long lsb, Id node)
+    {
+        return new Timestamp(msb, lsb, node);
+    }
+
+    public static Timestamp fromRaw(long epoch, long hlc, Id node)
+    {
+        return new Timestamp(epoch, hlc, 0, node);
+    }
+
+    public static Timestamp fromRaw(long epoch, long hlc, int flags, Id node)
+    {
+        return new Timestamp(epoch, hlc, flags, node);
+    }
+
+    public static Timestamp maxForEpoch(long epoch)
+    {
+        return new Timestamp((epoch << 16) | 0xffff, Long.MAX_VALUE, Id.MAX);
+    }
+
+    public static Timestamp minForEpoch(long epoch)
+    {
+        return new Timestamp(epoch << 16, 0, Id.NONE);
+    }
+
+    private static final long MAX_EPOCH = (1L << 48) - 1;
+    private static final long HLC_INCR = 1L << 16;
+    private static final long MAX_FLAGS = HLC_INCR - 1;
     public static final Timestamp NONE = new Timestamp(0, 0, 0, Id.NONE);
 
-    public final long epoch;
-    public final long real;
-    public final int logical;
+    public final long msb;
+    public final long lsb;
     public final Id node;
 
-    public Timestamp(long epoch, long real, int logical, Id node)
+    Timestamp(long epoch, long hlc, int flags, Id node)
     {
-        this.epoch = epoch;
-        this.real = real;
-        this.logical = logical;
+        Invariants.checkArgument(epoch <= MAX_EPOCH);
+        Invariants.checkArgument(flags <= MAX_FLAGS);
+        this.msb = (epoch << 16) | (hlc >>> 48);
+        this.lsb = (hlc << 16) | flags;
+        this.node = node;
+    }
+
+    Timestamp(long msb, long lsb, Id node)
+    {
+        this.msb = msb;
+        this.lsb = lsb;
         this.node = node;
     }
 
     public Timestamp(Timestamp copy)
     {
-        this.epoch = copy.epoch;
-        this.real = copy.real;
-        this.logical = copy.logical;
+        this.msb = copy.msb;
+        this.lsb = copy.lsb;
+        this.node = copy.node;
+    }
+
+    Timestamp(Timestamp copy, int flags)
+    {
+        Invariants.checkArgument(flags <= MAX_FLAGS);
+        this.msb = copy.msb;
+        this.lsb = (copy.lsb & ~MAX_FLAGS) | flags;
         this.node = copy.node;
     }
 
+    public long epoch()
+    {
+        return msb >>> 16;
+    }
+
+    /**
+     * A hybrid logical clock with implementation-defined resolution
+     */
+    public long hlc()
+    {
+        return (msb << 48) | (lsb >>> 16);
+    }
+
+    public int flags()
+    {
+        return (int) (lsb & MAX_FLAGS);
+    }
+
     public Timestamp withMinEpoch(long minEpoch)
     {
-        return minEpoch <= epoch ? this : new Timestamp(minEpoch, real, logical, node);
+        return minEpoch <= epoch() ? this : new Timestamp(minEpoch, hlc(), flags(), node);
     }
 
     public Timestamp logicalNext(Id node)
     {
-        return new Timestamp(epoch, real, logical + 1, node);
+        long lsb = this.lsb + HLC_INCR;
+        long msb = this.msb;
+        if (Long.compareUnsigned(this.lsb, lsb) > 0)
+            ++msb; // overflow of lsb
+        return new Timestamp(msb, lsb, node);
     }
 
     @Override
     public int compareTo(Timestamp that)
     {
         if (this == that) return 0;
-        int c = Long.compare(this.epoch, that.epoch);
-        if (c == 0) c = Long.compare(this.real, that.real);
-        if (c == 0) c = Integer.compare(this.logical, that.logical);
+        int c = Long.compareUnsigned(this.msb, that.msb);
+        if (c == 0) c = Long.compareUnsigned(this.lsb, that.lsb);

Review Comment:
   I've opted to ignore the flag bits entirely for identity purposes, to permit us to use them as carrier bits for things that do not relate 1:1 with the identity bits. We can move their position around later.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For additional commands, e-mail: pr-help@cassandra.apache.org