Bläddra i källkod

put message references into the sync records. match up the uids after
opening the boxes instead of "sort-of-on-demand" - this is much simpler.
match from messages to sync records, not the other way round - makes the
debug output shorter, as the separate dump_box() is gone now.

Oswald Buddenhagen 19 år sedan
förälder
incheckning
8c30ec4a25
1 ändrade filer med 69 tillägg och 72 borttagningar
  1. 69 72
      src/sync.c

+ 69 - 72
src/sync.c

@@ -78,48 +78,6 @@ make_flags( int flags, char *buf )
 	return d;
 }
 
-static void
-dump_box( store_t *ctx )
-{
-	message_t *msg;
-	char fbuf[16]; /* enlarge when support for keywords is added */
-
-	if (Debug)
-		for (msg = ctx->msgs; msg; msg = msg->next) {
-			make_flags( msg->flags, fbuf );
-			printf( "  message %d, %s, %d\n", msg->uid, fbuf, msg->size );
-		}
-}
-
-static message_t *
-findmsg( store_t *ctx, int uid, message_t **nmsg, const char *who )
-{
-	message_t *msg;
-
-	if (uid > 0) {
-		if (*nmsg && (*nmsg)->uid == uid) {
-			debug( " %s came in sequence\n", who );
-			msg = *nmsg;
-		  found:
-			*nmsg = msg->next;
-			if (!(msg->status & M_DEAD)) {
-				msg->status |= M_PROCESSED;
-				return msg;
-			}
-			debug( "  ... but it vanished under our feet!\n" );
-		} else {
-			for (msg = ctx->msgs; msg; msg = msg->next)
-				if (msg->uid == uid) {
-					debug( " %s came out of sequence\n", who );
-					goto found;
-				}
-				debug( " %s not present\n", who );
-		}
-	} else
-		debug( " no %s expected\n", who );
-	return 0;
-}
-
 #define S_DEAD         (1<<0)
 #define S_EXPIRED      (1<<1)
 #define S_DEL(ms)      (1<<(2+(ms)))
@@ -129,9 +87,51 @@ typedef struct sync_rec {
 	struct sync_rec *next;
 	/* string_list_t *keywords; */
 	int uid[2];
+	message_t *msg[2];
 	unsigned char flags, status;
 } sync_rec_t;
 
