def recv_inactive_osd():
    recv_inactive_osd_socket = socket.socket()
    print ("inactive osd listener socket successfully created")
    recv_inactive_osd_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # reserve a port on your computer
    port = OSD_INACTIVE_STATUS_PORT

    # Next bind to the port
    # we have not entered any ip in the ip field
    # instead we have inputted an empty string
    # this makes the server listen to requests
    # coming from other computers on the network
    recv_inactive_osd_socket.bind(('', port))
    print ("inactive osd listener socket bound to %s" %(port))

    # put the socket into listening mode
    recv_inactive_osd_socket.listen(5)
    print ("inactive osd listener socket is listening")

    # a forever loop until we interrupt it or
    # an error occurs
    while True:

        # Establish connection with client.
        c, addr = recv_inactive_osd_socket.accept()
        print ('Got connection from', addr)

        # recv the inactive osd
        osd = _recv_msg(c, 1024)

        # START THE RECOVERY

    recv_inactive_osd_socket.close()
def heartbeat_protocol(soc, live_osd):
    # Establish connection with client.
    c, addr = soc.accept()
    print(f"\nGot connection from {addr}")

    n = os.fork()

    if n == 0:
        print(F"Inside child process {os.getpid()}")
        msg = _recv_msg(c, MSG_SIZE)
        print(msg)

        if msg == None:
            print(f"Didn't receive data! [Timeout] {addr}")

        elif msg["type"] == "ALIVE":
            res = {"type": "ACK"}
            _send_msg(c, res)

        elif msg["type"] == "FAIL":
            res = {"type": "ACK"}
            _send_msg(c, res)
            gossip(c, msg, live_osd)

        c.close()

        print(f"Exiting from pid {os.getpid()} ..\n")
        os._exit(1)

    return
def recv_primary_update():
    recv_primary_update_socket = socket.socket()
    print("recv primary update socket successfully created")
    recv_primary_update_socket.setsockopt(socket.SOL_SOCKET,
                                          socket.SO_REUSEADDR, 1)

    # reserve a port on your computer
    port = RECV_PRIMARY_UPDATE_PORT

    # Next bind to the port
    # we have not entered any ip in the ip field
    # instead we have inputted an empty string
    # this makes the server listen to requests
    # coming from other computers on the network
    recv_primary_update_socket.bind(('', port))
    print("primary update socket bound to %s" % (port))

    # put the socket into listening mode
    recv_primary_update_socket.listen(5)
    print("primary update socket is listening")

    # a forever loop until we interrupt it or
    # an error occurs
    while True:

        # Establish connection with osd
        c, addr = recv_primary_update_socket.accept()
        print('Got connection from', addr)

        # recv the update
        update = _recv_msg(c, 1024)
        print(update)

        if update["update_type"] == "hash_table":
            for i in range(len(update["pg_or_osd_ids_list"])):
                hashtable[update["pg_or_osd_ids_list"]
                          [i]] = update["osd_list"][i]
        else:
            for i in range(len(update["pg_or_osd_ids_list"])):
                cluster_topology[update["pg_or_osd_ids_list"]
                                 [i]] = update["osd_list"][i]

        hashtable_file = open('hashtable', 'wb')
        hashtable_dump = pickle.dumps(hashtable)
        hashtable_file.write(hashtable_dump)
        hashtable_file.close()

        cluster_topology_file = open('cluster_topology', 'wb')
        cluster_topology_dump = pickle.dumps(cluster_topology)
        cluster_topology_file.write(cluster_topology_dump)
        cluster_topology_file.close()
        msg = {"status": "SUCCESS"}
        _send_msg(c, msg)
        # send the acknowledgement
        c.close()

    recv_primary_update_socket.close()
    def dispatch_primary(self):
        while True:
            # Establish connection with client.
            print("waiting for messages..")
            c, addr = self.mds_socket.accept()

            print('Got connection from', addr)

            msg = {}

            try:
                msg = _recv_msg(c, MSG_SIZE)
            except Exception as e:
                print(e)
                c.close()
                continue

            res = {}
            print(msg)

            if msg["type"] == "CLIENT_LOGIN":
                res = self._login_handle(msg)
                print(res["msg"])

            elif msg["type"] == "CLIENT_LOGOUT":
                res = self._logout_handle(msg)
                print(res["msg"])

            elif msg["type"] == "WRITE_RESPONSE":
                res = self.update_handle(msg)
                print(res["msg"])

            elif msg["type"] == "WRITE_QUERY":
                res = self._client_query_handle(msg)
                print(res["msg"])

            elif msg["type"] == "RECOVERY":
                res = self._recovery_handle()
                print(res["msg"])

            try:
                _send_msg(c, res)
            except Exception as e:
                print(e)
            finally:
                c.close()
