Ejemplo n.º 1
0
    def setUp(self):
        self.node1 = Node(uuid.uuid4())
        self.node2 = Node(uuid.uuid4())

        # Create a GCounter
        self.gc1 = GCounter(uuid.uuid4())

        # Add nodes to gc1
        self.gc1.add_new_node(self.node1.id)
        self.gc1.add_new_node(self.node2.id)

        # Create another GCounter
        self.gc2 = GCounter(uuid.uuid4())
        # Add nodes to gc2
        self.gc2.add_new_node(self.node1.id)
        self.gc2.add_new_node(self.node2.id)

        # Increment gc1 values for each node
        self.gc1.inc(self.node1.id)
        self.gc1.inc(self.node1.id)
        self.gc1.inc(self.node2.id)
        # Increment gc2 values for each node
        self.gc2.inc(self.node1.id)
        self.gc2.inc(self.node2.id)
        self.gc2.inc(self.node2.id)
        self.gc2.inc(self.node2.id)
Ejemplo n.º 2
0
 def __init__(self, port, peers):
     self.socket = socket.socket(type=socket.SOCK_DGRAM)
     #self.host = socket.gethostname()
     self.host = "localhost"
     self.port = port
     self.socket.bind((self.host, self.port))
     self.state = b"ack"
     self.peers = peers
     self.counter = GCounter(port, peers)
     self.lock = threading.Lock()
     logger.debug(peers)
Ejemplo n.º 3
0
def latency_demo():
    '''Demo gCRDT with latency'''
    ps = CloudyPubSub(CloudyException)
    nodes = [GCounter(idx, ps) for idx in range(3)]

    for i in range(10):
        node = random.choice(nodes)
        node.increment()
        for n in nodes:
            print("Node %d says %d" % (n.idx, n.value()))
Ejemplo n.º 4
0
def demo():
    '''Demo gCRDT'''
    ps = PubSub()
    nodes = [GCounter(idx, ps) for idx in range(3)]

    for i in range(10):
        node = random.choice(nodes)
        node.increment()
        for n in nodes:
            print("Node %d says %d" % (n.idx, n.value()))
Ejemplo n.º 5
0
    def test_integrated(self):
        '''Test some nodes hooked up with a pub/sub'''
        pubsub = PubSub()
        nodes = [GCounter(idx, pubsub) for idx in range(3)]

        for i in range(100):
            # Pick a random node and increment it
            node = random.choice(nodes)
            node.increment()
            # All .value() checks should have the same result
            self.assertTrue(all(n.value() == node.value() for n in nodes))
Ejemplo n.º 6
0
class TestGCounter(unittest.TestCase):
    def setUp(self):
        self.node1 = Node(uuid.uuid4())
        self.node2 = Node(uuid.uuid4())

        # Create a GCounter
        self.gc1 = GCounter(uuid.uuid4())

        # Add nodes to gc1
        self.gc1.add_new_node(self.node1.id)
        self.gc1.add_new_node(self.node2.id)

        # Create another GCounter
        self.gc2 = GCounter(uuid.uuid4())
        # Add nodes to gc2
        self.gc2.add_new_node(self.node1.id)
        self.gc2.add_new_node(self.node2.id)

        # Increment gc1 values for each node
        self.gc1.inc(self.node1.id)
        self.gc1.inc(self.node1.id)
        self.gc1.inc(self.node2.id)
        # Increment gc2 values for each node
        self.gc2.inc(self.node1.id)
        self.gc2.inc(self.node2.id)
        self.gc2.inc(self.node2.id)
        self.gc2.inc(self.node2.id)

    def test_check_increment(self):
        self.assertEqual(self.gc1.payload[self.node1.id], 2)
        self.assertEqual(self.gc1.payload[self.node2.id], 1)
        self.assertEqual(self.gc2.payload[self.node1.id], 1)
        self.assertEqual(self.gc2.payload[self.node2.id], 3)

    def test_merging_gcounters(self):
        # Check gc2 merging
        self.gc2.merge(self.gc1)
        self.assertEqual(self.gc2.payload[self.node1.id], 2)
        self.assertEqual(self.gc2.payload[self.node2.id], 3)
        # Check gc1 merging
        self.gc1.merge(self.gc2)
        self.assertEqual(self.gc1.payload[self.node1.id], 2)
        self.assertEqual(self.gc1.payload[self.node2.id], 3)
        # Check if they are both equal
        self.assertEqual(self.gc1.payload, self.gc2.payload)
Ejemplo n.º 7
0
    return wrapper


class CloudyGCounter(GCounter):
    '''A subclass of GCounter that randomly becomes unresponsive.'''
    CHANCE_OF_CRASH = 0.05

    def __init__(self, *args, **kwargs):
        self.crashed = False
        super().__init__(*args, **kwargs)

    def random_crash(self):
        if chance(self.CHANCE_OF_CRASH):
            self.crashed = True


wrap_some_fns_on_cls(CloudyGCounter, randomly_crash_inst_fn,
                     lambda name: name in ["increment", "value", "_join"])