+static void
+findmsgs( sync_rec_t *srecs, store_t *ctx[], int t )
+{
+	sync_rec_t *srec, *nsrec = 0;
+	message_t *msg;
+	const char *diag;
+	int uid;
+	char fbuf[16]; /* enlarge when support for keywords is added */
+
+	for (msg = ctx[t]->msgs; msg; msg = msg->next) {
+		uid = msg->uid;
+		if (Debug) {
+			make_flags( msg->flags, fbuf );
+			printf( ctx[t]->opts & OPEN_SIZE ? "  message %5d, %-4s, %6d: " : "  message %5d, %-4s: ", uid, fbuf, msg->size );
+		}
+		for (srec = nsrec; srec; srec = srec->next) {
+			if (srec->status & S_DEAD)
+				continue;
+			if (srec->uid[t] == uid) {
+				diag = srec == nsrec ? "adjacently" : "after gap";
+				goto found;
+			}
+		}
+		for (srec = srecs; srec != nsrec; srec = srec->next) {
+			if (srec->status & S_DEAD)
+				continue;
+			if (srec->uid[t] == uid) {
+				diag = "after reset";
+				goto found;
+			}
+		}
+		debug( "new\n" );
+		continue;
+	  found:
+		msg->status |= M_PROCESSED;
+		srec->msg[t] = msg;
+		nsrec = srec->next;
+		debug( "pairs %5d %s\n", srec->uid[1-t], diag );
+	}
+}
+
 
 /* cases:
    a) both non-null
@@ -177,7 +177,7 @@ int
 sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 {
 	driver_t *driver[2];
-	message_t *msg[2], *tmsg, *nmmsg, *nsmsg;
+	message_t *tmsg;
 	sync_rec_t *recs, *srec, **srecadd, *nsrec;
 	char *dname, *jname, *nname, *lname, *s, *cmname, *csname;
 	FILE *dfp, *jfp, *nfp;
@@ -196,8 +196,6 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 	ret = SYNC_OK;
 	recs = 0, srecadd = &recs;
 
-	nmmsg = nsmsg = 0;
-
 	opts[M] = opts[S] = 0;
 	for (t = 0; t < 2; t++) {
 		if (chan->ops[t] & (OP_DELETE|OP_FLAGS)) {
@@ -327,6 +325,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 				srec->status = 0;
 			srec->flags = parse_flags( s );
 			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->next = 0;
 			*srecadd = srec;
 			srecadd = &srec->next;
@@ -379,6 +378,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 						srec->uid[S] = t2;
 						srec->flags = t3;
 						debug( "  new entry(%d,%d,%u)\n", t1, t2, t3 );
+						srec->msg[M] = srec->msg[S] = 0;
 						srec->status = 0;
 						srec->next = 0;
 						*srecadd = srec;
@@ -455,7 +455,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 	case DRV_BOX_BAD: ret = SYNC_FAIL; goto bail;
 	}
 	info( "%d messages, %d recent\n", ctx[S]->count, ctx[S]->recent );
-	dump_box( ctx[S] );
+	findmsgs( recs, ctx, S );
 
 	if (suidval && suidval != ctx[S]->uidvalidity) {
 		fprintf( stderr, "Error: UIDVALIDITY of slave changed\n" );
@@ -495,7 +495,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 			if (srec->status & S_DEAD)
 				continue;
 			if (srec->status & S_EXPIRED) {
-				if (!srec->uid[S] || ((ctx[S]->opts & OPEN_OLD) && !findmsg( ctx[S], srec->uid[S], &nsmsg, "slave" ))) {
+				if (!srec->uid[S] || ((ctx[S]->opts & OPEN_OLD) && !srec->msg[S])) {
 					srec->status |= S_EXP_S;
 					continue;
 				}
@@ -562,7 +562,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 	case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
 	}
 	info( "%d messages, %d recent\n", ctx[M]->count, ctx[M]->recent );
-	dump_box( ctx[M] );
+	findmsgs( recs, ctx, M );
 
 	if (muidval && muidval != ctx[M]->uidvalidity) {
 		fprintf( stderr, "Error: UIDVALIDITY of master changed\n" );
@@ -583,10 +583,8 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 		if (srec->status & S_DEAD)
 			continue;
 		debug( "pair (%d,%d)\n", srec->uid[M], srec->uid[S] );
-		msg[M] = findmsg( ctx[M], srec->uid[M], &nmmsg, "master" );
-		msg[S] = (srec->status & S_EXP_S) ? 0 : findmsg( ctx[S], srec->uid[S], &nsmsg, "slave" );
-		nom = !msg[M] && (ctx[M]->opts & OPEN_OLD);
-		nos = !msg[S] && (ctx[S]->opts & OPEN_OLD);
+		nom = !srec->msg[M] && (ctx[M]->opts & OPEN_OLD);
+		nos = !srec->msg[S] && (ctx[S]->opts & OPEN_OLD);
 		if (nom && nos) {
 			debug( "  vanished\n" );
 			/* d.1) d.5) d.6) d.10) d.11) */