def send_heartbeat():
    #This will check for incoming messages
    #from other nodes and reply

    s = socket.socket()
    print("Socket successfully created for Heartbeat")
    port = storage_ip[STORAGE_ID]["port"]
    s.bind(('', port))
    print("Socket binded to %s" % (port))

    # put the socket into listening mode
    s.listen(5)

    while True:
        # Establish connection with client.
        c, addr = s.accept()
        print(f"\nGot connection from {addr}")

        n = os.fork()
        if n == 0:
            print(F"Inside child process {os.getpid()}")
            msg = _recv_msg(c, MSG_SIZE)
            print(msg)

            if msg == None:
                print(f"Didn't receive data from ip {addr}! [Timeout] ")
                report_monitor(addr, None)

            elif msg["type"] == "ALIVE":
                res = {"type": "ACK"}
                _send_msg(c, res)

            c.close()

            print(f"Exiting from pid {os.getpid()} ..\n\n")
            os._exit(1)
def replicate_pg(soc):
    # This will be always true loop that will run in parallel

    c, addr = soc.accept()
    print(f"Got connection from {addr} to do the replication")

    n = os.fork()

    if n == 0:
        msg = _recv_msg(c, MSG_SIZE)
        print(msg)

        if msg == None:
            print(f"Didn't receive data! [Timeout] {addr}")
            msg = {"type": "SEND AGAIN"}
            _send_msg(c, msg)

        elif msg["type"] == "REPLICATE":
            # Can do one thing here
            # call the func that act as access this pg_id for the client
            # then call other function that act as send this pg to osd to do a write
            pg_id = msg["pg_id"]
            osd_id = msg["osd_id"]

            file = open("./data/" + pg_id, 'rb')

            pg_b = file.read()
            pg = pickle.loads(pg_b)

            ## Connect to this osd_id with new socket
            new_soc = socket.socket()
            print(
                f"Socket created to send request to SAVE data at OSD {osd_id}")

            ip_add = storage_ip[osd_id]["ip"]
            port = storage_ip[osd_id]["port"] + 10
            # Remember replication is on normal port + 10

            try:
                new_soc.connect((ip_add, port))
                print(f"Connection made with {ip_add} on {port}")

                msg = {"type": "SAVE", "pg_id": pg_id, "pg": pg}
                _send_msg(new_soc, msg)
                print("Msg send to SAVE the data")

                msg = _wait_recv_msg(new_soc, MSG_SIZE)
                print("Msg received !")

            except Exception as e:
                print(e)

            if msg == None:
                res = {"type": "REPLICATION FAIL"}
                _send_msg(c, res)
                print("Fail Msg send to the monitor")

            elif msg["type"] == "ACK":
                res = {"type": "ACK"}
                _send_msg(c, res)
                print("Success Msg send to the monitor")

        elif msg["type"] == "SAVE":
            # This will take request from other osd to save some data
            # This is basic replication strategy
            pg_id = msg["pg_id"]
            pg = msg["pg"]

            try:
                file = open("./data/" + pg_id, 'wb')
                print("Replicated data is saved")

                pg_dump = pickle.dump(pg)
                file.write(pg_dump)

            except Exception as e:
                print(e)

            msg = {"type": "ACK"}
            _send_msg(c, msg)
            print("Write successful..send back Ack to the master osd")

        else:
            print("[ERROR] Check the code in replication")

        c.close()

        print(f"Exiting from pid {os.getpid()} ..")
        os._exit(1)
    def dispatch_backup(self):
        while True:
            # Establish connection with client.
            print("waiting for messages..")
            c, addr = self.mds_socket.accept()

            print('Got connection from', addr)

            msg = {}

            try:
                msg = _recv_msg(c, MSG_SIZE)
            except Exception as e:
                print(e)
                c.close()
                continue

            res = {"status": "", "msg": ""}
            print(msg)

            if msg["type"] == "UPD":
                if msg["update_type"] == "ADD_LOGIN_USER":
                    self.logged_in.append(msg["update"]["user"])
                    self._write_logged_in()
                    res["status"] = "SUCCESS"

                elif msg["update_type"] == "REMOVE_LOGIN_USER":
                    self.logged_in.remove(msg["update"]["user"])
                    self._write_logged_in()
                    res["status"] = "SUCCESS"

                elif msg["update_type"] == "WRITE_SUCCESS":
                    username = msg["update"]["user"]
                    tree = self._read_tree(username)

                    pg_id = msg["update"]["pg_id"]
                    direc = tree["processing"][pg_id][0]
                    file_id = tree["processing"][pg_id][1]
                    filename = tree["processing"][pg_id][2]

                    tree["dir_tree"][direc][file_id] = [filename, [pg_id]]
                    tree["processing"][pg_id][3] = 1
                    self._write_tree(username, tree)
                    res["status"] = "SUCCESS"

                elif msg["update_type"] == "UPDATE_PROCESSING":
                    username = msg["update"]["username"]
                    pg_written = msg["update"]["pg_written"]
                    pg_wait = msg["update"]["pg_wait"]

                    tree = self._read_tree(username)

                    for pg_id in pg_written:
                        tree["processing"].pop(pg_id)
                    for pg_id in pg_wait.keys():
                        tree["processing"][pg_id] = pg_wait[pg_id]

                    self._write_tree(username, tree)
                    res["status"] = "SUCCESS"

            elif msg["type"] == "RECOVERY":
                res = self._recovery_handle()
                print(res["msg"])

            else:
                res["status"] = "ERROR"
                res["msg"] = "msg type not define !"

            try:
                _send_msg(c, res)
            except Exception as e:
                print(e)
            finally:
                c.close()
