]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20010720
authorWietse Venema <wietse@porcupine.org>
Fri, 20 Jul 2001 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:27:22 +0000 (06:27 +0000)
24 files changed:
postfix/HISTORY
postfix/conf/main.cf
postfix/conf/sample-smtpd.cf
postfix/src/cleanup/Makefile.in
postfix/src/cleanup/cleanup.c
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/master/Makefile.in
postfix/src/master/mail_flow.c [new file with mode: 0644]
postfix/src/master/mail_flow.h [new file with mode: 0644]
postfix/src/master/mail_server.h
postfix/src/master/master.c
postfix/src/master/master.h
postfix/src/master/master_flow.c [new file with mode: 0644]
postfix/src/master/master_proto.h
postfix/src/master/master_spawn.c
postfix/src/master/multi_server.c
postfix/src/master/single_server.c
postfix/src/master/trigger_server.c
postfix/src/nqmgr/qmgr.c
postfix/src/postalias/postalias.c
postfix/src/postmap/postmap.c
postfix/src/qmgr/qmgr.c

index 5fce918f452434e4b9e0a79f4ec0ffcc33f1e2a7..a000faf3e5b101f35d0d67dd99843bebc7acfb4a 100644 (file)
@@ -5347,3 +5347,16 @@ Apologies for any names omitted.
        Logging: the queue manager now logs a "status=expired"
        record when it returns a message that is too old.  Files:
        *qmgr/qmgr_active.c.
+
+20010719
+
+       Feature: stiffer coupling between mail arrival rates and
+       mail delivery rates, using a trivial token-based scheme
+       where qmgr provides a token when it retrieves mail from
+       the incoming queue, and where the cleanup daemon wants a
+       token after enqueueing mail. If no token is available the
+       cleanup server pauses briefly and proceeds anyway. This
+       allows input rates to gradually exceed output rates.  After
+       sustained exposure to high input loads Postfix reverts to
+       the old situation where it sacrifices output rates in favor
+       of receiving mail.
index 1612b1d45463b8873979af14eb6539b5179be1cd..8807373a4188f6bbaf4096f4dda9a6a8d58aba4a 100644 (file)
@@ -163,7 +163,8 @@ mail_owner = postfix
 # address.
 #
 # You can also specify the absolute pathname of a pattern file instead
-# of listing the patterns here.
+# of listing the patterns here. Specify type:name for table-based lookups
+# (the value on the table right-hand side is not used).
 #
 #mynetworks = 168.100.189.0/28, 127.0.0.0/8
 #mynetworks = $config_directory/mynetworks
index c0ff345f407dc371f03e972584073ba609a8eb31..1429a5e742334f64f98c442555191a8f2b6e0cf9 100644 (file)
@@ -135,7 +135,8 @@ mynetworks_style = subnet
 # address.
 #
 # You can also specify the absolute pathname of a pattern file instead
-# of listing the patterns here.
+# of listing the patterns here. Specify type:name for table-based lookups
+# (the value on the table right-hand side is not used).
 #
 #mynetworks = 168.100.189.0/28, 127.0.0.0/8
 #mynetworks = $config_directory/mynetworks
index 168040d94dc997e2c3227eb070802f17f1d6d3ee..75d74b513b34a76f00ef2153a157ffcd059a56c7 100644 (file)
@@ -75,6 +75,7 @@ cleanup.o: ../../include/iostuff.h
 cleanup.o: ../../include/mail_params.h
 cleanup.o: ../../include/record.h
 cleanup.o: ../../include/rec_type.h
+cleanup.o: ../../include/mail_flow.h
 cleanup.o: ../../include/mail_server.h
 cleanup.o: cleanup.h
 cleanup.o: ../../include/maps.h
index 70476aa2ec28d71309bda8fe32822743cc88a559..9891a03cca7b8b27a7a4b8055a1df834294c37f3 100644 (file)
@@ -271,5 +271,6 @@ int     main(int argc, char **argv)
                       MAIL_SERVER_PRE_INIT, cleanup_pre_jail,
                       MAIL_SERVER_POST_INIT, cleanup_post_jail,
                       MAIL_SERVER_PRE_ACCEPT, pre_accept,
