in priam/src/main/java/com/netflix/priam/defaultimpl/CassandraProcessManager.java [143:217]
public void stop(boolean force) throws IOException {
logger.info("Stopping cassandra server ....");
List<String> command = Lists.newArrayList();
if (config.useSudo()) {
logger.info("Configured to use sudo to stop C*");
if (!"root".equals(System.getProperty("user.name"))) {
command.add(SUDO_STRING);
command.add("-n");
command.add("-E");
}
}
for (String param : config.getCassStopScript().split(" ")) {
if (StringUtils.isNotBlank(param)) command.add(param);
}
ProcessBuilder stopCass = new ProcessBuilder(command);
stopCass.directory(new File("/"));
stopCass.redirectErrorStream(true);
instanceState.setShouldCassandraBeAlive(false);
if (!force && config.getGracefulDrainHealthWaitSeconds() >= 0) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future drainFuture =
executor.submit(
() -> {
// As the node has been marked as shutting down above in
// setShouldCassandraBeAlive, we wait this
// duration to allow external healthcheck systems time to pick up
// the state change.
try {
Thread.sleep(config.getGracefulDrainHealthWaitSeconds() * 1000);
} catch (InterruptedException e) {
return;
}
try {
JMXNodeTool nodetool = JMXNodeTool.instance(config);
nodetool.drain();
} catch (InterruptedException
| IOException
| ExecutionException e) {
logger.error(
"Exception draining Cassandra, could not drain. Proceeding with shutdown.",
e);
}
// Once Cassandra is drained the thrift/native servers are shutdown
// and there is no need to wait to
// stop Cassandra. Just stop it now.
});
// In case drain hangs, timeout the future and continue stopping anyways. Give drain 30s
// always
// In production we frequently see servers that do not want to drain
try {
drainFuture.get(config.getGracefulDrainHealthWaitSeconds() + 30, TimeUnit.SECONDS);
} catch (ExecutionException | TimeoutException | InterruptedException e) {
logger.error(
"Waited 30s for drain but it did not complete, continuing to shutdown", e);
}
}
Process stopper = stopCass.start();
try {
int code = stopper.waitFor();
if (code == 0) {
logger.info("Cassandra server has been stopped");
this.cassMonitorMetrics.incCassStop();
instanceState.setCassandraProcessAlive(false);
} else {
logger.error("Unable to stop cassandra server. Error code: {}", code);
logProcessOutput(stopper);
}
} catch (Exception e) {
logger.warn("couldn't shut down cassandra correctly", e);
}
}