Exemplo n.º 1
0
 def debug_statistics(self):
     return {
         "node":
         lib.raft_get_nodeid(self.raft),
         "state":
         state2str(lib.raft_get_state(self.raft)),
         "current_idx":
         lib.raft_get_current_idx(self.raft),
         "last_log_term":
         lib.raft_get_last_log_term(self.raft),
         "current_term":
         lib.raft_get_current_term(self.raft),
         "commit_idx":
         lib.raft_get_commit_idx(self.raft),
         "last_applied_idx":
         lib.raft_get_last_applied_idx(self.raft),
         "log_count":
         lib.raft_get_log_count(self.raft),
         "peers":
         lib.raft_get_num_nodes(self.raft),
         "voting_peers":
         lib.raft_get_num_voting_nodes(self.raft),
         "connection_status":
         connectstatus2str(self.connection_status),
         "voting_change_in_progress":
         lib.raft_voting_change_is_in_progress(self.raft),
         "removed":
         getattr(self, 'removed', False),
     }
Exemplo n.º 2
0
    def remove_member(self):
        if not self.leader:
            logging.error('no leader')
            return

        leader = self.leader
        server = self.random.choice(self.active_servers)

        if not lib.raft_is_leader(leader.raft):
            return

        if lib.raft_voting_change_is_in_progress(leader.raft):
            # logging.error('{} voting change in progress'.format(server))
            return

        if leader == server:
            # logging.error('can not remove leader')
            return

        if server.connection_status in [NODE_CONNECTING, NODE_DISCONNECTING]:
            # logging.error('can not remove server that is changing connection status')
            return

        if NODE_DISCONNECTED == server.connection_status:
            self.remove_server(server)
            return

        # Create a new configuration entry to be processed by the leader
        ety = ffi.new('msg_entry_t*')
        ety.term = 0
        ety.id = self.new_entry_id()
        assert server.connection_status == NODE_CONNECTED
        ety.type = lib.RAFT_LOGTYPE_DEMOTE_NODE
        change = ffi.new_handle(ChangeRaftEntry(server.id))
        ety.data.buf = change
        ety.data.len = ffi.sizeof(ety.data.buf)
        assert (lib.raft_entry_is_cfg_change(ety))

        self.entries.append((ety, change))

        e = leader.recv_entry(ety)
        if 0 != e:
            logging.error(err2str(e))
            return
        else:
            self.num_membership_changes += 1

        # Wake up new node
        assert NODE_CONNECTED == server.connection_status
        server.set_connection_status(NODE_DISCONNECTING)
Exemplo n.º 3
0
    def add_member(self):
        if net.num_of_servers <= len(self.active_servers):
            return

        if not self.leader:
            logging.error('no leader')
            return

        leader = self.leader

        if not lib.raft_is_leader(leader.raft):
            return

        if lib.raft_voting_change_is_in_progress(leader.raft):
            # logging.error('{} voting change in progress'.format(server))
            return

        server = RaftServer(self)

        # Create a new configuration entry to be processed by the leader
        ety = ffi.new('msg_entry_t*')
        ety.term = 0
        ety.id = self.new_entry_id()
        ety.type = lib.RAFT_LOGTYPE_ADD_NONVOTING_NODE
        change = ffi.new_handle(ChangeRaftEntry(server.id))
        ety.data.buf = change
        ety.data.len = ffi.sizeof(ety.data.buf)
        assert (lib.raft_entry_is_cfg_change(ety))

        self.entries.append((ety, change))

        e = leader.recv_entry(ety)
        if 0 != e:
            logging.error(err2str(e))
            return
        else:
            self.num_membership_changes += 1

        # Wake up new node
        server.set_connection_status(NODE_CONNECTING)
        assert server.udata
        added_node = lib.raft_add_non_voting_node(server.raft, server.udata,
                                                  server.id, 1)
        assert added_node
