Просмотр исходного кода

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 лет назад
Родитель
Сommit
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;