Package co.cask.cdap

Source Code of co.cask.cdap.StandaloneMain

/*
* Copyright © 2014 Cask Data, 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 co.cask.cdap;

import co.cask.cdap.app.guice.AppFabricServiceRuntimeModule;
import co.cask.cdap.app.guice.ProgramRunnerRuntimeModule;
import co.cask.cdap.app.guice.ServiceStoreModules;
import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.common.guice.ConfigModule;
import co.cask.cdap.common.guice.DiscoveryRuntimeModule;
import co.cask.cdap.common.guice.IOModule;
import co.cask.cdap.common.guice.LocationRuntimeModule;
import co.cask.cdap.common.metrics.MetricsCollectionService;
import co.cask.cdap.common.utils.OSDetector;
import co.cask.cdap.data.runtime.DataFabricModules;
import co.cask.cdap.data.runtime.DataSetServiceModules;
import co.cask.cdap.data.runtime.DataSetsModules;
import co.cask.cdap.data.stream.service.StreamHttpService;
import co.cask.cdap.data.stream.service.StreamServiceRuntimeModule;
import co.cask.cdap.data2.datafabric.dataset.service.DatasetService;
import co.cask.cdap.explore.client.ExploreClient;
import co.cask.cdap.explore.executor.ExploreExecutorService;
import co.cask.cdap.explore.guice.ExploreClientModule;
import co.cask.cdap.explore.guice.ExploreRuntimeModule;
import co.cask.cdap.explore.service.ExploreServiceUtils;
import co.cask.cdap.gateway.Gateway;
import co.cask.cdap.gateway.auth.AuthModule;
import co.cask.cdap.gateway.collector.NettyFlumeCollector;
import co.cask.cdap.gateway.router.NettyRouter;
import co.cask.cdap.gateway.router.RouterModules;
import co.cask.cdap.gateway.runtime.GatewayModule;
import co.cask.cdap.internal.app.services.AppFabricServer;
import co.cask.cdap.logging.appender.LogAppenderInitializer;
import co.cask.cdap.logging.guice.LoggingModules;
import co.cask.cdap.metrics.guice.MetricsClientRuntimeModule;
import co.cask.cdap.metrics.guice.MetricsHandlerModule;
import co.cask.cdap.metrics.query.MetricsQueryService;
import co.cask.cdap.passport.http.client.PassportClient;
import co.cask.cdap.security.guice.SecurityModules;
import co.cask.cdap.security.server.ExternalAuthenticationServer;
import co.cask.tephra.inmemory.InMemoryTransactionService;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Service;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.name.Names;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.counters.Limits;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.PrintStream;
import java.net.InetAddress;
import java.util.List;

/**
* Standalone Main.
* NOTE: Use AbstractIdleService
*/
public class StandaloneMain {
  private static final Logger LOG = LoggerFactory.getLogger(StandaloneMain.class);

  private final WebCloudAppService webCloudAppService;
  private final NettyRouter router;
  private final Gateway gatewayV2;
  private final MetricsQueryService metricsQueryService;
  private final NettyFlumeCollector flumeCollector;
  private final AppFabricServer appFabricServer;
  private final StreamHttpService streamHttpService;

  private final MetricsCollectionService metricsCollectionService;

  private final LogAppenderInitializer logAppenderInitializer;
  private final InMemoryTransactionService txService;
  private final boolean securityEnabled;
  private final boolean sslEnabled;
  private final CConfiguration configuration;

  private ExternalAuthenticationServer externalAuthenticationServer;
  private final DatasetService datasetService;

  private ExploreExecutorService exploreExecutorService;
  private final ExploreClient exploreClient;

