]> mj.ucw.cz Git - libucw.git/commitdiff
Fastbufs: Clean up exception handling
authorMartin Mares <mj@ucw.cz>
Tue, 19 Apr 2011 13:07:15 +0000 (15:07 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 19 Apr 2011 13:07:15 +0000 (15:07 +0200)
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.

12 files changed:
ucw/doc/fastbuf.txt
ucw/fastbuf.c
ucw/fb-atomic.c
ucw/fb-buffer.c
ucw/fb-direct.c
ucw/fb-file.c
ucw/fb-grow.c
ucw/fb-limfd.c
ucw/fb-mem.c
ucw/fb-mmap.c
ucw/fb-param.c
ucw/fb-temp.c

index 47109906c9d7bf739c97634334f695dc95bc316f..1578e7607fcfc6603a9d48fb0b8df66d04feda5a 100644 (file)
@@ -40,6 +40,7 @@ When the pool gets cleaned up, the fastbuf is automatically closed. If you call
 .Other reading:
 - <<internal,Internal structure>>
 - <<bconfig,Configuring streams>>
+- <<fbexc,Exceptions>>
 
 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)
index 7bec4bfd4b08b8d9a20b53f249cd2fbb8d700f03..3c0481b3a9b93d33708873347a8f3c8bc04e5864 100644 (file)
@@ -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 ? : "<fb>", 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);
index 1dce8f08e1ab10a6add345018cb4a5616486a4ac..227e324cb929bb0dbc21d47bf2b77fd7533dbba1 100644 (file)
@@ -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;
index e0350f374f30fb99745cbeda3fd2cf899b9c304b..846ff8f9814b94aece359f873959562549073545 100644 (file)
@@ -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
index eb1144cae6ec321dcdb84400c5b02564d04db813..74249a31feb589525fe7b587cb7aedae5f461b7e 100644 (file)
@@ -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);
index a7af6108742fcd4f7326bf1bc17b4f58384dbaaf..d995451c75bfab283c56c1ab773bf306bdc1be84 100644 (file)
@@ -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;
index 803e411e651b7659eeb5afd4d6ab3e3247e1e8f8..f6131536662a3c2c4ff25123192e09d4af6aefa4 100644 (file)
@@ -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;
index 75733fba9537486f4d7ecefe8aed92fb48880614..76e728a495b34718c137924e36f44bacc085814d 100644 (file)
@@ -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;
index 61e94dadb52ed2ace1d074a317e3d8d5b9762506..92e3b4972a4e358093762b5c83c077d51ebcd2ee 100644 (file)
@@ -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
index 2704d07362550209b7b9a4c3bd5a10a88904538b..fa0f03e03232bf6fa0b734e767278a967eb44e9f 100644 (file)
@@ -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);
 }
index 7543220fa0e89a5853626945415453d0f449f2da..e59444cbde876cf440dc3f4a263e3b89f9ded0f8 100644 (file)
@@ -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)
index a68eb5824d86cfd11c4a3151c0962896de793314..d9a31274ad7bc126ff27841981dc4295702d4446 100644 (file)
@@ -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);
 }