소스 검색

move whole responsibility for recycling open stores/server connections
to the drivers.

Oswald Buddenhagen 19 년 전
부모
커밋
7f9ece8e7e
4개의 변경된 파일87개의 추가작업 그리고 43개의 파일을 삭제
  1. 51 12
      src/drv_imap.c
  2. 18 7
      src/drv_maildir.c
  3. 6 2
      src/isync.h
  4. 12 22
      src/main.c

+ 51 - 12
src/drv_imap.c

@@ -1036,16 +1036,14 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
 }
 
 static void
-imap_close_store( store_t *gctx )
+imap_cancel_store( store_t *gctx )
 {
 	imap_store_t *ctx = (imap_store_t *)gctx;
 
 	free_generic_messages( gctx->msgs );
 	free_string_list( ctx->gen.boxes );
-	if (ctx->buf.sock.fd != -1) {
-		imap_exec( ctx, 0, "LOGOUT" );
+	if (ctx->buf.sock.fd >= 0)
 		close( ctx->buf.sock.fd );
-	}
 #ifdef HAVE_LIBSSL
 	if (ctx->SSLContext)
 		SSL_CTX_free( ctx->SSLContext );
@@ -1056,6 +1054,42 @@ imap_close_store( store_t *gctx )
 	free( ctx );
 }
 
+static store_t *unowned;
+
+static void
+imap_disown_store( store_t *gctx )
+{
+	free_generic_messages( gctx->msgs );
+	gctx->msgs = 0;
+	gctx->next = unowned;
+	unowned = gctx;
+}
+
+static store_t *
+imap_own_store( store_conf_t *conf )
+{
+	store_t *store, **storep;
+
+	for (storep = &unowned; (store = *storep); storep = &store->next)
+		if (store->conf == conf) {
+			*storep = store->next;
+			return store;
+		}
+	return 0;
+}
+
+static void
+imap_cleanup( void )
+{
+	store_t *ctx, *nctx;
+
+	for (ctx = unowned; ctx; ctx = nctx) {
+		nctx = ctx->next;
+		imap_exec( (imap_store_t *)ctx, 0, "LOGOUT" );
+		imap_cancel_store( ctx );
+	}
+}
+
 #ifdef HAVE_LIBSSL
 static int
 start_tls( imap_store_t *ctx )
@@ -1165,11 +1199,12 @@ do_cram_auth( imap_store_t *ctx, struct imap_cmd *cmdp, const char *prompt )
 #endif
 
 static store_t *