Пример #8
0
def recv_client_reqs():
    global MY_OSD_ID

    recv_client_reqs_socket = socket.socket()
    print("client reqs socket successfully created")
    recv_client_reqs_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                       1)

    # reserve a port on your computer
    port = READ_WRITE_PORT

    # Next bind to the port
    # we have not entered any ip in the ip field
    # instead we have inputted an empty string
    # this makes the server listen to requests
    # coming from other computers on the network
    recv_client_reqs_socket.bind(('', port))
    print("write ack socket bound to %s" % (port))

    # put the socket into listening mode
    recv_client_reqs_socket.listen(5)
    print("socket is listening")

    # a forever loop until we interrupt it or
    # an error occurs
    while True:

        # Establish connection with client.
        c, addr = recv_client_reqs_socket.accept()
        print('Got connection from', addr)

        # recv the acknowledgement
        req = _recv_msg(c, 1024)
        print(req)

        if (req["type"] == "CLIENT_WRITE"):
            res = {"status": "RECEIVED", "msg": "data received"}
            _send_msg(c, res)

            client_id = req["client_id"]
            # client_addr = req["client_addr"]

            osd_dict = req["osd_dict"]

            for osd_id in osd_dict["osd_ids"]:
                if osd_id == MY_OSD_ID:
                    continue

                # sending write update to client
                write_forward_socket = socket.socket()
                print("write forward socket successfully created")

                write_forward_socket.connect(osd_dict["addrs"][osd_id])

                req["type"] = "OSD_WRITE"

                _send_msg(write_forward_socket, req)

                write_forward_socket.close()

            pg = req["pg"]
            file = open("./data/" + pg.pg_id, 'wb')

            pg_dump = pickle.dumps(pg)
            file.write(pg_dump)

            file.close()

            # sending write ack to monitor
            write_ack_socket = socket.socket()
            print("write forward socket successfully created")

            write_ack_socket.connect((MONITOR_IP, WRITE_ACK_PORT))
            ack = {}
            ack["client_id"] = client_id
            # ack["client_addr"] = client_addr # addr = (ip, port)
            ack["pg_id"] = pg.pg_id
            ack["free_space"] = FREESPACE - req["size"]
            ack["osd_id"] = MY_OSD_ID

            _send_msg(write_ack_socket, ack)

            write_ack_socket.close()

            # _send_msg(c, [pg.pg_id, "SUCCESS"])

        elif req["type"] == "OSD_WRITE":
            client_id = req["client_id"]
            # client_addr = req["client_addr"]

            pg = req["pg"]
            file = open("./data/" + pg.pg_id, 'wb')

            pg_dump = pickle.dumps(pg)
            file.write(pg_dump)

            file.close()

            # sending write ack to monitor
            write_ack_socket = socket.socket()
            print("write forward socket successfully created")

            write_ack_socket.connect((MONITOR_IP, WRITE_ACK_PORT))
            ack = {}
            ack["client_id"] = client_id
            # ack["client_addr"] = client_addr # addr = (ip, port)
            ack["pg_id"] = pg.pg_id
            ack["free_space"] = FREESPACE - sys.getsizeof(pg_dump)
            ack["osd_id"] = MY_OSD_ID

            _send_msg(write_ack_socket, ack)

            write_ack_socket.close()

        elif req["type"] == "READ":
            pg_id = req["pg_id"]
            file = open("./data/" + pg_id, 'rb')

            pg_b = file.read()
            pg = pickle.loads(pg_b)

            file.close()
            # print(pg)
            print("sending pg to client " + str(pg_id))
            msg = {"pg_id": pg.pg_id, "res": "SUCCESS", "pg": pg}

            _send_msg(c, msg)

        c.close()

        # print(msg)

    recv_client_reqs_socket.close()
