import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import java.util.concurrent.atomic.AtomicReference;
-import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.ce.ComputeEngine;
private volatile boolean stopAwait = false;
private final ComputeEngine computeEngine;
- @CheckForNull
+ @Nullable
private CeMainThread ceMainThread = null;
@VisibleForTesting
Thread.sleep(CHECK_FOR_STOP_DELAY);
} catch (InterruptedException e) {
// ignore the interruption itself, check the flag
+ Thread.currentThread().interrupt();
}
}
attemptShutdown();
private void attemptShutdown() {
try {
- shutdown();
+ LOG.info("Compute Engine shutting down...");
+ computeEngine.shutdown();
} catch (Throwable e) {
LOG.error("Compute Engine shutdown failed", e);
} finally {
}
}
- private void shutdown() {
- LOG.info("Compute Engine shutting down...");
- computeEngine.shutdown();
- }
-
public boolean isStarted() {
return started;
}
Status getStatus();
enum Status {
- INIT, STARTING, STARTED, STOPPING, STOPPED;
+ INIT, STARTING, STARTED, STOPPING, STOPPED
}
}
import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_KEY;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
-import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT;
+import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT_MS;
public class ProcessLauncherImpl implements ProcessLauncher {
private static final Logger LOG = LoggerFactory.getLogger(ProcessLauncherImpl.class);
props.putAll(javaCommand.getArguments());
props.setProperty(PROPERTY_PROCESS_KEY, javaCommand.getProcessId().getKey());
props.setProperty(PROPERTY_PROCESS_INDEX, Integer.toString(javaCommand.getProcessId().getIpcIndex()));
- props.setProperty(PROPERTY_TERMINATION_TIMEOUT, "60000");
+ props.setProperty(PROPERTY_TERMINATION_TIMEOUT_MS, "60000");
props.setProperty(PROPERTY_SHARED_PATH, tempDir.getAbsolutePath());
try (OutputStream out = new FileOutputStream(propertiesFile)) {
props.store(out, format("Temporary properties file for command [%s]", javaCommand.getProcessId().getKey()));
*/
package org.sonar.process;
+/**
+ * Base interface for the processes started by the bootstrap process.
+ * It provides the information and operations required by {@link ProcessEntryPoint}
+ * to handle the lifecycle of the process.
+ */
public interface Monitored {
/**
}
/**
- * Blocks until the process is terminated
+ * Blocks until the process is stopped
*/
void awaitStop();
+ /**
+ * Stop process and wait until it's stopped.
+ */
void stop();
}
public static final String PROPERTY_PROCESS_KEY = "process.key";
public static final String PROPERTY_PROCESS_INDEX = "process.index";
- public static final String PROPERTY_TERMINATION_TIMEOUT = "process.terminationTimeout";
+ public static final String PROPERTY_TERMINATION_TIMEOUT_MS = "process.terminationTimeout";
public static final String PROPERTY_SHARED_PATH = "process.sharedDir";
private final Props props;
@Override
public void stopAsync() {
if (lifecycle.tryToMoveTo(Lifecycle.State.STOPPING)) {
- stopperThread = new StopperThread(monitored, commands, Long.parseLong(props.nonNullValue(PROPERTY_TERMINATION_TIMEOUT)));
+ stopperThread = new StopperThread(monitored, commands, Long.parseLong(props.nonNullValue(PROPERTY_TERMINATION_TIMEOUT_MS)));
stopperThread.start();
stopWatcher.stopWatching();
}
import java.util.concurrent.TimeUnit;
import org.sonar.process.sharedmemoryfile.ProcessCommands;
+import static java.lang.String.format;
+
/**
* Gracefully stops process in a timely fashion
*/
class StopperThread extends Thread {
private final Monitored monitored;
- private final long terminationTimeout;
+ private final long terminationTimeoutMs;
private final ProcessCommands commands;
- StopperThread(Monitored monitored, ProcessCommands commands, long terminationTimeout) {
+ StopperThread(Monitored monitored, ProcessCommands commands, long terminationTimeoutMs) {
super("Stopper");
this.monitored = monitored;
- this.terminationTimeout = terminationTimeout;
+ this.terminationTimeoutMs = terminationTimeoutMs;
this.commands = commands;
}
@Override
public void run() {
ExecutorService executor = Executors.newSingleThreadExecutor();
- Future future = executor.submit(new Runnable() {
- @Override
- public void run() {
- monitored.stop();
- }
- });
try {
- future.get(terminationTimeout, TimeUnit.MILLISECONDS);
+ Future future = executor.submit(monitored::stop);
+ future.get(terminationTimeoutMs, TimeUnit.MILLISECONDS);
} catch (Exception e) {
- LoggerFactory.getLogger(getClass()).error(String.format("Can not stop in %dms", terminationTimeout), e);
+ LoggerFactory.getLogger(getClass()).error(format("Can not stop in %dms", terminationTimeoutMs), e);
}
executor.shutdownNow();
commands.endWatch();
import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_KEY;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
-import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT;
+import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT_MS;
public class ProcessEntryPointTest {
props.set(PROPERTY_SHARED_PATH, temp.newFolder().getAbsolutePath());
props.set(PROPERTY_PROCESS_INDEX, "1");
props.set(PROPERTY_PROCESS_KEY, "test");
- props.set(PROPERTY_TERMINATION_TIMEOUT, "30000");
+ props.set(PROPERTY_TERMINATION_TIMEOUT_MS, "30000");
return props;
}