-/* $Cambridge: exim/src/src/retry.c,v 1.3 2005/06/29 14:17:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/retry.c,v 1.6 2006/02/08 14:28:51 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. */
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;
}
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 */
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
if (rule == NULL) next_try = now; else
{
if (rule->rule == 'F') next_try = now + rule->p1;
- else /* assume rule = 'G' */
+ else /* rule = 'G' or 'H' */
{
int last_predicted_gap =
retry_record->next_try - retry_record->last_try;
int last_actual_gap = now - retry_record->last_try;
int lastgap = (last_predicted_gap < last_actual_gap)?
last_predicted_gap : last_actual_gap;
- next_try = now + ((lastgap < rule->p1)? rule->p1 :
- (lastgap * rule->p2)/1000);
+ int next_gap = (lastgap * rule->p2)/1000;
+ if (rule->rule == 'G')
+ {
+ next_try = now + ((lastgap < rule->p1)? rule->p1 : next_gap);
+ }
+ else /* The 'H' rule */
+ {
+ next_try = now + rule->p1;
+ if (next_gap > rule->p1)
+ next_try += random_number(next_gap - rule->p1);
+ }
}
}