def recv_write_acks():
    global hashtable, cluster_topology, MDS_IP, MDS_flags

    write_ack_socket = socket.socket()
    print ("write ack socket successfully created")
    write_ack_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # reserve a port on your computer
    port = WRITE_ACK_PORT

    # Next bind to the port
    # we have not entered any ip in the ip field
    # instead we have inputted an empty string
    # this makes the server listen to requests
    # coming from other computers on the network
    write_ack_socket.bind(('', port))
    print ("write ack socket bound to %s" %(port))

    # put the socket into listening mode
    write_ack_socket.listen(5)
    print ("socket is listening")

    # a forever loop until we interrupt it or
    # an error occurs
    while True:

        # Establish connection with osd
        c, addr = write_ack_socket.accept()
        print ('Got connection from', addr)

        # recv the acknowledgement
        ack = _recv_msg(c, 1024)
        print(ack)

        # extracting the written pd_id, free_space, osd_id of that osd
        client_id = ack["client_id"]
        # client_addr = ack["client_addr"]    # addr = (ip, port)
        pg_id = ack["pg_id"]
        free_space = ack["free_space"]
        osd_id = ack["osd_id"]

        # if the osd is down or out, make it up again
        # [need to check this]
        if cluster_topology[osd_id]["status"] != 0:
            cluster_topology[osd_id]["status"] = 0
        
        # updating the write status of the osd to 1
        for i in range(len(hashtable[pg_id])):
            if hashtable[pg_id][i][0] == osd_id:
                hashtable[pg_id][i][1] = 1
        
        replication_factor = 0
        # adding the new friend
        for osd in hashtable[pg_id]:
            if osd[0] != osd_id:
                if osd[1] == 1:
                    replication_factor += 1
                    cluster_topology[osd_id]["friends"].add(osd[0])
                    cluster_topology[osd[0]]["friends"].add(osd_id)

        cluster_topology[osd_id]["free_space"] = free_space

        if isPrimary:
            # updating the backup        
            update_backup_monitor("hash_table", [pg_id], [hashtable[pg_id]])
            update_backup_monitor("cluster_topology", [osd[0] for osd in hashtable[pg_id]], \
                                [cluster_topology[osd[0]] for osd in hashtable[pg_id]])

        hashtable_file = open('hashtable', 'wb')
        cluster_topology_file = open('cluster_topology', 'wb')
        
        hashtable_dump = pickle.dumps(hashtable)
        hashtable_file.write(hashtable_dump)
        hashtable_file.close()

        cluster_topology_dump = pickle.dumps(cluster_topology)
        cluster_topology_file.write(cluster_topology_dump)
        cluster_topology_file.close()

        if replication_factor > 1:
            # # sending write update to client
            # client_update = socket.socket()
            # print ("client write ack socket successfully created")
            
            # client_update.connect(client_addr)

            # msg = {"type": "WRITE_RESPONSE", "PG_ID": pg_id, \
            #        "status": "SUCCESS", "message": "write successful",\
            #        "client_id": client_id} 

            # _send_msg(client_update, msg)

            # client_update.close()

            # sending write update to MDS
            MDS_update_socket = socket.socket()
            print ("MDS write ack socket successfully created")

            MDS_update_socket.connect((MDS_IP, MDS_PORT))

            msg = {"type": "WRITE_RESPONSE", "PG_ID": pg_id, \
                   "status": "SUCCESS", "message": "write successful",\
                   "client_id": client_id} 

            _send_msg(MDS_update_socket, msg)

            MDS_ack = _wait_recv_msg(MDS_update_socket, 1024)
            pg_id = MDS_ack["pg_id"]
            if MDS_ack["status"] == "SUCCESS":
                print("Write successful")
                MDS_flags[pg_id] = 0
            else:
                print("Write error from MDS")
                print(MDS_ack["msg"])
                MDS_flags[pg_id] = 1
                ## resend pgs in MDS_flags with flag = 1
                ## start that loop here

            MDS_update_socket.close()

        error = ""
        status = "SUCCESS"

        # send success
        _send_msg(c, {"error":error, "status":status})

        c.close()

    write_ack_socket.close()
