فهرست منبع

make sync state header format less obscure

the header is not space-critical, so use proper name-value pairs.
this has the additional advantage that subsequent format changes can be
done much easier.
Oswald Buddenhagen 11 سال پیش
والد
کامیت
48754ecc74
2فایلهای تغییر یافته به همراه109 افزوده شده و 47 حذف شده
  1. 58 29
      src/run-tests.pl
  2. 51 18
      src/sync.c

+ 58 - 29
src/run-tests.pl

@@ -364,16 +364,24 @@ sub showstate($)
 	}
 	chomp(my @ls = <FILE>);
 	close FILE;
-	$_ = shift(@ls);
-	if (!defined $_) {
-		print STDERR " Missing sync state header.\n";
-		return;
-	}
-	if (!/^1:(\d+) 1:(\d+):(\d+)$/) {
-		print STDERR " Malformed sync state header '$_'.\n";
+	my %hdr;
+	OUTER: while (1) {
+		while (@ls) {
+			$_ = shift(@ls);
+			last OUTER if (!length($_));
+			if (!/^([^ ]+) (\d+)$/) {
+				print STDERR "Malformed sync state header entry: $_\n";
+				close FILE;
+				return;
+			}
+			$hdr{$1} = $2;
+		}
+		print STDERR "Unterminated sync state header.\n";
+		close FILE;
 		return;
 	}
-	print " [ $1, $2, $3,\n   ";
+	print " [ ".($hdr{'MaxPulledUid'} // "missing").", ".
+	            ($hdr{'MaxExpiredSlaveUid'} // "0").", ".($hdr{'MaxPushedUid'} // "missing").",\n   ";
 	my $frst = 1;
 	for (@ls) {
 		if ($frst) {
@@ -456,7 +464,8 @@ sub mkchan($$@)
 	&mkbox("slave", @{ $s });
 	open(FILE, ">", "slave/.mbsyncstate") or
 		die "Cannot create sync state.\n";
-	print FILE "1:".shift(@t)." 1:".shift(@t).":".shift(@t)."\n";
+	print FILE "MasterUidValidity 1\nMaxPulledUid ".shift(@t)."\n".
+	           "SlaveUidValidity 1\nMaxExpiredSlaveUid ".shift(@t)."\nMaxPushedUid ".shift(@t)."\n\n";
 	while (@t) {
 		print FILE shift(@t)." ".shift(@t)." ".shift(@t)."\n";
 	}
@@ -499,36 +508,56 @@ sub ckbox($$$@)
 # $filename, @syncstate
 sub ckstate($@)
 {
-	my ($fn, @T) = @_;
+	my ($fn, $mmaxuid, $smaxxuid, $smaxuid, @T) = @_;
+	my %hdr;
+	$hdr{'MasterUidValidity'} = "1";
+	$hdr{'SlaveUidValidity'} = "1";
+	$hdr{'MaxPulledUid'} = $mmaxuid;
+	$hdr{'MaxPushedUid'} = $smaxuid;
+	$hdr{'MaxExpiredSlaveUid'} = $smaxxuid if ($smaxxuid ne 0);
 	open(FILE, "<", $fn) or die "Cannot read sync state $fn.\n";
-	my $l = <FILE>;
 	chomp(my @ls = <FILE>);
 	close FILE;
-	if (!defined $l) {
-		print STDERR "Sync state header missing.\n";
-		return 1;
-	}
-	chomp($l);
-	my $xl = "1:".shift(@T)." 1:".shift(@T).":".shift(@T);
-	if ($l ne $xl) {
-		print STDERR "Sync state header mismatch: '$l' instead of '$xl'.\n";
-		return 1;
-	} else {
-		for $l (@ls) {
-			if (!@T) {
-				print STDERR "Excess sync state entry: '$l'.\n";
+	OUTER: while (1) {
+		while (@ls) {
+			my $l = shift(@ls);
+			last OUTER if (!length($l));
+			if ($l !~ /^([^ ]+) (\d+)$/) {
+				print STDERR "Malformed sync state header entry: $l\n";
+				return 1;
+			}
+			my $want = delete $hdr{$1};
+			if (!defined($want)) {
+				print STDERR "Unexpected sync state header entry: $1\n";
 				return 1;
 			}
-			$xl = shift(@T)." ".shift(@T)." ".shift(@T);
-			if ($l ne $xl) {
-				print STDERR "Sync state entry mismatch: '$l' instead of '$xl'.\n";
+			if ($2 != $want) {
+				print STDERR "Sync state header entry $1 mismatch: got $2, wanted $want\n";
 				return 1;
 			}
 		}
-		if (@T) {
-			print STDERR "Missing sync state entry: '".shift(@T)." ".shift(@T)." ".shift(@T)."'.\n";
+		print STDERR "Unterminated sync state header.\n";
+		return 1;
+	}
+	my @ky = keys %hdr;
+	if (@ky) {
+		print STDERR "Keys missing from sync state header: @ky\n";
+		return 1;
+	}
+	for my $l (@ls) {
+		if (!@T) {
+			print STDERR "Excess sync state entry: '$l'.\n";
 			return 1;
 		}
+		my $xl = shift(@T)." ".shift(@T)." ".shift(@T);
+		if ($l ne $xl) {
+			print STDERR "Sync state entry mismatch: '$l' instead of '$xl'.\n";
+			return 1;
+		}
+	}
+	if (@T) {
+		print STDERR "Missing sync state entry: '".shift(@T)." ".shift(@T)." ".shift(@T)."'.\n";
+		return 1;
 	}
 	return 0;
 }

+ 51 - 18
src/sync.c

@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <time.h>
 #include <fcntl.h>
+#include <ctype.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/stat.h>
@@ -723,22 +724,51 @@ box_selected( int sts, void *aux )
 	}
 	if ((jfp = fopen( svars->dname, "r" ))) {
 		debug( "reading sync state %s ...\n", svars->dname );
-		if (!fgets( buf, sizeof(buf), jfp ) || !(t = strlen( buf )) || buf[t - 1] != '\n') {
-			error( "Error: incomplete sync state header in %s\n", svars->dname );
-		  jbail:
-			fclose( jfp );
-		  bail:
-			svars->ret = SYNC_FAIL;
-			sync_bail( svars );
-			return;
-		}
-		if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 ||
-		    sscanf( buf1, "%d:%d", &svars->uidval[M], &svars->maxuid[M] ) < 2 ||
-		    sscanf( buf2, "%d:%d:%d", &svars->uidval[S], &svars->smaxxuid, &svars->maxuid[S] ) < 3) {
-			error( "Error: invalid sync state header in %s\n", svars->dname );
-			goto jbail;
+		line = 0;
+		while (fgets( buf, sizeof(buf), jfp )) {
+			line++;
+			if (!(t = strlen( buf )) || buf[t - 1] != '\n') {
+				error( "Error: incomplete sync state header entry at %s:%d\n", svars->dname, line );
+			  jbail:
+				fclose( jfp );
+			  bail:
+				svars->ret = SYNC_FAIL;
+				sync_bail( svars );
+				return;
+			}
+			if (t == 1)
+				goto gothdr;
+			if (line == 1 && isdigit( buf[0] )) {
+				if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 ||
+				    sscanf( buf1, "%d:%d", &svars->uidval[M], &svars->maxuid[M] ) < 2 ||
+				    sscanf( buf2, "%d:%d:%d", &svars->uidval[S], &svars->smaxxuid, &svars->maxuid[S] ) < 3) {
+					error( "Error: invalid sync state header in %s\n", svars->dname );
+					goto jbail;
+				}
+				goto gothdr;
+			}
+			if (sscanf( buf, "%63s %d", buf1, &t1 ) != 2) {
+				error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line );
+				goto jbail;
+			}
+			if (!strcmp( buf1, "MasterUidValidity" ))
+				svars->uidval[M] = t1;
+			else if (!strcmp( buf1, "SlaveUidValidity" ))
+				svars->uidval[S] = t1;
+			else if (!strcmp( buf1, "MaxPulledUid" ))
+				svars->maxuid[M] = t1;
+			else if (!strcmp( buf1, "MaxPushedUid" ))
+				svars->maxuid[S] = t1;
+			else if (!strcmp( buf1, "MaxExpiredSlaveUid" ))
+				svars->smaxxuid = t1;
+			else {
+				error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line );
+				goto jbail;
+			}
 		}
-		line = 1;
+		error( "Error: unterminated sync state header in %s\n", svars->dname );
+		goto jbail;
+	  gothdr:
 		while (fgets( buf, sizeof(buf), jfp )) {
 			line++;
 			if (!(t = strlen( buf )) || buf[t - 1] != '\n') {
@@ -1747,9 +1777,12 @@ box_closed_p2( sync_vars_t *svars, int t )
 		}
 	}
 
-	Fprintf( svars->nfp, "%d:%d %d:%d:%d\n",
-	         svars->uidval[M], svars->maxuid[M],
-	         svars->uidval[S], svars->smaxxuid, svars->maxuid[S] );
+	Fprintf( svars->nfp,
+	         "MasterUidValidity %d\nSlaveUidValidity %d\nMaxPulledUid %d\nMaxPushedUid %d\n",
+	         svars->uidval[M], svars->uidval[S], svars->maxuid[M], svars->maxuid[S] );
+	if (svars->smaxxuid)
+		Fprintf( svars->nfp, "MaxExpiredSlaveUid %d\n", svars->smaxxuid );
+	Fprintf( svars->nfp, "\n" );
 	for (srec = svars->srecs; srec; srec = srec->next) {
 		if (srec->status & S_DEAD)
 			continue;