commit bbe4567bce8ed964db8a52221ad28ae32b699176
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Fri Mar 24 19:24:30 2017 +0100

    let driver_t::openbox_box() return the UID validity
    
    ... and make 'uidvalidity' private to the drivers.

 src/driver.h      |  5 +----
 src/drv_imap.c    | 41 +++++++++++++++++++++++++++++------------
 src/drv_maildir.c | 20 ++++++++++----------
 src/sync.c        | 29 ++++++++++++++++-------------
 4 files changed, 56 insertions(+), 39 deletions(-)

diff --git a/src/driver.h b/src/driver.h
index 8907621..caf29c4 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -88,9 +88,6 @@ typedef struct message {
 typedef struct store {
        struct store *next;
        store_conf_t *conf; /* foreign */
-
-       /* currently open mailbox */
-       int uidvalidity;
 } store_t;
 
 typedef struct {
@@ -174,7 +171,7 @@ struct driver {
        /* Open the selected mailbox.
         * Note that this should not directly complain about failure to open. */
        void (*open_box)( store_t *ctx,
-                         void (*cb)( int sts, void *aux ), void *aux );
+                         void (*cb)( int sts, int uidvalidity, void *aux ), 
void *aux );
 
        /* Return the minimal UID the next stored message will have. */
        int (*get_uidnext)( store_t *ctx );
diff --git a/src/drv_imap.c b/src/drv_imap.c
index d6bd177..baba08d 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -112,7 +112,7 @@ struct imap_store {
        // note that the message counts do _not_ reflect stats from msgs,
        // but mailbox totals. also, don't trust them beyond the initial load.
        int total_msgs, recent_msgs;
-       int uidnext;
+       int uidvalidity, uidnext;
        message_t *msgs;
        message_t **msgapp; /* FETCH results */
        uint caps; /* CAPABILITY results */
@@ -1166,7 +1166,7 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, 
char *s )
                goto bad_resp;
        if (!strcmp( "UIDVALIDITY", arg )) {
                if (!(arg = next_arg( &s )) ||
-                   (ctx->gen.uidvalidity = strtoll( arg, &earg, 10 ), *earg))
+                   (ctx->uidvalidity = strtoll( arg, &earg, 10 ), *earg))
                {
                        error( "IMAP error: malformed UIDVALIDITY status\n" );
                        return RESP_CANCEL;
@@ -1186,7 +1186,7 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, 
char *s )
                error( "*** IMAP ALERT *** %s\n", p );
        } else if (cmd && !strcmp( "APPENDUID", arg )) {
                if (!(arg = next_arg( &s )) ||
-                   (ctx->gen.uidvalidity = strtoll( arg, &earg, 10 ), *earg) ||
+                   (ctx->uidvalidity = strtoll( arg, &earg, 10 ), *earg) ||
                    !(arg = next_arg( &s )) ||
                    !(((imap_cmd_out_uid_t *)cmd)->out_uid = atoi( arg )))
                {
@@ -2340,25 +2340,33 @@ imap_get_box_path( store_t *gctx ATTR_UNUSED )
        return 0;
 }
 
+typedef struct {
+       imap_cmd_t gen;
+       void (*callback)( int sts, int uidvalidity, void *aux );
+       void *callback_aux;
+} imap_cmd_open_box_t;
+
 static void imap_open_box_p2( imap_store_t *, imap_cmd_t *, int );
 static void imap_open_box_p3( imap_store_t *, imap_cmd_t *, int );
+static void imap_open_box_p4( imap_store_t *, imap_cmd_open_box_t *, int );
 
 static void
 imap_open_box( store_t *gctx,
-               void (*cb)( int sts, void *aux ), void *aux )
+               void (*cb)( int sts, int uidvalidity, void *aux ), void *aux )
 {
        imap_store_t *ctx = (imap_store_t *)gctx;
-       imap_cmd_simple_t *cmd;
+       imap_cmd_open_box_t *cmd;
        char *buf;
 
        if (prepare_box( &buf, ctx ) < 0) {
-               cb( DRV_BOX_BAD, aux );
+               cb( DRV_BOX_BAD, UIDVAL_BAD, aux );
                return;
        }
 
+       ctx->uidvalidity = UIDVAL_BAD;
        ctx->uidnext = 0;
 
-       INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cb, aux)
+       INIT_IMAP_CMD(imap_cmd_open_box_t, cmd, cb, aux)
        cmd->gen.param.failok = 1;
        imap_exec( ctx, &cmd->gen, imap_open_box_p2,
                   "SELECT \"%\\s\"", buf );
@@ -2368,15 +2376,15 @@ imap_open_box( store_t *gctx,
 static void
 imap_open_box_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
 {
-       imap_cmd_simple_t *cmdp = (imap_cmd_simple_t *)gcmd;
-       imap_cmd_simple_t *cmd;
+       imap_cmd_open_box_t *cmdp = (imap_cmd_open_box_t *)gcmd;
+       imap_cmd_open_box_t *cmd;
 
        if (response != RESP_OK || ctx->uidnext) {
-               imap_done_simple_box( ctx, &cmdp->gen, response );
+               imap_open_box_p4( ctx, cmdp, response );
                return;
        }
 
-       INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cmdp->callback, 
cmdp->callback_aux)
+       INIT_IMAP_CMD(imap_cmd_open_box_t, cmd, cmdp->callback, 
cmdp->callback_aux)
        cmd->gen.param.lastuid = 1;
        imap_exec( ctx, &cmd->gen, imap_open_box_p3,
                   "UID FETCH *:* (UID)" );
@@ -2385,11 +2393,20 @@ imap_open_box_p2( imap_store_t *ctx, imap_cmd_t *gcmd, 
int response )
 static void
 imap_open_box_p3( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
 {
+       imap_cmd_open_box_t *cmdp = (imap_cmd_open_box_t *)gcmd;
+
        // This will happen if the box is empty.
        if (!ctx->uidnext)
                ctx->uidnext = 1;
 
-       imap_done_simple_box( ctx, gcmd, response );
+       imap_open_box_p4( ctx, cmdp, response );
+}
+
+static void
+imap_open_box_p4( imap_store_t *ctx, imap_cmd_open_box_t *cmdp, int response )
+{
+       transform_box_response( &response );
+       cmdp->callback( response, ctx->uidvalidity, cmdp->callback_aux );
 }
 
 static int
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index ef92987..2017c44 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -70,7 +70,7 @@ typedef struct {
 typedef struct {
        store_t gen;
        uint opts;
-       int uvfd, uvok, nuid, is_inbox, fresh[3];
+       int uvfd, uvok, uidvalidity, nuid, is_inbox, fresh[3];
        int minuid, maxuid, newuid, seenuid;
        int_array_t excs;
        char *path; /* own */
@@ -657,7 +657,7 @@ maildir_store_uidval( maildir_store_t *ctx )
        if (ctx->db) {
                key.data = (void *)"UIDVALIDITY";
                key.size = 11;
-               uv[0] = ctx->gen.uidvalidity;
+               uv[0] = ctx->uidvalidity;
                uv[1] = ctx->nuid;
                value.data = uv;
                value.size = sizeof(uv);
@@ -672,7 +672,7 @@ maildir_store_uidval( maildir_store_t *ctx )
        } else
 #endif /* USE_DB */
        {
-               n = sprintf( buf, "%d\n%d\n", ctx->gen.uidvalidity, ctx->nuid );
+               n = sprintf( buf, "%d\n%d\n", ctx->uidvalidity, ctx->nuid );
                lseek( ctx->uvfd, 0, SEEK_SET );
                if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n 
) || (UseFSync && fdatasync( ctx->uvfd ))) {
                        error( "Maildir error: cannot write UIDVALIDITY.\n" );
@@ -686,7 +686,7 @@ maildir_store_uidval( maildir_store_t *ctx )
 static int
 maildir_init_uidval( maildir_store_t *ctx )
 {
-       ctx->gen.uidvalidity = time( 0 );
+       ctx->uidvalidity = time( 0 );
        ctx->nuid = 0;
        ctx->uvok = 0;
 #ifdef USE_DB
@@ -754,14 +754,14 @@ maildir_uidval_lock( maildir_store_t *ctx )
                        }
                        return maildir_init_uidval_new( ctx );
                }
-               ctx->gen.uidvalidity = ((int *)value.data)[0];
+               ctx->uidvalidity = ((int *)value.data)[0];
                ctx->nuid = ((int *)value.data)[1];
        } else
 #endif
        {
                lseek( ctx->uvfd, 0, SEEK_SET );
                if ((n = read( ctx->uvfd, buf, sizeof(buf) - 1 )) <= 0 ||
-                       (buf[n] = 0, sscanf( buf, "%d\n%d", 
&ctx->gen.uidvalidity, &ctx->nuid ) != 2)) {
+                       (buf[n] = 0, sscanf( buf, "%d\n%d", &ctx->uidvalidity, 
&ctx->nuid ) != 2)) {
 #if 1
                        /* In a generic driver, resetting the UID validity 
would be the right thing.
                         * But this would mess up the sync state completely. So 
better bail out and
@@ -1266,7 +1266,7 @@ maildir_get_box_path( store_t *gctx )
 
 static void
 maildir_open_box( store_t *gctx,
-                  void (*cb)( int sts, void *aux ), void *aux )
+                  void (*cb)( int sts, int uidvalidity, void *aux ), void *aux 
)
 {
        maildir_store_t *ctx = (maildir_store_t *)gctx;
        int ret;
@@ -1279,7 +1279,7 @@ maildir_open_box( store_t *gctx,
 #ifndef USE_DB
        if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 0600 )) < 0) {
                sys_error( "Maildir error: cannot write %s", uvpath );
-               cb( DRV_BOX_BAD, aux );
+               cb( DRV_BOX_BAD, UIDVAL_BAD, aux );
                return;
        }
 #else
@@ -1296,7 +1296,7 @@ maildir_open_box( store_t *gctx,
                                        goto fnok;
                        }
                        sys_error( "Maildir error: cannot write %s", uvpath );
-                       cb( DRV_BOX_BAD, aux );
+                       cb( DRV_BOX_BAD, UIDVAL_BAD, aux );
                        return;
                } else {
                  dbok:
@@ -1308,7 +1308,7 @@ maildir_open_box( store_t *gctx,
        ret = maildir_uidval_lock( ctx );
 
   bail:
-       cb( ret, aux );
+       cb( ret, ctx->uidvalidity, aux );
 }
 
 static int
diff --git a/src/sync.c b/src/sync.c
index d2d7ead..b829958 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -158,6 +158,7 @@ typedef struct {
        int maxuid[2]; /* highest UID that was already propagated */
        int newmaxuid[2]; /* highest UID that is currently being propagated */
        int uidval[2]; /* UID validity value */
+       int newuidval[2]; /* UID validity obtained from driver */
        int newuid[2]; /* TUID lookup makes sense only for UIDs >= this */
        int mmaxxuid; /* highest expired UID on master */
 } sync_vars_t;
@@ -962,11 +963,11 @@ delete_state( sync_vars_t *svars )
        }
 }
 
-static void box_confirmed( int sts, void *aux );
+static void box_confirmed( int sts, int uidvalidity, void *aux );
 static void box_confirmed2( sync_vars_t *svars, int t );
 static void box_deleted( int sts, void *aux );
 static void box_created( int sts, void *aux );
-static void box_opened( int sts, void *aux );
+static void box_opened( int sts, int uidvalidity, void *aux );
 static void box_opened2( sync_vars_t *svars, int t );
 static void load_box( sync_vars_t *svars, int t, int minwuid, int_array_t 
mexcs );
 
@@ -1002,7 +1003,6 @@ sync_boxes( store_t *ctx[], const char *names[], int 
present[], channel_conf_t *
                        sync_bail3( svars );
                        return;
                }
-               ctx[t]->uidvalidity = UIDVAL_BAD;
                svars->drv[t] = ctx[t]->conf->driver;
                svars->drv[t]->set_bad_callback( ctx[t], store_bad, AUX );
        }
@@ -1043,7 +1043,7 @@ sync_boxes( store_t *ctx[], const char *names[], int 
present[], channel_conf_t *
 }
 
 static void
-box_confirmed( int sts, void *aux )
+box_confirmed( int sts, int uidvalidity, void *aux )
 {
        DECL_SVARS;
 
@@ -1053,8 +1053,10 @@ box_confirmed( int sts, void *aux )
        if (check_cancel( svars ))
                return;
 
-       if (sts == DRV_OK)
+       if (sts == DRV_OK) {
                svars->state[t] |= ST_PRESENT;
+               svars->newuidval[t] = uidvalidity;
+       }
        box_confirmed2( svars, t );
 }
 
@@ -1100,7 +1102,7 @@ box_confirmed2( sync_vars_t *svars, int t )
                                svars->drv[1-t]->delete_box( svars->ctx[1-t], 
box_deleted, INV_AUX );
                        } else {
                                if (!(svars->chan->ops[t] & OP_CREATE)) {
-                                       box_opened( DRV_BOX_BAD, AUX );
+                                       box_opened( DRV_BOX_BAD, UIDVAL_BAD, 
AUX );
                                } else {
                                        info( "Creating %s %s...\n", str_ms[t], 
svars->orig_name[t] );
                                        svars->drv[t]->create_box( 
svars->ctx[t], box_created, AUX );
@@ -1142,7 +1144,7 @@ box_created( int sts, void *aux )
 }
 
 static void
-box_opened( int sts, void *aux )
+box_opened( int sts, int uidvalidity, void *aux )
 {
        DECL_SVARS;
 
@@ -1158,6 +1160,7 @@ box_opened( int sts, void *aux )
                svars->ret = SYNC_FAIL;
                sync_bail( svars );
        } else {
+               svars->newuidval[t] = uidvalidity;
                box_opened2( svars, t );
        }
 }
