Class PNCounter

java.lang.Object
com.loomcache.server.datastructures.PNCounter

public class PNCounter extends Object
Positive-Negative Counter (PN-Counter) CRDT.

Maintains two internal G-Counters so that both increments and decrements are monotonic at the state level:

  • P: sum of all positive increments per node
  • N: sum of all negative decrements per node
Value = sum(P) - sum(N).

Merges are element-wise max per node and commutative, associative and idempotent — anti-entropy-safe.

Since:
1.0
  • Constructor Details

  • Method Details

    • increment

      public void increment()
      Increment the counter by 1.
    • increment

      public void increment(long delta)
      Increment the counter by delta.
      Parameters:
      delta - the amount to add (can be negative for decrement)
    • incrementForNode

      public void incrementForNode(String contributorId, long delta)
      Increment the counter by delta for a logical contributor.

      Wire operations use the client PN-counter session id as the contributor so every Raft replica applies an identical CRDT state, independent of the server node that happened to execute the log entry.

      Parameters:
      contributorId - logical CRDT contributor/session id
      delta - the amount to add (can be negative for decrement)
    • decrement

      public void decrement()
      Decrement the counter by 1.
    • decrement

      public void decrement(long delta)
      Decrement the counter by delta.
      Parameters:
      delta - the amount to subtract
    • decrementForNode

      public void decrementForNode(String contributorId, long delta)
      Decrement the counter by delta for a logical contributor.
      Parameters:
      contributorId - logical CRDT contributor/session id
      delta - the amount to subtract
    • get

      public long get()
      Get the current value of the counter. Value = sum(P) - sum(N) across all known nodes.
    • merge

      public void merge(PNCounter other)
      Merge another PN-Counter into this one.
    • getPSum

      public long getPSum()
      Get the P (positive) sum across all nodes.
    • getNSum

      public long getNSum()
      Get the N (negative) sum across all nodes.
    • getVectorClock

      public Map<String,Long> getVectorClock()
      Get the vector clock version (for diagnostics).
    • getPositiveCountersSnapshot

      public Map<String,Long> getPositiveCountersSnapshot()
      Snapshot the positive component by contributor id.
    • getNegativeCountersSnapshot

      public Map<String,Long> getNegativeCountersSnapshot()
      Snapshot the negative component by contributor id.
    • getNodeCount

      public int getNodeCount()
      Get the number of nodes that have contributed to this counter.
    • getLocalP

      public long getLocalP()
      Get the local P counter value for this node.
    • getLocalN

      public long getLocalN()
      Get the local N counter value for this node.
    • getNodeP

      public long getNodeP(String node)
      Get the P counter value for a specific node.
    • getNodeN

      public long getNodeN(String node)
      Get the N counter value for a specific node.
    • reset

      public void reset()
      Reset is NOT supported for PN-Counters in a distributed context.

      PN-Counter state must evolve monotonically (element-wise max on merge). A local reset is non-monotonic: if A resets after B merges A's state, a subsequent merge of B into A will silently restore pre-reset values.

      Throws:
      UnsupportedOperationException - always — reset violates CRDT merge invariants