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.
This commit is contained in:
		
							parent
							
								
									5f265ad7da
								
							
						
					
					
						commit
						74c78c70b9
					
				
					 4 changed files with 42 additions and 18 deletions
				
			
		|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 ); | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
| 		} | ||||
|  |  | |||
							
								
								
									
										11
									
								
								src/main.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								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; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue