
com.github.phantomthief.zookeeper.util.ZkUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zkconfig-resources Show documentation
Show all versions of zkconfig-resources Show documentation
A ZooKeeper based configuration resources holder
The newest version!
package com.github.phantomthief.zookeeper.util;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.throwIfUnchecked;
import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.Stream.concat;
import static java.util.stream.Stream.empty;
import static org.apache.commons.lang3.StringUtils.removeEnd;
import static org.apache.commons.lang3.StringUtils.removeStart;
import static org.apache.curator.framework.state.ConnectionState.RECONNECTED;
import static org.apache.curator.utils.ZKPaths.makePath;
import static org.apache.zookeeper.CreateMode.EPHEMERAL;
import static org.apache.zookeeper.CreateMode.PERSISTENT;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.framework.state.ConnectionStateListener;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import com.github.phantomthief.util.ThrowableFunction;
/**
* @author w.vela
* Created on 03/12/2016.
*/
public class ZkUtils {
private static final Logger logger = getLogger(ZkUtils.class);
private static final long DEFAULT_WAIT = SECONDS.toMillis(1);
private static final int INFINITY_LOOP = -1;
private ZkUtils() {
throw new UnsupportedOperationException();
}
public static String getStringFromZk(CuratorFramework client, String path) {
return getFromZk(client, path, String::new);
}
public static byte[] getBytesFromZk(CuratorFramework client, String path) {
return getFromZk(client, path, b -> b);
}
public static T getFromZk(CuratorFramework client, String path,
ThrowableFunction decoder) throws X {
checkNotNull(client);
checkNotNull(path);
checkNotNull(decoder);
try {
byte[] bytes = client.getData().forPath(path);
if (bytes == null) {
return null;
}
return decoder.apply(bytes);
} catch (NoNodeException e) {
return null;
} catch (Exception e) {
throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
public static void setToZk(CuratorFramework client, String path, byte[] value) {
setToZk(client, path, value, PERSISTENT);
}
/**
* use {@link #setToZk(CuratorFramework, String, byte[])}
* or {@link #createEphemeralNode(CuratorFramework, String, byte[])}
*/
@Deprecated
public static void setToZk(CuratorFramework client, String path, byte[] value,
CreateMode createMode) {
checkNotNull(client);
checkNotNull(path);
checkNotNull(value);
checkNotNull(createMode);
int retryTimes = 0;
while (retryTimes++ < 3) {
try {
client.setData().forPath(path, value);
break;
} catch (NoNodeException e) {
try {
client.create().creatingParentsIfNeeded().withMode(createMode)
.forPath(path, value);
break;
} catch (NodeExistsException retry) {
continue;
} catch (Exception toThrow) {
throwIfUnchecked(toThrow);
throw new RuntimeException(toThrow);
}
} catch (Exception toThrow) {
throwIfUnchecked(toThrow);
throw new RuntimeException(toThrow);
}
}
}
public static EphemeralNode createEphemeralNode(CuratorFramework client, String path,
byte[] value) throws NodeExistsException {
checkNotNull(client);
checkNotNull(path);
checkNotNull(value);
return new KeepEphemeralListener(client, path, value);
}
public static void removeFromZk(CuratorFramework client, String path) {
removeFromZk(client, path, false);
}
public static void removeFromZk(CuratorFramework client, String path,
boolean recruitDeletedChildren) {
checkNotNull(client);
checkNotNull(path);
try {
if (recruitDeletedChildren) {
client.delete().deletingChildrenIfNeeded().forPath(path);
} else {
client.delete().forPath(path);
}
} catch (NoNodeException e) {
logger.debug("no zookeeper path found:{}, ignore deleted.", path);
} catch (Exception e) {
throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
public static void changeZkValue(CuratorFramework client, String path,
Function changeFunction, Function decoder,
Function encoder) {
Function realFunction = old -> {
T decodedOld = decoder.apply(old);
return encoder.apply(changeFunction.apply(decodedOld));
};
changeZkValue(client, path, realFunction, INFINITY_LOOP, DEFAULT_WAIT);
}
public static boolean changeZkValue(CuratorFramework client, String path,
Function changeFunction, int retryTimes, long retryWait) {
int times = 0;
do {
try {
Stat stat = new Stat();
byte[] oldData = client.getData().storingStatIn(stat).forPath(path);
byte[] newData = changeFunction.apply(oldData);
client.setData().withVersion(stat.getVersion()).forPath(path, newData);
if (logger.isDebugEnabled()) {
logger.debug("success update znode:{} from {} to {}", path,
Arrays.toString(oldData), Arrays.toString(newData));
}
return true;
} catch (KeeperException.BadVersionException e) {
logger.debug("bad version for znode:{}, retry.{}", path, times);
} catch (NoNodeException e) {
byte[] newData = changeFunction.apply(null);
try {
client.create().creatingParentsIfNeeded().forPath(path, newData);
if (logger.isDebugEnabled()) {
logger.debug("success create znode:{} -> {}", path,
Arrays.toString(newData));
}
return true;
} catch (NodeExistsException ex) {
logger.debug("node exist for znode:{}, retry.{}", path, times);
} catch (Exception ex) {
logger.error("Ops.{}/{}", path, times, ex);
}
} catch (Exception e) {
logger.error("Ops.{}/{}", path, times, e);
times++;
sleepUninterruptibly(retryWait, MILLISECONDS);
}
} while (times < retryTimes || retryTimes == INFINITY_LOOP);
logger.warn("fail to change znode:{}, retry times:{}", path, times);
return false;
}
public static Stream getAllChildrenWithData(CuratorFramework curator, String parentPath){
String parentPath0 = removeEnd(parentPath, "/");
return getAllChildrenWithData0(curator, parentPath0);
}
private static Stream getAllChildrenWithData0(CuratorFramework curator, String parentPath) {
try {
List children = curator.getChildren().forPath(parentPath);
if (children.isEmpty()) {
return empty();
} else {
Stream original = children.stream()
.map(child -> makePath(parentPath, child)) //
.map(path -> toChildData(curator, path)) //
.filter(Objects::nonNull);
return concat(original,
children.stream() //
.map(child -> makePath(parentPath, child)) //
.flatMap(path -> getAllChildrenWithData0(curator, path)));
}
} catch (NoNodeException e) {
return empty();
} catch (Exception e) {
throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Nullable
private static ChildData toChildData(CuratorFramework curator, String path) {
Stat stat = new Stat();
try {
byte[] bytes = curator.getData().storingStatIn(stat).forPath(path);
return new ChildData(path, stat, bytes);
} catch (NoNodeException e) {
return null;
} catch (Exception e) {
throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
public static Stream getAllChildren(CuratorFramework curator, String parentPath) {
String parentPath0 = removeEnd(parentPath, "/");
return getAllChildren0(curator, parentPath0).map(p -> removeStart(p, parentPath0));
}
private static Stream getAllChildren0(CuratorFramework curator, String parentPath) {
try {
List children = curator.getChildren().forPath(parentPath);
if (children.isEmpty()) {
return children.stream();
} else {
Stream original = children.stream()
.map(child -> makePath(parentPath, child));
return concat(original,
children.stream() //
.map(child -> makePath(parentPath, child)) //
.flatMap(path -> getAllChildren0(curator, path)));
}
} catch (NoNodeException e) {
return empty();
} catch (Exception e) {
throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
static class KeepEphemeralListener implements EphemeralNode, ConnectionStateListener {
private final CuratorFramework originalClient;
private final String path;
private volatile byte[] value;
@GuardedBy("this")
private volatile boolean closed;
KeepEphemeralListener(CuratorFramework originalClient, String path, byte[] value)
throws NodeExistsException {
try {
originalClient.create().creatingParentsIfNeeded().withMode(EPHEMERAL).forPath(path,
value);
} catch (NodeExistsException e) {
throw e;
} catch (Exception e) {
throwIfUnchecked(e);
throw new RuntimeException(e);
}
this.originalClient = originalClient;
this.path = path;
this.value = value;
this.originalClient.getConnectionStateListenable().addListener(this);
}
@Override
public void close() throws Exception {
synchronized (this) {
closed = true;
originalClient.getConnectionStateListenable().removeListener(this);
try {
originalClient.delete().forPath(path);
} catch (NoNodeException e) {
// ignore
}
}
}
@Override
public void stateChanged(CuratorFramework client, ConnectionState newState) {
synchronized (this) {
if (closed) {
return;
}
if (newState == RECONNECTED) {
try {
if (originalClient.checkExists().forPath(path) == null) {
logger.info("try recovery ephemeral node for:{}", path);
originalClient.create().creatingParentsIfNeeded().withMode(EPHEMERAL)
.forPath(path, value);
}
} catch (NodeExistsException e) {
// ignore
} catch (Exception e) {
logger.error("", e);
}
}
}
}
@Override
public void updateValue(@Nonnull byte[] value) {
synchronized (this) {
if (closed) {
return;
}
this.value = checkNotNull(value);
try {
originalClient.setData().forPath(path, value);
} catch (NoNodeException e) {
try {
originalClient.create().creatingParentsIfNeeded().withMode(EPHEMERAL)
.forPath(path, value);
} catch (NodeExistsException e1) {
// ignore
} catch (Exception e1) {
throwIfUnchecked(e1);
throw new RuntimeException(e1);
}
} catch (Exception e) {
throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy