commit 48754ecc74123d4405999e3e5e720779d7a10bd2
parent 83bb1cf716d5f44b773b952aa789aadac04171b2
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date: Sat, 16 Nov 2013 13:25:31 +0100
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.
Diffstat:
M | src/run-tests.pl | | | 87 | +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
M | src/sync.c | | | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++------------------ |
2 files changed, 109 insertions(+), 47 deletions(-)
diff --git a/src/run-tests.pl b/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;
}
diff --git a/src/sync.c b/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;