Example #1
0
    def test_follower_server_on_receive_message_with_greater_term(self):

        msg = AppendEntriesMessage(0, 1, 2, {})

        self.server.on_message(msg)

        self.assertEqual(2, self.server._currentTerm)
Example #2
0
    def test_follower_server_on_receive_message_where_log_contains_conflicting_entry_at_new_index(
            self):

        self.server._log.append({"term": 1, "value": 0})
        self.server._log.append({"term": 1, "value": 200})
        self.server._log.append({"term": 1, "value": 300})
        self.server._log.append({"term": 2, "value": 400})

        msg = AppendEntriesMessage(
            0, 1, 2, {
                "prevLogIndex": 0,
                "prevLogTerm": 1,
                "leaderCommit": 1,
                "entries": [{
                    "term": 1,
                    "value": 100
                }]
            })

        self.server.on_message(msg)
        self.assertEqual({"term": 1, "value": 100}, self.server._log[1])
        self.assertEqual([{
            "term": 1,
            "value": 0
        }, {
            "term": 1,
            "value": 100
        }], self.server._log)
Example #3
0
    def test_follower_server_on_receive_message_with_lesser_term(self):
        msg = AppendEntriesMessage(0, 1, -1, {})
        self.server.on_message(msg)

        self.assertEquals(
            False,
            self.oserver._messageBoard.get_message().data["response"])
Example #4
0
    def test_leader_server_sends_appendentries_to_all_neighbors_but_some_have_dirtied_logs(
            self):

        self.leader._neighbors[0]._log.append({"term": 2, "value": 100})
        self.leader._neighbors[0]._log.append({"term": 2, "value": 200})
        self.leader._neighbors[1]._log.append({"term": 3, "value": 200})
        self.leader._log.append({"term": 1, "value": 100})

        self._perform_hearbeat()

        msg = AppendEntriesMessage(
            0, None, 1, {
                "prevLogIndex": 0,
                "prevLogTerm": 0,
                "leaderCommit": 1,
                "entries": [{
                    "term": 1,
                    "value": 100
                }]
            })

        self.leader.send_message(msg)

        for i in self.leader._neighbors:
            i.on_message(i._messageBoard.get_message())

        for i in self.leader._neighbors:
            self.assertEqual([{"term": 1, "value": 100}], i._log)
Example #5
0
    def on_response_received(self, message):
        # Was the last AppendEntries good?
        if (not message.data["response"]):
            # No, so lets back up the log for this node
            self._nextIndexes[message.sender] -= 1

            # Get the next log entry to send to the client.
            previousIndex = max(0, self._nextIndexes[message.sender] - 1)
            previous = self._server._log[previousIndex]
            current = self._server._log[self._nextIndexes[message.sender]]

            # Send the new log to the client and wait for it to respond.
            appendEntry = AppendEntriesMessage(
                self._server._name, message.sender, self._server._currentTerm,
                {
                    "leaderId": self._server._name,
                    "prevLogIndex": previousIndex,
                    "prevLogTerm": previous["term"],
                    "entries": [current],
                    "leaderCommit": self._server._commitIndex,
                })

            self._send_response_message(appendEntry)
        else:
            # The last append was good so increase their index.
            self._nextIndexes[message.sender] += 1

            # Are they caught up?
            if (self._nextIndexes[message.sender] >
                    self._server._lastLogIndex):
                self._nextIndexes[message.sender] = self._server._lastLogIndex

        return self, None
Example #6
0
    def _send_heartbeat(self):
        # "Queue" a call to itself that will be run in the future
        self.heartbeat_handler = threading.Timer(self.heartbeat_interval,
                                                 self._send_heartbeat).start()

        message = AppendEntriesMessage(sender=self.server.name,
                                       receiver=None,
                                       term=self.server.current_term,
                                       data=None)
        self.server.send_message_to_all(message, self.heartbeat_list)
