package com.baidu.disconf.core.common.zookeeper.inner;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ZK读写
*
* @author liaoqiqi
* @version 2014-7-7
*/
public class ResilientActiveKeyValueStore extends ConnectionWatcher {
protected static final Logger LOGGER = LoggerFactory.getLogger(ResilientActiveKeyValueStore.class);
private static final Charset CHARSET = Charset.forName("UTF-8");
// 最大重试次数
public static final int MAX_RETRIES = 3;
// 每次重试超时时间
public static final int RETRY_PERIOD_SECONDS = 2;
/**
* @param debug
*/
public ResilientActiveKeyValueStore(boolean debug) {
super(debug);
}
/**
* @param path
* @param value
*
* @return void
*
* @throws InterruptedException
* @throws KeeperException
* @Description: 写PATH数据, 是持久化的
* @author liaoqiqi
* @date 2013-6-14
*/
public void write(String path, String value) throws InterruptedException, KeeperException {
int retries = 0;
while (true) {
try {
Stat stat = zk.exists(path, false);
if (stat == null) {
zk.create(path, value.getBytes(CHARSET), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
} else {
zk.setData(path, value.getBytes(CHARSET), stat.getVersion());
}
break;
} catch (KeeperException.SessionExpiredException e) {
throw e;
} catch (KeeperException e) {
LOGGER.warn("write connect lost... will retry " + retries + "\t" + e.toString());
if (retries++ == MAX_RETRIES) {
throw e;
}
// sleep then retry
int sec = RETRY_PERIOD_SECONDS * retries;
LOGGER.warn("sleep " + sec);
TimeUnit.SECONDS.sleep(sec);
}
}
}
/**
* @param path
* @param value
*
* @return void
*
* @throws InterruptedException
* @throws KeeperException
* @Description: 创建一个临时结点,如果原本存在,则不新建, 如果存在,则更新值
* @author liaoqiqi
* @date 2013-6-14
*/
public String createEphemeralNode(String path, String value, CreateMode createMode)
throws InterruptedException, KeeperException {
int retries = 0;
while (true) {
try {
Stat stat = zk.exists(path, false);
if (stat == null) {
return zk.create(path, value.getBytes(CHARSET), Ids.OPEN_ACL_UNSAFE, createMode);
} else {
if (value != null) {
zk.setData(path, value.getBytes(CHARSET), stat.getVersion());
}
}
return path;
} catch (KeeperException.SessionExpiredException e) {
throw e;
} catch (KeeperException e) {
LOGGER.warn("createEphemeralNode connect lost... will retry " + retries + "\t" + e.toString());
if (retries++ == MAX_RETRIES) {
throw e;
}
// sleep then retry
int sec = RETRY_PERIOD_SECONDS * retries;
LOGGER.warn("sleep " + sec);
TimeUnit.SECONDS.sleep(sec);
}
}
}
/**
* 判断是否存在
*
* @param path
*
* @return
*
* @throws InterruptedException
* @throws KeeperException
*/
public boolean exists(String path) throws InterruptedException, KeeperException {
int retries = 0;
while (true) {
try {
Stat stat = zk.exists(path, false);
if (stat == null) {
return false;
} else {
return true;
}
} catch (KeeperException.SessionExpiredException e) {
throw e;
} catch (KeeperException e) {
LOGGER.warn("exists connect lost... will retry " + retries + "\t" + e.toString());
if (retries++ == MAX_RETRIES) {
LOGGER.error("connect final failed");
throw e;
}
// sleep then retry
int sec = RETRY_PERIOD_SECONDS * retries;
LOGGER.warn("sleep " + sec);
TimeUnit.SECONDS.sleep(sec);
}
}
}
/**
* @param path
* @param watcher
*
* @return String
*
* @throws InterruptedException
* @throws KeeperException
* @Description: 读数据
* @author liaoqiqi
* @date 2013-6-14
*/
public String read(String path, Watcher watcher, Stat stat) throws InterruptedException, KeeperException {
byte[] data = zk.getData(path, watcher, stat);
return new String(data, CHARSET);
}
/**
* @return List<String>
*
* @Description: 获取子孩子数据
* @author liaoqiqi
* @date 2013-6-14
*/
public List<String> getRootChildren() {
List<String> children = new ArrayList<String>();
try {
children = zk.getChildren("/", false);
} catch (KeeperException e) {
LOGGER.error(e.toString());
} catch (InterruptedException e) {
LOGGER.error(e.toString());
}
return children;
}
/**
* @param path
*
* @return void
*
* @Description: 删除结点
* @author liaoqiqi
* @date 2013-6-17
*/
public void deleteNode(String path) {
try {
zk.delete(path, -1);
} catch (KeeperException.NoNodeException e) {
LOGGER.error("cannot delete path: " + path, e);
} catch (InterruptedException e) {
LOGGER.warn(e.toString());
} catch (KeeperException e) {
LOGGER.error("cannot delete path: " + path, e);
}
}
}