2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 13:48:06 +00:00

snapshot-20001004

This commit is contained in:
Wietse Venema 2000-10-04 00:00:00 -05:00 committed by Viktor Dukhovni
parent 04bda7598b
commit 18a7a4179e
17 changed files with 380 additions and 276 deletions

View File

@ -4,6 +4,12 @@ Purpose of this document
This document describes the purpose of the Postfix fast ETRN service,
how the service works, and how it can be tested.
Other documents with information on this subject:
- conf/sample-flush.cf, sample configuration file
- conf/main.cf, sample configuration file
- flush(8), flush service implementation
The Postfix fast ETRN service
=============================

View File

@ -0,0 +1,50 @@
# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF
# HERE JUST SERVES AS AN EXAMPLE.
#
# This file contains example settings of Postfix parameters that
# control the fast flush service, which is the engine that implements
# ETRN and "sendmail -qR".
# The fast_flush_policy parameter specifies what destinations are
# eligible for per-destination logfiles with mail that is queued to
# those destinations.
#
# When a destination is eligible, ETRN and "sendmail -qR" are
# implemented by delivering only messages that are queued for that
# destination (Postfix will deliver to all recipients of those
# messages, regardless of their destination).
#
# When a destination is not eligible, ETRN and "sendmail -qR" are
# implemented simply by attempting to deliver all queued mail.
#
# By default, Postfix maintains per-destination deferred mail logfiles
# only for destinations that the Postfix SMTP server is willing to
# relay to (see the relay_domains parameter in sample-smtpd.cf).
#
# Specify "all" to enable per-destination deferred mail logfiles
# for all destinations, "none" to disable the logfiles altogether.
#
#fast_flush_policy = all
fast_flush_policy = relay
#fast_flush_policy = none
# The fast_flush_purge_delay parameter controls how long an empty
# per-destination deferred mail logfile is allowed to live.
#
# You can specify the time as a number, or as a number followed by
# a letter that indicates the time unit: s=seconds, m=minutes, h=hours,
# d=days, w=weeks. The default time unit is days.
#
fast_flush_purge_delay = 7d
# The fast_flush_refresh_delay parameter controls how long a non-empty
# per-destination deferred mail logfile is allowed to remain unread
# before its contents need to be refreshed. The contents of a logfile
# are refreshed by requesting delivery of messages listed in the
# logfile.
#
# You can specify the time as a number, or as a number followed by
# a letter that indicates the time unit: s=seconds, m=minutes, h=hours,
# d=days, w=weeks. The default time unit is hours.
#
fast_flush_refresh_delay = 12h

View File

