06ab6c8b90
services. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1591 542714f4-19e9-0310-aa3c-eee0fc999fb1
265 lines
10 KiB
Plaintext
265 lines
10 KiB
Plaintext
Presents Notes -*- outline -*-
|
|
|
|
* TODO
|
|
- Pass cause back to client somehow via FailureResponse in
|
|
Client.requestFailed
|
|
|
|
- clientWillLogff becomes clientMayLogoff?
|
|
|
|
- Look into nbio waking up all sockets when any data comes in.
|
|
|
|
- (maybe) Allow piggybacking of object subscription onto service defined
|
|
responses (like moveTo request).
|
|
|
|
- (maybe) Allow better server side control of subscription management (to
|
|
ensure that clients don't remain subscribed to objects they should no
|
|
longer be susbcribed to; like scenes they've departed from).
|
|
|
|
- Sort out support for server-side modifiable only fields to DObject.
|
|
|
|
- Create a CompoundEvent that allows packaging up of multiple events to be
|
|
dispatched in unison. Build dobj source generator and have it add
|
|
versions of all update methods that take a compound event to which to
|
|
append the event rather than dispatching them directly.
|
|
|
|
- Maybe make AuthResponseData a Streamable instead of a DObject.
|
|
|
|
- Have the LocationRegistry register the LocationProvider rather than
|
|
doing it via a config file. Perhaps lose the config file element
|
|
altogether.
|
|
|
|
- Think about Subscriber business and whether or not DObject needs a list
|
|
of subscribers or if there's a better way to handle
|
|
removedLastSubscriber() on the client side and not taint the server side
|
|
with all dat crap.
|
|
|
|
* Server-side event concentrator
|
|
- The client objects will not subscribe directly, but will subscribe
|
|
through the concentrator so that, at least, it can create a single
|
|
ForwardEventNotification for each Event being dispatched to a group of
|
|
clients. Optimally, it would be able to flatten that notification as
|
|
well and the byte array can be written to the socket of each of the
|
|
individual clients rather than creating a separate byte array for each
|
|
client. This will require a special "flattened notification" that can be
|
|
inserted into the queue to preserve message ordering but then is simply
|
|
sent rather than flattened and sent.
|
|
|
|
* Marshaller
|
|
- Consider how the dobject marshaller deals with classes loaded and
|
|
reloaded using flushable classloaders.
|
|
|
|
Also consider whether access to the marshaller cache needs to be
|
|
synchronized.
|
|
|
|
* Check into "connection closed by peer" thread exiting on client
|
|
|
|
* TypedObjectFactory
|
|
- Maybe modify so that types are assigned automatically even if everything
|
|
has to be registered in a single place, since it pretty much does
|
|
anyway.
|
|
|
|
* Client network mgmt
|
|
- Client perform all network ops on own thread, will call back to main
|
|
code through Observer interface to notify of state changes in the
|
|
authentication process/connectedness:
|
|
|
|
public interface ClientObserver
|
|
{
|
|
public void didConnect ();
|
|
public void connectionFailed ();
|
|
public void didLogon ();
|
|
public void logonFailed ();
|
|
public void didDisconnect ();
|
|
public void didLogoff ();
|
|
}
|
|
|
|
* DObject class generation
|
|
- Distributed objects are defined like a class with a set of public data
|
|
members which is then converted into an actual class with get/set
|
|
methods for each member.
|
|
|
|
public dclass GameObject
|
|
{
|
|
public int[] players;
|
|
public String description;
|
|
}
|
|
|
|
becomes
|
|
|
|
public class GameObject extends DObject
|
|
{
|
|
public void setPlayers (int[] players);
|
|
public void setPlayersAt (int index, int value);
|
|
public int[] getPlayers ();
|
|
public int getPlayersAt (int index);
|
|
|
|
public void setDescription (String description);
|
|
public String getDescription ();
|
|
}
|
|
|
|
* 5/27/2002
|
|
** Synchronizing time between client and server
|
|
- After authentication, client begins a process of establishing the time
|
|
differential between the client clock and the server clock.
|
|
|
|
- The client sends a PING packet, noting the time immediately prior to
|
|
delivering the packet over the network.
|
|
|
|
- The server notes the at which the PING packet was unserialized. It
|
|
supplies that time to the constructed PONG packet which then notes the
|
|
time immediately prior to serialization and uses that to deliver to the
|
|
client the server time and the number of milliseconds that passed
|
|
between the unserialization of the PING packet and the serialization
|
|
(and subsequent network delivery) of the PONG packet.
|
|
|
|
- The client can then subtract the server processing time from the total
|
|
round trip delay, divide the round trip delay by two, adjust the server
|
|
time stamp accordingly and then obtain the client/server time
|
|
differential.
|
|
|
|
- The client then repeats this process some small number of times (five)
|
|
to attempt to account for spurious differences in upstream
|
|
vs. downstream transmission times and finally settles on a dT that will
|
|
be used for the duration of the session.
|
|
|
|
- We assume that the session will not last long enough for clock drift on
|
|
either the client or server to become significant when compared to the
|
|
error in the original time differential measurement.
|
|
|
|
- We'll want to use the high-precision timing services once we have those
|
|
because we don't want unnecessary error introduced into our ping and
|
|
pong time stamps by the unreliable granularity of
|
|
System.currentTimeMillis().
|
|
|
|
* 7/8/2002
|
|
** Improved invocation services
|
|
- Adding remote method call support to distributed objects doesn't allow
|
|
us to separate interface from implementation; DObject classes are shared
|
|
on the client and server by definition; whereas we would want an
|
|
interface that could be known on the client and the interface and
|
|
implementation known on the server
|
|
|
|
- Perhaps RMI could somehow be rolled into the DObject system... more
|
|
likely we'd want to automate the process of instantiating the
|
|
implementation on the server and the proxy on the client and wouldn't
|
|
want to use their object registry; we'd also want to do method dispatch
|
|
on the omgr thread and use our messaging services
|
|
|
|
* 7/15/2002
|
|
** BEEP!
|
|
- Look into replacing low-level network protocol with BEEP (and rolling
|
|
our performance enhancements into BEEP's implementation if necessary)
|
|
|
|
* 7/18/2002
|
|
** PRMI (Presents remote method invocation)
|
|
- PRMI ends up looking a lot like RMI with a few critical differences:
|
|
|
|
+ it uses the same message passing infrastructure as the distributed
|
|
object system to accomplish its calls and responses
|
|
|
|
+ it requires asynchronous response delivery (return values from
|
|
remotely invoked methods are prohibited)
|
|
|
|
- It all starts with an interface that defines the remotely callable
|
|
methods and remotely callable response interfaces:
|
|
|
|
public interface LocationService extends InvocationService
|
|
{
|
|
/**
|
|
* Used to communicate responses to {@link #moveTo} requests.
|
|
*/
|
|
public interface MoveListener extends InvocationListener
|
|
{
|
|
/**
|
|
* Called in response to a successful {@link #moveTo} request.
|
|
*/
|
|
public void moveSucceeded (PlaceConfig config);
|
|
}
|
|
|
|
/**
|
|
* Requests that this client's body be moved to the specified
|
|
* location.
|
|
*
|
|
* @param placeId the object id of the place object to which the
|
|
* body should be moved.
|
|
* @param listener the listener that will be informed of success or
|
|
* failure.
|
|
*/
|
|
public void moveTo (int placeId, MoveListener listener)
|
|
throws InvocationException;
|
|
}
|
|
|
|
Note again that remotely callable methods cannot return values.
|
|
Responses must be communicated asynchronously via listener parameters.
|
|
|
|
The InvocationListener interface provides a standard method for handling
|
|
request failure:
|
|
|
|
public InvocationListener
|
|
{
|
|
public void requestFailed (InvocationException cause)
|
|
}
|
|
|
|
This will be used to report unexpected failure and can also be used to
|
|
report expected failures by the remotely callable method implementations
|
|
if they so desire. This is accomplished by their throwing exceptions
|
|
that extend InvocationException. Non-InvocationException exceptions
|
|
thrown by the remotely callable methods will be wrapped in an
|
|
InvocationException and then passed on to the appropriate listener.
|
|
|
|
For methods that declare multiple result listeners (a design choice that
|
|
is not recommended), the first listener in the argument list will be the
|
|
one to which caught exceptions are delivered.
|
|
|
|
- From the interface, marshaller implementations are generated for the
|
|
service interface and all listener interfaces contained therein:
|
|
|
|
public class LocationMarshaller implements LocationService
|
|
{
|
|
// ...
|
|
|
|
public int marshallerId;
|
|
|
|
public void moveTo (int placeId, MoveListener listener)
|
|
{
|
|
try {
|
|
if (_provider != null) {
|
|
// this is a local request, dispatch it directly
|
|
_provider.moveTo(placeId, listener);
|
|
} else {
|
|
// pass the request to the invocation services for
|
|
// dispatch over the network
|
|
}
|
|
|
|
} catch (InvocationException ie) {
|
|
if (listener != null) {
|
|
listener.requestFailed(ie);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected transient LocationService _provider;
|
|
}
|
|
|
|
An InvocationMarshaller is constructed on the server and passed at
|
|
construct time a InvocationService implementation that will provide
|
|
the actual implementation of the service. The marshaller will then
|
|
register itself with the invocation services to receive an invocation
|
|
object id which will be used to identify that marshaller in client
|
|
JVMs.
|
|
|
|
The InvocationMarshaller instance can then be passed around the
|
|
distributed object system as any other object. If it is used on the
|
|
server, the methods will be passed directly through to the
|
|
implementation. If it is used on the client, it will marshall the
|
|
request parameters and send them over the network to the server --
|
|
where they will be dispatched to the implementation -- any response
|
|
from which will be communicated back through InvocationListener
|
|
proxies which marshall the response and deliver it to the calling
|
|
client, which then unpacks the response and delivers it to the
|
|
original InvocationListener.
|
|
|
|
- Notification services? Client provides "marshaller" in ClientObject,
|
|
server calls down to client through said marshaller object. How to
|
|
register implementations on the client end?
|