class App(object): def __init__(self): self.parser = argparse.ArgumentParser( description='A p2p key-value databse.') def parse_commandline(self): self.parser.add_argument( '-f', '--first', action='store_true', dest='first_node', default=False, help="Start the first node in the p2p network") self.parser.add_argument( '-b', '--bootstrap', nargs=2, dest='bootstrap', metavar=('<address>', '<port>'), help= "Start a node and connect to bootstrap node in existing network") self.parser.add_argument('-p', '--port', nargs=1, dest='port', metavar=('<port>'), default=[8468], help='Server listen to this port.') self.parser.add_argument( '--flooding', dest='flooding', nargs=3, metavar=('<iprange_l>', '<iprange_r>', '<ports>'), default=None, help= "Flooding neighbors instead of explicit bootstrapping given node. " "Format of <ports>:" "I: 9468,8469,8890 (equals [9468, 8469, 8890])" "II: 8469~8891 (equals list(range(8469, 8892)))" "Example: 192.168.1.1 192.168.2.0 8468~8470") self.parser.add_argument( '-t', '--timeout', nargs=1, dest='wait_timeout', metavar='<timeout>', default=(5, ), help='Wait timeout for bootstrapping and flooding') self.parser.add_argument( '-r', '--record', action='store_true', dest='record', default=False, help='If True, record active neighbors in the 0-th k-bucket') options = self.parser.parse_args() try: return (options.flooding, options.bootstrap, options.port, options.wait_timeout, options.record) except: print( 'To join existing network, you need a bootstrap node or flooding setting.' ) # if options.first_node: return (options.flooding, options.bootstrap, options.port) # else: # try: # return (options.flooding, options.bootstrap, options.port) # except: # print('To join existing network, you need a bootstrap node to connect the exist network.') def print_help(self): commands = { 'help': 'print this help', 'get': 'get the value for given key', 'put': 'update the value of the specified key', 'delete': 'delete the key in the storage system', 'quit': 'exit the system' } self.parser.print_help() print('\nCLI commands:') for command, description in commands.items(): print("%-10s %s" % (command, description)) def quit(self): self.server.stop() self.loop.close() def start_loop(self): self.loop.set_debug(True) asyncio.set_event_loop(self.loop) try: self.loop.run_forever() except KeyboardInterrupt: pass finally: self.server.stop() self.loop.close() def run(self): print( """Welcome to this p2p key-value system. To find out what other commands exist, type 'help'""" ) # log handler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) log = logging.getLogger('kademlia') log.addHandler(handler) log.setLevel(logging.DEBUG) # command information flooding_nodes, bootstrap_node, port, timeout, record = self.parse_commandline( ) # run subthread self.loop = asyncio.new_event_loop() self.t = Thread(target=self.start_loop) self.server = Server(timeout=int(timeout[0]), record=record) self.t.setDaemon(True) self.t.start() # self.server.reset(timeout=int(timeout[0]), record=record) asyncio.run_coroutine_threadsafe(self.server.listen(int(port[0])), self.loop).result() if bootstrap_node is not None: bootstrap_node = (bootstrap_node[0], int(bootstrap_node[1])) re = asyncio.run_coroutine_threadsafe( self.server.bootstrap([bootstrap_node]), self.loop).result() elif flooding_nodes is not None: iprange_l, iprange_r, ports = flooding_nodes if '~' in ports: l, r = ports.split('~') ports = list(range(int(l), int(r))) else: str_ports = ports.split(',') ports = [int(i) for i in str_ports] re = asyncio.run_coroutine_threadsafe( self.server.bootstrap(flooding=True, iprange_l=iprange_l, iprange_r=iprange_r, ports=ports), self.loop).result() while True: sleep(0.3) try: io = input('Command: ').lstrip().rstrip() if io == 'help': self.print_help() elif io == 'get': print("Usage: <key>") args = input().split(' ') if len(args) != 1: print("Number of parameters does not match.") else: result = asyncio.run_coroutine_threadsafe( self.server.get(args[0]), self.loop).result() result = result[0] if result else None print("Get result:", result) elif io == 'put': print("Usage: <key> <value>") args = input().split(' ') if len(args) != 2: print('Number of parameters dose not match.') else: asyncio.run_coroutine_threadsafe( self.server.set(args[0], args[1]), self.loop).result() elif io == 'delete': print("Usage: <key>") args = input().split(' ') if len(args) != 1: print('Number of parameters dose not match.') else: asyncio.run_coroutine_threadsafe( self.server.delete(args[0]), self.loop).result() elif io == 'quit': print('Bye ~ Have a nice day.') self.loop.call_soon_threadsafe(self.quit) break else: print('Sorry! Invalid command.') except EOFError: self.loop.call_soon_threadsafe(self.quit) break
bootstrap_node = ('192.168.1.240', 8468) loop.run_until_complete(server.bootstrap([bootstrap_node])) avg_response_time = 0 key = 'performance_test' value = 'testValue' loop.run_until_complete(server.set(key, value)) for i in range(500): option = random.randint(1, 3) start = time.time() if option == 1: # read loop.run_until_complete(server.get(key)) elif option == 2: # write loop.run_until_complete(server.set(key, value)) else: loop.run_until_complete(server.delete(key)) end = time.time() print('Operation time: %d' % (end-start)) avg_response_time += (end-start) avg_response_time /= 500 print('Average respone time: %d' % avg_response_time) try: loop.run_forever() except KeyboardInterrupt: pass finally: server.stop() loop.close()