From 3a9c6ced447b66bfe89246e3d3a73b331c82f8fe Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Sat, 1 Jul 2006 03:34:00 +0000 Subject: [PATCH] A bunch more peer business. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4241 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../crowd/peer/client/CrowdPeerService.java | 40 +++++ .../crowd/peer/data/CrowdClientInfo.java | 35 +++++ .../crowd/peer/data/CrowdNodeObject.java | 56 +++++++ .../crowd/peer/data/CrowdPeerMarshaller.java | 55 +++++++ .../peer/server/CrowdPeerDispatcher.java | 73 +++++++++ .../crowd/peer/server/CrowdPeerManager.java | 53 +++++++ .../crowd/peer/server/CrowdPeerProvider.java | 43 ++++++ .../presents/peer/data/ClientInfo.java | 43 ++++++ .../presents/peer/data/NodeObject.java | 87 +++++++++++ .../presents/peer/net/PeerBootstrapData.java | 33 ++++ .../presents/peer/server/PeerClient.java | 44 +++++- .../peer/server/PeerClientFactory.java | 6 +- .../presents/peer/server/PeerManager.java | 144 +++++++++++++----- 13 files changed, 675 insertions(+), 37 deletions(-) create mode 100644 src/java/com/threerings/crowd/peer/client/CrowdPeerService.java create mode 100644 src/java/com/threerings/crowd/peer/data/CrowdClientInfo.java create mode 100644 src/java/com/threerings/crowd/peer/data/CrowdNodeObject.java create mode 100644 src/java/com/threerings/crowd/peer/data/CrowdPeerMarshaller.java create mode 100644 src/java/com/threerings/crowd/peer/server/CrowdPeerDispatcher.java create mode 100644 src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java create mode 100644 src/java/com/threerings/crowd/peer/server/CrowdPeerProvider.java create mode 100644 src/java/com/threerings/presents/peer/data/ClientInfo.java create mode 100644 src/java/com/threerings/presents/peer/data/NodeObject.java create mode 100644 src/java/com/threerings/presents/peer/net/PeerBootstrapData.java diff --git a/src/java/com/threerings/crowd/peer/client/CrowdPeerService.java b/src/java/com/threerings/crowd/peer/client/CrowdPeerService.java new file mode 100644 index 000000000..8dc7ea14d --- /dev/null +++ b/src/java/com/threerings/crowd/peer/client/CrowdPeerService.java @@ -0,0 +1,40 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.peer.client; + +import com.threerings.presents.client.Client; +import com.threerings.presents.client.InvocationService; + +import com.threerings.crowd.chat.client.ChatService; +import com.threerings.crowd.chat.data.ChatMessage; + +/** + * Bridges certain Crowd services between peers in a cluster configuration. + */ +public interface CrowdPeerService extends InvocationService +{ + /** + * Forwards a tell request to the server on which a user actually resides. + */ + public void deliverTell ( + Client client, ChatMessage message, ChatService.TellListener listener); +} diff --git a/src/java/com/threerings/crowd/peer/data/CrowdClientInfo.java b/src/java/com/threerings/crowd/peer/data/CrowdClientInfo.java new file mode 100644 index 000000000..4081d5160 --- /dev/null +++ b/src/java/com/threerings/crowd/peer/data/CrowdClientInfo.java @@ -0,0 +1,35 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.peer.data; + +import com.threerings.util.Name; + +import com.threerings.presents.peer.data.ClientInfo; + +/** + * Extends the standard {@link ClientInfo} with Crowd bits. + */ +public class CrowdClientInfo extends ClientInfo +{ + /** The client's visible name, which is used for chatting. */ + public Name visibleName; +} diff --git a/src/java/com/threerings/crowd/peer/data/CrowdNodeObject.java b/src/java/com/threerings/crowd/peer/data/CrowdNodeObject.java new file mode 100644 index 000000000..42b993a66 --- /dev/null +++ b/src/java/com/threerings/crowd/peer/data/CrowdNodeObject.java @@ -0,0 +1,56 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.peer.data; + +import com.threerings.presents.peer.data.NodeObject; + +/** + * Extends the basic {@link NodeObject} with Crowd bits. + */ +public class CrowdNodeObject extends NodeObject +{ + // AUTO-GENERATED: FIELDS START + /** The field name of the crowdPeerService field. */ + public static final String CROWD_PEER_SERVICE = "crowdPeerService"; + // AUTO-GENERATED: FIELDS END + + /** Used to coordinate tells between servers. */ + public CrowdPeerMarshaller crowdPeerService; + + // AUTO-GENERATED: METHODS START + /** + * Requests that the crowdPeerService field be set to the + * specified value. The local value will be updated immediately and an + * event will be propagated through the system to notify all listeners + * that the attribute did change. Proxied copies of this object (on + * clients) will apply the value change when they received the + * attribute changed notification. + */ + public void setCrowdPeerService (CrowdPeerMarshaller value) + { + CrowdPeerMarshaller ovalue = this.crowdPeerService; + requestAttributeChange( + CROWD_PEER_SERVICE, value, ovalue); + this.crowdPeerService = value; + } + // AUTO-GENERATED: METHODS END +} diff --git a/src/java/com/threerings/crowd/peer/data/CrowdPeerMarshaller.java b/src/java/com/threerings/crowd/peer/data/CrowdPeerMarshaller.java new file mode 100644 index 000000000..d670ef6b2 --- /dev/null +++ b/src/java/com/threerings/crowd/peer/data/CrowdPeerMarshaller.java @@ -0,0 +1,55 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.peer.data; + +import com.threerings.crowd.chat.client.ChatService; +import com.threerings.crowd.chat.data.ChatMarshaller; +import com.threerings.crowd.chat.data.ChatMessage; +import com.threerings.crowd.peer.client.CrowdPeerService; +import com.threerings.presents.client.Client; +import com.threerings.presents.data.InvocationMarshaller; +import com.threerings.presents.dobj.InvocationResponseEvent; + +/** + * Provides the implementation of the {@link CrowdPeerService} interface + * that marshalls the arguments and delivers the request to the provider + * on the server. Also provides an implementation of the response listener + * interfaces that marshall the response arguments and deliver them back + * to the requesting client. + */ +public class CrowdPeerMarshaller extends InvocationMarshaller + implements CrowdPeerService +{ + /** The method id used to dispatch {@link #deliverTell} requests. */ + public static final int DELIVER_TELL = 1; + + // documentation inherited from interface + public void deliverTell (Client arg1, ChatMessage arg2, ChatService.TellListener arg3) + { + ChatMarshaller.TellMarshaller listener3 = new ChatMarshaller.TellMarshaller(); + listener3.listener = arg3; + sendRequest(arg1, DELIVER_TELL, new Object[] { + arg2, listener3 + }); + } + +} diff --git a/src/java/com/threerings/crowd/peer/server/CrowdPeerDispatcher.java b/src/java/com/threerings/crowd/peer/server/CrowdPeerDispatcher.java new file mode 100644 index 000000000..e4d4b9feb --- /dev/null +++ b/src/java/com/threerings/crowd/peer/server/CrowdPeerDispatcher.java @@ -0,0 +1,73 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.peer.server; + +import com.threerings.crowd.chat.client.ChatService; +import com.threerings.crowd.chat.data.ChatMarshaller; +import com.threerings.crowd.chat.data.ChatMessage; +import com.threerings.crowd.peer.client.CrowdPeerService; +import com.threerings.crowd.peer.data.CrowdPeerMarshaller; +import com.threerings.presents.client.Client; +import com.threerings.presents.data.ClientObject; +import com.threerings.presents.data.InvocationMarshaller; +import com.threerings.presents.server.InvocationDispatcher; +import com.threerings.presents.server.InvocationException; + +/** + * Dispatches requests to the {@link CrowdPeerProvider}. + */ +public class CrowdPeerDispatcher extends InvocationDispatcher +{ + /** + * Creates a dispatcher that may be registered to dispatch invocation + * service requests for the specified provider. + */ + public CrowdPeerDispatcher (CrowdPeerProvider provider) + { + this.provider = provider; + } + + // documentation inherited + public InvocationMarshaller createMarshaller () + { + return new CrowdPeerMarshaller(); + } + + // documentation inherited + public void dispatchRequest ( + ClientObject source, int methodId, Object[] args) + throws InvocationException + { + switch (methodId) { + case CrowdPeerMarshaller.DELIVER_TELL: + ((CrowdPeerProvider)provider).deliverTell( + source, + (ChatMessage)args[0], (ChatService.TellListener)args[1] + ); + return; + + default: + super.dispatchRequest(source, methodId, args); + return; + } + } +} diff --git a/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java b/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java new file mode 100644 index 000000000..b703fd91d --- /dev/null +++ b/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java @@ -0,0 +1,53 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.peer.server; + +import com.samskivert.io.PersistenceException; +import com.samskivert.jdbc.ConnectionProvider; +import com.samskivert.util.Invoker; + +import com.threerings.presents.peer.data.NodeObject; +import com.threerings.presents.peer.server.PeerManager; + +import com.threerings.crowd.peer.data.CrowdNodeObject; + +/** + * Extends the standard peer manager and bridges certain Crowd services. + */ +public class CrowdPeerManager extends PeerManager +{ + /** + * Creates a peer manager that integrates Crowd services across a cluster + * of servers. + */ + public CrowdPeerManager (ConnectionProvider conprov, Invoker invoker) + throws PersistenceException + { + super(conprov, invoker); + } + + @Override // documentation inherited + protected Class getNodeObjectClass () + { + return CrowdNodeObject.class; + } +} diff --git a/src/java/com/threerings/crowd/peer/server/CrowdPeerProvider.java b/src/java/com/threerings/crowd/peer/server/CrowdPeerProvider.java new file mode 100644 index 000000000..a289067c4 --- /dev/null +++ b/src/java/com/threerings/crowd/peer/server/CrowdPeerProvider.java @@ -0,0 +1,43 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.peer.server; + +import com.threerings.crowd.chat.client.ChatService; +import com.threerings.crowd.chat.data.ChatMarshaller; +import com.threerings.crowd.chat.data.ChatMessage; +import com.threerings.crowd.peer.client.CrowdPeerService; +import com.threerings.presents.client.Client; +import com.threerings.presents.data.ClientObject; +import com.threerings.presents.server.InvocationException; +import com.threerings.presents.server.InvocationProvider; + +/** + * Defines the server-side of the {@link CrowdPeerService}. + */ +public interface CrowdPeerProvider extends InvocationProvider +{ + /** + * Handles a {@link CrowdPeerService#deliverTell} request. + */ + public void deliverTell (ClientObject caller, ChatMessage arg1, ChatService.TellListener arg2) + throws InvocationException; +} diff --git a/src/java/com/threerings/presents/peer/data/ClientInfo.java b/src/java/com/threerings/presents/peer/data/ClientInfo.java new file mode 100644 index 000000000..dde92254b --- /dev/null +++ b/src/java/com/threerings/presents/peer/data/ClientInfo.java @@ -0,0 +1,43 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.presents.peer.data; + +import com.threerings.io.SimpleStreamableObject; +import com.threerings.util.Name; + +import com.threerings.presents.dobj.DSet; + +/** + * Contains information on a particular client. + */ +public class ClientInfo extends SimpleStreamableObject + implements DSet.Entry +{ + /** The username used by this client to authenticate. */ + public Name username; + + // documentation inherited from interface DSet.Entry + public Comparable getKey () + { + return username; + } +} diff --git a/src/java/com/threerings/presents/peer/data/NodeObject.java b/src/java/com/threerings/presents/peer/data/NodeObject.java new file mode 100644 index 000000000..0262458b4 --- /dev/null +++ b/src/java/com/threerings/presents/peer/data/NodeObject.java @@ -0,0 +1,87 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.presents.peer.data; + +import com.threerings.presents.dobj.DObject; +import com.threerings.presents.dobj.DSet; + +/** + * Contains information that one node published for all of its peers. + */ +public class NodeObject extends DObject +{ + // AUTO-GENERATED: FIELDS START + /** The field name of the clients field. */ + public static final String CLIENTS = "clients"; + // AUTO-GENERATED: FIELDS END + + /** Contains information on all clients connected to this node. */ + public DSet clients; + + // AUTO-GENERATED: METHODS START + /** + * Requests that the specified entry be added to the + * clients set. The set will not change until the event is + * actually propagated through the system. + */ + public void addToClients (DSet.Entry elem) + { + requestEntryAdd(CLIENTS, clients, elem); + } + + /** + * Requests that the entry matching the supplied key be removed from + * the clients set. The set will not change until the + * event is actually propagated through the system. + */ + public void removeFromClients (Comparable key) + { + requestEntryRemove(CLIENTS, clients, key); + } + + /** + * Requests that the specified entry be updated in the + * clients set. The set will not change until the event is + * actually propagated through the system. + */ + public void updateClients (DSet.Entry elem) + { + requestEntryUpdate(CLIENTS, clients, elem); + } + + /** + * Requests that the clients field be set to the + * specified value. Generally one only adds, updates and removes + * entries of a distributed set, but certain situations call for a + * complete replacement of the set value. The local value will be + * updated immediately and an event will be propagated through the + * system to notify all listeners that the attribute did + * change. Proxied copies of this object (on clients) will apply the + * value change when they received the attribute changed notification. + */ + public void setClients (DSet value) + { + requestAttributeChange(CLIENTS, value, this.clients); + this.clients = (value == null) ? null : value.typedClone(); + } + // AUTO-GENERATED: METHODS END +} diff --git a/src/java/com/threerings/presents/peer/net/PeerBootstrapData.java b/src/java/com/threerings/presents/peer/net/PeerBootstrapData.java new file mode 100644 index 000000000..62a0f0b0b --- /dev/null +++ b/src/java/com/threerings/presents/peer/net/PeerBootstrapData.java @@ -0,0 +1,33 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.presents.peer.net; + +import com.threerings.presents.net.BootstrapData; + +/** + * Extensd the standard bootstrap with some information needed by our peers. + */ +public class PeerBootstrapData extends BootstrapData +{ + /** The id of this peer's node object. */ + public int nodeOid; +} diff --git a/src/java/com/threerings/presents/peer/server/PeerClient.java b/src/java/com/threerings/presents/peer/server/PeerClient.java index bae2bc4ac..37a68c0a2 100644 --- a/src/java/com/threerings/presents/peer/server/PeerClient.java +++ b/src/java/com/threerings/presents/peer/server/PeerClient.java @@ -21,11 +21,53 @@ package com.threerings.presents.peer.server; +import com.threerings.presents.net.BootstrapData; import com.threerings.presents.server.PresentsClient; +import com.threerings.presents.peer.net.PeerBootstrapData; + /** - * Manages a peer server connection. + * Manages a peer connection. */ public class PeerClient extends PresentsClient { + /** + * Creates a peer client and provides it with a reference to the peer + * manager. This is only done by the {@link PeerClientFactory}. + */ + protected PeerClient (PeerManager peermgr) + { + _peermgr = peermgr; + } + + /** + * Derived client classes can override this member to create derived + * bootstrap data classes that contain extra bootstrap information, if + * desired. + */ + protected BootstrapData createBootstrapData () + { + return new PeerBootstrapData(); + } + + /** + * Derived client classes can override this member to populate the + * bootstrap data with additional information. They should be sure to + * call super.populateBootstrapData before doing their + * own populating, however. + * + *

Note: This function will be called on the dobjmgr + * thread which means that object manipulations are OK, but client + * instance manipulations must be done carefully. + */ + protected void populateBootstrapData (BootstrapData data) + { + super.populateBootstrapData(data); + + // tell our peer about our node object so they can wire up + PeerBootstrapData pdata = (PeerBootstrapData)data; + pdata.nodeOid = _peermgr.getNodeObject().getOid(); + } + + protected PeerManager _peermgr; } diff --git a/src/java/com/threerings/presents/peer/server/PeerClientFactory.java b/src/java/com/threerings/presents/peer/server/PeerClientFactory.java index 555a22fe0..d2c22de34 100644 --- a/src/java/com/threerings/presents/peer/server/PeerClientFactory.java +++ b/src/java/com/threerings/presents/peer/server/PeerClientFactory.java @@ -36,8 +36,9 @@ import com.threerings.presents.peer.net.PeerCreds; */ public class PeerClientFactory implements ClientFactory { - public PeerClientFactory (ClientFactory delegate) + public PeerClientFactory (PeerManager peermgr, ClientFactory delegate) { + _peermgr = peermgr; _delegate = delegate; } @@ -45,7 +46,7 @@ public class PeerClientFactory implements ClientFactory public PresentsClient createClient (AuthRequest areq) { if (areq.getCredentials() instanceof PeerCreds) { - return new PeerClient(); + return new PeerClient(_peermgr); } else { return _delegate.createClient(areq); } @@ -61,5 +62,6 @@ public class PeerClientFactory implements ClientFactory } } + protected PeerManager _peermgr; protected ClientFactory _delegate; } diff --git a/src/java/com/threerings/presents/peer/server/PeerManager.java b/src/java/com/threerings/presents/peer/server/PeerManager.java index 4f9005c9d..46f2a001b 100644 --- a/src/java/com/threerings/presents/peer/server/PeerManager.java +++ b/src/java/com/threerings/presents/peer/server/PeerManager.java @@ -33,8 +33,12 @@ import com.samskivert.util.Invoker; import com.threerings.presents.client.Client; import com.threerings.presents.client.ClientObserver; +import com.threerings.presents.dobj.ObjectAccessException; +import com.threerings.presents.dobj.Subscriber; import com.threerings.presents.server.PresentsServer; +import com.threerings.presents.peer.data.NodeObject; +import com.threerings.presents.peer.net.PeerBootstrapData; import com.threerings.presents.peer.net.PeerCreds; import com.threerings.presents.peer.server.persist.NodeRecord; import com.threerings.presents.peer.server.persist.NodeRepository; @@ -51,7 +55,29 @@ public class PeerManager { /** * Creates a peer manager which will create a {@link NodeRepository} which - * is used to publish our existence and discover the other nodes. + * will be used to publish our existence and discover the other nodes. + */ + public PeerManager (ConnectionProvider conprov, Invoker invoker) + throws PersistenceException + { + _invoker = invoker; + _noderepo = new NodeRepository(conprov); + } + + /** + * Returns the distributed object that represents this node to its peers. + */ + public NodeObject getNodeObject () + { + return _nodeobj; + } + + /** + * 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 + * after 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 @@ -62,46 +88,32 @@ public class PeerManager * @param invoker we will perform all database operations on the supplied * invoker thread. */ - public PeerManager ( - String nodeName, String sharedSecret, String hostName, int port, - ConnectionProvider conprov, Invoker invoker) - throws PersistenceException + public void init (String nodeName, String sharedSecret, + String hostName, int port) { _nodeName = nodeName; _hostName = hostName; _port = port; _sharedSecret = sharedSecret; - _invoker = invoker; - _noderepo = new NodeRepository(conprov); - } - /** - * Instructs the node manager to load up information about its other nodes - * and attempt to establish connections with those nodes. - */ - public void init () - { - // first register ourselves with the node table - _invoker.postUnit(new Invoker.Unit() { - public boolean invoke () { - NodeRecord record = new NodeRecord(_nodeName, _hostName, _port); - try { - _noderepo.updateNode(record); - } catch (PersistenceException pe) { - log.warning("Failed to register node record " + - "[rec=" + record + ", error=" + pe + "]."); - } - return false; + // wire ourselves into the server + PresentsServer.conmgr.setAuthenticator( + new PeerAuthenticator( + this, PresentsServer.conmgr.getAuthenticator())); + PresentsServer.clmgr.setClientFactory( + new PeerClientFactory( + this, PresentsServer.clmgr.getClientFactory())); + + // create our node object + Class clazz = (Class)getNodeObjectClass(); + PresentsServer.omgr.createObject(clazz, new Subscriber() { + public void objectAvailable (NodeObject object) { + finishInit(object); + } + public void requestFailed (int oid, ObjectAccessException cause) { + log.warning("Failed to create NodeObject: " + cause + "."); } }); - - // then start our peer refresh interval (this need not use a runqueue - // as all it will do is post an invoker unit) - new Interval() { - public void expired () { - refreshPeers(); - } - }.schedule(5000L, 60*1000L); } /** @@ -126,6 +138,37 @@ public class PeerManager creds.getNodeName(), _sharedSecret).equals(creds.getPassword()); } + /** + * Called once our node object is available. + */ + protected void finishInit (NodeObject nodeobj) + { + // keep a handle on our node object + _nodeobj = nodeobj; + + // register ourselves with the node table + _invoker.postUnit(new Invoker.Unit() { + public boolean invoke () { + NodeRecord record = new NodeRecord(_nodeName, _hostName, _port); + try { + _noderepo.updateNode(record); + } catch (PersistenceException pe) { + log.warning("Failed to register node record " + + "[rec=" + record + ", error=" + pe + "]."); + } + return false; + } + }); + + // and start our peer refresh interval (this need not use a runqueue as + // all it will do is post an invoker unit) + new Interval() { + public void expired () { + refreshPeers(); + } + }.schedule(5000L, 60*1000L); + } + /** * Reloads the list of peer nodes from our table and refreshes each with a * call to {@link #refreshPeer}. @@ -174,12 +217,23 @@ public class PeerManager peer.refresh(record); } + /** + * Returns the class we use when creating our {@link NodeObject}. + */ + protected Class getNodeObjectClass () + { + return NodeObject.class; + } + /** * Contains all runtime information for one of our peer nodes. */ protected class PeerNode - implements ClientObserver + implements ClientObserver, Subscriber { + /** This peer's node object. */ + public NodeObject nodeobj; + public PeerNode (NodeRecord record) { _record = record; @@ -242,11 +296,17 @@ public class PeerManager public void clientDidLogon (Client client) { log.info("Connected to peer " + _record + "."); + + // subscribe to this peer's node object + PeerBootstrapData pdata = (PeerBootstrapData) + client.getBootstrapData(); + client.getDObjectManager().subscribeToObject(pdata.nodeOid, this); } // documentation inherited from interface ClientObserver public void clientObjectDidChange (Client client) { + // nothing doing } // documentation inherited from interface ClientObserver @@ -258,6 +318,21 @@ public class PeerManager // documentation inherited from interface ClientObserver public void clientDidLogoff (Client client) { + // TODO: clean things up? + } + + // documentation inherited from interface Subscriber + public void objectAvailable (NodeObject object) + { + nodeobj = object; + // TODO: stuff! + } + + // documentation inherited from interface Subscriber + public void requestFailed (int oid, ObjectAccessException cause) + { + log.warning("Failed to subscribe to peer's node object " + + "[peer=" + _record + ", cause=" + cause + "]."); } protected NodeRecord _record; @@ -269,5 +344,6 @@ public class PeerManager protected int _port; protected Invoker _invoker; protected NodeRepository _noderepo; + protected NodeObject _nodeobj; protected HashMap _peers = new HashMap(); }