package org.apache.blur.zookeeper;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.blur.log.Log;
import org.apache.blur.log.LogFactory;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class ZkUtils {
private final static Log LOG = LogFactory.getLog(ZkUtils.class);
public static final int ANY_VERSION = -1;
public static class ConnectionWatcher implements Watcher {
private String zkConnectionString;
private int sessionTimeout;
public void setZkConnectionString(String zkConnectionString) {
this.zkConnectionString = zkConnectionString;
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
@Override
public void process(WatchedEvent event) {
KeeperState state = event.getState();
LOG.info("ZooKeeper [{0}] timeout [{1}] changed to [{2}] state", zkConnectionString, sessionTimeout, state);
}
}
public static void pause(Object o) {
synchronized (o) {
try {
o.wait(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException e) {
return;
}
}
}
public static ZooKeeper newZooKeeper(String zkConnectionString, int sessionTimeout) throws IOException {
ConnectionWatcher watcher = new ConnectionWatcher();
watcher.setSessionTimeout(sessionTimeout);
watcher.setZkConnectionString(zkConnectionString);
return new ZooKeeperClient(zkConnectionString, sessionTimeout, watcher);
}
public static void mkNodesStr(ZooKeeper zk, String path) {
if (path == null) {
return;
}
mkNodes(zk, path.split("/"));
}
public static void mkNodes(ZooKeeper zk, String... path) {
if (path == null) {
return;
}
for (int i = 0; i < path.length; i++) {
StringBuilder builder = new StringBuilder();
for (int j = 0; j <= i; j++) {
if (!path[j].isEmpty()) {
builder.append('/');
builder.append(path[j]);
}
}
String pathToCheck = removeDupSeps(builder.toString());
if (pathToCheck.isEmpty()) {
continue;
}
try {
if (zk.exists(pathToCheck, false) == null) {
zk.create(pathToCheck, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
} catch (NodeExistsException e) {
// do nothing
} catch (KeeperException e) {
LOG.error("error", e);
throw new RuntimeException(e);
} catch (InterruptedException e) {
LOG.error("error", e);
throw new RuntimeException(e);
}
}
}
private static String removeDupSeps(String path) {
return path.replace("//", "/");
}
public static String getPath(String... parts) {
if (parts == null || parts.length == 0) {
return null;
}
StringBuilder builder = new StringBuilder(parts[0]);
for (int i = 1; i < parts.length; i++) {
builder.append('/');
builder.append(parts[i]);
}
return builder.toString();
}
public static boolean exists(ZooKeeper zk, String... path) {
if (path == null || path.length == 0) {
return true;
}
StringBuilder builder = new StringBuilder(path[0]);
for (int i = 1; i < path.length; i++) {
builder.append('/').append(path[i]);
}
try {
return zk.exists(builder.toString(), false) != null;
} catch (KeeperException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void deleteAnyVersion(ZooKeeper zk, String path) {
try {
List<String> children = zk.getChildren(path, false);
for (String c : children) {
deleteAnyVersion(zk, path + "/" + c);
}
zk.delete(path, ANY_VERSION);
} catch (KeeperException e) {
if (e.code() == KeeperException.Code.NONODE) {
return;
}
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void waitUntilExists(ZooKeeper zooKeeper, String path) {
final Object o = new Object();
try {
while (true) {
Stat stat = zooKeeper.exists(path, new Watcher() {
@Override
public void process(WatchedEvent event) {
synchronized (o) {
o.notifyAll();
}
}
});
if (stat == null) {
synchronized (o) {
o.wait();
}
} else {
return;
}
}
} catch (KeeperException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void rmr(ZooKeeper zooKeeper, String path) throws KeeperException, InterruptedException {
List<String> children = zooKeeper.getChildren(path, false);
for (String c : children) {
rmr(zooKeeper, path + "/" + c);
}
zooKeeper.delete(path, -1);
}
}