Example #7
0
 def _send_heart_beat(self):
     message = AppendEntriesMessage(
         self._server._name, None, self._server._currentTerm, {
             "leaderId": self._server._name,
             "prevLogIndex": self._server._lastLogIndex,
             "prevLogTerm": self._server._lastLogTerm,
             "entries": [],
             "leaderCommit": self._server._commitIndex,
         })
     self._server.send_message(message)
 def send_new_entry(self, new_entry):
     self._server._log.add_block(new_entry)
     message = AppendEntriesMessage(
         self._server._name, None, self._server._currentTerm, {
             "leaderId": self._server._name,
             "prevLogIndex": self._server._lastLogIndex,
             "prevLogTerm": self._server._lastLogTerm,
             "entries": [new_entry],
             "leaderCommit": self._server._commitIndex,
         })
     self._server.logger.info('try to append new block')
     self._server.send_message(message)
Example #9
0
 def test_follower_server_on_receive_message_where_log_is_empty_and_receives_its_first_value(
         self):
     msg = AppendEntriesMessage(
         0, 1, 2, {
             "prevLogIndex": 0,
             "prevLogTerm": 100,
             "leaderCommit": 1,
             "entries": [{
                 "term": 1,
                 "value": 100
             }]
         })
     self.server.on_message(msg)
     self.assertEquals({"term": 1, "value": 100}, self.server._log[0])
Example #10
0
    def test_append(self):
        self._perform_hearbeat()

        msg = AppendEntriesMessage(0, None, 1, {
            "prevLogIndex": 0,
            "prevLogTerm": 0,
            "leaderCommit": 1,
            "entries": [{"term": 1, "value": 100}]})

        self.leader.send_message(msg)

        for i in self.leader._neighbors:
            i.on_message(i._messageBoard.get_message())

        for i in self.leader._neighbors:
            self.assertEqual([{"term": 1, "value": 100}], i._log)
Example #11
0
 def test_follower_server_on_receive_message_where_log_does_not_have_prevLogTerm(
         self):
     self.server._log.append({"term": 100, "value": 2000})
     msg = AppendEntriesMessage(
         0, 1, 2, {
             "prevLogIndex": 0,
             "prevLogTerm": 1,
             "leaderCommit": 1,
             "entries": [{
                 "term": 1,
                 "value": 100
             }]
         })
     self.server.on_message(msg)
     self.assertEquals(
         False,
         self.oserver._messageBoard.get_message().data["response"])
     self.assertEquals([], self.server._log)
Example #12
0
 def test_follower_server_on_message(self):
     msg = AppendEntriesMessage(0, 1, 2, {})
     self.server.on_message(msg)
    def on_response_received(self, message):
        # Was the last AppendEntries good?
        if (not message.data["response"]):
            # No, so lets back up the log for this node
            self._nextIndexes[message.sender] = \
                min(self._nextIndexes[message.sender],
                    self._server._log.size()-1)
            if not message.data['reply_heartbeat']:
                self._nextIndexes[message.sender] -= 1

            # Get the next log entry to send to the client.
            previousIndex = max(0, self._nextIndexes[message.sender] - 1)
            previous = self._server._log.get(previousIndex)
            self._server.logger.info(str(self._nextIndexes[message.sender]))
            current = self._server._log.get(self._nextIndexes[message.sender])

            # Send the new log to the client and wait for it to respond.
            appendEntry = AppendEntriesMessage(
                self._server._name, message.sender, self._server._currentTerm,
                {
                    "leaderId": self._server._name,
                    "prevLogIndex": previousIndex,
                    "prevLogTerm": previous.get_term(),
                    "entries": [current],
                    "leaderCommit": self._server._commitIndex,
                })
            self._server.send_message(appendEntry)

        else:
            # The last append was good so increase their index.
            self._server.logger.info('append an entry to follower')
            self._nextIndexes[message.sender] += 1

            # Are they caught up?
            if (self._nextIndexes[message.sender] >
                    self._server._lastLogIndex + 1):
                self._nextIndexes[
                    message.sender] = self._server._lastLogIndex + 1

            self._matchIndex[
                message.sender] = self._nextIndexes[message.sender] - 1
            commit_count = 1
            for _ in self._matchIndex:
                #print(self._matchIndex[_], self._nextIndexes[_])
                if self._matchIndex[_] > self._server._commitIndex:
                    commit_count += 1
            if commit_count > (self._server._total_nodes - 1) / 2:
                self._server.logger.info('commitIndex add 1')
                self._server._commitIndex += 1
                self._server._log.set_commitIndex(self._server._commitIndex)
                commit_log = self._server._log.get(self._server._commitIndex)
                log_data = commit_log.txns
                for txn in log_data:
                    #print(txn)
                    if len(txn.split('\t')) == 1:
                        continue
                    txn_id = txn.split('\t')[0]
                    receiver = txn_id.split('_')[0].replace(' ', '\t')
                    response = ResponseMessage(
                        self._server._name, receiver, None, {
                            "response": True,
                            "currentTerm": self._server._currentTerm,
                            'txn_id': txn_id
                        })
                    self._server.send_message(response)

        return self, None