@ -18,47 +18,47 @@ FLUSH(8) FLUSH(8)
equivalent, <b>sendmail</b> <b>-qR</b>. This program expects to be run
from the <a href="master.8.html"><b>master</b>(8)</a> process manager.
The record is implemented as per-destination logfiles with
as contents the queue IDs of deferred mail. The files are
append-only, and are truncated when delivery is requested
for a specific site.
The record is implemented as a per-destination logfile
with as contents the queue IDs of deferred mail. A logfile
is append-only, and is truncated when delivery is
requested for the corresponding destination. A destination
is the part on the right-hand side of the right-most <b>@</b> in
an email address.
Deferred mail by destination information is recorded only
for destinations that are eligible according to a config-
urable policy. The policy is specified with the
<b>fast</b><i>_</i><b>flush</b><i>_</i><b>cache</b><i>_</i><b>policy</b> configuration parameter:
Per-destination logfiles of deferred mail are maintained
only for eligible destinations. The policy is specified
with the <b>fast</b><i>_</i><b>flush</b><i>_</i><b>cache</b><i>_</i><b>policy</b> configuration parameter:
<b>all</b> Maintain per-destination deferred mail logfiles for
all destinations.
<b>all</b> Maintain per-destination logfiles for all destina-
tions.
<b>relay</b> Maintain per-destination deferred mail logfiles
only for destinations that this system is willing
to relay mail to ($<b>relay</b><i>_</i><b>domains</b>).
<b>relay</b> (default policy)
Maintain per-destination logfiles only for destina-
tions that this system is willing to relay mail to
(as controlled by the <b>relay</b><i>_</i><b>domains</b> configuration
parameter).
<b>none</b> Do not maintain per-destination deferred mail log-
files.
<b>none</b> Do not maintain per-destination logfiles.
This server implements the following requests:
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>ADD</b> <i>sitename</i> <i>queue_id</i>
Inform the cache manager that the specified message
is queued for the specified site. Depending on
caching policy, the cache manager stores or ignores
the information.
is queued for <i>sitename</i>. Depending on caching pol-
icy, the cache manager stores or ignores the infor-
mation.
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>SEND</b> <i>sitename</i>
Request delivery of all messages that are queued
for the specified site. Depending on cache policy,
this triggers delivery of specific messages or of
all queued mail. The per-destination logfile is
discarded.
<b>TRIGGER</b><i>_</i><b>REQ</b><i>_</i><b>WAKEUP</b> (wakeup signal from master)
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>PURGE</b>
Delete empty per-destination logfiles that haven't
been updated in $<b>fast</b><i>_</i><b>flush</b><i>_</i><b>purge</b><i>_</i><b>delay</b> seconds.
Request delivery of mail that is queued for <i>site-</i>
<i>name</i>. If the destination is eligible for a fast
flush logfile, this request triggers delivery of
specific messages; the per-destination logfile is
truncated to zero length; if mail is undeliverable,
it will be logged to the per-destination logfile.
If the destination is not eligible for a fast flush
logfile, this request triggers delivery of all
queued mail.
@ -71,22 +71,36 @@ FLUSH(8) FLUSH(8)
FLUSH(8) FLUSH(8)
<b>TRIGGER</b><i>_</i><b>REQ</b><i>_</i><b>WAKEUP</b>
This wakeup request from the master is an alterna-
tive way to request <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>REFRESH</b>.
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>REFRESH</b> (completes in the background)
Refresh non-empty per-destination logfiles that
were not read in $<b>fast</b><i>_</i><b>flush</b><i>_</i><b>refresh</b><i>_</i><b>delay</b> seconds.
This is done by pretending that send requests were
received for the corresponding sites.
were not read in $<b>fast</b><i>_</i><b>flush</b><i>_</i><b>refresh</b><i>_</i><b>delay</b> hours,
by simulating send requests (see above) for the
corresponding destinations.
Fast flush logfiles are truncated only after a
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>SEND</b> request, not when mail is actually
delivered, and therefore can accumulate outdated or
redundant data. In order to maintain sanity,
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>PURGE</b> should be requested at regular
imtervals.
Delete empty per-destination logfiles that were not
updated in <b>fast</b><i>_</i><b>flush</b><i>_</i><b>purge</b><i>_</i><b>delay</b> days.
After an initial sanity check of request parame-
ters, this request proceeds in the background.
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>PURGE</b> (completes in the background)
Refresh all non-empty per-destination logfiles, by
simulating send requests (see above) for the corre-
sponding destinations. This can be incredibly
expensive when caching is enabled for all deferred
mail, and is not recommended.
The response to the client is one of:
Delete empty per-destination logfiles that were not
updated in <b>fast</b><i>_</i><b>flush</b><i>_</i><b>purge</b><i>_</i><b>delay</b> days.
Fast flush logfiles are truncated only after a
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>SEND</b> request, not when mail is actually deliv-
ered, and therefore can accumulate outdated or redundant
data. In order to maintain sanity, <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>REFRESH</b> must
be executed periodically.
The server response is one of:
<b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>OK</b>
The request completed normally.
@ -109,8 +123,20 @@ FLUSH(8) FLUSH(8)
<b>BUGS</b>
In reality, this server schedules delivery of all recipi-
ents of deferred messages. This limitation is due to the
ents of a deferred message. This limitation is due to the
fact that one queue runner has to handle mail for multiple
2
FLUSH(8) FLUSH(8)
destinations.
<b>FILES</b>
@ -125,26 +151,16 @@ FLUSH(8) FLUSH(8)
What destinations can have a "fast flush" logfile:
<b>all</b>, <b>relay</b> (relay destinations) or <b>none</b>.
2
FLUSH(8) FLUSH(8)
<b>fast</b><i>_</i><b>flush</b><i>_</i><b>refresh</b><i>_</i><b>delay</b>
Refresh a non-empty "fast flush" logfile that was
not read in this amount of time, by simulating a
send request for the corresponding destination.
not read in this amount of time (default time unit:
hours), by simulating a send request for the corre-
sponding destination.
<b>fast</b><i>_</i><b>flush</b><i>_</i><b>purge</b><i>_</i><b>delay</b>
Remove an empty "fast flush" logfile that was not
updated in this amount of time.
Remove an empty "fast flush" logfile that was not
updated in this amount of time (default time unit:
days).
<b>SEE</b> <b>ALSO</b>
<a href="smtpd.8.html">smtpd(8)</a> Postfix SMTP server
@ -173,22 +189,6 @@ FLUSH(8) FLUSH(8)

View File

