package edu.uw.zookeeper.client.cli; import java.io.IOException; import java.util.Collections; import java.util.Set; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.util.concurrent.AbstractIdleService; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import edu.uw.zookeeper.client.ClientExecutor; import edu.uw.zookeeper.client.DeleteSubtree; import edu.uw.zookeeper.data.AbsoluteZNodePath; import edu.uw.zookeeper.data.ZNodePath; import edu.uw.zookeeper.protocol.proto.Records; public class RmrInvoker extends AbstractIdleService implements Invoker<RmrInvoker.Command> { @Invokes(commands={Command.class}) public static RmrInvoker create(Shell shell) { return new RmrInvoker(shell); } public static enum Command { @CommandDescriptor( names = {"rmr", "deleteall"}, description="Recursive delete", arguments = { @ArgumentDescriptor(token = TokenType.PATH)}) RMR; } protected final Shell shell; protected final Set<ListenableFuture<?>> pending; public RmrInvoker(Shell shell) { this.shell = shell; this.pending = Collections.synchronizedSet(Sets.<ListenableFuture<?>>newHashSet()); } @Override public void invoke(final Invocation<Command> input) throws Exception { ClientExecutor<? super Records.Request, ?, ?> client = shell.getEnvironment().get(ClientExecutorInvoker.CLIENT_KEY).getConnectionClientExecutor(); ZNodePath root = (ZNodePath) input.getArguments()[1]; final ListenableFuture<?> future = root.isRoot() ? DeleteSubtree.deleteChildren(root, client): DeleteSubtree.deleteAll((AbsoluteZNodePath) root, client); Futures.addCallback(future, new FutureCallback<Object>(){ @Override public void onSuccess(Object result) { pending.remove(future); try { shell.println(String.format("%s => OK", input)); shell.flush(); } catch (IOException e) { onFailure(e); } } @Override public void onFailure(Throwable t) { pending.remove(future); try { shell.printThrowable(new RuntimeException(String.format("%s => FAILED (%s)", input, t))); } catch (IOException e) { } if (isRunning()) { stopAsync(); } }}); pending.add(future); } @Override protected void startUp() throws Exception { for (Command command: Command.values()) { shell.getCommands().withCommand(command); } } @Override protected void shutDown() throws Exception { synchronized (pending) { for (ListenableFuture<?> e: Iterables.consumingIterable(pending)) { e.cancel(true); } } } }