Beispiel #1
0
def read_file(fn, metadata_stub, block_stub):
    # Read the file first
    fileinfo = metadata_stub.ReadFile(SurfStoreBasic_pb2.FileInfo(filename=fn))
    print("ReadFile rpc call returned successfully\n")
    print(fileinfo.version)

    # Check if the file exist in Store
    if fileinfo.version == 0:
        print("File " + fn + " does not exist in SurfStore")
    else:
        f = open(fn + "1", "w+")
        # Download the blocks from BlockStore
        print(fileinfo.blocklist)
        for hashes in fileinfo.blocklist:
            blk = block_stub.GetBlock(SurfStoreBasic_pb2.Block(hash=hashes))
            print(blk)
            print("GetBlock rpc call returned successfully\n")
            f.write(blockToString(blk))
        # Create and write the file
        f.close()
        print("File has been downloaded and created\n")
Beispiel #2
0
    def two_phase_commit(self, cmd, file_info):
        # leader log locally
        log = [cmd, file_info.filename, file_info.version, file_info.blocklist]
        self.logs.append(log)
        votes = 0
        # 1st phase of 2PC
        for i in range(len(self.mstub_list)):
            result = self.mstub_list[i][1].Vote(SurfStoreBasic_pb2.Empty())
            if result.answer == True:
                votes += 1
            else:
                if i not in self.crashed_followers:
                    self.crashed_followers.append(i)
        # 2nd phase of 2PC
        if votes >= 1. * len(self.mstub_list) / 2:
            for i in range(len(self.mstub_list)):
                if i in self.crashed_followers:
                    continue
                rpc_log = SurfStoreBasic_pb2.Log(cmd=log[0],
                                                 filename=log[1],
                                                 version=log[2],
                                                 blocklist=log[3])
                self.mstub_list[i][1].Commit(rpc_log)
            return True
        else:
            # piazza says if we don't get majority vote, we just hang on there
            # though it seems like TA won't actually test on it
            self.logs.pop()
            # check whether crashed server is up
            while (len(self.crashed_followers) >
                   1. * len(self.mstub_list) / 2):
                for i in self.crashed_followers:
                    result = self.mstub_list[i][1].Vote(
                        SurfStoreBasic_pb2.Empty())
                    if result.answer == True:
                        self.crashed_followers.remove(i)

            # call the function again, now we should be good to go
            self.two_phase_commit(cmd, file_info)
            return False
Beispiel #3
0
def _ping(serverID, config):
    if serverID > config.num_metadata_servers:
        print("the specified server was not born")
        return
    channel = grpc.insecure_channel('localhost:%d' %
                                    config.metadata_ports[serverID])
    stub = SurfStoreBasic_pb2_grpc.MetadataStoreStub(channel)
    try:
        stub.Ping(SurfStoreBasic_pb2.Empty())
    except:
        print("can't ping server #%d" % serverID)
        return
    print("ping server #%d successfully" % serverID)
Beispiel #4
0
def test_blockserver(mstub, bstub):
    b1 = SurfStoreBasic_pb2.Block(hash=sha256('block_01'), data='block_01')
    b2 = SurfStoreBasic_pb2.Block(hash=sha256('block_02'), data='block_02')

    assert bstub.HasBlock(b1).answer == False
    assert bstub.HasBlock(b2).answer == False

    bstub.StoreBlock(b1)
    assert bstub.HasBlock(b1).answer == True

    bstub.StoreBlock(b2)
    assert bstub.HasBlock(b2).answer == True

    b1_prime = bstub.GetBlock(b1)
    assert b1_prime.hash == b1.hash
    assert b1_prime.data == b1.data

    b2_prime = bstub.GetBlock(b2)
    assert b2_prime.hash == b2.hash
    assert b2_prime.data == b2.data

    return 'test_blockserver == PASS'
    def TwoPhaseCommit(self):
        """ Helper Function to carry out 2-Phase Commit with follower server

        Allows for a command to be processed if the majority (qty: 1) of the follower servers are online, if not, then 
        this Two-Phase Commit process will block untul the majority are onlne

        Args:
            None

        Return:
            None
        """
        f1_response = False
        f2_response = False
        while (f1_response == False) and (f2_response == False):
            response1_future = self.follower_stubs[0].Prepare.future(
                SurfStoreBasic_pb2.Empty())
            response1 = response1_future.result()
            if response1:
                if response1.server_crashed == False:
                    f1_response = response1.answer
            response2_future = self.follower_stubs[1].Prepare.future(
                SurfStoreBasic_pb2.Empty())
            response2 = response2_future.result()
            if response2:
                if response2.server_crashed == False:
                    f2_response = response2.answer
        resp1 = self.follower_stubs[0].Commit(
            self.logs[self.currentCommandIndex])
        if resp1.server_crashed == True:
            self.follower1_missedLogs.append(
                self.logs[self.currentCommandIndex])
        resp2 = self.follower_stubs[1].Commit(
            self.logs[self.currentCommandIndex])
        if resp1.server_crashed == True:
            self.follower1_missedLogs.append(
                self.logs[self.currentCommandIndex])
        self.currentCommandIndex += 1
    def Crash(self, request, context):
        """ Crash RPC Function

        RPC Function used to emulate a "crashed" server state (only Follower Metadata Server will crash)

        Args:
            request (Empty): Empty RPC Message

        Return:
             Empty: Empty RPC Message
        """
        self.isCrashed = True
        print("Now in crashed state...\n")
        return SurfStoreBasic_pb2.Empty()
