X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fretry.c;h=dbfd3cee85554b0195d8baf39eefd5fcc4fba3db;hb=ed72ace5f09d07c620b96efaf72d328d6e7439be;hp=5126e5344d4b889c564d0a448c14bf5d54b67177;hpb=6af56900ac77d083b8c3abc76bd808e6718412ee;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/retry.c b/src/src/retry.c index 5126e5344..dbfd3cee8 100644 --- a/src/src/retry.c +++ b/src/src/retry.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/retry.c,v 1.4 2005/09/19 11:56:11 ph10 Exp $ */ +/* $Cambridge: exim/src/src/retry.c,v 1.8 2006/02/16 16:37:57 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2006 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions concerned with retrying unsuccessful deliveries. */ @@ -46,8 +46,17 @@ if (retry != NULL && retry->rules != NULL) for (last_rule = retry->rules; last_rule->next != NULL; last_rule = last_rule->next); + DEBUG(D_transport|D_retry) + debug_printf("now=%d received_time=%d diff=%d timeout=%d\n", + (int)now, received_time, (int)(now - received_time), + last_rule->timeout); address_timeout = (now - received_time > last_rule->timeout); } +else + { + DEBUG(D_transport|D_retry) + debug_printf("no retry rule found: assume timed out\n"); + } return address_timeout; } @@ -340,23 +349,38 @@ retry_config * retry_find_config(uschar *key, uschar *alternate, int basic_errno, int more_errno) { -int replace; +int replace = 0; uschar *use_key, *use_alternate; uschar *colon = Ustrchr(key, ':'); retry_config *yield; -/* If there's a colon in the key, temporarily replace it with -a zero to terminate the string there. */ +/* If there's a colon in the key, there are two possibilities: + +(1) This is a key for a host, ip address, and possibly port, in the format + + hostname:ip+port + + In this case, we temporarily replace the colon with a zero, to terminate + the string after the host name. + +(2) This is a key for a pipe, file, or autoreply delivery, in the format + + pipe-or-file-or-auto:x@y + + where x@y is the original address that provoked the delivery. The pipe or + file or auto will start with | or / or >, whereas a host name will start + with a letter or a digit. In this case we want to use the original address + to search for a retry rule. */ if (colon != NULL) { - replace = ':'; - } -else - { - colon = key + Ustrlen(key); - replace = 0; + if (isalnum(*key)) + replace = ':'; + else + key = Ustrrchr(key, ':') + 1; /* Take from the last colon */ } + +if (replace == 0) colon = key + Ustrlen(key); *colon = 0; /* Sort out the keys */ @@ -619,10 +643,12 @@ for (i = 0; i < 3; i++) DEBUG(D_retry) { if ((rti->flags & rf_host) != 0) - debug_printf("retry for %s (%s) = %s\n", rti->key, - addr->domain, retry->pattern); + debug_printf("retry for %s (%s) = %s %d %d\n", rti->key, + addr->domain, retry->pattern, retry->basic_errno, + retry->more_errno); else - debug_printf("retry for %s = %s\n", rti->key, retry->pattern); + debug_printf("retry for %s = %s %d %d\n", rti->key, retry->pattern, + retry->basic_errno, retry->more_errno); } /* Set up the message for the database retry record. Because DBM @@ -658,6 +684,16 @@ for (i = 0; i < 3; i++) /* Compute how long this destination has been failing */ failing_interval = now - retry_record->first_failed; + DEBUG(D_retry) debug_printf("failing_interval=%d message_age=%d\n", + failing_interval, message_age); + + /* If the message has been on the queue longer than the recorded time + of failure, use the message's age instead. This can happen when some + messages can be delivered and others cannot; a successful delivery will + reset the first_failed time, and this can lead to a failing message + being retried too often. */ + + if (message_age > failing_interval) failing_interval = message_age; /* Search for the current retry rule. The cutoff time of the last rule is handled differently to the others. The rule continues @@ -712,7 +748,14 @@ for (i = 0; i < 3; i++) This implements "timeout this rule if EITHER the host (or routing or directing) has been failing for more than the maximum time, OR if the - message has been on the queue for more than the maximum time." */ + message has been on the queue for more than the maximum time." + + February 2006: It is possible that this code is no longer needed + following the change to the retry calculation to use the message age if + it is larger than the time since first failure. It may be that the + expired flag is always set when the other conditions are met. However, + this is a small bit of code, and it does no harm to leave it in place, + just in case. */ if (received_time <= retry_record->first_failed && addr == endaddr && !retry_record->expired && rule != NULL) @@ -755,7 +798,8 @@ for (i = 0; i < 3; i++) { next_try = now + rule->p1; if (next_gap > rule->p1) - next_try += random_number(next_gap - rule->p1); + next_try += random_number(next_gap - rule->p1)/2 + + (next_gap - rule->p1)/2; } } }