def launch_node(args: Namespace, chain_config: ChainConfig, endpoint: Endpoint) -> None: with chain_config.process_id_file('networking'): endpoint.connect() NodeClass = chain_config.node_class # Temporary hack: We setup a second instance of the PluginManager. # The first instance was only to configure the ArgumentParser whereas # for now, the second instance that lives inside the networking process # performs the bulk of the work. In the future, the PluginManager # should probably live in its own process and manage whether plugins # run in the shared plugin process or spawn their own. plugin_manager = setup_plugins(SharedProcessScope(endpoint)) plugin_manager.prepare(args, chain_config) plugin_manager.broadcast(HeliosStartupEvent( args, chain_config )) node = NodeClass(plugin_manager, chain_config) loop = node.get_event_loop() asyncio.ensure_future(handle_networking_exit(node, plugin_manager, endpoint), loop=loop) asyncio.ensure_future(node.run(), loop=loop) loop.run_forever() loop.close()
def run_database_process(chain_config: ChainConfig, db_class: Type[BaseDB]) -> None: with chain_config.process_id_file('database'): if chain_config.report_memory_usage: from threading import Thread memory_logger = logging.getLogger('hvm.memoryLogger') t = Thread(target=sync_periodically_report_memory_stats, args=(chain_config.memory_usage_report_interval, memory_logger)) t.start() base_db = db_class(db_path=chain_config.database_dir) # TODO:remove #base_db = JournalDB(base_db) manager = get_chaindb_manager(chain_config, base_db) server = manager.get_server() # type: ignore def _sigint_handler(*args: Any) -> None: server.stop_event.set() signal.signal(signal.SIGINT, _sigint_handler) try: server.serve_forever() except SystemExit: server.stop_event.set() raise
def run_chain_process(chain_config: ChainConfig, instance = 0) -> None: with chain_config.process_id_file('database_{}'.format(instance)): # connect with database process db_manager = create_db_manager(chain_config.database_ipc_path) db_manager.connect() base_db = db_manager.get_db() # start chain process manager = get_chain_manager(chain_config, base_db, instance) server = manager.get_server() # type: ignore def _sigint_handler(*args: Any) -> None: server.stop_event.set() signal.signal(signal.SIGINT, _sigint_handler) try: server.serve_forever() except SystemExit: server.stop_event.set() raise
def helios_boot(args: Namespace, chain_config: ChainConfig, extra_kwargs: Dict[str, Any], plugin_manager: PluginManager, listener: logging.handlers.QueueListener, event_bus: EventBus, main_endpoint: Endpoint, logger: logging.Logger) -> None: # start the listener thread to handle logs produced by other processes in # the local logger. listener.start() logger.info( "Checking for any already running Helios Protocol processes that need shutting down. Remember that you can only run 1 instance at a time." ) fix_unclean_shutdown(chain_config, logger) with chain_config.process_id_file('main'): networking_endpoint = event_bus.create_endpoint( NETWORKING_EVENTBUS_ENDPOINT) event_bus.start() # First initialize the database process. database_server_process = ctx.Process( target=run_database_process, args=( chain_config, LevelDB, ), kwargs=extra_kwargs, ) chain_processes = [] for i in range(chain_config.num_chain_processes): chain_process = ctx.Process( target=run_chain_process, args=(chain_config, i), kwargs=extra_kwargs, ) chain_processes.append(chain_process) networking_process = ctx.Process( target=launch_node, args=( args, chain_config, networking_endpoint, ), kwargs=extra_kwargs, ) # start the processes database_server_process.start() logger.info("Started DB server process (pid=%d)", database_server_process.pid) # networking process needs the IPC socket file provided by the database process try: wait_for_ipc(chain_config.database_ipc_path) except TimeoutError as e: logger.error("Timeout waiting for database to start. Exiting...") kill_process_gracefully(database_server_process, logger) ArgumentParser().error( message="Timed out waiting for database start") for i in range(chain_config.num_chain_processes): chain_process = chain_processes[i] chain_process.start() logger.info("Started chain instance {} process (pid={})".format( i, chain_process.pid)) try: wait_for_ipc(chain_config.get_chain_ipc_path(i)) except TimeoutError as e: logger.error( "Timeout waiting for chain instance {} to start. Exiting..." .format(i)) kill_process_gracefully(chain_process, logger) for j in range(i + 1): kill_process_gracefully(chain_processes[j], logger) ArgumentParser().error( message="Timed out waiting for chain instance {} start". format(i)) networking_process.start() logger.info("Started networking process (pid=%d)", networking_process.pid) main_endpoint.subscribe( ShutdownRequest, lambda ev: kill_helios_gracefully( logger, database_server_process, chain_processes, networking_process, plugin_manager, main_endpoint, event_bus)) plugin_manager.prepare(args, chain_config, extra_kwargs) plugin_manager.broadcast(HeliosStartupEvent(args, chain_config)) try: loop = asyncio.get_event_loop() loop.run_forever() loop.close() except KeyboardInterrupt: kill_helios_gracefully(logger, database_server_process, chain_processes, networking_process, plugin_manager, main_endpoint, event_bus)