From 5365b53ee677907646e21d34f5ae2f4b1ba23c81 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Tue, 7 Sep 2010 19:08:26 +0000 Subject: [PATCH] Let's take invokdeNodeRequest the final distance; NodeRequest allows each peer to submit a result, so let's pass those results back to the caller instead of throwing them away. With this, we should be able to stop shoving all complex peer operations into PeerManager subclasses, and instead sprinkling them as NodeRequests in the sub-packages in which they belong. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6141 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../peer/server/NodeRequestsListener.java | 32 +++++++++ .../presents/peer/server/PeerManager.java | 68 +++++++++++++++---- 2 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 src/java/com/threerings/presents/peer/server/NodeRequestsListener.java diff --git a/src/java/com/threerings/presents/peer/server/NodeRequestsListener.java b/src/java/com/threerings/presents/peer/server/NodeRequestsListener.java new file mode 100644 index 000000000..a398657bf --- /dev/null +++ b/src/java/com/threerings/presents/peer/server/NodeRequestsListener.java @@ -0,0 +1,32 @@ +package com.threerings.presents.peer.server; + +import java.util.Map; + +import com.threerings.presents.client.InvocationService; + +/** + * Communicates the {@link NodeRequestsResult} of a {@link PeerManager.NodeRequest} sent to one + * or more peer nodes. + */ +public interface + NodeRequestsListener extends InvocationService.InvocationListener +{ + /** + * Called upon the successful completion of {@link PeerManager#invokeNodeRequest}, regardless + * of how many nodes were contacted or applicable. + */ + public void requestsProcessed (NodeRequestsResult result); + + /** + * Contains the result of a {@link PeerManager.NodeRequest} sent to one or more peer nodes. + * Any node that returned true for {@link PeerManager.NodeRequest#isApplicable} will appear + * in either {@link #getNodeResults()} or {@link #getNodeErrors()}. The wasDropped() method + * will return true iff both mappings are empty. + */ + public interface NodeRequestsResult + { + public Map getNodeResults (); + public Map getNodeErrors (); + boolean wasDropped (); + } +} diff --git a/src/java/com/threerings/presents/peer/server/PeerManager.java b/src/java/com/threerings/presents/peer/server/PeerManager.java index 9b32ca59c..d06396628 100644 --- a/src/java/com/threerings/presents/peer/server/PeerManager.java +++ b/src/java/com/threerings/presents/peer/server/PeerManager.java @@ -471,15 +471,13 @@ public abstract class PeerManager * If any one node reports failure, this function reports failure. If all nodes report success, * this function will report success. */ - public void invokeNodeRequest ( - final NodeRequest request, final InvocationService.ConfirmListener listener, - final Runnable onDropped) + public void invokeNodeRequest (final NodeRequest request, final NodeRequestsListener listener) { // if we're not on the dobjmgr thread, get there if (!_omgr.isDispatchThread()) { _omgr.postRunnable(new Runnable() { public void run () { - invokeNodeRequest(request, listener, onDropped); + invokeNodeRequest(request, listener); } }); return; @@ -498,24 +496,32 @@ public abstract class PeerManager nodes.add(peer.getNodeName()); } } - if (nodes.isEmpty() && onDropped != null) { - onDropped.run(); + if (nodes.isEmpty()) { + listener.requestsProcessed(new NodeRequestsResultImpl()); return; } + final Map results = Maps.newHashMap(); + final Map failures = Maps.newHashMap(); for (final String node : nodes) { invokeNodeRequest(node, requestBytes, new InvocationService.ResultListener() { public void requestProcessed (Object result) { // check off this node's successful response - nodes.remove(node); - if (nodes.isEmpty()) { - // if all nodes have responded in the affirmative, let caller know - listener.requestProcessed(); - } + @SuppressWarnings("unchecked") + T castResult = (T) result; + results.put(node, castResult); + nodeDone(node); } public void requestFailed (String cause) { - // let the caller know a node failed - listener.requestFailed(cause); + failures.put(node, cause); + nodeDone(node); + } + protected void nodeDone (String node) { + nodes.remove(node); + if (nodes.isEmpty()) { + // if all nodes have responded, let caller know + listener.requestsProcessed(new NodeRequestsResultImpl(results, failures)); + } } }); } @@ -1520,6 +1526,42 @@ public abstract class PeerManager protected long _startStamp = System.currentTimeMillis(); } + protected static class NodeRequestsResultImpl + implements NodeRequestsListener.NodeRequestsResult + { + public NodeRequestsResultImpl (Map results, Map errors) + { + _results = Maps.newHashMap(results); + _errors = Maps.newHashMap(errors); + } + + public NodeRequestsResultImpl () + { + this(Collections.EMPTY_MAP, Collections.EMPTY_MAP); + } + + @Override public Map getNodeResults () + { + return _results; + } + + @Override + public Map getNodeErrors () + { + return _errors; + } + + @Override + public boolean wasDropped () + { + return _results.isEmpty() && _errors.isEmpty(); + } + + protected Map _results; + protected Map _errors; + } + + /** Extracts the node object from the supplied peer. */ protected static final Function GET_NODE_OBJECT = new Function() {