Beispiel #7
0
def _delete(mstub, bstub, filename, ver):
    # create the fileinfo message to send to metadata
    file_info = mstub.ReadFile(SurfStoreBasic_pb2.FileInfo(filename=filename))

    file_info.version = ver

    result = mstub.DeleteFile(file_info).result

    if result == 0:
        print("Deleted file successfully!")
    elif result == 1:
        print("Delete unsuccessful, old version")
    elif result == 3:
        print("Delete unsuccessful, the server is not leader")
    def Restore(self, request, context):
        """ Restore RPC Function

        RPC Function used to restore a follower Metadata Server from its emulated "crashed" state

        Args:
            request (Empty): Empty RPC Message

        Return:
             Empty: Empty RPC Message
        """
        print("Restoring from crashed state...\n")
        self.isCrashed = False
        return SurfStoreBasic_pb2.Empty()
Beispiel #9
0
    def Update(self, request, context):
        if self.crashed:
            return SurfStoreBasic_pb2.SimpleAnswer(answer=False)
        # convert grpc format to python list
        leaderLogs = []
        for entry in request.allLogs:
            log = (entry.cmd, entry.filename, entry.version, entry.blocklist)
            leaderLogs.append(log)
        myLogSize, leaderLogSize = len(self.logs), len(leaderLogs)
        if myLogSize != leaderLogSize:
            for i in range(myLogSize, leaderLogSize):
                missedLog = leaderLogs[i]

                # update the file map
                if missedLog[0] == "mod":
                    self.files[missedLog[1]] = (missedLog[2], missedLog[3],
                                                False)
                if missedLog[0] == "del":
                    self.files[missedLog[1]] = (missedLog[2], ['0'], True)
                # append the missed log
                self.logs.append(missedLog)

        return SurfStoreBasic_pb2.SimpleAnswer(answer=True)
Beispiel #10
0
def store_to_bs_test_init(mstub, bstub, mb):
    for req in mb.keys():
        to_add = SurfStoreBasic_pb2.Block(hash=req, data=mb[req])
        assert not bstub.HasBlock(to_add).answer
        bstub.StoreBlock(to_add)

    for req in mb.keys():
        to_add = SurfStoreBasic_pb2.Block(hash=req)
        assert bstub.HasBlock(to_add).answer
        assert bstub.GetBlock(to_add).data == mb[req]

    for req in mb.keys():
        to_add = SurfStoreBasic_pb2.Block(hash='')
        assert not bstub.HasBlock(to_add).answer
        assert bstub.GetBlock(to_add).data == ''
        assert bstub.GetBlock(to_add).hash == ''

    for req in mb.keys():
        to_add = SurfStoreBasic_pb2.Block(hash=req + 'z')
        assert not bstub.HasBlock(to_add).answer
        assert bstub.GetBlock(to_add).data == ''
        assert bstub.GetBlock(to_add).hash == ''

    return 'store_to_bs_test_init == PASS'
Beispiel #11
0
def _modify(mstub, bstub, filename, ver):
    # Get the current file info if it exists
    file_info = mstub.ReadFile(SurfStoreBasic_pb2.FileInfo(filename=filename))
    remote_ver = file_info.version
    if remote_ver == 0:
        print("FAILED, file doesn't exit")
        return
    if ver != remote_ver + 1:
        print("File version incorrect w/ remote version #" +
              str(file_info.version))
        return
    # we shouldn't be reusing _create here, because it modifies file only if it didn't exist or was deleted, while _modify needs to modify file that alredy exists so it might be better to have a helper function
    # Set the request version
    file_info.version = ver

    modifyFile(file_info, mstub, bstub)