Example #14
0
# print(server)
"""
_name: 1, 
_state: <states.follower.Follower object at 0x10ef77048>, 
_log: [], 
_messageBoard: board: [], 
_neighbors: [<servers.server.Server object at 0x10ef71cf8>], 
_total_nodes: 0, 
_commitIndex: 0, 
_currentTerm: 0, 
_lastApplied: 0, 
_lastLogIndex: 0, 
_lastLogTerm: None
"""

msg = AppendEntriesMessage(0, 1, 2, {})
# print(msg)
"""
AppendEntries: 0, RequestVote: 1, RequestVoteResponse: 2, Response: 3, 
_timestamp: 1581654239, _sender: 0, _receiver: 1, _data: {}, _term: 2, _type: 0
"""
server.on_message(msg)
# print(server)
"""
_name: 1, 
_state: <states.follower.Follower object at 0x10d08afd0>, 
_log: [], 
_messageBoard: board: [], 
_neighbors: [<servers.server.Server object at 0x10d08acf8>], 
_total_nodes: 0, 
_commitIndex: 0, 
Example #15
0
    def test_mtd(self):
        print("\n\n***test_mtd***")
        print("---perform_heartbeat---")
        self._perform_hearbeat()

        self.leader._log.append({"term": 1, "value": "10.0.1.1"})

        # form and add typical entry
        msg = AppendEntriesMessage(
            0, None, 1, {
                "prevLogIndex": 0,
                "prevLogTerm": 0,
                "leaderCommit": 0,
                "entries": [{
                    "term": 1,
                    "value": "10.0.1.1"
                }]
            })

        self.leader.send_message(msg)

        for i in self.leader._neighbors:
            i.on_message(i._messageBoard.get_message())

        # for i in self.leader._neighbors:
        #     self.assertEqual([{"term": 1, "value": 100}], i._log)

        self.printLogs()

        # print("---perform_heartbeat---")
        # self._perform_hearbeat()

        self.leader._log.append({"term": 1, "value": "10.0.1.2"})

        # form and add another typical entry
        msg = AppendEntriesMessage(
            0, None, 1, {
                "prevLogIndex": 0,
                "prevLogTerm": 1,
                "leaderCommit": 0,
                "entries": [{
                    "term": 1,
                    "value": "10.0.1.2"
                }]
            })

        self.leader.send_message(msg)

        for i in self.leader._neighbors:
            i.on_message(i._messageBoard.get_message())

        # for i in self.leader._neighbors:
        #     self.assertEqual([{"term": 1, "value": 100.100.100.100}, {"term": 1, "value": 200}], i._log)

        self.printLogs()

        print("---Regular entries added. Request change---")

        # self._perform_hearbeat()

        self.leader._log.append({"term": 1, "value": "hashthis"})
        # attack detected, leader requests address change via AppendEntries
        # value of 999 signifies an attack was detected
        msg = AppendEntriesMessage(
            0, None, 1, {
                "prevLogIndex": 0,
                "prevLogTerm": 1,
                "leaderCommit": 1,
                "entries": [{
                    "term": 1,
                    "value": 999,
                    "addr": "hashthis"
                }]
            })

        self.leader.send_message(msg)

        for i in self.leader._neighbors:
            i.on_message(i._messageBoard.get_message())

        # for i in self.leader._neighbors:
        #     self.assertEqual([{"term": 1, "value": 100}, {"term": 1, "value": 200}, {"term": 1, "value": 999}], i._log)

        self.printLogs()