Merge branch 'master' of github.com:threerings/narya
This commit is contained in:
@@ -31,6 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
@@ -61,6 +62,7 @@ import com.threerings.presents.annotation.PeerInvoker;
|
|||||||
import com.threerings.presents.client.Client;
|
import com.threerings.presents.client.Client;
|
||||||
import com.threerings.presents.client.InvocationService;
|
import com.threerings.presents.client.InvocationService;
|
||||||
import com.threerings.presents.data.ClientObject;
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.data.InvocationCodes;
|
||||||
import com.threerings.presents.dobj.DObject;
|
import com.threerings.presents.dobj.DObject;
|
||||||
import com.threerings.presents.dobj.ObjectAccessException;
|
import com.threerings.presents.dobj.ObjectAccessException;
|
||||||
import com.threerings.presents.dobj.Subscriber;
|
import com.threerings.presents.dobj.Subscriber;
|
||||||
@@ -319,9 +321,37 @@ public abstract class PeerManager
|
|||||||
String nodeName, String sharedSecret, String hostName, String publicHostName,
|
String nodeName, String sharedSecret, String hostName, String publicHostName,
|
||||||
String region, int port, String nodeNamespace)
|
String region, int port, String nodeNamespace)
|
||||||
{
|
{
|
||||||
_nodeNamespace = nodeNamespace;
|
init(nodeName, sharedSecret, hostName, publicHostName, region, port, nodeNamespace, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
* so this should not be called until <em>after</em> the main server has set up its client
|
||||||
|
* factory and authenticator.
|
||||||
|
*
|
||||||
|
* @param nodeName this node's unique name.
|
||||||
|
* @param sharedSecret a shared secret used to allow the peers to authenticate with one
|
||||||
|
* another.
|
||||||
|
* @param hostName the DNS name of the server running this node.
|
||||||
|
* @param publicHostName if non-null, a separate public DNS hostname by which the node is to
|
||||||
|
* be known to normal clients (we may want inter-peer communication to take place over a
|
||||||
|
* different network than the communication between real clients and the various peer
|
||||||
|
* servers).
|
||||||
|
* @param region the region in which the node lives, which may be null. Nodes in different
|
||||||
|
* regions must connect to each other through the public host name.
|
||||||
|
* @param port the port on which other nodes should connect to us.
|
||||||
|
* @param nodeNamespace The namespace for nodes to peer with. This node will connect to other
|
||||||
|
* nodes with the same prefix from the NODES table.
|
||||||
|
*/
|
||||||
|
public void init (
|
||||||
|
String nodeName, String sharedSecret, String hostName, String publicHostName,
|
||||||
|
String region, int port, String nodeNamespace, boolean adHoc)
|
||||||
|
{
|
||||||
_nodeName = nodeName;
|
_nodeName = nodeName;
|
||||||
_sharedSecret = sharedSecret;
|
_sharedSecret = sharedSecret;
|
||||||
|
_nodeNamespace = nodeNamespace;
|
||||||
|
_adHoc = adHoc;
|
||||||
|
|
||||||
// wire ourselves into the server
|
// wire ourselves into the server
|
||||||
_conmgr.addChainedAuthenticator(
|
_conmgr.addChainedAuthenticator(
|
||||||
@@ -343,7 +373,7 @@ public abstract class PeerManager
|
|||||||
_self = new NodeRecord(
|
_self = new NodeRecord(
|
||||||
_nodeName, hostName, (publicHostName == null) ? hostName : publicHostName,
|
_nodeName, hostName, (publicHostName == null) ? hostName : publicHostName,
|
||||||
region, port);
|
region, port);
|
||||||
if (_nodeName != null) {
|
if (!adHoc) {
|
||||||
_invoker.postUnit(new WriteOnlyUnit("registerNode(" + _self + ")") {
|
_invoker.postUnit(new WriteOnlyUnit("registerNode(" + _self + ")") {
|
||||||
@Override
|
@Override
|
||||||
public void invokePersist () throws Exception {
|
public void invokePersist () throws Exception {
|
||||||
@@ -359,11 +389,13 @@ public abstract class PeerManager
|
|||||||
_clmgr.addClientObserver(this);
|
_clmgr.addClientObserver(this);
|
||||||
|
|
||||||
// and start our peer refresh interval (this lives for the lifetime of the server)
|
// and start our peer refresh interval (this lives for the lifetime of the server)
|
||||||
_omgr.newInterval(new Runnable() {
|
if (!adHoc) {
|
||||||
public void run () {
|
_omgr.newInterval(new Runnable() {
|
||||||
refreshPeers();
|
public void run () {
|
||||||
}
|
refreshPeers();
|
||||||
}).schedule(5000L, 60*1000L);
|
}
|
||||||
|
}).schedule(5000L, 60*1000L);
|
||||||
|
}
|
||||||
|
|
||||||
// give derived classes an easy way to get in on the init action
|
// give derived classes an easy way to get in on the init action
|
||||||
didInit();
|
didInit();
|
||||||
@@ -491,8 +523,14 @@ public abstract class PeerManager
|
|||||||
{
|
{
|
||||||
PeerNode peer = _peers.get(nodeName);
|
PeerNode peer = _peers.get(nodeName);
|
||||||
if (peer != null) {
|
if (peer != null) {
|
||||||
peer.nodeobj.peerService.invokeAction(flattenAction(action));
|
if (peer.nodeobj != null) {
|
||||||
} else if (nodeName.equals(_nodeName)) {
|
peer.nodeobj.peerService.invokeAction(flattenAction(action));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.warning("Dropped NodeAction", "nodeName", nodeName, "action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (Objects.equal(nodeName, _nodeName)) {
|
||||||
invokeAction(null, flattenAction(action));
|
invokeAction(null, flattenAction(action));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -563,7 +601,7 @@ public abstract class PeerManager
|
|||||||
nodes.add(_nodeobj.nodeName);
|
nodes.add(_nodeobj.nodeName);
|
||||||
}
|
}
|
||||||
for (PeerNode peer : _peers.values()) {
|
for (PeerNode peer : _peers.values()) {
|
||||||
if (applicant.isApplicable(peer.nodeobj)) {
|
if (peer.nodeobj != null && applicant.isApplicable(peer.nodeobj)) {
|
||||||
nodes.add(peer.getNodeName());
|
nodes.add(peer.getNodeName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -599,7 +637,7 @@ public abstract class PeerManager
|
|||||||
public <T extends DObject> void proxyRemoteObject (
|
public <T extends DObject> void proxyRemoteObject (
|
||||||
final DObjectAddress remote, final ResultListener<Integer> listener)
|
final DObjectAddress remote, final ResultListener<Integer> listener)
|
||||||
{
|
{
|
||||||
if (remote.nodeName.equals(_nodeName)) {
|
if (Objects.equal(remote.nodeName, _nodeName)) {
|
||||||
// Still subscribe if the DObject is local to preserve the behavior of
|
// Still subscribe if the DObject is local to preserve the behavior of
|
||||||
// DObject.setDestroyOnLastSubscriberRemoved on the proxied object
|
// DObject.setDestroyOnLastSubscriberRemoved on the proxied object
|
||||||
_omgr.subscribeToObject(remote.oid, new Subscriber<T>() {
|
_omgr.subscribeToObject(remote.oid, new Subscriber<T>() {
|
||||||
@@ -666,7 +704,7 @@ public abstract class PeerManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If it's local, just remove the subscriber we added and bail
|
// If it's local, just remove the subscriber we added and bail
|
||||||
if (addr.nodeName.equals(_nodeName)) {
|
if (Objects.equal(addr.nodeName, _nodeName)) {
|
||||||
bits.right.removeSubscriber(bits.left);
|
bits.right.removeSubscriber(bits.left);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -696,7 +734,7 @@ public abstract class PeerManager
|
|||||||
*/
|
*/
|
||||||
public NodeObject getPeerNodeObject (String nodeName)
|
public NodeObject getPeerNodeObject (String nodeName)
|
||||||
{
|
{
|
||||||
if (_nodeName.equals(nodeName)) {
|
if (Objects.equal(_nodeName, nodeName)) {
|
||||||
return _nodeobj;
|
return _nodeobj;
|
||||||
}
|
}
|
||||||
PeerNode peer = _peers.get(nodeName);
|
PeerNode peer = _peers.get(nodeName);
|
||||||
@@ -719,7 +757,7 @@ public abstract class PeerManager
|
|||||||
*/
|
*/
|
||||||
public String getPeerPublicHostName (String nodeName)
|
public String getPeerPublicHostName (String nodeName)
|
||||||
{
|
{
|
||||||
if (_nodeName.equals(nodeName)) {
|
if (Objects.equal(_nodeName, nodeName)) {
|
||||||
return _self.publicHostName;
|
return _self.publicHostName;
|
||||||
}
|
}
|
||||||
PeerNode peer = _peers.get(nodeName);
|
PeerNode peer = _peers.get(nodeName);
|
||||||
@@ -733,7 +771,7 @@ public abstract class PeerManager
|
|||||||
*/
|
*/
|
||||||
public String getPeerInternalHostName (String nodeName)
|
public String getPeerInternalHostName (String nodeName)
|
||||||
{
|
{
|
||||||
if (_nodeName.equals(nodeName)) {
|
if (Objects.equal(_nodeName, nodeName)) {
|
||||||
return _self.hostName;
|
return _self.hostName;
|
||||||
}
|
}
|
||||||
PeerNode peer = _peers.get(nodeName);
|
PeerNode peer = _peers.get(nodeName);
|
||||||
@@ -746,7 +784,7 @@ public abstract class PeerManager
|
|||||||
*/
|
*/
|
||||||
public int getPeerPort (String nodeName)
|
public int getPeerPort (String nodeName)
|
||||||
{
|
{
|
||||||
if (_nodeName.equals(nodeName)) {
|
if (Objects.equal(_nodeName, nodeName)) {
|
||||||
return _self.port;
|
return _self.port;
|
||||||
}
|
}
|
||||||
PeerNode peer = _peers.get(nodeName);
|
PeerNode peer = _peers.get(nodeName);
|
||||||
@@ -786,7 +824,7 @@ public abstract class PeerManager
|
|||||||
// wait until any pending resolution is complete
|
// wait until any pending resolution is complete
|
||||||
queryLock(lock, new ChainedResultListener<String, String>(listener) {
|
queryLock(lock, new ChainedResultListener<String, String>(listener) {
|
||||||
public void requestCompleted (String result) {
|
public void requestCompleted (String result) {
|
||||||
if (_nodeName.equals(result)) {
|
if (Objects.equal(_nodeName, result)) {
|
||||||
if (_suboids.isEmpty()) {
|
if (_suboids.isEmpty()) {
|
||||||
lockReleased(lock, listener);
|
lockReleased(lock, listener);
|
||||||
} else {
|
} else {
|
||||||
@@ -815,7 +853,8 @@ public abstract class PeerManager
|
|||||||
{
|
{
|
||||||
// make sure we're releasing it
|
// make sure we're releasing it
|
||||||
LockHandler handler = _locks.get(lock);
|
LockHandler handler = _locks.get(lock);
|
||||||
if (handler == null || !handler.getNodeName().equals(_nodeName) || handler.isAcquiring()) {
|
if (handler == null || !Objects.equal(handler.getNodeName(), _nodeName) ||
|
||||||
|
handler.isAcquiring()) {
|
||||||
log.warning("Tried to reacquire lock not being released", "lock", lock,
|
log.warning("Tried to reacquire lock not being released", "lock", lock,
|
||||||
"handler", handler);
|
"handler", handler);
|
||||||
return;
|
return;
|
||||||
@@ -923,7 +962,7 @@ public abstract class PeerManager
|
|||||||
{
|
{
|
||||||
_suboids.remove(cloid);
|
_suboids.remove(cloid);
|
||||||
for (LockHandler handler : _locks.values().toArray(new LockHandler[_locks.size()])) {
|
for (LockHandler handler : _locks.values().toArray(new LockHandler[_locks.size()])) {
|
||||||
if (handler.getNodeName().equals(_nodeName)) {
|
if (Objects.equal(handler.getNodeName(), _nodeName)) {
|
||||||
handler.clientUnsubscribed(cloid);
|
handler.clientUnsubscribed(cloid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -976,7 +1015,7 @@ public abstract class PeerManager
|
|||||||
// from interface Lifecycle.ShutdownComponent
|
// from interface Lifecycle.ShutdownComponent
|
||||||
public void shutdown ()
|
public void shutdown ()
|
||||||
{
|
{
|
||||||
if (_nodeName == null) { // never initialized
|
if (_self == null) { // never initialized
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -989,12 +1028,14 @@ public abstract class PeerManager
|
|||||||
_clmgr.removeClientObserver(this);
|
_clmgr.removeClientObserver(this);
|
||||||
|
|
||||||
// clear our record from the node table
|
// clear our record from the node table
|
||||||
_invoker.postUnit(new WriteOnlyUnit("shutdownNode(" + _nodeName + ")") {
|
if (!_adHoc) {
|
||||||
@Override
|
_invoker.postUnit(new WriteOnlyUnit("shutdownNode(" + _nodeName + ")") {
|
||||||
public void invokePersist () throws Exception {
|
@Override
|
||||||
_noderepo.shutdownNode(_nodeName);
|
public void invokePersist () throws Exception {
|
||||||
}
|
_noderepo.shutdownNode(_nodeName);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// shut down the peers
|
// shut down the peers
|
||||||
for (PeerNode peer : _peers.values()) {
|
for (PeerNode peer : _peers.values()) {
|
||||||
@@ -1006,7 +1047,7 @@ public abstract class PeerManager
|
|||||||
public void ratifyLockAction (ClientObject caller, NodeObject.Lock lock, boolean acquire)
|
public void ratifyLockAction (ClientObject caller, NodeObject.Lock lock, boolean acquire)
|
||||||
{
|
{
|
||||||
LockHandler handler = _locks.get(lock);
|
LockHandler handler = _locks.get(lock);
|
||||||
if (handler != null && handler.getNodeName().equals(_nodeName)) {
|
if (handler != null && Objects.equal(handler.getNodeName(), _nodeName)) {
|
||||||
handler.ratify(caller, acquire);
|
handler.ratify(caller, acquire);
|
||||||
} else {
|
} else {
|
||||||
// this is not an error condition, as we may have cancelled the handler or
|
// this is not an error condition, as we may have cancelled the handler or
|
||||||
@@ -1122,6 +1163,10 @@ public abstract class PeerManager
|
|||||||
*/
|
*/
|
||||||
protected void refreshPeers ()
|
protected void refreshPeers ()
|
||||||
{
|
{
|
||||||
|
if (_adHoc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// load up information on our nodes
|
// load up information on our nodes
|
||||||
_invoker.postUnit(new RepositoryUnit("refreshPeers") {
|
_invoker.postUnit(new RepositoryUnit("refreshPeers") {
|
||||||
@Override
|
@Override
|
||||||
@@ -1141,7 +1186,7 @@ public abstract class PeerManager
|
|||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
for (Iterator<NodeRecord> it = _nodes.values().iterator(); it.hasNext(); ) {
|
for (Iterator<NodeRecord> it = _nodes.values().iterator(); it.hasNext(); ) {
|
||||||
NodeRecord record = it.next();
|
NodeRecord record = it.next();
|
||||||
if (record.nodeName.equals(_nodeName)) {
|
if (Objects.equal(record.nodeName, _nodeName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((now - record.lastUpdated.getTime()) > PeerNode.STALE_INTERVAL) {
|
if ((now - record.lastUpdated.getTime()) > PeerNode.STALE_INTERVAL) {
|
||||||
@@ -1498,8 +1543,15 @@ public abstract class PeerManager
|
|||||||
{
|
{
|
||||||
PeerNode peer = _peers.get(nodeName);
|
PeerNode peer = _peers.get(nodeName);
|
||||||
if (peer != null) {
|
if (peer != null) {
|
||||||
peer.nodeobj.peerService.invokeRequest(requestBytes, listener);
|
if (peer.nodeobj != null) {
|
||||||
} else if (nodeName.equals(_nodeName)) {
|
peer.nodeobj.peerService.invokeRequest(requestBytes, listener);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.warning("Dropped NodeRequest", "nodeName", nodeName);
|
||||||
|
listener.requestFailed(InvocationCodes.INTERNAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (Objects.equal(nodeName, _nodeName)) {
|
||||||
invokeRequest(null, requestBytes, listener);
|
invokeRequest(null, requestBytes, listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1771,12 +1823,18 @@ public abstract class PeerManager
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected String _nodeName, _sharedSecret;
|
/** The name of our node, which may be null if we are running in ad-hoc "multinoded" mode
|
||||||
|
* with but a single node. */
|
||||||
|
protected String _nodeName;
|
||||||
|
protected String _sharedSecret;
|
||||||
protected NodeRecord _self;
|
protected NodeRecord _self;
|
||||||
protected NodeObject _nodeobj;
|
protected NodeObject _nodeobj;
|
||||||
protected String _nodeNamespace;
|
protected String _nodeNamespace;
|
||||||
protected Map<String,PeerNode> _peers = Maps.newHashMap();
|
protected Map<String,PeerNode> _peers = Maps.newHashMap();
|
||||||
|
|
||||||
|
/** Are we in ad-hoc mode? (Not really connected to peers) */
|
||||||
|
protected boolean _adHoc;
|
||||||
|
|
||||||
/** The client oids of all peers subscribed to the node object. */
|
/** The client oids of all peers subscribed to the node object. */
|
||||||
protected ArrayIntSet _suboids = new ArrayIntSet();
|
protected ArrayIntSet _suboids = new ArrayIntSet();
|
||||||
|
|
||||||
|
|||||||
@@ -457,7 +457,4 @@ public class InvocationManager
|
|||||||
* comes in on a service we don't know about. */
|
* comes in on a service we don't know about. */
|
||||||
protected final Map<Integer, String> _recentRegServices =
|
protected final Map<Integer, String> _recentRegServices =
|
||||||
new LRUHashMap<Integer, String>(10000);
|
new LRUHashMap<Integer, String>(10000);
|
||||||
|
|
||||||
/** The text appended to the procedure name when generating a failure response. */
|
|
||||||
protected static final String FAILED_SUFFIX = "Failed";
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user