def delete(self, path): """Delete a file under a given path.""" internal_path = validate_path(path) parent = Path('/') entry = None for part in internal_path.parts: entry = mongo.db.index.find_one({ 'name': part, 'parent': str(parent) }) if entry is None: abort(404) parent /= part if entry['is_directory']: abort(404) for server in entry['servers']: response = requests.delete(f'http://{server}/file/{internal_path}') mongo.db.servers.replace_one( {'_id': server}, { '_id': server, 'free_space': int(response.text) }, ) mongo.db.index.delete_one(entry) return jsonify(get_min_free_space())
def initialize(): """Wipe everything from the storage servers.""" for server in mongo.db.servers.find(): response = requests.post(f'http://{server["_id"]}/initialize') server['free_space'] = int(response.text) mongo.db.servers.replace_one({'_id': server['_id']}, server) mongo.db.index.remove() return jsonify(get_min_free_space())
def put(self, path): """Update a file under a given path.""" if 'file' not in request.files: abort(400, 'No file attached.') file = request.files['file'] internal_path = validate_path(path) *parents, name = internal_path.parts parent = Path('/') entry = None for part in parents: entry = mongo.db.index.find_one({ 'name': part, 'parent': str(parent) }) if entry is None: mongo.db.index.insert_one({ 'name': part, 'parent': str(parent), 'is_directory': True }) parent /= part entry = mongo.db.index.find_one({'name': name, 'parent': str(parent)}) if entry is not None: abort(400, 'A file with this name already exists.') ok_servers = [] for server in mongo.db.servers.find(): response = requests.post( f'http://{server["_id"]}/file/{internal_path}', files={'file': file.stream}) if not response.ok: continue server['free_space'] = int(response.text) mongo.db.servers.replace_one({'_id': server['_id']}, server) ok_servers.append(server['_id']) mongo.db.index.replace_one({ 'name': name, }, { 'name': name, 'parent': str(parent), 'is_directory': False, 'size': get_file_size(file), 'last_modified': int(time.time()), 'servers': ok_servers, }, upsert=True) return jsonify(get_min_free_space())
def copy(path: str): """Copy the file to the specified location.""" src_internal_path = validate_path(path) dst_internal_path = validate_path(request.json["destination"].lstrip('/')) src_parent = Path('/') src_entry = None for part in src_internal_path.parts: src_entry = mongo.db.index.find_one({ 'name': part, 'parent': str(src_parent) }) if src_entry is None: abort(404) src_parent /= part if src_entry is None or src_entry[ 'is_directory'] or not src_entry['servers']: abort(404) *dst_parents, dst_name = dst_internal_path.parts dst_parent = Path('/') dst_entry = None for part in dst_parents: dst_entry = mongo.db.index.find_one({ 'name': part, 'parent': str(dst_parent) }) if dst_entry is None: mongo.db.index.insert_one({ 'name': part, 'parent': str(dst_parent), 'is_directory': True }) dst_parent /= part dst_entry = mongo.db.index.find_one({ 'name': dst_name, 'parent': str(dst_parent) }) if dst_entry is not None: abort(400, 'A file with this name already exists.') server = choose_server(among=src_entry['servers']) file = requests.get(f'http://{server}/file/{src_internal_path}') if not file.ok: abort(400, 'Copying failed.') ok_servers = [] for server in mongo.db.servers.find(): response = requests.post( f'http://{server["_id"]}/file/{str(dst_internal_path)}', files={'file': io.BytesIO(file.content)}) if not response.ok: continue server['free_space'] = int(response.text) mongo.db.servers.replace_one({'_id': server['_id']}, server) ok_servers.append(server['_id']) mongo.db.index.insert_one({ 'name': dst_name, 'parent': str(dst_parent), 'is_directory': False, 'size': len(file.content), 'last_modified': int(time.time()), 'servers': ok_servers, }) return jsonify(get_min_free_space())
def free_space(): """Return the amount of free space among the storage servers.""" return jsonify(get_min_free_space())