Data structures for mailer satellite Each of the below is a separate LSE and the indicated name is the address of the LSE's HDR ARBLK. To reference, one must have AC L loaded with the starting address of the HDR, e.g. MOVE L,$ARLOC+MASTER will set up L to reference the master ID list. MASTER -> Master ID list, which is referenced whenever an actual message must be pulled in or written out. Each CAR is a sublist containing: A$I - node LLN A$ID The message ID (a string) A$IDAD Its disk address in the MSG LISTS file. (value) In addition, $LHMFG(L) contains the # of garbage words in file, $LHMFL(L) the total # of words. These 2 are "extra" LSE-HDR words. SCHDAR -> Scheduler list, which can be added to from any routine at almost any time, and which is processed between messages. It is kept sorted by requested time, which is "system time" - 30'ths of a sec since system came up. Each entry is a LLN: A$S - node LLN A$STIM Request Time (system time) A$SRTN Routine to execute (internal addr) A$SARG Argument for routine (arbitrary value) MSGAR -> Message list, which holds all attributes for the message currently being processed. Messages are composed into, written from, and loaded back into this list. Routines which operate on the "current message" operate on this list. Attributes are listed elsewhere. EMSGAR -> Like MSGAR, but used for collecting Error Message attribs (if any). This is a separate LSE so that it can be composed at the same time as the regular MSG. When sending, the EMSGAR ARBLK is simply copied into the MSGAR ARBLK. EQVAR -> Equivalences list. Holds the explicit translations which are to be done for message recipient names, as well as various sorts of options which recipients can specify. Later it will be possible to index this list via a sorted table; for the time being, each node has: A$E - node LLN ;this needs A$ENAM Name for which following options or equivalences apply. ;revising. A$ROPT Recipient option (any number, 0-n) A$RCP Recipient list. Can hold anything regular A$RCP does, but usually just A$RNAM, A$RHST, A$ROPT, A$RTYP. QMLAR -> Queued Message list. Indicates which messages, for which recipients, are queued to which sites. Each CAR is a sublist, one for each site: A$Q - node LLN A$QHST Site # of sublist (value) A$ID Message ID (string) When a "un-queue for this host" request is executed by scheduler, the indicated site is checked; if alive, each message in that site's list is then read into core and sent to all recipients in the message which have that site as destination. It is possible to process input requests between each message, since any additional messages queued are appended to the sitelists and will be processed in due turn. When un-queued (successfully or not), a recipient has its A$RCP attrib changed to A$RSNT, and the message list is stored back if any A$RCP's are left. If none are left, the message is flushed from the master ID list. In either case, its QML entry is deleted if there are no more recipients in the message for that site. It can try to be clever about keeping a message in core until all of its recipients for that site are sent. File-type recipients with devices such as ML, DM, etc will also be kept on their respective site lists. The network routines can also maintain information on connection status across message transmissions, so that re-ICP's are unnecessary if something interrupts un-queueing or the like. RMLAR -> Remind Message list. Holds a list of message ID's with the time each is due to be sent. Note that if such a "reminder" can't be sent immediately, a copy is put on the QML like any other message, and it is considered sent. Like the Schedule list, this is sorted by time. Note however that the "time" is in internal date/time format (see TIMRTS doc) rather than "system time". A$RML - node LLN A$RMLT Time for sending (internal date/time word) A$ID Message ID (string) When a send-reminder request is executed by the scheduler, the reminder in question is read into core and sent as if just composed. The more detailed "remind" options it contains are then examined to see if it should recur again; if not, it is flushed from the RML. Otherwise the next request time is determined and it is put back on the RML somewhere. Disk storage of data bases The above LSE's are stored on disk in the format specified in the LSE documentation, with either one or several to a file. The LSE's for all individual messages are stored in " LISTS MSGS", one disk-block LSE for each message. Each has a unique message-ID, and is referenced only by the MASTER list, which binds message-ID's to the disk address within this file. New MSG's are written onto the end of the file in write-over mode, and deletions made by flushing the MASTER-list information; whenever the count of known garbage words and known file length satisfies certain criteria, the file is GC'd. The other LSE's stored on disk include: MASTER = " LIST MASTER" QML = " LIST QUEUE " RML = " LIST REMIND" EQV = " LIST EQVS " MSGS'S = " LISTS MSGS " (included here for completeness) Updating the EQV file can be done with simple re-write and RENMWO, but information in the other files is interdependent and hence updating is slightly trickier. In general, to update any MSG LSE, it must first be written back out onto the end of LISTS MSGS; then MASTER can be updated, but to ensure permanence MASTER itself must be written out to NLIST MASTER, and RENMWO'd to LIST MASTER. The latter manuever is intended to foil any crashes that might leave the writing only partially done. Since upon completion of this storage the message is now solidly in the data base, whatever input request file it came from should be immediately flushed. Otherwise, a crash could leave both the stored LSE and original request extant, producing unnecessary duplication. Similarly, if such a MSG LSE is stored, it must contain all information necessary to continue correct processing should the mailer crash or the input file be deleted immediately after storing. To update either the RML or QML lists, one can simply write out in the same fashion as MASTER. Since in general a change in either will reflect some change in a MSG LSE, this must be coordinated with the MSG and MASTER file update. This is done by writing out the updated MSG-LSE and MASTER first, and then whichever auxiliary list is concerned. At worst, the MASTER/MSG-LSE will contain information which the RML/QML doesn't yet reflect, or could assume that the RML/QML has something it doesn't. Since the RML/QML are merely intended to serve as indexing aids, this can be resolved by ignoring and flushing any reference by the RML/QML to a MSG ID that doesn't exist on the MASTER list. Procedure for handling input requests (MAIL > files) An input request can be processed whenever the mailer is not already processing one, or between each transmission of a network message. The processing of an input request includes both the MSG list composition and all local sending for that message, on the grounds that local messages should receive the highest priority. A message can always, once composed, be queued or put on the scheduler list. From that point on, the mailer is interruptable whenever it is not actually sending to a single recipient. Input requests are made as files named MAIL >. However, the mailer does not actually read from these; first it attempts to rename MAIL > to MAILIN >, and if successful it thereupon proceeds to slurp up the MAILIN file and process the request. Thus, the RENAME call is the test for existence of a request. Extra MAILIN files are processed only after there are no MAIL files. The basic scheduling algorithm is: BEG: --> do it, return to BEG This includes items on the schedule list which resulted from previous actions, and which must be executed ASAP whenever not composing or sending a message. The time value for such requests is negative! --> rename to MAILIN, continue --> process input request, return to BEG. --> do, return to BEG This includes anything which needs doing sometime, but which has lower priority than input or remind requests. For example, testing a dead network site. Time value for these is normal system-time-to-run-at. The wakeup time is determined from the next schedule request due; perhaps there is a reminder going off in 15 minutes, or a network check to perform in 5, or a disk re-try in 1. It will never sleep for longer than c(SLPLIM) minutes (20 or so), and will be restarted instantly whenever a file is written to .MAIL. (by virtue of the NQMFWR crock). If the time to sleep is greater than c(NAPLIM) then various clean-up hacks will be done to reduce resources used by the mailer, before going to sleep. Otherwise, it takes a "nap" (less than 60 sec or so) without attempting to flush core etc, on the theory that it will just have to start all over again in a little bit. In addition to the basic algorithm above, there is a check after the composition of a message, and after each network transmission, to determine whether current processing should be interrupted and a pending input request handled. For message composition, this is based on whether the message has been assigned a low priority (in which case it is completely queued); if not, all local copies are sent without interruption. Before attempting to send any network message, a check is ALWAYS made for the existence of new input requests (MAIL >'s only). The current process will be either sending network copies of the last input request, or unqueueing messages from the QML list; if the former, the message is queued and put on the QML, and a scheduler request created to try unqueueing for these sites as soon as no more input requests are seen. If the latter, an appropriate schedule request is generated to re-try whatever site the unqueuer was interrupted from. Error messages are composed in a special LSE and are considered high-priority "input requests", and are checked for at the same times as described above. The fact that they are not sent immediately during composition or local sending allows such error messages to be cumulative and include as much information as is available after such processing. When necessary, it is (or should be) possible to interrupt and send immediately. This might have to be restricted to local names without equivalencing/forwarding, though. Programs as recipients: With the addition of "recipient types" it is possible to define a recipient as being of type "program"; when mail is sent to it, the specified program will be run, with the message possibly being given it as an argument in some fashion (such as JCL). Since the program will almost always require some attention, and run over a perhaps lengthy span of time, it is necessary for the mailer to handle such inferiors in parallel with normal processing. Although up to 8 inferiors are possible, only 1 will be allowed to exist at any given time; other program recipients will simply be queued and have to wait their turn. Handling will be done by means of the scheduler and inferior-interrupt routines; when an interrupt is received, it is analyzed and either handled immediately or the necessary scheduler request is generated, and the interrupt dismissed. There is no real obstacle to having multiple inferiors, other than increased complexity and possible core gronkage, since the message data for each must be maintained in core at the same time. ‡‡ï