def read_file_from_server(file_name, cache):
    # 1 - Check the DS, see if the file exist; get file id and file server id, and version
    response_from_directory_server = requests.get(
        Sff.create_url(DIRECTORY_SERVER_DETAILS[0],
                       DIRECTORY_SERVER_DETAILS[1]),
        params={'file_name': file_name},
        json={'client_id': cache.client_id})
    not_locked = response_from_directory_server.json()['lock']
    file_server_id = response_from_directory_server.json()['file_server_id']
    print not_locked
    if not_locked and file_server_id is not None:
        file_to_read = "Cache{}/".format(cache.client_id) + file_name + '.txt'
        file_name += '.txt'
        print 'file name client has requested {}'.format(file_name)

        file_id, file_server_id, version, file_server_details = Sff.get_file_details_from_DS(
            response_from_directory_server)

        # update cache if (1) The file is not in the cache (2) the copy in the cache is out of date
        if cache.get_key_to_file(
                file_name) is None or version > cache.get_version_of_file(
                    file_name):
            # getting file details
            Sff.print_file_details(file_name, file_id, file_server_id, version)

            # check and see if the file details are up to date - if they are ignore, else update cache
            if file_server_details is not None and file_id is not None:
                response_from_directory_server = requests.get(
                    Sff.create_url(file_server_details[0],
                                   file_server_details[1]),
                    params={
                        'file_id': file_id,
                        'file_server_id': file_server_id
                    })
                # update cache
                print "Updating data in the cache..."
                data = response_from_directory_server.json()['file_str']
                print data
                cache.update_data_in_cache(file_to_read, data)

        if not os.path.exists(file_to_read):
            print "ERROR: file {} does not exists in cache or on the server....\n Please enter a" \
                  " valid file name or create a new file...\n".format(file_name)
            return

        open_file = open(file_to_read, 'r')
        dat = open_file.read()
        open_file.close()

        open_text_editor(file_to_read)
        data_to_cache = open(file_to_read, 'r').read()
        if dat is not data_to_cache:  # if the data in the file is updated, update the data in the cache, else continue
            print "adding data to the cache\nLocation {}".format(file_name)
            cache.add_cache_entry(file_name,
                                  cache.set_version_of_file(file_name),
                                  data_to_cache)
    else:
        print "file is locked come back later..."
    def post(self):
        file_name = self.parser.parse_args()['file_name']
        file_id, file_server_details, file_server_id, version = get_file_details_if_exist(
            file_name)
        if file_name in LIST_OF_ALL_FILES_BY_NAME:
            return {
                'file_id': file_id,
                'file_server_id': file_server_details,
                'message': False,
                'version': version
            }
        print "creating a file..."

        file_id = len(LIST_OF_ALL_FILES_BY_NAME)
        file_server_id = find_least_loaded_file_server()
        LIST_OF_FILE_VERSIONS[file_name] = version
        LIST_OF_ALL_FILES_BY_NAME[file_name] = (file_id, file_server_id)
        ip = ONLINE_FILE_SERVERS[file_server_id][0]
        port = ONLINE_FILE_SERVERS[file_server_id][1]

        response = requests.post(SFL.create_url(ip, port, 'create_new_file'),
                                 json={
                                     'file_id': file_id,
                                     'file_name': file_name,
                                     'data': '',
                                     'server_id': file_server_id
                                 })
        print response.json()
        # return Y to let client now file is created
        return {
            'file_id': file_id,
            'file_server_id': file_server_id,
            'message': True,
            'server_details': ONLINE_FILE_SERVERS[file_server_id]
        }
    def get(self):
        file_id = self.parser.parse_args()['file_id']
        file_server_id = self.parser.parse_args()['file_server_id']
        file_name = 'Server' + str(
            file_server_id) + '/' + SFL.cast_file_id_to_file_name(file_id)
        print file_name

        with open(file_name, 'r') as read_from_file:
            file_str = read_from_file.read()
            print file_str
        return {'file_str': file_str}
    def get(self):
        file_name = self.parser.parse_args()['file_name']
        client_id = request.get_json()['client_id']
        print 'file name:' + file_name
        file_id, file_server_details, file_server_id, version = get_file_details_if_exist(
            file_name)

        resp = requests.post(SFL.create_url(LOCKING_SERVER_DETAILS[0],
                                            LOCKING_SERVER_DETAILS[1]),
                             json={
                                 'client_id': client_id,
                                 'file_id': file_id,
                                 'file_server_id': file_server_id
                             })
        foo = {'lock': resp.json()['lock']}
        print foo
        requests.post(SFL.create_url(LOCKING_SERVER_DETAILS[0],
                                     LOCKING_SERVER_DETAILS[1]),
                      json={
                          'client_id': client_id,
                          'file_id': file_id,
                          'file_server_id': file_server_id
                      })
        print foo
        if not resp.json()['lock']:
            return {
                'file_id': None,
                'file_server_details': None,
                'file_server_id': None,
                'version': None,
                'lock': foo
            }
        return {
            'file_id': file_id,
            'file_server_details': file_server_details,
            'file_server_id': file_server_id,
            'version': version,
            'lock': foo
        }