@@ -1180,13 +1183,13 @@ box_opened2( sync_vars_t *svars, int t )
 
        fails = 0;
        for (t = 0; t < 2; t++)
-               if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != 
ctx[t]->uidvalidity)
+               if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != 
svars->newuidval[t])
                        fails++;
        if (fails == 2) {
                error( "Error: channel %s: UIDVALIDITY of both master and slave 
changed\n"
                       "(master got %d, expected %d; slave got %d, expected 
%d).\n",
                       svars->chan->name,
-                      ctx[M]->uidvalidity, svars->uidval[M], 
ctx[S]->uidvalidity, svars->uidval[S] );
+                      svars->newuidval[M], svars->uidval[M], 
svars->newuidval[S], svars->uidval[S] );
          bail:
                svars->ret = SYNC_FAIL;
                sync_bail( svars );
@@ -1429,7 +1432,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
                return;
 
        for (t = 0; t < 2; t++) {
-               if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != 
svars->ctx[t]->uidvalidity) {
+               if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != 
svars->newuidval[t]) {
                        unsigned need = 0, got = 0;
                        debug( "trying to re-approve uid validity of %s\n", 
str_ms[t] );
                        for (srec = svars->srecs; srec; srec = srec->next) {
@@ -1460,7 +1463,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
                                error( "Error: channel %s, %s %s: Unable to 
recover from UIDVALIDITY change\n"
                                       "(got %d, expected %d).\n",
                                       svars->chan->name, str_ms[t], 
svars->orig_name[t],
-                                      svars->ctx[t]->uidvalidity, 
svars->uidval[t] );
+                                      svars->newuidval[t], svars->uidval[t] );
                                goto uvchg;
                        }
                        notice( "Notice: channel %s, %s %s: Recovered from 
change of UIDVALIDITY.\n",
@@ -1470,8 +1473,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
        }
 
        if (svars->uidval[M] == UIDVAL_BAD || svars->uidval[S] == UIDVAL_BAD) {
-               svars->uidval[M] = svars->ctx[M]->uidvalidity;
-               svars->uidval[S] = svars->ctx[S]->uidvalidity;
+               svars->uidval[M] = svars->newuidval[M];
+               svars->uidval[S] = svars->newuidval[S];
                jFprintf( svars, "| %d %d\n", svars->uidval[M], 
svars->uidval[S] );
        }
 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to