commit 1de3ecd8830e98754721fd3f0267f9890aed2d2a
Author: Oswald Buddenhagen <[email protected]>
Date:   Sat Mar 28 17:51:27 2015 +0100

    pre-calculate channel and box lists (as far as possible)
    
    ... instead of determining them on the fly, because
    - it enables early display of totals (to be used soon)
    - it enables re-use of the data (to be used at some point)
    - the code is less cryptic
    
    note that we leak the data created in main(), consistently with other
    configuration-related data.

 src/main.c |  315 ++++++++++++++++++++++++++--------------------------
 1 files changed, 159 insertions(+), 156 deletions(-)

diff --git a/src/main.c b/src/main.c
index 026be82..f435b0f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -234,17 +234,89 @@ typedef struct box_ent {
        int present[2];
 } box_ent_t;
 
+typedef struct chan_ent {
+       struct chan_ent *next;
+       channel_conf_t *conf;
+       box_ent_t *boxes;
+       char boxlist;
+} chan_ent_t;
+
+static chan_ent_t *
+add_channel( chan_ent_t ***chanapp, channel_conf_t *chan, int ops[] )
+{
+       chan_ent_t *ce = nfcalloc( sizeof(*ce) );
+       ce->conf = chan;
+
+       merge_actions( chan, ops, XOP_HAVE_TYPE, OP_MASK_TYPE, OP_MASK_TYPE );
+       merge_actions( chan, ops, XOP_HAVE_CREATE, OP_CREATE, 0 );
+       merge_actions( chan, ops, XOP_HAVE_REMOVE, OP_REMOVE, 0 );
+       merge_actions( chan, ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 );
+
+       **chanapp = ce;
+       *chanapp = &ce->next;
+       return ce;
+}
+
+static chan_ent_t *
+add_named_channel( chan_ent_t ***chanapp, char *channame, int ops[] )
+{
+       channel_conf_t *chan;
+       chan_ent_t *ce;
+       box_ent_t *boxes = 0, **mboxapp = &boxes, *mbox;
+       char *boxp, *nboxp;
+       int boxl, boxlist = 0;
+
+       if ((boxp = strchr( channame, ':' )))
+               *boxp++ = 0;
+       for (chan = channels; chan; chan = chan->next)
+               if (!strcmp( chan->name, channame ))
+                       goto gotchan;
+       error( "No channel or group named '%s' defined.\n", channame );
+       return 0;
+  gotchan:
+       if (boxp) {
+               if (!chan->patterns) {
+                       error( "Cannot override mailbox in channel '%s' - no 
Patterns.\n", channame );
+                       return 0;
+               }
+               boxlist = 1;
+               do {
+                       nboxp = strpbrk( boxp, ",\n" );
+                       if (nboxp) {
+                               boxl = nboxp - boxp;
+                               *nboxp++ = 0;
+                       } else {
+                               boxl = strlen( boxp );
+                       }
+                       mbox = nfmalloc( sizeof(*mbox) );
+                       if (boxl)
+                               mbox->name = nfstrndup( boxp, boxl );
+                       else
+                               mbox->name = nfstrndup( "INBOX", 5 );
+                       mbox->present[M] = mbox->present[S] = BOX_POSSIBLE;
+                       mbox->next = 0;
+                       *mboxapp = mbox;
+                       mboxapp = &mbox->next;
+                       boxp = nboxp;
+               } while (boxp);
+       }
+
+       ce = add_channel( chanapp, chan, ops );
+       ce->boxes = boxes;
+       ce->boxlist = boxlist;
+       return ce;
+}
+
 typedef struct {
        int t[2];
        channel_conf_t *chan;
        driver_t *drv[2];
        store_t *ctx[2];
-       box_ent_t *boxes;
-       string_list_t *chanptr;
+       chan_ent_t *chanptr;
+       box_ent_t *boxptr;
        char *names[2];
-       char **argv;
-       int oind, ret, multiple, all, list, ops[2], state[2];
-       char done, skip, cben, boxlist;
+       int ret, multiple, all, list, state[2];
+       char done, skip, cben;
 } main_vars_t;
 
 #define AUX &mvars->t[t]
@@ -262,9 +334,12 @@ int
 main( int argc, char **argv )
 {
        main_vars_t mvars[1];
+       chan_ent_t *chans = 0, **chanapp = &chans;
        group_conf_t *group;
+       channel_conf_t *chan;
+       string_list_t *channame;
        char *config = 0, *opt, *ochar;
-       int cops = 0, op, pseudo = 0;
+       int oind, cops = 0, op, ops[2] = { 0, 0 }, pseudo = 0;
 
        tzset();
        gethostname( Hostname, sizeof(Hostname) );
@@ -280,22 +355,22 @@ main( int argc, char **argv )
        memset( mvars, 0, sizeof(*mvars) );
        mvars->t[1] = 1;
 
-       for (mvars->oind = 1, ochar = 0; ; ) {
+       for (oind = 1, ochar = 0; ; ) {
                if (!ochar || !*ochar) {
-                       if (mvars->oind >= argc)
+                       if (oind >= argc)
                                break;
-                       if (argv[mvars->oind][0] != '-')
+                       if (argv[oind][0] != '-')
                                break;
-                       if (argv[mvars->oind][1] == '-') {
-                               opt = argv[mvars->oind++] + 2;
+                       if (argv[oind][1] == '-') {
+                               opt = argv[oind++] + 2;
                                if (!*opt)
                                        break;
                                if (!strcmp( opt, "config" )) {
-                                       if (mvars->oind >= argc) {
+                                       if (oind >= argc) {
                                                error( "--config requires an 
argument.\n" );
                                                return 1;
                                        }
-                                       config = argv[mvars->oind++];
+                                       config = argv[oind++];
                                } else if (starts_with( opt, -1, "config=", 7 ))
                                        config = opt + 7;
                                else if (!strcmp( opt, "all" ))
@@ -319,9 +394,9 @@ main( int argc, char **argv )
                                } else if (!strcmp( opt, "debug" ))
                                        DFlags |= DEBUG | QUIET;
                                else if (!strcmp( opt, "pull" ))
-                                       cops |= XOP_PULL, mvars->ops[M] |= 
XOP_HAVE_TYPE;
+                                       cops |= XOP_PULL, ops[M] |= 
XOP_HAVE_TYPE;
                                else if (!strcmp( opt, "push" ))
-                                       cops |= XOP_PUSH, mvars->ops[M] |= 
XOP_HAVE_TYPE;
+                                       cops |= XOP_PUSH, ops[M] |= 
XOP_HAVE_TYPE;
                                else if (starts_with( opt, -1, "create", 6 )) {
                                        opt += 6;
                                        op = OP_CREATE|XOP_HAVE_CREATE;
@@ -329,12 +404,12 @@ main( int argc, char **argv )
                                        if (!*opt)
                                                cops |= op;
                                        else if (!strcmp( opt, "-master" ))
-                                               mvars->ops[M] |= op;
+                                               ops[M] |= op;
                                        else if (!strcmp( opt, "-slave" ))
-                                               mvars->ops[S] |= op;
+                                               ops[S] |= op;
                                        else
                                                goto badopt;
-                                       mvars->ops[M] |= op & 
(XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE);
+                                       ops[M] |= op & 
(XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE);
                                } else if (starts_with( opt, -1, "remove", 6 )) 
{
                                        opt += 6;
                                        op = OP_REMOVE|XOP_HAVE_REMOVE;
@@ -344,15 +419,15 @@ main( int argc, char **argv )
                                        op = OP_EXPUNGE|XOP_HAVE_EXPUNGE;
                                        goto lcop;
                                } else if (!strcmp( opt, "no-expunge" ))
-                                       mvars->ops[M] |= XOP_HAVE_EXPUNGE;
+                                       ops[M] |= XOP_HAVE_EXPUNGE;
                                else if (!strcmp( opt, "no-create" ))
-                                       mvars->ops[M] |= XOP_HAVE_CREATE;
+                                       ops[M] |= XOP_HAVE_CREATE;
                                else if (!strcmp( opt, "no-remove" ))
-                                       mvars->ops[M] |= XOP_HAVE_REMOVE;
+                                       ops[M] |= XOP_HAVE_REMOVE;
                                else if (!strcmp( opt, "full" ))
-                                       mvars->ops[M] |= 
XOP_HAVE_TYPE|XOP_PULL|XOP_PUSH;
+                                       ops[M] |= 
XOP_HAVE_TYPE|XOP_PULL|XOP_PUSH;
                                else if (!strcmp( opt, "noop" ))
-                                       mvars->ops[M] |= XOP_HAVE_TYPE;
+                                       ops[M] |= XOP_HAVE_TYPE;
                                else if (starts_with( opt, -1, "pull", 4 )) {
                                        op = XOP_PULL;
                                  lcac:
@@ -380,19 +455,19 @@ main( int argc, char **argv )
                                                op |= OP_FLAGS;
                                        else {
                                          badopt:
-                                               error( "Unknown option '%s'\n", 
argv[mvars->oind - 1] );
+                                               error( "Unknown option '%s'\n", 
argv[oind - 1] );
                                                return 1;
                                        }
                                        switch (op & XOP_MASK_DIR) {
-                                       case XOP_PULL: mvars->ops[S] |= op & 
OP_MASK_TYPE; break;
-                                       case XOP_PUSH: mvars->ops[M] |= op & 
OP_MASK_TYPE; break;
+                                       case XOP_PULL: ops[S] |= op & 
OP_MASK_TYPE; break;
+                                       case XOP_PUSH: ops[M] |= op & 
OP_MASK_TYPE; break;
                                        default: cops |= op; break;
                                        }
-                                       mvars->ops[M] |= XOP_HAVE_TYPE;
+                                       ops[M] |= XOP_HAVE_TYPE;
                                }
                                continue;
                        }
-                       ochar = argv[mvars->oind++] + 1;
+                       ochar = argv[oind++] + 1;
                        if (!*ochar) {
                                error( "Invalid option '-'\n" );
                                return 1;
@@ -410,24 +485,24 @@ main( int argc, char **argv )
                                ochar++;
                                pseudo = 1;
                        }
-                       if (mvars->oind >= argc) {
+                       if (oind >= argc) {
                                error( "-c requires an argument.\n" );
                                return 1;
                        }
-                       config = argv[mvars->oind++];
+                       config = argv[oind++];
                        break;
                case 'C':
                        op = OP_CREATE|XOP_HAVE_CREATE;
                  cop:
                        if (*ochar == 'm')
-                               mvars->ops[M] |= op, ochar++;
+                               ops[M] |= op, ochar++;
                        else if (*ochar == 's')
-                               mvars->ops[S] |= op, ochar++;
+                               ops[S] |= op, ochar++;
                        else if (*ochar == '-')
                                ochar++;
                        else
                                cops |= op;
-                       mvars->ops[M] |= op & 
(XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE);
+                       ops[M] |= op & 
(XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE);
                        break;
                case 'R':
                        op = OP_REMOVE|XOP_HAVE_REMOVE;
@@ -439,7 +514,7 @@ main( int argc, char **argv )
                        cops |= XOP_PULL|XOP_PUSH;
                        /* fallthrough */
                case '0':
-                       mvars->ops[M] |= XOP_HAVE_TYPE;
+                       ops[M] |= XOP_HAVE_TYPE;
                        break;
                case 'n':
                case 'd':
@@ -462,13 +537,13 @@ main( int argc, char **argv )
                        }
                        if (op & OP_MASK_TYPE)
                                switch (op & XOP_MASK_DIR) {
-                               case XOP_PULL: mvars->ops[S] |= op & 
OP_MASK_TYPE; break;
-                               case XOP_PUSH: mvars->ops[M] |= op & 
OP_MASK_TYPE; break;
+                               case XOP_PULL: ops[S] |= op & OP_MASK_TYPE; 
break;
+                               case XOP_PUSH: ops[M] |= op & OP_MASK_TYPE; 
break;
                                default: cops |= op; break;
                                }
                        else
                                cops |= op;
-                       mvars->ops[M] |= XOP_HAVE_TYPE;
+                       ops[M] |= XOP_HAVE_TYPE;
                        break;
                case 'L':
                        op = XOP_PULL;
@@ -518,33 +593,42 @@ main( int argc, char **argv )
        }
 #endif
 
-       if (merge_ops( cops, mvars->ops ))
+       if (merge_ops( cops, ops ))
                return 1;
 
        if (load_config( config, pseudo ))
                return 1;
 
-       if (!mvars->all && !argv[mvars->oind]) {
-               fputs( "No channel specified. Try '" EXE " -h'\n", stderr );
-               return 1;
-       }
        if (!channels) {
                fputs( "No channels defined. Try 'man " EXE "'\n", stderr );
                return 1;
        }
 
-       mvars->chan = channels;
-       if (mvars->all)
-               mvars->multiple = channels->next != 0;
-       else if (argv[mvars->oind + 1])
-               mvars->multiple = 1;
-       else
-               for (group = groups; group; group = group->next)
-                       if (!strcmp( group->name, argv[mvars->oind] )) {
-                               mvars->multiple = 1;
-                               break;
+       if (mvars->all) {
+               for (chan = channels; chan; chan = chan->next)
+                       add_channel( &chanapp, chan, ops );
+       } else {
+               for (; argv[oind]; oind++) {
+                       for (group = groups; group; group = group->next) {
+                               if (!strcmp( group->name, argv[oind] )) {
+                                       for (channame = group->channels; 
channame; channame = channame->next)
+                                               if (!add_named_channel( 
&chanapp, channame->string, ops ))
+                                                       mvars->ret = 1;
+                                       goto gotgrp;
+                               }
                        }
-       mvars->argv = argv;
+                       if (!add_named_channel( &chanapp, argv[oind], ops ))
+                               mvars->ret = 1;
+                 gotgrp: ;
+               }
+       }
+       if (!chans) {
+               fputs( "No channel specified. Try '" EXE " -h'\n", stderr );
+               return 1;
+       }
+       mvars->chanptr = chans;
+       mvars->multiple = !!chans->next;
+
        mvars->cben = 1;
        sync_chans( mvars, E_START );
        main_loop();
@@ -558,7 +642,6 @@ main( int argc, char **argv )
 static void store_opened( store_t *ctx, void *aux );
 static void store_listed( int sts, void *aux );
 static int sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox );
-static void done_sync_dyn( int sts, void *aux );
 static void done_sync_2_dyn( int sts, void *aux );
 static void done_sync( int sts, void *aux );
 
@@ -567,10 +650,8 @@ static void done_sync( int sts, void *aux );
 static void
 sync_chans( main_vars_t *mvars, int ent )
 {
-       group_conf_t *group;
-       channel_conf_t *chan;
        box_ent_t *mbox, *nmbox, **mboxapp;
-       char *channame, **boxes[2], *boxp, *nboxp;
+       char **boxes[2];
        const char *labels[2];
        int t, mb, sb, cmp;
 
@@ -580,68 +661,8 @@ sync_chans( main_vars_t *mvars, int ent )
        case E_OPEN: goto opened;
        case E_SYNC: goto syncone;
        }
-       for (;;) {
-               mvars->boxlist = 0;
-               mvars->boxes = 0;
-               if (!mvars->all) {
-                       if (mvars->chanptr)
-                               channame = mvars->chanptr->string;
-                       else {
-                               for (group = groups; group; group = group->next)
-                                       if (!strcmp( group->name, 
mvars->argv[mvars->oind] )) {
-                                               mvars->chanptr = 
group->channels;
-                                               channame = 
mvars->chanptr->string;
-                                               goto gotgrp;
-                                       }
-                               channame = mvars->argv[mvars->oind];
-                         gotgrp: ;
-                       }
-                       if ((boxp = strchr( channame, ':' )))
-                               *boxp++ = 0;
-                       for (chan = channels; chan; chan = chan->next)
-                               if (!strcmp( chan->name, channame ))
-                                       goto gotchan;
-                       error( "No channel or group named '%s' defined.\n", 
channame );
-                       mvars->ret = 1;
-                       goto gotnone;
-                 gotchan:
-                       mvars->chan = chan;
-                       if (boxp) {
-                               if (!chan->patterns) {
-                                       error( "Cannot override mailbox in 
channel '%s' - no Patterns.\n", channame );
-                                       mvars->ret = 1;
-                                       goto gotnone;
-                               }
-                               mvars->boxlist = 1;
-                               mboxapp = &mvars->boxes;
-                               for (;;) {
-                                       nboxp = strpbrk( boxp, ",\n" );
-                                       if (nboxp) {
-                                               t = nboxp - boxp;
-                                               *nboxp++ = 0;
-                                       } else {
-                                               t = strlen( boxp );
-                                       }
-                                       mbox = nfmalloc( sizeof(*mbox) );
-                                       if (t)
-                                               mbox->name = nfstrndup( boxp, t 
);
-                                       else
-                                               mbox->name = nfstrndup( 
"INBOX", 5 );
-                                       mbox->present[M] = mbox->present[S] = 
BOX_POSSIBLE;
-                                       mbox->next = 0;
-                                       *mboxapp = mbox;
-                                       mboxapp = &mbox->next;
-                                       if (!nboxp)
-                                               break;
-                                       boxp = nboxp;
-                               }
-                       }
-               }
-               merge_actions( mvars->chan, mvars->ops, XOP_HAVE_TYPE, 
OP_MASK_TYPE, OP_MASK_TYPE );
-               merge_actions( mvars->chan, mvars->ops, XOP_HAVE_CREATE, 
OP_CREATE, 0 );
-               merge_actions( mvars->chan, mvars->ops, XOP_HAVE_REMOVE, 
OP_REMOVE, 0 );
-               merge_actions( mvars->chan, mvars->ops, XOP_HAVE_EXPUNGE, 
OP_EXPUNGE, 0 );
-
+       do {
+               mvars->chan = mvars->chanptr->conf;
                info( "Channel %s\n", mvars->chan->name );
                mvars->skip = mvars->cben = 0;
                for (t = 0; t < 2; t++) {
@@ -675,11 +696,11 @@ sync_chans( main_vars_t *mvars, int ent )
                if (mvars->state[M] != ST_OPEN || mvars->state[S] != ST_OPEN)
                        return;
 
-               if (!mvars->boxlist && mvars->chan->patterns) {
-                       mvars->boxlist = 1;
+               if (!mvars->chanptr->boxlist && mvars->chan->patterns) {
+                       mvars->chanptr->boxlist = 2;
                        boxes[M] = filter_boxes( mvars->ctx[M]->boxes, 
mvars->chan->boxes[M], mvars->chan->patterns );
                        boxes[S] = filter_boxes( mvars->ctx[S]->boxes, 
mvars->chan->boxes[S], mvars->chan->patterns );
-                       mboxapp = &mvars->boxes;
+                       mboxapp = &mvars->chanptr->boxes;
                        for (mb = sb = 0; boxes[M][mb] || boxes[S][sb]; ) {
                                mbox = nfmalloc( sizeof(*mbox) );
                                if (!(cmp = !boxes[M][mb] - !boxes[S][sb]) && 
!(cmp = cmp_box_names( boxes[M] + mb, boxes[S] + sb ))) {
@@ -706,14 +727,15 @@ sync_chans( main_vars_t *mvars, int ent )
                        free( boxes[M] );
                        free( boxes[S] );
                }
+               mvars->boxptr = mvars->chanptr->boxes;
 
                if (mvars->list && mvars->multiple)
                        printf( "%s:\n", mvars->chan->name );
          syncml:
                mvars->done = mvars->cben = 0;
-               if (mvars->boxlist) {
-                       while ((mbox = mvars->boxes)) {
-                               mvars->boxes = mbox->next;
+               if (mvars->chanptr->boxlist) {
+                       while ((mbox = mvars->boxptr)) {
+                               mvars->boxptr = mbox->next;
                                if (sync_listed_boxes( mvars, mbox ))
                                        goto syncw;
                        }
@@ -743,23 +765,18 @@ sync_chans( main_vars_t *mvars, int ent )
                        mvars->skip = mvars->cben = 1;
                        return;
                }
-               for (nmbox = mvars->boxes; (mbox = nmbox); ) {
-                       nmbox = mbox->next;
-                       free( mbox->name );
-                       free( mbox );
+               if (mvars->chanptr->boxlist == 2) {
+                       for (nmbox = mvars->chanptr->boxes; (mbox = nmbox); ) {
+                               nmbox = mbox->next;
+                               free( mbox->name );
+                               free( mbox );
+                       }
+                       mvars->chanptr->boxes = 0;
+                       mvars->chanptr->boxlist = 0;
                }
          next2:
-               if (mvars->all) {
-                       if (!(mvars->chan = mvars->chan->next))
-                               break;
-               } else {
-                       if (mvars->chanptr && (mvars->chanptr = 
mvars->chanptr->next))
-                               continue;
-                 gotnone:
-                       if (!mvars->argv[++mvars->oind])
-                               break;
-               }
-       }
+               ;
+       } while ((mvars->chanptr = mvars->chanptr->next));
        for (t = 0; t < N_DRIVERS; t++)
                drivers[t]->cleanup();
 }
@@ -789,7 +806,7 @@ store_opened( store_t *ctx, void *aux )
                return;
        }
        mvars->ctx[t] = ctx;
-       if (!mvars->skip && !mvars->boxlist && mvars->chan->patterns && 
!ctx->listed) {
+       if (!mvars->skip && !mvars->chanptr->boxlist && mvars->chan->patterns 
&& !ctx->listed) {
                for (flags = 0, cpat = mvars->chan->patterns; cpat; cpat = 
cpat->next) {
                        const char *pat = cpat->string;
                        if (*pat != '!') {
@@ -873,36 +890,22 @@ sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox )
                if (!mvars->list) {
                        nfasprintf( &mvars->names[M], "%s%s", mpfx, mbox->name 
);
                        nfasprintf( &mvars->names[S], "%s%s", spfx, mbox->name 
);
-                       free( mbox->name );
                        sync_boxes( mvars->ctx, (const char **)mvars->names, 
mbox->present, mvars->chan, done_sync_2_dyn, mvars );
-                       free( mbox );
                        return 1;
                }
                printf( "%s%s <=> %s%s\n", mpfx, mbox->name, spfx, mbox->name );
        } else {
                if (!mvars->list) {
                        mvars->names[M] = mvars->names[S] = mbox->name;
-                       sync_boxes( mvars->ctx, (const char **)mvars->names, 
mbox->present, mvars->chan, done_sync_dyn, mvars );
-                       free( mbox );
+                       sync_boxes( mvars->ctx, (const char **)mvars->names, 
mbox->present, mvars->chan, done_sync, mvars );
                        return 1;
                }
                puts( mbox->name );
        }
-       free( mbox->name );
-       free( mbox );
        return 0;
 }
 
 static void
-done_sync_dyn( int sts, void *aux )
-{
-       main_vars_t *mvars = (main_vars_t *)aux;
-
-       free( mvars->names[M] );
-       done_sync( sts, aux );
-}
-
-static void
 done_sync_2_dyn( int sts, void *aux )
 {
        main_vars_t *mvars = (main_vars_t *)aux;

------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to