def exists(path, n=replication): '''Checks whether a value is stored at a path.''' n = min(int(n), replication) key = hash(path, replication - n + 1) try: assert n > 0, 'n should be strictly positive.' # Lookup successor of 'key' host = node.lookup(key)[0] if host == None: if n > 1: return exists(path, n - 1) else: raise KeyError('Unable to access path {}.'.format(path)) elif host == node.host: # Request internal node with node.lock: return jsonify(node.exists(key, path)), 200 else: # Request external node url = address(host) + 'exists/{}/{:d}'.format(path, n) resp = requests.get(url) return resp.text, resp.status_code except Exception as e: return str(e), 500
def remove(path, n=replication): '''Removes the value stored at a path.''' n = min(int(n), replication) key = hash(path, replication - n + 1) try: assert n > 0, 'n should be strictly positive.' # Lookup successor of 'key' host = node.lookup(key)[0] if host == None: if n > 1: return remove(path, n - 1) else: raise KeyError('Unable to access path {}.'.format(path)) elif host == node.host: # Request internal node with node.lock: value = node.pop(key, path) if n > 1 and value is not None: remove(path, n - 1) return 'Value successfully removed from path {}.\n'.format( path), 200 else: # Request external node url = address(host) + 'remove/{}/{:d}'.format(path, n) resp = requests.get(url) return resp.text, resp.status_code except Exception as e: return str(e), 500
def put(path, n=replication): '''Stores a value at a path.''' n = min(int(n), replication) key = hash(path, replication - n + 1) value = request.get_json() try: assert n > 0, 'n should be strictly positive.' # Lookup successor of 'key' host = node.lookup(key)[0] if host == None: if n > 1: # Start again with 'hash(path)' return put(path, n - 1) else: raise KeyError('Unable to access path {}.'.format(path)) elif host == node.host: # Request internal node with node.lock: node.put(key, path, value) if n > 1: put(path, n - 1) return 'Value successfully stored at path {}.\n'.format(path), 200 else: # Request external node url = address(host) + 'put/{}/{:d}'.format(path, n) resp = requests.post(url, json=value) return resp.text, resp.status_code except Exception as e: return str(e), 500
def copy(src, dst): '''Copies the value at a path to another.''' try: # Get value with path 'src' url = address(node.host) + 'get/{}'.format(src) resp = requests.get(url) if resp.status_code != 200: return resp.text, resp.status_code # Put value with path 'dst' url = address(node.host) + 'put/{}'.format(dst) resp = requests.post(url, json=json.loads(resp.text)) return resp.text, resp.status_code except Exception as e: return str(e), 500
def ls(): '''Lists all occupied paths within the network.''' paths = {j[0] for i in node.hash_table.values() for j in i} visited = {node.id} stack = list(node.host_table.items()) # Depth-first search while stack: id, host = stack.pop() id = int(id) if id in visited: # If already visited continue # Add to visited visited.add(id) try: # Extend stack url = address(host) + 'network' resp = requests.get(url) if resp.status_code != 200: raise ConnectionError stack.extend(json.loads(resp.text).items()) # Gather content url = address(host) + 'content' resp = requests.get(url) if resp.status_code != 200: raise ConnectionError paths.update(j[0] for i in json.loads(resp.text).values() for j in i) except: pass return jsonify(sorted(paths)), 200