@ -19,51 +19,65 @@ This information is used to improve the performance of the SMTP
This program expects to be run from the \fBmaster\fR(8) process
manager.
The record is implemented as per-destination logfiles with
as contents the queue IDs of deferred mail. The files are
append-only, and are truncated when delivery is requested
for a specific site.
The record is implemented as a per-destination logfile with
as contents the queue IDs of deferred mail. A logfile is
append-only, and is truncated when delivery is requested
for the corresponding destination. A destination is the
part on the right-hand side of the right-most \fB@\fR in
an email address.
Deferred mail by destination information is recorded only for
destinations that are eligible according to a configurable policy.
The policy is specified with the \fBfast_flush_cache_policy\fR
configuration parameter:
Per-destination logfiles of deferred mail are maintained only for
eligible destinations. The policy is specified with the
\fBfast_flush_cache_policy\fR configuration parameter:
.IP \fBall\fR
Maintain per-destination deferred mail logfiles for all destinations.
.IP \fBrelay\fR
Maintain per-destination deferred mail logfiles only for destinations
that this system is willing to relay mail to ($\fBrelay_domains\fR).
Maintain per-destination logfiles for all destinations.
.IP "\fBrelay\fR (default policy)"
Maintain per-destination logfiles only for destinations
that this system is willing to relay mail to (as controlled
by the \fBrelay_domains\fR configuration parameter).
.IP \fBnone\fR
Do not maintain per-destination deferred mail logfiles.
Do not maintain per-destination logfiles.
.PP
This server implements the following requests:
.IP "\fBFLUSH_REQ_ADD\fI sitename queue_id\fR"
Inform the cache manager that the specified message is queued for
the specified site. Depending on caching policy, the cache manager
\fIsitename\fR. Depending on caching policy, the cache manager
stores or ignores the information.
.IP "\fBFLUSH_REQ_SEND\fI sitename\fR"
Request delivery of all messages that are queued for the specified
site. Depending on cache policy, this triggers delivery of specific
messages or of all queued mail. The per-destination logfile is
discarded.
.IP "\fBTRIGGER_REQ_WAKEUP\fR (wakeup signal from master)"
.IP "\fBFLUSH_REQ_PURGE\fR"
Delete empty per-destination logfiles that haven't been updated in
$\fBfast_flush_purge_delay\fR seconds.
Request delivery of mail that is queued for \fIsitename\fR.
If the destination is eligible for a fast flush logfile,
this request triggers delivery of specific messages; the
per-destination logfile is truncated to zero length; if mail
is undeliverable, it will be logged to the per-destination
logfile.
.sp
If the destination is not eligible for a fast flush logfile,
this request triggers delivery of all queued mail.
.IP \fBTRIGGER_REQ_WAKEUP\fR
This wakeup request from the master is an alternative way to
request \fBFLUSH_REQ_REFRESH\fR.
.IP "\fBFLUSH_REQ_REFRESH\fR (completes in the background)"
Refresh non-empty per-destination logfiles that were not read in
$\fBfast_flush_refresh_delay\fR seconds. This is done by pretending
that send requests were received for the corresponding sites.
$\fBfast_flush_refresh_delay\fR hours, by simulating
send requests (see above) for the corresponding destinations.
.sp
Delete empty per-destination logfiles that were not updated in
\fBfast_flush_purge_delay\fR days.
.IP "\fBFLUSH_REQ_PURGE\fR (completes in the background)"
Refresh all non-empty per-destination logfiles, by simulating
send requests (see above) for the corresponding destinations.
This can be incredibly expensive when caching is enabled for
all deferred mail, and is not recommended.
.sp
Delete empty per-destination logfiles that were not updated in
\fBfast_flush_purge_delay\fR days.
.PP
Fast flush logfiles are truncated only after a \fBFLUSH_REQ_SEND\fR
request, not when mail is actually delivered, and therefore can
accumulate outdated or redundant data. In order to maintain sanity,
\fBFLUSH_REQ_PURGE\fR should be requested at regular imtervals.
.sp
After an initial sanity check of request parameters, this request
proceeds in the background.
.PP
The response to the client is one of:
\fBFLUSH_REQ_REFRESH\fR must be executed periodically.
The server response is one of:
.IP \fBFLUSH_STAT_OK\fR
The request completed normally.
.IP \fBFLUSH_STAT_BAD\fR
@ -87,7 +101,7 @@ Problems and transactions are logged to \fBsyslogd\fR(8).
.ad
.fi
In reality, this server schedules delivery of all recipients
of deferred messages. This limitation is due to the fact that
of a deferred message. This limitation is due to the fact that
one queue runner has to handle mail for multiple destinations.
.SH FILES
.na
@ -106,11 +120,11 @@ What destinations can have a "fast flush" logfile: \fBall\fR,
\fBrelay\fR (relay destinations) or \fBnone\fR.
.IP \fBfast_flush_refresh_delay\fR
Refresh a non-empty "fast flush" logfile that was not read in
this amount of time, by simulating a send request for the
corresponding destination.
this amount of time (default time unit: hours), by simulating
a send request for the corresponding destination.
.IP \fBfast_flush_purge_delay\fR
Remove an empty "fast flush" logfile that was not updated in
this amount of time.
this amount of time (default time unit: days).
.SH SEE ALSO
.na
.nf

View File

