Jelajahi Sumber

split out drv->load() from drv->select()

Oswald Buddenhagen 14 tahun lalu
induk
melakukan
05fd0b9970
4 mengubah file dengan 121 tambahan dan 85 penghapusan
  1. 15 14
      src/drv_imap.c
  2. 40 32
      src/drv_maildir.c
  3. 4 4
      src/isync.h
  4. 62 35
      src/sync.c

+ 15 - 14
src/drv_imap.c

@@ -1541,13 +1541,6 @@ imap_open_store( store_conf_t *conf,
 	cb( 0, aux );
 }
 
-static void
-imap_prepare_paths( store_t *gctx )
-{
-	free_generic_messages( gctx->msgs );
-	gctx->msgs = 0;
-}
-
 static void
 imap_prepare_opts( store_t *gctx, int opts )
 {
@@ -1555,15 +1548,15 @@ imap_prepare_opts( store_t *gctx, int opts )
 }
 
 static void
-imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
+imap_select( store_t *gctx, int create,
              void (*cb)( int sts, void *aux ), void *aux )
 {
 	imap_store_t *ctx = (imap_store_t *)gctx;
 	struct imap_cmd *cmd = new_imap_cmd();
 	const char *prefix;
-	int ret, i, j, bl;
-	char buf[1000];
 
+	free_generic_messages( gctx->msgs );
+	gctx->msgs = 0;
 
 	if (!strcmp( gctx->name, "INBOX" )) {
 		prefix = "";
@@ -1573,10 +1566,18 @@ imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
 
 	ctx->uidnext = -1;
 
-	cmd->param.create = (gctx->opts & OPEN_CREATE) != 0;
+	cmd->param.create = create;
 	cmd->param.trycreate = 1;
-	if ((ret = imap_exec_b( ctx, cmd, "SELECT \"%s%s\"", prefix, gctx->name )) != DRV_OK)
-		goto bail;
+	cb( imap_exec_b( ctx, cmd, "SELECT \"%s%s\"", prefix, gctx->name ), aux );
+}
+
+static void
+imap_load( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
+           void (*cb)( int sts, void *aux ), void *aux )
+{
+	imap_store_t *ctx = (imap_store_t *)gctx;
+	int ret, i, j, bl;
+	char buf[1000];
 
 	if (gctx->count) {
 		ctx->msgapp = &gctx->msgs;
@@ -1907,9 +1908,9 @@ struct driver imap_driver = {
 	imap_own_store,
 	imap_cancel_store,
 	imap_list,
-	imap_prepare_paths,
 	imap_prepare_opts,
 	imap_select,
+	imap_load,
 	imap_fetch_msg,
 	imap_store_msg,
 	imap_find_msg,

+ 40 - 32
src/drv_maildir.c

@@ -745,9 +745,12 @@ maildir_app_msg( maildir_store_t *ctx, message_t ***msgapp, msg_t *entry )
 }
 
 static void
-maildir_prepare_paths( store_t *gctx )
+maildir_select( store_t *gctx, int create,
+                void (*cb)( int sts, void *aux ), void *aux )
 {
 	maildir_store_t *ctx = (maildir_store_t *)gctx;
+	int ret;
+	char uvpath[_POSIX_PATH_MAX];
 
 	maildir_cleanup( gctx );
 	gctx->msgs = 0;
@@ -759,37 +762,8 @@ maildir_prepare_paths( store_t *gctx )
 		gctx->path = nfstrdup( ((maildir_store_conf_t *)gctx->conf)->inbox );
 	else
 		nfasprintf( &gctx->path, "%s%s", gctx->conf->path, gctx->name );
-}
-
-static void
-maildir_prepare_opts( store_t *gctx, int opts )
-{
-	if (opts & OPEN_SETFLAGS)
-		opts |= OPEN_OLD;
-	if (opts & OPEN_EXPUNGE)
-		opts |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS;
-	gctx->opts = opts;
-}
-
-static void
-maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
-                void (*cb)( int sts, void *aux ), void *aux )
-{
-	maildir_store_t *ctx = (maildir_store_t *)gctx;
-	message_t **msgapp;
-	msglist_t msglist;
-	int i;
-#ifdef USE_DB
-	int ret;
-#endif /* USE_DB */
-	char uvpath[_POSIX_PATH_MAX];
-
-	ctx->minuid = minuid;
-	ctx->maxuid = maxuid;
-	ctx->excs = nfrealloc( excs, nexcs * sizeof(int) );
-	ctx->nexcs = nexcs;
 
-	if ((ret = maildir_validate( gctx->path, "", ctx->gen.opts & OPEN_CREATE, ctx )) != DRV_OK) {
+	if ((ret = maildir_validate( gctx->path, "", create, ctx )) != DRV_OK) {
 		cb( ret, aux );
 		return;
 	}
@@ -854,9 +828,43 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
 			ctx->nuid = ((int *)value.data)[1];
 			ctx->uvok = 1;
 		}
+		cb( DRV_OK, aux );
+		return;
 	}
   fnok:
 #endif /* USE_DB */
+	if ((ret = maildir_uidval_lock( ctx )) != DRV_OK) {
+		cb( ret, aux );
+		return;
+	}
+	maildir_uidval_unlock( ctx );
+
+	cb( DRV_OK, aux );
+}
+
+static void
+maildir_prepare_opts( store_t *gctx, int opts )
+{
+	if (opts & OPEN_SETFLAGS)
+		opts |= OPEN_OLD;
+	if (opts & OPEN_EXPUNGE)
+		opts |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS;
+	gctx->opts = opts;
+}
+
+static void
+maildir_load( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
+              void (*cb)( int sts, void *aux ), void *aux )
+{
+	maildir_store_t *ctx = (maildir_store_t *)gctx;
+	message_t **msgapp;
+	msglist_t msglist;
+	int i;
+
+	ctx->minuid = minuid;
+	ctx->maxuid = maxuid;
+	ctx->excs = nfrealloc( excs, nexcs * sizeof(int) );
+	ctx->nexcs = nexcs;
 
 	if (maildir_scan( ctx, &msglist ) != DRV_OK) {
 		cb( DRV_BOX_BAD, aux );
@@ -1302,9 +1310,9 @@ struct driver maildir_driver = {
 	maildir_own_store,
 	maildir_disown_store, /* _cancel_, but it's the same */
 	maildir_list,
-	maildir_prepare_paths,
 	maildir_prepare_opts,
 	maildir_select,
+	maildir_load,
 	maildir_fetch_msg,
 	maildir_store_msg,
 	maildir_find_msg,

+ 4 - 4
src/isync.h

@@ -142,7 +142,6 @@ typedef struct message {
 #define OPEN_NEW        (1<<1)
 #define OPEN_FLAGS      (1<<2)
 #define OPEN_SIZE       (1<<3)
-#define OPEN_CREATE     (1<<4)
 #define OPEN_EXPUNGE    (1<<5)
 #define OPEN_SETFLAGS   (1<<6)
 #define OPEN_APPEND     (1<<7)
@@ -208,10 +207,11 @@ struct driver {
 	void (*cancel_store)( store_t *ctx );
 	void (*list)( store_t *ctx,
 	              void (*cb)( int sts, void *aux ), void *aux );
-	void (*prepare_paths)( store_t *ctx );
 	void (*prepare_opts)( store_t *ctx, int opts );
-	void (*select)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs,
-	                void (*cb)( int sts, void *aux ), void *aux );
+	void (*select)( store_t *ctx, int create,
+	               void (*cb)( int sts, void *aux ), void *aux );
+	void (*load)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs,
+	              void (*cb)( int sts, void *aux ), void *aux );
 	void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data,
 	                   void (*cb)( int sts, void *aux ), void *aux );
 	void (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash,

+ 62 - 35
src/sync.c

@@ -207,6 +207,7 @@ static int check_cancel( sync_vars_t *svars );
 #define ST_CLOSED          (1<<5)
 #define ST_SENT_CANCEL     (1<<6)
 #define ST_CANCELED        (1<<7)
+#define ST_SELECTED        (1<<8)
 
 #define ST_DID_EXPUNGE     (1<<16)
 
@@ -452,9 +453,13 @@ cancel_done( void *aux )
 
 	svars->state[t] |= ST_CANCELED;
 	if (svars->state[1-t] & ST_CANCELED) {
-		Fclose( svars->nfp );
-		Fclose( svars->jfp );
-		sync_bail( svars );
+		if (svars->lfd) {
+			Fclose( svars->nfp );
+			Fclose( svars->jfp );
+			sync_bail( svars );
+		} else {
+			sync_bail2( svars );
+		}
 	}
 }
 
@@ -537,21 +542,14 @@ clean_strdup( const char *s )
 
 #define JOURNAL_VERSION "2"
 
-static int select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs );
+static void box_selected( int sts, void *aux );
 
 void
 sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
             void (*cb)( int sts, void *aux ), void *aux )
 {
 	sync_vars_t *svars;
-	sync_rec_t *srec, *nsrec;
-	char *s, *cmname, *csname;
-	FILE *jfp;
-	int opts[2], line, t1, t2, t3, t;
-	struct stat st;
-	struct flock lck;
-	char fbuf[16]; /* enlarge when support for keywords is added */
-	char buf[64];
+	int t;
 
 	svars = nfcalloc( sizeof(*svars) );
 	svars->t[1] = 1;
@@ -571,15 +569,44 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
 		ctx[t]->uidvalidity = -1;
 		set_bad_callback( ctx[t], store_bad, AUX );
 		svars->drv[t] = ctx[t]->conf->driver;
-		svars->drv[t]->prepare_paths( ctx[t] );
+		info( "Selecting %s %s...\n", str_ms[t], ctx[t]->name );
+		DRIVER_CALL(select( ctx[t], (chan->ops[t] & OP_CREATE) != 0, box_selected, AUX ));
 	}
+}
+
+static int load_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs );
 
