Advertisement
Guest User

Untitled

a guest
Mar 25th, 2019
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.60 KB | None | 0 0
  1. import random
  2.  
  3.  
  4. class GrowCounter:
  5. '''Convergent conflict-free replicated data type state based grow-only counter.
  6. Guarantees strong eventual consistency.
  7. '''
  8.  
  9. def __init__(self, n):
  10. assert n > 0, 'at least one node in cluster'
  11.  
  12. self.n = n
  13. self.p = [0 for _ in range(n)]
  14.  
  15.  
  16. def value(self):
  17. return sum(self.p)
  18.  
  19.  
  20. def increment(self, i):
  21. assert 0 <= i < n, 'node id in cluster bounds'
  22. self.p[i] += 1
  23.  
  24.  
  25. def merge(self, other):
  26. assert self.n == other.n
  27. self.p = list(map(max, zip(self.p, other.p)))
  28.  
  29.  
  30. def compare(self, other):
  31. assert self.n == other.n
  32. return all(l <= r for (l, r) in zip(self.p, other.p))
  33.  
  34.  
  35. def __repr__(self):
  36. return '<{}: value={}, n={}, p={}>'.format(self.__class__.__name__,
  37. self.value(), self.n, self.p)
  38.  
  39.  
  40. class PosNegCounter:
  41. '''Convergent conflict-free replicated data type state based positive-negative counter.
  42. Guarantees strong eventual consistency.
  43. '''
  44.  
  45. def __init__(self, n):
  46. self.pos = GrowCounter(n)
  47. self.neg = GrowCounter(n)
  48.  
  49.  
  50. def value(self):
  51. return self.pos.value() - self.neg.value()
  52.  
  53.  
  54. def increment(self, i):
  55. self.pos.increment(i)
  56.  
  57.  
  58. def decrement(self, i):
  59. self.neg.increment(i)
  60.  
  61.  
  62. def merge(self, other):
  63. self.pos.merge(other.pos)
  64. self.neg.merge(other.neg)
  65.  
  66.  
  67. def compare(self, other):
  68. return self.pos.compare(other.pos) and self.neg.compare(other.neg)
  69.  
  70.  
  71. def __repr__(self):
  72. return '<{}: value={}, pos={}, neg={}>'.format(self.__class__.__name__,
  73. self.value(), self.pos, self.neg)
  74.  
  75.  
  76.  
  77. if __name__ == '__main__':
  78.  
  79. # Simulate cluster of n nodes, each node with its own local counter
  80. n = 10
  81. counters = [GrowCounter(n) for _ in range(n)]
  82.  
  83. # Count to 100 in a distributed cluster of n nodes
  84. for _ in range(100):
  85. # Pick an arbitrary node and increment its counter
  86. node = random.randrange(n)
  87. counters[node].increment(node)
  88.  
  89. # Simulate eventual consistency through arbitrary node communication
  90. for i in range(1000):
  91. lhs = random.choice(counters)
  92. rhs = random.choice(counters)
  93.  
  94. # Merge is commutative, associative, idempotent
  95. lhs.merge(rhs)
  96.  
  97. # Merge always increases state monotonically
  98. assert rhs.compare(lhs)
  99.  
  100.  
  101. # If we waited long enough we will see a cluster-wide consistent state
  102. for i, counter in enumerate(counters):
  103. print('{}: {}'.format(i, counter))
  104.  
  105. assert all(v.value() == 100 for v in counters), 'final consistent state reached'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement