Exemple #1
0
    def process_election_voted(self, message):
        leader = message.payload['leader']

        if self.state in (GateNode.STATE_ELECTING, GateNode.STATE_INITIATED):
            self.answers[message.sender] = leader

            if self.has_all_answers():  # all children have responded now
                leader = self.get_best_answer()  # select the leader

                if self.state == GateNode.STATE_ELECTING:  # this is an intermediate node
                    self.state = GateNode.STATE_WAITING
                    yield NetworkMessage('election_voted',
                                         self.info,
                                         self.parent,
                                         leader=leader)
                else:  # this is the node which started the election
                    self.state = GateNode.STATE_IDLE
                    self.leader = leader

                    for neighbour in self.neighbours:
                        yield NetworkMessage('election_finished',
                                             self.info,
                                             neighbour,
                                             leader=leader)
        else:
            self.handle_error('Unexpected state')
def test_start_election(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2]], visitor_repository)

    assert list(node.process_message(LocalMessage('start_election'))) == \
        [NetworkMessage('election_started', nodes[0], nodes[1]), NetworkMessage('election_started', nodes[0], nodes[2])]
    
    assert node.state == GateNode.STATE_INITIATED
def test_leader_removed():
    node = GateNode(nodes[0], [nodes[1], nodes[2]], visitor_repository)
    node.leader = nodes[5]

    assert list(node.process_message(NetworkMessage('leader_removed', nodes[1], nodes[0]))) == \
        [NetworkMessage('leader_removed', nodes[0], nodes[2])]
    assert node.leader is None
def test_terminate():
    node = GateNode(nodes[0], [nodes[1], nodes[2]], visitor_repository)

    assert list(node.process_message(LocalMessage('terminate'))) == \
        [NetworkMessage('terminated', nodes[0], nodes[1]),
            NetworkMessage('terminated', nodes[0], nodes[2]),
            None]
Exemple #5
0
    def process_election_started(self, message):
        if self.state == GateNode.STATE_IDLE:
            self.state = GateNode.STATE_ELECTING

            self.parent = message.sender
            self.leader = None
            self.answers = {}

            for child in self.get_children():
                yield NetworkMessage('election_started', self.info, child)

            if self.has_all_answers():
                # in this case there are no children for this node, so it votes for itself as the leader
                self.state = GateNode.STATE_WAITING
                yield NetworkMessage('election_voted',
                                     self.info,
                                     message.sender,
                                     leader=self.info)

        elif self.state in (GateNode.STATE_ELECTING, GateNode.STATE_INITIATED):
            yield NetworkMessage('election_voted',
                                 self.info,
                                 message.sender,
                                 leader=None)

        else:
            self.handle_error('Unexpected state')
def test_election_start_without_children(visitor_repository):
    node = GateNode(nodes[0], [nodes[1]], visitor_repository)

    assert list(node.process_message(NetworkMessage('election_started', nodes[1], nodes[0]))) == \
        [NetworkMessage('election_voted', nodes[0], nodes[1], leader=nodes[0])]
    
    assert node.state == GateNode.STATE_WAITING
    assert node.parent == nodes[1]
def test_first_election_message(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2], nodes[3]], visitor_repository)

    assert list(node.process_message(NetworkMessage('election_started', nodes[1], nodes[0]))) == \
        [NetworkMessage('election_started', nodes[0], nodes[2]), NetworkMessage('election_started', nodes[0], nodes[3])]
    
    assert node.state == GateNode.STATE_ELECTING
    assert node.parent == nodes[1]
def test_hello(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2]], visitor_repository)

    assert list(node.process_message(LocalMessage('say_hello'))) == \
        [NetworkMessage('hello', nodes[0], nodes[1]), NetworkMessage('hello', nodes[0], nodes[2])]
    
    assert list(node.process_message(NetworkMessage('hello', nodes[1], nodes[0]))) == \
        [NetworkMessage('hey', nodes[0], nodes[1])]
def test_finishing_election(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2], nodes[3]], visitor_repository)
    node.state = GateNode.STATE_WAITING

    assert list(node.process_message(NetworkMessage('election_finished', nodes[1], nodes[0], leader=nodes[5]))) == \
        [NetworkMessage('election_finished', nodes[0], nodes[2], leader=nodes[5]), NetworkMessage('election_finished', nodes[0], nodes[3], leader=nodes[5])]
    
    assert node.state == GateNode.STATE_IDLE
    assert node.leader == nodes[5]
def test_another_election_message(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2], nodes[3]], visitor_repository)
    node.state = GateNode.STATE_ELECTING
    node.parent = nodes[1]

    assert list(node.process_message(NetworkMessage('election_started', nodes[2], nodes[0]))) == \
        [NetworkMessage('election_voted', nodes[0], nodes[2], leader=None)]
    
    assert node.state == GateNode.STATE_ELECTING
    assert node.parent == nodes[1]