+static void
+box_selected( int sts, void *aux )
+{
+	DECL_SVARS;
+	sync_rec_t *srec, *nsrec;
+	char *s, *cmname, *csname;
+	store_t *ctx[2];
+	channel_conf_t *chan;
+	FILE *jfp;
+	int opts[2], line, t1, t2, t3;
+	struct stat st;
+	struct flock lck;
+	char fbuf[16]; /* enlarge when support for keywords is added */
+	char buf[64];
+
+	if (check_ret( sts, aux ))
+		return;
+	INIT_SVARS(aux);
+	ctx[0] = svars->ctx[0];
+	ctx[1] = svars->ctx[1];
+	svars->state[t] |= ST_SELECTED;
+	if (!(svars->state[1-t] & ST_SELECTED))
+		return;
+
+	chan = svars->chan;
 	if (!strcmp( chan->sync_state ? chan->sync_state : global_sync_state, "*" )) {
 		if (!ctx[S]->path) {
 			error( "Error: store '%s' does not support in-box sync state\n", chan->stores[S]->name );
 		  sbail:
-			free( svars );
-			cb( SYNC_BAD(S), aux );
+			svars->ret = SYNC_BAD(S);
+			sync_bail2( svars );
 			return;
 		}
 		nfasprintf( &svars->dname, "%s/." EXE "state", ctx[S]->path );
@@ -597,13 +624,11 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
 	}
 	if (!(s = strrchr( svars->dname, '/' ))) {
 		error( "Error: invalid SyncState '%s'\n", svars->dname );
-		free( svars->dname );
 		goto sbail;
 	}
 	*s = 0;
 	if (mkdir( svars->dname, 0700 ) && errno != EEXIST) {
 		error( "Error: cannot create SyncState directory '%s': %s\n", svars->dname, strerror(errno) );
-		free( svars->dname );
 		goto sbail;
 	}
 	*s = '/';
@@ -810,6 +835,17 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
 			goto bail;
 		}
 	}