+                      MAIL_SERVER_FLOW_CTL,
                       0);
 }
index 6fc2db082ccd8e4eee3be079cf4c2c3004396997..ec3d780648d76fe339ab580082eab632e2cfcb63 100644 (file)
@@ -69,6 +69,7 @@
 /*     char    *var_export_environ;
 /*     char    *var_debug_peer_list;
 /*     int     var_debug_peer_level;
+/*     int     var_glob_flow_ctl;
 /*
 /*     void    mail_params_init()
 /* DESCRIPTION
@@ -185,6 +186,7 @@ char   *var_def_transport;
 char   *var_mynetworks_style;
 char   *var_verp_delims;
 char   *var_verp_filter;
+int     var_glob_flow_ctl;
 
 char   *var_import_environ;
 char   *var_export_environ;
@@ -325,6 +327,7 @@ void    mail_params_init()
        VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0,
        VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0,
        VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
+       VAR_GLOB_FLOW_CTL, DEF_GLOB_FLOW_CTL, &var_glob_flow_ctl, 0, 0,
        0,
     };
     static CONFIG_TIME_TABLE time_defaults[] = {
index 30b163489925af2832a49c3e8da746b194389cf2..7c6744d2de2bccc15bc6c484d2487f05afc2ad0d 100644 (file)
@@ -1283,6 +1283,17 @@ extern char *var_verp_delims;
 #define DEF_VERP_FILTER                        "-=+"
 extern char *var_verp_filter;
 
+ /*
+  * Global flow control. This allows for a stiffer coupling between receiving
+  * programs and the queue manager, so that receiving processes cannot easily
+  * overwhelm the file system. The coupling is not so tight that Postfix
+  * stops receiving mail althogether. It just slows down a bit so that
+  * sending processes get a chance to read from the disk.
+  */
+#define VAR_GLOB_FLOW_CTL                      "global_mail_flow_control"
+#define DEF_GLOB_FLOW_CTL                      0
+extern int var_glob_flow_ctl;
+
 /* LICENSE
 /* .ad
 /* .fi
index e53ebfb00128cd94d8ac243210c7a22031a8d03e..b2a510397ab0fb38f2703a431cdb3eac673859e0 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20010714"
+#define DEF_MAIL_VERSION       "Snapshot-20010720"
 extern char *var_mail_version;
 
 /* LICENSE
index d33912054c0c1d99ddf7aa35666f6bc974214c36..59f1e3cc866562e06f935709e2980f2378a580ed 100644 (file)
@@ -2,12 +2,13 @@ SHELL = /bin/sh
 SRCS   = master.c master_conf.c master_ent.c master_sig.c master_avail.c \
        master_spawn.c master_service.c master_status.o master_listen.c \
        master_proto.c single_server.c multi_server.c master_vars.c \
-       master_wakeup.c
+       master_wakeup.c master_flow.c mail_flow.c
 OBJS   = master.o master_conf.o master_ent.o master_sig.o master_avail.o \
        master_spawn.o master_service.o master_status.o master_listen.o \
-       master_vars.o master_wakeup.o
-LIB_OBJ        = single_server.o multi_server.o trigger_server.o master_proto.o
-HDRS   = mail_server.h master_proto.h
+       master_vars.o master_wakeup.o master_flow.o
+LIB_OBJ        = single_server.o multi_server.o trigger_server.o master_proto.o \
+       mail_flow.o
+HDRS   = mail_server.h master_proto.h mail_flow.h
 INT_HDR        = master.h
 WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
        -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
@@ -78,6 +79,11 @@ depend: $(MAKES)
        @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
+mail_flow.o: mail_flow.c
+mail_flow.o: ../../include/sys_defs.h
+mail_flow.o: ../../include/msg.h
+mail_flow.o: mail_flow.h
+mail_flow.o: master_proto.h
 master.o: master.c
 master.o: ../../include/sys_defs.h
 master.o: ../../include/events.h
@@ -129,6 +135,12 @@ master_ent.o: ../../include/mail_params.h
 master_ent.o: ../../include/own_inet_addr.h
 master_ent.o: master_proto.h
 master_ent.o: master.h
+master_flow.o: master_flow.c
+master_flow.o: ../../include/sys_defs.h
+master_flow.o: ../../include/msg.h
+master_flow.o: ../../include/iostuff.h
+master_flow.o: master.h
+master_flow.o: master_proto.h
 master_listen.o: master_listen.c
 master_listen.o: ../../include/sys_defs.h
 master_listen.o: ../../include/msg.h
diff --git a/postfix/src/master/mail_flow.c b/postfix/src/master/mail_flow.c
new file mode 100644 (file)
index 0000000..5fc1292
--- /dev/null
@@ -0,0 +1,112 @@
+/*++
+/* NAME
+/*     mail_flow 3
+/* SUMMARY
+/*     global mail flow control
+/* SYNOPSIS
+/*     #include <mail_flow.h>
+/*
+/*     int     mail_flow_get(count)
+/*     int     count;
+/*
+/*     void    mail_flow_put(count)
+/*     int     count;
+/* DESCRIPTION
+/*     This module implements a simple flow control mechanism that
+/*     is based on tokens that are consumed by mail receiving processes
+/*     and that are produced by mail sending processes.
+/*
+/*     mail_flow_get() attempts to read specified number of tokens. The
+/*     result is > 0 for success, < 0 for failure. In the latter case,
+/*     the process is expected to slow down a little.
+/*
+/*     mail_flow_put() produces the specified number of tokens. The
+/*     token producing process is expected to produce new tokens
+/*     whenever it falls idle and no more tokens are available.
+/* BUGS
+/*     The producer needs to wake up periodically to ensure that
+/*     tokens are not lost due to leakage.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* Global library. */
+
+#include <mail_flow.h>
+
+/* Master library. */
+
+#include <master_proto.h>
+
+#define BUFFER_SIZE    1024
+
+/* mail_flow_get - read N tokens */
+
+int     mail_flow_get(int len)
+{
+    char   *myname = "mail_flow_get";
+    char    buf[BUFFER_SIZE];
+    int     count;
+    int     n = 0;
+
+    /*
+     * Sanity check.
+     */
+    if (len <= 0)
+       msg_panic("%s: bad length %d", myname, len);
+
+    /*
+     * Read and discard N bytes.
+     */
+    for (count = len; count > 0; count -= n)
+       if ((n = read(MASTER_FLOW_READ, buf, count > BUFFER_SIZE ?
+                     BUFFER_SIZE : count)) < 0)
+           return (-1);
+    if (msg_verbose)
+       msg_info("%s: %d %d", myname, len, len - count);
+    return (len - count);
+}
+
+/* mail_flow_put - put N tokens */
+
+int     mail_flow_put(int len)
+{
+    char   *myname = "mail_flow_put";
+    char    buf[BUFFER_SIZE];
+    int     count;
+    int     n = 0;
+
+    /*
+     * Sanity check.
+     */
+    if (len <= 0)
+       msg_panic("%s: bad length %d", myname, len);
+
+    /*
+     * Read and discard N bytes.
+     */
+    for (count = len; count > 0; count -= n)
+       if ((n = read(MASTER_FLOW_READ, buf, count > BUFFER_SIZE ?
+                     BUFFER_SIZE : count)) < 0)
+           return (-1);
+    if (msg_verbose)
+       msg_info("%s: %d %d", myname, len, len - count);
+    return (len - count);
+}
diff --git a/postfix/src/master/mail_flow.h b/postfix/src/master/mail_flow.h
new file mode 100644 (file)
index 0000000..c146d83
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _MAIL_FLOW_H_INCLUDED_
+#define _MAIL_FLOW_H_INCLUDED_
+
+/*++
+/* NAME
+/*     mail_flow 3h
+/* SUMMARY
+/*     global mail flow control
+/* SYNOPSIS
+/*     #include <mail_flow.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Functional interface.
+  */
+extern int mail_flow_get(int);
+extern int mail_flow_put(int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
index d03313b1ead7106364a2daeb1f249bdbc5bcb2e0..6c55603c1546603f565df540ce94d22f1c74c795 100644 (file)
@@ -28,6 +28,8 @@
 #define MAIL_SERVER_EXIT       13
 #define MAIL_SERVER_PRE_ACCEPT 14
 
+#define MAIL_SERVER_FLOW_CTL   20
+
 typedef void (*MAIL_SERVER_INIT_FN) (char *, char **);
 typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **);
 typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **);
