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
This commit is contained in:
@@ -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<T> 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<T> 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<T>
|
||||
{
|
||||
public Map<String, T> getNodeResults ();
|
||||
public Map<String, String> getNodeErrors ();
|
||||
boolean wasDropped ();
|
||||
}
|
||||
}
|
||||
@@ -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 <T> void invokeNodeRequest (final NodeRequest request, final NodeRequestsListener<T> 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<String, T> results = Maps.newHashMap();
|
||||
final Map<String, String> 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<T>
|
||||
implements NodeRequestsListener.NodeRequestsResult<T>
|
||||
{
|
||||
public NodeRequestsResultImpl (Map<String, T> results, Map<String, String> errors)
|
||||
{
|
||||
_results = Maps.newHashMap(results);
|
||||
_errors = Maps.newHashMap(errors);
|
||||
}
|
||||
|
||||
public NodeRequestsResultImpl ()
|
||||
{
|
||||
this(Collections.EMPTY_MAP, Collections.EMPTY_MAP);
|
||||
}
|
||||
|
||||
@Override public Map<String, T> getNodeResults ()
|
||||
{
|
||||
return _results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getNodeErrors ()
|
||||
{
|
||||
return _errors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wasDropped ()
|
||||
{
|
||||
return _results.isEmpty() && _errors.isEmpty();
|
||||
}
|
||||
|
||||
protected Map<String, T> _results;
|
||||
protected Map<String, String> _errors;
|
||||
}
|
||||
|
||||
|
||||
/** Extracts the node object from the supplied peer. */
|
||||
protected static final Function<PeerNode, NodeObject> GET_NODE_OBJECT =
|
||||
new Function<PeerNode, NodeObject>() {
|
||||
|
||||
Reference in New Issue
Block a user