From ff95eaeecc77f5537c7beda2cc614008757739ae Mon Sep 17 00:00:00 2001 From: Abdelhamid Bakhta <45264458+abdelhamidbakhta@users.noreply.github.com> Date: Tue, 2 Jul 2019 10:55:59 +0200 Subject: [PATCH] [PIE-1737] Simplify PantheonCommand `run` and `parse` methods. (#1626) * split parse method - handleStandaloneCommand - addSubCommands - registerConverters - handleUnstableOptions - preparePlugins - parse * split run method -checkOptions - configure - controller - startPlugins - startSynchronization * Update PantheonCommand.java Signed-off-by: Adrian Sutton --- .../pegasys/pantheon/cli/PantheonCommand.java | 170 +++++++++++------- 1 file changed, 108 insertions(+), 62 deletions(-) diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java index fdc7bb9b1b..e278ec878d 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java @@ -568,6 +568,15 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { arity = "1") private final Integer pendingTxRetentionPeriod = PendingTransactions.DEFAULT_TX_RETENTION_HOURS; + private EthNetworkConfig ethNetworkConfig; + private JsonRpcConfiguration jsonRpcConfiguration; + private GraphQLConfiguration graphQLConfiguration; + private WebSocketConfiguration webSocketConfiguration; + private MetricsConfiguration metricsConfiguration; + private Optional permissioningConfiguration; + private Collection staticNodes; + private PantheonController pantheonController; + // Inner class so we can get to loggingLevel. public class PantheonExceptionHandler extends CommandLine.AbstractHandler, PantheonExceptionHandler> @@ -633,17 +642,36 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { final PantheonExceptionHandler exceptionHandler, final InputStream in, final String... args) { + commandLine = new CommandLine(this).setCaseInsensitiveEnumValuesAllowed(true); + handleStandaloneCommand() + .addSubCommands(resultHandler, in) + .registerConverters() + .handleUnstableOptions() + .preparePlugins() + .parse(resultHandler, exceptionHandler, args); + } - commandLine = new CommandLine(this); - - commandLine.setCaseInsensitiveEnumValuesAllowed(true); + @Override + public void run() { + try { + prepareLogging(); + logger.info("Starting Pantheon version: {}", PantheonInfo.version()); + checkOptions().configure().controller().startPlugins().startSynchronization(); + } catch (final Exception e) { + throw new ParameterException(this.commandLine, e.getMessage(), e); + } + } + private PantheonCommand handleStandaloneCommand() { standaloneCommands = new StandaloneCommand(); - if (isFullInstantiation()) { commandLine.addMixin("standaloneCommands", standaloneCommands); } + return this; + } + private PantheonCommand addSubCommands( + final AbstractParseResultHandler> resultHandler, final InputStream in) { commandLine.addSubcommand( BlocksSubCommand.COMMAND_NAME, new BlocksSubCommand(blockImporter, resultHandler.out())); commandLine.addSubcommand( @@ -655,7 +683,10 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { RLPSubCommand.COMMAND_NAME, new RLPSubCommand(resultHandler.out(), in)); commandLine.addSubcommand( OperatorSubCommand.COMMAND_NAME, new OperatorSubCommand(resultHandler.out())); + return this; + } + private PantheonCommand registerConverters() { commandLine.registerConverter(Address.class, Address::fromHexStringStrict); commandLine.registerConverter(BytesValue.class, BytesValue::fromHexString); commandLine.registerConverter(Level.class, Level::valueOf); @@ -663,13 +694,15 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { commandLine.registerConverter(UInt256.class, (arg) -> UInt256.of(new BigInteger(arg))); commandLine.registerConverter(Wei.class, (arg) -> Wei.of(Long.parseUnsignedLong(arg))); commandLine.registerConverter(PositiveNumber.class, PositiveNumber::fromString); - final MetricCategoryConverter metricCategoryConverter = new MetricCategoryConverter(); metricCategoryConverter.addCategories(PantheonMetricCategory.class); metricCategoryConverter.addCategories(StandardMetricCategory.class); commandLine.registerConverter(MetricCategory.class, metricCategoryConverter); + return this; + } - // Add performance options + private PantheonCommand handleUnstableOptions() { + // Add unstable options UnstableOptionsSubCommand.createUnstableOptions( commandLine, ImmutableMap.of( @@ -681,10 +714,19 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { ethereumWireConfigurationBuilder, "TransactionPool", transactionPoolConfigurationBuilder)); + return this; + } + private PantheonCommand preparePlugins() { pantheonPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); pantheonPluginContext.registerPlugins(pluginsDir()); + return this; + } + private PantheonCommand parse( + final AbstractParseResultHandler> resultHandler, + final PantheonExceptionHandler exceptionHandler, + final String... args) { // Create a handler that will search for a config file option and use it for // default values // and eventually it will run regular parsing of the remaining options. @@ -692,18 +734,44 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { new ConfigOptionSearchAndRunHandler( resultHandler, exceptionHandler, CONFIG_FILE_OPTION_NAME, environment, isDocker); commandLine.parseWithHandlers(configParsingHandler, exceptionHandler, args); + return this; } - @Override - public void run() { + private PantheonCommand startSynchronization() { + synchronize( + pantheonController, + p2pEnabled, + peerDiscoveryEnabled, + ethNetworkConfig, + maxPeers, + p2pHost, + p2pPort, + graphQLConfiguration, + jsonRpcConfiguration, + webSocketConfiguration, + metricsConfiguration, + permissioningConfiguration, + staticNodes); + return this; + } + + private PantheonCommand startPlugins() { + pantheonPluginContext.addService( + PantheonEvents.class, + new PantheonEventsImpl((pantheonController.getProtocolManager().getBlockBroadcaster()))); + pantheonPluginContext.startPlugins(); + return this; + } + + private void prepareLogging() { // set log level per CLI flags if (logLevel != null) { System.out.println("Setting logging level to " + logLevel.name()); Configurator.setAllLevels("", logLevel); } + } - logger.info("Starting Pantheon version: {}", PantheonInfo.version()); - + private PantheonCommand checkOptions() { // Check that P2P options are able to work or send an error checkOptionDependencies( logger, @@ -739,59 +807,32 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { "Unable to mine without a valid coinbase. Either disable mining (remove --miner-enabled)" + "or specify the beneficiary of mining (via --miner-coinbase
)"); } + return this; + } - final EthNetworkConfig ethNetworkConfig = updateNetworkConfig(getNetwork()); - try { - final JsonRpcConfiguration jsonRpcConfiguration = jsonRpcConfiguration(); - final GraphQLConfiguration graphQLConfiguration = graphQLConfiguration(); - final WebSocketConfiguration webSocketConfiguration = webSocketConfiguration(); - final Optional permissioningConfiguration = - permissioningConfiguration(); - - final Collection staticNodes = loadStaticNodes(); - logger.info("Connecting to {} static nodes.", staticNodes.size()); - logger.trace("Static Nodes = {}", staticNodes); - - final List enodeURIs = - ethNetworkConfig.getBootNodes().stream() - .map(EnodeURL::toURI) - .collect(Collectors.toList()); - permissioningConfiguration - .flatMap(PermissioningConfiguration::getLocalConfig) - .ifPresent(p -> ensureAllNodesAreInWhitelist(enodeURIs, p)); - - permissioningConfiguration - .flatMap(PermissioningConfiguration::getLocalConfig) - .ifPresent( - p -> - ensureAllNodesAreInWhitelist( - staticNodes.stream().map(EnodeURL::toURI).collect(Collectors.toList()), p)); - - final PantheonController pantheonController = buildController(); - final MetricsConfiguration metricsConfiguration = metricsConfiguration(); - - pantheonPluginContext.addService( - PantheonEvents.class, - new PantheonEventsImpl((pantheonController.getProtocolManager().getBlockBroadcaster()))); - pantheonPluginContext.startPlugins(); - - synchronize( - pantheonController, - p2pEnabled, - peerDiscoveryEnabled, - ethNetworkConfig, - maxPeers, - p2pHost, - p2pPort, - graphQLConfiguration, - jsonRpcConfiguration, - webSocketConfiguration, - metricsConfiguration, - permissioningConfiguration, - staticNodes); - } catch (final Exception e) { - throw new ParameterException(this.commandLine, e.getMessage(), e); - } + private PantheonCommand configure() throws Exception { + ethNetworkConfig = updateNetworkConfig(getNetwork()); + jsonRpcConfiguration = jsonRpcConfiguration(); + graphQLConfiguration = graphQLConfiguration(); + webSocketConfiguration = webSocketConfiguration(); + permissioningConfiguration = permissioningConfiguration(); + staticNodes = loadStaticNodes(); + logger.info("Connecting to {} static nodes.", staticNodes.size()); + logger.trace("Static Nodes = {}", staticNodes); + final List enodeURIs = + ethNetworkConfig.getBootNodes().stream().map(EnodeURL::toURI).collect(Collectors.toList()); + permissioningConfiguration + .flatMap(PermissioningConfiguration::getLocalConfig) + .ifPresent(p -> ensureAllNodesAreInWhitelist(enodeURIs, p)); + + permissioningConfiguration + .flatMap(PermissioningConfiguration::getLocalConfig) + .ifPresent( + p -> + ensureAllNodesAreInWhitelist( + staticNodes.stream().map(EnodeURL::toURI).collect(Collectors.toList()), p)); + metricsConfiguration = metricsConfiguration(); + return this; } private NetworkName getNetwork() { @@ -811,6 +852,11 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { } } + private PantheonCommand controller() { + pantheonController = buildController(); + return this; + } + PantheonController buildController() { try { return controllerBuilderFactory