예제 #1
0
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)
예제 #2
0
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")
예제 #3
0
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
        }
예제 #4
0
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)
예제 #5
0
def get_all_partition_ids():
    LV = range(1, fn.count_partitions() + 1)
    return fn.http_success({"result": "success", "partition_id_list": ','.join(LV)}, 200)
예제 #6
0
def get_partition_id():
    m = META.THIS_PARTITION
    return fn.http_success({"result": "success", "partition_id": str(m)}, 200)
예제 #7
0
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)
예제 #8
0
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")