if __name__ == "__main__":
    '''Demo some nodes incrementing and publishing to each other'''
    ps = CloudyPubSub()
    nodes = [GCounter(idx, ps) for idx in range(3)]

    for i in range(10):
        node = random.choice(nodes)
        node.increment()
        for n in nodes:
            print("Node %d says %d" % (n.idx, n.value()))
Ejemplo n.º 8
0
 def __init__(self, id):
     self.P = GCounter(id)
     self.N = GCounter(id)
     self.id = id
Ejemplo n.º 9
0
class PNCounter:
    def __init__(self, id):
        self.P = GCounter(id)
        self.N = GCounter(id)
        self.id = id

    def add_new_node(self, key):
        self.P.add_new_node(key)
        self.N.add_new_node(key)

    def inc(self, key):
        self.P.inc(key)

    def dec(self, key):
        self.N.inc(key)

    def query(self):
        return self.P.query() - self.N.query()

    def compare(self, gc2):
        return self.P.compare(gc2.P) and self.N.compare(gc2.N)

    def merge(self, gc2):
        self.P.merge(gc2.P)
        self.N.merge(gc2.N)
        # self.display()

    def display(self, name):
        print("{}.P: ".format(name), end="")
        self.P.display()
        print("{}.N: ".format(name), end="")
        self.N.display()
Ejemplo n.º 10
0
class Node:
    def __init__(self, port, peers):
        self.socket = socket.socket(type=socket.SOCK_DGRAM)
        #self.host = socket.gethostname()
        self.host = "localhost"
        self.port = port
        self.socket.bind((self.host, self.port))
        self.state = b"ack"
        self.peers = peers
        self.counter = GCounter(port, peers)
        self.lock = threading.Lock()
        logger.debug(peers)

    def add(self, x):
        self.counter.add(x)
        data = pickle.dumps(self.counter)
        self.infect(data)

    def query(self):
        return self.counter.query()

    def recv(self):
        logger.info("Node {} listen on {}"\
                .format(self.host, self.port))
        while True:
            msg, address = self.socket.recvfrom(1024)
            remote_counter = pickle.loads(msg)
            self.lock.acquire()
            try:
                self.counter.merge(remote_counter)
                logger.info("Counter now: {}".format(self.counter.query()))
                data = pickle.dumps(self.counter)
                self.infect(data, address)
            finally:
                self.lock.release()

            # self.state = int(msg)
            logger.debug("address: {}".format(address))
            logger.debug("msg: {}".format(msg))

    def send(self, msg, port):

        try:
            self.socket.sendto(msg, (self.host, port))
            logger.debug("sent to {}".format(port))
        except OSError:
            logger.debug("Failed to connecto to {}".format(port))

    def random_ports(self):
        tmp = self.peers.copy()
        port1 = random.choice(tmp)
        _idx = tmp.index(port1)
        del (tmp[_idx])
        port2 = random.choice(tmp)
        return port1, port2

    def choice_port(self, origin=None):
        tmp = self.peers.copy()
        if origin:
            _idx = tmp.index(origin)
            del (tmp[_idx])
        port1 = random.choice(tmp)
        _idx2 = tmp.index(port1)
        del (tmp[_idx2])
        port2 = random.choice(tmp)

        return port1, port2

    def infect(self, data, origin=None):

        if origin:
            port1, port2 = self.choice_port(origin[1])
        else:
            port1, port2 = self.choice_port()
        logger.debug("port1 {}".format(port1))
        self.send(data, port1)
        self.send(data, port2)
        #time.sleep(WAIT)
        time.sleep(random.uniform(0, 1) * 2)

    def listen(self):
        recv = threading.Thread(target=self.recv)
        rumor = threading.Thread(target=self.infect)
        recv.start()
Ejemplo n.º 11
0
def run():
    a = GCounter(0, 2, 2000)
    b = GCounter(1, 2, 3000)
    
    print(f"a-GCounter:query={a.query()}")
    a.add(1)
    print(f"a-GCounter:query={a.query()}")
    
    print(f"b-GCounter:query={b.query()}")
    b.add(2)
    print(f"b-GCounter:query={b.query()}")
    
    print(f"a-GCounter:{a.to_dict()}")
    print(f"b-GCounter:{b.to_dict()}")
    b.sync_to_peer(a.zmq_port)
    print(f"a-GCounter:{a.to_dict()}")
    print(f"b-GCounter:{b.to_dict()}")
    
    print(f"a-GCounter:query={a.query()}")
    
    b.add(4)
    print(f"b-GCounter:query={b.query()}")
    
    print(f"a-GCounter:{a.to_dict()}")
    print(f"b-GCounter:{b.to_dict()}")
   
    a.sync_to_peer(b.zmq_port)
    print(f"a-GCounter:{a.to_dict()}")
    print(f"b-GCounter:{b.to_dict()}")
    
    print(f"b-GCounter:query={b.query()}")