From f501fcf311379b78506474478a17d82382b753e4 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 19 Apr 2011 15:07:15 +0200 Subject: [PATCH] Fastbufs: Clean up exception handling All exceptions now reside in the "ucw.fb" namespace, bthrow() takes care of adding this prefix. "ucw.fb.eof" is used systematically, even at places when a read error was reported previously. Exceptions have been documented. --- ucw/doc/fastbuf.txt | 15 +++++++++++++++ ucw/fastbuf.c | 22 ++++++++++++---------- ucw/fb-atomic.c | 6 +++--- ucw/fb-buffer.c | 4 ++-- ucw/fb-direct.c | 4 ++-- ucw/fb-file.c | 12 ++++++------ ucw/fb-grow.c | 2 +- ucw/fb-limfd.c | 2 +- ucw/fb-mem.c | 2 +- ucw/fb-mmap.c | 6 +++--- ucw/fb-param.c | 4 ++-- ucw/fb-temp.c | 2 +- 12 files changed, 49 insertions(+), 32 deletions(-) diff --git a/ucw/doc/fastbuf.txt b/ucw/doc/fastbuf.txt index 47109906..1578e760 100644 --- a/ucw/doc/fastbuf.txt +++ b/ucw/doc/fastbuf.txt @@ -40,6 +40,7 @@ When the pool gets cleaned up, the fastbuf is automatically closed. If you call .Other reading: - <> - <> +- <> ucw/fastbuf.h ------------- @@ -66,3 +67,17 @@ ucw/ff-binary.h --------------- !!ucw/ff-binary.h + +Exceptions [[fbexc]] +-------------------- + +All standard back-ends and front-ends raise exceptions on errors. All such +exceptions live in the `ucw.fb` subtree. The following exceptions are defined: + +`ucw.fb.eof`:: Unexpected end of file (e.g., when the @FB_DIE_ON_EOF flag is set) +`ucw.fb.mmap`:: Memory mapping failed (e.g., the `mmap` syscall has failed) +`ucw.fb.open`:: Opening failed (file does not exist and similar problems) +`ucw.fb.read`:: Read error (e.g., the `read` syscall has failed or the stream is write-only) +`ucw.fb.seek`:: Seek error (e.g., file not seekable, or a seek behind EOF) +`ucw.fb.tmp`:: Creation of temporary file failed +`ucw.fb.write`:: Write error (e.g., the `write` syscall has failed or the stream is read-only) diff --git a/ucw/fastbuf.c b/ucw/fastbuf.c index 7bec4bfd..3c0481b3 100644 --- a/ucw/fastbuf.c +++ b/ucw/fastbuf.c @@ -32,15 +32,17 @@ void bclose(struct fastbuf *f) void NONRET bthrow(struct fastbuf *f, const char *id, const char *fmt, ...) { + DBG("FB: throwing %s", full_id); + char full_id[16]; + snprintf(full_id, sizeof(full_id), "ucw.fb.%s", id); ASSERT(!(f->flags & FB_DEAD)); /* Only one bthrow() is allowed before bclose() */ - DBG("FB: throwing %s", id); va_list args; va_start(args, fmt); if (!f->res) die("Fastbuf %s error: %s", f->name ? : "", stk_vprintf(fmt, args)); f->flags |= FB_DEAD; f->bptr = f->bstop = f->bufend; /* Reset the buffer to guard consecutive seek/read/write */ - trans_vthrow(id, f, fmt, args); + trans_vthrow(full_id, f, fmt, args); } int brefill(struct fastbuf *f, int allow_eof) @@ -48,7 +50,7 @@ int brefill(struct fastbuf *f, int allow_eof) DBG("FB: refill"); ASSERT(!(f->flags & FB_DEAD) && f->buffer <= f->bstop && f->bstop <= f->bptr && f->bptr <= f->bufend); if (!f->refill) - bthrow(f, "fb.read", "Stream not readable"); + bthrow(f, "read", "Stream not readable"); if (f->refill(f)) { ASSERT(f->buffer <= f->bptr && f->bptr < f->bstop && f->bstop <= f->bufend); @@ -58,7 +60,7 @@ int brefill(struct fastbuf *f, int allow_eof) { ASSERT(f->buffer <= f->bptr && f->bptr == f->bstop && f->bstop <= f->bufend); if (!allow_eof && (f->flags & FB_DIE_ON_EOF)) - bthrow(f, "fb.eof", "Unexpected EOF"); + bthrow(f, "eof", "Unexpected EOF"); return 0; } } @@ -68,7 +70,7 @@ static void do_spout(struct fastbuf *f) DBG("FB: spout"); ASSERT(!(f->flags & FB_DEAD) && f->buffer <= f->bstop && f->bstop <= f->bptr && f->bptr <= f->bufend); /* Check write mode possibly with unflushed data */ if (!f->spout) - bthrow(f, "fb.write", "Stream not writeable"); + bthrow(f, "write", "Stream not writeable"); f->spout(f); ASSERT(f->buffer <= f->bstop && f->bstop <= f->bptr && f->bptr <= f->bufend); } @@ -97,7 +99,7 @@ static void do_seek(struct fastbuf *f, ucw_off_t pos, int whence) bflush(f); DBG("FB: seeking to pos=%lld whence=%d %p %p %p %p", (long long)pos, whence, f->buffer, f->bstop, f->bptr, f->bufend); if (!f->seek || !f->seek(f, pos, whence)) - bthrow(f, "fb.seek", "Stream not seekable"); + bthrow(f, "seek", "Stream not seekable"); DBG("FB: seeked %p %p %p %p", f->buffer, f->bstop, f->bptr, f->bufend); ASSERT(f->buffer <= f->bstop && f->bstop <= f->bptr && f->bptr <= f->bufend); if (whence == SEEK_SET) @@ -114,7 +116,7 @@ inline void bsetpos(struct fastbuf *f, ucw_off_t pos) else if (pos != btell(f)) { if (pos < 0) - bthrow(f, "fb.seek", "Seek out of range"); + bthrow(f, "seek", "Seek out of range"); do_seek(f, pos, SEEK_SET); } } @@ -131,7 +133,7 @@ void bseek(struct fastbuf *f, ucw_off_t pos, int whence) break; case SEEK_END: if (pos > 0) - bthrow(f, "fb.seek", "Seek out of range"); + bthrow(f, "seek", "Seek out of range"); do_seek(f, pos, SEEK_END); break; default: @@ -192,7 +194,7 @@ uns bread_slow(struct fastbuf *f, void *b, uns l, uns check) total += k; } if (check && total && l) - bthrow(f, "fb.read", "breadb: short read"); + bthrow(f, "eof", "breadb: short read"); return total; } @@ -228,7 +230,7 @@ void bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l) { if (l == ~0U) return; - bthrow(f, "fb.read", "bbcopy: source exhausted"); + bthrow(f, "eof", "bbcopy: source exhausted"); } tavail = bdirect_write_prepare(t, &tptr); n = MIN(l, favail); diff --git a/ucw/fb-atomic.c b/ucw/fb-atomic.c index 1dce8f08..227e324c 100644 --- a/ucw/fb-atomic.c +++ b/ucw/fb-atomic.c @@ -54,9 +54,9 @@ fbatomic_internal_write(struct fastbuf *f) ASSERT(af->record_len < 0 || !(size % af->record_len)); int res = write(af->fd, f->buffer, size); if (res < 0) - bthrow(f, "fb.write", "Error writing %s: %m", f->name); + bthrow(f, "write", "Error writing %s: %m", f->name); if (res != size) - bthrow(f, "fb.write", "Unexpected partial write to %s: written only %d bytes of %d", f->name, res, size); + bthrow(f, "write", "Unexpected partial write to %s: written only %d bytes of %d", f->name, res, size); f->bptr = f->buffer; } } @@ -113,7 +113,7 @@ fbatomic_open(const char *name, struct fastbuf *master, uns bufsize, int record_ { int fd = ucw_open(name, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0666); if (fd < 0) - trans_throw("fb.open", NULL, "Cannot create %s: %m", name); + trans_throw("ucw.fb.open", NULL, "Cannot create %s: %m", name); af = xmalloc_zero(sizeof(*af) + strlen(name)); af->fd = fd; af->use_count = 1; diff --git a/ucw/fb-buffer.c b/ucw/fb-buffer.c index e0350f37..846ff8f9 100644 --- a/ucw/fb-buffer.c +++ b/ucw/fb-buffer.c @@ -29,7 +29,7 @@ fbbuf_seek(struct fastbuf *f, ucw_off_t pos, int whence) if (whence == SEEK_END) pos += len; if (pos < 0 || pos > len) - bthrow(f, "fb.seek", "Seek out of range"); + bthrow(f, "seek", "Seek out of range"); f->bptr = f->buffer + pos; f->bstop = f->buffer; f->pos = 0; @@ -54,7 +54,7 @@ fbbuf_init_read(struct fastbuf *f, byte *buf, uns size, uns can_overwrite) static void fbbuf_spout(struct fastbuf *f) { - bthrow(f, "fb.write", "fbbuf: buffer overflow on write"); + bthrow(f, "write", "fbbuf: buffer overflow on write"); } void diff --git a/ucw/fb-direct.c b/ucw/fb-direct.c index eb1144ca..74249a31 100644 --- a/ucw/fb-direct.c +++ b/ucw/fb-direct.c @@ -159,7 +159,7 @@ fbdir_refill(struct fastbuf *f) if (!r->status) return 0; if (r->status < 0) - bthrow(f, "fb.read", "Error reading %s: %s", f->name, strerror(r->returned_errno)); + bthrow(f, "read", "Error reading %s: %s", f->name, strerror(r->returned_errno)); f->bptr = f->buffer = r->buffer; f->bstop = f->bufend = f->buffer + r->status; f->pos += r->status; @@ -193,7 +193,7 @@ fbdir_spout(struct fastbuf *f) asio_sync(F->io_queue); DBG("FB-DIRECT: Truncating at %llu", (long long)f->pos); if (ucw_ftruncate(F->fd, f->pos) < 0) - bthrow(f, "fb.write", "Error truncating %s: %m", f->name); + bthrow(f, "write", "Error truncating %s: %m", f->name); } else asio_submit(r); diff --git a/ucw/fb-file.c b/ucw/fb-file.c index a7af6108..d995451c 100644 --- a/ucw/fb-file.c +++ b/ucw/fb-file.c @@ -56,7 +56,7 @@ long_seek: int l = read(F->fd, f->buffer, MIN(skip, blen)); if (unlikely(l <= 0)) if (l < 0) - bthrow(f, "fb.read", "Error reading %s: %m", f->name); + bthrow(f, "read", "Error reading %s: %m", f->name); else { F->wpos -= skip; @@ -114,14 +114,14 @@ seek: /* Do lseek() */ F->wpos = f->pos + (f->buffer - f->bptr); if (ucw_seek(F->fd, F->wpos, SEEK_SET) < 0) - bthrow(f, "fb.read", "Error seeking %s: %m", f->name); + bthrow(f, "read", "Error seeking %s: %m", f->name); } /* Read (part of) buffer */ do { int l = read(F->fd, read_ptr, read_len); if (unlikely(l < 0)) - bthrow(f, "fb.read", "Error reading %s: %m", f->name); + bthrow(f, "read", "Error reading %s: %m", f->name); if (!l) if (unlikely(read_ptr < f->bptr)) goto eof; @@ -149,7 +149,7 @@ bfd_spout(struct fastbuf *f) { /* Do delayed lseek() if needed */ if (FB_FILE(f)->wpos != f->pos && ucw_seek(FB_FILE(f)->fd, f->pos, SEEK_SET) < 0) - bthrow(f, "fb.write", "Error seeking %s: %m", f->name); + bthrow(f, "write", "Error seeking %s: %m", f->name); int l = f->bptr - f->buffer; byte *c = f->buffer; @@ -161,7 +161,7 @@ bfd_spout(struct fastbuf *f) { int z = write(FB_FILE(f)->fd, c, l); if (z <= 0) - bthrow(f, "fb.write", "Error writing %s: %m", f->name); + bthrow(f, "write", "Error writing %s: %m", f->name); l -= z; c += z; } @@ -181,7 +181,7 @@ bfd_seek(struct fastbuf *f, ucw_off_t pos, int whence) case SEEK_END: ; ucw_off_t l = ucw_seek(FB_FILE(f)->fd, pos, SEEK_END); if (l < 0) - bthrow(f, "fb.seek", "Error seeking %s: %m", f->name); + bthrow(f, "seek", "Error seeking %s: %m", f->name); FB_FILE(f)->wpos = f->pos = l; FB_FILE(f)->wlen = 0; return 1; diff --git a/ucw/fb-grow.c b/ucw/fb-grow.c index 803e411e..f6131536 100644 --- a/ucw/fb-grow.c +++ b/ucw/fb-grow.c @@ -56,7 +56,7 @@ static int fbgrow_seek(struct fastbuf *b, ucw_off_t pos, int whence) if (whence == SEEK_END) pos += len; if (pos < 0 || pos > len) - bthrow(b, "fb.seek", "Seek out of range"); + bthrow(b, "seek", "Seek out of range"); b->bptr = b->buffer + pos; b->bstop = b->buffer; b->pos = 0; diff --git a/ucw/fb-limfd.c b/ucw/fb-limfd.c index 75733fba..76e728a4 100644 --- a/ucw/fb-limfd.c +++ b/ucw/fb-limfd.c @@ -27,7 +27,7 @@ bfl_refill(struct fastbuf *f) int max = MIN(FB_LIMFD(f)->limit - f->pos, f->bufend - f->buffer); int l = read(FB_LIMFD(f)->fd, f->buffer, max); if (l < 0) - bthrow(f, "fb.read", "Error reading %s: %m", f->name); + bthrow(f, "read", "Error reading %s: %m", f->name); f->bstop = f->buffer + l; f->pos += l; return l; diff --git a/ucw/fb-mem.c b/ucw/fb-mem.c index 61e94dad..92e3b497 100644 --- a/ucw/fb-mem.c +++ b/ucw/fb-mem.c @@ -128,7 +128,7 @@ fbmem_seek(struct fastbuf *f, ucw_off_t pos, int whence) FB_MEM(f)->block = NULL; return 1; } - bthrow(f, "fb.seek", "fbmem_seek to invalid offset"); + bthrow(f, "seek", "fbmem_seek to an invalid offset"); } static void diff --git a/ucw/fb-mmap.c b/ucw/fb-mmap.c index 2704d073..fa0f03e0 100644 --- a/ucw/fb-mmap.c +++ b/ucw/fb-mmap.c @@ -72,7 +72,7 @@ bfmm_map_window(struct fastbuf *f) if (f->buffer == (byte *) MAP_FAILED) { f->buffer = NULL; - bthrow(f, "fb.mmap", "mmap(%s): %m", f->name); + bthrow(f, "mmap", "mmap(%s): %m", f->name); } #ifdef MADV_SEQUENTIAL if (ll > CPU_PAGE_SIZE) @@ -118,7 +118,7 @@ bfmm_spout(struct fastbuf *f) { F->file_extend = ALIGN_TO(F->file_extend + mmap_extend_size, (ucw_off_t)CPU_PAGE_SIZE); if (ucw_ftruncate(F->fd, F->file_extend)) - bthrow(f, "fb.write", "ftruncate(%s): %m", f->name); + bthrow(f, "write", "ftruncate(%s): %m", f->name); } bfmm_map_window(f); f->bstop = f->bptr; @@ -148,7 +148,7 @@ bfmm_close(struct fastbuf *f) if (!(f->flags & FB_DEAD) && F->file_extend > F->file_size && ucw_ftruncate(F->fd, F->file_size)) - bthrow(f, "fb.write", "ftruncate(%s): %m", f->name); + bthrow(f, "write", "ftruncate(%s): %m", f->name); bclose_file_helper(f, F->fd, F->is_temp_file); xfree(f); } diff --git a/ucw/fb-param.c b/ucw/fb-param.c index 7543220f..e59444cb 100644 --- a/ucw/fb-param.c +++ b/ucw/fb-param.c @@ -102,7 +102,7 @@ bopen_fd_internal(int fd, struct fb_params *params, uns mode, const char *name) return fb; case FB_MMAP: if (!~mode && (int)(mode = fcntl(fd, F_GETFL)) < 0) - trans_throw("fb.open", NULL, "Cannot get flags of fd %d: %m", fd); + trans_throw("ucw.fb.open", NULL, "Cannot get flags of fd %d: %m", fd); return bfmmopen_internal(fd, name, mode); default: ASSERT(0); @@ -125,7 +125,7 @@ bopen_file_internal(const char *name, int mode, struct fb_params *params, int tr if (try) return NULL; else - trans_throw("fb.open", NULL, "Unable to %s file %s: %m", (mode & O_CREAT) ? "create" : "open", name); + trans_throw("ucw.fb.open", NULL, "Unable to %s file %s: %m", (mode & O_CREAT) ? "create" : "open", name); struct fastbuf *fb = bopen_fd_internal(fd, params, mode, name); ASSERT(fb); if (mode & O_APPEND) diff --git a/ucw/fb-temp.c b/ucw/fb-temp.c index a68eb582..d9a31274 100644 --- a/ucw/fb-temp.c +++ b/ucw/fb-temp.c @@ -35,7 +35,7 @@ void bfix_tmp_file(struct fastbuf *fb, const char *name) int was_temp = bconfig(fb, BCONFIG_IS_TEMP_FILE, 0); ASSERT(was_temp == 1); if (rename(fb->name, name)) - bthrow(fb, "fb.tmp", "Cannot rename %s to %s: %m", fb->name, name); + bthrow(fb, "tmp", "Cannot rename %s to %s: %m", fb->name, name); bclose(fb); } -- 2.39.2