def get(key): isKeyValid = fn.onlyKeyCheck(key) client_CP = request.form.get('causal_payload') if not client_CP or client_CP == "''": client_CP = [0] * (META.REPLICAS_PER_PART) else: client_CP = fn.parseVC(client_CP) if not isKeyValid[0]: return fn.http_error(isKeyValid[1], isKeyValid[2]) if IS_REPLICA and fn.getPartitionId(key) == META.THIS_PARTITION: current_max_value, current_max_VC, current_max_timestamp = findNewest( key) my_value, my_VC, my_timestamp = kv.get(key) no_result = current_max_value is None need_update = not fn.equalityVC(current_max_VC, my_VC) status_code = 200 if need_update: success, status_code = kv.put( key, current_max_value, current_max_VC, current_max_timestamp) if success: message = {"result": "success", "value": current_max_value, "node_id": MY_ID, "causal_payload": current_max_VC, "timestamp": current_max_timestamp} return fn.http_success(message, status_code) # The put fails then: a, message, status_code = fn.keyCheck(key, value)[1] return fn.http_error(message, status_code) elif no_result: return fn.http_error({"result": "error", "msg": "Key does not exist"}, 404) message = {"result": "success", "value": current_max_value, "node_id": MY_ID, "causal_payload": current_max_VC, "timestamp": current_max_timestamp} return fn.http_error(message, status_code) # Proxy else: correct_part = fn.getPartitionId(key) for current_replica in META.GLOBAL_VIEW[correct_part]: try: A = requests.get("http://" + current_replica + "/kv-store/" + key, data={'causal_payload': client_CP}, timeout=2) status_code = A.status_code response = A.json() if status_code == 404: return fn.http_error({"result": "error", "msg": "Key does not exist"}, 404) message = {"result": response['result'], "value": response['value'], "partition_id": META.THIS_PARTITION, "causal_payload": response['causal_payload'], "timestamp": response['timestamp']} return fn.http_success(message, status_code) except requests.exceptions.Timeout: continue return fn.http_error({"result": "Error", "msg": "Server unavailable"}, 500)
def broadcastGlobals(): try: data = {'global_view': META.GLOBAL_VIEW, 'directory': META.DIRECTORY} urls = ["http://" + node_ip + "/kv-store/stupid_update" for node_ip in fn.get_all_nodes()] responses = fn.put_broadcast(data, urls) return fn.http_success("SUCCESS") except: print("FAILED STUPID UPDATE")
def update(): type = request.args.get('type') update_ip = request.form.get('ip_port') # update our global view if type == "add": resp = addNode(update_ip) r = resp["result"] part_id = resp["message"] else: resp = addNode(update_ip) r = resp["result"] part_id = resp["message"] if r == SUCCESS: # put this stuff in a callback message = { "result": "success", "partition_id": part_id, "number_of_partitions": len(META.GLOBAL_VIEW) } try: data = {'global_view': META.GLOBAL_VIEW, 'directory': META.DIRECTORY} urls = ["http://" + node_ip + "/kv-store/stupid_update" for node_ip in fn.get_all_nodes()] responses = fn.put_broadcast(data, urls) return fn.http_success(message) except: print("FAILED STUPID UPDATE") else: message = { "result": "error" # TODO check if correct response }
def stupidGet(key): value, causal_payload, timestamp = kv.get(key) message = {"value": value, "causal_payload": causal_payload, "timestamp": timestamp} return fn.http_success(message, 200)
def get_all_partition_ids(): LV = range(1, fn.count_partitions() + 1) return fn.http_success({"result": "success", "partition_id_list": ','.join(LV)}, 200)
def get_partition_id(): m = META.THIS_PARTITION return fn.http_success({"result": "success", "partition_id": str(m)}, 200)
def put(key): if not request.json: val = request.form.get('val') client_CP = request.form.get('causal_payload') client_timestamp = int(time.time()) if not client_CP or client_CP == "''": client_CP = [0] * (META.REPLICAS_PER_PART) else: client_CP = fn.parseVC(client_CP) # Check if key uses valid characters, value is small enough, etc. isKeyValid = fn.keyCheck(key, val) if not isKeyValid[0]: return fn.http_error(isKeyValid[1], isKeyValid[2]) if IS_REPLICA and fn.getPartitionId(key) == META.THIS_PARTITION: my_val, my_vc, my_ts = kv.get(key) # Client has old CP if fn.compare_payload(my_vc, client_CP) == LATEST: message = {"result": "error", "causal_payload": fn.deparseVC( client_CP), "msg": "Client payload not most recent, get again before trying again"} return fn.http_error(message, 404) else: current_max_value, current_max_VC, current_max_timestamp = findNewest( key) if len(current_max_VC) < META.REPLICAS_PER_PART: diff = len(META.REPLICAS_PER_PART) - len(current_max_VC) current_max_VC = [0] * diff compare_VC_results = fn.compare_payload( current_max_VC, client_CP) if fn.equalityVC(client_CP, current_max_VC): # update value + increment client_CP[fn.getNodeID(META.IP_PORT)] += 1 result, status_code = kv.put( key, val, client_CP, client_timestamp) message = {"result": "success", "value": val, "partition_id": META.THIS_PARTITION, "causal_payload": fn.deparseVC( client_CP), "timestamp": str(client_timestamp)} return fn.http_success(message, status_code) elif (compare_VC_results == CONCURRENT and client_timestamp > int(current_max_timestamp)) or compare_VC_results == UPDATE: # increment client_CP and update our value client_CP[fn.getNodeID(META.IP_PORT)] += 1 result, status_code = kv.put( key, val, client_CP, client_timestamp) message = {"result": "success", "value": val, "partition_id": META.THIS_PARTITION, "causal_payload": fn.deparseVC( client_CP), "timestamp": str(client_timestamp)} return fn.http_success(message, status_code) else: # client is smaller: update our value and return failure result, status_code = kv.put( key, current_max_value, current_max_VC, current_max_timestamp) message = {"result": "failure", "value": current_max_value, "partition_id": META.THIS_PARTITION, "causal_payload": fn.deparseVC(client_CP), "timestamp": str(current_max_timestamp)} return fn.http_error(message, status_code) else: correct_part = fn.getPartitionId(key) send_data = {'causal_payload': client_CP, 'val': val} for current_replica in META.GLOBAL_VIEW[correct_part]: try: A = requests.put("http://" + current_replica + "/kv-store/" + key, data=send_data, timeout=2) status_code = A.status_code response = A.json() message = {"result": response['result'], "value": response['value'], "partition_id": META.THIS_PARTITION, "causal_payload": response['causal_payload'], "timestamp": response['timestamp']} # this could be error or success return fn.http_success(message, status_code) except requests.exceptions.Timeout: continue return fn.http_error({"result": "Error", "msg": "Server unavailable"}, 500) else: return fn.http_error({"result": "Error", "msg": "No VALUE provided"}, 403)
def get_partition_id(): m = META.THIS_PARTITION return fn.http_success({"result": "success", "partition_id": str(m)}, 200) @app.route('/kv-store/get_all_partition_ids') def get_all_partition_ids(): LV = range(1, fn.count_partitions() + 1) return fn.http_success({"result": "success", "partition_id_list": ','.join(LV)}, 200) @app.route('/kv-store/get_partition_members') def get_partition_members(): LV = [] partition_id = request.form.get('partition_id') if 1 <= partition_id <= fn.count_partitions: LV = fn.get_replicas(partition_id) return fn.http_success({"result": "success", "partition_members": ', '.join(LV)}, 200) else: return fn.http_error({"result": "error", "partition_members": "failed"}, 404) # HELPERS - MOVE TO FUNCTIONS # def broadcastGlobals(): try: data = {'global_view': META.GLOBAL_VIEW, 'directory': META.DIRECTORY} urls = ["http://" + node_ip + "/kv-store/stupid_update" for node_ip in fn.get_all_nodes()] responses = fn.put_broadcast(data, urls) return fn.http_success("SUCCESS") except: print("FAILED STUPID UPDATE")