def poll_message(self, msg): msg_type = ffi.getctype(ffi.typeof(msg.data)) if msg_type == 'msg_appendentries_t *': node = lib.raft_get_node(msg.sendee.raft, msg.sendor.id) response = ffi.new('msg_appendentries_response_t*') e = lib.raft_recv_appendentries(msg.sendee.raft, node, msg.data, response) if lib.RAFT_ERR_SHUTDOWN == e: logging.error('Catastrophic') print(msg.sendee.debug_log()) print(msg.sendor.debug_log()) sys.exit(1) elif lib.RAFT_ERR_NEEDS_SNAPSHOT == e: pass # TODO: pretend as if snapshot works else: self.enqueue_msg(response, msg.sendee, msg.sendor) elif msg_type == 'msg_appendentries_response_t *': node = lib.raft_get_node(msg.sendee.raft, msg.sendor.id) lib.raft_recv_appendentries_response(msg.sendee.raft, node, msg.data) elif msg_type == 'msg_requestvote_t *': response = ffi.new('msg_requestvote_response_t*') node = lib.raft_get_node(msg.sendee.raft, msg.sendor.id) lib.raft_recv_requestvote(msg.sendee.raft, node, msg.data, response) self.enqueue_msg(response, msg.sendee, msg.sendor) elif msg_type == 'msg_requestvote_response_t *': node = lib.raft_get_node(msg.sendee.raft, msg.sendor.id) e = lib.raft_recv_requestvote_response(msg.sendee.raft, node, msg.data) if lib.RAFT_ERR_SHUTDOWN == e: msg.sendor.shutdown() else: assert False
def notify_membership_event(self, node, event_type): # Convenience: Ensure that added node has udata set if event_type == lib.RAFT_MEMBERSHIP_ADD: node_id = lib.raft_node_get_id(node) try: server = self.network.id2server(node_id) except ServerDoesNotExist: pass else: node = lib.raft_get_node(self.raft, node_id) lib.raft_node_set_udata(node, server.udata)
def load_snapshot(self, snapshot, other): # logging.warning('{} loading snapshot'.format(self)) e = lib.raft_begin_load_snapshot( self.raft, snapshot.last_term, snapshot.last_idx, ) if e == -1: return 0 elif e == lib.RAFT_ERR_SNAPSHOT_ALREADY_LOADED: return 0 elif e == 0: pass else: assert False # Send appendentries response for this snapshot response = ffi.new('msg_appendentries_response_t*') response.success = 1 response.current_idx = snapshot.last_idx response.term = lib.raft_get_current_term(self.raft) response.first_idx = response.current_idx self.network.enqueue_msg(response, self, other) node_id = lib.raft_get_nodeid(self.raft) # set membership configuration according to snapshot for member in snapshot.members: if -1 == member.id: continue node = lib.raft_get_node(self.raft, member.id) if not node: udata = ffi.NULL try: node_sv = self.network.id2server(member.id) udata = node_sv.udata except ServerDoesNotExist: pass node = lib.raft_add_node(self.raft, udata, member.id, member.id == node_id) lib.raft_node_set_active(node, 1) if member.voting and not lib.raft_node_is_voting(node): lib.raft_node_set_voting(node, 1) elif not member.voting and lib.raft_node_is_voting(node): lib.raft_node_set_voting(node, 0) if node_id != member.id: assert node # TODO: this is quite ugly # we should have a function that removes all nodes by ourself # if (!raft_get_my_node(self->raft)) */ # raft_add_non_voting_node(self->raft, NULL, node_id, 1); */ e = lib.raft_end_load_snapshot(self.raft) assert(0 == e) assert(lib.raft_get_log_count(self.raft) == 0) self.do_membership_snapshot() self.snapshot.image = dict(snapshot.image) self.snapshot.last_term = snapshot.last_term self.snapshot.last_idx = snapshot.last_idx assert(lib.raft_get_my_node(self.raft)) # assert(sv->snapshot_fsm); self.fsm_dict = dict(snapshot.image) logging.warning('{} loaded snapshot t:{} idx:{}'.format( self, snapshot.last_term, snapshot.last_idx))