From 3cee6033bae86d254e51b583d34f6b559a6d95ea Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Thu, 18 Jul 2024 14:50:14 +0100 Subject: [PATCH] HintsDB: Support transactions with a TDB backend. --- doc/doc-txt/ChangeLog | 10 +- src/src/dbfn.c | 58 +++---- src/src/dbfunctions.h | 11 -- src/src/deliver.c | 277 ++++++++++++++++++--------------- src/src/exim_dbmbuild.c | 21 +++ src/src/exim_dbutil.c | 41 ++++- src/src/hintsdb.h | 52 +++++-- src/src/hintsdb/hints_bdb.h | 26 +++- src/src/hintsdb/hints_gdbm.h | 11 +- src/src/hintsdb/hints_ndbm.h | 11 +- src/src/hintsdb/hints_sqlite.h | 10 +- src/src/hintsdb/hints_tdb.h | 89 +++++++++-- src/src/hintsdb_structs.h | 1 + src/src/queue.c | 30 ++-- src/src/retry.c | 104 +++++++++---- test/runtest | 37 +++-- test/stderr/0275 | 6 - test/stderr/0278 | 6 - test/stderr/0357 | 10 +- test/stderr/0358 | 6 +- test/stderr/0361 | 12 -- test/stderr/0386 | 12 -- test/stderr/0388 | 101 +++++------- test/stderr/0398 | 45 +++--- test/stderr/0402 | 21 --- test/stderr/0403 | 18 --- test/stderr/0404 | 15 -- test/stderr/0408 | 6 - test/stderr/0432 | 49 +++--- test/stderr/0450 | 4 +- test/stderr/0476 | 2 +- test/stderr/0487 | 6 - test/stderr/0512 | 12 +- test/stderr/0554 | 6 +- test/stderr/0623 | 8 +- test/stderr/0628 | 6 - test/stderr/0909 | 8 +- test/stderr/2600 | 6 - test/stderr/2610 | 6 - test/stderr/2620 | 6 - test/stderr/4052 | 4 +- test/stderr/5004 | 9 -- test/stderr/5005 | 116 +++++--------- test/stderr/5006 | 6 - 44 files changed, 658 insertions(+), 643 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index fadb4995a..abf90ca1f 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -10,11 +10,11 @@ JH/01 Use fewer forks & execs for sending many messages to a single host. we can loop there. A two-phase queue run will benefit, particularly for mailinglist and smarthost cases. -JH/02 Add transaction support for hintsdbs. The sole initial provider is - sqlite, and is used for the wait-transport and retry DBs. Transactions - imply locking internal to the DB. We no longer need a separate lockfile, - can keep the DB handle open for extended periods, yet potentially benefit - from concurrency on non-conflicting record uses. +JH/02 Add transaction support for hintsdbs. The providers supported are tdb and + sqlite. Transactions are used for the wait-transport and retry DBs. + They imply locking internal to the DB. We no longer need a separate + lockfile, can keep the DB handle open for extended periods, yet + potentially benefit from concurrency on non-conflicting record uses. JH/03 With dkim_verify_minimal, avoid calling the DKIM ACL after the first good verify. diff --git a/src/src/dbfn.c b/src/src/dbfn.c index c2c92cf44..1f6989164 100644 --- a/src/src/dbfn.c +++ b/src/src/dbfn.c @@ -38,8 +38,14 @@ are separate open and close functions. However, the calling modules should arrange to hold the locks for the bare minimum of time. API: - dbfn_open - dbfn_close + exim_lockfile_needed facilities predicate + dbfn_open takes lockfile or opens transaction + dbfn_open_multi only if transactions supported; + no lock or transaction taken + dbfn_close release lockfile or transaction + dbfn_close_multi + dbfn_transaction_start only if transactions supported + dbfn_transaction_commit dbfn_read_with_length dbfn_read_enforce_length dbfn_write @@ -166,6 +172,7 @@ exists, there is no error. */ dlen = snprintf(CS dirname, sizeof(dirname), "%s/db", spool_directory); +dbblock->readonly = (flags & O_ACCMODE) == O_RDONLY; dbblock->lockfd = -1; if (!exim_lockfile_needed()) db_dir_make(panic); @@ -194,7 +201,10 @@ open call. */ snprintf(CS filename, sizeof(filename), "%.*s/%s", dlen, dirname, name); priv_drop_temp(exim_uid, exim_gid); -dbblock->dbptr = exim_dbopen(filename, dirname, flags & O_ACCMODE, EXIMDB_MODE); +dbblock->dbptr = dbblock->readonly && !exim_lockfile_needed() + ? exim_dbopen_multi(filename, dirname, flags & O_ACCMODE, EXIMDB_MODE) + : exim_dbopen(filename, dirname, flags & O_ACCMODE, EXIMDB_MODE); + if (!dbblock->dbptr && errno == ENOENT && flags & O_CREAT) { DEBUG(D_hints_lookup) @@ -220,21 +230,13 @@ if (!dbblock->dbptr) filename)); (void)close(dbblock->lockfd); dbblock->lockfd = -1; - errno = save_errno; - DEBUG(D_hints_lookup) acl_level--; - return NULL; + dbblock = NULL; } -DEBUG(D_hints_lookup) - debug_printf_indent("opened hints database %s: flags=%s%s\n", filename, - (flags & O_ACCMODE) == O_RDONLY ? "O_RDONLY" - : (flags & O_ACCMODE) == O_RDWR ? "O_RDWR" - : "??", - flags & O_CREAT ? "|O_CREAT" : ""); - /* Pass back the block containing the opened database handle and the open fd for the lock. */ +DEBUG(D_hints_lookup) acl_level--; return dbblock; } @@ -284,21 +286,11 @@ if (!dbblock->dbptr) DEBUG(D_hints_lookup) debug_printf_indent("%s\n", CS string_open_failed("DB file %s", filename)); - errno = save_errno; - DEBUG(D_hints_lookup) acl_level--; - return NULL; + dbblock = NULL; } -DEBUG(D_hints_lookup) - debug_printf_indent("opened hints database %s for transactions: NOLOCK flags=%s%s\n", - filename, - (flags & O_ACCMODE) == O_RDONLY ? "O_RDONLY" - : (flags & O_ACCMODE) == O_RDWR ? "O_RDWR" - : "??", - flags & O_CREAT ? "|O_CREAT" : ""); - /* Pass back the block containing the opened database handle */ - +DEBUG(D_hints_lookup) acl_level--; return dbblock; } @@ -307,13 +299,13 @@ BOOL dbfn_transaction_start(open_db * dbp) { DEBUG(D_hints_lookup) debug_printf_indent("dbfn_transaction_start\n"); -return exim_dbtransaction_start(dbp->dbptr); +if (!dbp->readonly) return exim_dbtransaction_start(dbp->dbptr); } void dbfn_transaction_commit(open_db * dbp) { DEBUG(D_hints_lookup) debug_printf_indent("dbfn_transaction_commit\n"); -exim_dbtransaction_commit(dbp->dbptr); +if (!dbp->readonly) exim_dbtransaction_commit(dbp->dbptr); } @@ -334,14 +326,15 @@ dbfn_close(open_db * dbp) { int * fdp = &dbp->lockfd; -exim_dbclose(dbp->dbptr); +if (dbp->readonly && !exim_lockfile_needed()) + exim_dbclose_multi(dbp->dbptr); +else + exim_dbclose(dbp->dbptr); + if (*fdp >= 0) (void)close(*fdp); DEBUG(D_hints_lookup) - { debug_printf_indent("closed hints database%s\n", *fdp < 0 ? "" : " and lockfile"); - acl_level--; - } *fdp = -1; } @@ -351,10 +344,7 @@ dbfn_close_multi(open_db * dbp) { exim_dbclose_multi(dbp->dbptr); DEBUG(D_hints_lookup) - { debug_printf_indent("closed hints database\n"); - acl_level--; - } } diff --git a/src/src/dbfunctions.h b/src/src/dbfunctions.h index 0aa3b777c..08f8c2311 100644 --- a/src/src/dbfunctions.h +++ b/src/src/dbfunctions.h @@ -28,16 +28,5 @@ void dbfn_transaction_commit(open_db *); #define dbfn_read(a, b) dbfn_read_with_length(a, b, NULL) -/* Berkeley DB uses a callback function to pass back error details. Its API -changed at release 4.3. */ - -#if defined(USE_DB) && defined(DB_VERSION_STRING) -# if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) -void dbfn_bdb_error_callback(const DB_ENV *, const char *, const char *); -# else -void dbfn_bdb_error_callback(const char *, char *); -# endif -#endif - #endif /* End of dbfunctions.h */ diff --git a/src/src/deliver.c b/src/src/deliver.c index b04fe6f12..ee7650243 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -2896,7 +2896,12 @@ while (addr_local) of these checks, rather than for all local deliveries, because some local deliveries (e.g. to pipes) can take a substantial time. */ - if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE, TRUE))) + if (continue_retry_db && continue_retry_db != (open_db *)-1) + { + DEBUG(D_hints_lookup) debug_printf("using cached retry hintsdb handle\n"); + dbm_file = continue_retry_db; + } + else if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE, TRUE))) DEBUG(D_deliver|D_retry|D_hints_lookup) debug_printf("no retry data available\n"); @@ -2905,61 +2910,66 @@ while (addr_local) while (addr2) { BOOL ok = TRUE; /* to deliver this address */ - uschar *retry_key; - - /* Set up the retry key to include the domain or not, and change its - leading character from "R" to "T". Must make a copy before doing this, - because the old key may be pointed to from a "delete" retry item after - a routing delay. */ - retry_key = string_copy( - tp->retry_use_local_part ? addr2->address_retry_key : - addr2->domain_retry_key); - *retry_key = 'T'; + if (f.queue_2stage) + { + DEBUG(D_deliver) + debug_printf_indent("no router retry check (ph1 qrun)\n"); + } + else + { + /* Set up the retry key to include the domain or not, and change its + leading character from "R" to "T". Must make a copy before doing this, + because the old key may be pointed to from a "delete" retry item after + a routing delay. */ + uschar * retry_key = string_copy(tp->retry_use_local_part + ? addr2->address_retry_key : addr2->domain_retry_key); + *retry_key = 'T'; - /* Inspect the retry data. If there is no hints file, delivery happens. */ + /* Inspect the retry data. If there is no hints file, delivery happens. */ - if (dbm_file) - { - dbdata_retry * retry_record = dbfn_read(dbm_file, retry_key); + if (dbm_file) + { + dbdata_retry * retry_record = dbfn_read(dbm_file, retry_key); - /* If there is no retry record, delivery happens. If there is, - remember it exists so it can be deleted after a successful delivery. */ + /* If there is no retry record, delivery happens. If there is, + remember it exists so it can be deleted after a successful delivery. */ - if (retry_record) - { - setflag(addr2, af_lt_retry_exists); + if (retry_record) + { + setflag(addr2, af_lt_retry_exists); - /* A retry record exists for this address. If queue running and not - forcing, inspect its contents. If the record is too old, or if its - retry time has come, or if it has passed its cutoff time, delivery - will go ahead. */ + /* A retry record exists for this address. If queue running and not + forcing, inspect its contents. If the record is too old, or if its + retry time has come, or if it has passed its cutoff time, delivery + will go ahead. */ - DEBUG(D_retry) - { - debug_printf("retry record exists: age=%s ", - readconf_printtime(now - retry_record->time_stamp)); - debug_printf("(max %s)\n", readconf_printtime(retry_data_expire)); - debug_printf(" time to retry = %s expired = %d\n", - readconf_printtime(retry_record->next_try - now), - retry_record->expired); - } + DEBUG(D_retry) + { + debug_printf("retry record exists: age=%s ", + readconf_printtime(now - retry_record->time_stamp)); + debug_printf("(max %s)\n", readconf_printtime(retry_data_expire)); + debug_printf(" time to retry = %s expired = %d\n", + readconf_printtime(retry_record->next_try - now), + retry_record->expired); + } - if (f.queue_running && !f.deliver_force) - { - ok = (now - retry_record->time_stamp > retry_data_expire) - || (now >= retry_record->next_try) - || retry_record->expired; + if (f.queue_running && !f.deliver_force) + { + ok = (now - retry_record->time_stamp > retry_data_expire) + || (now >= retry_record->next_try) + || retry_record->expired; - /* If we haven't reached the retry time, there is one more check - to do, which is for the ultimate address timeout. */ + /* If we haven't reached the retry time, there is one more check + to do, which is for the ultimate address timeout. */ - if (!ok) - ok = retry_ultimate_address_timeout(retry_key, addr2->domain, - retry_record, now); - } - } - else DEBUG(D_retry) debug_printf("no retry record exists\n"); + if (!ok) + ok = retry_ultimate_address_timeout(retry_key, addr2->domain, + retry_record, now); + } + } + else DEBUG(D_retry) debug_printf("no retry record exists\n"); + } } /* This address is to be delivered. Leave it on the chain. */ @@ -2985,7 +2995,11 @@ while (addr_local) } } - if (dbm_file) dbfn_close(dbm_file); + if (dbm_file) + if (dbm_file != continue_retry_db) + { dbfn_close(dbm_file); dbm_file = NULL; } + else + DEBUG(D_hints_lookup) debug_printf("retaining retry hintsdb handle\n"); /* If there are no addresses left on the chain, they all deferred. Loop for the next set of addresses. */ @@ -7440,8 +7454,13 @@ while (addr_new) /* Loop until all addresses dealt with */ { /* If we have transaction-capable hintsdbs, open the retry db without locking, and leave open for the transport process and for subsequent - deliveries. If the open fails, tag that explicitly for the transport but - retry the open next time around, in case it was created in the interim. */ + deliveries. Use a writeable open as we can keep it open all the way through + to writing retry records if needed due to message fails. + If the open fails, tag that explicitly for the transport but retry the open + next time around, in case it was created in the interim. + If non-transaction, we are only reading records at this stage and + we close the db before running the transport. + Either way we do a non-creating open. */ if (continue_retry_db == (open_db *)-1) continue_retry_db = NULL; @@ -7451,7 +7470,7 @@ while (addr_new) /* Loop until all addresses dealt with */ DEBUG(D_hints_lookup) debug_printf("using cached retry hintsdb handle\n"); dbm_file = continue_retry_db; } - else if (!exim_lockfile_needed() && continue_transport) + else if (!exim_lockfile_needed()) { dbm_file = dbfn_open_multi(US"retry", O_RDWR, &dbblock); continue_retry_db = dbm_file ? dbm_file : (open_db *)-1; @@ -7471,7 +7490,7 @@ while (addr_new) /* Loop until all addresses dealt with */ { int rc; tree_node * tnode; - dbdata_retry * domain_retry_record, * address_retry_record; + dbdata_retry * domain_retry_record = NULL, * address_retry_record = NULL; addr = addr_new; addr_new = addr->next; @@ -7700,76 +7719,82 @@ while (addr_new) /* Loop until all addresses dealt with */ continue; } - /* Get the routing retry status, saving the two retry keys (with and - without the local part) for subsequent use. If there is no retry record for - the standard address routing retry key, we look for the same key with the - sender attached, because this form is used by the smtp transport after a - 4xx response to RCPT when address_retry_include_sender is true. */ - - DEBUG(D_retry) + if (f.queue_2stage) { - debug_printf_indent("checking router retry status\n"); - acl_level++; + DEBUG(D_deliver) + debug_printf_indent("no router retry check (ph1 qrun)\n"); } - addr->domain_retry_key = string_sprintf("R:%s", addr->domain); - addr->address_retry_key = string_sprintf("R:%s@%s", addr->local_part, - addr->domain); - - if (dbm_file) + else { - domain_retry_record = dbfn_read(dbm_file, addr->domain_retry_key); - if ( domain_retry_record - && now - domain_retry_record->time_stamp > retry_data_expire - ) + /* Get the routing retry status, saving the two retry keys (with and + without the local part) for subsequent use. If there is no retry record + for the standard address routing retry key, we look for the same key with + the sender attached, because this form is used by the smtp transport after + a 4xx response to RCPT when address_retry_include_sender is true. */ + + DEBUG(D_deliver|D_retry) { - DEBUG(D_deliver|D_retry) - debug_printf_indent("domain retry record present but expired\n"); - domain_retry_record = NULL; /* Ignore if too old */ + debug_printf_indent("checking router retry status\n"); + acl_level++; } + addr->domain_retry_key = string_sprintf("R:%s", addr->domain); + addr->address_retry_key = string_sprintf("R:%s@%s", addr->local_part, + addr->domain); - address_retry_record = dbfn_read(dbm_file, addr->address_retry_key); - if ( address_retry_record - && now - address_retry_record->time_stamp > retry_data_expire - ) + if (dbm_file) { - DEBUG(D_deliver|D_retry) - debug_printf_indent("address retry record present but expired\n"); - address_retry_record = NULL; /* Ignore if too old */ - } + domain_retry_record = dbfn_read(dbm_file, addr->domain_retry_key); + if ( domain_retry_record + && now - domain_retry_record->time_stamp > retry_data_expire + ) + { + DEBUG(D_deliver|D_retry) + debug_printf_indent("domain retry record present but expired\n"); + domain_retry_record = NULL; /* Ignore if too old */ + } - if (!address_retry_record) - { - uschar *altkey = string_sprintf("%s:<%s>", addr->address_retry_key, - sender_address); - address_retry_record = dbfn_read(dbm_file, altkey); - if ( address_retry_record - && now - address_retry_record->time_stamp > retry_data_expire) + address_retry_record = dbfn_read(dbm_file, addr->address_retry_key); + if ( address_retry_record + && now - address_retry_record->time_stamp > retry_data_expire + ) { DEBUG(D_deliver|D_retry) - debug_printf_indent("address retry record present but expired\n"); - address_retry_record = NULL; /* Ignore if too old */ + debug_printf_indent("address retry record present but expired\n"); + address_retry_record = NULL; /* Ignore if too old */ } - } - } - else - domain_retry_record = address_retry_record = NULL; - DEBUG(D_deliver|D_retry) - { - if (!domain_retry_record) - debug_printf_indent("no domain retry record\n"); - else - debug_printf_indent("have domain retry record; next_try = now%+d\n", - f.running_in_test_harness ? 0 : - (int)(domain_retry_record->next_try - now)); + if (!address_retry_record) + { + uschar *altkey = string_sprintf("%s:<%s>", addr->address_retry_key, + sender_address); + address_retry_record = dbfn_read(dbm_file, altkey); + if ( address_retry_record + && now - address_retry_record->time_stamp > retry_data_expire) + { + DEBUG(D_deliver|D_retry) + debug_printf_indent("address retry record present but expired\n"); + address_retry_record = NULL; /* Ignore if too old */ + } + } + } - if (!address_retry_record) - debug_printf_indent("no address retry record\n"); - else - debug_printf_indent("have address retry record; next_try = now%+d\n", - f.running_in_test_harness ? 0 : - (int)(address_retry_record->next_try - now)); - acl_level--; + DEBUG(D_deliver|D_retry) + { + if (!domain_retry_record) + debug_printf_indent("no domain retry record\n"); + else + debug_printf_indent("have domain retry record; next_try = now%+d\n", + f.running_in_test_harness ? 0 : + (int)(domain_retry_record->next_try - now)); + + if (!address_retry_record) + debug_printf_indent("no address retry record\n"); + else + debug_printf_indent("have address retry record; next_try = now%+d\n", + f.running_in_test_harness ? 0 : + (int)(address_retry_record->next_try - now)); + acl_level--; + } } /* If we are sending a message down an existing SMTP connection, we must @@ -7873,11 +7898,15 @@ while (addr_new) /* Loop until all addresses dealt with */ } } - /* The database is closed while routing is actually happening. Requests to - update it are put on a chain and all processed together at the end. */ + /* If not transaction-capable, the database is closed while routing is + actually happening. Requests to update it are put on a chain and all processed + together at the end. */ - if (dbm_file && !continue_retry_db) - { dbfn_close(dbm_file); dbm_file = NULL; } + if (dbm_file) + if (exim_lockfile_needed()) + { dbfn_close(dbm_file); dbm_file = NULL; } + else + DEBUG(D_hints_lookup) debug_printf("retaining retry hintsdb handle\n"); /* If queue_domains is set, we don't even want to try routing addresses in those domains. During queue runs, queue_domains is forced to be unset. @@ -8048,9 +8077,6 @@ while (addr_new) /* Loop until all addresses dealt with */ } /* Loop to process any child addresses that the routers created, and any rerouted addresses that got put back on the new chain. */ -if (dbm_file) /* Can only be continue_retry_db */ - { dbfn_close_multi(continue_retry_db); continue_retry_db = dbm_file = NULL; } - /* Debugging: show the results of the routing */ DEBUG(D_deliver|D_retry|D_route) @@ -8149,12 +8175,7 @@ if ( mua_wrapper /* If this is a run to continue deliveries to an external channel that is -already set up, defer any local deliveries. - -jgh 2020/12/20: I don't see why; locals should be quick. -The defer goes back to version 1.62 in 1997. A local being still deliverable -during a continued run might result from something like a defer during the -original delivery, eg. in a DB lookup. Unlikely but possible. +already set up, defer any local deliveries because we are handling remotes. To avoid delaying a local when combined with a callout-hold for a remote delivery, test continue_sequence rather than continue_transport. */ @@ -8402,9 +8423,10 @@ if (mua_wrapper) /* In a normal configuration, we now update the retry database. This is done in one fell swoop at the end in order not to keep opening and closing (and -locking) the database. The code for handling retries is hived off into a -separate module for convenience. We pass it the addresses of the various -chains, because deferred addresses can get moved onto the failed chain if the +locking) the database (at least, for non-transaction-capable DBs. +The code for handling retries is hived off into a separate module for +convenience. We pass it the addresses of the various chains, +because deferred addresses can get moved onto the failed chain if the retry cutoff time has expired for all alternative destinations. Bypass the updating of the database if the -N flag is set, which is a debugging thing that prevents actual delivery. */ @@ -8506,6 +8528,13 @@ f.disable_logging = FALSE; /* In case left set */ DELIVERY_TIDYUP: +if (dbm_file) /* Can only be continue_retry_db */ + { + DEBUG(D_hints_lookup) debug_printf("final close of cached retry db\n"); + dbfn_close_multi(continue_retry_db); + continue_retry_db = dbm_file = NULL; + } + /* If there are now no deferred addresses, we are done. Preserve the message log if so configured, and we are using them. Otherwise, sling it. Then delete the message itself. */ diff --git a/src/src/exim_dbmbuild.c b/src/src/exim_dbmbuild.c index 05387aa3f..f8fbd2b8c 100644 --- a/src/src/exim_dbmbuild.c +++ b/src/src/exim_dbmbuild.c @@ -88,6 +88,27 @@ if it is made static. */ const uschar *hex_digits = CUS"0123456789abcdef"; +/******************* +* Debug output * +*******************/ + +unsigned int debug_selector = 0; /* set -1 for debugging */ + +void +debug_printf(const char * fmt, ...) +{ +va_list ap; +va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); +} +void +debug_printf_indent(const char * fmt, ...) +{ +va_list ap; +va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); +} + + + #ifdef STRERROR_FROM_ERRLIST /* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror() in their libraries, but can provide the same facility by this simple diff --git a/src/src/exim_dbutil.c b/src/src/exim_dbutil.c index dd1444593..f3123c80b 100644 --- a/src/src/exim_dbutil.c +++ b/src/src/exim_dbutil.c @@ -112,6 +112,25 @@ exit(EXIT_FAILURE); +/******************* +* Debug output * +*******************/ + +unsigned int debug_selector = 0; /* set -1 for debugging */ + +void +debug_printf(const char * fmt, ...) +{ +va_list ap; +va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); +} +void +debug_printf_indent(const char * fmt, ...) +{ +va_list ap; +va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); +} + /************************************************* * Sort out the command arguments * *************************************************/ @@ -287,7 +306,6 @@ dbfn_open(const uschar * name, int flags, open_db * dbblock, { int rc; struct flock lock_data; -BOOL read_only = (flags & (O_WRONLY|O_RDWR)) == O_RDONLY; uschar * dirname, * filename; /* The first thing to do is to open a separate file on which to lock. This @@ -301,6 +319,7 @@ if ( asprintf(CSS &dirname, "%s/db", spool_directory) < 0 || asprintf(CSS &filename, "%s/%s.lockfile", dirname, name) < 0) return NULL; +dbblock->readonly = (flags & (O_WRONLY|O_RDWR)) == O_RDONLY; dbblock->lockfd = -1; if (exim_lockfile_needed()) { @@ -314,7 +333,7 @@ if (exim_lockfile_needed()) /* Now we must get a lock on the opened lock file; do this with a blocking lock that times out. */ - lock_data.l_type = read_only ? F_RDLCK : F_WRLCK; + lock_data.l_type = dbblock->readonly ? F_RDLCK : F_WRLCK; lock_data.l_whence = lock_data.l_start = lock_data.l_len = 0; sigalrm_seen = FALSE; @@ -327,7 +346,7 @@ if (exim_lockfile_needed()) if (rc < 0) { printf("** Failed to get %s lock for %s: %s", - read_only ? "read" : "write", + dbblock->readonly ? "read" : "write", filename, errno == ETIMEDOUT ? "timed out" : strerror(errno)); (void)close(dbblock->lockfd); @@ -340,10 +359,12 @@ if (exim_lockfile_needed()) if (asprintf(CSS &filename, "%s/%s", dirname, name) < 0) return NULL; -if (!(dbblock->dbptr = exim_dbopen(filename, dirname, flags, 0))) +if (!(dbblock->dbptr = dbblock->readonly && !exim_lockfile_needed() + ? exim_dbopen_multi(filename, dirname, flags, 0) + : exim_dbopen(filename, dirname, flags, 0))) { printf("** Failed to open hintsdb file %s for %s: %s%s\n", filename, - read_only ? "reading" : "writing", strerror(errno), + dbblock->readonly ? "reading" : "writing", strerror(errno), #ifdef USE_DB " (or Berkeley DB error while opening)" #else @@ -374,8 +395,13 @@ Returns: nothing void dbfn_close(open_db * dbp) { -exim_dbclose(dbp->dbptr); -if (dbp->lockfd >= 0) (void) close(dbp->lockfd); +if (dbp->readonly && !exim_lockfile_needed()) + exim_dbclose_multi(dbp->dbptr); +else + exim_dbclose(dbp->dbptr); + +if (dbp->lockfd >= 0) + (void) close(dbp->lockfd); } @@ -422,6 +448,7 @@ we should store the taint status along with the data. */ dlen = exim_datum_size_get(&result_datum); yield = store_get(dlen, GET_TAINTED); memcpy(yield, exim_datum_data_get(&result_datum), dlen); +DEBUG(D_hints_lookup) debug_printf_indent("dbfn_read: size %u return\n", dlen); if (length) *length = dlen; exim_datum_free(&result_datum); /* Some DBM libs require freeing */ diff --git a/src/src/hintsdb.h b/src/src/hintsdb.h index ba50ae1b9..a35791409 100644 --- a/src/src/hintsdb.h +++ b/src/src/hintsdb.h @@ -25,7 +25,11 @@ The API is: Functions: exim_lockfile_needed API semantics predicate exim_dbopen + exim_dbopen_multi only for no-lockfile-needed exim_dbclose + exim_dbclose_multi only for no-lockfile-needed + exim_dbtransaction_start only for no-lockfile-needed + exim_dbtransaction_commit only for no-lockfile-needed exim_dbget exim_dbput exim_dbputb non-overwriting put @@ -66,6 +70,9 @@ required by Exim's process transitions)? #ifndef HINTSDB_H #define HINTSDB_H +/* Include file ordering problem */ +extern void debug_printf_indent(const char *, ...) PRINTF_FUNCTION(1,2); + #ifdef USE_SQLITE # if defined(USE_DB) || defined(USE_GDBM) || defined(USE_TDB) @@ -103,20 +110,6 @@ the default is the NDBM interface (which seems to be a wrapper for GDBM) */ -#if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) - -static inline EXIM_DB * -exim_dbopen(const uschar * name, const uschar * dirname, int flags, - unsigned mode) -{ -return exim_dbopen__(name, dirname, flags, mode); -} - -static inline void -exim_dbclose(EXIM_DB * dbp) -{ exim_dbclose__(dbp); } - -#else /* exim mainline code */ /* Wrappers for open/close with debug tracing */ @@ -147,14 +140,43 @@ DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", dbp return dbp; } +static inline EXIM_DB * +exim_dbopen_multi(const uschar * name, const uschar * dirname, int flags, + unsigned mode) +{ +void * dbp; +DEBUG(D_hints_lookup) + debug_printf_indent("EXIM_DBOPEN_MULTI: file <%s> dir <%s> flags=%s\n", + name, dirname, + flags == O_RDONLY ? "O_RDONLY" + : flags == O_RDWR ? "O_RDWR" + : flags == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT" + : "??"); +if (is_tainted(name) || is_tainted(dirname)) + { + log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted"); + dbp = NULL; + } +else + dbp = exim_dbopen_multi__(name, dirname, flags, mode); + +DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN_MULTI: %p\n", dbp); +return dbp; +} + static inline void exim_dbclose(EXIM_DB * dbp) { DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", dbp); exim_dbclose__(dbp); } +static inline void +exim_dbclose_multi(EXIM_DB * dbp) +{ +DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE_MULTI(%p)\n", dbp); +exim_dbclose_multi__(dbp); +} -#endif /* defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) */ /********************* End of dbm library definitions **********************/ diff --git a/src/src/hintsdb/hints_bdb.h b/src/src/hintsdb/hints_bdb.h index e629cce4e..48573e907 100644 --- a/src/src/hintsdb/hints_bdb.h +++ b/src/src/hintsdb/hints_bdb.h @@ -48,6 +48,21 @@ definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */ # define DB_FORCESYNC 0 # endif + + +/* Berkeley DB uses a callback function to pass back error details. Its API +changed at release 4.3. */ + +#if defined(DB_VERSION_STRING) +# if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) +static void dbfn_bdb_error_callback(const DB_ENV *, const char *, const char *); +# else +static void dbfn_bdb_error_callback(const char *, char *); +# endif +#endif + + + /* Error callback */ /* For Berkeley DB >= 2, we can define a function to be called in case of DB errors. This should help with debugging strange DB problems, e.g. getting "File @@ -73,9 +88,9 @@ return TRUE; } static inline EXIM_DB * -exim_dbopen_multi(const uschar * name, const uschar * dirname, int flags, +exim_dbopen_multi__(const uschar * name, const uschar * dirname, int flags, unsigned mode) { return NULL; } -static inline void exim_dbclose_multi(EXIM_DB * dbp) {} +static inline void exim_dbclose_multi__(EXIM_DB * dbp) {} static inline BOOL exim_dbtransaction_start(EXIM_DB * dbp) { return FALSE; } static inline void exim_dbtransaction_commit(EXIM_DB * dbp) {} @@ -106,6 +121,9 @@ if (db_create(&b, dbp, 0) == 0) mode) == 0 ) return dbp; + else DEBUG(D_hints_lookup) + debug_printf_indent("bdb_open(flags 0x%x mode %04o) %s\n", + flags, mode, strerror(errno)); b->close(b, 0); } @@ -233,9 +251,9 @@ return TRUE; } static inline EXIM_DB * -exim_dbopen_multi(const uschar * name, const uschar * dirname, int flags, +exim_dbopen_multi__(const uschar * name, const uschar * dirname, int flags, unsigned mode) { return NULL; } -static inline void exim_dbclose_multi(EXIM_DB * dbp) {} +static inline void exim_dbclose_multi__(EXIM_DB * dbp) {} static inline BOOL exim_dbtransaction_start(EXIM_DB * dbp) { return FALSE; } static inline void exim_dbtransaction_commit(EXIM_DB * dbp) {} diff --git a/src/src/hintsdb/hints_gdbm.h b/src/src/hintsdb/hints_gdbm.h index b406d45e0..6b3789979 100644 --- a/src/src/hintsdb/hints_gdbm.h +++ b/src/src/hintsdb/hints_gdbm.h @@ -41,9 +41,9 @@ return TRUE; } static inline EXIM_DB * -exim_dbopen_multi(const uschar * name, const uschar * dirname, int flags, +exim_dbopen_multi__(const uschar * name, const uschar * dirname, int flags, unsigned mode) { return NULL; } -static inline void exim_dbclose_multi(EXIM_DB * dbp) {} +static inline void exim_dbclose_multi__(EXIM_DB * dbp) {} static inline BOOL exim_dbtransaction_start(EXIM_DB * dbp) { return FALSE; } static inline void exim_dbtransaction_commit(EXIM_DB * dbp) {} @@ -60,7 +60,12 @@ if (dbp) flags & O_CREAT ? GDBM_WRCREAT : flags & (O_RDWR|O_WRONLY) ? GDBM_WRITER : GDBM_READER, mode, 0); - if (dbp->gdbm) return dbp; + if (dbp->gdbm) + return dbp; + + DEBUG(D_hints_lookup) + debug_printf_indent("gdbm_open(flags 0x%x mode %04o) %s\n", + flags, mode, strerror(errno)); free(dbp); } return NULL; diff --git a/src/src/hintsdb/hints_ndbm.h b/src/src/hintsdb/hints_ndbm.h index fb1db57a8..389abd9e2 100644 --- a/src/src/hintsdb/hints_ndbm.h +++ b/src/src/hintsdb/hints_ndbm.h @@ -36,9 +36,9 @@ return TRUE; } static inline EXIM_DB * -exim_dbopen_multi(const uschar * name, const uschar * dirname, int flags, +exim_dbopen_multi__(const uschar * name, const uschar * dirname, int flags, unsigned mode) { return NULL; } -static inline void exim_dbclose_multi(EXIM_DB * dbp) {} +static inline void exim_dbclose_multi__(EXIM_DB * dbp) {} static inline BOOL exim_dbtransaction_start(EXIM_DB * dbp) { return FALSE; } static inline void exim_dbtransaction_commit(EXIM_DB * dbp) {} @@ -54,9 +54,10 @@ exim_dbopen__(const uschar * name, const uschar * dirname, int flags, struct stat st; if (!(flags & O_CREAT) || lstat(CCS name, &st) != 0 && errno == ENOENT) return dbm_open(CS name, flags, mode); -#ifndef COMPILE_UTILITY -debug_printf("%s %d errno %s\n", __FUNCTION__, __LINE__, strerror(errno)); -#endif + +DEBUG(D_hints_lookup) + debug_printf_indent("ndbm_open(flags 0x%x mode %04o) %s\n", + flags, mode, strerror(errno)); errno = (st.st_mode & S_IFMT) == S_IFDIR ? EISDIR : EEXIST; return NULL; } diff --git a/src/src/hintsdb/hints_sqlite.h b/src/src/hintsdb/hints_sqlite.h index da3bc2bff..262a414f6 100644 --- a/src/src/hintsdb/hints_sqlite.h +++ b/src/src/hintsdb/hints_sqlite.h @@ -35,11 +35,12 @@ return FALSE; /* We do transaction; no extra locking needed */ /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */ static inline EXIM_DB * -exim_dbopen_multi(const uschar * name, const uschar * dirname, int flags, +exim_dbopen_multi__(const uschar * name, const uschar * dirname, int flags, unsigned mode) { EXIM_DB * dbp; int ret, sflags = flags & O_RDWR ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY; + if (flags & O_CREAT) sflags |= SQLITE_OPEN_CREATE; if ((ret = sqlite3_open_v2(CCS name, &dbp, sflags, NULL)) == SQLITE_OK) { @@ -51,8 +52,9 @@ if ((ret = sqlite3_open_v2(CCS name, &dbp, sflags, NULL)) == SQLITE_OK) if (ret != SQLITE_OK) sqlite3_close(dbp); } -//else -// fprintf(stderr, "sqlite3_open_v2: %s\n", sqlite3_errmsg(dbp)); +else DEBUG(D_hints_lookup) + debug_printf_indent("sqlite_open(flags 0x%x mode %04o) %s\n", + flags, mode, sqlite3_errmsg(dbp)); return ret == SQLITE_OK ? dbp : NULL; } @@ -286,7 +288,7 @@ store_free(cursor); /* EXIM_DBCLOSE */ static inline void -exim_dbclose_multi(EXIM_DB * dbp) +exim_dbclose_multi__(EXIM_DB * dbp) { sqlite3_close(dbp); } diff --git a/src/src/hintsdb/hints_tdb.h b/src/src/hintsdb/hints_tdb.h index 436597115..2b4fcc7f6 100644 --- a/src/src/hintsdb/hints_tdb.h +++ b/src/src/hintsdb/hints_tdb.h @@ -11,9 +11,6 @@ backend provider. */ /* ************************* tdb interface ************************ */ -/*XXX https://manpages.org/tdb/3 mentions concurrent writes. -Could we lose the file lock? */ - # include /* Basic DB type */ @@ -34,22 +31,39 @@ tdb_traverse to be called) */ static inline BOOL exim_lockfile_needed(void) { -return TRUE; +return FALSE; /* Transactions are supported */ } -static inline EXIM_DB * -exim_dbopen_multi(const uschar * name, const uschar * dirname, int flags, - unsigned mode) { return NULL; } -static inline void exim_dbclose_multi(EXIM_DB * dbp) {} -static inline BOOL exim_dbtransaction_start(EXIM_DB * dbp) { return FALSE; } -static inline void exim_dbtransaction_commit(EXIM_DB * dbp) {} /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */ static inline EXIM_DB * exim_dbopen__(const uschar * name, const uschar * dirname, int flags, unsigned mode) { -return tdb_open(CS name, 0, TDB_DEFAULT, flags, mode); +EXIM_DB * db = tdb_open(CS name, 0, TDB_DEFAULT, flags, mode); +int e; + +DEBUG(D_hints_lookup) if (!db) + debug_printf_indent("tdb_open(flags 0x%x mode %04o) %s\n", + flags, mode, strerror(errno)); +if (!db || tdb_transaction_start(db) == 0) return db; +e = errno; +DEBUG(D_hints_lookup) if (db) + debug_printf_indent("tdb_transaction_start: %s\n", tdb_errorstr(db)); +tdb_close(db); +errno = e; +return NULL; +} + +static inline EXIM_DB * +exim_dbopen_multi__(const uschar * name, const uschar * dirname, int flags, + unsigned mode) +{ +EXIM_DB * db = tdb_open(CS name, 0, TDB_DEFAULT, flags, mode); +DEBUG(D_hints_lookup) if (!db) + debug_printf_indent("tdb_open(flags 0x%x mode %04o) %s\n", + flags, mode, strerror(errno)); +return db; } /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */ @@ -60,10 +74,36 @@ exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res) return res->dptr != NULL; } + +static inline BOOL +exim_dbtransaction_start(EXIM_DB * db) +{ +BOOL ok = tdb_transaction_start(db) == 0; +DEBUG(D_hints_lookup) if (!ok) + debug_printf_indent("tdb_transaction_start: %s\n", tdb_errorstr(db)); +return ok; +} + +static inline void +exim_dbtransaction_commit(EXIM_DB * db) +{ +BOOL ok = tdb_transaction_commit(db) == 0; +DEBUG(D_hints_lookup) if (!ok) + debug_printf_indent("tdb_transaction_commit: %s\n", tdb_errorstr(db)); +return; +} + + + /* EXIM_DBPUT - returns nothing useful, assumes replace mode */ static inline int exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data) -{ return tdb_store(dbp, *key, *data, TDB_REPLACE); } +{ +int rc = tdb_store(dbp, *key, *data, TDB_REPLACE); +DEBUG(D_hints_lookup) if (rc != 0) + debug_printf_indent("tdb_store: %s\n", tdb_errorstr(dbp)); +return rc; +} /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */ static inline int @@ -109,12 +149,33 @@ return key->dptr != NULL; /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */ static inline void exim_dbdelete_cursor(EXIM_CURSOR * cursor) -{ store_free(cursor); } +{ +#ifdef COMPILE_UTILITY +free(cursor); +#else +store_free(cursor); +#endif +} /* EXIM_DBCLOSE */ +static inline void +exim_dbclose_multi__(EXIM_DB * db) +{ +int rc = tdb_close(db); +DEBUG(D_hints_lookup) if (rc != 0) + debug_printf_indent("tdb_close: %s\n", tdb_errorstr(db)); +} + static inline void exim_dbclose__(EXIM_DB * db) -{ tdb_close(db); } +{ +int rc = tdb_transaction_commit(db); +DEBUG(D_hints_lookup) if (rc != 0) + debug_printf_indent("tdb_transaction_commit: %s\n", tdb_errorstr(db)); +rc = tdb_close(db); +DEBUG(D_hints_lookup) if (rc != 0) + debug_printf_indent("tdb_close: %s\n", tdb_errorstr(db)); +} /* Datum access */ diff --git a/src/src/hintsdb_structs.h b/src/src/hintsdb_structs.h index 5f50dfd5f..5adb68eb5 100644 --- a/src/src/hintsdb_structs.h +++ b/src/src/hintsdb_structs.h @@ -21,6 +21,7 @@ that relates to it. */ typedef struct { void * dbptr; int lockfd; + BOOL readonly; } open_db; diff --git a/src/src/queue.c b/src/src/queue.c index 3073ee780..57e5eb769 100644 --- a/src/src/queue.c +++ b/src/src/queue.c @@ -513,23 +513,31 @@ for (int i = queue_run_in_order ? -1 : 0; (double)load_average/1000.0, (double)deliver_queue_load_max/1000.0); - /* If initial of a 2-phase run, maintain a set of child procs - to get disk parallelism */ + /* If initial of a 2-phase run (and not under the test-harness) + maintain a set of child procs to get disk parallelism */ if (q->queue_2stage && !queue_run_in_order) { int i; - if (qpid[f.running_in_test_harness ? 0 : nelem(qpid) - 1]) - { - DEBUG(D_queue_run) debug_printf("q2stage waiting for child %d\n", (int)qpid[0]); + if (qpid[ +#ifndef MEASURE_TIMING + f.running_in_test_harness ? 0 : +#endif + nelem(qpid) - 1]) + { /* The child table is maxed out; wait for the oldest */ + DEBUG(D_queue_run) + debug_printf("q2stage waiting for child %d\n", (int)qpid[0]); waitpid(qpid[0], NULL, 0); - DEBUG(D_queue_run) debug_printf("q2stage reaped child %d\n", (int)qpid[0]); - if (f.running_in_test_harness) i = 0; - else for (i = 0; i < nelem(qpid) - 1; i++) qpid[i] = qpid[i+1]; + DEBUG(D_queue_run) + debug_printf("q2stage reaped child %d\n", (int)qpid[0]); +#ifndef MEASURE_TIMING + if (f.running_in_test_harness) i = 0; else +#endif + for (i = 0; i < nelem(qpid) - 1; i++) qpid[i] = qpid[i+1]; qpid[i] = 0; } else - for (i = 0; qpid[i]; ) i++; + for (i = 0; qpid[i]; ) i++; /* find first spare slot */ if ((qpid[i] = exim_fork(US"qrun-phase-one"))) continue; /* parent loops around */ } @@ -565,7 +573,8 @@ for (int i = queue_run_in_order ? -1 : 0; follow. If the message is chosen for delivery, the header is read again in the deliver_message() function, in a subprocess. */ - if (spool_read_header(fq->text, FALSE, TRUE) != spool_read_OK) goto go_around; + if (spool_read_header(fq->text, FALSE, TRUE) != spool_read_OK) + goto go_around; f.dont_deliver = orig_dont_deliver; /* Now decide if we want to deliver this message. As we have read the @@ -739,6 +748,7 @@ single_item_retry: set_process_info("running queue"); /* If initial of a 2-phase run, we are a child - so just exit */ + if (q->queue_2stage && !queue_run_in_order) exim_exit(EXIT_SUCCESS); diff --git a/src/src/retry.c b/src/src/retry.c index e86b1afe8..c32bd85b7 100644 --- a/src/src/retry.c +++ b/src/src/retry.c @@ -153,19 +153,23 @@ retry_check_address(const uschar *domain, host_item *host, uschar *portstring, BOOL yield = FALSE; time_t now = time(NULL); const uschar * host_key, * message_key; -open_db dbblock, * dbm_file; +open_db dbblock, * dbm_file = NULL; tree_node * node; dbdata_retry * host_retry_record, * message_retry_record; *retry_host_key = *retry_message_key = NULL; -DEBUG(D_transport|D_retry) debug_printf("checking retry status of %s\n", host->name); - /* Do nothing if status already set; otherwise initialize status as usable. */ if (host->status != hstatus_unknown) return FALSE; host->status = hstatus_usable; +DEBUG(D_transport|D_retry) + { + debug_printf_indent("checking retry status of %s\n", host->name); + acl_level++; + } + /* Generate the host key for the unusable tree and the retry database. Ensure host names are lower cased (that's what %S does). Generate the message-specific key too. @@ -182,11 +186,12 @@ the retry database when it is updated). */ if ((node = tree_search(tree_unusable, host_key))) { - DEBUG(D_transport|D_retry) debug_printf("found in tree of unusables\n"); - host->status = (node->data.val > 255)? - hstatus_unusable_expired : hstatus_unusable; + DEBUG(D_transport|D_retry) + debug_printf_indent("found in tree of unusables\n"); + host->status = node->data.val > 255 + ? hstatus_unusable_expired : hstatus_unusable; host->why = node->data.val & 255; - return FALSE; + goto out; } /* Open the retry database, giving up if there isn't one. Otherwise, search for @@ -194,40 +199,49 @@ the retry records, and then close the database again. */ if (!continue_retry_db) dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE, TRUE); -else if ((dbm_file = continue_retry_db) == (open_db *)-1) - dbm_file = NULL; +else if (continue_retry_db != (open_db *)-1) + { + DEBUG(D_hints_lookup) + debug_printf_indent(" using cached retry hintsdb handle\n"); + dbm_file = continue_retry_db; + } +else DEBUG(D_hints_lookup) + debug_printf_indent(" using cached retry hintsdb nonpresence\n"); if (!dbm_file) { DEBUG(D_deliver|D_retry|D_hints_lookup) - debug_printf("no retry data available\n"); - return FALSE; + debug_printf_indent("no retry data available\n"); + goto out; } host_retry_record = dbfn_read(dbm_file, host_key); message_retry_record = dbfn_read(dbm_file, message_key); if (!continue_retry_db) dbfn_close(dbm_file); +else + DEBUG(D_hints_lookup) debug_printf_indent("retaining retry hintsdb handle\n"); /* Ignore the data if it is too old - too long since it was written */ if (!host_retry_record) { - DEBUG(D_transport|D_retry) debug_printf("no host retry record\n"); + DEBUG(D_transport|D_retry) debug_printf_indent("no host retry record\n"); } else if (now - host_retry_record->time_stamp > retry_data_expire) { host_retry_record = NULL; - DEBUG(D_transport|D_retry) debug_printf("host retry record too old\n"); + DEBUG(D_transport|D_retry) debug_printf_indent("host retry record too old\n"); } if (!message_retry_record) { - DEBUG(D_transport|D_retry) debug_printf("no message retry record\n"); + DEBUG(D_transport|D_retry) debug_printf_indent("no message retry record\n"); } else if (now - message_retry_record->time_stamp > retry_data_expire) { message_retry_record = NULL; - DEBUG(D_transport|D_retry) debug_printf("message retry record too old\n"); + DEBUG(D_transport|D_retry) + debug_printf_indent("message retry record too old\n"); } /* If there's a host-specific retry record, check for reaching the retry @@ -249,7 +263,7 @@ if (host_retry_record) if (!host_retry_record->expired && retry_ultimate_address_timeout(host_key, domain, host_retry_record, now)) - return FALSE; + goto out; /* We have not hit the ultimate address timeout; host is unusable. */ @@ -257,7 +271,7 @@ if (host_retry_record) hstatus_unusable_expired : hstatus_unusable; host->why = hwhy_retry; host->last_try = host_retry_record->last_try; - return FALSE; + goto out; } /* Host is usable; set return TRUE if expired. */ @@ -280,10 +294,12 @@ if (message_retry_record) host->status = hstatus_unusable; host->why = hwhy_retry; } - return FALSE; + yield = FALSE; goto out; } } +out: +DEBUG(D_transport|D_retry) acl_level--; return yield; } @@ -531,6 +547,7 @@ return yield; /* Update the retry data for any directing/routing/transporting that was deferred, or delete it for those that succeeded after a previous defer. This is done all in one go to minimize opening/closing/locking of the database file. +Called (only) from deliver_message(). Note that, because SMTP delivery involves a list of destinations to try, there may be defer-type retry information for some of them even when the message was @@ -590,8 +607,7 @@ for (int i = 0; i < 3; i++) for (addr = endaddr; addr; addr = addr->parent) { - int update_count = 0; - int timedout_count = 0; + int update_count = 0, timedout_count = 0; DEBUG(D_retry) { @@ -617,14 +633,20 @@ for (int i = 0; i < 3; i++) reached their retry next try time. */ if (!dbm_file) - dbm_file = dbfn_open(US"retry", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE); - - if (!dbm_file) - { - DEBUG(D_deliver|D_retry|D_hints_lookup) - debug_printf_indent("retry database not available for updating\n"); - return; - } + if (continue_retry_db && continue_retry_db != (open_db *)-1) + { + DEBUG(D_hints_lookup) + debug_printf_indent("using cached retry hintsdb handle\n"); + dbm_file = continue_retry_db; + } + else if (!(dbm_file = exim_lockfile_needed() + ? dbfn_open(US"retry", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE) + : dbfn_open_multi(US"retry", O_RDWR|O_CREAT, &dbblock))) + { + DEBUG(D_deliver|D_retry|D_hints_lookup) + debug_printf_indent("retry db not available for updating\n"); + return; + } /* If there are no deferred addresses, that is, if this message is completing, and the retry item is for a message-specific SMTP error, @@ -699,6 +721,12 @@ for (int i = 0; i < 3; i++) message_length = EXIM_DB_RLIMIT; } + /* For a transaction-capable DB, open one for the read,write + sequence used for this retry record */ + + if (!exim_lockfile_needed()) + dbfn_transaction_start(dbm_file); + /* Read a retry record from the database or construct a new one. Ignore an old one if it is too old since it was last updated. */ @@ -888,8 +916,12 @@ for (int i = 0; i < 3; i++) debug_printf(" %s\n", retry_record->text); } - (void)dbfn_write(dbm_file, rti->key, retry_record, - sizeof(dbdata_retry) + message_length); + if (dbfn_write(dbm_file, rti->key, retry_record, + sizeof(dbdata_retry) + message_length) != 0) + DEBUG(D_retry) debug_printf_indent("retry record write failed\n"); + + if (!exim_lockfile_needed()) + dbfn_transaction_commit(dbm_file); } /* Loop for each retry item */ DEBUG(D_retry) acl_level--; @@ -971,9 +1003,17 @@ for (int i = 0; i < 3; i++) /* Close and unlock the database */ -if (dbm_file) dbfn_close(dbm_file); +if (dbm_file) + if (dbm_file != continue_retry_db) + if (exim_lockfile_needed()) + dbfn_close(dbm_file); + else + dbfn_close_multi(dbm_file); + else DEBUG(D_hints_lookup) + debug_printf_indent("retaining retry hintsdb handle\n"); -DEBUG(D_retry) { acl_level--; debug_printf_indent("end of retry processing\n"); } +DEBUG(D_retry) + { acl_level--; debug_printf_indent("end of retry processing\n"); } } /* End of retry.c */ diff --git a/test/runtest b/test/runtest index a41298f73..6a00a4642 100755 --- a/test/runtest +++ b/test/runtest @@ -1178,6 +1178,30 @@ RESET_AFTER_EXTRA_LINE_READ: next if /lock(?:ing|ed) .*\/spool\/db\/[^.]+\.lockfile$/; s/closed hints database\K and lockfile$//; + # Hints DBs with transactions are provider-dependent, and flow changes + # to take advantage of them need different opens and different flags. + # Drop all the debug output for opens and closes. + if (/EXIM_DBOPEN(_MULTI)?: file <.*spool\/db\/retry>/) + { + $_ = ; + next if (/returned from EXIM_DBOPEN(_MULTI)?: 0x[[:xdigit:]]+$/); + $_ = ; + if (/returned from EXIM_DBOPEN(_MULTI)?: \(nil\)$/); + next; + } + if (/EXIM_DBCLOSE(_MULTI)?/) { ; next; } + next if /retaining retry hintsdb handle$/; + next if /using cached retry hintsdb (?:handle|nonpresence)$/; + if (/final close of cached retry db$/) { ; ; next; } + next if /dbfn_transaction_(?:start|commit)$/; + + # Various hintsdb backends + s/(?:bdb|tdb|gdbm|ndbm|sqlite) + _open\(flags\ 0x(\d) + \ mode\ 0640\) + (?=\ No\ such\ file\ or\ directory$) + /hintsdb_open(flags 0x$1 mode 0640)/x; + # Lines with a leading pid. Only handle >= 4-digit PIDs to avoid converting SMTP respose codes s/^\s*(\d{4,})\s(?!(?:previous message|in\s|bytes remain in|SMTP accept process running))/new_value($1, "p%s", \$next_pid) . ' '/e; @@ -1390,19 +1414,6 @@ RESET_AFTER_EXTRA_LINE_READ: next if /failed to load readline:/; - # Some DBM libraries seem to make DBM files on opening with O_RDWR without - # O_CREAT; other's don't. In the latter case there is some debugging output - # which is not present in the former. Skip the relevant lines (there are - # three of them). - - if (/returned from EXIM_DBOPEN: \(nil\)/) - { - $_ .= ; - s?\Q$parm_cwd\E?TESTSUITE?g; - if (/TESTSUITE\/spool\/db\/\S+ appears not to exist: trying to create/) - { $_ = ; next; } - } - # Some tests turn on +expand debugging to check on expansions. # Unfortunately, the Received: expansion varies, depending on whether TLS # is compiled or not. So we must remove the relevant debugging if it is. diff --git a/test/stderr/0275 b/test/stderr/0275 index c4638ea60..aa6187d0d 100644 --- a/test/stderr/0275 +++ b/test/stderr/0275 @@ -259,9 +259,6 @@ body_linecount=0 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -459,9 +456,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to userx transport=t1 diff --git a/test/stderr/0278 b/test/stderr/0278 index 58729d516..fd94ee0c0 100644 --- a/test/stderr/0278 +++ b/test/stderr/0278 @@ -164,9 +164,6 @@ body_linecount=0 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: CALLER@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: CALLER@test.ex @@ -259,9 +256,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> CALLER@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to CALLER transport=t1 diff --git a/test/stderr/0357 b/test/stderr/0357 index a861c737d..4048d801f 100644 --- a/test/stderr/0357 +++ b/test/stderr/0357 @@ -25,7 +25,7 @@ After routing: Failed addresses: Deferred addresses: checking retry status of 127.0.0.1 -no retry data available + no retry data available added retry item for R:userx@test.ex:: errno=-44 more_errno=dd,A flags=0 cmdlog: '220:EHLO:250:MAIL:250:RCPT:451:QUIT+:250' >>>>>>>>>>>>>>>> Exim pid=p1239 (transport) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -69,8 +69,8 @@ After routing: Failed addresses: Deferred addresses: checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record added retry item for R:userx@test.ex:: errno=-44 more_errno=dd,A flags=0 cmdlog: '220:EHLO:250:MAIL:250:RCPT:451:QUIT+:250' >>>>>>>>>>>>>>>> Exim pid=p1240 (transport) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -127,8 +127,8 @@ After routing: Failed addresses: Deferred addresses: checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record added retry item for R:userx@test.ex:: errno=-44 more_errno=dd,A flags=0 cmdlog: '220:EHLO:250:MAIL:250:RCPT:451:QUIT+:250' >>>>>>>>>>>>>>>> Exim pid=p1242 (transport) terminating with rc=0 >>>>>>>>>>>>>>>> diff --git a/test/stderr/0358 b/test/stderr/0358 index b4c68382b..d51bcf1a9 100644 --- a/test/stderr/0358 +++ b/test/stderr/0358 @@ -31,7 +31,7 @@ After routing: Failed addresses: Deferred addresses: checking retry status of 127.0.0.1 -no retry data available + no retry data available added retry item for R:userx@test.ex:: errno=-44 more_errno=dd,A flags=0 added retry item for R:usery@test.ex:: errno=-44 more_errno=dd,A flags=0 cmdlog: '220:EHLO:250:MAIL:250:RCPT:451:RCPT:451:QUIT+:250' @@ -95,8 +95,8 @@ After routing: Failed addresses: Deferred addresses: checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record added retry item for R:userx@test.ex:: errno=-44 more_errno=dd,A flags=0 added retry item for R:usery@test.ex:: errno=-44 more_errno=dd,A flags=0 cmdlog: '220:EHLO:250:MAIL:250:RCPT:451:RCPT:451:QUIT+:250' diff --git a/test/stderr/0361 b/test/stderr/0361 index d54cdc43d..171d925e6 100644 --- a/test/stderr/0361 +++ b/test/stderr/0361 @@ -78,9 +78,6 @@ body_linecount=0 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: kilos@recurse.test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: kilos@recurse.test.ex @@ -136,9 +133,6 @@ rewriting header lines rewrite_one_header: type=F: From: CALLER_NAME re-routed to kilos@recurse.test.ex.test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: kilos@recurse.test.ex.test.ex @@ -182,9 +176,6 @@ r3 router generated kilos@recurse.test.ex.test.ex routed by r3 router envelope to: kilos@recurse.test.ex.test.ex transport: - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: kilos@recurse.test.ex.test.ex @@ -235,9 +226,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> kilos@recurse.test.ex.test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to kilos transport=t2 diff --git a/test/stderr/0386 b/test/stderr/0386 index db54ea8f4..fa1cfb63e 100644 --- a/test/stderr/0386 +++ b/test/stderr/0386 @@ -312,9 +312,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: 2@b - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: 2@b @@ -348,9 +345,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> 2@b <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to 2 <2@b> transport=t1 @@ -508,9 +502,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: 2@b - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: 2@b @@ -544,9 +535,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> 2@b <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to 2 <2@b> transport=t1 diff --git a/test/stderr/0388 b/test/stderr/0388 index 152c91a27..d924179fa 100644 --- a/test/stderr/0388 +++ b/test/stderr/0388 @@ -7,9 +7,6 @@ admin user dropping to exim gid; retaining priv uid set_process_info: pppp delivering specified messages set_process_info: pppp delivering 10HmaX-000000005vi-0000 - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: x@y @@ -77,10 +74,7 @@ changed uid/gid: remote delivery to x@y with transport=smtp uid=EXIM_UID gid=EXIM_GID pid=p1235 set_process_info: pppp delivering 10HmaX-000000005vi-0000 using smtp checking retry status of 127.0.0.1 - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory -no retry data available + no retry data available 127.0.0.1 in serialize_hosts? no (option unset) set_process_info: pppp delivering 10HmaX-000000005vi-0000 to 127.0.0.1 [127.0.0.1]:PORT_S (x@y) Connecting to 127.0.0.1 [127.0.0.1]:PORT_S ... @@ -118,10 +112,7 @@ set_process_info: pppp delivering 10HmaX-000000005vi-0000: just tried 127.0.0.1 *@127.0.0.1 in "*"? yes (matched "*") Clearing TFO as not first host for message checking retry status of V4NET.0.0.0 - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory -no retry data available + no retry data available V4NET.0.0.0 in serialize_hosts? no (option unset) set_process_info: pppp delivering 10HmaX-000000005vi-0000 to V4NET.0.0.0 [V4NET.0.0.0]:PORT_S (x@y) Connecting to V4NET.0.0.0 [V4NET.0.0.0]:PORT_S ... @@ -152,45 +143,40 @@ Processing retry items Failed addresses: Deferred addresses: x@y - ╎EXIM_DBOPEN: file dir flags=O_RDWR - ╎returned from EXIM_DBOPEN: 0xAAAAAAAA - ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR|O_CREAT - ╎x@y in "*"? + x@y in "*"? + ╎list element: * + ╎address match test: subject=x@y pattern=* + ╎y in "*"? ╎ list element: * - ╎ address match test: subject=x@y pattern=* - ╎ y in "*"? - ╎ list element: * - ╎ y in "*"? yes (matched "*") - ╎ x@y in "*"? yes (matched "*") - ╎retry for R:x@y = * 0 0 - ╎dbfn_read: key=R:x@y - ╎dbfn_read: null return - ╎failing_interval=ttt message_age=ttt - ╎Writing retry data for R:x@y - ╎ first failed=dddd last try=dddd next try=+1 expired=1 - ╎ errno=-44 more_errno=dd,A H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:: 451 Temporary error - ╎dbfn_write: key=R:x@y datalen nn - ╎*@V4NET.0.0.0 in "*"? + ╎ y in "*"? yes (matched "*") + ╎x@y in "*"? yes (matched "*") + retry for R:x@y = * 0 0 + dbfn_read: key=R:x@y + dbfn_read: null return + failing_interval=ttt message_age=ttt + Writing retry data for R:x@y + first failed=dddd last try=dddd next try=+1 expired=1 + errno=-44 more_errno=dd,A H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:: 451 Temporary error + dbfn_write: key=R:x@y datalen nn + *@V4NET.0.0.0 in "*"? + ╎list element: * + ╎address match test: subject=*@V4NET.0.0.0 pattern=* + ╎V4NET.0.0.0 in "*"? ╎ list element: * - ╎ address match test: subject=*@V4NET.0.0.0 pattern=* - ╎ V4NET.0.0.0 in "*"? - ╎ list element: * - ╎ V4NET.0.0.0 in "*"? yes (matched "*") - ╎ *@V4NET.0.0.0 in "*"? yes (matched "*") - ╎retry for T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S (y) = * 0 0 - ╎dbfn_read: key=T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S - ╎dbfn_read: null return - ╎failing_interval=ttt message_age=ttt - ╎on queue longer than maximum retry - ╎Writing retry data for T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S - ╎ first failed=dddd last try=dddd next try=+0 expired=0 - ╎ errno=dd more_errno=dd,A Network Error - ╎dbfn_write: key=T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S datalen nn - timed out: all retries expired + ╎ V4NET.0.0.0 in "*"? yes (matched "*") + ╎*@V4NET.0.0.0 in "*"? yes (matched "*") + retry for T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S (y) = * 0 0 + dbfn_read: key=T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S + dbfn_read: null return + failing_interval=ttt message_age=ttt + on queue longer than maximum retry + Writing retry data for T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S + first failed=dddd last try=dddd next try=+0 expired=0 + errno=dd more_errno=dd,A Network Error + dbfn_write: key=T:[V4NET.0.0.0]:V4NET.0.0.0:PORT_S datalen nn + timed out: all retries expired LOG: MAIN ** x@y: retry timeout exceeded - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database end of retry processing exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -C TESTSUITE/test-config -d=0xd7715ced -MCd bounce-message -odi -odi -t -oem -oi -f <> -E10HmaX-000000005vi-0000 Exim version x.yz .... @@ -263,24 +249,19 @@ admin user dropping to exim gid; retaining priv uid set_process_info: pppp delivering specified messages set_process_info: pppp delivering 10HmaY-000000005vi-0000 - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/retry: flags=O_RDONLY >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: CALLER@myhost.test.ex unique = CALLER@myhost.test.ex - checking router retry status - dbfn_read: key=R:myhost.test.ex - dbfn_read: null return - dbfn_read: key=R:CALLER@myhost.test.ex - dbfn_read: null return - dbfn_read: key=R:CALLER@myhost.test.ex:<> - dbfn_read: null return - no domain retry record - no address retry record +checking router retry status + dbfn_read: key=R:myhost.test.ex + dbfn_read: null return + dbfn_read: key=R:CALLER@myhost.test.ex + dbfn_read: null return + dbfn_read: key=R:CALLER@myhost.test.ex:<> + dbfn_read: null return + no domain retry record + no address retry record CALLER@myhost.test.ex: queued for routing - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> routing CALLER@myhost.test.ex --------> r0 router <-------- diff --git a/test/stderr/0398 b/test/stderr/0398 index 169c332ad..86fbb5acd 100644 --- a/test/stderr/0398 +++ b/test/stderr/0398 @@ -141,15 +141,12 @@ routed by r2 router Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT - dbfn_read: key=remote - dbfn_read: size nnn return - callout cache: found domain record for remote - dbfn_read: key=qq@remote - dbfn_read: null return - callout cache: no address record found for qq@remote - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database +dbfn_read: key=remote +dbfn_read: size nnn return +callout cache: found domain record for remote +dbfn_read: key=qq@remote +dbfn_read: null return +callout cache: no address record found for qq@remote interface=NULL port=PORT_S Connecting to 127.0.0.1 [127.0.0.1]:PORT_S ... 127.0.0.1 in hosts_try_fastopen? @@ -177,14 +174,11 @@ cmd buf flush ddd bytes cmdlog: '220:EHLO:250:MAIL:250:RCPT:550:QUIT:250' EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT - dbfn_write: key=remote datalen nn - wrote callout cache domain record for remote: - result=1 postmaster=0 random=0 - dbfn_write: key=qq@remote datalen nn - wrote negative callout cache address record for qq@remote - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database +dbfn_write: key=remote datalen nn +wrote callout cache domain record for remote: + result=1 postmaster=0 random=0 +dbfn_write: key=qq@remote datalen nn +wrote negative callout cache address record for qq@remote ----------- end verify ------------ l_message: $acl_verify_message warn: condition test succeeded in ACL "rcpt" @@ -274,16 +268,13 @@ routed by r2 router Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT - dbfn_read: key=remote - dbfn_read: size nnn return - callout cache: found domain record for remote - dbfn_read: key=qq@remote - dbfn_read: size nnn return - callout cache: found address record for qq@remote - callout cache: address record is negative - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database +dbfn_read: key=remote +dbfn_read: size nnn return +callout cache: found domain record for remote +dbfn_read: key=qq@remote +dbfn_read: size nnn return +callout cache: found address record for qq@remote +callout cache: address record is negative ----------- end verify ------------ l_message: $acl_verify_message warn: condition test succeeded in ACL "rcpt" diff --git a/test/stderr/0402 b/test/stderr/0402 index bf80809c8..a9dab0cdc 100644 --- a/test/stderr/0402 +++ b/test/stderr/0402 @@ -447,9 +447,6 @@ Delivery address list: userz@test.ex rd+CALLER@test.ex rd+usery@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: CALLER@test.ex @@ -724,9 +721,6 @@ try option unseen routed by r1 router envelope to: CALLER@test.ex transport: t1 - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: TESTSUITE/test-mail/junk @@ -750,9 +744,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> TESTSUITE/test-mail/junk <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available try option max_parallel try option return_path @@ -849,9 +840,6 @@ rd+usery@test.ex: children all complete LOG: MAIN => TESTSUITE/test-mail/junk R=r5 T=ft1 --------> TESTSUITE/test-mail/junk <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available try option max_parallel try option return_path @@ -940,9 +928,6 @@ rd+CALLER@test.ex: children all complete LOG: MAIN => TESTSUITE/test-mail/junk R=r4 T=ft1 --------> CALLER@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available try option max_parallel try option return_path @@ -974,9 +959,6 @@ CALLER@test.ex delivered LOG: MAIN => CALLER R=r1 T=t1 --------> usery@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available try option max_parallel try option return_path @@ -1016,9 +998,6 @@ usery@test.ex delivered LOG: MAIN => usery R=r2 T=t1 --------> userz@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available try option max_parallel try option return_path diff --git a/test/stderr/0403 b/test/stderr/0403 index 79dde380b..449b63a6d 100644 --- a/test/stderr/0403 +++ b/test/stderr/0403 @@ -72,9 +72,6 @@ body_linecount=0 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -160,9 +157,6 @@ r2 router generated TESTSUITE/test-mail/junk routed by r2 router envelope to: userx@test.ex transport: - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: TESTSUITE/test-mail/junk @@ -178,9 +172,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> TESTSUITE/test-mail/junk <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to TESTSUITE/test-mail/junk transport=t1 @@ -311,9 +302,6 @@ body_linecount=0 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: charlie@dom1.ain - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: charlie@dom1.ain @@ -377,9 +365,6 @@ r1 router generated TESTSUITE/test-mail/junk routed by r1 router envelope to: charlie@dom1.ain transport: - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: TESTSUITE/test-mail/junk @@ -395,9 +380,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> TESTSUITE/test-mail/junk <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to TESTSUITE/test-mail/junk transport=t1 diff --git a/test/stderr/0404 b/test/stderr/0404 index e1dbb4656..b3b91e227 100644 --- a/test/stderr/0404 +++ b/test/stderr/0404 @@ -173,9 +173,6 @@ body_linecount=0 message_linecount=160 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -218,9 +215,6 @@ r2 router generated >sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex routed by r2 router envelope to: userx@test.ex transport: - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: >sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex, ... @@ -236,9 +230,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> >sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex, ... <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to >sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex, ... <>sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex,sender@test.ex, ...> transport=t1 @@ -2762,9 +2753,6 @@ Delivery address list: sender@test.ex sender@test.ex sender@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: sender@test.ex @@ -19191,9 +19179,6 @@ sender@test.ex is a duplicate address: discarded sender@test.ex is a duplicate address: discarded >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> sender@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to sender transport=t2 diff --git a/test/stderr/0408 b/test/stderr/0408 index 6666f2209..38c348765 100644 --- a/test/stderr/0408 +++ b/test/stderr/0408 @@ -72,9 +72,6 @@ body_linecount=0 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -140,9 +137,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to userx transport=t1 diff --git a/test/stderr/0432 b/test/stderr/0432 index 162877b7a..b6629f893 100644 --- a/test/stderr/0432 +++ b/test/stderr/0432 @@ -93,16 +93,17 @@ get[host|ipnode]byname[2] looked up these IP addresses: name=127.0.0.1 address=127.0.0.1 Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR + hintsdb_open(flags 0x2 mode 0640) No such file or directory + returned from EXIM_DBOPEN: (nil) + TESTSUITE/spool/db/callout appears not to exist: trying to create + EXIM_DBOPEN: file dir flags=O_RDWR|O_CREAT returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT - dbfn_read: key=y - dbfn_read: null return - callout cache: no domain record found for y - dbfn_read: key=x@y - dbfn_read: null return - callout cache: no address record found for x@y - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database +dbfn_read: key=y +dbfn_read: null return +callout cache: no domain record found for y +dbfn_read: key=x@y +dbfn_read: null return +callout cache: no address record found for x@y interface=NULL port=PORT_S Connecting to 127.0.0.1 [127.0.0.1]:PORT_S ... 127.0.0.1 in hosts_try_fastopen? @@ -130,14 +131,11 @@ cmd buf flush ddd bytes cmdlog: '220:EHLO:250:MAIL:250:RCPT:250:QUIT:220' EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT - dbfn_write: key=y datalen nn - wrote callout cache domain record for y: - result=1 postmaster=0 random=0 - dbfn_write: key=x@y datalen nn - wrote positive callout cache address record for x@y - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database +dbfn_write: key=y datalen nn +wrote callout cache domain record for y: + result=1 postmaster=0 random=0 +dbfn_write: key=x@y datalen nn +wrote positive callout cache address record for x@y ----------- end verify ------------ sender x@y verified ok accept: condition test succeeded in ACL "mail" @@ -216,16 +214,13 @@ get[host|ipnode]byname[2] looked up these IP addresses: Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT - dbfn_read: key=y - dbfn_read: size nnn return - callout cache: found domain record for y - dbfn_read: key=x@y - dbfn_read: size nnn return - callout cache: found address record for x@y - callout cache: address record is positive - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database +dbfn_read: key=y +dbfn_read: size nnn return +callout cache: found domain record for y +dbfn_read: key=x@y +dbfn_read: size nnn return +callout cache: found address record for x@y +callout cache: address record is positive ----------- end verify ------------ sender x@y verified ok accept: condition test succeeded in ACL "mail" diff --git a/test/stderr/0450 b/test/stderr/0450 index 75b2e88ff..dec7fe0ac 100644 --- a/test/stderr/0450 +++ b/test/stderr/0450 @@ -49,8 +49,8 @@ t1 transport entered using the transport's hosts: 127.0.0.1 getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record 127.0.0.1 [127.0.0.1]:1112 retry-status = usable delivering 10HmaX-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (userx@test.ex) Connecting to 127.0.0.1 [127.0.0.1]:PORT_D2 ... diff --git a/test/stderr/0476 b/test/stderr/0476 index e83c006cb..3a321a727 100644 --- a/test/stderr/0476 +++ b/test/stderr/0476 @@ -125,7 +125,7 @@ t1 transport entered hostlist: '127.0.0.1' IP 127.0.0.1 port -1 checking retry status of 127.0.0.1 -no message retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = unusable all IP addresses skipped or deferred at least one address updating wait-t1 database diff --git a/test/stderr/0487 b/test/stderr/0487 index 3b692c2c5..868741f5b 100644 --- a/test/stderr/0487 +++ b/test/stderr/0487 @@ -106,9 +106,6 @@ body_linecount=1 message_linecount=9 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -142,9 +139,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to userx transport=t1 diff --git a/test/stderr/0512 b/test/stderr/0512 index e7fe36f86..1d4a61b53 100644 --- a/test/stderr/0512 +++ b/test/stderr/0512 @@ -14,7 +14,7 @@ t1 transport entered using the transport's hosts: 127.0.0.1 : 127.0.0.1 : 127.0.0.1 : 127.0.0.1 getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no message retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmaX-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (userx@myhost.test.ex) hosts_max_try limit reached with this host @@ -28,7 +28,7 @@ temporary delivery error(s) override hosts_max_try (message older than host's re Clearing TFO as not first host for message getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no message retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmaX-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (userx@myhost.test.ex) hosts_max_try limit reached with this host @@ -42,7 +42,7 @@ temporary delivery error(s) override hosts_max_try (message older than host's re Clearing TFO as not first host for message getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no message retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmaX-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (userx@myhost.test.ex) hosts_max_try limit reached with this host @@ -56,7 +56,7 @@ temporary delivery error(s) override hosts_max_try (message older than host's re Clearing TFO as not first host for message getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no message retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmaX-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (userx@myhost.test.ex) hosts_max_try limit reached with this host @@ -119,7 +119,7 @@ t1 transport entered using the transport's hosts: 127.0.0.1 : 127.0.0.1 : 127.0.0.1 : 127.0.0.1 getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no message retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmaZ-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (userx@myhost.test.ex) hosts_max_try limit reached with this host @@ -133,7 +133,7 @@ temporary delivery error(s) override hosts_max_try (message older than host's re Clearing TFO as not first host for message getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no message retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmaZ-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (userx@myhost.test.ex) hosts_max_try limit reached with this host diff --git a/test/stderr/0554 b/test/stderr/0554 index f9bbb7dd0..d8ee0171a 100644 --- a/test/stderr/0554 +++ b/test/stderr/0554 @@ -17,7 +17,7 @@ After routing: Failed addresses: Deferred addresses: checking retry status of 127.0.0.1 -no retry data available + no retry data available added retry item for R:x@y:: errno=-44 more_errno=dd,A flags=0 cmdlog: '220:EHLO:250:MAIL:250:RCPT:451:QUIT+:250' >>>>>>>>>>>>>>>> Exim pid=p1235 (transport) terminating with rc=0 >>>>>>>>>>>>>>>> @@ -58,8 +58,8 @@ After routing: Failed addresses: Deferred addresses: checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record added retry item for R:x@y:: errno=dd more_errno=dd,A flags=1 added retry item for R:x@y: errno=dd more_errno=dd,A flags=1 cmdlog: '220:EHLO:250:MAIL:250:RCPT:250:DATA:354:.:250:QUIT+:250' diff --git a/test/stderr/0623 b/test/stderr/0623 index 3786f7168..659aa892c 100644 --- a/test/stderr/0623 +++ b/test/stderr/0623 @@ -85,8 +85,8 @@ send_to_server transport entered using the transport's hosts: 127.0.0.1 getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmbA-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (permreject@test.ex) Connecting to 127.0.0.1 [127.0.0.1]:PORT_D ... @@ -155,8 +155,8 @@ send_to_server transport entered using the transport's hosts: 127.0.0.1 getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmbB-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (permreject@test.ex) Connecting to 127.0.0.1 [127.0.0.1]:PORT_D ... diff --git a/test/stderr/0628 b/test/stderr/0628 index 219218484..225347acc 100644 --- a/test/stderr/0628 +++ b/test/stderr/0628 @@ -53,9 +53,6 @@ 01:01:01 p1239 DSN: set orcpt: flags: 0x0 01:01:01 p1239 Delivery address list: 01:01:01 p1239 dest@test.ex -01:01:01 p1239 EXIM_DBOPEN: file dir flags=O_RDONLY -01:01:01 p1239 returned from EXIM_DBOPEN: (nil) -01:01:01 p1239 failed to open DB file TESTSUITE/spool/db/retry: No such file or directory 01:01:01 p1239 no retry data available 01:01:01 p1239 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 01:01:01 p1239 Considering: dest@test.ex @@ -158,9 +155,6 @@ 01:01:01 p1241 DSN: set orcpt: flags: 0x0 01:01:01 p1241 Delivery address list: 01:01:01 p1241 dest2@test.ex -01:01:01 p1241 EXIM_DBOPEN: file dir flags=O_RDONLY -01:01:01 p1241 returned from EXIM_DBOPEN: (nil) -01:01:01 p1241 failed to open DB file TESTSUITE/spool/db/retry: No such file or directory 01:01:01 p1241 no retry data available 01:01:01 p1241 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 01:01:01 p1241 Considering: dest2@test.ex diff --git a/test/stderr/0909 b/test/stderr/0909 index 3ba13b3b0..ffaf71b8c 100644 --- a/test/stderr/0909 +++ b/test/stderr/0909 @@ -232,8 +232,8 @@ send_to_server transport entered using the transport's hosts: 127.0.0.1 getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmbA-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (permreject@test.ex) Connecting to 127.0.0.1 [127.0.0.1]:PORT_D ... @@ -306,8 +306,8 @@ send_to_server transport entered using the transport's hosts: 127.0.0.1 getting address for 127.0.0.1 checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmbB-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (dataloss@test.ex) Connecting to 127.0.0.1 [127.0.0.1]:PORT_D ... diff --git a/test/stderr/2600 b/test/stderr/2600 index b7b55388c..dee2ef5c7 100644 --- a/test/stderr/2600 +++ b/test/stderr/2600 @@ -586,9 +586,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@myhost.test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@myhost.test.ex @@ -633,9 +630,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@myhost.test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to userx transport=t1 diff --git a/test/stderr/2610 b/test/stderr/2610 index a4a46c552..93c24bf58 100644 --- a/test/stderr/2610 +++ b/test/stderr/2610 @@ -808,9 +808,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: ph10@myhost.test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: ph10@myhost.test.ex @@ -876,9 +873,6 @@ search_tidyup called close MYSQL connection: 127.0.0.1:PORT_N/test/root >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> ph10@myhost.test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to ph10 transport=t1 diff --git a/test/stderr/2620 b/test/stderr/2620 index 40fc08f8a..7193592a9 100644 --- a/test/stderr/2620 +++ b/test/stderr/2620 @@ -727,9 +727,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: CALLER@myhost.test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: CALLER@myhost.test.ex @@ -776,9 +773,6 @@ search_tidyup called close PGSQL connection: localhost:PORT_N/test/CALLER >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> CALLER@myhost.test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to CALLER transport=t1 diff --git a/test/stderr/4052 b/test/stderr/4052 index f90265149..31baec047 100644 --- a/test/stderr/4052 +++ b/test/stderr/4052 @@ -17,8 +17,8 @@ smtp transport entered hostlist: '127.0.0.1' IP 127.0.0.1 port PORT_D checking retry status of 127.0.0.1 -no host retry record -no message retry record + no host retry record + no message retry record 127.0.0.1 [127.0.0.1]:1111 retry-status = usable delivering 10HmbP-000000005vi-0000 to 127.0.0.1 [127.0.0.1] (extchange@test.ex) Transport port=25 replaced by host-specific port=PORT_D diff --git a/test/stderr/5004 b/test/stderr/5004 index bf1ed20db..fdeed81ac 100644 --- a/test/stderr/5004 +++ b/test/stderr/5004 @@ -76,9 +76,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -113,9 +110,6 @@ r1 router generated TESTSUITE/test-mail routed by r1 router envelope to: userx@test.ex transport: - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: TESTSUITE/test-mail @@ -131,9 +125,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> TESTSUITE/test-mail <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to TESTSUITE/test-mail transport=t1 diff --git a/test/stderr/5005 b/test/stderr/5005 index 2e1c3b08d..9f3d8c172 100644 --- a/test/stderr/5005 +++ b/test/stderr/5005 @@ -72,9 +72,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: nofile@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: nofile@test.ex @@ -108,9 +105,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> nofile@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to nofile transport=t1 @@ -262,9 +256,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -298,9 +289,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to userx transport=t1 @@ -454,9 +442,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -490,9 +475,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to userx transport=t1 @@ -550,26 +532,21 @@ Processing retry items Failed addresses: Deferred addresses: userx@test.ex - ╎EXIM_DBOPEN: file dir flags=O_RDWR - ╎returned from EXIM_DBOPEN: 0xAAAAAAAA - ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR|O_CREAT - ╎userx@test.ex in "*"? + userx@test.ex in "*"? + ╎list element: * + ╎address match test: subject=userx@test.ex pattern=* + ╎test.ex in "*"? ╎ list element: * - ╎ address match test: subject=userx@test.ex pattern=* - ╎ test.ex in "*"? - ╎ list element: * - ╎ test.ex in "*"? yes (matched "*") - ╎ userx@test.ex in "*"? yes (matched "*") - ╎retry for T:userx@test.ex = * 0 0 - ╎dbfn_read: key=T:userx@test.ex - ╎dbfn_read: null return - ╎failing_interval=ttt message_age=ttt - ╎Writing retry data for T:userx@test.ex - ╎ first failed=dddd last try=dddd next try=+86400 expired=0 - ╎ errno=-22 more_errno=dd mailbox is full (MTA-imposed quota exceeded while writing to tmp/MAILDIR.myhost.test.ex) - ╎dbfn_write: key=T:userx@test.ex datalen nn - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database + ╎ test.ex in "*"? yes (matched "*") + ╎userx@test.ex in "*"? yes (matched "*") + retry for T:userx@test.ex = * 0 0 + dbfn_read: key=T:userx@test.ex + dbfn_read: null return + failing_interval=ttt message_age=ttt + Writing retry data for T:userx@test.ex + first failed=dddd last try=dddd next try=+86400 expired=0 + errno=-22 more_errno=dd mailbox is full (MTA-imposed quota exceeded while writing to tmp/MAILDIR.myhost.test.ex) + dbfn_write: key=T:userx@test.ex datalen nn end of retry processing delivery deferred: update_spool=1 header_rewritten=0 Writing spool header file: TESTSUITE/spool//input//hdr.10HmaZ-000000005vi-0000 @@ -655,24 +632,19 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/retry: flags=O_RDONLY >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex unique = userx@test.ex - checking router retry status - dbfn_read: key=R:test.ex - dbfn_read: null return - dbfn_read: key=R:userx@test.ex - dbfn_read: null return - dbfn_read: key=R:userx@test.ex: - dbfn_read: null return - no domain retry record - no address retry record +checking router retry status + dbfn_read: key=R:test.ex + dbfn_read: null return + dbfn_read: key=R:userx@test.ex + dbfn_read: null return + dbfn_read: key=R:userx@test.ex: + dbfn_read: null return + no domain retry record + no address retry record userx@test.ex: queued for routing - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> routing userx@test.ex --------> r1 router <-------- @@ -698,15 +670,10 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/retry: flags=O_RDONLY - dbfn_read: key=T:userx@test.ex - dbfn_read: size nnn return +dbfn_read: key=T:userx@test.ex +dbfn_read: size nnn return retry record exists: age=ttt (max 1w) time to retry = tttt expired = 0 - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database search_tidyup called changed uid/gid: local delivery to userx transport=t1 uid=CALLER_UID gid=CALLER_GID pid=p1245 @@ -750,26 +717,21 @@ Processing retry items Failed addresses: Deferred addresses: userx@test.ex - ╎EXIM_DBOPEN: file dir flags=O_RDWR - ╎returned from EXIM_DBOPEN: 0xAAAAAAAA - ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR|O_CREAT - ╎userx@test.ex in "*"? + userx@test.ex in "*"? + ╎list element: * + ╎address match test: subject=userx@test.ex pattern=* + ╎test.ex in "*"? ╎ list element: * - ╎ address match test: subject=userx@test.ex pattern=* - ╎ test.ex in "*"? - ╎ list element: * - ╎ test.ex in "*"? yes (matched "*") - ╎ userx@test.ex in "*"? yes (matched "*") - ╎retry for T:userx@test.ex = * 0 0 - ╎dbfn_read: key=T:userx@test.ex - ╎dbfn_read: size nnn return - ╎failing_interval=ttt message_age=ttt - ╎Writing retry data for T:userx@test.ex - ╎ first failed=dddd last try=dddd next try=+86400 expired=0 - ╎ errno=-22 more_errno=dd mailbox is full (MTA-imposed quota exceeded while writing to tmp/MAILDIR.myhost.test.ex) - ╎dbfn_write: key=T:userx@test.ex datalen nn - EXIM_DBCLOSE(0xAAAAAAAA) - closed hints database + ╎ test.ex in "*"? yes (matched "*") + ╎userx@test.ex in "*"? yes (matched "*") + retry for T:userx@test.ex = * 0 0 + dbfn_read: key=T:userx@test.ex + dbfn_read: size nnn return + failing_interval=ttt message_age=ttt + Writing retry data for T:userx@test.ex + first failed=dddd last try=dddd next try=+86400 expired=0 + errno=-22 more_errno=dd mailbox is full (MTA-imposed quota exceeded while writing to tmp/MAILDIR.myhost.test.ex) + dbfn_write: key=T:userx@test.ex datalen nn end of retry processing delivery deferred: update_spool=1 header_rewritten=0 Writing spool header file: TESTSUITE/spool//input//hdr.10HmbA-000000005vi-0000 diff --git a/test/stderr/5006 b/test/stderr/5006 index f13b5b879..d9e4556ef 100644 --- a/test/stderr/5006 +++ b/test/stderr/5006 @@ -72,9 +72,6 @@ body_linecount=1 message_linecount=8 DSN: set orcpt: flags: 0x0 Delivery address list: userx@test.ex - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Considering: userx@test.ex @@ -108,9 +105,6 @@ After routing: search_tidyup called >>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>> --------> userx@test.ex <-------- - EXIM_DBOPEN: file dir flags=O_RDONLY - returned from EXIM_DBOPEN: (nil) - failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available search_tidyup called changed uid/gid: local delivery to userx transport=t1 -- 2.30.2