index 4299424f1cec6717ec756389520f68f372931036..ad5af3b1721862f70526035e138ffe2155e1a253 100644 (file)
@@ -256,8 +256,11 @@ int     main(int argc, char **argv)
      * when a service listens on many ports. In order to do this right we
      * must change the master-child interface so that descriptors do not need
      * to have fixed numbers.
+     * 
+     * In a child we need two descriptors for the flow control pipe, one for
+     * child->master status updates and at least one for listening.
      */
-    for (n = 0; n < 3; n++) {
+    for (n = 0; n < 5; n++) {
        if (close_on_exec(dup(0), CLOSE_ON_EXEC) < 0)
            msg_fatal("dup(0): %m");
     }
@@ -349,6 +352,7 @@ int     main(int argc, char **argv)
      */
     master_config();
     master_sigsetup();
+    master_flow_init();
     msg_info("daemon started");
 
     /*
index abdfecc720f8005be01afb6a38fde4f4f057d13a..d2e4728615eefb38a3ebc94ede56ec9605d3cb84 100644 (file)
@@ -162,6 +162,12 @@ extern void master_spawn(MASTER_SERV *);
 extern void master_reap_child(void);
 extern void master_delete_children(MASTER_SERV *);
 
+ /*
+  * master_flow.c
+  */
+void    master_flow_init(void);
+int     master_flow_pipe[2];
+
 /* DIAGNOSTICS
 /* BUGS
 /* SEE ALSO
diff --git a/postfix/src/master/master_flow.c b/postfix/src/master/master_flow.c
new file mode 100644 (file)
index 0000000..cc13f8c
--- /dev/null
@@ -0,0 +1,30 @@
+/* System library. */
+
+#include <sys_defs.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <iostuff.h>
+
+/* Application-specific. */
+
+#include <master.h>
+#include <master_proto.h>
+
+int     master_flow_pipe[2];
+
+/* master_flow_init - initialize the flow control channel */
+
+void    master_flow_init(void)
+{
+    char   *myname = "master_flow_init";
+
+    if (pipe(master_flow_pipe) < 0)
+       msg_fatal("%s: pipe: %m", myname);
+
+    non_blocking(master_flow_pipe[0], NON_BLOCKING);
+    non_blocking(master_flow_pipe[1], NON_BLOCKING);
+}
index 2929ed46375005955a430f2227667c978ff0c439..36c30f8d5bbcf68160320a16affb466787ed7221 100644 (file)
@@ -31,6 +31,14 @@ typedef struct MASTER_STATUS {
 
 extern int master_notify(int, int);    /* encapsulate status msg */
 
+ /*
+  * File descriptors inherited from the master process. The flow control pipe
+  * is read by receive processes and is written to by send processes. If
+  * receive processes get too far ahead they will pause for a brief moment.
+  */
+#define MASTER_FLOW_READ       3
+#define MASTER_FLOW_WRITE      4
+
  /*
   * File descriptors inherited from the master process. All processes that
   * provide a given service share the same status file descriptor, and listen
@@ -41,8 +49,8 @@ extern int master_notify(int, int);   /* encapsulate status msg */
   * actually the lowest-numbered descriptor of a sequence of descriptors to
   * listen on.
   */
-#define MASTER_STATUS_FD       3       /* shared channel to parent */
-#define MASTER_LISTEN_FD       4       /* accept connections here */
+#define MASTER_STATUS_FD       5       /* shared channel to parent */
+#define MASTER_LISTEN_FD       6       /* accept connections here */
 
 /* LICENSE
 /* .ad
index 75dcfafbeec1f6a9726444d57d6f9b7e2020e0bd..2eaf7bf96b399bffb898217211f39192f129a13a 100644 (file)
@@ -175,6 +175,23 @@ void    master_spawn(MASTER_SERV *serv)
     case 0:
        msg_cleanup((void (*) (void)) 0);       /* disable exit handler */
        closelog();                             /* avoid filedes leak */
+
+       if (master_flow_pipe[0] <= MASTER_FLOW_READ)
+           msg_fatal("%s: flow pipe read descriptor <= %d",
+                     myname, MASTER_FLOW_READ);
+       if (DUP2(master_flow_pipe[0], MASTER_FLOW_READ) < 0)
+           msg_fatal("%s: dup2: %m", myname);
+       if (close(master_flow_pipe[0]) < 0)
+           msg_fatal("close %d: %m", master_flow_pipe[0]);
+
+       if (master_flow_pipe[1] <= MASTER_FLOW_WRITE)
+           msg_fatal("%s: flow pipe read descriptor <= %d",
+                     myname, MASTER_FLOW_WRITE);
+       if (DUP2(master_flow_pipe[1], MASTER_FLOW_WRITE) < 0)
+           msg_fatal("%s: dup2: %m", myname);
+       if (close(master_flow_pipe[1]) < 0)
+           msg_fatal("close %d: %m", master_flow_pipe[1]);
+
        close(serv->status_fd[0]);              /* status channel */
        if (serv->status_fd[1] <= MASTER_STATUS_FD)
            msg_fatal("%s: status file descriptor collision", myname);
index c9df296f4f957b5b361049a0c45479ef9397e3ce..e845ca5ff45ab095732ef8a841c5750cbdc991e8 100644 (file)
@@ -611,6 +611,8 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
     }
     event_enable_read(MASTER_STATUS_FD, multi_server_abort, (char *) 0);
     close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
+    close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC);
+    close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC);
     watchdog = watchdog_create(var_daemon_timeout, (WATCHDOG_FN) 0, (char *) 0);
 
     /*
index 9c6920a7d73320f50a5b9d9da4a87ac0e4c5f138..58cc6f7ce5b7e84e15a553ced66cabb3c277b940 100644 (file)
 #include <mail_conf.h>
 #include <timed_ipc.h>
 #include <resolve_local.h>
+#include <mail_flow.h>
 
 /* Process manager. */
 