def test_last_ack_starting_node(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2]], visitor_repository)
    node.state = GateNode.STATE_INITIATED
    node.answers = {nodes[1]: nodes[4]}
    
    assert list(node.process_message(NetworkMessage('election_voted', nodes[2], nodes[0], leader=nodes[5]))) == \
        [NetworkMessage('election_finished', nodes[0], nodes[1], leader=nodes[5]), NetworkMessage('election_finished', nodes[0], nodes[2], leader=nodes[5])]
    
    assert node.state == GateNode.STATE_IDLE
    assert node.leader == nodes[5]
def test_request_mutex(visitor_repository):
    node = GateNode(nodes[0], [], visitor_repository)
    node.leader = nodes[0]

    assert list(node.process_message(NetworkMessage('mutex_requested', nodes[1], nodes[0]))) == \
        [NetworkMessage('mutex_granted', nodes[0], nodes[1])]
    assert node.mutex_holder == nodes[1]
    assert not node.mutex_queue

    assert list(node.process_message(NetworkMessage('mutex_requested', nodes[2], nodes[0]))) == []
    assert node.mutex_queue == [nodes[2]]

    assert list(node.process_message(NetworkMessage('mutex_requested', nodes[3], nodes[0]))) == []
    assert node.mutex_queue == [nodes[2], nodes[3]]

    assert list(node.process_message(NetworkMessage('mutex_released', nodes[1], nodes[0]))) == \
        [NetworkMessage('mutex_granted', nodes[0], nodes[2])]
    assert node.mutex_holder == nodes[2]
    assert node.mutex_queue == [nodes[3]]

    assert list(node.process_message(NetworkMessage('mutex_released', nodes[2], nodes[0]))) == \
        [NetworkMessage('mutex_granted', nodes[0], nodes[3])]
    assert node.mutex_holder == nodes[3]
    assert node.mutex_queue == []

    assert list(node.process_message(NetworkMessage('mutex_released', nodes[3], nodes[0]))) == []
    assert node.mutex_holder is None
    assert node.mutex_queue == []
def test_last_ack_intermediate_node(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2], nodes[3]], visitor_repository)
    node.state = GateNode.STATE_ELECTING
    node.parent = nodes[1]
    node.answers = {nodes[2]: nodes[5]}
    
    assert list(node.process_message(NetworkMessage('election_voted', nodes[3], nodes[0], leader=nodes[4]))) == \
        [NetworkMessage('election_voted', nodes[0], nodes[1], leader=nodes[5])]
    
    assert node.state == GateNode.STATE_WAITING
    assert node.answers == {nodes[2]: nodes[5], nodes[3]: nodes[4]}
Exemple #14
0
def test_enter_refused():
    node = VisitorNode(nodes[0])

    assert list(node.process_message(LocalMessage('enter_park', gate=nodes[1]))) == \
        [NetworkMessage('enter_request', nodes[0], nodes[1])]
    assert node.state == VisitorNode.STATE_ENTERING

    assert not list(
        node.process_message(
            NetworkMessage('enter_response', nodes[1], nodes[0],
                           allowed=False)))
    assert node.state == VisitorNode.STATE_IDLE
Exemple #15
0
def test_leave_rejected():
    node = VisitorNode(nodes[0])
    node.state = VisitorNode.STATE_ENTERED

    assert list(node.process_message(LocalMessage('leave_park', gate=nodes[1]))) == \
        [NetworkMessage('leave_request', nodes[0], nodes[1])]
    assert node.state == VisitorNode.STATE_LEAVING

    assert not list(
        node.process_message(
            NetworkMessage('leave_response', nodes[1], nodes[0],
                           allowed=False)))
    assert node.state == VisitorNode.STATE_ENTERED
    def leave_park(self, message):
        gate = message.payload['gate']

        if self.state == VisitorNode.STATE_ENTERED:
            yield NetworkMessage('leave_request', self.info, gate)
            self.state = VisitorNode.STATE_LEAVING
        else:
            self.handle_unexpected_state()
Exemple #17
0
    def terminate(self):
        if self.state == GateNode.STATE_IDLE:
            for neighbour in self.neighbours:
                yield NetworkMessage('terminated', self.info, neighbour)

            yield None  # no more messages will be sent by this node
        else:
            self.handle_error('Unexpected state')
def test_first_ack(visitor_repository):
    node = GateNode(nodes[0], [nodes[1], nodes[2], nodes[3]], visitor_repository)
    node.state = GateNode.STATE_INITIATED
    
    assert list(node.process_message(NetworkMessage('election_voted', nodes[1], nodes[0], leader=nodes[5]))) == []
    
    assert node.state == GateNode.STATE_INITIATED
    assert node.answers == {nodes[1]: nodes[5]}
    def enter_park(self, message):
        gate = message.payload['gate']

        if self.state == VisitorNode.STATE_IDLE:
            yield NetworkMessage('enter_request', self.info, gate)
            self.state = VisitorNode.STATE_ENTERING
        else:
            self.handle_unexpected_state()
