package com.hubspot.singularity.executor;

import org.apache.mesos.MesosExecutorDriver;
import org.apache.mesos.Protos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.google.inject.name.Named;
import com.hubspot.mesos.JavaUtils;
import com.hubspot.singularity.executor.config.SingularityExecutorConfiguration;
import com.hubspot.singularity.executor.config.SingularityExecutorModule;
import com.hubspot.singularity.runner.base.config.SingularityRunnerBaseModule;
import com.hubspot.singularity.runner.base.configuration.BaseRunnerConfiguration;
import com.hubspot.singularity.s3.base.config.SingularityS3Configuration;

public class SingularityExecutorRunner {

  private static final Logger LOG = LoggerFactory.getLogger(SingularityExecutorRunner.class);

  public static void main(String... args) {
    final long start = System.currentTimeMillis();

    try {
      final Injector injector = Guice.createInjector(Stage.PRODUCTION, new SingularityRunnerBaseModule(SingularityExecutorConfiguration.class, ImmutableSet.<Class<? extends BaseRunnerConfiguration>>of(SingularityS3Configuration.class)), new SingularityExecutorModule());
      final SingularityExecutorRunner executorRunner = injector.getInstance(SingularityExecutorRunner.class);

      final Protos.Status driverStatus = executorRunner.run();

      LOG.info("Executor finished after {} with status: {}", JavaUtils.duration(start), driverStatus);

      System.exit(driverStatus == Protos.Status.DRIVER_STOPPED ? 0 : 1);
    } catch (Throwable t) {
      LOG.error("Finished after {} with error", JavaUtils.duration(start), t);
      System.exit(1);
    }
  }

  private final String name;
  private final SingularityExecutor singularityExecutor;
  private final SingularityExecutorMonitor monitor;

  @Inject
  public SingularityExecutorRunner(@Named(SingularityRunnerBaseModule.PROCESS_NAME) String name, SingularityExecutor singularityExecutor, SingularityExecutorMonitor monitor) {
    this.name = name;
    this.singularityExecutor = singularityExecutor;
    this.monitor = monitor;
  }

  public Protos.Status run() {
    LOG.info("{} starting MesosExecutorDriver...", name);

    final MesosExecutorDriver driver = new MesosExecutorDriver(singularityExecutor);
    monitor.start(driver);

    Runtime.getRuntime().addShutdownHook(new Thread("SingularityExecutorRunnerGracefulShutdown") {

      @Override
      public void run() {
        LOG.info("Executor is shutting down, ensuring shutdown via shutdown hook");
        monitor.shutdown(driver);
      }

    });

    return driver.run();
  }

}

@@ -113,16 +113,49 @@
 Protos;%0A
+import org.slf4j.ILoggerFactory;%0A
 import o
@@ -167,24 +167,24 @@
 f4j.Logger;%0A
-
 import org.s
@@ -847,16 +847,62 @@
 ation;%0A%0A
+import ch.qos.logback.classic.LoggerContext;%0A%0A
 public c
@@ -1682,24 +1682,42 @@
 erStatus);%0A%0A
+      stopLog();%0A%0A
       System
@@ -1888,27 +1888,293 @@
 t);%0A
-      System.exit(1
+%0A      stopLog();%0A%0A      System.exit(1);%0A    %7D%0A  %7D%0A%0A  private static void stopLog() %7B%0A   ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();%0A    if (loggerFactory instanceof LoggerContext) %7B%0A      LoggerContext context = (LoggerContext) loggerFactory;%0A      context.stop(
 );%0A 

stop log