@ -13,51 +13,65 @@
/* This program expects to be run from the \fBmaster\fR(8) process
/* manager.
/*
/* The record is implemented as per-destination logfiles with
/* as contents the queue IDs of deferred mail. The files are
/* append-only, and are truncated when delivery is requested
/* for a specific site.
/* The record is implemented as a per-destination logfile with
/* as contents the queue IDs of deferred mail. A logfile is
/* append-only, and is truncated when delivery is requested
/* for the corresponding destination. A destination is the
/* part on the right-hand side of the right-most \fB@\fR in
/* an email address.
/*
/* Deferred mail by destination information is recorded only for
/* destinations that are eligible according to a configurable policy.
/* The policy is specified with the \fBfast_flush_cache_policy\fR
/* configuration parameter:
/* Per-destination logfiles of deferred mail are maintained only for
/* eligible destinations. The policy is specified with the
/* \fBfast_flush_cache_policy\fR configuration parameter:
/* .IP \fBall\fR
/* Maintain per-destination deferred mail logfiles for all destinations.
/* .IP \fBrelay\fR
/* Maintain per-destination deferred mail logfiles only for destinations
/* that this system is willing to relay mail to ($\fBrelay_domains\fR).
/* Maintain per-destination logfiles for all destinations.
/* .IP "\fBrelay\fR (default policy)"
/* Maintain per-destination logfiles only for destinations
/* that this system is willing to relay mail to (as controlled
/* by the \fBrelay_domains\fR configuration parameter).
/* .IP \fBnone\fR
/* Do not maintain per-destination deferred mail logfiles.
/* Do not maintain per-destination logfiles.
/* .PP
/* This server implements the following requests:
/* .IP "\fBFLUSH_REQ_ADD\fI sitename queue_id\fR"
/* Inform the cache manager that the specified message is queued for
/* the specified site. Depending on caching policy, the cache manager
/* \fIsitename\fR. Depending on caching policy, the cache manager
/* stores or ignores the information.
/* .IP "\fBFLUSH_REQ_SEND\fI sitename\fR"
/* Request delivery of all messages that are queued for the specified
/* site. Depending on cache policy, this triggers delivery of specific
/* messages or of all queued mail. The per-destination logfile is
/* discarded.
/* .IP "\fBTRIGGER_REQ_WAKEUP\fR (wakeup signal from master)"
/* .IP "\fBFLUSH_REQ_PURGE\fR"
/* Delete empty per-destination logfiles that haven't been updated in
/* $\fBfast_flush_purge_delay\fR seconds.
/* Request delivery of mail that is queued for \fIsitename\fR.
/* If the destination is eligible for a fast flush logfile,
/* this request triggers delivery of specific messages; the
/* per-destination logfile is truncated to zero length; if mail
/* is undeliverable, it will be logged to the per-destination
/* logfile.
/* .sp
/* If the destination is not eligible for a fast flush logfile,
/* this request triggers delivery of all queued mail.
/* .IP \fBTRIGGER_REQ_WAKEUP\fR
/* This wakeup request from the master is an alternative way to
/* request \fBFLUSH_REQ_REFRESH\fR.
/* .IP "\fBFLUSH_REQ_REFRESH\fR (completes in the background)"
/* Refresh non-empty per-destination logfiles that were not read in
/* $\fBfast_flush_refresh_delay\fR seconds. This is done by pretending
/* that send requests were received for the corresponding sites.
/* $\fBfast_flush_refresh_delay\fR hours, by simulating
/* send requests (see above) for the corresponding destinations.
/* .sp
/* Delete empty per-destination logfiles that were not updated in
/* \fBfast_flush_purge_delay\fR days.
/* .IP "\fBFLUSH_REQ_PURGE\fR (completes in the background)"
/* Refresh all non-empty per-destination logfiles, by simulating
/* send requests (see above) for the corresponding destinations.
/* This can be incredibly expensive when caching is enabled for
/* all deferred mail, and is not recommended.
/* .sp
/* Delete empty per-destination logfiles that were not updated in
/* \fBfast_flush_purge_delay\fR days.
/* .PP
/* Fast flush logfiles are truncated only after a \fBFLUSH_REQ_SEND\fR
/* request, not when mail is actually delivered, and therefore can
/* accumulate outdated or redundant data. In order to maintain sanity,
/* \fBFLUSH_REQ_PURGE\fR should be requested at regular imtervals.
/* .sp
/* After an initial sanity check of request parameters, this request
/* proceeds in the background.
/* .PP
/* The response to the client is one of:
/* \fBFLUSH_REQ_REFRESH\fR must be executed periodically.
/*
/* The server response is one of:
/* .IP \fBFLUSH_STAT_OK\fR
/* The request completed normally.
/* .IP \fBFLUSH_STAT_BAD\fR
@ -75,7 +89,7 @@
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
/* In reality, this server schedules delivery of all recipients
/* of deferred messages. This limitation is due to the fact that
/* of a deferred message. This limitation is due to the fact that
/* one queue runner has to handle mail for multiple destinations.
/* FILES
/* /var/spool/postfix/flush, location of "fast flush" logfiles.
@ -90,11 +104,11 @@
/* \fBrelay\fR (relay destinations) or \fBnone\fR.
/* .IP \fBfast_flush_refresh_delay\fR
/* Refresh a non-empty "fast flush" logfile that was not read in
/* this amount of time, by simulating a send request for the
/* corresponding destination.
/* this amount of time (default time unit: hours), by simulating
/* a send request for the corresponding destination.
/* .IP \fBfast_flush_purge_delay\fR
/* Remove an empty "fast flush" logfile that was not updated in
/* this amount of time.
/* this amount of time (default time unit: days).
/* SEE ALSO
/* smtpd(8) Postfix SMTP server
/* qmgr(8) Postfix queue manager
@ -316,11 +330,20 @@ static int flush_send_service(const char *site)
/*
* This is the part that dominates running time: schedule the listed
* queue files for delivery by updating their file time stamps. This
* should take no more than a couple seconds under normal conditions.
* Filter out duplicate names to avoid hammering the file system, with
* queue files for delivery by updating their file time stamps and by
* moving them from the deferred queue to the incoming queue. This should
* take no more than a couple seconds under normal conditions. Filter out
* duplicate queue file names to avoid hammering the file system, with
* some finite limit on the amount of memory that we are willing to
* sacrifice. Graceful degradation.
* sacrifice for duplicate filtering. Graceful degradation.
*
* By moving selected queue files from the deferred queue to the incoming
* queue we optimize for the case where most deferred mail is for other
* sites. If that assumption does not hold, i.e. all deferred mail is for
* the same site, then doing a "fast flush" will cost more disk I/O than
* a "slow flush" that delivers the entire deferred queue. This penalty
* is only temporary - it will go away after we unite the active queue
* and the incoming queue.
*/
queue_id = vstring_alloc(10);
queue_file = vstring_alloc(10);
@ -385,11 +408,11 @@ static int flush_send_service(const char *site)
return (FLUSH_STAT_OK);
}
/* flush_purge_service - housekeeping */
/* flush_refresh_service - refresh logfiles beyond some age */
static int flush_purge_service(void)
static int flush_refresh_service(int max_age)
{
char *myname = "flush_purge_service";
char *myname = "flush_refresh_service";
SCAN_DIR *scan;
char *site;
struct stat st;
@ -397,11 +420,15 @@ static int flush_purge_service(void)
scan = scan_dir_open(MAIL_QUEUE_FLUSH);
while ((site = mail_scan_dir_next(scan)) != 0) {
if (!mail_queue_id_ok(site))
continue; /* XXX grumble. */
mail_queue_path(path, MAIL_QUEUE_FLUSH, site);
if (valid_hostname(site) == 0) {
msg_warn("%s: bad fast flush logfile name: %s", myname, site);
if (flush_policy_ok(site) == 0) {
if (unlink(STR(path)) < 0)
msg_warn("remove %s: %m", STR(path));
else if (msg_verbose)
msg_info("%s: spurious fast flush logfile name: %s",
myname, site);
continue;
}
if (stat(STR(path), &st) < 0) {
@ -420,14 +447,14 @@ static int flush_purge_service(void)
myname, STR(path), var_fflush_purge / 86400);
} else if (msg_verbose)
msg_info("%s: skip site %s - empty log", myname, site);
} else if (st.st_atime + var_fflush_refresh < event_time()) {
} else if (st.st_atime + max_age < event_time()) {
if (msg_verbose)
msg_info("%s: flush site %s", myname, site);
flush_send_service(site);
} else {
if (msg_verbose)
msg_info("%s: skip site %s, unread for <%d hours(s) ",
myname, site, var_fflush_refresh / 3600);
myname, site, max_age / 3600);
}
}
scan_dir_close(scan);
@ -448,7 +475,7 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
TRIGGER_REQ_WAKEUP,
0,
};
int status = FLUSH_STAT_OK;
int status = FLUSH_STAT_BAD;
/*
* Sanity check. This service takes no command-line arguments.
@ -471,23 +498,29 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
if (STREQ(STR(request), FLUSH_REQ_ADD)) {
site = vstring_alloc(10);
queue_id = vstring_alloc(10);
if (mail_scan(client_stream, "%s %s", site, queue_id) == 2
if (mail_command_read(client_stream, "%s %s", site, queue_id) == 2
&& valid_hostname(STR(site))
&& mail_queue_id_ok(STR(queue_id))) {
&& mail_queue_id_ok(STR(queue_id)))
status = flush_add_service(STR(site), STR(queue_id));
}
mail_print(client_stream, "%d", status);
} else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
site = vstring_alloc(10);
if (mail_scan(client_stream, "%s", site) == 1
&& valid_hostname(STR(site))) {
if (mail_command_read(client_stream, "%s", site) == 1
&& valid_hostname(STR(site)))
status = flush_send_service(STR(site));
}
} else if (STREQ(STR(request), FLUSH_REQ_PURGE)
mail_print(client_stream, "%d", status);
} else if (STREQ(STR(request), FLUSH_REQ_REFRESH)
|| STREQ(STR(request), wakeup)) {
status = flush_purge_service();
mail_print(client_stream, "%d", FLUSH_STAT_OK);
vstream_fflush(client_stream);
(void) flush_refresh_service(var_fflush_refresh);
} else if (STREQ(STR(request), FLUSH_REQ_PURGE)) {
mail_print(client_stream, "%d", FLUSH_STAT_OK);
vstream_fflush(client_stream);
(void) flush_refresh_service(0);
}
}
mail_print(client_stream, "%d", status);
} else
mail_print(client_stream, "%d", status);
vstring_free(request);
if (site)
vstring_free(site);
@ -500,8 +533,8 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
int main(int argc, char **argv)
{
static CONFIG_TIME_TABLE time_table[] = {
VAR_FFLUSH_REFRESH, DEF_FFLUSH_REFRESH, &var_fflush_refresh, 1, 0,
VAR_FFLUSH_PURGE, DEF_FFLUSH_PURGE, &var_fflush_purge, 1, 0,
VAR_FFLUSH_REFRESH, DEF_FFLUSH_REFRESH, &var_fflush_refresh, 'h', 1, 0,
VAR_FFLUSH_PURGE, DEF_FFLUSH_PURGE, &var_fflush_purge, 'd', 1, 0,
0,
};
static CONFIG_STR_TABLE str_table[] = {

View File

@ -158,7 +158,8 @@ int vdefer_append(int flags, const char *id, const char *recipient,
* bounce/defer daemon? Well, doing it here is more robust.
*/
if ((rcpt_domain = strrchr(recipient, '@')) != 0 && *++rcpt_domain != 0)
flush_add(rcpt_domain, id);
if (flush_add(rcpt_domain, id) != FLUSH_STAT_OK)
msg_warn("unable to talk to fast flush service");
return (-1);
}