Exemple #20
0
    def process_leader_removed(self, message):
        if self.leader is None:  # leader was already removed by a previous message
            return

        self.leader = None

        for neighbour in self.neighbours:
            if neighbour != message.sender:
                yield NetworkMessage('leader_removed', self.info, neighbour)
Exemple #21
0
    def remove_leader(self):
        if self.state != GateNode.STATE_IDLE:
            self.handle_error('Unexpected state')

        if self.leader != self.info:
            self.handle_error('Not the leader')

        self.leader = None

        for neighbour in self.neighbours:
            yield NetworkMessage('leader_removed', self.info, neighbour)
Exemple #22
0
    def start_election(self):
        if self.state == GateNode.STATE_IDLE:
            self.state = GateNode.STATE_INITIATED

            self.parent = None
            self.leader = None
            self.answers = {}

            for neighbour in self.neighbours:
                yield NetworkMessage('election_started', self.info, neighbour)
        else:
            self.handle_error('Unexpected state')
Exemple #23
0
    def process_mutex_granted(self, message):
        if not self.mutex_requested:
            self.handle_error('Mutex not requested')

        state = self.repository.read_state()

        for entering_node in self.enter_queue:
            try:
                state.enter(entering_node.id)
                yield NetworkMessage('enter_response',
                                     self.info,
                                     entering_node,
                                     allowed=True)
            except AssertionError:  # if node cannot enter
                yield NetworkMessage('enter_response',
                                     self.info,
                                     entering_node,
                                     allowed=False)

        for leaving_node in self.leave_queue:
            try:
                state.leave(leaving_node.id)
                yield NetworkMessage('leave_response',
                                     self.info,
                                     leaving_node,
                                     allowed=True)
            except AssertionError:  # if node cannot leave
                yield NetworkMessage('leave_response',
                                     self.info,
                                     leaving_node,
                                     allowed=False)

        self.repository.write_state(state)

        self.mutex_requested = False
        self.enter_queue = []
        self.leave_queue = []

        yield NetworkMessage('mutex_released', self.info, self.leader)
Exemple #24
0
    def process_election_finished(self, message):
        leader = message.payload['leader']

        if self.state == GateNode.STATE_WAITING:
            self.state = GateNode.STATE_IDLE
            self.leader = leader

            for neighbour in self.neighbours:
                if neighbour != message.sender:
                    yield NetworkMessage('election_finished',
                                         self.info,
                                         neighbour,
                                         leader=leader)
Exemple #25
0
    def process_mutex_released(self, message):
        if self.leader != self.info:
            self.handle_error('Not a leader')

        if self.mutex_holder is None:
            self.handle_error('No mutex holder')

        if self.mutex_holder != message.sender:
            self.handle_error('Invalid sender')

        if self.mutex_queue:  # some nodes are waiting in the queue
            self.mutex_holder = self.mutex_queue.pop(0)
            yield NetworkMessage('mutex_granted', self.info, self.mutex_holder)
        else:
            self.mutex_holder = None
def test_leave_request(visitor_repository):
    visitor_repository.write_state(State(capacity=1, visitors=[nodes[1].id]))

    node = GateNode(nodes[0], [], visitor_repository)
    node.leader = nodes[5]

    assert list(node.process_message(NetworkMessage('leave_request', nodes[1], nodes[0]))) == \
        [NetworkMessage('mutex_requested', nodes[0], nodes[5])]
    assert node.leave_queue == [nodes[1]]

    assert list(node.process_message(NetworkMessage('leave_request', nodes[2], nodes[0]))) == []
    assert node.leave_queue == [nodes[1], nodes[2]]

    assert list(node.process_message(NetworkMessage('mutex_granted', nodes[5], nodes[0]))) == \
        [NetworkMessage('leave_response', nodes[0], nodes[1], allowed=True),
            NetworkMessage('leave_response', nodes[0], nodes[2], allowed=False),
            NetworkMessage('mutex_released', nodes[0], nodes[5])]
    assert node.leave_queue == []

    assert list(node.process_message(NetworkMessage('leave_request', nodes[3], nodes[0]))) == \
        [NetworkMessage('mutex_requested', nodes[0], nodes[5])]
    assert node.leave_queue == [nodes[3]]
Exemple #27
0
 def process_hello(self, message):
     yield NetworkMessage('hey', self.info, message.sender)
Exemple #28
0
 def say_hello(self):
     for neighbour in self.neighbours:
         yield NetworkMessage('hello', self.info, neighbour)
Exemple #29
0
    def process_leave_request(self, message):
        if not self.mutex_requested:
            yield NetworkMessage('mutex_requested', self.info, self.leader)
            self.mutex_requested = True

        self.leave_queue.append(message.sender)
Exemple #30
0
 def process_mutex_requested(self, message):
     if self.mutex_holder is None:
         self.mutex_holder = message.sender
         yield NetworkMessage('mutex_granted', self.info, self.mutex_holder)
     else:
         self.mutex_queue.append(message.sender)