/* * Copyright © 2014-2016 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.app.guice; import co.cask.cdap.app.deploy.Manager; import co.cask.cdap.app.deploy.ManagerFactory; import co.cask.cdap.app.mapreduce.DistributedMRJobInfoFetcher; import co.cask.cdap.app.mapreduce.LocalMRJobInfoFetcher; import co.cask.cdap.app.mapreduce.MRJobInfoFetcher; import co.cask.cdap.app.store.Store; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.common.namespace.NamespaceAdmin; import co.cask.cdap.common.runtime.RuntimeModule; import co.cask.cdap.common.twill.MasterServiceManager; import co.cask.cdap.common.utils.Networks; import co.cask.cdap.config.guice.ConfigStoreModule; import co.cask.cdap.data.stream.StreamServiceManager; import co.cask.cdap.data.stream.StreamViewHttpHandler; import co.cask.cdap.data.stream.service.StreamFetchHandler; import co.cask.cdap.data.stream.service.StreamHandler; import co.cask.cdap.data2.datafabric.dataset.DatasetExecutorServiceManager; import co.cask.cdap.data2.datafabric.dataset.MetadataServiceManager; import co.cask.cdap.explore.service.ExploreServiceManager; import co.cask.cdap.gateway.handlers.AppFabricDataHttpHandler; import co.cask.cdap.gateway.handlers.AppLifecycleHttpHandler; import co.cask.cdap.gateway.handlers.ArtifactHttpHandler; import co.cask.cdap.gateway.handlers.AuthorizationHandler; import co.cask.cdap.gateway.handlers.CommonHandlers; import co.cask.cdap.gateway.handlers.ConfigHandler; import co.cask.cdap.gateway.handlers.ConsoleSettingsHttpHandler; import co.cask.cdap.gateway.handlers.DashboardHttpHandler; import co.cask.cdap.gateway.handlers.MonitorHandler; import co.cask.cdap.gateway.handlers.NamespaceHttpHandler; import co.cask.cdap.gateway.handlers.NotificationFeedHttpHandler; import co.cask.cdap.gateway.handlers.PreferencesHttpHandler; import co.cask.cdap.gateway.handlers.ProgramLifecycleHttpHandler; import co.cask.cdap.gateway.handlers.TransactionHttpHandler; import co.cask.cdap.gateway.handlers.UsageHandler; import co.cask.cdap.gateway.handlers.VersionHandler; import co.cask.cdap.gateway.handlers.WorkflowHttpHandler; import co.cask.cdap.gateway.handlers.WorkflowStatsSLAHttpHandler; import co.cask.cdap.internal.app.deploy.LocalApplicationManager; import co.cask.cdap.internal.app.deploy.pipeline.AppDeploymentInfo; import co.cask.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms; import co.cask.cdap.internal.app.namespace.DefaultNamespaceAdmin; import co.cask.cdap.internal.app.runtime.artifact.ArtifactStore; import co.cask.cdap.internal.app.runtime.batch.InMemoryTransactionServiceManager; import co.cask.cdap.internal.app.runtime.distributed.AppFabricServiceManager; import co.cask.cdap.internal.app.runtime.distributed.TransactionServiceManager; import co.cask.cdap.internal.app.runtime.schedule.DistributedSchedulerService; import co.cask.cdap.internal.app.runtime.schedule.ExecutorThreadPool; import co.cask.cdap.internal.app.runtime.schedule.LocalSchedulerService; import co.cask.cdap.internal.app.runtime.schedule.Scheduler; import co.cask.cdap.internal.app.runtime.schedule.SchedulerService; import co.cask.cdap.internal.app.runtime.schedule.store.DatasetBasedTimeScheduleStore; import co.cask.cdap.internal.app.services.AppFabricServer; import co.cask.cdap.internal.app.services.ProgramLifecycleService; import co.cask.cdap.internal.app.services.StandaloneAppFabricServer; import co.cask.cdap.internal.app.store.DefaultStore; import co.cask.cdap.internal.pipeline.SynchronousPipelineFactory; import co.cask.cdap.logging.run.InMemoryAppFabricServiceManager; import co.cask.cdap.logging.run.InMemoryDatasetExecutorServiceManager; import co.cask.cdap.logging.run.InMemoryExploreServiceManager; import co.cask.cdap.logging.run.InMemoryLogSaverServiceManager; import co.cask.cdap.logging.run.InMemoryMetadataServiceManager; import co.cask.cdap.logging.run.InMemoryMetricsProcessorServiceManager; import co.cask.cdap.logging.run.InMemoryMetricsServiceManager; import co.cask.cdap.logging.run.InMemoryStreamServiceManager; import co.cask.cdap.logging.run.LogSaverStatusServiceManager; import co.cask.cdap.metrics.runtime.MetricsProcessorStatusServiceManager; import co.cask.cdap.metrics.runtime.MetricsServiceManager; import co.cask.cdap.pipeline.PipelineFactory; import co.cask.http.HttpHandler; import com.google.common.base.Supplier; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.multibindings.MapBinder; import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.util.Modules; import org.quartz.SchedulerException; import org.quartz.core.JobRunShellFactory; import org.quartz.core.QuartzScheduler; import org.quartz.core.QuartzSchedulerResources; import org.quartz.impl.DefaultThreadExecutor; import org.quartz.impl.DirectSchedulerFactory; import org.quartz.impl.StdJobRunShellFactory; import org.quartz.impl.StdScheduler; import org.quartz.simpl.CascadingClassLoadHelper; import org.quartz.spi.ClassLoadHelper; import org.quartz.spi.JobStore; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.List; /** * AppFabric Service Runtime Module. */ public final class AppFabricServiceRuntimeModule extends RuntimeModule { @Override public Module getInMemoryModules() { return Modules.combine(new AppFabricServiceModule( StreamHandler.class, StreamFetchHandler.class, StreamViewHttpHandler.class), new ConfigStoreModule().getInMemoryModule(), new EntityVerifierModule(), new AbstractModule() { @Override protected void configure() { bind(SchedulerService.class).to(LocalSchedulerService.class).in(Scopes.SINGLETON); bind(Scheduler.class).to(SchedulerService.class); bind(MRJobInfoFetcher.class).to(LocalMRJobInfoFetcher.class); addInMemoryBindings(binder()); Multibinder<String> servicesNamesBinder = Multibinder.newSetBinder(binder(), String.class, Names.named("appfabric.services.names")); servicesNamesBinder.addBinding().toInstance(Constants.Service.APP_FABRIC_HTTP); servicesNamesBinder.addBinding().toInstance(Constants.Service.STREAMS); Multibinder<String> handlerHookNamesBinder = Multibinder.newSetBinder(binder(), String.class, Names.named("appfabric.handler.hooks")); handlerHookNamesBinder.addBinding().toInstance(Constants.Service.APP_FABRIC_HTTP); handlerHookNamesBinder.addBinding().toInstance(Constants.Stream.STREAM_HANDLER); } }); } @Override public Module getStandaloneModules() { return Modules.combine(new AppFabricServiceModule( StreamHandler.class, StreamFetchHandler.class, StreamViewHttpHandler.class), new ConfigStoreModule().getStandaloneModule(), new EntityVerifierModule(), new AbstractModule() { @Override protected void configure() { bind(AppFabricServer.class).to(StandaloneAppFabricServer.class).in(Scopes.SINGLETON); bind(SchedulerService.class).to(LocalSchedulerService.class).in(Scopes.SINGLETON); bind(Scheduler.class).to(SchedulerService.class); bind(MRJobInfoFetcher.class).to(LocalMRJobInfoFetcher.class); addInMemoryBindings(binder()); Multibinder<String> servicesNamesBinder = Multibinder.newSetBinder(binder(), String.class, Names.named("appfabric.services.names")); servicesNamesBinder.addBinding().toInstance(Constants.Service.APP_FABRIC_HTTP); servicesNamesBinder.addBinding().toInstance(Constants.Service.STREAMS); Multibinder<String> handlerHookNamesBinder = Multibinder.newSetBinder(binder(), String.class, Names.named("appfabric.handler.hooks")); handlerHookNamesBinder.addBinding().toInstance(Constants.Service.APP_FABRIC_HTTP); handlerHookNamesBinder.addBinding().toInstance(Constants.Stream.STREAM_HANDLER); } }); } private void addInMemoryBindings(Binder binder) { MapBinder<String, MasterServiceManager> mapBinder = MapBinder.newMapBinder( binder, String.class, MasterServiceManager.class); mapBinder.addBinding(Constants.Service.LOGSAVER) .to(InMemoryLogSaverServiceManager.class); mapBinder.addBinding(Constants.Service.TRANSACTION) .to(InMemoryTransactionServiceManager.class); mapBinder.addBinding(Constants.Service.METRICS_PROCESSOR) .to(InMemoryMetricsProcessorServiceManager.class); mapBinder.addBinding(Constants.Service.METRICS) .to(InMemoryMetricsServiceManager.class); mapBinder.addBinding(Constants.Service.APP_FABRIC_HTTP) .to(InMemoryAppFabricServiceManager.class); mapBinder.addBinding(Constants.Service.STREAMS) .to(InMemoryStreamServiceManager.class); mapBinder.addBinding(Constants.Service.DATASET_EXECUTOR) .to(InMemoryDatasetExecutorServiceManager.class); mapBinder.addBinding(Constants.Service.METADATA_SERVICE) .to(InMemoryMetadataServiceManager.class); mapBinder.addBinding(Constants.Service.EXPLORE_HTTP_USER_SERVICE) .to(InMemoryExploreServiceManager.class); } @Override public Module getDistributedModules() { return Modules.combine(new AppFabricServiceModule(), new ConfigStoreModule().getDistributedModule(), new EntityVerifierModule(), new AbstractModule() { @Override protected void configure() { bind(SchedulerService.class).to(DistributedSchedulerService.class).in(Scopes.SINGLETON); bind(Scheduler.class).to(SchedulerService.class); bind(MRJobInfoFetcher.class).to(DistributedMRJobInfoFetcher.class); MapBinder<String, MasterServiceManager> mapBinder = MapBinder.newMapBinder( binder(), String.class, MasterServiceManager.class); mapBinder.addBinding(Constants.Service.LOGSAVER) .to(LogSaverStatusServiceManager.class); mapBinder.addBinding(Constants.Service.TRANSACTION) .to(TransactionServiceManager.class); mapBinder.addBinding(Constants.Service.METRICS_PROCESSOR) .to(MetricsProcessorStatusServiceManager.class); mapBinder.addBinding(Constants.Service.METRICS) .to(MetricsServiceManager.class); mapBinder.addBinding(Constants.Service.APP_FABRIC_HTTP) .to(AppFabricServiceManager.class); mapBinder.addBinding(Constants.Service.STREAMS) .to(StreamServiceManager.class); mapBinder.addBinding(Constants.Service.DATASET_EXECUTOR) .to(DatasetExecutorServiceManager.class); mapBinder.addBinding(Constants.Service.METADATA_SERVICE) .to(MetadataServiceManager.class); mapBinder.addBinding(Constants.Service.EXPLORE_HTTP_USER_SERVICE) .to(ExploreServiceManager.class); Multibinder<String> servicesNamesBinder = Multibinder.newSetBinder(binder(), String.class, Names.named("appfabric.services.names")); servicesNamesBinder.addBinding().toInstance(Constants.Service.APP_FABRIC_HTTP); Multibinder<String> handlerHookNamesBinder = Multibinder.newSetBinder(binder(), String.class, Names.named("appfabric.handler.hooks")); handlerHookNamesBinder.addBinding().toInstance(Constants.Service.APP_FABRIC_HTTP); } }); } /** * Guice module for AppFabricServer. Requires data-fabric related bindings being available. */ private static final class AppFabricServiceModule extends AbstractModule { private final List<Class<? extends HttpHandler>> handlerClasses; @SafeVarargs private AppFabricServiceModule(Class<? extends HttpHandler>... handlerClasses) { this.handlerClasses = ImmutableList.copyOf(handlerClasses); } @Override protected void configure() { bind(PipelineFactory.class).to(SynchronousPipelineFactory.class); install( new FactoryModuleBuilder() .implement(new TypeLiteral<Manager<AppDeploymentInfo, ApplicationWithPrograms>>() { }, new TypeLiteral<LocalApplicationManager<AppDeploymentInfo, ApplicationWithPrograms>>() { }) .build(new TypeLiteral<ManagerFactory<AppDeploymentInfo, ApplicationWithPrograms>>() { }) ); bind(Store.class).to(DefaultStore.class); bind(ArtifactStore.class).in(Scopes.SINGLETON); bind(ProgramLifecycleService.class).in(Scopes.SINGLETON); bind(NamespaceAdmin.class).to(DefaultNamespaceAdmin.class).in(Scopes.SINGLETON); Multibinder<HttpHandler> handlerBinder = Multibinder.newSetBinder( binder(), HttpHandler.class, Names.named(Constants.AppFabric.HANDLERS_BINDING)); CommonHandlers.add(handlerBinder); handlerBinder.addBinding().to(ConfigHandler.class); handlerBinder.addBinding().to(AppFabricDataHttpHandler.class); handlerBinder.addBinding().to(VersionHandler.class); handlerBinder.addBinding().to(MonitorHandler.class); handlerBinder.addBinding().to(UsageHandler.class); handlerBinder.addBinding().to(NamespaceHttpHandler.class); handlerBinder.addBinding().to(NotificationFeedHttpHandler.class); handlerBinder.addBinding().to(AppLifecycleHttpHandler.class); handlerBinder.addBinding().to(DashboardHttpHandler.class); handlerBinder.addBinding().to(ProgramLifecycleHttpHandler.class); handlerBinder.addBinding().to(PreferencesHttpHandler.class); handlerBinder.addBinding().to(ConsoleSettingsHttpHandler.class); handlerBinder.addBinding().to(TransactionHttpHandler.class); handlerBinder.addBinding().to(WorkflowHttpHandler.class); handlerBinder.addBinding().to(ArtifactHttpHandler.class); handlerBinder.addBinding().to(WorkflowStatsSLAHttpHandler.class); handlerBinder.addBinding().to(AuthorizationHandler.class); for (Class<? extends HttpHandler> handlerClass : handlerClasses) { handlerBinder.addBinding().to(handlerClass); } } @Provides @Named(Constants.AppFabric.SERVER_ADDRESS) @SuppressWarnings("unused") public InetAddress providesHostname(CConfiguration cConf) { return Networks.resolve(cConf.get(Constants.AppFabric.SERVER_ADDRESS), new InetSocketAddress("localhost", 0).getAddress()); } /** * Provides a supplier of quartz scheduler so that initialization of the scheduler can be done after guice * injection. It returns a singleton of Scheduler. */ @Provides @SuppressWarnings("unused") public Supplier<org.quartz.Scheduler> providesSchedulerSupplier(final DatasetBasedTimeScheduleStore scheduleStore, final CConfiguration cConf) { return new Supplier<org.quartz.Scheduler>() { private org.quartz.Scheduler scheduler; @Override public synchronized org.quartz.Scheduler get() { try { if (scheduler == null) { scheduler = getScheduler(scheduleStore, cConf); } return scheduler; } catch (Exception e) { throw Throwables.propagate(e); } } }; } /** * Create a quartz scheduler. Quartz factory method is not used, because inflexible in allowing custom jobstore * and turning off check for new versions. * @param store JobStore. * @param cConf CConfiguration. * @return an instance of {@link org.quartz.Scheduler} * @throws SchedulerException */ private org.quartz.Scheduler getScheduler(JobStore store, CConfiguration cConf) throws SchedulerException { int threadPoolSize = cConf.getInt(Constants.Scheduler.CFG_SCHEDULER_MAX_THREAD_POOL_SIZE); ExecutorThreadPool threadPool = new ExecutorThreadPool(threadPoolSize); threadPool.initialize(); String schedulerName = DirectSchedulerFactory.DEFAULT_SCHEDULER_NAME; String schedulerInstanceId = DirectSchedulerFactory.DEFAULT_INSTANCE_ID; QuartzSchedulerResources qrs = new QuartzSchedulerResources(); JobRunShellFactory jrsf = new StdJobRunShellFactory(); qrs.setName(schedulerName); qrs.setInstanceId(schedulerInstanceId); qrs.setJobRunShellFactory(jrsf); qrs.setThreadPool(threadPool); qrs.setThreadExecutor(new DefaultThreadExecutor()); qrs.setJobStore(store); qrs.setRunUpdateCheck(false); QuartzScheduler qs = new QuartzScheduler(qrs, -1, -1); ClassLoadHelper cch = new CascadingClassLoadHelper(); cch.initialize(); store.initialize(cch, qs.getSchedulerSignaler()); org.quartz.Scheduler scheduler = new StdScheduler(qs); jrsf.initialize(scheduler); qs.initialize(); return scheduler; } } }