establish bi-directional mapping between mails and sync records. use it

to merge the --renew case into the --new case.
This commit is contained in:
Oswald Buddenhagen 2006-01-30 10:26:04 +00:00
parent 24910e2cdf
commit 2277ecefb6
2 changed files with 55 additions and 68 deletions

View File

@ -118,12 +118,12 @@ typedef struct group_conf {
#define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */ #define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */
#define M_DEAD (1<<1) /* expunged */ #define M_DEAD (1<<1) /* expunged */
#define M_FLAGS (1<<2) /* flags fetched */ #define M_FLAGS (1<<2) /* flags fetched */
#define M_PROCESSED (1<<3) /* registered in pair */
#define M_SYNCED (1<<4) /* already propagated */ #define M_SYNCED (1<<4) /* already propagated */
#define M_EXPIRED (1<<5) /* kicked out by MaxMessages */ #define M_EXPIRED (1<<5) /* kicked out by MaxMessages */
typedef struct message { typedef struct message {
struct message *next; struct message *next;
struct sync_rec *srec;
/* string_list_t *keywords; */ /* string_list_t *keywords; */
size_t size; /* zero implies "not fetched" */ size_t size; /* zero implies "not fetched" */
int uid; int uid;

View File

@ -82,6 +82,7 @@ make_flags( int flags, char *buf )
#define S_EXPIRED (1<<1) #define S_EXPIRED (1<<1)
#define S_DEL(ms) (1<<(2+(ms))) #define S_DEL(ms) (1<<(2+(ms)))
#define S_EXP_S (1<<4) #define S_EXP_S (1<<4)
#define S_DONE (1<<6)
typedef struct sync_rec { typedef struct sync_rec {
struct sync_rec *next; struct sync_rec *next;
@ -122,10 +123,11 @@ findmsgs( sync_rec_t *srecs, store_t *ctx[], int t )
goto found; goto found;
} }
} }
msg->srec = 0;
debug( "new\n" ); debug( "new\n" );
continue; continue;
found: found:
msg->status |= M_PROCESSED; msg->srec = srec;
if (srec->uid[1-t] >= 0) if (srec->uid[1-t] >= 0)
msg->status |= M_SYNCED; msg->status |= M_SYNCED;
srec->msg[t] = msg; srec->msg[t] = msg;
@ -588,48 +590,61 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
int nmsgs, uid; int nmsgs, uid;
for (nmsgs = 0, tmsg = ctx[1-t]->msgs; tmsg; tmsg = tmsg->next) for (nmsgs = 0, tmsg = ctx[1-t]->msgs; tmsg; tmsg = tmsg->next)
if (!(tmsg->status & M_PROCESSED)) { if (tmsg->srec ? tmsg->srec->uid[t] < 0 && (chan->ops[t] & OP_RENEW) : (chan->ops[t] & OP_NEW)) {
if (chan->ops[t] & OP_NEW) { debug( "new message %d on %s\n", tmsg->uid, str_ms[1-t] );
debug( "new message %d on %s\n", tmsg->uid, str_ms[1-t] ); if ((chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED))
if ((chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED)) { debug( " not %sing - would be expunged anyway\n", str_hl[t] );
debug( " not %sing - would be expunged anyway\n", str_hl[t] ); else {
} else { if ((tmsg->flags & F_FLAGGED) || !chan->stores[t]->max_size || tmsg->size <= chan->stores[t]->max_size) {
if ((tmsg->flags & F_FLAGGED) || !chan->stores[t]->max_size || tmsg->size <= chan->stores[t]->max_size) { debug( " %sing it\n", str_hl[t] );
debug( " %sing it\n", str_hl[t] ); if (!nmsgs)
if (!nmsgs) info( t ? "Pulling new messages..." : "Pushing new messages..." );
info( t ? "Pulling new messages..." : "Pushing new messages..." ); else
else infoc( '.' );
infoc( '.' ); nmsgs++;
nmsgs++; msgdata.flags = tmsg->flags;
msgdata.flags = tmsg->flags; switch (driver[1-t]->fetch_msg( ctx[1-t], tmsg, &msgdata )) {
switch (driver[1-t]->fetch_msg( ctx[1-t], tmsg, &msgdata )) { case DRV_STORE_BAD: return SYNC_BAD(1-t);
case DRV_STORE_BAD: return SYNC_BAD(1-t); case DRV_BOX_BAD: return SYNC_FAIL;
case DRV_BOX_BAD: return SYNC_FAIL; case DRV_MSG_BAD: /* ok */ continue;
case DRV_MSG_BAD: /* ok */ continue;
}
tmsg->flags = msgdata.flags;
switch (driver[t]->store_msg( ctx[t], &msgdata, &uid )) {
case DRV_STORE_BAD: return SYNC_BAD(t);
default: return SYNC_FAIL;
case DRV_OK: tmsg->status |= M_SYNCED; break;
}
} else {
debug( " not %sing - too big\n", str_hl[t] );
uid = -1;
} }
tmsg->flags = msgdata.flags;
switch (driver[t]->store_msg( ctx[t], &msgdata, &uid )) {
case DRV_STORE_BAD: return SYNC_BAD(t);
default: return SYNC_FAIL;
case DRV_OK: break;
}
} else {
if (tmsg->srec) {
debug( " -> not %sing - still too big\n", str_hl[t] );
continue;
}
debug( " not %sing - too big\n", str_hl[t] );
uid = -1;
}
tmsg->status |= M_SYNCED;
if (tmsg->srec) {
srec = tmsg->srec;
Fprintf( jfp, "%c %d %d %d\n", "<>"[t], srec->uid[M], srec->uid[S], uid );
} else {
srec = nfmalloc( sizeof(*srec) ); srec = nfmalloc( sizeof(*srec) );
srec->uid[1-t] = tmsg->uid;
srec->uid[t] = uid;
srec->flags = tmsg->flags;
srec->status = 0;
srec->next = 0; srec->next = 0;
*srecadd = srec; *srecadd = srec;
srecadd = &srec->next; srecadd = &srec->next;
Fprintf( jfp, "+ %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags ); srec->uid[1-t] = tmsg->uid;
}
srec->uid[t] = uid;
srec->flags = tmsg->flags;
srec->status = S_DONE;
if (tmsg->srec)
Fprintf( jfp, "* %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags );
else {
tmsg->srec = srec;
if (maxuid[1-t] < tmsg->uid) { if (maxuid[1-t] < tmsg->uid) {
maxuid[1-t] = tmsg->uid; maxuid[1-t] = tmsg->uid;
Fprintf( jfp, "%c %d\n", ")("[t], tmsg->uid ); Fprintf( jfp, "%c %d\n", ")("[t], tmsg->uid );
} }
Fprintf( jfp, "+ %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags );
} }
} }
} }
@ -640,7 +655,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
debug( "synchronizing old entries\n" ); debug( "synchronizing old entries\n" );
Fprintf( jfp, "^\n" ); Fprintf( jfp, "^\n" );
for (srec = recs; srec != *osrecadd; srec = srec->next) { for (srec = recs; srec != *osrecadd; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & (S_DEAD|S_DONE))
continue; continue;
debug( "pair (%d,%d)\n", srec->uid[M], srec->uid[S] ); debug( "pair (%d,%d)\n", srec->uid[M], srec->uid[S] );
nom = !srec->msg[M] && (ctx[M]->opts & OPEN_OLD); nom = !srec->msg[M] && (ctx[M]->opts & OPEN_OLD);
@ -656,7 +671,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
nflags = srec->flags; nflags = srec->flags;
for (t = 0; t < 2; t++) { for (t = 0; t < 2; t++) {
int uid, unex; int unex;
unsigned char sflags, aflags, dflags, rflags; unsigned char sflags, aflags, dflags, rflags;
/* excludes (push) c.3) d.2) d.3) d.4) / (pull) b.3) d.7) d.8) d.9) */ /* excludes (push) c.3) d.2) d.3) d.4) / (pull) b.3) d.7) d.8) d.9) */
@ -682,38 +697,10 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
} else if (!srec->msg[1-t]) } else if (!srec->msg[1-t])
/* c.1) c.2) d.7) d.8) / b.1) b.2) d.2) d.3) */ /* c.1) c.2) d.7) d.8) / b.1) b.2) d.2) d.3) */
; ;
else if (srec->uid[t] < 0) { else if (srec->uid[t] < 0)
/* b.2) / c.2) */ /* b.2) / c.2) */
debug( " no %s yet\n", str_ms[t] ); ; /* handled above */
if (chan->ops[t] & OP_RENEW) { else if (!del[t]) {
if ((chan->ops[t] & OP_EXPUNGE) && (srec->msg[1-t]->flags & F_DELETED)) {
debug( " -> not %sing - would be expunged anyway\n", str_hl[t] );
} else {
if ((srec->msg[1-t]->flags & F_FLAGGED) || !chan->stores[t]->max_size || srec->msg[1-t]->size <= chan->stores[t]->max_size) {
debug( " -> %sing it\n", str_hl[t] );
msgdata.flags = srec->msg[1-t]->flags;
switch (driver[1-t]->fetch_msg( ctx[1-t], srec->msg[1-t], &msgdata )) {
case DRV_STORE_BAD: ret = SYNC_BAD(1-t); goto finish;
case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
default: /* ok */ break;
case DRV_OK:
srec->msg[1-t]->flags = msgdata.flags;
switch (driver[t]->store_msg( ctx[t], &msgdata, &uid )) {
case DRV_STORE_BAD: ret = SYNC_BAD(t); goto finish;
default: ret = SYNC_FAIL; goto finish;
case DRV_OK:
Fprintf( jfp, "%c %d %d %d\n", "<>"[t], srec->uid[M], srec->uid[S], uid );
srec->uid[t] = uid;
srec->msg[1-t]->status |= M_SYNCED;
nflags = srec->msg[1-t]->flags;
}
}
} else {
debug( " -> not %sing - still too big\n", str_hl[t] );
}
}
}
} else if (!del[t]) {
/* a) & b.3) / c.3) */ /* a) & b.3) / c.3) */
debug( " may %s\n", str_hl[t] ); debug( " may %s\n", str_hl[t] );
if (chan->ops[t] & OP_FLAGS) { if (chan->ops[t] & OP_FLAGS) {