Beispiel #12
0
def modifyFile(file_info, mstub, bstub):
    filename = file_info.filename
    # Get the list of hashes
    hash_block_tups = create_blocklist(filename)

    # If this returns None, then the file is not in this directory
    if hash_block_tups == None:
        print("Filename: " + filename + ", does not exist!")
        return

    file_info.blocklist[:] = [x[0] for x in hash_block_tups]  # List of hashes

    result = mstub.ModifyFile(file_info)

    if result.result == 2:  # MISSING_BLOCKS
        block_map = dict(hash_block_tups)

        for req in result.missing_blocks:
            try:
                to_add = SurfStoreBasic_pb2.Block(hash=req,
                                                  data=block_map[req])
                bstub.StoreBlock(to_add)
            except Exception:
                print(
                    "Error during file storage, please check the blockstore connection."
                )
                break

        # the indent here was probably not needed
        updated_result = mstub.ModifyFile(file_info)

        if updated_result.result == 0:  # OK
            print("Upload successful!")
        else:
            print("Upload not successful :(")

    elif result.result == 1:  # OLD_VERSION
        print("FAILED, version incorrect")

    elif result.result == 3:
        print("FAILED the server is not leader")

    elif result.result == 0:  # OK
        print(
            "Did not update anything, but result == OK so the data probably already existed"
        )
    def createLogFromCommand(self, request, command):
        """ Helper Log Creation Function

        Creates a log from a FileInfo object and adds this log to our collection

        Args:
            request (FileInfo): FileInfo object for a command
            command (int): Command Enum referencing type of command

        Return:
            None
        """
        log_builder = SurfStoreBasic_pb2.LogEntry()
        log_builder.file_info.CopyFrom(request)
        log_builder.index = self.currentCommandIndex
        log_builder.command = command
        self.addEntryToLog(log_builder)
    def StoreBlock(self, request, context):
        """ StoreBlock RPC Function

        Stores a block in myBlockStore dictionary, referenced by its hash

        Args:
            request (Block): Block RPC Message, contains a hash and the data

        Return:
            Empty: Empty RPC Message
        """
        lock = threading.Lock()
        lock.acquire()
        try:
            self.myBlockStore[request.hash] = request.data.decode()
        finally:
            lock.release()
        return SurfStoreBasic_pb2.Empty()
    def Prepare(self, request, context):
        """ Prepare RPC Function

        RPC needed for part one of 2-Phase Commit
        
        Args:
            request (Empty): Empty Object

        Return:
            SimpleAnswer: SimpleAnswer RPC Message
        """
        builder = SurfStoreBasic_pb2.SimpleAnswer()
        if self.isCrashed == False:
            builder.answer = True
            builder.server_crashed = False
        else:
            builder.server_crashed = True
        return builder
    def IsCrashed(self, request, context):
        """ IsCrashed RPC Function

        RPC Function used to determine if a Metadata Server is in an emulated "crashed" state or not
        
        Args:
            request (Empty): Empty Object

        Return:
            SimpleAnswer: True if crashed, false otherwise
        """
        builder = SurfStoreBasic_pb2.SimpleAnswer()
        if self.isCrashed == True:
            builder.answer = True
            builder.server_crashed = True
        else:
            builder.answer = False
            builder.server_crashed = False
        return builder
    def GetBlock(self, request, context):
        """ GetBlock RPC Function

        Returns a block from the myBlockStore dictionary, referenced by its hash

        Args:
            request (Block): Block RPC Message, contains a hash for which the data needs to be returned for

        Return:
            Block: BLock RPC Message containing data, and hash
        """
        builder = SurfStoreBasic_pb2.Block()
        try:
            data = self.myBlockStore[request.hash]
            builder.data = data.encode()
            builder.hash = request.hash
        except:
            print("No mapping found for hash", request.hash)
        return builder
