예제 #1
0
파일: agent.py 프로젝트: cs648/dissertation
    def recv_acceptrequest(self, msg, instance):
        """Update instance state appropriately based upon msg.

        (b) If an acceptor receives an accept request for a proposal numbered n, it
        accepts the proposal unless it has already responded to a prepare request
        having a number greater than n.
        """
        if msg['prop_num'] >= instance['acceptor_prepare_prop_num']:
            dbprint("Instance %d: accepting prop %s (current is %s)"
                    % (instance['instance_id'],
                       msg['prop_num'],
                       instance['acceptor_cur_prop_num']),
                    level=4)
            instance['acceptor_cur_prop_num'] = msg.prop_num
            instance['acceptor_cur_prop_value'] = msg.prop_value
            self.writeAll(Msg({
                "msg_type": "acceptnotify",
                "prop_num": msg.prop_num,
                "prop_value": msg.prop_value,
                "instance_id": instance['instance_id']
            }))
        else:
            if config.NACKS_ENABLED:
                d = {
                    'msg_type': 'nack_acceptrequest',
                    'prop_num': msg['prop_num'],
                    'instance_id': instance['instance_id'],
                }
                if config.NACKS_ENABLED == 2:
                    d['prev_prop_num'] = instance['acceptor_cur_prop_num']
                    d['prev_prop_value'] = instance['acceptor_cur_prop_value']
                self.writeMessage(msg['uid'], Msg(d))
예제 #2
0
파일: core.py 프로젝트: cs648/dissertation
    def process(self, tx_id, d):
        """Process an operation that's been passed up through Paxos."""
        dbprint("processing op %r, tx id %d" % (d, tx_id), level=4)
        assert tx_id == self.tx_version+1, "process: tx_id %d != tx_version+1: %d" % (tx_id, self.tx_version+1)
        self.history.append((tx_id, d))
        assert isinstance(d, dict), "process: %s is not a dict" % (d,)

        if self.lock_holder is not None:
            if self.lock_holder != d['uid']:
                dbprint("ignoring op '%s', lock held by %s" % (d, self.lock_holder), level=3)
                self.tx_version = tx_id
                return

        op = d['type']
        if op == "nop":
            pass
        elif op == "attemptlock":
            self.process_lock(d)
        elif op == "unlock":
            self.process_unlock(d)
        elif op == "db_op":
            self.process_op(d)
        if tx_id in self.waiters:
            for d in self.waiters[tx_id]:
                d.callback(tx_id)
            del self.waiters[tx_id]
        self.tx_version = tx_id
예제 #3
0
    def process(self, tx_id, d):
        """Process an operation that's been passed up through Paxos."""
        dbprint("processing op %r, tx id %d" % (d, tx_id), level=4)
        assert tx_id == self.tx_version + 1, "process: tx_id %d != tx_version+1: %d" % (
            tx_id, self.tx_version + 1)
        self.history.append((tx_id, d))
        assert isinstance(d, dict), "process: %s is not a dict" % (d, )

        if self.lock_holder is not None:
            if self.lock_holder != d['uid']:
                dbprint("ignoring op '%s', lock held by %s" %
                        (d, self.lock_holder),
                        level=3)
                self.tx_version = tx_id
                return

        op = d['type']
        if op == "nop":
            pass
        elif op == "attemptlock":
            self.process_lock(d)
        elif op == "unlock":
            self.process_unlock(d)
        elif op == "db_op":
            self.process_op(d)
        if tx_id in self.waiters:
            for d in self.waiters[tx_id]:
                d.callback(tx_id)
            del self.waiters[tx_id]
        self.tx_version = tx_id
예제 #4
0
    def recv_acceptrequest(self, msg, instance):
        """Update instance state appropriately based upon msg.

        (b) If an acceptor receives an accept request for a proposal numbered n, it
        accepts the proposal unless it has already responded to a prepare request
        having a number greater than n.
        """
        if msg['prop_num'] >= instance['acceptor_prepare_prop_num']:
            dbprint("Instance %d: accepting prop %s (current is %s)" %
                    (instance['instance_id'], msg['prop_num'],
                     instance['acceptor_cur_prop_num']),
                    level=4)
            instance['acceptor_cur_prop_num'] = msg.prop_num
            instance['acceptor_cur_prop_value'] = msg.prop_value
            self.writeAll(
                Msg({
                    "msg_type": "acceptnotify",
                    "prop_num": msg.prop_num,
                    "prop_value": msg.prop_value,
                    "instance_id": instance['instance_id']
                }))
        else:
            if config.NACKS_ENABLED:
                d = {
                    'msg_type': 'nack_acceptrequest',
                    'prop_num': msg['prop_num'],
                    'instance_id': instance['instance_id'],
                }
                if config.NACKS_ENABLED == 2:
                    d['prev_prop_num'] = instance['acceptor_cur_prop_num']
                    d['prev_prop_value'] = instance['acceptor_cur_prop_value']
                self.writeMessage(msg['uid'], Msg(d))