+
+	t1 = 0;
+	for (t = 0; t < 2; t++)
+		if (svars->uidval[t] >= 0 && svars->uidval[t] != ctx[t]->uidvalidity) {
+			error( "Error: UIDVALIDITY of %s changed (got %d, expected %d)\n",
+			       str_ms[t], ctx[t]->uidvalidity, svars->uidval[t] );
+			t1++;
+		}
+	if (t1)
+		goto bail;
+
 	if (!(svars->nfp = fopen( svars->nname, "w" ))) {
 		error( "Error: cannot write new sync state %s\n", svars->nname );
 		goto bail;
@@ -851,8 +887,6 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
 			} else if (chan->stores[1-t]->trash && chan->stores[1-t]->trash_remote_new)
 				opts[t] |= OPEN_NEW|OPEN_FLAGS;
 		}
-		if (chan->ops[t] & OP_CREATE)
-			opts[t] |= OPEN_CREATE;
 	}
 	if ((chan->ops[S] & (OP_NEW|OP_RENEW)) && chan->max_messages)
 		opts[S] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS;
@@ -873,15 +907,15 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
 	svars->drv[S]->prepare_opts( ctx[S], opts[S] );
 
 	svars->find = line != 0;
-	if (!svars->smaxxuid && select_box( svars, M, (ctx[M]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 ))
+	if (!svars->smaxxuid && load_box( svars, M, (ctx[M]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 ))
 		return;
-	select_box( svars, S, (ctx[S]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 );
+	load_box( svars, S, (ctx[S]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 );
 }
 
-static void box_selected( int sts, void *aux );
+static void box_loaded( int sts, void *aux );
 
 static int
-select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs )
+load_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs )
 {
 	sync_rec_t *srec;
 	int maxwuid;
@@ -897,9 +931,9 @@ select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs )
 				maxwuid = srec->uid[t];
 	} else
 		maxwuid = 0;