-imap_open_store( store_conf_t *conf, store_t *oldctx )
+imap_open_store( store_conf_t *conf )
 {
 	imap_store_conf_t *cfg = (imap_store_conf_t *)conf;
 	imap_server_conf_t *srvc = cfg->server;
-	imap_store_t *ctx = (imap_store_t *)oldctx;
+	imap_store_t *ctx;
+	store_t **ctxp;
 	char *arg, *rsp;
 	struct hostent *he;
 	struct sockaddr_in addr;
@@ -1178,16 +1213,17 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
 	int use_ssl;
 #endif
 
-	if (ctx) {
-		if (((imap_store_conf_t *)(ctx->gen.conf))->server == cfg->server) {
+	for (ctxp = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->gen.next)
+		if (((imap_store_conf_t *)ctx->gen.conf)->server == srvc) {
+			*ctxp = ctx->gen.next;
+			/* One could ping the server here, but given that the idle timeout
+			 * is at least 30 minutes, this sounds pretty pointless. */
 			free_string_list( ctx->gen.boxes );
 			ctx->gen.boxes = 0;
 			ctx->gen.listed = 0;
 			ctx->gen.conf = conf;
 			goto final;
 		}
-		imap_close_store( &ctx->gen );
-	}
 
 	ctx = nfcalloc( sizeof(*ctx) );
 	ctx->gen.conf = conf;
@@ -1372,7 +1408,7 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
 	return &ctx->gen;
 
   bail:
-	imap_close_store( &ctx->gen );
+	imap_cancel_store( &ctx->gen );
 	return 0;
 }
 
@@ -1739,8 +1775,11 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
 struct driver imap_driver = {
 	DRV_CRLF,
 	imap_parse_store,
+	imap_cleanup,
 	imap_open_store,
-	imap_close_store,
+	imap_disown_store,
+	imap_own_store,
+	imap_cancel_store,
 	imap_list,
 	imap_prepare_paths,
 	imap_prepare_opts,

+ 18 - 7
src/drv_maildir.c

@@ -93,16 +93,12 @@ maildir_parse_flags( const char *base )
 	return flags;
 }
 
-static void maildir_close_store( store_t *gctx );
-
 static store_t *
-maildir_open_store( store_conf_t *conf, store_t *oldctx )
+maildir_open_store( store_conf_t *conf )
 {
 	maildir_store_t *ctx;
 	struct stat st;
 
-	if (oldctx)
-		maildir_close_store( oldctx );
 	if (stat( conf->path, &st ) || !S_ISDIR(st.st_mode)) {
 		error( "Maildir error: cannot open store %s\n", conf->path );
 		return 0;
@@ -144,13 +140,25 @@ maildir_cleanup( store_t *gctx )
 }
 
 static void
-maildir_close_store( store_t *gctx )
+maildir_disown_store( store_t *gctx )
 {
 	maildir_cleanup( gctx );
 	free_string_list( gctx->boxes );
 	free( gctx );
 }
 
+static store_t *
+maildir_own_store( store_conf_t *conf )
+{
+	(void)conf;
+	return 0;
+}
+
+static void
+maildir_cleanup_drv( void )
+{
+}
+
 static int
 maildir_list( store_t *gctx )
 {
@@ -1226,8 +1234,11 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
 struct driver maildir_driver = {
 	0,
 	maildir_parse_store,
+	maildir_cleanup_drv,
 	maildir_open_store,
-	maildir_close_store,
+	maildir_disown_store,
+	maildir_own_store,
+	maildir_disown_store, /* _cancel_, but it's the same */
 	maildir_list,
 	maildir_prepare_paths,
 	maildir_prepare_opts,

+ 6 - 2
src/isync.h

@@ -143,6 +143,7 @@ typedef struct message {
 #define OPEN_FIND       (1<<8)
 
 typedef struct store {
+	struct store *next;
 	store_conf_t *conf; /* foreign */
 	string_list_t *boxes; /* _list results - own */
 	unsigned listed:1; /* was _list already run? */
@@ -176,8 +177,11 @@ typedef struct {
 struct driver {
 	int flags;
 	int (*parse_store)( conffile_t *cfg, store_conf_t **storep, int *err );
-	store_t *(*open_store)( store_conf_t *conf, store_t *oldctx );
-	void (*close_store)( store_t *ctx );
+	void (*cleanup)( void );
+	store_t *(*open_store)( store_conf_t *conf );
+	void (*disown_store)( store_t *ctx );
+	store_t *(*own_store)( store_conf_t *conf );
+	void (*cancel_store)( store_t *ctx );
 	int (*list)( store_t *ctx );
 	void (*prepare_paths)( store_t *ctx );
 	void (*prepare_opts)( store_t *ctx, int opts );

+ 12 - 22
src/main.c

@@ -190,7 +190,6 @@ int
 main( int argc, char **argv )
 {
 	channel_conf_t *chan;
-	store_conf_t *conf[2];
 	group_conf_t *group;
 	driver_t *driver[2];
 	store_t *ctx[2];
@@ -441,9 +440,6 @@ main( int argc, char **argv )
 	ret = 0;
 	chan = channels;
 	chanptr = 0;
-	ctx[M] = ctx[S] = 0;
-	conf[M] = conf[S] = 0;	/* make-gcc-happy */
-	driver[M] = driver[S] = 0;	/* make-gcc-happy */
 	if (all)
 		multiple = channels->next != 0;
 	else if (argv[oind + 1])
@@ -486,23 +482,15 @@ main( int argc, char **argv )
 		merge_actions( chan, ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 );
 
 		boxes[M] = boxes[S] = cboxes = 0;
-		/* possible todo: handle master <-> slave swaps */
 		for (t = 0; t < 2; t++) {
-			if (ctx[t]) {
-				if (conf[t] == chan->stores[t])
-					continue;
-				if (conf[t]->driver != chan->stores[t]->driver) {
-					driver[t]->close_store( ctx[t] );
-					ctx[t] = 0;
-				}
-			}
-			conf[t] = chan->stores[t];
-			driver[t] = conf[t]->driver;
-			if (!(ctx[t] = driver[t]->open_store( chan->stores[t], ctx[t] ))) {
+			driver[t] = chan->stores[t]->driver;
+			ctx[t] = driver[t]->own_store( chan->stores[t] );
+		}
+		for (t = 0; t < 2; t++)
+			if (!ctx[t] && !(ctx[t] = driver[t]->open_store( chan->stores[t] ))) {
 				ret = 1;
 				goto next;
 			}
-		}
 		info( "Channel %s\n", chan->name );
 		if (list && multiple)
 			printf( "%s:\n", chan->name );
@@ -523,7 +511,7 @@ main( int argc, char **argv )
 				if (!ctx[t]->listed) {
 					if (driver[t]->list( ctx[t] ) != DRV_OK) {
 					  screwt:
-						driver[t]->close_store( ctx[t] );
+						driver[t]->cancel_store( ctx[t] );
 						ctx[t] = 0;
 						ret = 1;
 						goto next;
@@ -584,6 +572,10 @@ main( int argc, char **argv )
 		free_string_list( cboxes );
 		free_string_list( boxes[M] );
 		free_string_list( boxes[S] );
+		if (ctx[M])
+			driver[M]->disown_store( ctx[M] );
+		if (ctx[S])
+			driver[S]->disown_store( ctx[S] );
 		if (all) {
 			if (!(chan = chan->next))
 				break;
@@ -595,10 +587,8 @@ main( int argc, char **argv )
 				break;
 		}
 	}
-	if (ctx[S])
-		driver[S]->close_store( ctx[S] );
-	if (ctx[M])
-		driver[M]->close_store( ctx[M] );
+	for (t = 0; t < N_DRIVERS; t++)
+		drivers[t]->cleanup();
 
 	return ret;
 }