@@ -608,11 +606,11 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 				} else if (del[1-t]) {
 					/* c.4) d.9) / b.4) d.4) */
 					debug( "  %s vanished\n", str_ms[1-t] );
-					if (msg[t] && msg[t]->flags != nflags)
+					if (srec->msg[t] && srec->msg[t]->flags != nflags)
 						info( "Info: conflicting changes in (%d,%d)\n", srec->uid[M], srec->uid[S] );
 					if (chan->ops[t] & OP_DELETE) {
 						debug( "  -> %s delete\n", str_hl[t] );
-						switch (driver[t]->set_flags( ctx[t], msg[t], srec->uid[t], F_DELETED, 0 )) {
+						switch (driver[t]->set_flags( ctx[t], srec->msg[t], srec->uid[t], F_DELETED, 0 )) {
 						case DRV_STORE_BAD: ret = SYNC_BAD(t); goto finish;
 						case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
 						default: /* ok */ break;
@@ -621,48 +619,48 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 							srec->uid[1-t] = 0;
 						}
 					}
-				} else if (!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) */
 					;
 				else if (srec->uid[t] < 0) {
 					/* b.2) / c.2) */
 					debug( "  no %s yet\n", str_ms[t] );
 					if (chan->ops[t] & OP_RENEW) {
-						if ((chan->ops[t] & OP_EXPUNGE) && (msg[1-t]->flags & F_DELETED)) {
+						if ((chan->ops[t] & OP_EXPUNGE) && (srec->msg[1-t]->flags & F_DELETED)) {
 							debug( "  -> not %sing - would be expunged anyway\n", str_hl[t] );
-							msg[1-t]->status |= M_NOT_SYNCED;
+							srec->msg[1-t]->status |= M_NOT_SYNCED;
 						} else {
-							if ((msg[1-t]->flags & F_FLAGGED) || !chan->stores[t]->max_size || msg[1-t]->size <= chan->stores[t]->max_size) {
+							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 = msg[1-t]->flags;
-								switch (driver[1-t]->fetch_msg( ctx[1-t], msg[1-t], &msgdata )) {
+								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 */ msg[1-t]->status |= M_NOT_SYNCED; break;
+								default: /* ok */ srec->msg[1-t]->status |= M_NOT_SYNCED; break;
 								case DRV_OK:
-									msg[1-t]->flags = msgdata.flags;
+									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;
-										nflags = msg[1-t]->flags;
+										nflags = srec->msg[1-t]->flags;
 									}
 								}
 							} else {
 								debug( "  -> not %sing - still too big\n", str_hl[t] );
-								msg[1-t]->status |= M_NOT_SYNCED;
+								srec->msg[1-t]->status |= M_NOT_SYNCED;
 							}
 						}
 					} else
-						msg[1-t]->status |= M_NOT_SYNCED;
+						srec->msg[1-t]->status |= M_NOT_SYNCED;
 				} else if (!del[t]) {
 					/* a) & b.3) / c.3) */
 					debug( "  may %s\n", str_hl[t] );
 					if (chan->ops[t] & OP_FLAGS) {
 						debug( "  -> %sing flags\n", str_hl[t] );
-						sflags = msg[1-t]->flags;
+						sflags = srec->msg[1-t]->flags;
 						aflags = sflags & ~nflags;
 						dflags = ~sflags & nflags;
 						unex = 0;
@@ -686,7 +684,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 							aflags &= F_DELETED;
 							dflags = 0;
 						}
-						switch ((aflags | dflags) ? driver[t]->set_flags( ctx[t], msg[t], srec->uid[t], aflags, dflags ) : DRV_OK) {
+						switch ((aflags | dflags) ? driver[t]->set_flags( ctx[t], srec->msg[t], srec->uid[t], aflags, dflags ) : DRV_OK) {
 						case DRV_STORE_BAD: ret = SYNC_BAD(t); goto finish;
 						case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
 						default: /* ok */ break;
@@ -708,9 +706,9 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 				srec->flags = nflags;
 				Fprintf( jfp, "* %d %d %u\n", srec->uid[M], srec->uid[S], nflags );
 			}
-			if (msg[M] && (msg[M]->flags & F_DELETED))
+			if (srec->msg[M] && (srec->msg[M]->flags & F_DELETED))
 				srec->status |= S_DEL(M);
-			if (msg[S] && (msg[S]->flags & F_DELETED))
+			if (srec->msg[S] && (srec->msg[S]->flags & F_DELETED))
 				srec->status |= S_DEL(S);
 		}
 	}
@@ -795,15 +793,14 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 			for (srec = recs; srec; srec = srec->next) {
 				if (srec->status & (S_DEAD|S_EXPIRED))
 					continue;
-				tmsg = findmsg( ctx[S], srec->uid[S], &nsmsg, "slave" );
-				if (tmsg && (tmsg->status & M_EXPIRED)) {
+				if (srec->msg[S] && (srec->msg[S]->status & M_EXPIRED)) {
 					debug( "  expiring pair(%d,%d)\n", srec->uid[M], srec->uid[S] );
 					/* log first, so deletion can't be misinterpreted! */
 					Fprintf( jfp, "~ %d %d 1\n", srec->uid[M], srec->uid[S] );
 					if (smaxxuid < srec->uid[S])
 						smaxxuid = srec->uid[S];
 					srec->status |= S_EXPIRED;
-					switch (driver[S]->set_flags( ctx[S], tmsg, 0, F_DELETED, 0 )) {
+					switch (driver[S]->set_flags( ctx[S], srec->msg[S], 0, F_DELETED, 0 )) {
 					case DRV_STORE_BAD: ret = SYNC_BAD(S); goto finish;
 					case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
 					default: /* ok */ break;