def recv_client_reqs():
    global cluster_topology, hashtable

    recv_client_reqs_socket = socket.socket()
    print ("client req listener socket successfully created")
    recv_client_reqs_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # reserve a port on your computer
    port = CLIENT_REQ_PORT

    # Next bind to the port
    # we have not entered any ip in the ip field
    # instead we have inputted an empty string
    # this makes the server listen to requests
    # coming from other computers on the network
    recv_client_reqs_socket.bind(('', port))
    print ("client req listener socket bound to %s" %(port))

    # put the socket into listening mode
    recv_client_reqs_socket.listen(5)
    print ("client req listener socket is listening")

    # a forever loop until we interrupt it or
    # an error occurs
    while True:

        # Establish connection with client.
        c, addr = recv_client_reqs_socket.accept()
        print ('Got connection from', addr)
        
        # recv the pg_id, size
        req = _recv_msg(c, 1024)

        if(req["type"] == "WRITE"):
            pg_id = req["pg_id"]
            size = req["size"]
            print(size)
            hashtable[pg_id] = []

            i = 0
            for osd_id in cluster_topology:
                if cluster_topology[osd_id]["free_space"] > size and cluster_topology[osd_id]["status"] == 0:
                    hashtable[pg_id].append([osd_id, 0])
                    i = i+1

                if(i>2):
                    break
            
            if i < 3:
                print("less than two osds are free/alive")
                response = {"status":"ERROR", "msg": "sufficent storage not available"}
                _send_msg(c, response)
                c.close()
                continue

                
            osd_ids = [osd[0] for osd in hashtable[pg_id]]
            
            addrs = {}
            for osd_id in osd_ids:
                addrs[osd_id] = (cluster_topology[osd_id]["ip"], cluster_topology[osd_id]["port"])
            osd_dict = {"osd_ids": osd_ids, "addrs": addrs}
            response = {"osd_dict": osd_dict, "status":"SUCCESS", "msg": "written succefully"}
            if isPrimary:
                # updating the backup(only hash_table)
                update_backup_monitor("hash_table", [pg_id], [hashtable[pg_id]])

            hashtable_file = open('hashtable', 'wb')
            hashtable_dump = pickle.dumps(hashtable)
            hashtable_file.write(hashtable_dump)
            hashtable_file.close()

            _send_msg(c, response)

        elif req["type"] == "READ":
            pg_id = req["pg_id"]
            osd_ids = [hashtable[pg_id][i][0] for i in range(3)]
            addrs = [(cluster_topology[osd_id]["ip"], cluster_topology[osd_id]["port"]) \
                            for osd_id in osd_ids]
            osds_dict = {"osd_ids": osd_ids, "addrs": addrs}
            _send_msg(c, osds_dict)

        c.close()

    recv_client_reqs_socket.close()