@@ -183,6 +184,7 @@ static void (*single_server_accept) (int, char *);
 static void (*single_server_onexit) (char *, char **);
 static void (*single_server_pre_accept) (char *, char **);
 static VSTREAM *single_server_lock;
+static int single_server_flow_ctl;
 
 /* single_server_exit - normal termination */
 
@@ -238,6 +240,9 @@ static void single_server_wakeup(int fd)
     if (msg_verbose)
        msg_info("connection closed");
     use_count++;
+    if (single_server_flow_ctl)
+       if (mail_flow_get(1) < 0)
+           rand_sleep(single_server_flow_ctl, 0);
     if (var_idle_limit > 0)
        event_request_timer(single_server_timeout, (char *) 0, var_idle_limit);
 }
@@ -469,6 +474,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
        case MAIL_SERVER_PRE_ACCEPT:
            single_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
            break;
+       case MAIL_SERVER_FLOW_CTL:
+           single_server_flow_ctl = var_glob_flow_ctl;
+           break;
        default:
            msg_panic("%s: unknown argument type: %d", myname, key);
        }
@@ -582,6 +590,8 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
     }
     event_enable_read(MASTER_STATUS_FD, single_server_abort, (char *) 0);
     close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
+    close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC);
+    close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC);
     watchdog = watchdog_create(var_daemon_timeout, (WATCHDOG_FN) 0, (char *) 0);
 
     /*
index 7edd05ff6d6f2bde2d46759eb667c1869a6bd454..61307e2a4d37a5932b3d4098e8652f25f7ba38e3 100644 (file)
@@ -593,6 +593,8 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
     }
     event_enable_read(MASTER_STATUS_FD, trigger_server_abort, (char *) 0);
     close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
+    close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC);
+    close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC);
     watchdog = watchdog_create(1000, (WATCHDOG_FN) 0, (char *) 0);
 
     /*
index 030c82d2de4600b2b1aec5e73cc57e144c7e0088..c8c7f8685f5e81593a65a8e033f62f5674083721 100644 (file)
 #include <mail_conf.h>
 #include <mail_params.h>
 #include <mail_proto.h>                        /* QMGR_SCAN constants */