def get_client_num():
    try:
        path = os.getcwd()
        response_from_create_client_id = requests.get(Sff.create_url(
            DIRECTORY_SERVER_DETAILS[0], DIRECTORY_SERVER_DETAILS[1],
            'create_new_client'),
                                                      json={
                                                          'client_id': 'Y',
                                                          'path': path
                                                      })
        if response_from_create_client_id is not None:
            return response_from_create_client_id.json()['client_id']
    except Exception as e:
        print "ERROR: error occured when getting client id\n{}".format(
            e.message)
 def delete(self):
     global LOCK_SERVER_ON
     message_to_locking_server = request.get_json()
     client_id = message_to_locking_server['client_id']
     file_id = message_to_locking_server['file_id']
     file_server_id = message_to_locking_server['file_server_id']
     if LOCK_SERVER_ON is True:
         resp = requests.delete(SFL.create_url(LOCKING_SERVER_DETAILS[0],
                                               LOCKING_SERVER_DETAILS[1]),
                                json={
                                    'client_id': client_id,
                                    'file_id': file_id,
                                    'file_server_id': file_server_id
                                })
         return {'lock': resp.json()['lock']}
     else:
         return {'lock': False, 'message': "Lock Server is not online"}
def create_new_file(file_name, cache):
    try:
        print "Creating a new file {0} for the client{1}\n".format(
            file_name, cache.client_id)
        response = requests.post(Sff.create_url(DIRECTORY_SERVER_DETAILS[0],
                                                DIRECTORY_SERVER_DETAILS[1]),
                                 params={'file_name': file_name},
                                 json={'client_id': cache.client_id})
        open_file = open(file_name + '.txt', 'w')
        open_file.write("First Time file is opened.... Edit me!")
        open_file.close()
        if response.json()['message'] is True:
            print "file {0} has been created for client{1}".format(
                file_name, cache.client_id)

    except Exception as e:
        print "ERROR: occurred when creating a new file\n{}".format(e.message)
    def post(self):
        file_id = request.get_json()['file_id']
        file_name = request.get_json()['file_name']
        file_server_id = request.get_json()['server_id']
        print "file_id: " + str(file_id)
        edits_to_file = request.get_json()['data']
        print "edits: " + edits_to_file
        file_name = 'Server' + str(
            file_server_id) + '/' + SFL.cast_file_id_to_file_name(file_id)
        print "file name: " + file_name
        f = open(file_name, 'w')
        f.close()
        f.close()

        with open(file_name, 'r+') as edit_file:
            edit_file.write(edits_to_file)
            print "adding {} to the file...".format(edits_to_file)
            edit_file.close()
            final_edit = open(file_name, 'r').read()
        if os.path.exists(file_name):
            return {'file': True, 'final_edit': final_edit}
        else:
            return {'file': False}
def verify_file_exists(file_name, cache):
    try:
        response_from_directory_server = requests.get(
            Sff.create_url(DIRECTORY_SERVER_DETAILS[0],
                           DIRECTORY_SERVER_DETAILS[1]),
            params={'file_name': file_name},
            json={'client_id': cache.client_id})
        file_server_details = response_from_directory_server.json(
        )['file_server_details']
        file_id = response_from_directory_server.json()['file_id']

        if file_server_details is not None:
            print "file {0} requested by client {1} is on the file server: 'http://{2}:{3}\nAnd has id:{4}\n". \
                format(file_name, cache.client_id, file_server_details[0], file_server_details[1], file_id)
        elif cache.get_key_to_file(file_name) is not None:
            print "file {0} requested by client {1} is in your cache\n". \
                format(file_name, cache.client_id)
        else:
            print "The file {0} requested by client{1} does not exist on any of our servers...\n". \
                format(file_name, cache.client_id)
        return file_server_details, file_id
    except Exception as e:
        print "ERROR: occurred when verifying if file exists\n{}".format(
            e.message)

