From 74c78c70b973f95d4e9150e4da8284c01aa22b69 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sun, 4 Jan 2015 00:39:06 +0100 Subject: [PATCH] deal sensibly with permanent errors don't retry dead Stores for every Channel. this also introduces a state for transient errors (specifically, connect failures), but this is currently unused. --- src/driver.h | 5 +++++ src/drv_imap.c | 39 +++++++++++++++++++++++---------------- src/drv_maildir.c | 5 ++++- src/main.c | 11 ++++++++++- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/driver.h b/src/driver.h index 9416686..e79a096 100644 --- a/src/driver.h +++ b/src/driver.h @@ -27,6 +27,10 @@ typedef struct driver driver_t; +#define FAIL_TEMP 0 /* Retry immediately (also: no error) */ +#define FAIL_WAIT 1 /* Retry after some time (if at all) */ +#define FAIL_FINAL 2 /* Don't retry until store reconfiguration */ + typedef struct store_conf { struct store_conf *next; char *name; @@ -37,6 +41,7 @@ typedef struct store_conf { const char *trash; uint max_size; /* off_t is overkill */ char trash_remote_new, trash_only_new; + char failed; } store_conf_t; /* For message->flags */ diff --git a/src/drv_imap.c b/src/drv_imap.c index b9505dd..447bc6e 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1508,7 +1508,13 @@ static void imap_open_store_finalize( imap_store_t * ); #ifdef HAVE_LIBSSL static void imap_open_store_ssl_bail( imap_store_t * ); #endif -static void imap_open_store_bail( imap_store_t * ); +static void imap_open_store_bail( imap_store_t *, int ); + +static void +imap_open_store_bad( void *aux ) +{ + imap_open_store_bail( (imap_store_t *)aux, FAIL_TEMP ); +} static void imap_open_store( store_conf_t *conf, const char *label, @@ -1540,7 +1546,7 @@ imap_open_store( store_conf_t *conf, const char *label, ctx->delimiter = 0; ctx->callbacks.imap_open = cb; ctx->callback_aux = aux; - set_bad_callback( &ctx->gen, (void (*)(void *))imap_open_store_bail, ctx ); + set_bad_callback( &ctx->gen, imap_open_store_bad, ctx ); imap_open_store_namespace( ctx ); return; } @@ -1551,7 +1557,7 @@ imap_open_store( store_conf_t *conf, const char *label, ctx->ref_count = 1; ctx->callbacks.imap_open = cb; ctx->callback_aux = aux; - set_bad_callback( &ctx->gen, (void (*)(void *))imap_open_store_bail, ctx ); + set_bad_callback( &ctx->gen, imap_open_store_bad, ctx ); ctx->in_progress_append = &ctx->in_progress; ctx->pending_append = &ctx->pending; @@ -1571,7 +1577,7 @@ imap_open_store_connected( int ok, void *aux ) #endif if (!ok) - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_WAIT ); #ifdef HAVE_LIBSSL else if (srvc->ssl_type == SSL_IMAPS) socket_start_tls( &ctx->conn, imap_open_store_tlsstarted1 ); @@ -1602,7 +1608,7 @@ static void imap_open_store_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) imap_open_store_authenticate( ctx ); } @@ -1623,7 +1629,7 @@ imap_open_store_authenticate( imap_store_t *ctx ) return; } else { error( "IMAP error: SSL support not available\n" ); - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); return; } } @@ -1633,7 +1639,7 @@ imap_open_store_authenticate( imap_store_t *ctx ) #ifdef HAVE_LIBSSL if (srvc->ssl_type == SSL_STARTTLS) { error( "IMAP error: SSL support not available\n" ); - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); return; } #endif @@ -1646,7 +1652,7 @@ static void imap_open_store_authenticate_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) socket_start_tls( &ctx->conn, imap_open_store_tlsstarted2 ); } @@ -1666,7 +1672,7 @@ static void imap_open_store_authenticate_p3( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) imap_open_store_authenticate2( ctx ); } @@ -1872,7 +1878,7 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char * return socket_write( &ctx->conn, iov, iovcnt ); bail: - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); return -1; } @@ -1996,14 +2002,14 @@ imap_open_store_authenticate2( imap_store_t *ctx ) error( "IMAP error: server supports no acceptable authentication mechanism\n" ); bail: - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); } static void imap_open_store_authenticate2_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) imap_open_store_namespace( ctx ); } @@ -2030,7 +2036,7 @@ static void imap_open_store_namespace_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) { - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); } else if (response == RESP_OK) { ctx->got_namespace = 1; imap_open_store_namespace2( ctx ); @@ -2061,7 +2067,7 @@ imap_open_store_namespace2( imap_store_t *ctx ) #endif imap_open_store_finalize( ctx ); } else { - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); } } @@ -2095,15 +2101,16 @@ imap_open_store_ssl_bail( imap_store_t *ctx ) { /* This avoids that we try to send LOGOUT to an unusable socket. */ socket_close( &ctx->conn ); - imap_open_store_bail( ctx ); + imap_open_store_bail( ctx, FAIL_FINAL ); } #endif static void -imap_open_store_bail( imap_store_t *ctx ) +imap_open_store_bail( imap_store_t *ctx, int failed ) { void (*cb)( store_t *srv, void *aux ) = ctx->callbacks.imap_open; void *aux = ctx->callback_aux; + ctx->gen.conf->failed = failed; imap_cancel_store( &ctx->gen ); cb( 0, aux ); } diff --git a/src/drv_maildir.c b/src/drv_maildir.c index 85313df..f6fa0c5 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -126,16 +126,18 @@ maildir_join_path( const char *prefix, const char *box ) } static int -maildir_validate_path( const store_conf_t *conf ) +maildir_validate_path( store_conf_t *conf ) { struct stat st; if (!conf->path) { error( "Maildir error: store '%s' has no Path\n", conf->name ); + conf->failed = FAIL_FINAL; return -1; } if (stat( conf->path, &st ) || !S_ISDIR(st.st_mode)) { error( "Maildir error: cannot open store '%s'\n", conf->path ); + conf->failed = FAIL_FINAL; return -1; } return 0; @@ -414,6 +416,7 @@ maildir_validate( const char *box, int create, maildir_store_t *ctx ) return DRV_BOX_BAD; if (make_box_dir( buf, bl )) { sys_error( "Maildir error: cannot create mailbox '%s'", box ); + ctx->gen.conf->failed = FAIL_FINAL; maildir_invoke_bad_callback( &ctx->gen ); return DRV_CANCELED; } diff --git a/src/main.c b/src/main.c index 6c0b822..beb6059 100644 --- a/src/main.c +++ b/src/main.c @@ -601,9 +601,17 @@ sync_chans( main_vars_t *mvars, int ent ) merge_actions( mvars->chan, mvars->ops, XOP_HAVE_REMOVE, OP_REMOVE, 0 ); merge_actions( mvars->chan, mvars->ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 ); - mvars->state[M] = mvars->state[S] = ST_FRESH; info( "Channel %s\n", mvars->chan->name ); mvars->skip = mvars->cben = 0; + for (t = 0; t < 2; t++) { + if (mvars->chan->stores[t]->failed != FAIL_TEMP) { + info( "Skipping due to failed %s store %s.\n", str_ms[t], mvars->chan->stores[t]->name ); + mvars->skip = 1; + } + } + if (mvars->skip) + goto next2; + mvars->state[M] = mvars->state[S] = ST_FRESH; if (mvars->chan->stores[M]->driver->flags & mvars->chan->stores[S]->driver->flags & DRV_VERBOSE) labels[M] = "M: ", labels[S] = "S: "; else @@ -694,6 +702,7 @@ sync_chans( main_vars_t *mvars, int ent ) free_string_list( mvars->cboxes ); free_string_list( mvars->boxes[M] ); free_string_list( mvars->boxes[S] ); + next2: if (mvars->all) { if (!(mvars->chan = mvars->chan->next)) break;