Browse Source

SONAR-12043 Refactor ProcessEntryPoint

* Remove unused methods
* Extract method 'waitForStatus'
tags/7.8
Duarte Meneses 5 years ago
parent
commit
c89f7855ce

+ 1
- 0
server/sonar-ce/src/main/java/org/sonar/ce/app/CeServer.java View File

@@ -212,6 +212,7 @@ public class CeServer implements Monitored {
// stop looping indefinitely
this.stop = true;
// interrupt current thread in case its waiting for WebServer
// TODO is the waiting during startup or shutdown? this will most likely cause the shutdown to always fail to finish cleanly
interrupt();
}


+ 26
- 48
server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java View File

@@ -21,6 +21,8 @@ package org.sonar.process;

import java.io.File;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,8 +44,6 @@ public class ProcessEntryPoint {

private final Props props;
private final String processKey;
private final int processNumber;
private final File sharedDir;
private final Lifecycle lifecycle = new Lifecycle();
private final ProcessCommands commands;
private final SystemExit exit;
@@ -55,15 +55,9 @@ public class ProcessEntryPoint {
private volatile StopperThread stopperThread;
private volatile HardStopperThread hardStopperThread;

ProcessEntryPoint(Props props, SystemExit exit, ProcessCommands commands) {
this(props, getProcessNumber(props), getSharedDir(props), exit, commands, Runtime.getRuntime());
}

private ProcessEntryPoint(Props props, int processNumber, File sharedDir, SystemExit exit, ProcessCommands commands, Runtime runtime) {
private ProcessEntryPoint(Props props, SystemExit exit, ProcessCommands commands, Runtime runtime) {
this.props = props;
this.processKey = props.nonNullValue(PROPERTY_PROCESS_KEY);
this.processNumber = processNumber;
this.sharedDir = sharedDir;
this.exit = exit;
this.commands = commands;
this.stopWatcher = createStopWatcher(commands, this);
@@ -79,18 +73,6 @@ public class ProcessEntryPoint {
return props;
}

public String getKey() {
return processKey;
}

public int getProcessNumber() {
return processNumber;
}

public File getSharedDir() {
return sharedDir;
}

/**
* Launch process and waits until it's down
*/
@@ -104,7 +86,7 @@ public class ProcessEntryPoint {
try {
launch(logger);
} catch (Exception e) {
logger.warn("Fail to start {}", getKey(), e);
logger.warn("Fail to start {}", processKey, e);
} finally {
logger.trace("Hard stopping to clean any resource...");
hardStop();
@@ -112,7 +94,7 @@ public class ProcessEntryPoint {
}

private void launch(Logger logger) throws InterruptedException {
logger.info("Starting {}", getKey());
logger.info("Starting {}", processKey);
runtime.addShutdownHook(new Thread(() -> {
exit.setInShutdownHook();
stop();
@@ -121,13 +103,13 @@ public class ProcessEntryPoint {
hardStopWatcher.start();

monitored.start();
Monitored.Status status = waitForNotDownStatus();
Monitored.Status status = waitForStatus(s -> s != Monitored.Status.DOWN);
if (status == Monitored.Status.UP || status == Monitored.Status.OPERATIONAL) {
// notify monitor that process is ready
commands.setUp();

if (lifecycle.tryToMoveTo(Lifecycle.State.STARTED)) {
Monitored.Status newStatus = waitForOperational(status);
Monitored.Status newStatus = waitForStatus(s -> s == Monitored.Status.OPERATIONAL || s == Monitored.Status.FAILED);
if (newStatus == Monitored.Status.OPERATIONAL && lifecycle.tryToMoveTo(Lifecycle.State.OPERATIONAL)) {
commands.setOperational();
}
@@ -135,35 +117,25 @@ public class ProcessEntryPoint {
monitored.awaitStop();
}
} else {
logger.trace("Timeout waiting for process to go UP or OPERATIONAL. Hard stopping...");
logger.trace("Fail to start. Hard stopping...");
hardStop();
}
}

private Monitored.Status waitForNotDownStatus() throws InterruptedException {
Monitored.Status status = Monitored.Status.DOWN;
while (status == Monitored.Status.DOWN) {
private Monitored.Status waitForStatus(Predicate<Monitored.Status> statusPredicate) throws InterruptedException {
Monitored.Status status = monitored.getStatus();
while (!statusPredicate.test(status)) {
Thread.sleep(20);
status = monitored.getStatus();
Thread.sleep(20L);
}
return status;
}

private Monitored.Status waitForOperational(Monitored.Status currentStatus) throws InterruptedException {
Monitored.Status status = currentStatus;
// wait for operation or stop waiting if going to OPERATIONAL failed
while (status != Monitored.Status.OPERATIONAL && status != Monitored.Status.FAILED) {
status = monitored.getStatus();
Thread.sleep(20L);
}
return status;
}
void stop() {
stopAsync();
waitForStop();

boolean isStarted() {
return lifecycle.isCurrentState(Lifecycle.State.STARTED);
}

void stop() {
stopAsync()
.ifPresent(stoppingThread -> {
try {
@@ -178,6 +150,16 @@ public class ProcessEntryPoint {
});
}

private void waitForStop() {
try {
stopLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private CountDownLatch stopLatch = new CountDownLatch(1);

private Optional<StopperThread> stopAsync() {
if (lifecycle.tryToMoveTo(Lifecycle.State.STOPPING)) {
long terminationTimeoutMs = Long.parseLong(props.nonNullValue(PROPERTY_GRACEFUL_STOP_TIMEOUT_MS));
@@ -219,16 +201,12 @@ public class ProcessEntryPoint {
return ofNullable(hardStopperThread);
}

boolean isCurrentState(Lifecycle.State candidateState) {
return lifecycle.isCurrentState(candidateState);
}

public static ProcessEntryPoint createForArguments(String[] args) {
Props props = ConfigurationUtils.loadPropsFromCommandLineArgs(args);
File sharedDir = getSharedDir(props);
int processNumber = getProcessNumber(props);
ProcessCommands commands = DefaultProcessCommands.main(sharedDir, processNumber);
return new ProcessEntryPoint(props, processNumber, sharedDir, new SystemExit(), commands, Runtime.getRuntime());
return new ProcessEntryPoint(props, new SystemExit(), commands, Runtime.getRuntime());
}

private static int getProcessNumber(Props props) {

Loading…
Cancel
Save