package com.nvarghese.beowulf.common.zookeeper;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ZkClientRunner will create the group in zookeeper, and joins as an ephemeral
* node for indefinite time
*
* @author nibin
*
*/
public class ZkClientRunner implements Runnable {
private ZooKeeper zk;
private ZkConnectionWatcher zkConnectionWatcher;
private final String connectString;
private final String groupName;
private Thread thread;
private final String memberIpAddressAndPort;
private static final int SESSION_TIMEOUT = 5000;
static Logger logger = LoggerFactory.getLogger(ZkClientRunner.class);
public ZkClientRunner(String connectString, String memberIpAddressAndPort, String groupName) {
zkConnectionWatcher = new ZkConnectionWatcher();
this.connectString = connectString;
this.memberIpAddressAndPort = memberIpAddressAndPort;
this.groupName = groupName;
thread = new Thread(this, "zkClientRunner");
}
public String getGroupName() {
return groupName;
}
public void connect() throws IOException {
logger.info("Connecting to zookeeper servers");
zk = new ZooKeeper(connectString, SESSION_TIMEOUT, zkConnectionWatcher);
try {
zkConnectionWatcher.getConnectSignal().await();
logger.info("Connection established with zookeeper servers");
} catch (InterruptedException ie) {
}
}
/**
* If group doesn't exit, then this will create the group
*
* @throws InterruptedException
* @throws KeeperException
*/
public void createGroup() throws KeeperException, InterruptedException {
Stat stat;
String path = "/" + this.groupName;
stat = zk.exists(path, false);
if (stat == null) {
logger.info("`{}` group doesn't exist in zookeeper. Trying to create the group", groupName);
String createdPath = zk.create(path, null/* data */, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
logger.info("Created `{}` Group: {}", groupName, createdPath);
} else {
logger.info("`{}` group exists in zookeeper", groupName);
}
}
/**
* Joins the group with registered IPAddress
*
* @param memberIpAddressAndPort
* @throws InterruptedException
* @throws KeeperException
* @throws KeeperException
*/
private void joinGroup() throws InterruptedException, KeeperException {
String path = "/" + groupName + "/" + memberIpAddressAndPort;
String createdPath = zk.create(path, null/* data */, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
logger.info("Joined `{}` Group: {}", groupName, createdPath);
}
public boolean checkMemberInGroup() throws KeeperException, InterruptedException {
boolean exists = false;
Stat stat;
String path = "/" + groupName + "/" + memberIpAddressAndPort;
stat = zk.exists(path, false);
if (stat != null)
exists = true;
return exists;
}
private void close() throws InterruptedException {
zk.close();
}
@Override
public void run() {
try {
joinGroup();
/* stay alive indefinetly */
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException ie) {
} catch (KeeperException e) {
logger.error("KeeperException while ZkClientRunner join group", e);
} finally {
try {
close();
} catch (InterruptedException e) {
}
}
}
public void interupt() {
thread.interrupt();
}
public void start() {
thread.start();
}
}