From 0b8120d0d1e4d9970059c577bccb401703f52235 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 1 Sep 2001 21:41:39 +0000 Subject: [PATCH] Added function for shaking down the bucket file. --- lib/bucket.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++-- lib/bucket.h | 3 ++ 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/lib/bucket.c b/lib/bucket.c index abe97672..e073e6df 100644 --- a/lib/bucket.c +++ b/lib/bucket.c @@ -11,6 +11,7 @@ #include "lib/conf.h" #include +#include #include #include #include @@ -25,11 +26,13 @@ static sh_off_t bucket_start; byte *obuck_name = "not/configured"; static int obuck_io_buflen = 65536; +static int obuck_shake_buflen = 1048576; static struct cfitem obuck_config[] = { { "Buckets", CT_SECTION, NULL }, { "BucketFile", CT_STRING, &obuck_name }, { "BufSize", CT_INT, &obuck_io_buflen }, + { "ShakeBufSize", CT_INT, &obuck_shake_buflen }, { NULL, CT_STOP, NULL } }; @@ -110,9 +113,7 @@ obuck_fb_refill(struct fastbuf *f) obuck_remains -= limit; if (!obuck_remains) /* Should check the trailer */ { - u32 check; - memcpy(&check, f->buffer + size - 4, 4); - if (check != OBUCK_TRAILER) + if (GET_U32(f->buffer + size - 4) != OBUCK_TRAILER) obuck_broken("Missing trailer"); } return limit; @@ -315,6 +316,99 @@ obuck_delete(oid_t oid) obuck_unlock(); } +/*** Shakedown ***/ + +void +obuck_shakedown(int (*kibitz)(struct obuck_header *old, oid_t new, byte *buck)) +{ + byte *rbuf, *wbuf; + sh_off_t rstart, wstart, w_bucket_start; + int roff, woff, rsize, l; + struct obuck_header *rhdr, *whdr; + + rbuf = xmalloc(obuck_shake_buflen); + wbuf = xmalloc(obuck_shake_buflen); + rstart = wstart = 0; + roff = woff = rsize = 0; + + /* We need to be the only accessor, all the object ID's are becoming invalid */ + obuck_lock_write(); + + for(;;) + { + bucket_start = rstart + roff; + w_bucket_start = wstart + woff; + if (rsize - roff < OBUCK_ALIGN) + goto reread; + rhdr = (struct obuck_header *)(rbuf + roff); + if (rhdr->magic != OBUCK_MAGIC || + rhdr->oid != OBUCK_OID_DELETED && rhdr->oid != (bucket_start >> OBUCK_SHIFT)) + obuck_broken("header mismatch during shakedown"); + l = (sizeof(struct obuck_header) + rhdr->length + 4 + OBUCK_ALIGN - 1) & ~(OBUCK_ALIGN-1); + if (rsize - roff < l) + goto reread; + if (GET_U32(rbuf + roff + l - 4) != OBUCK_TRAILER) + obuck_broken("missing trailer during shakedown"); + if (rhdr->oid != OBUCK_OID_DELETED && + kibitz(rhdr, w_bucket_start >> OBUCK_SHIFT, (byte *)(rhdr+1))) + { + if (bucket_start == w_bucket_start) + { + /* No copying needed now nor ever in the past, hence woff==0 */ + wstart += l; + } + else + { + if (obuck_shake_buflen - woff < l) + { + if (sh_pwrite(obuck_fd, wbuf, woff, wstart) != woff) + die("obuck_shakedown write failed: %m"); + wstart += woff; + woff = 0; + } + whdr = (struct obuck_header *)(wbuf+woff); + memcpy(whdr, rhdr, l); + whdr->oid = w_bucket_start >> OBUCK_SHIFT; + woff += l; + } + } + else + kibitz(rhdr, OBUCK_OID_DELETED, NULL); + roff += l; + continue; + + reread: + if (roff) + { + memmove(rbuf, rbuf+roff, rsize-roff); + rsize -= roff; + rstart += roff; + roff = 0; + } + l = sh_pread(obuck_fd, rbuf+rsize, obuck_shake_buflen-rsize, rstart+rsize); + if (l < 0) + die("obuck_shakedown read error: %m"); + if (!l) + { + if (!rsize) + break; + obuck_broken("unexpected EOF during shakedown"); + } + rsize += l; + } + if (woff) + { + if (sh_pwrite(obuck_fd, wbuf, woff, wstart) != woff) + die("obuck_shakedown write failed: %m"); + wstart += woff; + } + sh_ftruncate(obuck_fd, wstart); + + obuck_unlock(); + xfree(rbuf); + xfree(wbuf); +} + /*** Testing ***/ #ifdef TEST diff --git a/lib/bucket.h b/lib/bucket.h index bdf35e81..759ef0e4 100644 --- a/lib/bucket.h +++ b/lib/bucket.h @@ -62,3 +62,6 @@ static inline sh_off_t obuck_get_pos(oid_t oid) { return ((sh_off_t) oid) << OBUCK_SHIFT; } + +/* Shaking down bucket file */ +void obuck_shakedown(int (*kibitz)(struct obuck_header *old, oid_t new, byte *buck)); -- 2.39.2