CVS commit by ossi:
wrap message storing into transactions. nice side effect: drivers don't
need to deal with line end conversion any move.
M +0 -7 TODO 1.20
M +30 -85 src/drv_imap.c 1.15
M +39 -8 src/drv_maildir.c 1.10
M +12 -4 src/isync.h 1.53
M +268 -58 src/sync.c 1.70
M +0 -14 src/util.c 1.6
--- isync/TODO #1.19:1.20
@@ -12,11 +12,4 @@
add a way to automatically create and sync subfolders.
-could store TUID even when UIDPLUS is supported. would avoid duplicated
-messages after abort before new UID arrives.
-
-decouple TUID search from append. that's a prerequisite for usable
-MULTIAPPEND, and is generally good for async. should be way faster, too,
-as it saves repeated mailbox rescans with single-file formats.
-
use MULTIAPPEND and FETCH with multiple messages.
--- isync/src/drv_imap.c #1.14:1.15
@@ -759,5 +759,5 @@ parse_fetch( imap_t *imap, char *cmd ) /
size = atoi( tmp->val );
else
- fprintf( stderr, "IMAP error: unable to
parse SIZE\n" );
+ fprintf( stderr, "IMAP error: unable to
parse RFC822.SIZE\n" );
} else if (!strcmp( "BODY[]", tmp->val )) {
tmp = tmp->next;
@@ -783,5 +783,4 @@ parse_fetch( imap_t *imap, char *cmd ) /
msgdata->data = body;
msgdata->len = size;
- msgdata->crlf = 1;
if (status & M_FLAGS)
msgdata->flags = mask;
@@ -867,8 +866,12 @@ parse_search( imap_t *imap, char *cmd )
int uid;
- arg = next_arg( &cmd );
- if (!arg || !(uid = atoi( arg ))) {
+ if (!(arg = next_arg( &cmd )))
+ uid = -1;
+ else if (!(uid = atoi( arg ))) {
fprintf( stderr, "IMAP error: malformed SEARCH response\n" );
return;
+ } else if (next_arg( &cmd )) {
+ warn( "IMAP warning: SEARCH returns multiple matches\n" );
+ uid = -1; /* to avoid havoc */
}
@@ -1547,6 +1550,4 @@ imap_trash_msg( store_t *gctx, message_t
}
-#define TUIDL 8
-
static int
imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
@@ -1555,79 +1556,7 @@ imap_store_msg( store_t *gctx, msg_data_
imap_t *imap = ctx->imap;
struct imap_cmd_cb cb;
- char *fmap, *buf;
const char *prefix, *box;
- int ret, i, j, d, len, extra, nocr;
- int start, sbreak = 0, ebreak = 0;
- char flagstr[128], tuid[TUIDL * 2 + 1];
-
- memset( &cb, 0, sizeof(cb) );
-
- fmap = data->data;
- len = data->len;
- nocr = !data->crlf;
- extra = 0, i = 0;
- if (!CAP(UIDPLUS) && uid) {
- nloop:
- start = i;
- while (i < len)
- if (fmap[i++] == '\n') {
- extra += nocr;
- if (i - 2 + nocr == start) {
- sbreak = ebreak = i - 2 + nocr;
- goto mktid;
- }
- if (!memcmp( fmap + start, "X-TUID: ", 8 )) {
- extra -= (ebreak = i) - (sbreak =
start) + nocr;
- goto mktid;
- }
- goto nloop;
- }
- /* invalid message */
- free( fmap );
- return DRV_MSG_BAD;
- mktid:
- for (j = 0; j < TUIDL; j++)
- sprintf( tuid + j * 2, "%02x", arc4_getbyte() );
- extra += 8 + TUIDL * 2 + 2;
- }
- if (nocr)
- for (; i < len; i++)
- if (fmap[i] == '\n')
- extra++;
-
- cb.dlen = len + extra;
- buf = cb.data = nfmalloc( cb.dlen );
- i = 0;
- if (!CAP(UIDPLUS) && uid) {
- if (nocr) {
- for (; i < sbreak; i++)
- if (fmap[i] == '\n') {
- *buf++ = '\r';
- *buf++ = '\n';
- } else
- *buf++ = fmap[i];
- } else {
- memcpy( buf, fmap, sbreak );
- buf += sbreak;
- }
- memcpy( buf, "X-TUID: ", 8 );
- buf += 8;
- memcpy( buf, tuid, TUIDL * 2 );
- buf += TUIDL * 2;
- *buf++ = '\r';
- *buf++ = '\n';
- i = ebreak;
- }
- if (nocr) {
- for (; i < len; i++)
- if (fmap[i] == '\n') {
- *buf++ = '\r';
- *buf++ = '\n';
- } else
- *buf++ = fmap[i];
- } else
- memcpy( buf, fmap + i, len - i );
-
- free( fmap );
+ int ret, d;
+ char flagstr[128];
d = 0;
@@ -1638,4 +1567,7 @@ imap_store_msg( store_t *gctx, msg_data_
flagstr[d] = 0;
+ memset( &cb, 0, sizeof(cb) );
+ cb.dlen = data->len;
+ cb.data = data->data;
if (!uid) {
box = gctx->conf->trash;
@@ -1650,4 +1582,5 @@ imap_store_msg( store_t *gctx, msg_data_
/*if (ctx->currentnc)
imap->caps = imap->rcaps & ~(1 << LITERALPLUS);*/
+ *uid = -2;
}
cb.ctx = uid;
@@ -1663,11 +1596,21 @@ imap_store_msg( store_t *gctx, msg_data_
}
- if (CAP(UIDPLUS) || !uid)
return DRV_OK;
+}
- /* Didn't receive an APPENDUID */
+static int
+imap_find_msg( store_t *gctx, const char *tuid, int *uid )
+{
+ imap_store_t *ctx = (imap_store_t *)gctx;
+ struct imap_cmd_cb cb;
+ int ret;
+
+ memset( &cb, 0, sizeof(cb) );
+ cb.ctx = uid;
cb.uid = -1; /* we're looking for a UID */
- cb.data = 0; /* reset; ctx still set */
- return imap_exec_m( ctx, &cb, "UID SEARCH HEADER X-TUID %s", tuid );
+ *uid = -1; /* in case we get no SEARCH response at all */
+ if ((ret = imap_exec_m( ctx, &cb, "UID SEARCH HEADER X-TUID %."
stringify(TUIDL) "s", tuid )) != DRV_OK)
+ return ret;
+ return *uid < 0 ? DRV_MSG_BAD : DRV_OK;
}
@@ -1814,4 +1757,5 @@ imap_parse_store( conffile_t *cfg, store
struct driver imap_driver = {
+ DRV_CRLF,
imap_parse_store,
imap_open_store,
@@ -1823,4 +1767,5 @@ struct driver imap_driver = {
imap_fetch_msg,
imap_store_msg,
+ imap_find_msg,
imap_set_flags,
imap_trash_msg,
--- isync/src/drv_maildir.c #1.9:1.10
@@ -58,4 +58,5 @@ typedef struct maildir_message {
message_t gen;
char *base;
+ char tuid[TUIDL];
} maildir_message_t;
@@ -183,4 +184,5 @@ typedef struct {
int size;
unsigned uid:31, recent:1;
+ char tuid[TUIDL];
} msg_t;
@@ -469,4 +471,5 @@ maildir_scan( maildir_store_t *ctx, msgl
{
DIR *d;
+ FILE *f;
struct dirent *e;
const char *u, *ru;
@@ -571,4 +574,5 @@ maildir_scan( maildir_store_t *ctx, msgl
entry->recent = i;
entry->size = 0;
+ entry->tuid[0] = 0;
}
}
@@ -616,5 +620,5 @@ maildir_scan( maildir_store_t *ctx, msgl
}
uid = entry->uid;
- if (ctx->gen.opts & OPEN_SIZE)
+ if (ctx->gen.opts & (OPEN_SIZE|OPEN_FIND))
nfsnprintf( buf + bl, sizeof(buf) - bl,
"%s/%s", subdirs[entry->recent], entry->base );
#ifdef USE_DB
@@ -625,5 +629,5 @@ maildir_scan( maildir_store_t *ctx, msgl
}
entry->uid = uid;
- if (ctx->gen.opts & OPEN_SIZE)
+ if (ctx->gen.opts & (OPEN_SIZE|OPEN_FIND))
nfsnprintf( buf + bl, sizeof(buf) - bl,
"%s/%s", subdirs[entry->recent], entry->base );
#endif /* USE_DB */
@@ -646,4 +650,5 @@ maildir_scan( maildir_store_t *ctx, msgl
nfsnprintf( nbuf + bl + 4, sizeof(nbuf) - bl -
4, "%s", entry->base );
if (rename( nbuf, buf )) {
+ notok:
if (errno != ENOENT) {
perror( buf );
@@ -660,10 +665,21 @@ maildir_scan( maildir_store_t *ctx, msgl
}
if (ctx->gen.opts & OPEN_SIZE) {
- if (stat( buf, &st )) {
- maildir_free_scan( msglist );
- goto again;
- }
+ if (stat( buf, &st ))
+ goto notok;
entry->size = st.st_size;
}
+ if (ctx->gen.opts & OPEN_FIND) {
+ if (!(f = fopen( buf, "r" )))
+ goto notok;
+ while (fgets( nbuf, sizeof(nbuf), f )) {
+ if (!nbuf[0] || nbuf[0] == '\n')
+ break;
+ if (!memcmp( nbuf, "X-TUID: ", 8 ) &&
nbuf[8 + TUIDL] == '\n') {
+ memcpy( entry->tuid, nbuf + 8,
TUIDL );
+ break;
+ }
+ }
+ fclose( f );
+ }
}
ctx->uvok = 1;
@@ -682,4 +698,5 @@ maildir_init_msg( maildir_store_t *ctx,
entry->base = 0; /* prevent deletion */
msg->gen.size = entry->size;
+ strncpy( msg->tuid, entry->tuid, TUIDL );
if (entry->recent)
msg->gen.status |= M_RECENT;
@@ -903,5 +920,4 @@ maildir_fetch_msg( store_t *gctx, messag
}
fstat( fd, &st );
- data->crlf = 0;
data->len = st.st_size;
data->data = nfmalloc( data->len );
@@ -982,5 +998,4 @@ maildir_store_msg( store_t *gctx, msg_da
}
}
- strip_cr( data );
ret = write( fd, data->data, data->len );
free( data->data );
@@ -1005,4 +1020,18 @@ maildir_store_msg( store_t *gctx, msg_da
static int
+maildir_find_msg( store_t *gctx, const char *tuid, int *uid )
+{
+ message_t *msg;
+
+ /* using a hash table might turn out to be more appropriate ... */
+ for (msg = gctx->msgs; msg; msg = msg->next)
+ if (!(msg->status & M_DEAD) && !memcmp( ((maildir_message_t
*)msg)->tuid, tuid, TUIDL )) {
+ *uid = msg->uid;
+ return DRV_OK;
+ }
+ return DRV_MSG_BAD;
+}
+
+static int
maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del )
{
@@ -1190,4 +1219,5 @@ maildir_parse_store( conffile_t *cfg, st
struct driver maildir_driver = {
+ 0,
maildir_parse_store,
maildir_open_store,
@@ -1199,4 +1229,5 @@ struct driver maildir_driver = {
maildir_fetch_msg,
maildir_store_msg,
+ maildir_find_msg,
maildir_set_flags,
maildir_trash_msg,
--- isync/src/isync.h #1.52:1.53
@@ -32,4 +32,7 @@
#define as(ar) (sizeof(ar)/sizeof(ar[0]))
+#define __stringify(x) #x
+#define stringify(x) __stringify(x)
+
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
# define ATTR_UNUSED __attribute__((unused))
@@ -138,4 +141,5 @@ typedef struct message {
#define OPEN_SETFLAGS (1<<6)
#define OPEN_APPEND (1<<7)
+#define OPEN_FIND (1<<8)
typedef struct store {
@@ -147,5 +151,5 @@ typedef struct store {
message_t *msgs; /* own */
int uidvalidity;
- unsigned char opts; /* maybe preset? */
+ unsigned opts; /* maybe preset? */
/* note that the following do _not_ reflect stats from msgs, but
mailbox totals */
int count; /* # of messages */
@@ -157,5 +161,4 @@ typedef struct {
int len;
unsigned char flags;
- unsigned char crlf:1;
} msg_data_t;
@@ -165,5 +168,10 @@ typedef struct {
#define DRV_STORE_BAD -3
+#define DRV_CRLF 1
+
+#define TUIDL 12
+
struct driver {
+ int flags;
int (*parse_store)( conffile_t *cfg, store_conf_t **storep, int *err );
store_t *(*open_store)( store_conf_t *conf, store_t *oldctx );
@@ -175,4 +183,5 @@ struct driver {
int (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data );
int (*store_msg)( store_t *ctx, msg_data_t *data, int *uid ); /* if uid
is null, store to trash */
+ int (*find_msg)( store_t *ctx, const char *tuid, int *uid );
int (*set_flags)( store_t *ctx, message_t *msg, int uid, int add, int
del ); /* msg can be null, therefore uid as a fallback */
int (*trash_msg)( store_t *ctx, message_t *msg ); /* This may expunge
the original message immediately, but it needn't to */
@@ -211,6 +220,4 @@ void free_string_list( string_list_t *li
void free_generic_messages( message_t * );
-void strip_cr( msg_data_t *msgdata );
-
void *nfmalloc( size_t sz );
void *nfcalloc( size_t sz );
@@ -234,4 +241,5 @@ unsigned char arc4_getbyte( void );
#define SYNC_FAIL 1
#define SYNC_BAD(ms) (2+(ms))
+#define SYNC_NOGOOD 4 /* internal */
int sync_boxes( store_t *ctx[], const char *names[], channel_conf_t * );
--- isync/src/sync.c #1.69:1.70
@@ -95,8 +95,9 @@ typedef struct sync_rec {
message_t *msg[2];
unsigned char status, flags, aflags[2], dflags[2];
+ char tuid[TUIDL];
} sync_rec_t;
-static void
-findmsgs( sync_rec_t *srecs, store_t *ctx[], int t )
+static int
+findmsgs( sync_rec_t *srecs, store_t *ctx[], int t, FILE *jfp )
{
sync_rec_t *srec, *nsrec = 0;
@@ -106,4 +107,44 @@ findmsgs( sync_rec_t *srecs, store_t *ct
char fbuf[16]; /* enlarge when support for keywords is added */
+ if (jfp) {
+ /*
+ * Alternatively, the TUIDs could be fetched into the messages
and
+ * looked up here. This would make the search faster (probably)
and
+ * save roundtrips. On the downside, quite some additional data
would
+ * have to be fetched for every message and the IMAP driver
would be
+ * more complicated. This is a corner case anyway, so why
bother.
+ */
+ debug( "finding previously copied messages\n" );
+ for (srec = srecs; srec; srec = srec->next) {
+ if (srec->status & S_DEAD)
+ continue;
+ if (srec->uid[t] == -2 && srec->tuid[0]) {
+ debug( " pair(%d,%d): lookup %s, TUID %."
stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], str_ms[t], srec->tuid );
+ switch (ctx[t]->conf->driver->find_msg( ctx[t],
srec->tuid, &uid )) {
+ case DRV_STORE_BAD: return SYNC_BAD(t);
+ case DRV_OK:
+ debug( " -> new UID %d\n", uid );
+ Fprintf( jfp, "%c %d %d %d\n", "<>"[t],
srec->uid[M], srec->uid[S], uid );
+ srec->uid[t] = uid;
+ srec->tuid[0] = 0;
+ break;
+ default:
+ debug( " -> TUID lost\n" );
+ Fprintf( jfp, "& %d %d\n",
srec->uid[M], srec->uid[S] );
+ srec->flags = 0;
+ srec->tuid[0] = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Mapping msg -> srec (this variant) is dog slow for new messages.
+ * Mapping srec -> msg is dog slow for deleted messages.
+ * One solution would be using binary search on an index array.
+ * msgs are already sorted by UID, srecs would have to be sorted by
uid[t].
+ */
+ debug( "matching messages against sync records\n" );
for (msg = ctx[t]->msgs; msg; msg = msg->next) {
uid = msg->uid;
@@ -137,6 +178,120 @@ findmsgs( sync_rec_t *srecs, store_t *ct
debug( "pairs %5d %s\n", srec->uid[1-t], diag );
}
+
+ return SYNC_OK;
}
+static int
+copy_msg( store_t *ctx[], int t, message_t *tmsg, const char *tuid, int *uid )
+{
+ msg_data_t msgdata;
+ char *fmap, *buf;
+ int i, len, extra, cra, crd, scr, tcr;
+ int start, sbreak = 0, ebreak = 0;
+ char c;
+
+ msgdata.flags = tmsg->flags;
+ switch (ctx[1-t]->conf->driver->fetch_msg( ctx[1-t], tmsg, &msgdata )) {
+ case DRV_STORE_BAD: return SYNC_BAD(1-t);
+ case DRV_BOX_BAD: return SYNC_FAIL;
+ case DRV_MSG_BAD: return SYNC_NOGOOD;
+ }
+ tmsg->flags = msgdata.flags;
+
+ scr = (ctx[1-t]->conf->driver->flags / DRV_CRLF) & 1;
+ tcr = (ctx[t]->conf->driver->flags / DRV_CRLF) & 1;
+ if (tuid || scr != tcr) {
+ fmap = msgdata.data;
+ len = msgdata.len;
+ cra = crd = 0;
+ if (scr > tcr)
+ crd = -1;
+ else if (scr < tcr)
+ crd = 1;
+ extra = 0, i = 0;
+ if (tuid) {
+ extra += 8 + TUIDL + 1 + tcr;
+ nloop:
+ start = i;
+ while (i < len) {
+ c = fmap[i++];
+ if (c == '\r')
+ extra += crd;
+ else if (c == '\n') {
+ extra += cra;
+ if (i - 2 + !scr == start) {
+ sbreak = ebreak = i - 2 + !scr;
// precalc this!
+ goto oke;
+ }
+ if (!memcmp( fmap + start, "X-TUID: ",
8 )) {
+ extra -= (ebreak = i) - (sbreak
= start);
+ goto oke;
+ }
+ goto nloop;
+ }
+ }
+ /* invalid message */
+ free( fmap );
+ return SYNC_NOGOOD;
+ }
+ oke:
+ if (cra || crd)
+ for (; i < len; i++) {
+ c = fmap[i++];
+ if (c == '\r')
+ extra += crd;
+ else if (c == '\n')
+ extra += cra;
+ }
+
+ msgdata.len = len + extra;
+ buf = msgdata.data = nfmalloc( msgdata.len );
+ i = 0;
+ if (tuid) {
+ if (cra) {
+ for (; i < sbreak; i++) {
+ if (fmap[i] == '\n')
+ *buf++ = '\r';
+ *buf++ = fmap[i];
+ }
+ } else if (crd) {
+ for (; i < sbreak; i++)
+ if (fmap[i] != '\r')
+ *buf++ = fmap[i];
+ } else {
+ memcpy( buf, fmap, sbreak );
+ buf += sbreak;
+ }
+ memcpy( buf, "X-TUID: ", 8 );
+ buf += 8;
+ memcpy( buf, tuid, TUIDL );
+ buf += TUIDL;
+ if (tcr)
+ *buf++ = '\r';
+ *buf++ = '\n';
+ i = ebreak;
+ }
+ if (cra) {
+ for (; i < len; i++) {
+ if (fmap[i] == '\n')
+ *buf++ = '\r';
+ *buf++ = fmap[i];
+ }
+ } else if (crd) {
+ for (; i < len; i++)
+ if (fmap[i] != '\r')
+ *buf++ = fmap[i];
+ } else
+ memcpy( buf, fmap + i, len - i );
+
+ free( fmap );
+ }
+
+ switch (ctx[t]->conf->driver->store_msg( ctx[t], &msgdata, uid )) {
+ case DRV_STORE_BAD: return SYNC_BAD(t);
+ case DRV_OK: return SYNC_OK;
+ default: return SYNC_FAIL;
+ }
+}
/* cases:
@@ -180,5 +335,5 @@ clean_strdup( const char *s )
}
-#define JOURNAL_VERSION "1"
+#define JOURNAL_VERSION "2"
int
@@ -196,5 +351,4 @@ sync_boxes( store_t *ctx[], const char *
int lfd, ret, line, sline, todel, *mexcs, nmexcs, rmexcs;
unsigned char nflags, sflags, aflags, dflags;
- msg_data_t msgdata;
struct stat st;
struct flock lck;
@@ -302,4 +456,5 @@ sync_boxes( store_t *ctx[], const char *
debug( " entry (%d,%d,%u,%s)\n", srec->uid[M],
srec->uid[S], srec->flags, srec->status & S_EXPIRED ? "X" : "" );
srec->msg[M] = srec->msg[S] = 0;
+ srec->tuid[0] = 0;
srec->next = 0;
*srecadd = srec;
@@ -340,7 +495,9 @@ sync_boxes( store_t *ctx[], const char *
goto bail;
}
- if (buf[0] == '(' || buf[0] == ')' ?
+ if (buf[0] == '#' ?
+ (t3 = 0, (sscanf( buf + 2, "%d %d %n",
&t1, &t2, &t3 ) < 2) || !t3 || (t - t3 != TUIDL + 3)) :
+ buf[0] == '(' || buf[0] == ')' ?
(sscanf( buf + 2, "%d", &t1 ) != 1) :
- buf[0] == '-' || buf[0] == '|' || buf[0] ==
'/' || buf[0] == '\\' ?
+ buf[0] == '+' || buf[0] == '&' ||
buf[0] == '-' || buf[0] == '|' || buf[0] == '/' || buf[0] == '\\' ?
(sscanf( buf + 2, "%d %d", &t1, &t2 )
!= 2) :
(sscanf( buf + 2, "%d %d %d", &t1, &t2,
&t3 ) != 3))
@@ -362,8 +519,9 @@ sync_boxes( store_t *ctx[], const char *
srec->uid[M] = t1;
srec->uid[S] = t2;
- srec->flags = t3;
- debug( " new entry(%d,%d,%u)\n", t1,
t2, t3 );
+ debug( " new entry(%d,%d)\n", t1, t2 );
srec->msg[M] = srec->msg[S] = 0;
srec->status = 0;
+ srec->flags = 0;
+ srec->tuid[0] = 0;
srec->next = 0;
*srecadd = srec;
@@ -387,11 +545,22 @@ sync_boxes( store_t *ctx[], const char *
srec->status = S_DEAD;
break;
+ case '#':
+ debug( "TUID now %."
stringify(TUIDL) "s\n", buf + t3 + 2 );
+ memcpy( srec->tuid, buf + t3 +
2, TUIDL );
+ break;
+ case '&':
+ debug( "TUID %."
stringify(TUIDL) "s lost\n", srec->tuid );
+ srec->flags = 0;
+ srec->tuid[0] = 0;
+ break;
case '<':
debug( "master now %d\n", t3 );
srec->uid[M] = t3;
+ srec->tuid[0] = 0;
break;
case '>':
debug( "slave now %d\n", t3 );
srec->uid[S] = t3;
+ srec->tuid[0] = 0;
break;
case '*':
@@ -477,8 +646,15 @@ sync_boxes( store_t *ctx[], const char *
opts[S] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS;
if (line)
- for (srec = recs; srec; srec = srec->next)
- if (!(srec->status & S_DEAD) && ((mvBit(srec->status,
S_EXPIRE, S_EXPIRED) ^ srec->status) & S_EXPIRED)) {
+ for (srec = recs; srec; srec = srec->next) {
+ if (srec->status & S_DEAD)
+ continue;
+ if ((mvBit(srec->status, S_EXPIRE, S_EXPIRED) ^
srec->status) & S_EXPIRED)
opts[S] |= OPEN_OLD|OPEN_FLAGS;
- break;
+ if (srec->tuid[0]) {
+ if (srec->uid[M] == -2)
+ opts[M] |= OPEN_OLD|OPEN_FIND;
+ else if (srec->uid[S] == -2)
+ opts[S] |= OPEN_OLD|OPEN_FIND;
+ }
}
driver[M]->prepare_opts( ctx[M], opts[M] );
@@ -500,7 +676,4 @@ sync_boxes( store_t *ctx[], const char *
case DRV_BOX_BAD: ret = SYNC_FAIL; goto bail;
}
- info( "%d messages, %d recent\n", ctx[S]->count, ctx[S]->recent );
- findmsgs( recs, ctx, S );
-
if (suidval && suidval != ctx[S]->uidvalidity) {
fprintf( stderr, "Error: UIDVALIDITY of slave changed\n" );
@@ -508,4 +681,5 @@ sync_boxes( store_t *ctx[], const char *
goto bail;
}
+ info( "%d messages, %d recent\n", ctx[S]->count, ctx[S]->recent );
s = strrchr( dname, '/' );
@@ -534,4 +708,7 @@ sync_boxes( store_t *ctx[], const char *
Fprintf( jfp, JOURNAL_VERSION "\n" );
+ if ((ret = findmsgs( recs, ctx, S, line ? jfp : 0 )) != SYNC_OK)
+ goto finish;
+
mexcs = 0;
nmexcs = rmexcs = 0;
@@ -608,7 +785,4 @@ sync_boxes( store_t *ctx[], const char *
case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
}
- info( "%d messages, %d recent\n", ctx[M]->count, ctx[M]->recent );
- findmsgs( recs, ctx, M );
-
if (muidval && muidval != ctx[M]->uidvalidity) {
fprintf( stderr, "Error: UIDVALIDITY of master changed\n" );
@@ -616,4 +790,8 @@ sync_boxes( store_t *ctx[], const char *
goto finish;
}
+ info( "%d messages, %d recent\n", ctx[M]->count, ctx[M]->recent );
+
+ if ((ret = findmsgs( recs, ctx, M, line ? jfp : 0 )) != SYNC_OK)
+ goto finish;
if (!muidval || !suidval) {
@@ -629,11 +807,27 @@ sync_boxes( store_t *ctx[], const char *
for (t = 0; t < 2; t++) {
for (nmsgs = 0, tmsg = ctx[1-t]->msgs; tmsg; tmsg = tmsg->next)
- if (tmsg->srec ? tmsg->srec->uid[t] < 0 &&
(chan->ops[t] & OP_RENEW) : (chan->ops[t] & OP_NEW)) {
+ if (tmsg->srec ? tmsg->srec->uid[t] < 0 &&
(tmsg->srec->uid[t] == -1 ? (chan->ops[t] & OP_RENEW) : (chan->ops[t] &
OP_NEW)) : (chan->ops[t] & OP_NEW)) {
debug( "new message %d on %s\n", tmsg->uid,
str_ms[1-t] );
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 {
+ if (tmsg->srec) {
+ srec = tmsg->srec;
+ srec->status |= S_DONE;
+ debug( " -> pair(%d,%d)
exists\n", srec->uid[M], srec->uid[S] );
+ } else {
+ srec = nfmalloc( sizeof(*srec)
);
+ srec->next = 0;
+ *srecadd = srec;
+ srecadd = &srec->next;
+ srec->status = S_DONE;
+ srec->flags = 0;
+ srec->tuid[0] = 0;
+ srec->uid[1-t] = tmsg->uid;
+ srec->uid[t] = -2;
+ Fprintf( jfp, "+ %d %d\n",
srec->uid[M], srec->uid[S] );
+ debug( " -> pair(%d,%d)
created\n", srec->uid[M], srec->uid[S] );
+ }
if ((tmsg->flags & F_FLAGGED) ||
!chan->stores[t]->max_size || tmsg->size <= chan->stores[t]->max_size) {
- debug( " %sing it\n",
str_hl[t] );
if (!nmsgs)
info( t ? "Pulling new
messages..." : "Pushing new messages..." );
@@ -641,15 +835,24 @@ sync_boxes( store_t *ctx[], const char *
infoc( '.' );
nmsgs++;
- msgdata.flags = tmsg->flags;
- switch (driver[1-t]->fetch_msg(
ctx[1-t], tmsg, &msgdata )) {
- case DRV_STORE_BAD: return
SYNC_BAD(1-t);
- case DRV_BOX_BAD: return
SYNC_FAIL;
- case DRV_MSG_BAD: /* ok */
continue;
+ if (tmsg->flags) {
+ srec->flags =
tmsg->flags;
+ Fprintf( jfp, "* %d %d
%u\n", srec->uid[M], srec->uid[S], srec->flags );
+ debug( " -> updated
flags to %u\n", tmsg->flags );
}
- 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;
+ for (t1 = 0; t1 < TUIDL; t1++) {
+ t2 = arc4_getbyte() &
0x3f;
+ srec->tuid[t1] = t2 <
26 ? t2 + 'A' : t2 < 52 ? t2 + 'a' - 26 : t2 < 62 ? t2 + '0' - 52 : t2 == 62 ?
'+' : '/';
+ }
+ Fprintf( jfp, "# %d %d %."
stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid );
+ debug( " -> %sing message,
TUID %." stringify(TUIDL) "s\n", str_hl[t], srec->tuid );
+ switch ((ret = copy_msg( ctx,
t, tmsg, srec->tuid, &uid ))) {
+ case SYNC_OK: break;
+ case SYNC_NOGOOD:
+ /* The error is either
transient or the message is gone. */
+ debug( " -> killing
(%d,%d)\n", srec->uid[M], srec->uid[S] );
+ srec->status = S_DEAD;
+ Fprintf( jfp, "- %d
%d\n", srec->uid[M], srec->uid[S] );
+ continue;
+ default: goto finish;
}
} else {
@@ -658,23 +861,14 @@ sync_boxes( store_t *ctx[], const char *
continue;
}
- debug( " not %sing - too
big\n", str_hl[t] );
+ debug( " -> not %sing - too
big\n", str_hl[t] );
uid = -1;
}
- if (tmsg->srec) {
- srec = tmsg->srec;
+ if (srec->uid[t] != uid) {
+ debug( " -> new UID %d\n", uid
);
Fprintf( jfp, "%c %d %d %d\n",
"<>"[t], srec->uid[M], srec->uid[S], uid );
- } else {
- srec = nfmalloc( sizeof(*srec)
);
- srec->next = 0;
- *srecadd = srec;
- srecadd = &srec->next;
- 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 {
+ srec->tuid[0] = 0;
+ }
+ if (!tmsg->srec) {
tmsg->srec = srec;
if (maxuid[1-t] < tmsg->uid) {
@@ -682,5 +876,4 @@ sync_boxes( store_t *ctx[], const char *
Fprintf( jfp, "%c
%d\n", ")("[t], tmsg->uid );
}
- Fprintf( jfp, "+ %d %d %u\n",
srec->uid[M], srec->uid[S], srec->flags );
}
}
@@ -689,4 +882,26 @@ sync_boxes( store_t *ctx[], const char *
info( " %d messages\n", nmsgs );
}
+ debug( "finding just copied messages\n" );
+ for (srec = recs; srec; srec = srec->next) {
+ if (srec->status & S_DEAD)
+ continue;
+ if (srec->tuid[0]) {
+ t = (srec->uid[M] == -2) ? M : S;
+ debug( " pair(%d,%d): lookup %s, TUID %."
stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], str_ms[t], srec->tuid );
+ switch (driver[t]->find_msg( ctx[t], srec->tuid, &uid
)) {
+ case DRV_STORE_BAD: ret = SYNC_BAD(t); goto finish;
+ case DRV_OK:
+ debug( " -> new UID %d\n", uid );
+ break;
+ default:
+ warn( "Warning: cannot find newly stored
message %." stringify(TUIDL) "s on %s.\n", srec->tuid, str_ms[t] );
+ uid = 0;
+ break;
+ }
+ Fprintf( jfp, "%c %d %d %d\n", "<>"[t], srec->uid[M],
srec->uid[S], uid );
+ srec->uid[t] = uid;
+ srec->tuid[0] = 0;
+ }
+ }
debug( "synchronizing old entries\n" );
@@ -883,14 +1098,9 @@ sync_boxes( store_t *ctx[], const char *
if
(!ctx[1-t]->conf->max_size || tmsg->size <= ctx[1-t]->conf->max_size) {
debug( "
remote trashing message %d\n", tmsg->uid );
- msgdata.flags =
tmsg->flags;
- switch
(driver[t]->fetch_msg( ctx[t], tmsg, &msgdata )) {
- case DRV_OK:
break;
- case
DRV_STORE_BAD: ret = SYNC_BAD(t); goto finish;
- default: ret =
SYNC_FAIL; goto nexex;
- }
- switch
(driver[1-t]->store_msg( ctx[1-t], &msgdata, 0 )) {
- case DRV_OK:
break;
- case
DRV_STORE_BAD: ret = SYNC_BAD(1-t); goto finish;
- default: ret =
SYNC_FAIL; goto nexex;
+ switch ((ret =
copy_msg( ctx, 1 - t, tmsg, 0, 0 ))) {
+ case SYNC_OK:
break;
+ case
SYNC_NOGOOD: ret = SYNC_FAIL; goto nexex;
+ case SYNC_FAIL:
goto nexex;
+ default: goto
finish;
}
} else
--- isync/src/util.c #1.5:1.6
@@ -146,18 +146,4 @@ free_generic_messages( message_t *msgs )
}
-void
-strip_cr( msg_data_t *msgdata )
-{
- int i, o;
-
- if (msgdata->crlf) {
- for (i = o = 0; i < msgdata->len; i++)
- if (msgdata->data[i] != '\r')
- msgdata->data[o++] = msgdata->data[i];
- msgdata->len = o;
- msgdata->crlf = 0;
- }
-}
-
#ifndef HAVE_VASPRINTF
static int
-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems? Stop! Download the new AJAX search engine that makes
searching your log files as easy as surfing the web. DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel