Java tutorial
/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.caliper.runner; import static com.google.common.util.concurrent.MoreExecutors.shutdownAndAwaitTermination; import static java.util.concurrent.TimeUnit.SECONDS; import com.google.caliper.core.InvalidBenchmarkException; import com.google.caliper.runner.config.CaliperConfig; import com.google.caliper.runner.config.InvalidConfigurationException; import com.google.caliper.runner.options.CaliperOptions; import com.google.caliper.runner.worker.targetinfo.TargetInfo; import com.google.caliper.runner.worker.targetinfo.TargetInfoFactory; import com.google.caliper.util.DisplayUsageException; import com.google.caliper.util.InvalidCommandException; import com.google.caliper.util.Stderr; import com.google.caliper.util.Stdout; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSortedMap; import com.google.common.util.concurrent.Service; import com.google.common.util.concurrent.ServiceManager; import dagger.Lazy; import java.io.PrintWriter; import java.util.Map.Entry; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import javax.inject.Inject; import javax.inject.Provider; /** * The Caliper runner. * * <p>This is the entry point class for the Caliper runner process which controls a full benchmark * run. */ public final class CaliperRunner { // These core dependencies should be lazy since some of them throw exceptions and we want that // to occur inside of run() instead of when constructing this object. private final Lazy<CaliperOptions> options; private final Lazy<CaliperConfig> config; private final Lazy<ServiceManager> serviceManager; // TODO(cgdecker): This shouldn't need to be lazy, but it causes problems, weirdly enough, with // if the user passes --help on the command line if it isn't lazy. Would be nice to fix that. private final Lazy<TargetInfoFactory> targetInfoFactory; private final PrintWriter stdout; private final PrintWriter stderr; private final Provider<CaliperRunComponent.Builder> runComponentBuilder; private final ExecutorService executor; @Inject CaliperRunner(Lazy<CaliperOptions> options, Lazy<CaliperConfig> config, Lazy<ServiceManager> serviceManager, Lazy<TargetInfoFactory> targetInfoFactory, @Stdout PrintWriter stdout, @Stderr PrintWriter stderr, Provider<CaliperRunComponent.Builder> runComponentBuilder, ExecutorService executor) { this.options = options; this.config = config; this.serviceManager = serviceManager; this.targetInfoFactory = targetInfoFactory; this.stdout = stdout; this.stderr = stderr; this.runComponentBuilder = runComponentBuilder; this.executor = executor; } /** Runs Caliper, handles any exceptions and returns an exit code. */ public int run() { int code = 1; // pessimism! try { runInternal(); code = 0; } catch (DisplayUsageException e) { e.display(stdout); code = e.exitCode(); } catch (InvalidCommandException e) { e.display(stderr); code = e.exitCode(); } catch (InvalidBenchmarkException e) { e.display(stderr); } catch (InvalidConfigurationException e) { e.display(stderr); } catch (Throwable t) { t.printStackTrace(stderr); stdout.println(); stdout.println("An unexpected exception has been thrown by the caliper runner."); stdout.println("Please see https://sites.google.com/site/caliperusers/issues"); } stdout.flush(); stderr.flush(); return code; } /** * Runs Caliper, handling any exceptions and exiting the process with an appropriate exit code. */ public void runAndExit() { System.exit(run()); } /** * Runs Caliper, throwing an exception if the command line, configuration or benchmark class is * invalid. */ @VisibleForTesting public void runInternal() throws InvalidCommandException, InvalidBenchmarkException, InvalidConfigurationException { try { if (options.get().printConfiguration()) { stdout.println("Configuration:"); ImmutableSortedMap<String, String> sortedProperties = ImmutableSortedMap .copyOf(config.get().properties()); for (Entry<String, String> entry : sortedProperties.entrySet()) { stdout.printf(" %s = %s%n", entry.getKey(), entry.getValue()); } } serviceManager.get().addListener(new ServiceManager.Listener() { @Override public void failure(Service service) { stderr.println("Service " + service + " failed with the following exception:"); service.failureCause().printStackTrace(stderr); } }); serviceManager.get().startAsync().awaitHealthy(); try { TargetInfo targetInfo = targetInfoFactory.get().getTargetInfo(); CaliperRun run = runComponentBuilder.get().targetInfo(targetInfo).build().getCaliperRun(); run.run(); // throws IBE } finally { try { // We have some shutdown logic to ensure that files are cleaned up so give it a chance to // run serviceManager.get().stopAsync().awaitStopped(10, TimeUnit.SECONDS); } catch (TimeoutException e) { // That's fine } } } finally { shutdownAndAwaitTermination(executor, 5, SECONDS); // courtesy flush stderr.flush(); stdout.flush(); } } }