commit 74e936812183f6c1c3c82ad676b6805bbf8aa149
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Fri Mar 24 18:09:40 2017 +0100

    let driver_t::load_box() return the list of messages
    
    ... and make 'msgs', 'count', and 'recent' private to the drivers.

 src/driver.h      |  9 +++------
 src/drv_imap.c    | 48 +++++++++++++++++++++++++++--------------------
 src/drv_maildir.c | 32 +++++++++++++++++--------------
 src/sync.c        | 27 +++++++++++++-------------
 4 files changed, 63 insertions(+), 53 deletions(-)

diff --git a/src/driver.h b/src/driver.h
index 11fe8b2..e8edb59 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -88,12 +88,8 @@ typedef struct store {
        store_conf_t *conf; /* foreign */
 
        /* currently open mailbox */
-       message_t *msgs; /* own */
        int uidvalidity;
        int uidnext; /* from SELECT responses */
-       /* note that the following do _not_ reflect stats from msgs, but 
mailbox totals */
-       int count; /* # of messages */
-       int recent; /* # of recent messages - don't trust this beyond the 
initial read */
 } store_t;
 
 typedef struct {
@@ -204,9 +200,10 @@ struct driver {
         * Messages starting with newuid need to have the TUID populated when 
OPEN_FIND is set.
         * Messages up to seenuid need to have the Message-Id populated when 
OPEN_OLD_IDS is set.
         * Messages up to seenuid need to have the size populated when 
OPEN_OLD_SIZE is set;
-        * likewise messages above seenuid when OPEN_NEW_SIZE is set. */
+        * likewise messages above seenuid when OPEN_NEW_SIZE is set.
+        * The returned message list remains owned by the driver. */
        void (*load_box)( store_t *ctx, int minuid, int maxuid, int newuid, int 
seenuid, int_array_t excs,
-                         void (*cb)( int sts, void *aux ), void *aux );
+                         void (*cb)( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux ), void *aux );
 
        /* Fetch the contents and flags of the given message from the current 
mailbox. */
        void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data,
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 1e86ed7..f00470c 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -109,6 +109,10 @@ struct imap_store {
        list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
        string_list_t *boxes; // _list results
        char listed; // was _list already run with these flags?
+       // 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;
+       message_t *msgs;
        message_t **msgapp; /* FETCH results */
        uint caps; /* CAPABILITY results */
        string_list_t *auth_mechs;
@@ -1391,9 +1395,9 @@ imap_socket_read( void *aux )
                                goto listret;
                        } else if ((arg1 = next_arg( &cmd ))) {
                                if (!strcmp( "EXISTS", arg1 ))
-                                       ctx->gen.count = atoi( arg );
+                                       ctx->total_msgs = atoi( arg );
                                else if (!strcmp( "RECENT", arg1 ))
-                                       ctx->gen.recent = atoi( arg );
+                                       ctx->recent_msgs = atoi( arg );
                                else if(!strcmp ( "FETCH", arg1 )) {
                                        resp = parse_list( ctx, cmd, 
parse_fetch_rsp );
                                        goto listret;
@@ -1528,7 +1532,7 @@ get_cmd_result_p2( imap_store_t *ctx, imap_cmd_t *cmd, 
int response )
 static void
 imap_cleanup_store( imap_store_t *ctx )
 {
-       free_generic_messages( ctx->gen.msgs );
+       free_generic_messages( ctx->msgs );
        free_string_list( ctx->boxes );
 }
 
@@ -1596,8 +1600,10 @@ imap_cancel_unowned( void *gctx )
 static void
 imap_free_store( store_t *gctx )
 {
-       free_generic_messages( gctx->msgs );
-       gctx->msgs = 0;
+       imap_store_t *ctx = (imap_store_t *)gctx;
+
+       free_generic_messages( ctx->msgs );
+       ctx->msgs = 0;
        imap_set_bad_callback( gctx, imap_cancel_unowned, gctx );
        gctx->next = unowned;
        unowned = gctx;
@@ -2316,9 +2322,9 @@ imap_select_box( store_t *gctx, const char *name )
 {
        imap_store_t *ctx = (imap_store_t *)gctx;
 
-       free_generic_messages( gctx->msgs );
-       gctx->msgs = 0;
-       ctx->msgapp = &gctx->msgs;
+       free_generic_messages( ctx->msgs );
+       ctx->msgs = 0;
+       ctx->msgapp = &ctx->msgs;
 
        ctx->name = name;
        return DRV_OK;
@@ -2408,7 +2414,9 @@ imap_create_box( store_t *gctx,
 static int
 imap_confirm_box_empty( store_t *gctx )
 {
-       return gctx->count ? DRV_BOX_BAD : DRV_OK;
+       imap_store_t *ctx = (imap_store_t *)gctx;
+
+       return ctx->total_msgs ? DRV_BOX_BAD : DRV_OK;
 }
 
 static void imap_delete_box_p2( imap_store_t *, imap_cmd_t *, int );
@@ -2492,24 +2500,24 @@ imap_set_range( imap_range_t *ranges, int *nranges, int 
low_flags, int high_flag
 
 typedef struct {
        imap_cmd_refcounted_state_t gen;
-       void (*callback)( int sts, void *aux );
+       void (*callback)( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux );
        void *callback_aux;
 } imap_load_box_state_t;
 
 static void imap_submit_load( imap_store_t *, const char *, int, 
imap_load_box_state_t * );
-static void imap_submit_load_p3( imap_load_box_state_t * );
+static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t * );
 
 static void
 imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int seenuid, 
int_array_t excs,
-               void (*cb)( int sts, void *aux ), void *aux )
+               void (*cb)( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux ), void *aux )
 {
        imap_store_t *ctx = (imap_store_t *)gctx;
        int i, j, bl;
        char buf[1000];
 
-       if (!ctx->gen.count) {
+       if (!ctx->total_msgs) {
                free( excs.data );
-               cb( DRV_OK, aux );
+               cb( DRV_OK, 0, 0, 0, aux );
        } else {
                INIT_REFCOUNTED_STATE(imap_load_box_state_t, sts, cb, aux)
                for (i = 0; i < excs.size; ) {
@@ -2545,7 +2553,7 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int 
newuid, int seenuid, i
                        }
                }
                free( excs.data );
-               imap_submit_load_p3( sts );
+               imap_submit_load_p3( ctx, sts );
        }
 }
 
@@ -2566,18 +2574,18 @@ imap_submit_load( imap_store_t *ctx, const char *buf, 
int flags, imap_load_box_s
 }
 
 static void
-imap_submit_load_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int 
response )
+imap_submit_load_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response )
 {
        imap_load_box_state_t *sts = (imap_load_box_state_t 
*)((imap_cmd_refcounted_t *)cmd)->state;
 
        transform_refcounted_box_response( &sts->gen, response );
-       imap_submit_load_p3( sts );
+       imap_submit_load_p3( ctx, sts );
 }
 
 static void
-imap_submit_load_p3( imap_load_box_state_t *sts )
+imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t *sts )
 {
-       DONE_REFCOUNTED_STATE(sts)
+       DONE_REFCOUNTED_STATE_ARGS(sts, ctx->msgs, ctx->total_msgs, 
ctx->recent_msgs)
 }
 
 /******************* imap_fetch_msg *******************/
@@ -2715,7 +2723,7 @@ imap_close_box( store_t *gctx,
                int bl;
                char buf[1000];
 
-               for (msg = ctx->gen.msgs; ; ) {
+               for (msg = ctx->msgs; ; ) {
                        for (bl = 0; msg && bl < 960; msg = msg->next) {
                                if (!(msg->flags & F_DELETED))
                                        continue;
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 73c9445..4d2e25c 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -81,6 +81,10 @@ typedef struct {
 #endif /* USE_DB */
        string_list_t *boxes; // _list results
        char listed; // was _list already run with these flags?
+       // 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;
+       message_t *msgs;
        wakeup_t lcktmr;
 
        void (*bad_callback)( void *aux );
@@ -263,7 +267,7 @@ maildir_cleanup( store_t *gctx )
 {
        maildir_store_t *ctx = (maildir_store_t *)gctx;
 
-       free_maildir_messages( gctx->msgs );
+       free_maildir_messages( ctx->msgs );
 #ifdef USE_DB
        if (ctx->db)
                ctx->db->close( ctx->db, 0 );
@@ -908,7 +912,7 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t 
*msglist )
 
   again:
        ARRAY_INIT( msglist );
-       ctx->gen.count = ctx->gen.recent = 0;
+       ctx->total_msgs = ctx->recent_msgs = 0;
        if (ctx->uvok || ctx->maxuid == INT_MAX) {
 #ifdef USE_DB
                if (ctx->usedb) {
@@ -960,8 +964,8 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t 
*msglist )
                        while ((e = readdir( d ))) {
                                if (*e->d_name == '.')
                                        continue;
-                               ctx->gen.count++;
-                               ctx->gen.recent += i;
+                               ctx->total_msgs++;
+                               ctx->recent_msgs += i;
 #ifdef USE_DB
                                if (ctx->usedb) {
                                        if (maildir_uidval_lock( ctx ) != 
DRV_OK)
@@ -1230,7 +1234,7 @@ maildir_select_box( store_t *gctx, const char *name )
        maildir_store_t *ctx = (maildir_store_t *)gctx;
 
        maildir_cleanup( gctx );
-       gctx->msgs = 0;
+       ctx->msgs = 0;
        ctx->excs.data = 0;
        ctx->uvfd = -1;
 #ifdef USE_DB
@@ -1327,7 +1331,7 @@ maildir_confirm_box_empty( store_t *gctx )
        if (maildir_scan( ctx, &msglist ) != DRV_OK)
                return DRV_BOX_BAD;
        maildir_free_scan( &msglist );
-       return gctx->count ? DRV_BOX_BAD : DRV_OK;
+       return ctx->total_msgs ? DRV_BOX_BAD : DRV_OK;
 }
 
 static void
@@ -1401,7 +1405,7 @@ maildir_prepare_load_box( store_t *gctx, int opts )
 
 static void
 maildir_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int 
seenuid, int_array_t excs,
-                  void (*cb)( int sts, void *aux ), void *aux )
+                  void (*cb)( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux ), void *aux )
 {
        maildir_store_t *ctx = (maildir_store_t *)gctx;
        message_t **msgapp;
@@ -1416,15 +1420,15 @@ maildir_load_box( store_t *gctx, int minuid, int 
maxuid, int newuid, int seenuid
        ctx->excs = excs;
 
        if (maildir_scan( ctx, &msglist ) != DRV_OK) {
-               cb( DRV_BOX_BAD, aux );
+               cb( DRV_BOX_BAD, 0, 0, 0, aux );
                return;
        }
-       msgapp = &ctx->gen.msgs;
+       msgapp = &ctx->msgs;
        for (i = 0; i < msglist.array.size; i++)
                maildir_app_msg( ctx, &msgapp, msglist.array.data + i );
        maildir_free_scan( &msglist );
 
-       cb( DRV_OK, aux );
+       cb( DRV_OK, ctx->msgs, ctx->total_msgs, ctx->recent_msgs, aux );
 }
 
 static int
@@ -1438,7 +1442,7 @@ maildir_rescan( maildir_store_t *ctx )
        ctx->fresh[0] = ctx->fresh[1] = 0;
        if (maildir_scan( ctx, &msglist ) != DRV_OK)
                return DRV_BOX_BAD;
-       for (msgapp = &ctx->gen.msgs, i = 0;
+       for (msgapp = &ctx->msgs, i = 0;
             (msg = (maildir_message_t *)*msgapp) || i < msglist.array.size; )
        {
                if (!msg) {
@@ -1758,7 +1762,7 @@ maildir_trash_msg( store_t *gctx, message_t *gmsg,
                }
        }
        gmsg->status |= M_DEAD;
-       gctx->count--;
+       ctx->total_msgs--;
 
 #ifdef USE_DB
        if (ctx->usedb) {
@@ -1783,7 +1787,7 @@ maildir_close_box( store_t *gctx,
        for (;;) {
                retry = 0;
                basel = nfsnprintf( buf, sizeof(buf), "%s/", ctx->path );
-               for (msg = gctx->msgs; msg; msg = msg->next)
+               for (msg = ctx->msgs; msg; msg = msg->next)
                        if (!(msg->status & M_DEAD) && (msg->flags & 
F_DELETED)) {
                                nfsnprintf( buf + basel, sizeof(buf) - basel, 
"%s/%s", subdirs[msg->status & M_RECENT], ((maildir_message_t *)msg)->base );
                                if (unlink( buf )) {
@@ -1793,7 +1797,7 @@ maildir_close_box( store_t *gctx,
                                                sys_error( "Maildir error: 
cannot remove %s", buf );
                                } else {
                                        msg->status |= M_DEAD;
-                                       gctx->count--;
+                                       ctx->total_msgs--;
 #ifdef USE_DB
                                        if (ctx->db && (ret = 
maildir_purge_msg( ctx, ((maildir_message_t *)msg)->base )) != DRV_OK) {
                                                cb( ret, aux );
diff --git a/src/sync.c b/src/sync.c
index fcef2ce..cca339f 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -151,7 +151,7 @@ typedef struct {
        store_t *ctx[2];
        driver_t *drv[2];
        const char *orig_name[2];
-       message_t *new_msgs[2];
+       message_t *msgs[2], *new_msgs[2];
        int_array_alloc_t trashed_msgs[2];
        int state[2], opts[2], ref_count, nsrecs, ret, lfd, existing, replayed;
        int new_pending[2], flags_pending[2], trash_pending[2];
@@ -237,7 +237,7 @@ match_tuids( sync_vars_t *svars, int t )
                                        goto mfound;
                                }
                        }
-                       for (tmsg = svars->ctx[t]->msgs; tmsg != ntmsg; tmsg = 
tmsg->next) {
+                       for (tmsg = svars->msgs[t]; tmsg != ntmsg; tmsg = 
tmsg->next) {
                                if (tmsg->status & M_DEAD)
                                        continue;
                                if (tmsg->tuid[0] && !memcmp( tmsg->tuid, 
srec->tuid, TUIDL )) {
@@ -1308,7 +1308,7 @@ get_seenuid( sync_vars_t *svars, int t )
        return seenuid;
 }
 
-static void box_loaded( int sts, void *aux );
+static void box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux );
 
 static void
 load_box( sync_vars_t *svars, int t, int minwuid, int_array_t mexcs )
@@ -1359,7 +1359,7 @@ static void msg_copied_p2( sync_vars_t *svars, sync_rec_t 
*srec, int t, int uid
 static void msgs_copied( sync_vars_t *svars, int t );
 
 static void
-box_loaded( int sts, void *aux )
+box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void 
*aux )
 {
        DECL_SVARS;
        sync_rec_t *srec;
@@ -1375,7 +1375,8 @@ box_loaded( int sts, void *aux )
                return;
        INIT_SVARS(aux);
        svars->state[t] |= ST_LOADED;
-       info( "%s: %d messages, %d recent\n", str_ms[t], svars->ctx[t]->count, 
svars->ctx[t]->recent );
+       svars->msgs[t] = msgs;
+       info( "%s: %d messages, %d recent\n", str_ms[t], total_msgs, 
recent_msgs );
 
        if (svars->state[t] & ST_FIND_OLD) {
                debug( "matching previously copied messages on %s\n", str_ms[t] 
);
@@ -1398,7 +1399,7 @@ box_loaded( int sts, void *aux )
                srecmap[idx].uid = uid;
                srecmap[idx].srec = srec;
        }
-       for (tmsg = svars->ctx[t]->msgs; tmsg; tmsg = tmsg->next) {
+       for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) {
                if (tmsg->srec) /* found by TUID */
                        continue;
                uid = tmsg->uid;
@@ -1556,7 +1557,7 @@ box_loaded( int sts, void *aux )
 
        debug( "synchronizing new entries\n" );
        for (t = 0; t < 2; t++) {
-               for (tmsg = svars->ctx[1-t]->msgs; tmsg; tmsg = tmsg->next) {
+               for (tmsg = svars->msgs[1-t]; tmsg; tmsg = tmsg->next) {
                        // If new have no srec, the message is always New. If 
we have a srec:
                        // - message is old (> 0) or expired (0) => ignore
                        // - message was skipped (-1) => ReNew
@@ -1633,7 +1634,7 @@ box_loaded( int sts, void *aux )
                 * older than the first not expired message are not counted 
towards the total. */
                debug( "preparing message expiration\n" );
                alive = 0;
-               for (tmsg = svars->ctx[S]->msgs; tmsg; tmsg = tmsg->next) {
+               for (tmsg = svars->msgs[S]; tmsg; tmsg = tmsg->next) {
                        if (tmsg->status & M_DEAD)
                                continue;
                        if ((srec = tmsg->srec) && srec->uid[M] > 0 &&
@@ -1644,14 +1645,14 @@ box_loaded( int sts, void *aux )
                                alive++;
                        }
                }
-               for (tmsg = svars->ctx[M]->msgs; tmsg; tmsg = tmsg->next) {
+               for (tmsg = svars->msgs[M]; tmsg; tmsg = tmsg->next) {
                        if ((srec = tmsg->srec) && srec->tuid[0] && 
!(tmsg->flags & F_DELETED))
                                alive++;
                }
                todel = alive - svars->chan->max_messages;
                debug( "%d alive messages, %d excess - expiring\n", alive, 
todel );
                alive = 0;
-               for (tmsg = svars->ctx[S]->msgs; tmsg; tmsg = tmsg->next) {
+               for (tmsg = svars->msgs[S]; tmsg; tmsg = tmsg->next) {
                        if (tmsg->status & M_DEAD)
                                continue;
                        if (!(srec = tmsg->srec) || srec->uid[M] <= 0) {
@@ -1679,7 +1680,7 @@ box_loaded( int sts, void *aux )
                                }
                        }
                }
-               for (tmsg = svars->ctx[M]->msgs; tmsg; tmsg = tmsg->next) {
+               for (tmsg = svars->msgs[M]; tmsg; tmsg = tmsg->next) {
                        if ((srec = tmsg->srec) && srec->tuid[0]) {
                                nflags = tmsg->flags;
                                if (!(nflags & F_DELETED)) {
@@ -1808,7 +1809,7 @@ box_loaded( int sts, void *aux )
        for (t = 0; t < 2; t++) {
                svars->newuid[t] = svars->ctx[t]->uidnext;
                jFprintf( svars, "F %d %d\n", t, svars->newuid[t] );
-               svars->new_msgs[t] = svars->ctx[1-t]->msgs;
+               svars->new_msgs[t] = svars->msgs[1-t];
                msgs_copied( svars, t );
                if (check_cancel( svars ))
                        goto out;
@@ -2021,7 +2022,7 @@ msgs_flags_set( sync_vars_t *svars, int t )
        if ((svars->chan->ops[t] & OP_EXPUNGE) &&
            (svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && 
svars->ctx[1-t]->conf->trash_remote_new))) {
                debug( "trashing in %s\n", str_ms[t] );
-               for (tmsg = svars->ctx[t]->msgs; tmsg; tmsg = tmsg->next)
+               for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next)
                        if ((tmsg->flags & F_DELETED) && !find_int_array( 
svars->trashed_msgs[t].array, tmsg->uid ) &&
                            (t == M || !tmsg->srec || !(tmsg->srec->status & 
(S_EXPIRE|S_EXPIRED)))) {
                                if (svars->ctx[t]->conf->trash) {

------------------------------------------------------------------------------
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