Sprinkled some functional programming onto node object handling.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5868 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2009-07-13 00:55:03 +00:00
parent 9cdd93ee11
commit 047dd3b871
@@ -21,6 +21,7 @@
package com.threerings.presents.peer.server; package com.threerings.presents.peer.server;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@@ -29,6 +30,9 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
@@ -214,6 +218,17 @@ public abstract class PeerManager
return _nodeobj; return _nodeobj;
} }
/**
* Returns an iterable over our node object and that of our peers.
*/
public Iterable<NodeObject> getNodeObjects ()
{
return Iterables.filter(
Iterables.concat(Collections.singleton(_nodeobj),
Iterables.transform(_peers.values(), GET_NODE_OBJECT)),
Predicates.notNull());
}
/** /**
* Initializes this peer manager and initiates the process of connecting to its peer nodes. * Initializes this peer manager and initiates the process of connecting to its peer nodes.
* This will also reconfigure the ConnectionManager and ClientManager with peer related bits, * This will also reconfigure the ConnectionManager and ClientManager with peer related bits,
@@ -302,35 +317,20 @@ public abstract class PeerManager
*/ */
public <T> T lookupNodeDatum (Function<NodeObject,T> op) public <T> T lookupNodeDatum (Function<NodeObject,T> op)
{ {
T value = op.apply(_nodeobj); for (T value : Iterables.transform(getNodeObjects(), op)) {
if (value != null) {
return value; return value;
} }
for (PeerNode peer : _peers.values()) { return null;
if (peer.nodeobj == null) {
continue;
}
value = op.apply(peer.nodeobj);
if (value != null) {
return value;
}
}
return value;
} }
/** /**
* Applies the supplied operation to all {@link NodeObject}s. The operation should not modify * Applies the supplied function to all {@link NodeObject}s. The operation should not modify
* the objects unless you really know what you're doing. More likely it will summarize * the objects unless you really know what you're doing. More likely it will summarize
* information contained therein. * information contained therein.
*/ */
public void applyToNodes (Function<NodeObject,Void> op) public <T> Iterable<T> applyToNodes (Function<NodeObject,T> op)
{ {
op.apply(_nodeobj); return Iterables.transform(getNodeObjects(), op);
for (PeerNode peer : _peers.values()) {
if (peer.nodeobj != null) {
op.apply(peer.nodeobj);
}
}
} }
/** /**
@@ -650,15 +650,9 @@ public abstract class PeerManager
*/ */
public String queryLock (NodeObject.Lock lock) public String queryLock (NodeObject.Lock lock)
{ {
// look for it in our own lock set for (NodeObject nodeobj : getNodeObjects()) {
if (_nodeobj.locks.contains(lock)) { if (nodeobj.locks.contains(lock)) {
return _nodeName; return nodeobj.nodeName;
}
// then in our peers
for (PeerNode peer : _peers.values()) {
if (peer.nodeobj != null && peer.nodeobj.locks.contains(lock)) {
return peer.getNodeName();
} }
} }
return null; return null;
@@ -1380,6 +1374,14 @@ public abstract class PeerManager
protected long _startStamp = System.currentTimeMillis(); protected long _startStamp = System.currentTimeMillis();
} }
/** Extracts the node object from the supplied peer. */
protected static final Function<PeerNode, NodeObject> GET_NODE_OBJECT =
new Function<PeerNode, NodeObject>() {
public NodeObject apply (PeerNode peer) {
return peer.nodeobj;
}
};
// (this need not use a runqueue as all it will do is post an invoker unit) // (this need not use a runqueue as all it will do is post an invoker unit)
protected Interval _peerRefresher = new Interval() { protected Interval _peerRefresher = new Interval() {
@Override public void expired () { @Override public void expired () {