def send_heartbeat(self, follower): # check if the new follower have same commit index, else we tell them to update to our log level if self.log: self.update_follower_commitIdx(follower) while self.status == LEADER: start = time.time() channel = grpc.insecure_channel(follower) stub = mykvserver_pb2_grpc.KVServerStub(channel) ping = mykvserver_pb2.JoinRequest() #print(ping) if ping: if follower not in self.fellow: self.fellow.append(follower) message = mykvserver_pb2.HBMessage() message.term = self.term message.addr = self.addr reply = stub.HeartBeat(message) if reply: self.heartbeat_reply_handler(reply.term, reply.commitIdx) delta = time.time() - start # keep the heartbeat constant even if the network speed is varying time.sleep((cfg.HB_TIME - delta) / 1000) else: for index in range(len(self.fellow)): if self.fellow[index] == follower: self.fellow.pop(index) print('Server {} lost connect'.format(follower)) break
def update_follower_commitIdx(self, follower): channel = grpc.insecure_channel(follower) stub = mykvserver_pb2_grpc.KVServerStub(channel) message = mykvserver_pb2.HBMessage() message.term = self.term message.addr = self.addr message.action = 'commit' message.payload.act = self.log[-1]['act'] message.payload.key = self.log[-1]['key'] message.commitIdx = self.commitIdx if self.log[-1]['value']: message.payload.value = self.log[-1]['value'] reply = stub.HeartBeat(message)
def spread_update(self, message, confirmations=None, lock=None): for i, each in enumerate(self.fellow): channel = grpc.insecure_channel(each) stub = mykvserver_pb2_grpc.KVServerStub(channel) m = mykvserver_pb2.HBMessage() m.term = message['term'] m.addr = message['addr'] if message['payload'] is not None: #print(message['payload']) m.payload.act = message['payload']['act'] m.payload.key = message['payload']['key'] m.payload.value = message['payload']['value'] #m.action = 'commit' if message['action']: m.action = message['action'] m.commitIdx = self.commitIdx r = stub.HeartBeat(m) if r and confirmations: # print(f" - - {message['action']} by {each}") confirmations[i] = True if lock: lock.release()
def ask_for_vote(self, voter, term): # need to include self.commitIdx, only up-to-date candidate could win #debugger (self.addr+'+'+voter) channel = grpc.insecure_channel(voter) stub = mykvserver_pb2_grpc.KVServerStub(channel) message = mykvserver_pb2.VoteMessage() #debugger (stub.VoteRequest(message),2) message.term = term message.commitIdx = self.commitIdx if self.staged: message.staged.act = self.staged['act'] message.staged.key = self.staged['key'] message.staged.value = self.staged['value'] while self.status == CANDIDATE and self.term == term: reply = stub.VoteRequest(message) if reply: #choice = reply.json()["choice"] choice = reply.choice #print(f"RECEIVED VOTE {choice} from {voter}") if choice and self.status == CANDIDATE: self.incrementVote() elif not choice: # they declined because either I'm out-of-date or not newest term # update my term and terminate the vote_req #term = reply.json()["term"] term = int(reply.term) if term > self.term: self.term = term self.status = FOLLOWER # fix out-of-date needed break
# client put request if __name__ == "__main__": print(' * this is grpc client') action = sys.argv[1] addr = sys.argv[2] key = sys.argv[3] while True: channel = grpc.insecure_channel(addr) # print(addr) if len(sys.argv) == 4: # addr, key # get,del stub = mykvserver_pb2_grpc.KVServerStub(channel) response = None if action == 'get' or action == 'GET': msg = mykvserver_pb2.GetMessage() msg.type = 'get' msg.payload.act = 'get' msg.payload.key = key msg.payload.value = '' response = stub.GetRequest(msg) if response.payload.message: print('redirect to leader', response.payload.message) addr = response.payload.message else: print(response) break elif action == 'del' or action == 'DEL':