예제 #5
0
 def value_learned(self, instance):
     assert instance['status'] == "completed"
     dbprint("passing TX(%s, %s) up" %
             (instance['instance_id'], instance['value']),
             level=3)
     self.manager._passup_tx((instance['instance_id'], instance['value']))
     return instance
예제 #6
0
 def writeMessage(self, uid, msg):
     dbprint("Sent %s message to %s\n%s\n" % (msg['msg_type'], uid, msg),
             level=1)
     msg.contents['uid'] = self.uid
     msg = msg.serialize()
     addr = self.hosts[uid]
     self.transport.write(msg, addr)
예제 #7
0
파일: agent.py 프로젝트: cs648/dissertation
    def recv_acceptnotify(self, msg, instance):
        """Update instance state appropriately based upon msg.

        If the proposal has been accepted by a quorum, it's completed.
        """
        # if we've already learnt it's been accepted, there's no need to
        # deal with it any more
        if instance['status'] == "completed":
            return
        s = instance['learner_accepted'].setdefault(msg['prop_num'], set())
        s.add(msg['uid'])
        if len(s) >= self.quorum_size:
            dbprint("Instance %d: learnt value %s (prop %s)"
                    % (instance['instance_id'],
                       msg['prop_value'],
                       msg['prop_num']),
                    level=4)
            instance['status'] = "completed"
            instance['value'] = msg['prop_value']
            assert not instance['callback'].called, "completion error 1: %s: %s" % (msg, instance)
            instance['callback'].callback(instance)
예제 #8
0
파일: agent.py 프로젝트: cs648/dissertation
    def datagramReceived(self, msg, host):
        """Called when a message is received by a specific agent.

        """
        self._msgs.append((msg, host))
        try:
            m = parse_message(msg)
            # If we haven't heard this host before, add them to the record
            if m['uid'] not in self.hosts and m['uid'] != self.uid:
                self.addHost(m['uid'], host)
            t = m['msg_type']
            dbprint("Got %s message from %s\n%s\n" % (m['msg_type'], host, m), level=1)
            if m['instance_id'] is not None:
                i = m['instance_id']
                if i not in self.instances:
                    if i >= self.current_instance_number:
                        self.current_instance_number = i+1
                    self.instances[i] = self.create_instance(i)
                else:
                    assert i < self.current_instance_number, "known but oddly large instance number %s (%s)" % (i, self.current_instance_number)
                instance = self.instances[i]
                if instance['status'] == 'completed':
                    dbprint("dropping msg as instance %s is already completed" % i, level=2)
                    return
            else:
                instance = None
            method = getattr(self, "recv_%s" % t)
            method(m, instance)
        except (InvalidMessageException, KeyError), e:
            dbprint("%s received invalid message %s (%s)" % (self, msg, e), level=4)
            raise
예제 #9
0
    def recv_acceptnotify(self, msg, instance):
        """Update instance state appropriately based upon msg.

        If the proposal has been accepted by a quorum, it's completed.
        """
        # if we've already learnt it's been accepted, there's no need to
        # deal with it any more
        if instance['status'] == "completed":
            return
        s = instance['learner_accepted'].setdefault(msg['prop_num'], set())
        s.add(msg['uid'])
        if len(s) >= self.quorum_size:
            dbprint(
                "Instance %d: learnt value %s (prop %s)" %
                (instance['instance_id'], msg['prop_value'], msg['prop_num']),
                level=4)
            instance['status'] = "completed"
            instance['value'] = msg['prop_value']
            assert not instance[
                'callback'].called, "completion error 1: %s: %s" % (msg,
                                                                    instance)
            instance['callback'].callback(instance)
