class DirectoryService(Database): DATABASE = "sql.db" def __init__(self, port, replication): super(DirectoryService, self).__init__() self.port = port self.replication = replication self._create_tables() self.server = Server(port, self._handler) def _insert_server(self, sock, master, host, port): exists = self._server_exists(host, port) if exists: return True else: self.execute_sql("insert into servers (master, host, port) values (?, ?, ?)", (master, host, port), exclusive=True) return True def _delete_server(self, sock, host, port): self.execute_sql("delete from servers where host=? and port=?", (host, port)) def _list_servers(self, sock): # return (pickle.dumps(self.fetch_sql("select * from servers", ())), "PADDING") pass def _server_exists(self, host, port): return len(self.fetch_sql("select * from servers where host=? and port=?", (host, port))) != 0 def _select_random_server(self): return self.fetch_sql("select * from servers where id >= (abs(random()) % (SELECT max(id) FROM servers));", ()) def _select_server_by_id(self, id): return self.fetch_sql("select * from servers where id=?", (str(id),)) def _select_server_master(self, host, port): return self.fetch_sql("select id from servers where host=? and port=?", (host, port)) def _find_directory_host(self, file_name): return self.fetch_sql("select * from directories where file=?", (file_name,)) def _insert_directory_host(self, directory, file_name, server_id): self.execute_sql("insert into directories (directory, file, server_id) values (?, ?, ?)", (directory, file_name, str(server_id))) def _create_tables(self): conn = sqlite3.connect(self.DATABASE) cur = conn.cursor() cur.executescript(""" create table if not exists servers( id INTEGER PRIMARY KEY ASC, master INTEGER, host TEXT, port TEXT ); create table if not exists directories( id INTEGER PRIMARY KEY ASC, directory TEXT, file TEXT, server_id TEXT );""") def _handler(self, sock): try: data = sock.recv(1024) msg = data.decode('utf-8') msg = msg.replace('$', ' ') if 'KILL_SERVICE' in msg: exit() elif msg[:6] == "INSERT": temp = msg.split() ip_port = temp[1].split(':') master = temp[2] self._insert_server(sock, master, ip_port[0], ip_port[1]) self.server.respond(sock, response200()) elif msg[:4] == "DELETE": temp = msg.split() ip_port = temp[1].split(':') self._delete_server(sock, ip_port[0], ip_port[1]) self.server.respond(sock, response200()) elif msg[:3] == "GET": temp = msg.split() file_name = temp[1] row = self._select_random_server() file_dir = self._find_directory_host(file_name) pdb.set_trace() if file_dir is not None: response = response200() + " " + row[0][2] + ":" + row[0][3] + " " + file_dir[0][1] + " " + str(file_dir[0][0]) self.server.respond(sock, response) else: self.server.respond(sock, response404()) elif msg[:4] == "LIST": # TODO not complete, for replication temp = msg.split() #self._mkdir_handler(sock, temp[1]) elif msg[:3] == "ADD": temp = msg.split() ip_port = temp[1].split(':') server_ids = self._select_server_master(ip_port[0], ip_port[1]) server_id = server_ids[0] self._insert_directory_host(temp[2], temp[3], server_id[0]) else: self.server.error(sock, 0, responseErrParse()) except sock.error as e: err = e.args[0] self.server.error(sock, 0, e.args[1])
class FileService(object): """docstring for FileService""" def __init__(self, port, ds_host, ds_port): super(FileService, self).__init__() self.dir = '' self.port = port self.ds_host = ds_host self.ds_port = ds_port self.server = Server(port, self._handler) def announce_server(self): sock = self.server.send_as_client(self.ds_host, self.ds_port, "INSERT " + self.server.host + ":" + str(self.port) + " " + "1") data = sock.recv(1024) if data.decode('utf-8') != response200(): print("Error with Directory Server: ", data) sock.shutdown(socket.SHUT_WR) sock.close() #TODO Add to allow exsting files or remove def _open_handler(self, conn, path): filename = self.dir + path if not os.path.isfile(filename): self.server.error(conn, 404, response404()) else: f = open(filename, "rb") pdb.set_trace() self.server.send_file(conn, f) conn.shutdown(socket.SHUT_WR) conn.close() def _create_handler(self, conn, path): file_path = os.path.dirname(path) if not os.path.isdir(file_path): self.server.error(conn, 405, response405()) else: self.server.respond(conn, response200()) exists = os.path.isfile(self.dir + path) f = open(self.dir + path, "wb") conn.recv_file(f) f.close() self.server.respond(conn, response200()) # TODO: send to other replication managers # if not exists: # def _mkdir_handler(self, conn, path): newdir = str(self.dir + path.strip('/')) basedir = os.path.dirname(newdir) if not os.path.isdir(basedir): self.server.error(conn, 404, response404()) else: try: os.makedirs(newdir) self.server.respond(conn, response200()) # self._advertise_buffer.add(path.strip('/'), ObjectBuffer.Type.directory) # TODO: send to replication manager except Exception as e: if e.errno != errno.EEXIST: raise else: conn.send() def _delete_handler(self, conn, path): pdb.set_trace() obj = str(self.dir + path).rstrip('/') if os.path.isdir(obj): shutil.rmtree(obj) self.server.respond(conn, response200()) # self._advertise_buffer.add(path, ObjectBuffer.Type.deleteDirectory) elif os.path.isfile(obj): os.remove(obj) self.server.respond(conn, response200()) # self._advertise_buffer.add(path, ObjectBuffer.Type.deleteFile) else: self.server.error(conn, 404, "not found!") def _handler(self, sock): LF = "\n" try: data = sock.recv(1024) msg = data.decode('utf-8') msg = msg.replace('$', ' ') if 'KILL_SERVICE' in msg: exit() elif msg[:4] == "HELO": response = ["IP:" + self.server.host, "Port:" + str(self.port), "StudentID:" + self.server.studentId] fullResponse = msg + LF.join(response) print(response) sock.send(fullResponse.encode('utf-8')) elif msg[:4] == "OPEN": temp = msg.split() self._open_handler(sock, temp[1]) elif msg[:6] == "CREATE": temp = msg.split() self._create_handler(sock, temp[1]) elif msg[:5] == "MKDIR": temp = msg.split() self._mkdir_handler(sock, temp[1]) elif msg[:6] == "DELETE": temp = msg.split() self._delete_handler(sock, temp[1]) else: self.server.error(sock, 0, responseErrParse()) except sock.error as e: err = e.args[0] self.server.error(sock, 0, e.args[1])
class LockService(Database): """ LockService provdes functionality to lock access to a particular file on the fileservers. Every service that writes to file uses the lockService, every read of a file checks if the particular file is locked. The lockservice provides rudimentary acknowledgments on all operations """ DATABASE = "sql.db" def __init__(self, port): super(LockService, self).__init__() self.port = port self._create_tables() self.server = Server(port, self._handler) def _lock_file(self, file_name): is_locked = self._check_if_locked(file_name) if is_locked: return False insert = self.execute_sql("insert into locks (file_name) values (?)", (file_name,), exclusive=True) if insert: return True else: return False def _unlock_file(self, file_name): delete = self.execute_sql("delete from locks where file_name = ?", (file_name,), exclusive=True) if delete: return True else: return False def _check_if_locked(self, file_name): data = self.fetch_sql("select * from locks where file_name=?", (file_name,)) if file_name in data: return True else: return False def _handler(self, sock): try: data = sock.recv(1024) msg = data.decode('utf-8') msg = msg.replace('$', ' ') if 'KILL_SERVICE' in msg: exit() elif msg[:4] == "LOCK": temp = msg.split() is_locked = self._unlock_file(temp[1]) if is_locked: self.server.respond(sock, response200()) else: self.server.respond(sock, response604()) elif msg[:6] == "UNLOCK": temp = msg.split() is_unlocked = self._unlock_file( temp[1]) if is_unlocked: self.server.respond(sock, response200()) else: self.server.respond(sock, response604()) elif msg[:5] == "CHECK": temp = msg.split() locked = self._check_if_locked(temp[1]) if locked: self.server.respond(sock, responseLocked()) else: self.server.respond(sock, responseUnlocked()) else: self.server.error(sock, 0, responseErrParse()) except sock.error as e: err = e.args[0] self.server.error(sock, 0, e.args[1]) def _create_tables(self): conn = sqlite3.connect(self.DATABASE) cur = conn.cursor() cur.executescript(""" create table if not exists locks( id INTEGER PRIMARY KEY AUTOINCREMENT, file_name TEXT );""")