<CHAPTER ID="ZADM-THE-QUEUE"><?dbhtml filename="zadm-queues.html">
<TITLE>The Queue</TITLE>

<PARA>
Normal processing within ZMailer goes via directories described at
<XREF LINKEND=fig.zadm.zmdirs>.
A message <EMPHASIS>may</> get sidelined or copied to other directories
for several possible reasons.
</PARA>

<IMPORTANT>
<PARA>
<EMPHASIS>
A filesystem without following two properties is not suitable for ZMailer's
</EMPHASIS>
<FILENAME CLASS=DIRECTORY>$<VARNAME>POSTOFFICE</>/</>:
<ITEMIZEDLIST>
<LISTITEM><PARA><EMPHASIS>
Files must succeed to be <FUNCTION>link</>(2):ed in between directories
within the filesystem without copying them.
</EMPHASIS></PARA></LISTITEM>
<LISTITEM><PARA><EMPHASIS>
The file i-node numbers must not change with <FUNCTION>rename</>(2) or
<FUNCTION>link</>(2) calls applied to them.
</EMPHASIS></PARA></LISTITEM>
</ITEMIZEDLIST>
</PARA>

<PARA>
The <FILENAME CLASS=DIRECTORY>$<VARNAME>POSTOFFICE</>/</> directory must be
a single partition within which files can be <FUNCTION>link</>(2)ed from one
directory to another, as well as moved around with <FUNCTION>rename</>(2).
</PARA>

<PARA>
People have asked several times if e.g.
 <FILENAME CLASS=DIRECTORY>$<VARNAME>POSTOFFICE</>/public/</>, and
 <FILENAME CLASS=DIRECTORY>$<VARNAME>POSTOFFICE</>/transport/</>
could be at separate partitions.  No they can't!
</PARA>
</IMPORTANT>

<FIGURE PGWIDE="1" FLOAT="1" ID=fig.zadm.zmdirs>
  <TITLE ID=figtit.zadm.zmdirs>
    Directories that ZMailer uses for message processing.
  </TITLE>
  <MEDIAOBJECT>
    <IMAGEOBJECT>
      <IMAGEDATA FILEREF="zmdirs.&GEXT;" FORMAT="&GEXT;">
    </IMAGEOBJECT>
  </MEDIAOBJECT>
</FIGURE>

<PARA>
There are multiple queues in ZMailer. Messages exist in
in one of five locations:

<ITEMIZEDLIST>
<LISTITEM><PARA>
Submission temporary directory
   (<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/public/</>)
</PARA></LISTITEM>
<LISTITEM><PARA>
Freezer directory
   (<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/freezer/</>)
</PARA></LISTITEM>
<LISTITEM><PARA>
Router directory
   (<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/router/</>)
</PARA></LISTITEM>
<LISTITEM><PARA>
Deferred directory
   (<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/deferred/</>)
</PARA></LISTITEM>
<LISTITEM><PARA>
Scheduler directories
   (<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/transport/</>,
    <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/queue/</>)
</PARA></LISTITEM>
</ITEMIZEDLIST>

and sometimes is also copied into the 
<ITEMIZEDLIST>
<LISTITEM><PARA>
Postmaster analysis area
   (<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/postman/</>)
</PARA></LISTITEM>
</ITEMIZEDLIST>
</PARA>

<SECT1 ID=zadm-queue-msgsubmission>
<TITLE>Message Submission Areas</>


<PARA>
Message submission is done by writing a temporary file into the directory
(<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/public/</>),
the  actual format of the submitted message is described in
<XREF LINKEND="zapp.msg-file-format">.
</PARA>

<PARA>
When the temporary file is completely written, it is renamed into one 
of the <COMMAND>router</> input directories, usually into 
  <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/router/</>
ith a name that is a decimal representation of the spool-file i-node number.
This is a way to ensure that the name of the file in the
  <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/router/</>
directory is unique.
</PARA>

<PARA>
The message may also be renamed into alternate router directories, 
which give lower priorities on which messages to process when.
</PARA>

<PARA>
Sometimes, especially <COMMAND>smtpserver</> built files may be moved
into alternate directories.
The <COMMAND>smtpserver</> <QUOTE>ETRN</> command has two implementations,
original one is by moving the built special file to the directory
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/transport/</>
without going through the <COMMAND>router</>.
The <COMMAND>smtpserver</> may also move newly arrived files into the
  <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/freezer/</>
directory.
</PARA>

</SECT1>

<SECT1 ID=zadm-queue-router-behaviour>
<TITLE><COMMAND>Router</> Behaviour on Queues</>

<PARA>
<SCREEN>
FIXME:
   This description is from era before the router got
   ``daemonized'' in a sense of having separate instance
   of queue processor (and it also handles logging/log rotation)
   and a worker-farm of routing work processes.
</SCREEN>
</PARA>

<PARA>
FIXME:
The system can have multiple <COMMAND>router</> processes running in parallel
and competeting on input files.  Multiple processes may make sense when
there are multiple processors in the system allowing running them in
parallel, but also perhaps for handling cases where one process is handling
routing of some large list, and other (hopefully) will get less costly jobs.
</PARA>

<PARA>
The <COMMAND>router</> processes have a few different behaviours when
they go over their input directories.
</PARA>

<PARA>
First of all, if there are <VARNAME>ROUTERDIRS</> entries, those
are scanned for processing after the primary 
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/router/</>
directory is found empty.
</PARA>