예제 #10
0
 def chase_up(self, instance_id):
     dbprint("chasing up instance %s" % instance_id, level=2)
     if instance_id not in self.instances:
         dbprint("chase up: haven't heard of %s yet, starting again" % instance_id, level=2)
         self.instances[i] = self.create_instance(instance_id)
         self.proposer_start(i, "nop", restart=False)
     else:
         dbprint("chase up: already heard of %s, being mean anyway" % instance_id, level=2)
         i = self.instances[instance_id]
         self.proposer_start(i, "nop", restart=False)
예제 #11
0
 def chase_up(self, instance_id):
     dbprint("chasing up instance %s" % instance_id, level=2)
     if instance_id not in self.instances:
         dbprint("chase up: haven't heard of %s yet, starting again" %
                 instance_id,
                 level=2)
         self.instances[i] = self.create_instance(instance_id)
         self.proposer_start(i, "nop", restart=False)
     else:
         dbprint("chase up: already heard of %s, being mean anyway" %
                 instance_id,
                 level=2)
         i = self.instances[instance_id]
         self.proposer_start(i, "nop", restart=False)
예제 #12
0
파일: agent.py 프로젝트: cs648/dissertation
    def recv_promise(self, msg, instance):
        """Update instance state appropriately based upon msg.

        (a) If the proposer receives a response to its prepare requests (numbered n)
        from a majority of acceptors, then it sends an accept request to each of those
        acceptors for a proposal numbered n with a value v, where v is the value of
        the highest-numbered proposal among the responses, or if the responses reported
        no proposals, a value of its own choosing.
        """
        # If this is an old message or we're in the wrong state, ignore
        if msg['prop_num'] != instance['last_tried']:# or instance['status'] != "trying":
            dbprint("proposer ignoring msg %s, not appropriate (%s)"
                    % (msg, instance),
                    level=1)
            return

        instance['quorum'].add(msg['uid'])

        if msg['prev_prop_value'] is not None:
            if msg['prev_prop_num'] > instance['proposer_prev_prop_num']:
                dbprint("loading old prop value of %s (num %s)"
                        % (msg['prev_prop_value'], msg['prev_prop_num']),
                        level=2)
                instance['proposer_prev_prop_num'] = msg['prev_prop_num']
                instance['proposer_prev_prop_value'] = msg['prev_prop_value']
            else:
                dbprint("ignoring old prop value of %s (num %s) for prop %s"
                        % (msg['prev_prop_value'],
                           msg['prev_prop_num'],
                           instance['proposer_prev_prop_value']),
                        level=2)

        if len(instance['quorum']) >= self.quorum_size:
            # If this is the message that tips us over the edge and we
            # finally accept the proposal, deal with it appropriately.
            if instance['status'] == 'trying':
                self.poll(instance, msg['prop_num'])
예제 #13
0
    def recv_promise(self, msg, instance):
        """Update instance state appropriately based upon msg.

        (a) If the proposer receives a response to its prepare requests (numbered n)
        from a majority of acceptors, then it sends an accept request to each of those
        acceptors for a proposal numbered n with a value v, where v is the value of
        the highest-numbered proposal among the responses, or if the responses reported
        no proposals, a value of its own choosing.
        """
        # If this is an old message or we're in the wrong state, ignore
        if msg['prop_num'] != instance[
                'last_tried']:  # or instance['status'] != "trying":
            dbprint("proposer ignoring msg %s, not appropriate (%s)" %
                    (msg, instance),
                    level=1)
            return

        instance['quorum'].add(msg['uid'])

        if msg['prev_prop_value'] is not None:
            if msg['prev_prop_num'] > instance['proposer_prev_prop_num']:
                dbprint("loading old prop value of %s (num %s)" %
                        (msg['prev_prop_value'], msg['prev_prop_num']),
                        level=2)
                instance['proposer_prev_prop_num'] = msg['prev_prop_num']
                instance['proposer_prev_prop_value'] = msg['prev_prop_value']
            else:
                dbprint("ignoring old prop value of %s (num %s) for prop %s" %
                        (msg['prev_prop_value'], msg['prev_prop_num'],
                         instance['proposer_prev_prop_value']),
                        level=2)

        if len(instance['quorum']) >= self.quorum_size:
            # If this is the message that tips us over the edge and we
            # finally accept the proposal, deal with it appropriately.
            if instance['status'] == 'trying':
                self.poll(instance, msg['prop_num'])