+#include <mail_flow.h>
 
 /* Master process interface */
 
@@ -448,6 +449,17 @@ static int qmgr_loop(char *unused_name, char **unused_argv)
     if (qmgr_message_count < var_qmgr_active_limit)
        if ((df_path = qmgr_scan_next(qmgr_deferred)) != 0)
            qmgr_active_feed(qmgr_deferred, df_path);
+
+    /*
+     * Global flow control. If enabled, slow down receiving processes that
+     * get ahead of the queue manager, but don't block them completely.
+     */
+    if (var_glob_flow_ctl) {
+       if (in_path)
+           mail_flow_put(1);
+       else
+           mail_flow_get(1000);
+    }
     if (in_path || df_path)
        return (DONT_WAIT);
     return (WAIT_FOR_EVENT);
index 22125480968a0265f1d87c0b5512b4100ff66bac..c2bbbbde6e37019f0e768a5ad560941427d9881d 100644 (file)
@@ -90,9 +90,6 @@
 /*     \fBpostalias\fR terminates with zero exit status in case of success
 /*     (including successful \fBpostmap -q\fR lookup) and terminates
 /*     with non-zero exit status in case of failure.
-/* BUGS
-/*     The "delete key" support is limited to one delete operation
-/*     per command invocation.
 /* ENVIRONMENT
 /* .ad
 /* .fi
index aac5b1f695ad5885af25710bb46d716a851dcfa9..a22ea3321caea05a0e1597c3119924276e19aeed 100644 (file)
 /*     \fBpostmap\fR terminates with zero exit status in case of success
 /*     (including successful \fBpostmap -q\fR lookup) and terminates
 /*     with non-zero exit status in case of failure.
-/* BUGS
-/*     The "delete key" support is limited to one delete operation
-/*     per command invocation.
 /* ENVIRONMENT
 /* .ad
 /* .fi
index 7513aa368e9a379d4a21a25aed92f7e9d0c61eee..0ce592ece79842914eac2b6e49865fa99e9859b9 100644 (file)
 #include <mail_conf.h>
 #include <mail_params.h>
 #include <mail_proto.h>                        /* QMGR_SCAN constants */
+#include <mail_flow.h>
 
 /* Master process interface */
 
@@ -410,6 +411,17 @@ static int qmgr_loop(char *unused_name, char **unused_argv)
        && qmgr_recipient_count < var_qmgr_rcpt_limit)
        if ((df_path = qmgr_scan_next(qmgr_deferred)) != 0)
            qmgr_active_feed(qmgr_deferred, df_path);
+
+    /*
+     * Global flow control. If enabled, slow down receiving processes that
+     * get ahead of the queue manager, but don't block them completely.
+     */
+    if (var_glob_flow_ctl) {
+       if (in_path)
+           mail_flow_put(1);
+       else
+           mail_flow_get(1000);
+    }
     if (in_path || df_path)
        return (DONT_WAIT);
     return (WAIT_FOR_EVENT);