Search in sources :

Example 11 with Cancellable

use of org.apache.twill.common.Cancellable in project cdap by caskdata.

the class WebappProgramRunner method run.

@Override
public ProgramController run(Program program, ProgramOptions options) {
    try {
        ProgramType processorType = program.getType();
        Preconditions.checkNotNull(processorType, "Missing processor type");
        Preconditions.checkArgument(processorType == ProgramType.WEBAPP, "Only WEBAPP process type is supported");
        LOG.info("Initializing Webapp for app {} with jar {}", program.getApplicationId(), program.getJarLocation().getName());
        String serviceName = getServiceName(program.getId());
        Preconditions.checkNotNull(serviceName, "Cannot determine service name for program %s", program.getName());
        LOG.info("Got service name {}", serviceName);
        // Start netty server
        // TODO: add metrics reporting
        JarHttpHandler jarHttpHandler = webappHttpHandlerFactory.createHandler(program.getJarLocation());
        NettyHttpService.Builder builder = new CommonNettyHttpServiceBuilder(cConf, program.getId().toString());
        builder.setHttpHandlers(jarHttpHandler);
        builder.setUrlRewriter(new WebappURLRewriter(jarHttpHandler));
        builder.setHost(hostname.getCanonicalHostName());
        NettyHttpService httpService = builder.build();
        httpService.start();
        final InetSocketAddress address = httpService.getBindAddress();
        RunId runId = ProgramRunners.getRunId(options);
        // Register service, and the serving host names.
        final List<Cancellable> cancellables = Lists.newArrayList();
        LOG.info("Webapp {} running on address {} registering as {}", program.getApplicationId(), address, serviceName);
        cancellables.add(serviceAnnouncer.announce(serviceName, address.getPort()));
        for (String hname : getServingHostNames(Locations.newInputSupplier(program.getJarLocation()))) {
            final String sname = ProgramType.WEBAPP.name().toLowerCase() + "/" + hname;
            LOG.info("Webapp {} running on address {} registering as {}", program.getApplicationId(), address, sname);
            cancellables.add(discoveryService.register(ResolvingDiscoverable.of(new Discoverable(sname, address))));
        }
        return new WebappProgramController(program.getId().run(runId), httpService, new Cancellable() {

            @Override
            public void cancel() {
                for (Cancellable cancellable : cancellables) {
                    cancellable.cancel();
                }
            }
        });
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}
Also used : Discoverable(org.apache.twill.discovery.Discoverable) ResolvingDiscoverable(co.cask.cdap.common.discovery.ResolvingDiscoverable) CommonNettyHttpServiceBuilder(co.cask.cdap.common.http.CommonNettyHttpServiceBuilder) InetSocketAddress(java.net.InetSocketAddress) Cancellable(org.apache.twill.common.Cancellable) NettyHttpService(co.cask.http.NettyHttpService) ProgramType(co.cask.cdap.proto.ProgramType) RunId(org.apache.twill.api.RunId)

Example 12 with Cancellable

use of org.apache.twill.common.Cancellable in project cdap by caskdata.

the class AbstractHttpHandlerDelegator method wrapResponder.

/**
   * Returns a new instance of {@link DelayedHttpServiceResponder} that wraps around the given {@link HttpResponder}
   * object. This method is called from handler class generated by {@link HttpHandlerGenerator}.
   */
@SuppressWarnings("unused")
protected final DelayedHttpServiceResponder wrapResponder(HttpResponder responder) {
    MetricsContext collector = this.metricsContext;
    HttpServiceContext serviceContext = context.getServiceContext();
    Preconditions.checkState(serviceContext instanceof TransactionalHttpServiceContext, "This instance of HttpServiceContext does not support transactions.");
    if (serviceContext.getSpecification() != null) {
        collector = metricsContext.childContext(Constants.Metrics.Tag.HANDLER, serviceContext.getSpecification().getName());
    }
    return new DelayedHttpServiceResponder(responder, new BodyProducerFactory() {

        @Override
        public BodyProducer create(HttpContentProducer contentProducer, TransactionalHttpServiceContext serviceContext) {
            final ClassLoader programContextClassLoader = new CombineClassLoader(null, ImmutableList.of(contentProducer.getClass().getClassLoader(), getClass().getClassLoader()));
            // Capture the context since we need to keep it until the end of the content producing.
            // We don't need to worry about double capturing of the context when HttpContentConsumer is used.
            // This is because when HttpContentConsumer is used, the responder constructed here will get closed and this
            // BodyProducerFactory won't be used.
            final Cancellable contextReleaser = context.capture();
            return new BodyProducerAdapter(contentProducer, serviceContext, programContextClassLoader, contextReleaser);
        }
    }, (TransactionalHttpServiceContext) serviceContext, collector);
}
Also used : BodyProducer(co.cask.http.BodyProducer) CombineClassLoader(co.cask.cdap.common.lang.CombineClassLoader) HttpServiceContext(co.cask.cdap.api.service.http.HttpServiceContext) Cancellable(org.apache.twill.common.Cancellable) MetricsContext(co.cask.cdap.api.metrics.MetricsContext) HttpContentProducer(co.cask.cdap.api.service.http.HttpContentProducer) CombineClassLoader(co.cask.cdap.common.lang.CombineClassLoader)

Example 13 with Cancellable

use of org.apache.twill.common.Cancellable in project cdap by caskdata.

the class AbstractHttpHandlerDelegator method wrapContentConsumer.

/**
   * Returns a new instance of {@link BodyConsumer} that wraps around the given {@link HttpContentConsumer}
   * and {@link DelayedHttpServiceResponder}.
   *
   * IMPORTANT: This method will also capture the context associated with the current thread, hence after
   * this method is called, no other methods on this class should be called from the current thread.
   *
   * This method is called from handler class generated by {@link HttpHandlerGenerator}.
   */
@SuppressWarnings("unused")
protected final BodyConsumer wrapContentConsumer(HttpContentConsumer consumer, DelayedHttpServiceResponder responder) {
    Preconditions.checkState(!responder.hasBufferedResponse(), "HttpContentConsumer may not be used after a response has already been sent.");
    // Close the provided responder since a new one will be created for the BodyConsumerAdapter to use.
    responder.close();
    final HttpServiceContext serviceContext = context.getServiceContext();
    Preconditions.checkState(serviceContext instanceof TransactionalHttpServiceContext, "This instance of HttpServiceContext does not support transactions.");
    final Cancellable contextReleaser = context.capture();
    final ClassLoader programContextClassLoader = new CombineClassLoader(null, ImmutableList.of(consumer.getClass().getClassLoader(), getClass().getClassLoader()));
    return new BodyConsumerAdapter(new DelayedHttpServiceResponder(responder, new BodyProducerFactory() {

        @Override
        public BodyProducer create(HttpContentProducer contentProducer, TransactionalHttpServiceContext serviceContext) {
            // Transfer the captured context from the content consumer to the content producer
            return new BodyProducerAdapter(contentProducer, serviceContext, programContextClassLoader, contextReleaser);
        }
    }), consumer, serviceContext, programContextClassLoader, contextReleaser);
}
Also used : CombineClassLoader(co.cask.cdap.common.lang.CombineClassLoader) HttpServiceContext(co.cask.cdap.api.service.http.HttpServiceContext) Cancellable(org.apache.twill.common.Cancellable) HttpContentProducer(co.cask.cdap.api.service.http.HttpContentProducer) CombineClassLoader(co.cask.cdap.common.lang.CombineClassLoader)

Example 14 with Cancellable

use of org.apache.twill.common.Cancellable in project cdap by caskdata.

the class SparkRuntimeUtils method initSparkMain.

/**
 * Initialize a Spark main() method. This is the first method to be called from the main() method of any
 * spark program.
 *
 * @return a {@link Cancellable} for releasing resources.
 */
public static Cancellable initSparkMain() {
    final Thread mainThread = Thread.currentThread();
    SparkClassLoader sparkClassLoader;
    try {
        sparkClassLoader = SparkClassLoader.findFromContext();
    } catch (IllegalStateException e) {
        sparkClassLoader = SparkClassLoader.create();
    }
    final ClassLoader oldClassLoader = ClassLoaders.setContextClassLoader(sparkClassLoader.getRuntimeContext().getProgramInvocationClassLoader());
    final SparkExecutionContext sec = sparkClassLoader.getSparkExecutionContext(true);
    final SparkRuntimeContext runtimeContext = sparkClassLoader.getRuntimeContext();
    String executorServiceURI = System.getenv(CDAP_SPARK_EXECUTION_SERVICE_URI);
    final Service driverService;
    if (executorServiceURI != null) {
        // Creates the SparkDriverService in distributed mode for heartbeating and tokens update
        driverService = new SparkDriverService(URI.create(executorServiceURI), runtimeContext);
    } else {
        // In local mode, just create a no-op service for state transition.
        driverService = new AbstractService() {

            @Override
            protected void doStart() {
                notifyStarted();
            }

            @Override
            protected void doStop() {
                notifyStopped();
            }
        };
    }
    // Watch for stopping of the driver service.
    // It can happen when a user program finished such that the Cancellable.cancel() returned by this method is called,
    // or it can happen when it received a stop command (distributed mode) in the SparkDriverService via heartbeat.
    // In local mode, the LocalSparkSubmitter calls the Cancellable.cancel() returned by this method directly
    // (via SparkMainWraper).
    // We use a service listener so that it can handle all cases.
    final CountDownLatch mainThreadCallLatch = new CountDownLatch(1);
    driverService.addListener(new ServiceListenerAdapter() {

        @Override
        public void terminated(Service.State from) {
            handleStopped();
        }

        @Override
        public void failed(Service.State from, Throwable failure) {
            handleStopped();
        }

        private void handleStopped() {
            // Avoid interrupt/join on the current thread
            if (Thread.currentThread() != mainThread) {
                mainThread.interrupt();
                // If it is spark streaming, wait for the user class call returns from the main thread.
                if (SparkRuntimeEnv.getStreamingContext().isDefined()) {
                    Uninterruptibles.awaitUninterruptibly(mainThreadCallLatch);
                }
            }
            // Close the SparkExecutionContext (it will stop all the SparkContext and release all resources)
            if (sec instanceof AutoCloseable) {
                try {
                    ((AutoCloseable) sec).close();
                } catch (Exception e) {
                    // Just log. It shouldn't throw, and if it does (due to bug), nothing much can be done
                    LOG.warn("Exception raised when calling {}.close() for program run {}.", sec.getClass().getName(), runtimeContext.getProgramRunId(), e);
                }
            }
        }
    }, Threads.SAME_THREAD_EXECUTOR);
    driverService.startAndWait();
    return new Cancellable() {

        @Override
        public void cancel() {
            // since it's the last thing that Spark main methhod would do.
            if (Thread.currentThread() == mainThread) {
                mainThreadCallLatch.countDown();
                mainThread.setContextClassLoader(oldClassLoader);
            }
            driverService.stopAndWait();
        }
    };
}
Also used : Cancellable(org.apache.twill.common.Cancellable) AbstractService(com.google.common.util.concurrent.AbstractService) SparkDriverService(co.cask.cdap.app.runtime.spark.distributed.SparkDriverService) Service(com.google.common.util.concurrent.Service) ServiceListenerAdapter(org.apache.twill.internal.ServiceListenerAdapter) AbstractService(com.google.common.util.concurrent.AbstractService) CountDownLatch(java.util.concurrent.CountDownLatch) SparkDriverService(co.cask.cdap.app.runtime.spark.distributed.SparkDriverService) IOException(java.io.IOException) SparkRunnerClassLoader(co.cask.cdap.app.runtime.spark.classloader.SparkRunnerClassLoader) FilterClassLoader(co.cask.cdap.common.lang.FilterClassLoader) SparkExecutionContext(co.cask.cdap.api.spark.SparkExecutionContext)

Example 15 with Cancellable

use of org.apache.twill.common.Cancellable in project cdap by caskdata.

the class AuthenticationHandler method getAuthenticationURLs.

/**
 * Gets a {@link JsonArray} of url strings to the authentication server instances.
 */
private JsonArray getAuthenticationURLs() {
    // If the auth server urls are known via configuration, just use it
    final JsonArray result = new JsonArray();
    if (!authServerURLs.isEmpty()) {
        for (String url : authServerURLs) {
            result.add(new JsonPrimitive(url));
        }
        return result;
    }
    // Use service discovery to get URLs of the auth servers
    final String protocol = getProtocol(cConf);
    final int port = getPort(cConf);
    ServiceDiscovered serviceDiscovered = discoveryServiceClient.discover(Constants.Service.EXTERNAL_AUTHENTICATION);
    addAuthServerUrls(serviceDiscovered, protocol, port, result);
    if (result.size() > 0) {
        return result;
    }
    // For bootstrapping, the service discovery takes time to fill in the cache from ZK, hence use a callback
    // and a timed future to get the result
    final SettableFuture<JsonArray> future = SettableFuture.create();
    Cancellable cancellable = serviceDiscovered.watchChanges(new ServiceDiscovered.ChangeListener() {

        @Override
        public void onChange(ServiceDiscovered serviceDiscovered) {
            addAuthServerUrls(serviceDiscovered, protocol, port, result);
            if (result.size() > 0) {
                future.set(result);
            }
        }
    }, Threads.SAME_THREAD_EXECUTOR);
    try {
        return future.get(2, TimeUnit.SECONDS);
    } catch (TimeoutException e) {
        LOG.warn("No authentication server detected via service discovery");
        return result;
    } catch (Exception e) {
        // There shouldn't be other exception, hence just returning
        return result;
    } finally {
        cancellable.cancel();
    }
}
Also used : JsonArray(com.google.gson.JsonArray) JsonPrimitive(com.google.gson.JsonPrimitive) Cancellable(org.apache.twill.common.Cancellable) ServiceDiscovered(org.apache.twill.discovery.ServiceDiscovered) TimeoutException(java.util.concurrent.TimeoutException) PatternSyntaxException(java.util.regex.PatternSyntaxException) TimeoutException(java.util.concurrent.TimeoutException)

Aggregations

Cancellable (org.apache.twill.common.Cancellable)27 CountDownLatch (java.util.concurrent.CountDownLatch)7 Test (org.junit.Test)6 InetSocketAddress (java.net.InetSocketAddress)5 Discoverable (org.apache.twill.discovery.Discoverable)5 HttpContentProducer (co.cask.cdap.api.service.http.HttpContentProducer)3 ResolvingDiscoverable (co.cask.cdap.common.discovery.ResolvingDiscoverable)3 CombineClassLoader (co.cask.cdap.common.lang.CombineClassLoader)3 NotificationFeedNotFoundException (co.cask.cdap.notifications.feeds.NotificationFeedNotFoundException)3 ArrayList (java.util.ArrayList)3 ZKClientService (org.apache.twill.zookeeper.ZKClientService)3 MetricsContext (co.cask.cdap.api.metrics.MetricsContext)2 HttpServiceContext (co.cask.cdap.api.service.http.HttpServiceContext)2 SparkRunnerClassLoader (co.cask.cdap.app.runtime.spark.classloader.SparkRunnerClassLoader)2 FilterClassLoader (co.cask.cdap.common.lang.FilterClassLoader)2 StreamPropertyListener (co.cask.cdap.data.stream.StreamPropertyListener)2 NotificationContext (co.cask.cdap.notifications.service.NotificationContext)2 StreamId (co.cask.cdap.proto.id.StreamId)2 BodyProducer (co.cask.http.BodyProducer)2 ImmutableSet (com.google.common.collect.ImmutableSet)2