def Join(self, server_addr): self.initialize() mprint('join start') self.predecessor = None self.hashed_predecessor = None with grpc.insecure_channel(server_addr) as channel: stub = cpg.chordStub(channel) res = stub.GetSuccessor( cp.GetSuccessorRequest(id=str(self.hashed_addr)), timeout=self.config['rpc_timeout']) successor = res.server_addr successor_list = [successor]+[''] * \ (self.config['successor_list_len']-1) with grpc.insecure_channel(successor) as channel: stub = cpg.chordStub(channel) # get my own data res = stub.GetPredecessor(cp.Null()) hashed_predecessor = (self.hash(res.server_addr) + 1) & ( (1 << self.config['mbits']) - 1) res = stub.GetRange( cp.GetRangeRequest(from_id=str(hashed_predecessor), to_id=str(self.hashed_addr))) for k, v in zip(res.keys, res.vals): self.store[k] = {'val': v, 'id': self.hash(k)} self.successor = successor self.successor_list = successor_list # delete successor's my own data res = stub.DeleteRange( cp.DeleteRangeRequest(from_id=str(hashed_predecessor), to_id=str(self.hashed_addr))) # res = stub.GetReplicas(cp.GetReplicasRequest( # remaining=self.config['max_failures'])) # for k, v in zip(res.keys, res.vals): # self.store[k] = {'val': v, 'id': self.hash(k), 'own': False} mprint('join', self.successor)
def _DoReplicate(self, remaining, uid): keys = [k for k in self.store if self.Own(self.hash(k))] vals = [self.store[k]['val'] for k in keys] mprint('dorep', self.predecessor, keys, vals, self.store) with grpc.insecure_channel(self.predecessor) as channel: stub = cpg.chordStub(channel) stub.DirectPutMulti(cp.DirectPutMultiRequest( keys=keys, vals=vals, remaining=self.config['max_failures'], uuid=uuid.uuid4().hex), timeout=self.config['rpc_timeout'] * self.config['max_failures']) if remaining > 1: for addr in list(self.successor_list): try: with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) stub.DoReplicate( cp.DoReplicateRequest(remaining=remaining - 1, uuid=uid), timeout=remaining * self.config['rpc_timeout']) mprint('rep to', addr) break except Exception as e: mprint('dor', e)
def Put(self, req, ctx): if self.leave: raise Exception('Leave') return key, val, id = req.key, req.val, int(req.id) if self.hashed_predecessor and (in_range(self.hashed_predecessor, id, self.hashed_addr) or id == self.hashed_addr): self.store[key] = {'val': val, 'id': id} with grpc.insecure_channel(self.predecessor) as channel: stub = cpg.chordStub(channel) stub.DirectPut(cp.DirectPutRequest( key=key, id=str(id), val=val, uuid=uuid.uuid4().hex, remaining=self.config['max_failures']), timeout=self.config['rpc_timeout'] * self.config['max_failures']) return cp.PutResponse(code=cp.Success) else: nxt_addr, _ = self.FindSuccessor(id) try: with grpc.insecure_channel(nxt_addr) as channel: stub = cpg.chordStub(channel) return stub.Put(cp.PutRequest(key=req.key, val=req.val, id=str(req.id)), timeout=self.config['rpc_timeout']) except Exception as e: mprint('put', e) return cp.PutResponse(code=cp.Error)
def pl_kd(config, rg, kvs): f = gen_hash(config['mbits']) plens = [] for key, val in tqdm(kvs.items()): with grpc.insecure_channel(np.random.choice( config['servers'][:rg])) as channel: stub = cpg.chordStub(channel) resp = stub.Put(cp.PutRequest(key=key, val=val, id=str(f(key)))) for key in tqdm(kvs.keys()): with grpc.insecure_channel(np.random.choice( config['servers'][:rg])) as channel: stub = cpg.chordStub(channel) resp = stub.GetSuccessor(cp.GetSuccessorRequest(id=str(f(key)))) plens.append(resp.path_length) plens = np.asarray(plens) kd = {} for srv in config['servers'][:rg]: with grpc.insecure_channel(srv) as channel: stub = cpg.chordStub(channel) resp = stub.GetStatus(cp.Null()) kd[srv] = list(resp.keys) for srv in config['servers'][:rg]: with grpc.insecure_channel(srv) as channel: stub = cpg.chordStub(channel) resp = stub.Reset(cp.Null()) return plens, kd
def check_stable(config, rg): fgs = {} for srv in config['servers'][:rg]: with grpc.insecure_channel(srv) as channel: stub = cpg.chordStub(channel) resp = stub.GetFingers(cp.Null()) fgs[srv] = resp.server_addrs time.sleep(12 * rg) for srv in config['servers'][:rg]: with grpc.insecure_channel(srv) as channel: stub = cpg.chordStub(channel) resp = stub.GetFingers(cp.Null()) if fgs[srv] != resp.server_addrs: return False return True
def FindSuccessor(self, id): successor = None plen = 0 if in_range(self.hashed_addr, id, self.hashed_successor) or id == self.hashed_successor: successor = self.successor else: nxt_addrs = self.ClosestPrecedingNode(id) mprint('nxt addr', id, nxt_addrs) while len(nxt_addrs): nxt_addr = nxt_addrs[0] nxt_addrs = nxt_addrs[1:] try: with grpc.insecure_channel(nxt_addr) as channel: stub = cpg.chordStub(channel) res = stub.GetSuccessor( cp.GetSuccessorRequest(id=str(id)), timeout=self.config['rpc_timeout']) successor = res.server_addr plen = res.path_length + 1 break except Exception as e: mprint("fs", e) # mprint('get suc', successor) return successor, plen
def Get(self, req, ctx): if self.leave: raise Exception('Leave') return mprint('get', req.key, type(req.id)) key, id = req.key, int(req.id) if self.hashed_predecessor and (in_range(self.hashed_predecessor, id, self.hashed_addr) or id == self.hashed_addr): if key in self.store: return cp.GetResponse(val=self.store[key]['val'], server_addr=self.addr, code=cp.Success) else: return cp.GetResponse(server_addr=self.addr, code=cp.KEY_NOT_EXIST) else: nxt_addr, _ = self.FindSuccessor(id) try: with grpc.insecure_channel(nxt_addr) as channel: stub = cpg.chordStub(channel) return stub.Get(cp.GetRequest(key=req.key, id=str(req.id)), timeout=self.config['rpc_timeout']) except Exception as e: mprint('get', e) return cp.GetResponse(code=cp.Error)
def DirectPutMulti(self, req, ctx): if self.leave: raise Exception('Leave') return keys, vals, remaining, uid = req.keys, req.vals, req.remaining, req.uuid if uid in self.replica_uuids: return cp.DirectPutMultiResponse(code=cp.Success) self.replica_uuids.add(uid) mprint('multiput', keys, vals, remaining, self.predecessor) for k, v in zip(keys, vals): self.store[k] = {'val': v, 'id': int(self.hash(k))} if remaining > 1: try: with grpc.insecure_channel(self.predecessor) as channel: stub = cpg.chordStub(channel) stub.DirectPutMulti( cp.DirectPutMultiRequest(keys=keys, vals=vals, uuid=uid, remaining=remaining - 1), timeout=self.config['rpc_timeout'] * remaining) except Exception as e: mprint('multiputE', e, self.predecessor) self.replica_uuids.remove(uid) return cp.DirectPutMultiResponse(code=cp.Success)
def Stabilize(self): mprint('stable') try: x = None while self.successor_list[0]: self.successor = self.successor_list[0] self.hashed_successor = self.hash(self.successor) mprint('stable', self.successor) try: if self.addr != self.successor: with grpc.insecure_channel(self.successor) as channel: stub = cpg.chordStub(channel) res = stub.GetPredecessor( cp.Null(), timeout=self.config['rpc_timeout']) mprint('pred', self.successor, res) x = res.server_addr else: x = self.predecessor break except Exception as e: self.successor_list = self.successor_list[1:] + [None] mprint('s1', e, self.successor_list) if x: hashed_x = self.hash(x) if in_range(self.hashed_addr, hashed_x, self.hashed_successor): self.successor = x self.hashed_successor = self.hash(self.successor) self.successor_list = [self.successor ] + self.successor_list[:-1] print('update sl', self.successor_list) self.successor = self.successor_list[0] if self.addr != self.successor: with grpc.insecure_channel(self.successor) as channel: stub = cpg.chordStub(channel) res = stub.Notify(cp.NotifyRequest(server_addr=self.addr), timeout=self.config['rpc_timeout']) res = stub.GetSuccessorList( cp.Null(), timeout=self.config['rpc_timeout']) self.successor_list = [self.successor ] + res.server_addrs[:-1] else: self._Notify(self.addr) except Exception as e: import traceback as tb mprint('s2', self.successor_list, e, tb.format_stack()) pass
def wait_until_alive(self, addr): while True: try: with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) stub.Noop(cp.Null()) break except: time.sleep(1)
def CheckPredecessor(self): try: mprint('checkpred', self.predecessor) if self.predecessor != None: mprint(self.predecessor) with grpc.insecure_channel(self.predecessor) as channel: stub = cpg.chordStub(channel) stub.Noop(cp.Null(), timeout=self.config['rpc_timeout']) except Exception as e: mprint('predE', e) self.predecessor = None self.hashed_predecessor = None
def _Notify(self, addr): hashed_addr = self.hash(addr) # mprint("not", addr) if self.predecessor == None or in_range(self.hashed_predecessor, hashed_addr, self.hashed_addr): self.predecessor = addr self.hashed_predecessor = hashed_addr with grpc.insecure_channel(self.predecessor) as channel: stub = cpg.chordStub(channel) res = stub.GetRange( cp.GetRangeRequest( from_id=str((self.hashed_predecessor + 1) & ((1 << self.config['mbits']) - 1)), to_id=str(self.hashed_addr))) for k, v in zip(res.keys, res.vals): self.store[k] = {'val': v, 'id': self.hash(k)} self._DoReplicate(self.config['max_failures'], uuid.uuid4().hex)
def DirectPut(self, req, ctx): if self.leave: raise Exception('Leave') return key, id, val, remaining, uid = req.key, int( req.id), req.val, req.remaining, req.uuid if uid in self.replica_uuids: return cp.DirectPutResponse(code=cp.Success) self.replica_uuids.add(uid) self.store[key] = {'val': val, 'id': id} if remaining > 1: with grpc.insecure_channel(self.predecessor) as channel: stub = cpg.chordStub(channel) stub.DirectPut(cp.DirectPutRequest(key=key, id=str(id), val=val, uuid=uid, remaining=remaining - 1), timeout=self.config['rpc_timeout'] * remaining) self.replica_uuids.remove(uid) return cp.DirectPutResponse(code=cp.Success)
def GetReplicas(self, req, ctx): if self.leave: raise Exception('Leave') return remaining, uid = req.remaining, req.uuid keys, vals = [], [] if uid in self.replica_uuids: return cp.GetReplicasResponse(keys=keys, vals=vals) self.replica_uuids.add(uid) for k, v in self.store.items(): if self.Own(self.hash(k)): keys.append(k) vals.append(v['val']) if remaining > 1: with grpc.insecure_channel(self.successor) as channel: stub = cpg.chordStub(channel) res = stub.GetReplicas( cp.GetReplicasRequest(remaining=remaining - 1, uuid=uid), timeout=self.config['rpc_timeout'] * remaining) keys += res.keys vals += res.vals self.replica_uuids.remove(uid) return cp.GetReplicasResponse(keys=keys, vals=vals)
def Get(self, addr, key): with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) res = stub.Get(cp.GetRequest(key=key, id=str(self.hash(key)))) return res
def GetFingers(self, addr): with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) res = stub.GetFingers(cp.Null()) return res
def GetPredecessor(self, addr): with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) res = stub.GetPredecessor(cp.Null()) return res
def Resume(self, addr, server_addr): with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) stub.Resume(cp.ResumeRequest(server_addr=server_addr))
def Leave(self, addr): with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) stub.Leave(cp.Null())
def Put(self, addr, key, val): with grpc.insecure_channel(addr) as channel: stub = cpg.chordStub(channel) res = stub.Put( cp.PutRequest(key=key, id=str(self.hash(key)), val=val)) return res
import chord_pb2 as cp import chord_pb2_grpc as cpg import grpc from utils import gen_hash h = gen_hash(10) if __name__ == '__main__': with grpc.insecure_channel('127.0.0.1:40000') as channel: # h9 = (h('127.0.0.1:50001')+(1 << 9)) & ((1 << 10)-1) stub = cpg.chordStub(channel) # for i in range(10): # stub.Put(cp.PutRequest(key=str(i), val=str(i), id=str(h(str(i))))) print(stub.GetStatus(cp.Null()).successor_list) # print(stub.Get(cp.GetRequest(key="0", id=str(h("0"))))) # print(stub.GetSuccessor(cp.GetSuccessorRequest(id=str(h9)))) exit() # stub.Leave(cp.Null()) # stub.Resume(cp.ResumeRequest(server_addr='127.0.0.1:50003')) key = 'key1' val = 'val2' hk = str(h(key)) print(key, val, hk) res = stub.Put(cp.PutRequest(key=key, val=val, id=str(h(key)))) res = stub.Get(cp.GetRequest(key=key, id=hk)) print(res) # # res = stub.Noop(cp.Null()) # # res = stub.GetSuccessor( # # cp.GetSuccessorRequest(id=str(h('127.0.0.1:50001')))) # print(res)