Beispiel #18
0
    def ModifyFile(self, file_info, context):
        # Use this to return the result, assume MISSING_BLOCKS
        mod_result = SurfStoreBasic_pb2.WriteResult(result=2)

        if not self.leader:
            mod_result.result = 3
            return mod_result

        file_tup = None

        # Check if the file already exists in the metadata record
        if file_info.filename in self.files:
            file_tup = self.files[file_info.filename]
            mod_result.current_version = file_tup[_VERS]
        else:
            file_tup = (0, file_info.blocklist, False)

        # The case where the new vers is not current version + 1
        if file_info.version != (file_tup[_VERS] + 1):
            mod_result.result = 1  # OLD_VERSION
        # The case where the file exists and the next vers num is correct
        else:
            ###################
            # 2PC
            if self.distributed:
                if self.leader:
                    self.two_phase_commit("mod", file_info)
            ###################

            self.check_blockstore_connection()
            # Used to maintain a list of missing blocks in the blockstore
            missing_blocks = self.get_missing_blocks(file_info)
            mod_result.missing_blocks[:] = missing_blocks

            if len(missing_blocks) == 0:
                mod_result.result = 0  # OK

        if mod_result.result == 0:  # OK
            mod_result.current_version = file_info.version
            self.files[file_info.filename] = \
                (file_info.version,file_info.blocklist,False)

        return mod_result
    def HasBlock(self, request, context):
        """ Hash RPC Function

        Returns a block identified by a hash exists in myBlockStore

        Args:
            request (Block): Block RPC Message, contains a hash for which we're checking if it exists or not

        Return:
            SimpleAnswer: True if exists, false otherwise
        """
        builder = SurfStoreBasic_pb2.SimpleAnswer()
        try:
            if request.hash in self.myBlockStore.keys():
                builder.answer = True
            else:
                builder.answer = False
        except:
            print("No mapping found for hash", request.hash)
        return builder
Beispiel #20
0
def delete_file(fn, metadata_stub, block_stub):
    # Read the file first
    fileinfo = metadata_stub.ReadFile(SurfStoreBasic_pb2.FileInfo(filename=fn))
    print("ReadFile rpc call returned successfully\n")

    # Check if the file exist in Store
    if fileinfo.version == 0:
        print("File " + fn + " does not exist in SurfStore")

    else:
        # Calling DeleteFile RPC
        fileinfo.version += 1
        writeRes = metadata_stub.DeleteFile(fileinfo)
        print("DeleteFile rpc call returned successfully\n")

    if writeRes.result == SurfStoreBasic_pb2.WriteResult.NOT_LEADER:
        print("The metadata_stub server been called is not the leader\n")
    elif writeRes.result == SurfStoreBasic_pb2.WriteResult.OK:
        print("Delete the file successfully\n")

    return None
    def IsLeader(self, request, context):
        """ IsLeader RPC Function

        RPC Function used to determine if a Metadata Server is a leader or not
        
        Args:
            request (Empty): Empty Object

        Return:
            SimpleAnswer: True if leader, false otherwise
        """
        builder = SurfStoreBasic_pb2.SimpleAnswer()
        if self.isCrashed != True:
            if self.isLeader == True:
                builder.answer = True
            else:
                builder.answer = 0
            builder.isCrashed = False
        else:
            builder.isCrashed = True
        return builder
Beispiel #22
0
def modify_file_initial_test(mstub, bstub):
    file_info = SurfStoreBasic_pb2.FileInfo(filename='testfiles/code',
                                            version=0,
                                            blocklist=[])

    result = mstub.ReadFile(file_info)

    missing_blocks = create_blocklist(file_info.filename)
    file_info.blocklist[:] = missing_blocks.keys()
    write_result = mstub.ModifyFile(file_info)

    assert write_result.result == 1  #OLD_VERSION

    file_info.version = 1
    write_result = mstub.ModifyFile(file_info)

    assert write_result.result == 2  #MISSING_BLOCKS
    assert write_result.current_version == 0
    assert sorted(write_result.missing_blocks) == sorted(missing_blocks.keys())

    return ('modify_file_initial_test == PASS', missing_blocks)
    def ReadFile(self, request, context):
        """ ReadFile RPC Function

        ReadFile Command 
        
        Args:
            request (FileInfo): Contains filename for which to return version and blocklist for

        Return:
            FileInfo: Returns a FileInfo object with version and blocklist appropriately set
        """
        builder = SurfStoreBasic_pb2.FileInfo()
        if request.filename in self.myMetaDataStore.keys():
            print("Mapping found for: %s\n" % request.filename)
            (version, blocklist) = self.myMetaDataStore[request.filename]
            builder.filename = request.filename
            builder.version = self.myMetaDataStore[request.filename][0]
            for hashVal in self.myMetaDataStore[request.filename][1]:
                builder.blocklist.append(hashVal)
            if self.isLeader == True:
                self.createLogFromCommand(request, 0)
                resp1 = self.follower_stubs[0].Commit(
                    self.logs[self.currentCommandIndex])
                if resp1.server_crashed == True:
                    self.follower1_missedLogs.append(
                        self.logs[self.currentCommandIndex])
                resp2 = self.follower_stubs[1].Commit(
                    self.logs[self.currentCommandIndex])
                if resp1.server_crashed == True:
                    self.follower1_missedLogs.append(
                        self.logs[self.currentCommandIndex])
                self.currentCommandIndex += 1
        else:
            print("No mapping found for: %s" % request.filename)
            self.myMetaDataStore[request.filename] = (0, [])
            builder.filename = request.filename
            builder.version = 0
        return builder