-	info( "Selecting %s %s...\n", str_ms[t], svars->ctx[t]->name );
-	debug( maxwuid == INT_MAX ? "selecting %s [%d,inf]\n" : "selecting %s [%d,%d]\n", str_ms[t], minwuid, maxwuid );
-	DRIVER_CALL_RET(select( svars->ctx[t], minwuid, maxwuid, mexcs, nmexcs, box_selected, AUX ));
+	info( "Loading %s...\n", str_ms[t] );
+	debug( maxwuid == INT_MAX ? "loading %s [%d,inf]\n" : "loading %s [%d,%d]\n", str_ms[t], minwuid, maxwuid );
+	DRIVER_CALL_RET(load( svars->ctx[t], minwuid, maxwuid, mexcs, nmexcs, box_loaded, AUX ));
 }
 
 typedef struct {
@@ -911,19 +945,12 @@ static void msg_found_sel( int sts, int uid, void *aux );
 static void msgs_found_sel( sync_vars_t *svars, int t );
 
 static void
-box_selected( int sts, void *aux )
+box_loaded( int sts, void *aux )
 {
 	find_vars_t *fv;
 	sync_rec_t *srec;
 
 	SVARS_CHECK_RET;
-	if (svars->uidval[t] >= 0 && svars->uidval[t] != svars->ctx[t]->uidvalidity) {
-		error( "Error: UIDVALIDITY of %s changed (got %d, expected %d)\n",
-		         str_ms[t], svars->ctx[t]->uidvalidity, svars->uidval[t] );
-		svars->ret |= SYNC_FAIL;
-		cancel_sync( svars );
-		return;
-	}
 	info( "%s: %d messages, %d recent\n", str_ms[t], svars->ctx[t]->count, svars->ctx[t]->recent );
 
 	if (svars->find) {
@@ -1100,7 +1127,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
 		for (t = 0; t < nmexcs; t++)
 			debugn( " %d", mexcs[t] );
 		debug( "\n" );
-		select_box( svars, M, minwuid, mexcs, nmexcs );
+		load_box( svars, M, minwuid, mexcs, nmexcs );
 		return;
 	}