下面列出了org.apache.zookeeper.KeeperException#NotEmptyException ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Tries to delete empty parent znodes.
*
* <p>IMPORTANT: This method can be removed once all supported ZooKeeper versions
* support the container {@link org.apache.zookeeper.CreateMode}.
*
* @throws Exception if the deletion fails for other reason than {@link KeeperException.NotEmptyException}
*/
private void tryDeleteEmptyParentZNodes() throws Exception {
// try to delete the parent znodes if they are empty
String remainingPath = getParentPath(getNormalizedPath(client.getNamespace()));
final CuratorFramework nonNamespaceClient = client.usingNamespace(null);
while (!isRootPath(remainingPath)) {
try {
nonNamespaceClient.delete().forPath(remainingPath);
} catch (KeeperException.NotEmptyException ignored) {
// We can only delete empty znodes
break;
}
remainingPath = getParentPath(remainingPath);
}
}
/**
* Tries to delete empty parent znodes.
*
* <p>IMPORTANT: This method can be removed once all supported ZooKeeper versions
* support the container {@link org.apache.zookeeper.CreateMode}.
*
* @throws Exception if the deletion fails for other reason than {@link KeeperException.NotEmptyException}
*/
private void tryDeleteEmptyParentZNodes() throws Exception {
// try to delete the parent znodes if they are empty
String remainingPath = getParentPath(getNormalizedPath(client.getNamespace()));
final CuratorFramework nonNamespaceClient = client.usingNamespace(null);
while (!isRootPath(remainingPath)) {
try {
nonNamespaceClient.delete().forPath(remainingPath);
} catch (KeeperException.NotEmptyException ignored) {
// We can only delete empty znodes
break;
}
remainingPath = getParentPath(remainingPath);
}
}
private void deleteBranch(final String key) throws KeeperException, InterruptedException {
deleteChildren(key, false);
Stack<String> pathStack = getProvider().getDeletingPaths(key);
while (!pathStack.empty()) {
String node = pathStack.pop();
// contrast cache
if (getProvider().exists(node)) {
try {
getProvider().delete(node);
} catch (KeeperException.NotEmptyException e) {
log.warn("deleteBranch {} exist other children: {}", node, this.getChildren(node));
return;
}
}
log.info("deleteBranch node not exist: {}", node);
}
}
/**
* Deletes the given ZK path.
*
* @param path path to delete
* @return true if the path was deleted, false if failed to delete due to {@link KeeperException.NotEmptyException}.
* @throws Exception if failed to delete the path
*/
private boolean delete(String path) throws Exception {
try {
LOG.info("Removing ZK path: {}{}", zkClient.getConnectString(), path);
zkClient.delete(path).get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
return true;
} catch (ExecutionException e) {
if (e.getCause() instanceof KeeperException.NotEmptyException) {
return false;
}
if (e.getCause() instanceof KeeperException.NoNodeException) {
// If the node to be deleted was not created or is already gone, it is the same as delete successfully.
return true;
}
throw e;
}
}
/**
* Delete a path and all of its sub nodes
* @param filter for node to be deleted
*/
public static void clean(SolrZkClient zkClient, String path, Predicate<String> filter) throws InterruptedException, KeeperException {
if (filter == null) {
clean(zkClient, path);
return;
}
TreeSet<String> paths = new TreeSet<>(Comparator.comparingInt(String::length).reversed());
traverseZkTree(zkClient, path, VISIT_ORDER.VISIT_POST, znode -> {
if (!znode.equals("/") && filter.test(znode)) paths.add(znode);
});
for (String subpath : paths) {
if (!subpath.equals("/")) {
try {
zkClient.delete(subpath, -1, true);
} catch (KeeperException.NotEmptyException | KeeperException.NoNodeException e) {
// expected
}
}
}
}
/**
* Releases the lock for the given state node and tries to remove the state node if it is no longer locked.
* It returns the {@link RetrievableStateHandle} stored under the given state node if any.
*
* @param pathInZooKeeper Path of state handle to remove
* @return True if the state handle could be released
* @throws Exception If the ZooKeeper operation or discarding the state handle fails
*/
@Nullable
public boolean releaseAndTryRemove(String pathInZooKeeper) throws Exception {
checkNotNull(pathInZooKeeper, "Path in ZooKeeper");
final String path = normalizePath(pathInZooKeeper);
RetrievableStateHandle<T> stateHandle = null;
try {
stateHandle = get(path, false);
} catch (Exception e) {
LOG.warn("Could not retrieve the state handle from node {}.", path, e);
}
release(pathInZooKeeper);
try {
client.delete().forPath(path);
} catch (KeeperException.NotEmptyException ignored) {
LOG.debug("Could not delete znode {} because it is still locked.", path);
return false;
}
if (stateHandle != null) {
stateHandle.discardState();
}
return true;
}
/**
* Releases the lock for the given state node and tries to remove the state node if it is no longer locked.
* It returns the {@link RetrievableStateHandle} stored under the given state node if any.
*
* @param pathInZooKeeper Path of state handle to remove
* @return True if the state handle could be released
* @throws Exception If the ZooKeeper operation or discarding the state handle fails
*/
public boolean releaseAndTryRemove(String pathInZooKeeper) throws Exception {
checkNotNull(pathInZooKeeper, "Path in ZooKeeper");
final String path = normalizePath(pathInZooKeeper);
RetrievableStateHandle<T> stateHandle = null;
try {
stateHandle = get(path, false);
} catch (Exception e) {
LOG.warn("Could not retrieve the state handle from node {}.", path, e);
}
release(pathInZooKeeper);
try {
client.delete().forPath(path);
} catch (KeeperException.NotEmptyException ignored) {
LOG.debug("Could not delete znode {} because it is still locked.", path);
return false;
}
if (stateHandle != null) {
stateHandle.discardState();
}
return true;
}
protected final void deleteNamespace() throws KeeperException, InterruptedException {
try {
holder.getZooKeeper().delete(rootNode, ZookeeperConstants.VERSION);
} catch (final KeeperException.NodeExistsException | KeeperException.NotEmptyException ex) {
log.info("delete root :{}", ex.getMessage());
}
rootExist = false;
}
private void deleteRecursively(final String path) throws KeeperException, InterruptedException {
int index = path.lastIndexOf(ZookeeperConstants.PATH_SEPARATOR);
if (index == 0) {
deleteOnlyCurrent(path);
return;
}
String superPath = path.substring(0, index);
try {
deleteOnlyCurrent(path);
deleteRecursively(superPath);
} catch (final KeeperException.NotEmptyException ex) {
log.info("deleteRecursively exist children: {}, ex: {}", path, ex.getMessage());
}
}
public void run() {
try {
List<String> list = client.getChildren().forPath(path);
if (list == null || list.isEmpty()) {
client.delete().forPath(path);
}
} catch (KeeperException.NoNodeException e1) {
//nothing
} catch (KeeperException.NotEmptyException e2) {
//nothing
} catch (Exception e) {
log.error(e.getMessage(), e);//准备删除时,正好有线程创建锁
}
}
public void run() {
try {
List list = client.getChildren().forPath(path);
if (list == null || list.isEmpty()) {
client.delete().forPath(path);
}
} catch (KeeperException.NoNodeException e1) {
//nothing
} catch (KeeperException.NotEmptyException e2) {
//nothing
} catch (Exception e) {
log.error(e.getMessage(), e);//准备删除时,正好有线程创建锁
}
}
/** Deletes a node below the given directory root */
private void deleteNode(String pathString, boolean deleteChildren, Node root, Listeners listeners)
throws KeeperException.NoNodeException, KeeperException.NotEmptyException {
validatePath(pathString);
Path path = Path.fromString(pathString);
Node parent = root.getNode(Paths.get(path.getParentPath().toString()), false);
if (parent == null) throw new KeeperException.NoNodeException(path.toString());
Node node = parent.children().get(path.getName());
if (node == null) throw new KeeperException.NoNodeException(path.getName() + " under " + parent);
if ( ! node.children().isEmpty() && ! deleteChildren)
throw new KeeperException.NotEmptyException(path.toString());
parent.remove(path.getName());
listeners.notify(path, new byte[0], PathChildrenCacheEvent.Type.CHILD_REMOVED);
}
@Override
protected void shutDown() throws Exception {
super.shutDown();
// Deletes ZK nodes created for the application execution.
// We don't have to worry about a race condition if another instance of the same app starts at the same time
// as when removal is performed. This is because we always create nodes with "createParent == true",
// which takes care of the parent node recreation if it is removed from here.
// Try to delete the /instances path. It may throws NotEmptyException if there are other instances of the
// same app running, which we can safely ignore and return.
if (!delete(Constants.INSTANCES_PATH_PREFIX)) {
return;
}
// Try to delete children under /discovery. It may fail with NotEmptyException if there are other instances
// of the same app running that has discovery services running.
List<String> children = getChildren(Constants.DISCOVERY_PATH_PREFIX);
List<OperationFuture<?>> deleteFutures = new ArrayList<>();
for (String child : children) {
String path = Constants.DISCOVERY_PATH_PREFIX + "/" + child;
LOG.info("Removing ZK path: {}{}", zkClient.getConnectString(), path);
deleteFutures.add(zkClient.delete(path));
}
Futures.successfulAsList(deleteFutures).get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
for (OperationFuture<?> future : deleteFutures) {
try {
future.get();
} catch (ExecutionException e) {
if (e.getCause() instanceof KeeperException.NotEmptyException) {
// If any deletion of the service failed with not empty, if means there are other apps running,
// hence just return
return;
}
if (e.getCause() instanceof KeeperException.NoNodeException) {
// If the service node is gone, it maybe deleted by another app instance that is also shutting down,
// hence just keep going
continue;
}
throw e;
}
}
// Delete the /discovery. It may fail with NotEmptyException (due to race between apps),
// which can safely ignore and return.
if (!delete(Constants.DISCOVERY_PATH_PREFIX)) {
return;
}
// Delete the ZK path for the app namespace.
delete("/");
}
@Override
public void dropInstance(String clusterName, InstanceConfig instanceConfig) {
logger.info("Drop instance {} from cluster {}.", instanceConfig.getInstanceName(), clusterName);
String instanceName = instanceConfig.getInstanceName();
String instanceConfigPath = PropertyPathBuilder.instanceConfig(clusterName, instanceName);
if (!_zkClient.exists(instanceConfigPath)) {
throw new HelixException(
"Node " + instanceName + " does not exist in config for cluster " + clusterName);
}
String instancePath = PropertyPathBuilder.instance(clusterName, instanceName);
if (!_zkClient.exists(instancePath)) {
throw new HelixException(
"Node " + instanceName + " does not exist in instances for cluster " + clusterName);
}
String liveInstancePath = PropertyPathBuilder.liveInstance(clusterName, instanceName);
if (_zkClient.exists(liveInstancePath)) {
throw new HelixException(
"Node " + instanceName + " is still alive for cluster " + clusterName + ", can't drop.");
}
// delete config path
String instanceConfigsPath = PropertyPathBuilder.instanceConfig(clusterName);
ZKUtil.dropChildren(_zkClient, instanceConfigsPath, instanceConfig.getRecord());
// delete instance path
int retryCnt = 0;
while (true) {
try {
_zkClient.deleteRecursively(instancePath);
return;
} catch (ZkClientException e) {
if (retryCnt < 3 && e.getCause() instanceof ZkException && e.getCause()
.getCause() instanceof KeeperException.NotEmptyException) {
// Racing condition with controller's persisting node history, retryable.
// We don't need to backoff here as this racing condition only happens once (controller
// does not repeatedly write instance history)
logger.warn("Retrying dropping instance {} with exception {}",
instanceConfig.getInstanceName(), e.getCause().getMessage());
retryCnt++;
} else {
String errorMessage = "Failed to drop instance: " + instanceConfig.getInstanceName()
+ ". Retry times: " + retryCnt;
logger.error(errorMessage, e);
throw new HelixException(errorMessage, e);
}
}
}
}