api.add_resource(FileServer, '/')
api.add_resource(CreateNewFile, '/create_new_file')

if __name__ == '__main__':
    print "'hello world' said the file server"
    print "sys[1]: {}".format(str(sys.argv[1]))
    print "sys[2]: {}".format(str(sys.argv[2]))

    if len(sys.argv) == 3:
        print "registering the file server at 'http://{}:{} with the directory server...".format(
            str(sys.argv[1]), str(sys.argv[2]))
        path = os.getcwd()
        response = requests.post(SFL.create_url(DIRECTORY_SERVER_DETAILS[0],
                                                DIRECTORY_SERVER_DETAILS[1],
                                                "create_new_file_server"),
                                 json={
                                     'new_file_server_ip_address': sys.argv[1],
                                     "new_file_server_port_number":
                                     sys.argv[2],
                                     'path': path
                                 })
        print "registered the file server at 'http://{}:{} with the directory server...".format(
            str(sys.argv[1]), str(sys.argv[2]))
        if os.path.exists(
            (path + '/' + 'Server' + str(response.json()['file_server_id']))):
            shutil.rmtree((path + '/' + 'Server' +
                           str(response.json()['file_server_id'])))
            os.mkdir(path + '/' + 'Server' +
                     str(response.json()['file_server_id']))
def write_file_to_server(file_name, cache):
    file_name_ = file_name + '.txt'
    key_in_cache = cache.get_key_to_file(file_name_)
    is_file_in_cache = cache.get_cache_entry(file_name_)

    if key_in_cache is not None and is_file_in_cache is not None:
        # I have a file in the cache
        response_from_directory_server = requests.get(
            Sff.create_url(DIRECTORY_SERVER_DETAILS[0],
                           DIRECTORY_SERVER_DETAILS[1]),
            params={'file_name': file_name},
            json={'client_id': cache.client_id})
        file_id, file_server_id, version, file_server_details = Sff.get_file_details_from_DS(
            response_from_directory_server)
        Sff.print_file_details(file_name, file_id, file_server_id, version)

        # get details for the server my file is on
        print "Trying to obtain a lock on file {} for client {}...".format(
            file_name, cache.client_id)
        # try to lock file on server
        response_from_locking_server = requests.get(Sff.create_url(
            DIRECTORY_SERVER_DETAILS[0], DIRECTORY_SERVER_DETAILS[1],
            'lock_server'),
                                                    json={
                                                        'client_id':
                                                        cache.client_id,
                                                        'file_id':
                                                        file_id,
                                                        'file_server_id':
                                                        file_server_id
                                                    })

        # if I can lock this file...
        if response_from_locking_server.json()['lock']:
            print "Lock has been received for client{} for file: {}".format(
                cache.client_id, file_name)
            file_to_read = "Cache{}/".format(cache.client_id) + file_name_
            open_file = open(file_to_read, 'r')
            dat = open_file.read()
            open_file.close()

            open_text_editor(file_to_read)
            file_ = open(file_to_read, 'r')
            data_to_send = file_.read()
            file_.close()
            if dat is not data_to_send:  # if the data in the file is updated
                # update the cache
                cache.update_data_in_cache(file_name_, data_to_send)
                # update the file on the server
                requests.post(Sff.create_url(file_server_details[0],
                                             file_server_details[1]),
                              json={
                                  'file_id': file_id,
                                  'data': data_to_send,
                                  'server_id': file_server_id,
                                  'file_name': file_name,
                                  'version': str(datetime.datetime.now())
                              })

            print "unlocking client{} from file .\n".format(
                cache.client_id, file_id)
            requests.delete(Sff.create_url(DIRECTORY_SERVER_DETAILS[0],
                                           DIRECTORY_SERVER_DETAILS[1],
                                           'lock_server'),
                            json={
                                'client_id': cache.client_id,
                                'file_id': file_id,
                                'file_server_id': file_server_id
                            })
            print "File has been unlocked by locking server!"

        elif not response_from_locking_server.json()['lock']:
            print 'The file is locked by another client - Try again later...'
    else:
        print "Data is not in cache/stored locally! - To be able to write the file to a server, first read it and" \
              " make changes"