in twill-zookeeper/src/main/java/org/apache/twill/zookeeper/ZKOperations.java [221:282]
public static OperationFuture<String> recursiveDelete(final ZKClient zkClient, final String path) {
final SettableOperationFuture<String> resultFuture =
SettableOperationFuture.create(path, Threads.SAME_THREAD_EXECUTOR);
// Try to delete the given path.
Futures.addCallback(zkClient.delete(path), new FutureCallback<String>() {
private final FutureCallback<String> deleteCallback = this;
@Override
public void onSuccess(String result) {
// Path deleted successfully. Operation done.
resultFuture.set(result);
}
@Override
public void onFailure(Throwable t) {
// Failed to delete the given path
if (!(t instanceof KeeperException.NotEmptyException || t instanceof KeeperException.NoNodeException)) {
// For errors other than NotEmptyException, treat the operation as failed.
resultFuture.setException(t);
return;
}
// If failed because of NotEmptyException, get the list of children under the given path
Futures.addCallback(zkClient.getChildren(path), new FutureCallback<NodeChildren>() {
@Override
public void onSuccess(NodeChildren result) {
// Delete all children nodes recursively.
final List<OperationFuture<String>> deleteFutures = Lists.newLinkedList();
for (String child :result.getChildren()) {
deleteFutures.add(recursiveDelete(zkClient, path + "/" + child));
}
// When deletion of all children succeeded, delete the given path again.
Futures.successfulAsList(deleteFutures).addListener(new Runnable() {
@Override
public void run() {
for (OperationFuture<String> deleteFuture : deleteFutures) {
try {
// If any exception when deleting children, treat the operation as failed.
deleteFuture.get();
} catch (Exception e) {
resultFuture.setException(e.getCause());
}
}
Futures.addCallback(zkClient.delete(path), deleteCallback, Threads.SAME_THREAD_EXECUTOR);
}
}, Threads.SAME_THREAD_EXECUTOR);
}
@Override
public void onFailure(Throwable t) {
// If failed to get list of children, treat the operation as failed.
resultFuture.setException(t);
}
}, Threads.SAME_THREAD_EXECUTOR);
}
}, Threads.SAME_THREAD_EXECUTOR);
return resultFuture;
}