diff -Nurd cdb-0.75.orig/FILES cdb-0.75/FILES --- cdb-0.75.orig/FILES Sat Feb 19 20:42:05 2000 +++ cdb-0.75/FILES Sun Oct 19 11:21:02 2003 @@ -1,4 +1,5 @@ README +README.cdbpatch TODO CHANGES VERSION @@ -11,6 +12,7 @@ Makefile cdbget.c cdbmake.c +cdbpatch.c cdbdump.c cdbstats.c cdbtest.c diff -Nurd cdb-0.75.orig/Makefile cdb-0.75/Makefile --- cdb-0.75.orig/Makefile Sat Feb 19 20:42:05 2000 +++ cdb-0.75/Makefile Sun Oct 19 11:21:02 2003 @@ -142,6 +142,15 @@ uint32.h cdb.h uint32.h ./compile cdbmake.c +cdbpatch: \ +load cdbpatch.o cdb.a alloc.a buffer.a unix.a byte.a + ./load cdbpatch cdb.a alloc.a buffer.a unix.a byte.a + +cdbpatch.o: \ +compile cdbpatch.c error.h open.h strerr.h cdb_make.h buffer.h \ +uint32.h cdb.h uint32.h fmt.h alloc.h seek.h readwrite.h + ./compile cdbpatch.c + cdbstats: \ load cdbstats.o cdb.a buffer.a unix.a byte.a ./load cdbstats cdb.a buffer.a unix.a byte.a @@ -243,7 +252,7 @@ ./compile open_trunc.c prog: \ -cdbget cdbmake cdbdump cdbstats cdbtest cdbmake-12 cdbmake-sv rts \ +cdbget cdbmake cdbpatch cdbdump cdbstats cdbtest cdbmake-12 cdbmake-sv rts \ testzero rts: \ diff -Nurd cdb-0.75.orig/README.cdbpatch cdb-0.75/README.cdbpatch --- cdb-0.75.orig/README.cdbpatch Thu Jan 1 01:00:00 1970 +++ cdb-0.75/README.cdbpatch Sun Oct 19 11:21:02 2003 @@ -0,0 +1,59 @@ + +Like cdbmake, the cdbpatch program makes changes to a cdb by rebuilding the +database and renaming the new version into place. The difference is the +input format; cdbpatch reads the old version of the target cdb and a patch +file, rather than a flat file in cdbmake format. The intention is to allow +a set of changes to be made to a large cdb as efficiently as possible. + +The patch file is itself a cdb, in a special format. All values in the +patch cdb must either be of zero length or start with an '=' character. + +The new target cdb is generated as follows. + + First, entries are copied from the old target cdb to the new, skipping any + for which there is an entry in the patch cdb. + + Next, entries are copied from the patch cdb to the new target cdb. Entries + with zero length values are skipped, and the leading '=' is removed from + all values copied. + +In effect, entries with zero length values in the patch cdb are instructions +to delete entries, while entries with nonempty values are instructions to +add or replace entries. + +For example, if the old target cdb contains: + ++5,4:hello->wooo ++3,3:foo->foo ++3,1:foo->x ++3,3:bar->bar ++2,2:oh->ho ++2,2:hi->ho + + +and we wish to change it to: + ++3,3:foo->foo ++3,0:bar-> ++4,1:woot:x ++2,2:oh->ho ++2,2:hi->ho + + +then we would run this through cdbmake to build a patch cdb: + ++3,4:foo->=foo ++3,1:bar->= ++5,0:hello-> ++4,2:woot->=x + + +The cdbpatch program expects to read the old target cdb from fd 0 and the +patch cdb from fd 6. Both must be seekable. For example: + + cdbpatch len) r = len; + x = buffer_peek(&buffer_in); + if (buffer_put(&cdbout.b,x,r) == -1) die_write(); + buffer_seek(&buffer_in,r); + len -= r; + } +} + +uint32 copyh(unsigned int len) +{ + uint32 h = CDB_HASHSTART; + unsigned int i; + unsigned int r; + char *x; + + input_pos += len; + while (len) { + r = buffer_feed(&buffer_in); + if (r == -1) die_read(); + if (r == 0) die_trunc(); + if (r > len) r = len; + x = buffer_peek(&buffer_in); + for (i = 0;i < r;++i) + h = cdb_hashadd(h,x[i]); + if (buffer_put(&cdbout.b,x,r) == -1) die_write(); + buffer_seek(&buffer_in,r); + len -= r; + } + return h; +} + +void get(char *buf,unsigned int len) +{ + unsigned int r; + + input_pos += len; + while (len) { + r = buffer_get(&buffer_in,buf,len); + if (r == -1) die_read(); + if (r == 0) die_trunc(); + buf += r; + len -= r; + } +} + +char buf[512]; + +void skip(unsigned int bytes) { + while(bytes > sizeof buf) { + get(buf,sizeof buf); + bytes -= sizeof buf; + } + get(buf,bytes); +} + +void getnum(uint32 *num) +{ + get(buf,4); + uint32_unpack(buf,num); +} + +void buffer_in_init(int fd) +{ + input_pos = 0; + buffer_init(&buffer_in,buffer_in_read,fd, + buffer_in_space,sizeof buffer_in_space); + + getnum(&input_eod); + skip(2048 - input_pos); +} + +static struct cdb pcdb; + +#define KCAP 8192 +main(int argc,char **argv) +{ + int fd; + uint32 klen; + uint32 dlen; + uint32 h; + unsigned int i; + char ch; + unsigned int kcap; + char *kstore; + + if (!*argv) die_usage(); + + if (!*++argv) die_usage(); + fn = *argv; + + if (!*++argv) die_usage(); + fntmp = *argv; + + fd = open_trunc(fntmp); + if (fd == -1) die_write(); + + if (cdb_make_start(&cdbout,fd) == -1) die_write(); + + /* Copy any keys that aren't in the patch from old to new */ + kcap = KCAP; + kstore = alloc(kcap); + if (!kstore) die_nomem(); + cdb_init(&pcdb,PATCH_CDB_FD); + buffer_in_init(ORIG_CDB_FD); + while (input_pos < input_eod) { + getnum(&klen); + getnum(&dlen); + if (klen > kcap) { + while (klen > kcap) kcap *= 2; + alloc_free(kstore); + kstore = alloc(kcap); + if (!kstore) die_nomem(); + } + get(kstore, klen); + switch (cdb_find(&pcdb,kstore,klen)) { + case -1: + die_write(); + case 0: + h = cdb_hash(kstore,klen); + if (cdb_make_addbegin(&cdbout,klen,dlen) == -1) die_write(); + if (buffer_put(&cdbout.b,kstore,klen) == -1) die_write(); + copy(dlen); + if (cdb_make_addend(&cdbout,klen,dlen,h) == -1) die_write(); + break; + default: + skip(dlen); + } + } + cdb_free(&pcdb); + + /* Copy keys from patch to new */ + seek_begin(PATCH_CDB_FD); + buffer_in_init(PATCH_CDB_FD); + while (input_pos < input_eod) { + getnum(&klen); + getnum(&dlen); + if (dlen == 0) + skip(klen); + else { + --dlen; + if (cdb_make_addbegin(&cdbout,klen,dlen) == -1) die_write(); + h = copyh(klen); + get(&ch,1); + if (ch != '=') die_notpatch(); + copy(dlen); + if (cdb_make_addend(&cdbout,klen,dlen,h) == -1) die_write(); + } + } + + if (cdb_make_finish(&cdbout) == -1) die_write(); + if (fsync(fd) == -1) die_write(); + if (close(fd) == -1) die_write(); /* NFS silliness */ + if (rename(fntmp,fn) == -1) + strerr_die6sys(111,FATAL,"unable to rename ",fntmp," to ",fn,": "); + + _exit(0); +} + diff -Nurd cdb-0.75.orig/hier.c cdb-0.75/hier.c --- cdb-0.75.orig/hier.c Sat Feb 19 20:42:05 2000 +++ cdb-0.75/hier.c Sun Oct 19 11:21:02 2003 @@ -7,6 +7,7 @@ c(auto_home,"bin","cdbget",-1,-1,0755); c(auto_home,"bin","cdbmake",-1,-1,0755); + c(auto_home,"bin","cdbpatch",-1,-1,0755); c(auto_home,"bin","cdbdump",-1,-1,0755); c(auto_home,"bin","cdbstats",-1,-1,0755); c(auto_home,"bin","cdbtest",-1,-1,0755);