Beispiel #24
0
def _create(mstub, bstub, filename, ver):
    # Get the current file info if it exists
    file_info = mstub.ReadFile(SurfStoreBasic_pb2.FileInfo(filename=filename))

    # Create can only be used if the file never exist or was deleted, else use _modify
    # If was deleted
    if file_info.version != 0:
        remote_ver = file_info.version
        # Fail if file currently exists
        if file_info.blocklist[
                0] != '0':  #deleted file has a hashlist with a single hash value of '0'
            print("File already exists w/ version #" + str(file_info.version))
            return
        # Fail if file version which user provided is smaller than v+1
        if ver != remote_ver + 1:
            print("File version incorrect w/ remote version #" +
                  str(file_info.version))
            return

    # Set the request version
    file_info.version = ver

    modifyFile(file_info, mstub, bstub)
    def AppendEntries(self, request, context):
        """ AppendEntries RPC Function

        Used by Leader MetadataStore Server to sync missing logs when a follower was down
        
        Args:
            request (LogEntry): Missing Log Entry

        Return:
            LogEntries: LogEntries RPC Message
        """
        builder = SurfStoreBasic_pb2.SimpleAnswer()
        if self.isCrashed == True:
            builder.server_crashed = True
        else:
            for missedLog in request.log_entries:
                print(
                    "Appending Log:\nFilename: %s\nVersion: %d\nCommand: %d\n"
                    % (missedLog.file_info.filename,
                       missedLog.file_info.version, missedLog.command))
                self.updateMetadataStoreFromLog(missedLog)
            builder.answer = True
        return builder
    def DeleteFile(self, request, context):
        """ DeleteFile RPC Function

        ModifyFile Command 
        
        Args:
            request (FileInfo): Contains filename to delete blocklist for in myMetadataStore, granted correct versions was supplied

        Return:
            WriteResult: WriteResult RPC Message that indicates success or failure of this operation
        """
        builder = SurfStoreBasic_pb2.WriteResult()
        lock = threading.Lock()
        lock.acquire()
        try:
            if self.isLeader == True:
                if request.filename in self.myMetaDataStore.keys():
                    if request.version == (
                            self.myMetaDataStore[request.filename][0] + 1):
                        self.myMetaDataStore[request.filename] = (
                            request.version, ["0"])
                        builder.current_version = request.version
                        builder.result = 0
                        self.createLogFromCommand(request, 2)
                        self.TwoPhaseCommit()
                    else:
                        builder.current_version = self.myMetaDataStore[
                            request.filename][0]
                        builder.result = 1
                else:
                    print("No mapping found for filename", request.filename)
                return builder
            else:
                builder.result = 3
        finally:
            lock.release()
        return builder
Beispiel #27
0
 def IsCrashed(self, request, context):
     if self.crashed == True:
         return SurfStoreBasic_pb2.SimpleAnswer(answer=True)
     else:
         return SurfStoreBasic_pb2.SimpleAnswer(answer=False)
Beispiel #28
0
 def Restore(self, request, context):
     self.crashed = False
     return SurfStoreBasic_pb2.Empty()
Beispiel #29
0
 def Crash(self, request, context):
     # only non-leader replica can be crashed
     if self.leader == False:
         self.crashed = True
     return SurfStoreBasic_pb2.Empty()
Beispiel #30
0
 def IsLeader(self, request, context):
     if self.leader == True:
         return SurfStoreBasic_pb2.SimpleAnswer(answer=True)
     else:
         return SurfStoreBasic_pb2.SimpleAnswer(answer=False)