<PARA>
Within each directory, the <COMMAND>router</> will sort files
at first into mod-time order, and then process the oldest message
first. (Unless the  <COMMAND>router</> has been started with
the `-s' option.)
</PARA>

<PARA>
The <COMMAND>router</> acquires a lock on the message (spool file) by means of
renaming the file from its previous name to a name created with
formatting statement:
<SCREEN>
  sprintf(buf, "%ld-%d", (long)filestat.st_ino, (int)getpid());
</SCREEN>
</PARA>

<PARA>
Once the <COMMAND>router</> has been able to acquire a new name
for the file, it starts off by creating a temporary file of
<COMMAND>router</> routing decisions. 
The file has a name created with formatting statement:
<SCREEN>
  sprintf(buf, "..%ld-%d", (long)filestat.st_ino, (int)getpid());
</SCREEN>
</PARA>

<PARA>
Once the processing has completed successfully, the original
input file is moved into the directory
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/queue/</>,
and the <COMMAND>router</> produced
<COMMAND>scheduler</> work-specification file is moved to
the <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/transports/</>
directory with the <EMPHASIS ROLE="BOLD">same name</> that the original
file has.
</PARA>

<PARA>
If the routing analysis encountered problems, the message may end up
moved into the directory
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/deferred/</>,
from which the command <COMMAND>zmailer resubmit</> is needed to return
the messages into processing
(The <COMMAND>router</> logs should be consulted for the reason why
 the message ended up in the <FILENAME CLASS="DIRECTORY">/deferred/</>
 area, especially if the command <COMMAND>zmailer resubmit</> is not able
 to get the messages processed successfully and the files end up back
 in the <FILENAME CLASS="DIRECTORY">/deferred/</> area.)
</PARA>

<PARA>
If the original message had errors in its RFC-822 compliance,
or some other detail, a copy of the message may end up in the 
directory <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/postman/</>.
</PARA>

<PARA>
See Postmaster Analysis Area on section
<XREF LINKEND="zadm-queue-postmaster-analysis-area">.
</PARA>

</SECT1>

<SECT1 ID=zadm-queue-scheduler-and-transport-agents>
<TITLE><COMMAND>Scheduler</>, and Transport Agents</>

<PARA>
The scheduler work specification files are in the directory
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/transport/</>,
under which there can be (optionally) one or two levels of
subdirectories into which the actual work files will be scattered
to lessen the sizes of individual directories in which files reside,
and thus to speed up the system implied directory lookups at
the transport agents, when they open files, (and also in the scheduler).
</PARA>

<PARA>
When the <COMMAND>router</> has completed message file processing,
it places the resulting files into the top level directory of the
<COMMAND>scheduler</>; 
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/transport/</>,
and <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/queue/</>.
</PARA>

<PARA>
The <COMMAND>scheduler</> (if so configured by ``<OPTION>-H</>'' option) will
move the messages into ``hashed subdirectories,'' when it finds the
new work specification files, and then start processing them.
</PARA>

<PARA>
The transport agents are run with their CWD in directory 
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/transport/</>,
and they open files relative to that location.
Actual message bodies, when  needed, are opened with the path prefix
``<FILENAME CLASS="DIRECTORY">../queue/</>'' to the work specification
file name.
</PARA>

<PARA>
Usually it is the <EMPHASIS>transport agent's</> duty to log different
permanent status reports (failures, successes) into the end of
the work-specification file.  
Sometimes the <COMMAND>scheduler</> also logs something at the end of
this file.  
All such operations are attempted <EMPHASIS ROLE="BOLD">without</> any sort 
of explicit locking, instead trusting the <EMPHASIS>write(2)</> system call
to  behave in an atomic manner while writing to the disk file, and 
having a single buffer of data to write.
</PARA>

<PARA>
Once the <COMMAND>scheduler</> has had all message recipient addresses
processed by the <EMPHASIS>transport agents</>, it will handle possible
diagnostics on the message, and finally it will remove the original spool-file
from the <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/queue/</>, and 
the work-specification file from
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/transport/</>.
</PARA>

</SECT1>

<SECT1 ID="zadm-queue-postmaster-analysis-area">
<TITLE>Postmaster Analysis Area</TITLE>

<PARA>
If the filename in the
 <FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/postman/</>
directory has an underscore in it, the reason for the copy is
<EMPHASIS ROLE="BOLD">soft</>, that is, the message has been sent
through successfully in spite of being copied into the directory.
</PARA>

<PARA>
<EMPHASIS ROLE="STRONG">If the filename in that directory does not have
an underscrore in it, that file has not been processed successfully, and
the <EMPHASIS ROLE="BOLD">only</> copy of the message is now in that
directory!</EMPHASIS>
</PARA>

<PARA>
Usually forementioned underscoreless filenames 
</PARA>

<PARA>
If the <COMMAND>smtpserver</> receives a message with content that
the <EMPHASIS>policy filtering</> system decides to be dubious,
it can move the message into
<FILENAME CLASS="DIRECTORY">$<VARNAME>POSTOFFICE</>/freezer/</> directory
with a bit explanatory name of type:
<SCREEN>
  sprintf(buf, "%ld.%s", (long)filestat.st_ino, causecodestring);
</SCREEN>
</PARA>

<PARA>
The files in the freezer-area are in the input format to
the <COMMAND>router</>, and as of this wiring, there are no tools
to automatically process them for obvious spams, and just those
that were falsely triggered.
</PARA>
</SECT1>
</CHAPTER>
