package com.autonavi.tinfo.t1.traffic.pub.openlr.util;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.zkclient.IZkChildListener;
import com.github.zkclient.IZkStateListener;
import com.github.zkclient.ZkClient;
public class StatusMonitor {
private Lock lock = new ReentrantLock();// 锁对象
private boolean usingHA = true;
private volatile boolean isLeader = false;
private static final Logger logger = LoggerFactory.getLogger(StatusMonitor.class);
// 超时时间
private int zkSessionTimeOut=5000;
private int zkConnectionTimeOut=5000;
//private int SESSION_TIMEOUT = 5000;
//private int CONNECTION_TIMEOUT = 5000;
// zookeeper server列表
private String zkServerList = "10.17.132.71:2181";
private String zkServerDir = "fast-update";
private String subNode = "openlr";
// 当前client创建的子节点
private String curPath;
private ZkClient zkClient;
ScheduledExecutorService intervalMonitorExecutor = Executors.newSingleThreadScheduledExecutor();
/**
* 连接zookeeper
*/
public void init() {
logger.info("StatusMonitor.init zkSessionTimeOut:{},zkConnectionTimeOut:{}",zkSessionTimeOut,zkConnectionTimeOut);
try {
connect();
} catch (Exception e) {
this.isLeader = false;
logger.error(e.getMessage(), e);
try {
connect();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
logger.error("error occurs during sync data from zk");
System.exit(0);
} finally {
;
}
}
intervalMonitorExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
lock.lock();
try {
if (zkClient == null) {
isLeader = false;
return;
}
if (zkClient != null && zkClient.getZooKeeper() == null) {
isLeader = false;
return;
}
if (zkClient != null && (!zkClient.getZooKeeper().getState().isAlive()
|| !zkClient.getZooKeeper().getState().isConnected())) {
isLeader = false;
return;
}
} finally {
lock.unlock();
}
}
}, 0, 2, TimeUnit.SECONDS);
}
public void connect() throws Exception {
if (!usingHA) {
return;
}
if (this.zkClient != null) {
this.zkClient.close();
}
this.zkClient = new ZkClient(zkServerList, zkSessionTimeOut, zkConnectionTimeOut);
if (!zkClient.exists("/" + zkServerDir)) {
zkClient.createPersistent("/" + zkServerDir, null);
}
if (curPath == null) {
curPath = zkClient.createEphemeralSequential("/" + zkServerDir + "/" + subNode, "monitor".getBytes());
}
try {
startWatchingTopicStatus();
} catch (Exception e) {
// TODO Auto-generated catch block
logger.error(e.getMessage(), e);
logger.error("error occurs during sync data from zk");
System.exit(0);
}
Thread.sleep(2000);// */
handleMonitorNodeChange();
}
public void startWatchingTopicStatus() {
ZkTopicStatusListener topicEventListener = new ZkTopicStatusListener();
ZkConnectedStatusListener connectedStatusListener = new ZkConnectedStatusListener();
try {
zkClient.subscribeChildChanges("/" + zkServerDir, topicEventListener);
zkClient.subscribeStateChanges(connectedStatusListener);
} catch (Exception e) {
logger.error(e.getMessage(), e);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
startWatchingTopicStatus();
}
}
public void stop() {
if (zkClient == null) {
logger.warn("shutdown topic event watcher");
return;
}
// stopWatchingTopicEvents();
zkClient.close();
zkClient = null;
}
private void beLeader() {
logger.info("this node gains lock {} and becomes leader ", curPath);
System.out.println("this node gains lock " + curPath + " and becomes leader");
this.isLeader = true;
}
public void setUsingHA(boolean isUsingHA) {
this.usingHA = isUsingHA;
}
public void setZkServerDir(String zkServerDir) {
this.zkServerDir = zkServerDir;
}
public boolean isUsingHA() {
return usingHA;
}
public boolean isLeader() {
return isLeader;
}
public void setZkServerList(String zkServerList) {
this.zkServerList = zkServerList;
}
/*public int getSESSION_TIMEOUT() {
return SESSION_TIMEOUT;
}
public void setSESSION_TIMEOUT(int sESSION_TIMEOUT) {
SESSION_TIMEOUT = sESSION_TIMEOUT;
}
public int getCONNECTION_TIMEOUT() {
return CONNECTION_TIMEOUT;
}
public void setCONNECTION_TIMEOUT(int cONNECTION_TIMEOUT) {
CONNECTION_TIMEOUT = cONNECTION_TIMEOUT;
}*/
public int getZkSessionTimeOut() {
return zkSessionTimeOut;
}
public void setZkSessionTimeOut(int zkSessionTimeOut) {
this.zkSessionTimeOut = zkSessionTimeOut;
}
public int getZkConnectionTimeOut() {
return zkConnectionTimeOut;
}
public void setZkConnectionTimeOut(int zkConnectionTimeOut) {
this.zkConnectionTimeOut = zkConnectionTimeOut;
}
public void handleMonitorNodeChange() throws Exception {
this.lock.lock();
try {
if (zkClient == null)
return;
if (!zkClient.exists("/" + zkServerDir)) {
zkClient.createPersistent("/" + zkServerDir, null);
}
// 确认curPath是否真的是列表中的最小节点
List<String> childs = zkClient.getChildren("/" + zkServerDir);
if (childs == null || childs.size() == 0) {
// 创建子节点
curPath = zkClient.createEphemeralSequential("/" + zkServerDir + "/" + subNode, "monitor".getBytes());
childs = zkClient.getChildren("/" + zkServerDir);
}
Collections.sort(childs);
String thisNode = curPath.substring(("/" + zkServerDir + "/").length());
int index = childs.indexOf(thisNode);
if (index < 0) {
curPath = zkClient.createEphemeralSequential("/" + zkServerDir + "/" + subNode, "monitor".getBytes());
childs = zkClient.getChildren("/" + zkServerDir);
Collections.sort(childs);
thisNode = curPath.substring(("/" + zkServerDir + "/").length());
index = childs.indexOf(thisNode);
}
if (index == 0) {
// 确实是最小节点
beLeader();
} else {
this.isLeader = false;
}
} finally {
this.lock.unlock();
}
}
class ZkTopicStatusListener implements IZkChildListener {
@Override
public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
handleMonitorNodeChange();
}
}
class ZkConnectedStatusListener implements IZkStateListener {
@Override
public void handleStateChanged(KeeperState state) throws Exception {
// TODO Auto-generated method stub
if (state.equals(state.SyncConnected) || state.equals(state.ConnectedReadOnly)) {
System.out.println("zookeeper start to be connected");
handleMonitorNodeChange();
}
}
@Override
public void handleNewSession() throws Exception {
// TODO Auto-generated method stub
}
}
public static void main(String[] args) throws Exception {
StatusMonitor statusMonitor = new StatusMonitor();
statusMonitor.setZkServerList("10.61.97.23:2181");
statusMonitor.setUsingHA(true);
statusMonitor.init();
Thread.sleep(100000000);
}
}