| This class manages the contents of a discussion. Messages may be added
at any time. There is an option limit on the size of the message queue,
if so the oldest messages are deleted as new ones arrive.
Optionally the method startHarvester() may be called, once, to start
a background thread that enforces an age limit on messages. If this
method is not called, then there will be no age limit.
This class implements what I call the "on hold push" algorithm.
The server (this class) maintains some state (a list of messages).
Clients (ContentsPresentation.po and the web browser) request snapshots of this state.
If the state has changed
since the last time the client asked for a snapshot, then a new
snapshot is sent to the client right away. If the state has not changed
since the last time the client asked for a snapshot, then the request
for a snapshot blocks until the state changes (either by a new message
being added, or messages being deleted). As soon as the client has
processed the snapshot it gets, it immediatly requests a new snapshot.
This has the following advantages:
As soon as new information is available, it is sent immediatly to
all interested parties.
Since a whole snapshot is sent every time, the problem of having
to do "diffs" between the old and new states is avoided. As is the
problem of how to recover when this mechanism breaks down.
Only standard HTTP is used, so the method is compatible with firewalls,
proxies, all browsers, and even, in the case of an applet,
paranoid security policies. (HTTP requests are commonly
blocked on a read in real life. But usually it is a filesystem read,
and the delay is much shorter.) For an example of this, try running
this application in the Enhydra Multiserver, and then add a WAI
connection. Your requests are being tunneled via CORBA from the
Netscape server to the Multiserver, yet the application runs fine.
Because the interested parties all have already established a socket
connection, and are poised and ready to read data, they recieve the
new state the instant it changes, pretty much as quickly as is possible.
It is simple, robust and effective.
This has the following disadvantages:
If you have N users, you will have N open socket connections. This
method does not scale well to very large values of N. If N is too large,
some users will experience network errors, and their automatic
reloading will stop. See your operating system for details on the
maximum number of open sockets, and the optional NumThreads setting
for connections in the Enhydra Multiserver config file.
The whole state is sent every time. This uses more bandwidth than
methods that only send deltas to the state.
If the clients stop asking for snapshots, there is no way (from the
server) to do anything about it.
In order to tell if a client has a current copy of the state of things,
timestamps are used. Every time the state changes, a unique identifier
is assigned to the new current state (using time). The important thing
is that the identifiers uniquely identify their state. Time is just
one way of generating unique identifiers. Every time the client asks
for a snapshot, it also sends the identifier for the state it currently
has (there must be a special identifier used for the first request, when
the client has no data. In this program it sends 0). If the id sent with
the request matches, then the request blocks until the state changes.
In real life most connections to the server use TCP/IP, which imposes
a timeout limit on how long requests can block on a read.
More importantly, web browsers will give up after a short period of time.
Therefore, when a request is sent in, in addition to the current id a
time limit is sent. This tells the server the maximum number of seconds
the client is willing to wait (in this program 60 seconds is used).
If this time limit expires, and the state has not yet changed, the
server must return an answer to the client. In this program a snapshot
is returned, even though the browser already has the same data
(if the client were an applet, a special "no change" response could be
sent). If a client wants to force an update, or wants to do a
non-blocking read for some other reason, then it simply sets the timeout
to zero.
Static methods are used because there is only one chat room. This
program's main goal is to show off a simple yet "real" Enhydra application.
|