package edu.uw.zookeeper;
import static com.google.common.base.Preconditions.checkNotNull;
import net.engio.mbassy.common.IConcurrentSet;
import net.engio.mbassy.common.StrongConcurrentSet;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListenableFuture;
import edu.uw.zookeeper.client.ClientExecutor;
import edu.uw.zookeeper.common.Processors;
import edu.uw.zookeeper.common.Promise;
import edu.uw.zookeeper.common.SettableFuturePromise;
import edu.uw.zookeeper.data.NameTrie;
import edu.uw.zookeeper.data.SimpleLabelTrie;
import edu.uw.zookeeper.data.TxnOperation;
import edu.uw.zookeeper.data.ZNodeNode;
import edu.uw.zookeeper.protocol.Message;
import edu.uw.zookeeper.protocol.ProtocolResponseMessage;
import edu.uw.zookeeper.protocol.SessionListener;
import edu.uw.zookeeper.protocol.SessionOperation;
import edu.uw.zookeeper.protocol.proto.Records;
import edu.uw.zookeeper.protocol.server.AssignZxidProcessor;
import edu.uw.zookeeper.server.ByOpcodeTxnRequestProcessor;
import edu.uw.zookeeper.server.RequestErrorProcessor;
import edu.uw.zookeeper.server.ToTxnRequestProcessor;
import edu.uw.zookeeper.protocol.server.ZxidGenerator;
import edu.uw.zookeeper.protocol.server.ZxidIncrementer;
// FIXME: notifications
public class ZNodeTrieExecutor implements ClientExecutor<SessionOperation.Request<?>, Message.ServerResponse<?>, SessionListener>,
Processors.UncheckedProcessor<SessionOperation.Request<?>, Message.ServerResponse<?>> {
public static ZNodeTrieExecutor defaults() {
return newInstance(
SimpleLabelTrie.forRoot(ZNodeNode.root()),
ZxidIncrementer.fromZero(),
new StrongConcurrentSet<SessionListener>());
}
public static ZNodeTrieExecutor newInstance(
NameTrie<ZNodeNode> trie,
ZxidGenerator zxids,
IConcurrentSet<SessionListener> listeners) {
return new ZNodeTrieExecutor(trie, zxids, listeners);
}
protected final IConcurrentSet<SessionListener> listeners;
protected final NameTrie<ZNodeNode> trie;
protected final RequestErrorProcessor<TxnOperation.Request<?>> operator;
protected final ToTxnRequestProcessor txnProcessor;
public ZNodeTrieExecutor(
NameTrie<ZNodeNode> trie,
ZxidGenerator zxids,
IConcurrentSet<SessionListener> listeners) {
this.trie = checkNotNull(trie);
this.listeners = checkNotNull(listeners);
this.txnProcessor = ToTxnRequestProcessor.create(
AssignZxidProcessor.newInstance(zxids));
this.operator = RequestErrorProcessor.create(
ByOpcodeTxnRequestProcessor.create(
ImmutableMap.copyOf(ZNodeNode.Operators.of(trie))));
}
@Override
public ListenableFuture<Message.ServerResponse<?>> submit(
SessionOperation.Request<?> request) {
return submit(request, SettableFuturePromise.<Message.ServerResponse<?>>create());
}
@Override
public synchronized ListenableFuture<Message.ServerResponse<?>> submit(
SessionOperation.Request<?> request,
Promise<Message.ServerResponse<?>> promise) {
Message.ServerResponse<?> result = apply(request);
promise.set(result);
return promise;
}
@Override
public synchronized Message.ServerResponse<?> apply(SessionOperation.Request<?> input) {
TxnOperation.Request<?> request = txnProcessor.apply(input);
Message.ServerResponse<Records.Response> response = ProtocolResponseMessage.of(request.xid(), request.zxid(), operator.apply(request));
return response;
}
@Override
public void subscribe(SessionListener listener) {
listeners.add(listener);
}
@Override
public boolean unsubscribe(SessionListener listener) {
return listeners.remove(listener);
}
}