예제 #14
0
    def datagramReceived(self, msg, host):
        """Called when a message is received by a specific agent.

        """
        self._msgs.append((msg, host))
        try:
            m = parse_message(msg)
            # If we haven't heard this host before, add them to the record
            if m['uid'] not in self.hosts and m['uid'] != self.uid:
                self.addHost(m['uid'], host)
            t = m['msg_type']
            dbprint("Got %s message from %s\n%s\n" % (m['msg_type'], host, m),
                    level=1)
            if m['instance_id'] is not None:
                i = m['instance_id']
                if i not in self.instances:
                    if i >= self.current_instance_number:
                        self.current_instance_number = i + 1
                    self.instances[i] = self.create_instance(i)
                else:
                    assert i < self.current_instance_number, "known but oddly large instance number %s (%s)" % (
                        i, self.current_instance_number)
                instance = self.instances[i]
                if instance['status'] == 'completed':
                    dbprint(
                        "dropping msg as instance %s is already completed" % i,
                        level=2)
                    return
            else:
                instance = None
            method = getattr(self, "recv_%s" % t)
            method(m, instance)
        except (InvalidMessageException, KeyError), e:
            dbprint("%s received invalid message %s (%s)" % (self, msg, e),
                    level=4)
            raise
예제 #15
0
 def writeAll(self, msg):
     dbprint("%s sent message %s to all" % (self, msg), level=1)
     for uid in self.hosts:
         self.writeMessage(uid, msg)
예제 #16
0
 def value_learned(self, instance):
     assert instance['status'] == "completed"
     dbprint("passing TX(%s, %s) up" % (instance['instance_id'], instance['value']), level=3)
     self.manager._passup_tx((instance['instance_id'], instance['value']))
     return instance
예제 #17
0
파일: core.py 프로젝트: cs648/dissertation
 def process_unlock(self, d):
     """Handle someone requesting to take the global lock"""
     guid = d['uid']
     dbprint("unlock: released by %s" % guid, level=3)
     self.lock_holder = None
예제 #18
0
파일: core.py 프로젝트: cs648/dissertation
 def process_op(self, d):
     try:
         op = parse_op(d)
         op.perform_op(self.db)
     except InvalidOp, e:
         dbprint("Invalid op (%s)" % e)
예제 #19
0
파일: core.py 프로젝트: cs648/dissertation
 def process_lock(self, d):
     """Handle someone requesting to take the global lock"""
     guid = d['uid']
     dbprint("lock: taken by %s" % guid, level=3)
     self.lock_holder = guid
예제 #20
0
 def process_unlock(self, d):
     """Handle someone requesting to take the global lock"""
     guid = d['uid']
     dbprint("unlock: released by %s" % guid, level=3)
     self.lock_holder = None
예제 #21
0
파일: agent.py 프로젝트: cs648/dissertation
 def addHost(self, uid, host):
     dbprint("Adding node %s (%s)" % (uid, host), level=3)
     self.hosts[uid] = host
     self.quorum_size = (len(self.hosts)+1) // 2
예제 #22
0
 def process_lock(self, d):
     """Handle someone requesting to take the global lock"""
     guid = d['uid']
     dbprint("lock: taken by %s" % guid, level=3)
     self.lock_holder = guid
예제 #23
0
 def process_op(self, d):
     try:
         op = parse_op(d)
         op.perform_op(self.db)
     except InvalidOp, e:
         dbprint("Invalid op (%s)" % e)
예제 #24
0
 def addHost(self, uid, host):
     dbprint("Adding node %s (%s)" % (uid, host), level=3)
     self.hosts[uid] = host
     self.quorum_size = (len(self.hosts) + 1) // 2
예제 #25
0
파일: agent.py 프로젝트: cs648/dissertation
 def writeMessage(self, uid, msg):
     dbprint("Sent %s message to %s\n%s\n" % (msg['msg_type'], uid, msg), level=1)
     msg.contents['uid'] = self.uid
     msg = msg.serialize()
     addr = self.hosts[uid]
     self.transport.write(msg, addr)
예제 #26
0
파일: agent.py 프로젝트: cs648/dissertation
 def writeAll(self, msg):
     dbprint("%s sent message %s to all" % (self, msg), level=1)
     for uid in self.hosts:
         self.writeMessage(uid, msg)