olcr. It was developed by a
consultant, for consultants, out of frustration with the limitations of
the simple interface provided by olcr, and out of a need for greater
power and flexibility.
The first section of this chapter will discuss the motivation behind writing the EOLCR client. The second section will focus on the use and capabilities of EOLCR. Ideas and details of its implementation will be investigated in the third section. Finally, the fourth section will present a brief analysis of the more salient aspects of EOLCR as a whole.
Note that EOLCR is a large, comprehensive system; for the sake of economy, only the most distinctive and important features of EOLCR will be mentioned. Those interested in more complete documentation of EOLCR's capabilities are referred to the Emacs OLCR User's Manual and the Emacs OLCR Programmer's Manual.
However, the olcr client provides only a very primitive, scrolling ASCII
interface with which to handle this load. Consultants with multiple
questions need to constantly monitor the replay logs of their users, the
OLC queue, and their status in OLC. With olcr, consultants have to
continually replay logs and relist the queue. They are also hindered by
the fact that they can only do one thing at a time, which is frustrating
since olcr commands are far from instantaneous.[2] Also, as mentioned
in the previous chapter, consultants use many special tools on-line.
However, these tools are not integrated with olcr,[3] resulting in more
inefficiency. The standard ``solution'' was to run several xterm
programs, each one dedicated to running a separate olcr. This, however,
provided a very limited solution to only some of these problems.
Out of this frustration arose the Emacs OLCR client.[4] EOLCR caches
the OLC queue, replay logs, and the consultant's status, making them
instantly available within a keystroke or two. All EOLCR commands are run
in the background, so several commands can be executed one after the after
the other without waiting for one to terminate before starting another.
EOLCR listens to Zephyrgrams from the OLC daemon regarding OLC state
changes, so that the consultant is kept as up to date as possible. EOLCR
works particularly well with the consulting tools mentioned in the previous
chapter; they were written with EOLCR in mind. EOLCR also has an
extended set of commands, a convenient and customizable user interface, and
complete on-line documentation. Over the last two years, EOLCR has
replaced olcr as the standard OLCR interface, and is currently used by
over 70 Athena consultants, volunteers, and staff.
Emacs was chosen as the user interface for several reasons. Initially, the ease and power of elisp allowed development of a client which was actually useful very quickly. In fact, throughout EOLCR's development the inherent power of Lisp as an extension language was crucial, since it allowed many invaluable features to be added in a short amount of time and with relatively small amounts of code.
Furthermore, the Emacs interface provided a familiar, well-liked, and easily customizable environment. The fact that Emacs itself is a text editor was essential, since much of a consultant's job involves writing text. Finally, Emacs could also be used on a plain text terminal, which benefited the many consultants which poll the queue remotely by dialing in to Athena.
EOLCR creates three main types of buffers: the List buffer, Replay buffers, and the Status buffer. The List buffer is created automatically on startup; it holds the current OLC queue. The Status buffer displays all users to which the consultant is connected.[5] Replay buffers are created when the consultant replays logs. All three types of buffers share a common set of consulting commands, most of which are single keystroke, for example g to grab a user, r to replay a question, s to send a message to the user, and so on.
EOLCR provides several other commands to ease manipulation of the various buffers. Typing RET switches to a Replay buffer; typing RET several times cycles among all the Replay buffers in EOLCR. ESC n and ESC p cycle among the consultant's connected Replay buffers, i.e. the Replay logs of users to which the consultant is connected. ESC n goes to the user with the next highest instance, and ESC p goes to the user with the next lowest instance. Alternatively, typing n i switches to the log of user with instance n.
In addition to the standard set of consulting commands available in olcr,
EOLCR provides commands to perform other common consulting tasks. The
Emacs version of Athena's On-Line Help module, OLH, and the stock answers
are available with C-c a. Similarly, CRef, Dig, and Klook are
available via C-c c, C-c d, and C-c k.
Other additional EOLCR commands include z to zlocate a user,
C-c h to obtain a user's Hesiod information,
C-c f to finger a user @Athena and @MIT, C-c
H to run hostcheck, a program retrieving useful information about a
user's workstation, and
C-c p to check the status (via /etc/ping) of a user's file
server.
The zlocate command of EOLCR---olcr-zlocate, invoked by typing
z---deserves some special attention. A common nuisance
consultant's face is users who are logged in, but idle at their
workstation. This is frustrating when the consultant attempts to
communicate with the user, but is not aware that the user is idle and
thus probably not at the workstation. olcr-zlocate runs
zlocate on the user, and if the user is logged in, fingers the
user's workstation so the consultant can see if the user is idle.
Furthermore, the result is displayed in the consultant's Status
buffer---discussed in detail below---so the consultant is aware of
whether the user is logged in or idle.
olcr to grab a user.
The Zephyr client updates EOLCR according to the type of Zephyrgrams it receives. For example, if a new question arrives, the Zephyr client will automatically add the question to the List buffer. Likewise, if a question is forwarded, the List buffer will be updated to reflect the new status of the question. For other types of Zephyrgrams---for example those informing the consultant that a user has logged out---the Status buffer and the corresponding Replay buffer are updated.
- Idle?
- This field shows if the user is logged in, and if so, if the user is idle. ``L'' means that the user is logged out, ``Y'' that the user is idle, ``N'' that the user is logged in but not idle. EOLCR normally keeps track of whether a user is logged in; the decision of whether the user is idle comes from running
olcr-zlocateon the user.- Status
- This field serves as a useful summary of the consultant's current interaction with the user. The possible entries are listed in Table 3-2.
- Last Update
- The last time the consultant updated the user's log.
- Last Transaction
- The last time there was a message transaction between the user and the consultant; i.e. the last time the user or the consultant sent a message, or the consultant sent mail.
Any of these fields may have a ``?'', meaning EOLCR does not have the information.
The Emacs mode line of EOLCR List, Status, and Replay buffers displays a summary of the consultant's status in OLC by showing the ``Status'' column of the Status buffer. Initially, the right portion of the mode line looks like this:
|
|
|
Input mode provides another very useful command for consultants
referring users to the stock answers: C-c p
(olh-insert-path[6]). Suppose a consultant wishes to
refer a user to the stock answer on including PostScript figures in
LaTeX documents. The consultant types C-c a to enter the stock
answers browser, finds the stock answer, then enters the Input buffer
and types C-c p, which inserts the following into the buffer:
|
Typing ? enters EOLCR help. The initial Help buffer gives an overview of how EOLCR help works (see Figure 3-3). At this point, the consultant can request command help by typing c, major mode help by typing m, or ``general'' help via the EOLCR user's manual by typing g.
|
olcr-grab or
olcr-cancel. Useful if the consultant is customizing EOLCR.
olcr, olcr's own
help text on the command is included.
Major mode help is similar in concept to Emacs' C-h m command, but provides additional information. For example, for Status mode the full meaning of the columns in the Status buffer is explained. Also, the key bindings for all major EOLCR modes, and not just for those in that particular mode, are displayed in a more organized format than that provided by C-h m.[7]
General help enters the Emacs Info documentation browser and loads the user's manual. Info is an on-line documentation system allowing perusal of on-line documents with chapters, sections, and cross references. The GNU Emacs, Texinfo, and Regex library manuals are available on-line in Info format.
The EOLCR user's manual is a very extensive document covering almost every imaginable aspect of EOLCR, from basic operation to advanced commands to specialized customization. It contains several indices and a special section on the changes made to the most recent EOLCR version. It is also available in DVI format on-line, and as a printed manual in the OLC office.
Some of the customizations in this section refer to a data structure
called an olcr-user. This is a data type defined by EOLCR
which represents a user in OLC. For this section, how it is defined
and used will not be important; these will be discussed in detail later.
For now, consider the olcr-user type as a structure representing
a user, and containing all information EOLCR knows about the user.
This section will cover the more important features of EOLCR which can be customized by the consultant. Many more options are available, but for economy only the two most widely used will be discussed. The rest are covered in the Emacs OLCR User's Manual.
olcr-user, and which return a string that is inserted in the List or
Status buffer when that user is displayed in the corresponding buffer. The
default functions yield the List and Status buffers shown in Figure 3-1 and Chapter 2, Figure 2-7. The print function is called
when the List and Status buffers are created, once for each user, and when
EOLCR needs to update a user.
For both buffers, the consultant can also specify the order in which
users appear. Another two functions, called insert functions,
take an olcr-user, and a list of olcr-user, and insert
the first into the second. The order in which users appear in the list
is the order in which they appear in the List or Status buffer. (There
is a separate list for each.) The default List buffer insert function
orders users according to when the question was asked, from latest to
most recent, and the Status buffer insert function orders them in
increasing order according to their instance with the consultant.
The List buffer allows specification of which queues should be displayed in the buffer, and in what order. The default is to display all six queues---active, pending, unseen, pickup, refer, and on-duty. This is useful for volunteer consultants or consultants performing queue management, neither of which need to see the entire OLC queue. Also, the actual name of the queue as displayed in the buffer is customizable; for example one can have ``New Questions'' appear instead of ``unseen''.
Finally, because many of the consultants using EOLCR are volunteers, it is
unnecessary to always consider all the questions in the queue. For
example, certain volunteers may only be interested in answering questions
under the ``matlab'' or ``fortran'' topics. For these consultants, EOLCR
specifies a filter predicate which takes an olcr-user and
returns t if the user should be displayed in the List buffer, or
nil otherwise.[9] For consultants which must consider the entire
queue, but pay special attention to certain types of questions, the ESC
TAB command in the List buffer jumps to the next user in OLC having a
question in one of these ``specialty'' topics. The default list of
specialty topics is not set, but the consultant can easily set it in the
$HOME/.emacs file.
In EOLCR, a consultant simply specifies a header file and a signature file in their home directory, whose contents are the header and signature of all OLC mail. The automatic insertion of unseen messages and the user's question is also variable. For unseen messages, because it is not always the case that a consultant wants to have them inserted automatically, the consultant can tell EOLCR to display them first before actually inserting them.
autoload function. The following
files define some of the modules essential to EOLCR operation:
- olcr.el
- This is the initial file loaded by EOLCR; its main function is simply to load all other files.
- autoloads.el
- Sets up all the EOLCR modules which are not loaded on startup to be loaded on demand. Consists mostly of
autoloadinstructions for the various commands.- main.el
- Defines some essential functions of EOLCR: manipulation of users, basic subprocess execution, automatic updating, and parsing of the OLC queue.
- misc.el
- Various miscellaneous functions needed by EOLCR. This file is actually about twice the size of main.el because it contains many functions used throughout the rest of the code.
- list-mode.el
- Defines List mode and its associated functions. This includes code to obtain the queue listing from the OLC daemon and to implement the various commands available in List mode.
- commands.el
- Defines the core set of EOLCR commands. These are the most basic commands almost always used, for example
olcr-change-descriptionandolcr-motd.
The main modules consist of the List module, the Status module, the
Input module, and the Replay module, corresponding to the List, Status,
Input and Replay buffers and their associated functions. The List and
Replay modules are always loaded. The Status module is loaded only when
the olcr-status command, which displays the Status buffer, is
executed. Once loaded, the Status module recreates the Status buffer
whenever the List buffer is updated.
Most other modules form orthogonal sets of commands which are loaded on
demand. The Zephyr client and Help modules are good examples. Other
EOLCR commands are also grouped according to overall functionality,
and loaded on demand as a unit. For example, all commands interacting
with the OLC daemon which the consultant can only use once connected to
a user are defined in olc-commands.el. Other commands, such as
olcr-finger and olcr-hesinfo, are defined in
other-commands.el. Finally, specialized minor modes for the
Replay, List, and Status buffers are each treated individually, rather
than as a unit. Thus, the Description minor mode for the List and
Status buffers is defined in description-mode.el, Indent mode for
Replay buffers in indent-mode.el, and so on.
olcr-user Data Typeolcr-user data type to represent a user in
OLC. The olcr-user type is manipulated in similar fashion to
structures created with Common Lisp's
defstruct. An
olcr-user instance is created with the make-olcr-user
macro. Slots are accessed and modified via
olcr-user-slotname
and olcr-user-set-slotname macros
respectively.
Because elisp does not have a defstruct facility, EOLCR
defines a very simple DEFSTRUCT macro in
defstruct.el.[10] It provides the essential
functionality of defining a structure, creating instances of the
structure, and accessing and modifying the fields of an instance.
Many of the slots defined for an olcr-user correspond to the
obvious values relating to the user: username, machine, user instance,
queue, status, and so on. Others hold EOLCR-specific information, such
as the Replay buffer associated with the user (if any), and the last
update and last transaction times as displayed in the Status buffer.
To facilitate updating of other EOLCR state when slots of an
olcr-user structure are modified, EOLCR provides the
olcr-with-user-redisplay macro. This macro takes as arguments
an olcr-user structure and a body of elisp code. The code is
executed; afterwards, the macro examines which slots of the
olcr-user structure were modified, and updates other EOLCR
state as necessary. The macro is actually far from all-inclusive and
handles only a few simple situations, but is nevertheless very useful in
many circumstances.
The above scheme is actually slightly more complicated. EOLCR also
keeps an association list of pointers to these variables, because often
a user must be looked up given an arbitrary queue. (Using only the
above variables works well only if EOLCR knows a priori in
what queue the user is going to be in, which is not true.) The
association list is indexed given a queue name, and the resulting entry
contains the symbol name of the variable containing users in that queue.
The symbol-value and set functions can then be used to
modify the variable.
EOLCR keeps the users in the variables, rather than in the entry
directly, for two reasons. First, it greatly simplifies some operations
in which the queues involved are known a priori. Second, elisp
unfortunately does not provide an equivalent for Common Lisp's
setf macro; thus, modifying an element of a list (other than the
first, which is easily handled by setcar) requires using
nthcdr followed by setcar, which is less convenient.
Because users must be often looked up without knowing what queue they are
in, EOLCR also maintains a hash table of pointers to users, implemented as
an elisp obarray. An obarray is an elisp data type which serves as a very
simple hash table: it only works with strings as keys and symbols as
values.[11] The idea is to indirectly keep each user in the obarray by
constructing a unique Lisp symbol for that user based on the user's
username and user instance. Because obarrays can only store symbols hashed
by strings, the symbol's property list stores the actual user structure,
under the olcr-user property. Thus, to look up a user structure,
given the username and user instance, EOLCR first constructs the string
used to hash into the obarray from the username and user instance. This
returns a unique symbol, whose print name is the string used to hash into
the obarray. The user structure is then retrieved from the property list
of this symbol.
Lisp hackers may wonder why EOLCR needs to create its own obarray to do this (instead of using the global Emacs obarray containing all elisp symbols), or even why any obarray is necessary, since once the symbol is created, it does not need to be ``looked up'' anywhere. One problem is that symbols in elisp do need to be stored somewhere; most are interned in the global Emacs obarray. EOLCR uses its own obarray for two reasons: first, hash look up is faster, since the EOLCR obarray will be much smaller and with many less symbols. Second, there is no way to remove a symbol from an obarray. If EOLCR were to use Emacs' global obarray, there would be no way to remove its entries once EOLCR finished or when users were removed from the queue. Keeping its own obarray allows EOLCR to simply discard the obarray when reading in a new queue listing, thus letting garbage collection clean up the mess.
Besides using the Zephyr client and the OLC queue to stay up to date, EOLCR examines the contents of replay logs, since all transactions between the user and OLC are recorded in the replay log for the user. When EOLCR replays a question, it examines the contents of the Replay buffer to determine the latest status of the question: the topic and description, whether the user is connected to a consultant, whether the user is logged in, and so on. The new information is then reflected in the List buffer. For connected users, the information displayed in the various fields of the Status buffer is also obtained from parsing the log.
EOLCR making sure that it is constantly up to date serves a very important function, since consultants do not have to worry as much about repeatedly querying the OLC server for information. It also helps reduce the load on the server. However, as already mentioned, EOLCR cannot know about all transactions, so it is still necessary to occasionally retrieve the queue listing to obtain a complete picture.
If the users were all displayed in a uniform format, EOLCR would know where on that line the username of the user is found, and could thus extract the information directly from the buffer.[12] Or, if the user print function were forced to always return a string of predetermined length, EOLCR could easily calculate what user should be present at that line. But the print function has no such restrictions. It can display each user in the same format, or use a different format for each user. It can return a string of any length for a user, with or without newlines. How then can EOLCR know which user the cursor is on?
EOLCR solves this problem by keeping track of the start and end positions in the buffer where a user is displayed. This approach would not normally work, because if a user is removed or inserted in the queue, these start and end numbers would have to be manually updated to reflect the new positions of all subsequent users. Fortunately, EOLCR can let elisp keep track of this automatically by using markers---the same type of structure used to hold ``the mark'' defining a region for many Emacs editing commands---to hold the start and end positions, instead of plain numbers. Markers accomplish this because the positions in the buffer they refer to are automatically updated, by Emacs, when text in the buffer is deleted or inserted. Use of many markers in a buffer can slow down editing in the buffer, but the range at which this becomes a problem is much larger than the number of markers typically needed by EOLCR.
EOLCR uses markers in the above fashion as follows: when a user is
inserted in the buffer, the start and end positions of the user in the
buffer are stored in markers. These markers are stored in the
olcr-user structure of the user, under
olcr-user-lbuf-marks for the List buffer, and
olcr-user-sbuf-marks for the Status buffer. Now, given an
arbitrary cursor position in for example the List buffer, EOLCR can
find out which user, if any, is displayed at that position by using a
binary search through the lbuf-marks of each user in the queue.
Note that a binary search assumes that the marks it is searching through
are numbered incrementally; but this is the case, because users are
stored in the order in which they are displayed in the List buffer. The
Status buffer is slightly different, because it keeps a separate ordered
list of the users displayed in the buffer, but the idea is the same.
start-process function:
olist- Actually written for use with EOLCR, it is a convenient and fast client which can be used elsewhere. It interacts directly with the OLC query daemon to retrieve the OLC queue.
oreplay- Like
olist, in that it is a fast client interacting directly with the OLC query daemon.oreplayretrieves replay logs.olcr- The text-based
olcrclient is used for all other OLC daemon transactions. It is somewhat ironic that EOLCR uses the very program it is intended to replace to perform its dirty work. But even though the way in which EOLCR is forced to interface witholcris far from ideal---mainly becauseolcrwas not intended to server as a subclient---it is exactly what EOLCR needs: a general purpose OLC client which can perform all the actual OLC daemon transactions.zclient- The Zephyr client is implemented as a small C program, run as a subprocesses, which does the actual interaction with Zephyr. The Zephyr client will be discussed separately in the Section Zephyr Client Interaction.
EOLCR also relies on other programs, such as zlocate and
finger, to execute commands not interacting with the OLC
daemon.[13] Because EOLCR must
handle a variety of subprocesses, each of which must be handled
differently, EOLCR has four different mechanisms for interacting with
subprocesses. Two of these deal with olist and oreplay
respectively; EOLCR has a unique method for each because of their
specialized use. The rest of the processes (including olcr and those
not interacting directly with the daemon, like zlocate) are
treated differently depending on whether the command executing the
process requires the consultant provide input via an Input buffer.
olist and oreplayolist and oreplay are treated individually. olist is run by the
List buffer module, and oreplay by the Replay buffer module. The
interface is very simple: they are run in the background with
start-process, and their output is collected in a file.
The output file is removed when the consultant quits EOLCR, or in the
case of oreplay, if the consultant is not connected to the
user.[14] Note that the oreplay
output file is used directly as the actual Replay buffer. However,
while the olist output file is parsed internally, what is actually
displayed in the List buffer is the result of calling the user print
function on each user in the queue.
The Replay module performs some extensive parsing of the log to obtain
information about the user, as already discussed. The List buffer
module is more thorough since it must reconstruct most of the internal
state of EOLCR from the output of olist. However, because
EOLCR maintains some information about each user that is not available
from olist's queue listing---namely the information displayed in the
Status buffer---it does not throw away its previous state. In
particular, it updates only the new information in its database,
discarding just those users no longer in the queue.
olcr-execute and olcr-start-input. They are very
similar in concept and functionality. The main difference is that
olcr-start-input is meant for use by commands requiring an Input
buffer in which the consultant can provide the input to be given to the
process. Both take similar arguments, but while
olcr-execute starts the subprocess immediately,
olcr-start-input creates an Input buffer for the consultant, and
starts the subprocess only when the consultant types C-c C-c to
actually execute the command.
The general policy followed by both olcr-execute and
olcr-start-input allows for a flexible process handling
mechanism which must accommodate the varying needs of EOLCR commands
using subprocesses. In particular, these functions take care of the
following:
olcr-start-input has two ways of passing the subprocess its
input: one, as an actual argument, the second as input sent to the
process (using elisp's
process-send-string function) after it
has been started. The former is faster, but is not possible for all
commands.
Checking if the process is already running is easy using elisp's
get-process function, since each process is given a unique name.
Error checking is done in two ways. First, the exit status of the
process is examined. Second, the output of the process is examined; if
it does not match what the command calling olcr-execute or
olcr-start-input expected, an error is assumed. In either case,
an error is handled by immediately displaying the buffer to the
consultant.
If the process terminated normally, the done function is called with the
buffer holding the process output. This done function performs whatever
task the command initiating the subprocess needs performed; for example,
the done function for the olcr-grab command actually updates the
user's
olcr-user structure to reflect the fact that the user is now
connected, places the user in the active queue, and updates the List and
Status buffers.
If no done function is specified, EOLCR assumes that the result should be displayed to the consultant. Because subprocesses are run asynchronously, the consultant may have switched buffers since the command was originally executed. Thus, EOLCR displays the buffer only if the consultant is in the same buffer in which the command was executed. Otherwise the consultant is notified the process terminated via the Emacs minibuffer; the buffer can then be examined at the consultant's own leisure when desired.
The zclient program is a very small C client whose only job is to
subscribe to certain types of Zephyrgrams, and to print such Zephyrgrams
when they arrive. It subscribes to personal messages of the consultant
so that it can catch personal messages from the OLC daemon. It also
subscribes to the following instances of class ``OLC'', recipient ``*'':
- new_question
- Announces new OLC questions.
- nol
- Broadcasts when a consultant has signed on or off duty.
- aloha
- Broadcasts when a user has logged out.
- resurrection
- Broadcasts when a user has logged in.
- forward
- Announces users that are being forwarded by a consultant.
zclient registers its subscriptions with the Zephyr
ZSubscribeToSansDefault function, then waits for a Zephyrgram via
ZReceiveNotice. Because of a problem with Zephyr in which the
Zephyr servers occasionally and quite randomly lose track of client
subscriptions, zclient sets up the SIGALRM interrupt to recheck its
subscriptions every few minutes, resubscribing and continuing if they
have been lost.[15]
On the EOLCR side, the Zephyr client module manages the zclient
subprocess. Its tasks consist of starting the process, handling any
errors, and taking appropriate action when zclient receives a
Zephyrgram.
Errors are handled in a straightforward manner: they are directly
reported to the consultant by displaying the zclient process buffer.
The error message is inserted into the buffer, including instructions on
how to restart the Zephyr client. (This consists of simply typing
M-x olcr-start-zclient.)
When the Zephyr client module receives output from zclient, it checks
to see if it is any of the known Zephyrgrams which it is prepared to
handle. If so, appropriate action is taken; for example, if a
``new_question'' message was received, an olcr-user structure
is created (obtaining the necessary information about the username and
topic from the Zephyrgram), and the question is inserted in the queue.
If the output does not match a known Zephyrgram, the zclient process
is stopped, and an error is reported.
EOLCR, however, faces some awkward situations when dealing with
inferior processes. The elisp subprocess interface provided by Emacs
has proved adequate for EOLCR use. But the actual communication
protocol between EOLCR and its subprocesses is not wholly
satisfactory. In particular, the fact that olcr---EOLCR's chief
subprocess---was not written to run as an inferior to a parent with whom
it must communicate has made EOLCR's general handling of subprocesses
less than ideal. EOLCR must rely heavily on regular expressions to
parse the output of virtually all its subprocesses. This is not a bad
thing in and of itself; for example olist's output is tailored for easy
parsing by EOLCR. However, for other processes, such as olcr and
oreplay, output is formatted for human viewing rather than EOLCR
parsing. EOLCR must therefore parse the output making assumptions
based on experimental analysis rather than a well-defined protocol.
Another somewhat more complicated problem is that of EOLCR's insistence
on asynchrony among its subprocesses, in particular with olcr.
Currently, olcr is loaded for every daemon request (other than list
and replay log updates, which are handled by olist and oreplay).
This is wasteful, especially considering that olcr is not a trivial
program. Ideally, the asynchrony could be maintained without running a
new olcr process for every command. Some ideas on resolving this are:
olcr client written specifically for use with EOLCR. This
client would handle multiple requests simultaneously, and also provide a
well-defined interface to EOLCR.
olcr. In this scheme, EOLCR would always keep at least one olcr
process running all the time, and would spawn other olcr processes
when the central one was occupied with a request.
olcr program, take the olist and
oreplay approach: write a host a smaller subclients, each of which
would perform a single, specialized task. For example, there would be
an ograb client to grab questions, an osend client to
send messages, and so on. This would reduce some of the overhead
involved in starting a subprocess, since each of these clients would be
significantly smaller than the complete olcr client.
Among these solutions, the last is the more realistic (though not necessarily the more preferable), since it requires no changes in the OLC protocol and little work in terms of writing the actual clients and of the changes that would have to be made to EOLCR.
Finally, EOLCR attempts to resolve problems of state maintenance in
interesting ways. EOLCR grabs bits and pieces of OLC state from
wherever it can: Zephyrgrams, replay logs, and command output. EOLCR's
view of the world is always an approximation, although a very good one.
Even after reading the OLC queue, its picture is not guaranteed to be
accurate, for two reasons. First, the OLC poll daemon, which keeps
track of the login status of users, is itself not always completely up
to date, because it checks every user periodically, not constantly.
Second, the OLC query daemon from which olist obtains its output is
likewise not guaranteed to always be up to date. In particular, the
query daemon does not obtain the queue listing directly from the
main lock daemon: it instead retrieves a dumped backup copy made by the
lock daemon after only certain types of transactions.[17]
EOLCR's use of Zephyr as an updating mechanism is an innovative approach which seems natural but has actually not been widely used elsewhere.[18] Zephyr as a sole communication medium between a client and a server exchanging significant amounts of information is probably not a good idea. But to the limited extent in which EOLCR uses Zephyr in this respect, it does serve as a practical and simple relayer of state information without requiring a hefty protocol specification or a complicated communication model.