Documented invocation services.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@65 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
Cher Mk3 Design -*- outline -*-
|
Cher Design -*- outline -*-
|
||||||
|
|
||||||
* Why Cher?
|
* Why Cher?
|
||||||
The basic function of this layer is to allow the sharing (Cher-ing) of
|
The basic function of this layer is to allow the sharing (Cher-ing) of
|
||||||
@@ -6,8 +6,102 @@ information among different nodes in the network. Plus, I don't think Cher
|
|||||||
has ever had a software system named after her and it's high time. Imagine
|
has ever had a software system named after her and it's high time. Imagine
|
||||||
Cher as the social lubricant that allows the party goers to communicate.
|
Cher as the social lubricant that allows the party goers to communicate.
|
||||||
|
|
||||||
* A note on thread-safety
|
* Overview
|
||||||
|
The Cher layer implements the distributed object services described in the
|
||||||
|
Cocktail design document. It does this within the context of an extensible
|
||||||
|
client/server application framework. Cher provides services that can be
|
||||||
|
integrated into your distributed application to share information between
|
||||||
|
a set of clients and entities operating on the server.
|
||||||
|
|
||||||
|
* Invocation services
|
||||||
|
To facilitate the client invoking code on the server (in a
|
||||||
|
request/response arrangement) and the server invoking code on the client
|
||||||
|
(in an asynchronous notification arrangement), the invocation services are
|
||||||
|
provided.
|
||||||
|
|
||||||
|
We make use of reflection to make the invocation services feel a bit like
|
||||||
|
remote procedure calls. All invocation traffic is managed by the
|
||||||
|
invocation manager, part of which resides on the client and part on the
|
||||||
|
server.
|
||||||
|
|
||||||
|
There are three classes involved when fully using the services. They are
|
||||||
|
the service class, the provider class and the receiver class.
|
||||||
|
|
||||||
|
** Service class
|
||||||
|
The service class provides the client-side API to the request/response
|
||||||
|
component. For example:
|
||||||
|
|
||||||
|
public class ChatService
|
||||||
|
{
|
||||||
|
public void requestTell (String username, String message,
|
||||||
|
Object rsptarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
The tell() implementation would wrap the arguments up and pass them off to
|
||||||
|
the invocation manager for delivery to the server. If provided, the
|
||||||
|
response target object will receive a callback when the response comes in
|
||||||
|
from the server. The callback will come in the form of a call to a
|
||||||
|
reflected method on that object. The exact name of the method depends on
|
||||||
|
the implementation of the provider class which runs on the server.
|
||||||
|
|
||||||
|
** Provider class
|
||||||
|
The provider class implements the server-end of the service and is
|
||||||
|
registered with the invocation manager on the server to handle a
|
||||||
|
particular class of invocations. Continuing with our example:
|
||||||
|
|
||||||
|
public class ChatProvider
|
||||||
|
{
|
||||||
|
public void handleTellRequest (int invid, String username, String message);
|
||||||
|
}
|
||||||
|
|
||||||
|
The handleTellRequest() function will process the request and then
|
||||||
|
generate a response which is passed on to the invocation manager for
|
||||||
|
delivery to the client. The response will be named and the name of the
|
||||||
|
response will dictate the method that is invoked on the response target
|
||||||
|
object. The arguments that go along with the name must correspond to the
|
||||||
|
signature of that method. For example:
|
||||||
|
|
||||||
|
invmgr.respond(invid, "TellFailed", new Object[] { "m.no_such_user" });
|
||||||
|
|
||||||
|
will result in:
|
||||||
|
|
||||||
|
public void handleTellFailed (String reason);
|
||||||
|
|
||||||
|
being called on the response target object. Because the response target
|
||||||
|
method is looked up only by name, all responses using the same name must
|
||||||
|
use the argument signature and the response target object may only have
|
||||||
|
one method with that particular name and its signature must match exactly
|
||||||
|
the signature dictated by the arguments.
|
||||||
|
|
||||||
|
** Receiver class
|
||||||
|
For asynchronous messages from the server to the client, there exists the
|
||||||
|
receiver class. The receiver is registered with the client invocation
|
||||||
|
manager to handle messages of a particular type (much like the provider
|
||||||
|
class is registered on the server) which is identified by a string name.
|
||||||
|
|
||||||
|
The receiver class provides methods named like so:
|
||||||
|
|
||||||
|
public class ChatReceiver
|
||||||
|
{
|
||||||
|
public void handleTellNotification (String from, String msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
where the arguments to the method again correlate with the arguments in
|
||||||
|
the invocation message.
|
||||||
|
|
||||||
|
The server wrapper that generates the corresponding invocation message for
|
||||||
|
delivery to the client will likely also reside in the ChatProvider class
|
||||||
|
already described. For example:
|
||||||
|
|
||||||
|
public class ChatProvider
|
||||||
|
{
|
||||||
|
public void sendTell (BodyObject to, String from, String msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
This function will simply wrap up the arguments and pass them to the
|
||||||
|
invocation manager for delivery to the appropriate client.
|
||||||
|
|
||||||
|
* A note on thread-safety
|
||||||
Distributed objects are designed only to be accessed from one thread. On
|
Distributed objects are designed only to be accessed from one thread. On
|
||||||
the server, there is a distributed object dispatch thread on which 95% of
|
the server, there is a distributed object dispatch thread on which 95% of
|
||||||
all activity takes place anyway. It would be questionable to require that
|
all activity takes place anyway. It would be questionable to require that
|
||||||
@@ -35,7 +129,6 @@ need to fetch values from a distributed object after another thread has
|
|||||||
already started, you'll just have to rethink your approach.
|
already started, you'll just have to rethink your approach.
|
||||||
|
|
||||||
* Client components
|
* Client components
|
||||||
|
|
||||||
** DObjectManager
|
** DObjectManager
|
||||||
Manages object proxies; converts value change requests into events,
|
Manages object proxies; converts value change requests into events,
|
||||||
forwards them via the iomgr; dispatches events on incoming queue; reaps
|
forwards them via the iomgr; dispatches events on incoming queue; reaps
|
||||||
@@ -66,7 +159,6 @@ connection + authentication (logon) and disconnection (logoff); provides
|
|||||||
access to omgr and client dobj
|
access to omgr and client dobj
|
||||||
|
|
||||||
* Server components
|
* Server components
|
||||||
|
|
||||||
** Connection Manager
|
** Connection Manager
|
||||||
Listens on accepting socket; creates and manages connection objects;
|
Listens on accepting socket; creates and manages connection objects;
|
||||||
informs connection observer of state changes; handles all network traffic
|
informs connection observer of state changes; handles all network traffic
|
||||||
|
|||||||
Reference in New Issue
Block a user