  private StandaloneMain(List<Module> modules, CConfiguration configuration, String webAppPath) {
    this.configuration = configuration;

    Injector injector = Guice.createInjector(modules);
    txService = injector.getInstance(InMemoryTransactionService.class);
    router = injector.getInstance(NettyRouter.class);
    gatewayV2 = injector.getInstance(Gateway.class);
    metricsQueryService = injector.getInstance(MetricsQueryService.class);
    flumeCollector = injector.getInstance(NettyFlumeCollector.class);
    appFabricServer = injector.getInstance(AppFabricServer.class);
    logAppenderInitializer = injector.getInstance(LogAppenderInitializer.class);

    metricsCollectionService = injector.getInstance(MetricsCollectionService.class);
    datasetService = injector.getInstance(DatasetService.class);

    this.webCloudAppService = (webAppPath == null) ? null : injector.getInstance(WebCloudAppService.class);

    streamHttpService = injector.getInstance(StreamHttpService.class);

    sslEnabled = configuration.getBoolean(Constants.Security.SSL_ENABLED);
    securityEnabled = configuration.getBoolean(Constants.Security.CFG_SECURITY_ENABLED);
    if (securityEnabled) {
      externalAuthenticationServer = injector.getInstance(ExternalAuthenticationServer.class);
    }

    boolean exploreEnabled = configuration.getBoolean(Constants.Explore.EXPLORE_ENABLED);
    if (exploreEnabled) {
      ExploreServiceUtils.checkHiveSupportWithoutSecurity(this.getClass().getClassLoader());
      exploreExecutorService = injector.getInstance(ExploreExecutorService.class);
    }

    exploreClient = injector.getInstance(ExploreClient.class);

    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        try {
          shutDown();
        } catch (Throwable e) {
          LOG.error("Failed to shutdown", e);
          // because shutdown hooks execute concurrently, the logger may be closed already: thus also print it.
          System.err.println("Failed to shutdown: " + e.getMessage());
          e.printStackTrace(System.err);
        }
      }
    });
  }

  /**
   * Start the service.
   */
  public void startUp() throws Exception {
    // Start all the services.
    txService.startAndWait();
    metricsCollectionService.startAndWait();
    datasetService.startAndWait();

    // It is recommended to initialize log appender after datasetService is started,
    // since log appender instantiates a dataset.
    logAppenderInitializer.initialize();

    Service.State state = appFabricServer.startAndWait();
    if (state != Service.State.RUNNING) {
      throw new Exception("Failed to start Application Fabric");
    }

    gatewayV2.startAndWait();
    metricsQueryService.startAndWait();
    router.startAndWait();
    flumeCollector.startAndWait();
    if (webCloudAppService != null) {
      webCloudAppService.startAndWait();
    }
    streamHttpService.startAndWait();

    if (securityEnabled) {
      externalAuthenticationServer.startAndWait();
    }

    if (exploreExecutorService != null) {
      exploreExecutorService.startAndWait();
    }

    String hostname = InetAddress.getLocalHost().getHostName();
    String protocol = sslEnabled ? "https" : "http";
    int dashboardPort = sslEnabled ?
      configuration.getInt(Constants.Dashboard.SSL_BIND_PORT) :
      configuration.getInt(Constants.Dashboard.BIND_PORT);
    System.out.println("Application Server started successfully");
    System.out.printf("Connect to dashboard at %s://%s:%d\n", protocol, hostname, dashboardPort);
  }

  /**
   * Shutdown the service.
   */
  public void shutDown() {
    LOG.info("Shutting down the Application Server");

    try {
      // order matters: first shut down web app 'cause it will stop working after router is down
      if (webCloudAppService != null) {
        webCloudAppService.stopAndWait();
      }
      //  shut down router, gateway and flume, to stop all incoming traffic
      router.stopAndWait();
      gatewayV2.stopAndWait();
      flumeCollector.stopAndWait();
      // now the stream writer and the explore service (they need tx)
      streamHttpService.stopAndWait();
      if (exploreExecutorService != null) {
        exploreExecutorService.stopAndWait();
      }
      exploreClient.close();
      // app fabric will also stop all programs
      appFabricServer.stopAndWait();
      // all programs are stopped: dataset service, metrics, transactions can stop now
      datasetService.stopAndWait();
      metricsQueryService.stopAndWait();
      txService.stopAndWait();

      if (securityEnabled) {
        // auth service is on the side anyway
        externalAuthenticationServer.stopAndWait();
      }
      logAppenderInitializer.close();

    } catch (Throwable e) {
      LOG.error("Exception during shutdown", e);
      // we can't do much but exit. Because there was an exception, some non-daemon threads may still be running.
      // therefore System.exit() won't do it, we need to farce a halt.
      Runtime.getRuntime().halt(1);
    }
  }

  /**
   * Print the usage statement and return null.
   *
   * @param error indicates whether this was invoked as the result of an error
   * @throws IllegalArgumentException in case of error
   */
  static void usage(boolean error) {

    // Which output stream should we use?
    PrintStream out = (error ? System.err : System.out);

    // And our requirements and usage
    out.println("Requirements: ");
    out.println("  Java:    JDK 1.6+ must be installed and JAVA_HOME environment variable set to the java executable");
    out.println("  Node.js: Node.js must be installed (obtain from http://nodejs.org/#download).  ");
    out.println("           The \"node\" executable must be in the system $PATH environment variable");
    out.println("");
    out.println("Usage: ");
    if (OSDetector.isWindows()) {
      out.println("  cdap.bat [options]");
    } else {
      out.println("  ./cdap.sh [options]");
    }
    out.println("");
    out.println("Additional options:");
    out.println("  --web-app-path  Path to Webapp");
    out.println("  --help          To print this message");
    out.println("");

    if (error) {
      throw new IllegalArgumentException();
    }
  }

  public static void main(String[] args) {
    String webAppPath = WebCloudAppService.WEB_APP;

    if (args.length > 0) {
      if ("--help".equals(args[0]) || "-h".equals(args[0])) {
        usage(false);
        return;
      } else if ("--web-app-path".equals(args[0])) {
        webAppPath = args[1];
      } else {
        usage(true);
      }
    }

    StandaloneMain main = null;

    try {
      main = create(webAppPath);
      main.startUp();
    } catch (Throwable e) {
      System.err.println("Failed to start server. " + e.getMessage());
      LOG.error("Failed to start server", e);
      if (main != null) {
        main.shutDown();
      }
      System.exit(-2);
    }
  }

  public static StandaloneMain create() {
    return create(WebCloudAppService.WEB_APP);
  }

  /**
   * The root of all goodness!
   */
  public static StandaloneMain create(String webAppPath) {
    return create(webAppPath, CConfiguration.create(), new Configuration());
  }

  public static StandaloneMain create(CConfiguration cConf, Configuration hConf) {
    return create(WebCloudAppService.WEB_APP, cConf, hConf);
  }

  public static StandaloneMain create(String webAppPath, CConfiguration cConf, Configuration hConf) {
    // This is needed to use LocalJobRunner with fixes (we have it in app-fabric).
    // For the modified local job runner
    hConf.addResource("mapred-site-local.xml");
    hConf.reloadConfiguration();
    // Due to incredibly stupid design of Limits class, once it is initialized, it keeps its settings. We
    // want to make sure it uses our settings in this hConf, so we have to force it initialize here before
    // someone else initializes it.
    Limits.init(hConf);

    File localDataDir = new File(cConf.get(Constants.CFG_LOCAL_DATA_DIR));
    hConf.set(Constants.CFG_LOCAL_DATA_DIR, localDataDir.getAbsolutePath());
    hConf.set(Constants.AppFabric.OUTPUT_DIR, cConf.get(Constants.AppFabric.OUTPUT_DIR));
    hConf.set("hadoop.tmp.dir", new File(localDataDir, cConf.get(Constants.AppFabric.TEMP_DIR)).getAbsolutePath());

    // Windows specific requirements
    if (OSDetector.isWindows()) {
      String userDir = System.getProperty("user.dir");
      System.load(userDir + "/lib/native/hadoop.dll");
    }

    //Run gateway on random port and forward using router.
    cConf.setInt(Constants.Gateway.PORT, 0);

    //Run dataset service on random port
    List<Module> modules = createPersistentModules(cConf, hConf, webAppPath);

    return new StandaloneMain(modules, cConf, webAppPath);
  }

  private static List<Module> createPersistentModules(CConfiguration configuration, Configuration hConf,
                                                      final String webAppPath) {
    configuration.setIfUnset(Constants.CFG_DATA_LEVELDB_DIR, Constants.DEFAULT_DATA_LEVELDB_DIR);

    String environment =
      configuration.get(Constants.CFG_APPFABRIC_ENVIRONMENT, Constants.DEFAULT_APPFABRIC_ENVIRONMENT);
    if (environment.equals("vpc")) {
      System.err.println("Application Server Environment: " + environment);
    }

    configuration.set(Constants.CFG_DATA_INMEMORY_PERSISTENCE, Constants.InMemoryPersistenceType.LEVELDB.name());

    String passportUri = configuration.get(Constants.Gateway.CFG_PASSPORT_SERVER_URI);
    final PassportClient client = passportUri == null || passportUri.isEmpty() ? new PassportClient()
      : PassportClient.create(passportUri);

    return ImmutableList.of(
      new AbstractModule() {
        @Override
        protected void configure() {
          bind(PassportClient.class).toProvider(new Provider<PassportClient>() {
            @Override
            public PassportClient get() {
              return client;
            }
          });
          if (webAppPath != null) {
            bindConstant().annotatedWith(Names.named("web-app-path")).to(webAppPath);
          }
        }
      },
      new ConfigModule(configuration, hConf),
      new IOModule(),
      new MetricsHandlerModule(),
      new AuthModule(),
      new DiscoveryRuntimeModule().getStandaloneModules(),
      new LocationRuntimeModule().getStandaloneModules(),
      new AppFabricServiceRuntimeModule().getStandaloneModules(),
      new ProgramRunnerRuntimeModule().getStandaloneModules(),
      new GatewayModule().getStandaloneModules(),
      new DataFabricModules().getStandaloneModules(),
      new DataSetsModules().getLocalModule(),
      new DataSetServiceModules().getLocalModule(),
      new MetricsClientRuntimeModule().getStandaloneModules(),
      new LoggingModules().getStandaloneModules(),
      new RouterModules().getStandaloneModules(),
      new SecurityModules().getStandaloneModules(),
      new StreamServiceRuntimeModule().getStandaloneModules(),
      new ExploreRuntimeModule().getStandaloneModules(),
      new ServiceStoreModules().getStandaloneModule(),
      new ExploreClientModule()
    );
  }
}
TOP

Related Classes of co.cask.cdap.StandaloneMain

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.