Exemplo n.º 4
0
    def remove_member(self):
        if not self.leader:
            logger.error('no leader')
            return

        leader = self.leader
        server = self.random.choice(self.active_servers)

        if not lib.raft_is_leader(leader.raft):
            return

        if lib.raft_voting_change_is_in_progress(leader.raft):
            # logger.error('{} voting change in progress'.format(server))
            return

        if leader == server:
            # logger.error('can not remove leader')
            return

        if server.connection_status in [NODE_CONNECTING, NODE_DISCONNECTING]:
            # logger.error('can not remove server that is changing connection status')
            return

        if NODE_DISCONNECTED == server.connection_status:
            self.remove_server(server)
            return

        # Create a new configuration entry to be processed by the leader
        ety = self.add_entry(lib.RAFT_LOGTYPE_DEMOTE_NODE,
                             ChangeRaftEntry(server.id))
        assert server.connection_status == NODE_CONNECTED
        assert (lib.raft_entry_is_cfg_change(ety))

        e = leader.recv_entry(ety)
        if 0 != e:
            logger.error(err2str(e))
            return
        else:
            self.num_membership_changes += 1

        # Wake up new node
        assert NODE_CONNECTED == server.connection_status
        server.set_connection_status(NODE_DISCONNECTING)
Exemplo n.º 5
0
    def add_member(self):
        if net.num_of_servers <= len(self.active_servers):
            return

        if not self.leader:
            logger.error('no leader')
            return

        leader = self.leader

        if not lib.raft_is_leader(leader.raft):
            return

        if lib.raft_voting_change_is_in_progress(leader.raft):
            # logger.error('{} voting change in progress'.format(server))
            return

        server = RaftServer(self)

        # Create a new configuration entry to be processed by the leader
        ety = self.add_entry(lib.RAFT_LOGTYPE_ADD_NONVOTING_NODE,
                             ChangeRaftEntry(server.id))
        assert (lib.raft_entry_is_cfg_change(ety))

        e = leader.recv_entry(ety)
        if 0 != e:
            logger.error(err2str(e))
            return
        else:
            self.num_membership_changes += 1

        # Wake up new node
        server.set_connection_status(NODE_CONNECTING)
        assert server.udata
        added_node = lib.raft_add_non_voting_node(server.raft, server.udata,
                                                  server.id, 1)
        assert added_node
Exemplo n.º 6
0
    def toggle_membership(self):
        if not self.leader:
            logging.error('no leader')
            return

        leader = self.leader
        server = self.random.choice(self.active_servers)

        if not lib.raft_is_leader(leader.raft):
            return

        if lib.raft_voting_change_is_in_progress(leader.raft):
            # logging.error('{} voting change in progress'.format(server))
            return

        if leader == server:
            # logging.error('can not remove leader')
            return

        if server.connection_status in [NODE_CONNECTING, NODE_DISCONNECTING]:
            # logging.error('can not remove server that is changing connection status')
            return

        if NODE_DISCONNECTED == server.connection_status:
            self.remove_server(server)
            server = RaftServer(self)

        # Create a new configuration entry to be processed by the leader
        ety = ffi.new('msg_entry_t*')
        ety.term = 0
        ety.id = self.new_entry_id()
        if server.connection_status == NODE_CONNECTED:
            ety.type = lib.RAFT_LOGTYPE_DEMOTE_NODE
        else:
            ety.type = lib.RAFT_LOGTYPE_ADD_NONVOTING_NODE
        change = ffi.new_handle(ChangeRaftEntry(server.id))
        ety.data.buf = change
        ety.data.len = ffi.sizeof(ety.data.buf)
        assert(lib.raft_entry_is_cfg_change(ety))

        self.entries.append((ety, change))

        # logging.warning("{}> {} Membership change {}: ety.id:{} id:{} {}".format(
        #     self.iteration,
        #     server,
        #     "ADD" if ety.type == lib.RAFT_LOGTYPE_ADD_NONVOTING_NODE else "DEMOTE",
        #     ety.id,
        #     lib.raft_get_nodeid(leader.raft),
        #     server.id,
        # ))

        e = leader.recv_entry(ety)
        if 0 != e:
            logging.error(err2str(e))
            return
        else:
            self.num_membership_changes += 1

        # Wake up new node
        if NODE_DISCONNECTED == server.connection_status:
            server.set_connection_status(NODE_CONNECTING)
            assert server.udata
            added_node = lib.raft_add_non_voting_node(server.raft, server.udata, server.id, 1)
            assert added_node
        elif NODE_CONNECTED == server.connection_status:
            server.set_connection_status(NODE_DISCONNECTING)
        else:
            logging.warning('Unknown status set {}'.format(server.connection_status))