package io.fathom.auto.zookeeper;
import io.fathom.auto.TimeSpan;
import io.fathom.auto.processes.Pid;
import io.fathom.auto.processes.ProcFs;
import io.fathom.auto.processes.ProcessExecution;
import io.fathom.auto.processes.Processes;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
public class ZookeeperProcess {
private static final Logger log = LoggerFactory.getLogger(ZookeeperProcess.class);
private final Pid pid;
final ZookeeperConfig config;
public ZookeeperProcess(ZookeeperConfig config, Pid pid) {
this.config = config;
this.pid = pid;
}
static File getPidFile(File instanceDir) {
return new File(getDataDir(instanceDir), "zookeeper_server.pid");
}
private static File getDataDir(File instanceDir) {
return new File(instanceDir, "data");
}
static File getLogFile(File instanceDir) {
return new File(instanceDir, "zookeeper.out");
}
public static ZookeeperProcess start(ZookeeperConfig config) throws IOException {
File instanceDir = config.getInstanceDir();
File installDir = config.getInstallDir();
File startScript = new File(installDir, "bin/zkServer.sh");
List<String> args = Lists.newArrayList();
args.add(startScript.getAbsolutePath());
args.add("start");
args.add(config.getConfigFile().getAbsolutePath());
ProcessBuilder pb = new ProcessBuilder(args);
pb.directory(instanceDir);
ProcessExecution execution = Processes.run(pb, TimeSpan.minutes(1));
if (!execution.didExit()) {
throw new IOException("Timeout while starting zookeeper");
} else {
if (execution.getExitCode() == 0) {
log.info("Zookeeper started OK");
File pidFile = getPidFile(instanceDir);
Pid pid = Pid.read(pidFile);
if (pid == null) {
throw new IOException("Zookeeper started, but could not read pid from file");
}
return new ZookeeperProcess(config, pid);
} else {
throw new IOException("Error starting zookeeper process");
}
}
}
public static ZookeeperProcess find(ZookeeperConfig config) throws IOException {
File instanceDir = config.getInstanceDir();
File pidFile = getPidFile(instanceDir);
Pid pid = Pid.read(pidFile);
if (pid == null) {
log.info("No zookeeper pid");
return null;
}
if (!isZookeeper(pid)) {
log.info("Pid found, but was not zookeeper");
return null;
}
log.info("Found existing zookeeper: {}", pid);
return new ZookeeperProcess(config, pid);
}
public static boolean isZookeeper(Pid pid) throws IOException {
ProcFs.Process process = ProcFs.findProcess(pid);
if (process == null) {
log.info("Process went away (no process with pid)");
return false;
}
List<String> cmdline = process.getCmdline();
if (cmdline == null) {
// Process stopped
log.info("Process went away (no process with pid)");
return false;
}
if (cmdline.isEmpty()) {
log.info("Process went away (cmdline empty)");
return false;
}
String c = Joiner.on(" ").join(cmdline);
if (c.indexOf("org.apache.zookeeper.server") == -1) {
log.info("Process went away (cmdline is {})", c);
return false;
}
log.info("Matched zookeeper process (cmdline is {})", c);
return true;
}
}