View File

@ -13,6 +13,8 @@
/* int flush_send(site)
/* const char *site;
/*
/* int flush_refresh()
/*
/* int flush_purge()
/* DESCRIPTION
/* The following routines operate through the "fast flush" service.
@ -26,13 +28,18 @@
/* flush_send() requests delivery of all mail that is queued for
/* the specified destination.
/*
/* flush_refresh() requests the "fast flush" cache manager to refresh
/* cached information that was not used for some configurable amount
/* time.
/*
/* flush_purge() requests the "fast flush" cache manager to refresh
/* cached information that was not used or not updated for some
/* configurable amount of time.
/* all cached information. This is incredibly expensive, and is not
/* recommended.
/* DIAGNOSTICS
/* The result codes and their meanings are (see flush_clnt(5h)):
/* .IP MAIL_FLUSH_OK
/* The request completed successfully.
/* The request completed successfully (in case of requests that
/* complete in the background: the request was accepted by the server).
/* .IP MAIL_FLUSH_FAIL
/* The request failed (the request could not be sent to the server,
/* or the server reported failure).
@ -74,46 +81,6 @@
#define STR(x) vstring_str(x)
/* flush_clnt - generic fast flush service client */
static int flush_clnt(const char *format,...)
{
VSTREAM *flush;
int status;
va_list ap;
/*
* Connect to the fast flush service over local IPC.
*/
if ((flush = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
BLOCKING)) == 0)
return (FLUSH_STAT_FAIL);
/*
* Do not get stuck forever.
*/
vstream_control(flush,
VSTREAM_CTL_TIMEOUT, var_ipc_timeout,
VSTREAM_CTL_END);
/*
* Send a request with the site name, and receive the request acceptance
* status.
*/
va_start(ap, format);
mail_vprint(flush, format, ap);
va_end(ap);
if (mail_scan(flush, "%d", &status) != 1)
status = FLUSH_STAT_FAIL;
/*
* Clean up.
*/
vstream_fclose(flush);
return (status);
}
/* flush_purge - house keeping */
int flush_purge(void)
@ -130,7 +97,33 @@ int flush_purge(void)
if (strcmp(var_fflush_policy, FFLUSH_POLICY_NONE) == 0)
status = FLUSH_STAT_OK;
else
status = flush_clnt("%s", FLUSH_REQ_PURGE);
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
"%s", FLUSH_REQ_PURGE);
if (msg_verbose)
msg_info("%s: status %d", myname, status);
return (status);
}
/* flush_refresh - house keeping */
int flush_refresh(void)
{
char *myname = "flush_refresh";
int status;
if (msg_verbose)
msg_info("%s", myname);
/*
* Don't bother the server if the service is turned off.
*/
if (strcmp(var_fflush_policy, FFLUSH_POLICY_NONE) == 0)
status = FLUSH_STAT_OK;
else
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
"%s", FLUSH_REQ_REFRESH);
if (msg_verbose)
msg_info("%s: status %d", myname, status);
@ -154,7 +147,8 @@ int flush_send(const char *site)
if (strcmp(var_fflush_policy, FFLUSH_POLICY_NONE) == 0)
status = mail_flush_deferred();
else
status = flush_clnt("%s %s", FLUSH_REQ_SEND, site);
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
"%s %s", FLUSH_REQ_SEND, site);
if (msg_verbose)
msg_info("%s: site %s status %d", myname, site, status);
@ -178,7 +172,8 @@ int flush_add(const char *site, const char *queue_id)
if (strcmp(var_fflush_policy, FFLUSH_POLICY_NONE) == 0)
status = FLUSH_STAT_OK;
else
status = flush_clnt("%s %s %s", FLUSH_REQ_ADD, site, queue_id);
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
"%s %s %s", FLUSH_REQ_ADD, site, queue_id);
if (msg_verbose)
msg_info("%s: site %s id %s status %d", myname, site, queue_id,

View File

@ -16,6 +16,7 @@
*/
extern int flush_add(const char *, const char *);
extern int flush_send(const char *);
extern int flush_refresh(void);
extern int flush_purge(void);
/*
@ -23,7 +24,8 @@ extern int flush_purge(void);
*/
#define FLUSH_REQ_ADD "add" /* append queue ID to site log */
#define FLUSH_REQ_SEND "send" /* flush mail queued for site */
#define FLUSH_REQ_PURGE "purge" /* refresh or delete old info */
#define FLUSH_REQ_REFRESH "rfrsh" /* refresh old logfiles */
#define FLUSH_REQ_PURGE "purge" /* refresh all logfiles */
/*
* Mail flush server status codes.

View File

@ -23,7 +23,8 @@
/* .IP format
/* Format string understood by mail_print(3).
/* DIAGNOSTICS
/* The result is zero in case of success, non-zero otherwise.
/* The result is -1 if the request could not be sent, otherwise
/* the result is the status reported by the server.
/* Warnings: problems connecting to the requested service.
/* Fatal: out of memory.
/* SEE ALSO
@ -43,7 +44,7 @@
/* System library. */
#include <sys_defs.h>
#include <stdlib.h> /* 44BSD stdarg.h uses abort() */
#include <stdlib.h> /* 44BSD stdarg.h uses abort() */
#include <stdarg.h>
/* Utility library. */
@ -67,13 +68,14 @@ int mail_command_write(const char *class, const char *name,
* Talk a little protocol with the specified service.
*/
if ((stream = mail_connect(class, name, BLOCKING)) == 0)
return (1);
return (-1);
va_start(ap, fmt);
status = mail_vprint(stream, fmt, ap);
va_end(ap);
status |= mail_print(stream, "%s", MAIL_EOF);
status |= vstream_fflush(stream);
if (mail_scan(stream, "%d", &status) != 1)
if (status != 0
|| mail_print(stream, "%s", MAIL_EOF) != 0
|| vstream_fflush(stream) != 0
|| mail_scan(stream, "%d", &status) != 1)
status = -1;
(void) vstream_fclose(stream);
return (status);

View File

@ -46,11 +46,11 @@ extern const char *mail_conf_lookup_eval(const char *);
extern char *get_mail_conf_str(const char *, const char *, int, int);
extern int get_mail_conf_int(const char *, int, int, int);
extern int get_mail_conf_bool(const char *, int);
extern int get_mail_conf_time(const char *, const char *, int, int);
extern int get_mail_conf_time(const char *, const char *, int, int, int);
extern char *get_mail_conf_raw(const char *, const char *, int, int);
extern int get_mail_conf_int2(const char *, const char *, int, int, int);
extern int get_mail_conf_time2(const char *, const char *, const char *, int, int);
extern int get_mail_conf_time2(const char *, const char *, const char *, int, int, int);
/*
* Lookup with function-call defaults.
@ -58,7 +58,7 @@ extern int get_mail_conf_time2(const char *, const char *, const char *, int, in
extern char *get_mail_conf_str_fn(const char *, const char *(*) (void), int, int);
extern int get_mail_conf_int_fn(const char *, int (*) (void), int, int);
extern int get_mail_conf_bool_fn(const char *, int (*) (void));
extern int get_mail_conf_time_fn(const char *, const char *(*) (void), int, int);
extern int get_mail_conf_time_fn(const char *, const char *(*) (void), int, int, int);
extern char *get_mail_conf_raw_fn(const char *, const char *(*) (void), int, int);
/*
@ -99,6 +99,7 @@ typedef struct {
const char *name; /* config variable name */
const char *defval; /* default value */
int *target; /* pointer to global variable */
int def_unit; /* default unit: s|m|h|d|w */
int min; /* lower bound or zero */
int max; /* upper bound or zero */
} CONFIG_TIME_TABLE;
@ -139,6 +140,7 @@ typedef struct {
const char *name; /* config variable name */
const char *(*defval) (void); /* default value provider */
int *target; /* pointer to global variable */
int def_unit; /* default unit: s|m|h|d|w */
int min; /* lower bound or zero */
int max; /* upper bound or zero */
} CONFIG_TIME_FN_TABLE;

View File

@ -6,15 +6,17 @@
/* SYNOPSIS
/* #include <mail_conf.h>
/*
/* int get_mail_conf_time(name, defval, min, max);
/* int get_mail_conf_time(name, defval, def_unit, min, max);
/* const char *name;
/* const char *defval;
/* int def_unit;
/* int min;
/* int max;
/*
/* int get_mail_conf_time_fn(name, defval, min, max);
/* int get_mail_conf_time_fn(name, defval, def_unit, min, max);
/* const char *name;
/* const char *(*defval)();
/* int def_unit;
/* int min;
/* int max;
/*
@ -28,22 +30,23 @@
/* void get_mail_conf_time_fn_table(table)
/* CONFIG_INT_TABLE *table;
/* AUXILIARY FUNCTIONS
/* int get_mail_conf_time2(name1, name2, defval, min, max);
/* int get_mail_conf_time2(name1, name2, defval, def_unit, min, max);
/* const char *name1;
/* const char *name2;
/* const char *defval;
/* int def_unit;
/* int min;
/* int max;
/* DESCRIPTION
/* This module implements configuration parameter support
/* for time interval values. By default, times are specified
/* in units of seconds, but the conversion routines understand
/* for time interval values. The conversion routines understand
/* one-letter suffixes to specify an explicit time unit: s
/* (seconds), m (minutes), h (hours), d (days) or w (weeks).
/*
/* get_mail_conf_time() looks up the named entry in the global
/* configuration dictionary. The default value is returned
/* when no value was found.
/* when no value was found. \fIdef_unit\fR supplies the default
/* time unit for numbers numbers specified without explicit unit.
/* \fImin\fR is zero or specifies a lower limit on the integer
/* value or string length; \fImax\fR is zero or specifies an
/* upper limit on the integer value or string length.
@ -102,14 +105,17 @@
/* convert_mail_conf_time - look up and convert integer parameter value */
static int convert_mail_conf_time(const char *name, int *intval)
static int convert_mail_conf_time(const char *name, int *intval, int def_unit)
{
const char *strval;
char unit;
char junk;
if ((strval = mail_conf_lookup_eval(name)) != 0) {
if (sscanf(strval, "%d%c%c", intval, &unit, &junk) == 2) {
switch (sscanf(strval, "%d%c%c", intval, &unit, &junk)) {
case 1:
unit = def_unit;
case 2:
switch (unit) {
case 'w':
*intval *= WEEK;
@ -125,14 +131,9 @@ static int convert_mail_conf_time(const char *name, int *intval)
return (1);
case 's':
return (1);
break;
default:
msg_fatal("bad time unit: %s", strval);
}
}
if (sscanf(strval, "%d%c", intval, &junk) != 1)
msg_fatal("bad numerical configuration: %s = %s", name, strval);
return (1);
msg_fatal("bad time configuration: %s = %s", name, strval);
}
return (0);
}
@ -149,13 +150,13 @@ static void check_mail_conf_time(const char *name, int intval, int min, int max)
/* get_mail_conf_time - evaluate integer-valued configuration variable */
int get_mail_conf_time(const char *name, const char *defval, int min, int max)
int get_mail_conf_time(const char *name, const char *defval, int def_unit, int min, int max)
{
int intval;
if (convert_mail_conf_time(name, &intval) == 0)
if (convert_mail_conf_time(name, &intval, def_unit) == 0)
set_mail_conf_time(name, defval);
if (convert_mail_conf_time(name, &intval) == 0)
if (convert_mail_conf_time(name, &intval, def_unit) == 0)
msg_panic("get_mail_conf_time: parameter not found: %s", name);
check_mail_conf_time(name, intval, min, max);
return (intval);
@ -164,15 +165,15 @@ int get_mail_conf_time(const char *name, const char *defval, int min, int ma
/* get_mail_conf_time2 - evaluate integer-valued configuration variable */
int get_mail_conf_time2(const char *name1, const char *name2,
const char *defval, int min, int max)
const char *defval, int def_unit, int min, int max)
{
int intval;
char *name;
name = concatenate(name1, name2, (char *) 0);
if (convert_mail_conf_time(name, &intval) == 0)
if (convert_mail_conf_time(name, &intval, def_unit) == 0)
set_mail_conf_time(name, defval);
if (convert_mail_conf_time(name, &intval) == 0)
if (convert_mail_conf_time(name, &intval, def_unit) == 0)
msg_panic("get_mail_conf_time2: parameter not found: %s", name);
check_mail_conf_time(name, intval, min, max);
myfree(name);
@ -184,13 +185,13 @@ int get_mail_conf_time2(const char *name1, const char *name2,
typedef const char *(*stupid_indent_time) (void);
int get_mail_conf_time_fn(const char *name, stupid_indent_time defval,
int min, int max)
int def_unit, int min, int max)
{
int intval;
if (convert_mail_conf_time(name, &intval) == 0)
if (convert_mail_conf_time(name, &intval, def_unit) == 0)
set_mail_conf_time(name, defval());
if (convert_mail_conf_time(name, &intval) == 0)
if (convert_mail_conf_time(name, &intval, def_unit) == 0)
msg_panic("get_mail_conf_time_fn: parameter not found: %s", name);
check_mail_conf_time(name, intval, min, max);
return (intval);
@ -209,7 +210,7 @@ void get_mail_conf_time_table(CONFIG_TIME_TABLE *table)
{
while (table->name) {
table->target[0] = get_mail_conf_time(table->name, table->defval,
table->min, table->max);
table->def_unit, table->min, table->max);
table++;
}
}
@ -220,7 +221,7 @@ void get_mail_conf_time_fn_table(CONFIG_TIME_FN_TABLE *table)
{
while (table->name) {
table->target[0] = get_mail_conf_time_fn(table->name, table->defval,
table->min, table->max);
table->def_unit, table->min, table->max);
table++;
}
}
@ -239,16 +240,31 @@ int main(int unused_argc, char **unused_argv)
static int hours;
static int days;
static int weeks;
static CONFIG_TIME_TABLE time_table[] = {
"seconds", "10s", &seconds, 0, 0,
"minutes", "10m", &minutes, 0, 0,
"hours", "10h", &hours, 0, 0,
"days", "10d", &days, 0, 0,
"weeks", "10w", &weeks, 0, 0,
static CONFIG_TIME_TABLE time_table1[] = {
"seconds", "10s", &seconds, 's', 0, 0,
"minutes", "10m", &minutes, 'm', 0, 0,
"hours", "10h", &hours, 'h', 0, 0,
"days", "10d", &days, 'd', 0, 0,
"weeks", "10w", &weeks, 'w', 0, 0,
0,
};
static CONFIG_TIME_TABLE time_table2[] = {
"seconds", "10", &seconds, 's', 0, 0,
"minutes", "10", &minutes, 'm', 0, 0,
"hours", "10", &hours, 'h', 0, 0,
"days", "10", &days, 'd', 0, 0,
"weeks", "10", &weeks, 'w', 0, 0,
0,
};
get_mail_conf_time_table(time_table);
get_mail_conf_time_table(time_table1);
vstream_printf("seconds = %d\n", seconds);
vstream_printf("minutes = %d\n", minutes);
vstream_printf("hours = %d\n", hours);
vstream_printf("days = %d\n", days);
vstream_printf("weeks = %d\n", weeks);
get_mail_conf_time_table(time_table2);
vstream_printf("seconds = %d\n", seconds);
vstream_printf("minutes = %d\n", minutes);
vstream_printf("hours = %d\n", hours);

View File

@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-20001003"
#define DEF_MAIL_VERSION "Snapshot-20001004"
extern char *var_mail_version;
/* LICENSE

View File

@ -263,7 +263,6 @@ qmgr_scan.o: ../../include/msg.h
qmgr_scan.o: ../../include/mymalloc.h
qmgr_scan.o: ../../include/scan_dir.h
qmgr_scan.o: ../../include/mail_scan_dir.h
qmgr_scan.o: ../../include/flush_clnt.h
qmgr_scan.o: qmgr.h
qmgr_scan.o: ../../include/vstream.h
qmgr_scan.o: ../../include/vbuf.h

View File

@ -67,7 +67,6 @@
/* Global library. */
#include <mail_scan_dir.h>
#include <flush_clnt.h>
/* Application-specific. */
@ -101,14 +100,6 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
if (scan_info->nflags & QMGR_FLUSH_DEAD)
qmgr_enable_all();
/*
* Optionally inform the fast flush cache manager that we're attempting
* to deliver all queued mail.
*/
if ((scan_info->nflags & QMGR_FLUSH_DEAD)
&& (scan_info->nflags & QMGR_SCAN_ALL))
flush_purge();
/*
* Start or restart the scan.
*/

View File

@ -235,7 +235,6 @@ qmgr_scan.o: ../../include/msg.h
qmgr_scan.o: ../../include/mymalloc.h
qmgr_scan.o: ../../include/scan_dir.h
qmgr_scan.o: ../../include/mail_scan_dir.h
qmgr_scan.o: ../../include/flush_clnt.h
qmgr_scan.o: qmgr.h
qmgr_scan.o: ../../include/vstream.h
qmgr_scan.o: ../../include/vbuf.h

View File

@ -67,7 +67,6 @@
/* Global library. */
#include <mail_scan_dir.h>
#include <flush_clnt.h>
/* Application-specific. */
@ -101,14 +100,6 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
if (scan_info->nflags & QMGR_FLUSH_DEAD)
qmgr_enable_all();
/*
* Optionally inform the fast flush cache manager that we're attempting
* to deliver all queued mail.
*/
if ((scan_info->nflags & QMGR_FLUSH_DEAD)
&& (scan_info->nflags & QMGR_SCAN_ALL))
flush_purge();
/*
* Start or restart the scan.
*/

View File

@ -1095,7 +1095,10 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
return (0);
case FLUSH_STAT_BAD:
msg_warn("bad ETRN %.100s... from %s", argv[1].strval, state->namaddr);
smtpd_chat_reply(state, "458 Unable to queue messages");
return (-1);
default:
msg_warn("unable to talk to fast flush service");
smtpd_chat_reply(state, "458 Unable to queue messages");
return (-1);
}