Change mfile_/cfile-functions to return error code(s) rather than exit.
authorAdam Dickmeiss <adam@indexdata.dk>
Wed, 8 Nov 2006 22:08:26 +0000 (22:08 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Wed, 8 Nov 2006 22:08:26 +0000 (22:08 +0000)
Added bf_read2 / bf_write2 which does not call exit for errors.

bfile/bfile.c
bfile/cfile.c
bfile/mfile.c
include/idzebra/bfile.h

index b05fc1d..7fb6a8c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bfile.c,v 1.50 2006-10-10 10:19:28 adam Exp $
+/* $Id: bfile.c,v 1.51 2006-11-08 22:08:27 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -62,12 +62,12 @@ struct BFiles_struct {
 
 BFiles bfs_create (const char *spec, const char *base)
 {
 
 BFiles bfs_create (const char *spec, const char *base)
 {
-    BFiles bfs = (BFiles) xmalloc (sizeof(*bfs));
-    bfs->commit_area = NULL;
+    BFiles bfs = (BFiles) xmalloc(sizeof(*bfs));
+    bfs->commit_area = 0;
     bfs->base = 0;
     bfs->cache_fname = 0;
     if (base)
     bfs->base = 0;
     bfs->cache_fname = 0;
     if (base)
-        bfs->base = xstrdup (base);
+        bfs->base = xstrdup(base);
     bfs->register_area = mf_init("register", spec, base);
     if (!bfs->register_area)
     {
     bfs->register_area = mf_init("register", spec, base);
     if (!bfs->register_area)
     {
@@ -77,44 +77,44 @@ BFiles bfs_create (const char *spec, const char *base)
     return bfs;
 }
 
     return bfs;
 }
 
-void bfs_destroy (BFiles bfs)
+void bfs_destroy(BFiles bfs)
 {
     if (!bfs)
         return;
 {
     if (!bfs)
         return;
-    xfree (bfs->cache_fname);
-    xfree (bfs->base);
-    mf_destroy (bfs->commit_area);
-    mf_destroy (bfs->register_area);
-    xfree (bfs);
+    xfree(bfs->cache_fname);
+    xfree(bfs->base);
+    mf_destroy(bfs->commit_area);
+    mf_destroy(bfs->register_area);
+    xfree(bfs);
 }
 
 }
 
-static FILE *open_cache (BFiles bfs, const char *flags)
+static FILE *open_cache(BFiles bfs, const char *flags)
 {
     FILE *file;
 
 {
     FILE *file;
 
-    file = fopen (bfs->cache_fname, flags);
+    file = fopen(bfs->cache_fname, flags);
     return file;
 }
 
     return file;
 }
 
-static void unlink_cache (BFiles bfs)
+static void unlink_cache(BFiles bfs)
 {
 {
-    unlink (bfs->cache_fname);
+    unlink(bfs->cache_fname);
 }
 
 }
 
-ZEBRA_RES bf_cache (BFiles bfs, const char *spec)
+ZEBRA_RES bf_cache(BFiles bfs, const char *spec)
 {
     if (spec)
     {
 {
     if (spec)
     {
-        yaz_log (YLOG_LOG, "enabling shadow spec=%s", spec);
+        yaz_log(YLOG_LOG, "enabling shadow spec=%s", spec);
         if (!bfs->commit_area)
         if (!bfs->commit_area)
-           bfs->commit_area = mf_init ("shadow", spec, bfs->base);
+           bfs->commit_area = mf_init("shadow", spec, bfs->base);
         if (bfs->commit_area)
         {
         if (bfs->commit_area)
         {
-            bfs->cache_fname = xmalloc (strlen(bfs->commit_area->dirs->name)+
+            bfs->cache_fname = xmalloc(strlen(bfs->commit_area->dirs->name)+
                                        8);
                                        8);
-            strcpy (bfs->cache_fname, bfs->commit_area->dirs->name);
-            strcat (bfs->cache_fname, "/cache");
-            yaz_log (YLOG_LOG, "cache_fname = %s", bfs->cache_fname);
+            strcpy(bfs->cache_fname, bfs->commit_area->dirs->name);
+            strcat(bfs->cache_fname, "/cache");
+            yaz_log(YLOG_LOG, "cache_fname = %s", bfs->cache_fname);
         }
        else
        {
         }
        else
        {
@@ -123,16 +123,17 @@ ZEBRA_RES bf_cache (BFiles bfs, const char *spec)
        }
     }
     else
        }
     }
     else
-        bfs->commit_area = NULL;
+        bfs->commit_area = 0;
     return ZEBRA_OK;
 }
 
     return ZEBRA_OK;
 }
 
-int bf_close (BFile bf)
+int bf_close(BFile bf)
 {
 {
-    zebra_lock_rdwr_destroy (&bf->rdwr_lock);
+    zebra_lock_rdwr_destroy(&bf->rdwr_lock);
     if (bf->cf)
     if (bf->cf)
-        cf_close (bf->cf);
-    mf_close (bf->mf);
+        cf_close(bf->cf);
+    if (bf->mf)
+        mf_close(bf->mf);
     xfree(bf->alloc_buf);
     xfree(bf->magic);
     xfree(bf);
     xfree(bf->alloc_buf);
     xfree(bf->magic);
     xfree(bf);
@@ -218,7 +219,7 @@ BFile bf_xopen(BFiles bfs, const char *name, int block_size, int wrflag,
     return bf;
 }
 
     return bf;
 }
 
-int bf_xclose (BFile bf, int version, const char *more_info)
+int bf_xclose(BFile bf, int version, const char *more_info)
 {
     if (bf->header_dirty)
     {
 {
     if (bf->header_dirty)
     {
@@ -240,21 +241,31 @@ int bf_xclose (BFile bf, int version, const char *more_info)
     return bf_close(bf);
 }
 
     return bf_close(bf);
 }
 
-BFile bf_open (BFiles bfs, const char *name, int block_size, int wflag)
+BFile bf_open(BFiles bfs, const char *name, int block_size, int wflag)
 {
 {
-    BFile bf = (BFile) xmalloc(sizeof(struct BFile_struct));
+    BFile bf = (BFile) xmalloc(sizeof(*bf));
 
     bf->alloc_buf = 0;
     bf->magic = 0;
     bf->block_size = block_size;
     bf->header_dirty = 0;
 
     bf->alloc_buf = 0;
     bf->magic = 0;
     bf->block_size = block_size;
     bf->header_dirty = 0;
+    bf->cf = 0;
+    bf->mf = 0;
+    zebra_lock_rdwr_init(&bf->rdwr_lock);
+
     if (bfs->commit_area)
     {
         int first_time;
 
     if (bfs->commit_area)
     {
         int first_time;
 
-        bf->mf = mf_open (bfs->register_area, name, block_size, 0);
-        bf->cf = cf_open (bf->mf, bfs->commit_area, name, block_size,
-                           wflag, &first_time);
+        bf->mf = mf_open(bfs->register_area, name, block_size, 0);
+        bf->cf = cf_open(bf->mf, bfs->commit_area, name, block_size,
+                         wflag, &first_time);
+        if (!bf->cf)
+        {
+            yaz_log(YLOG_FATAL, "cf_open failed for %s", name);
+            bf_close(bf);
+            return 0;
+        }
         if (first_time)
         {
             FILE *outf;
         if (first_time)
         {
             FILE *outf;
@@ -263,77 +274,104 @@ BFile bf_open (BFiles bfs, const char *name, int block_size, int wflag)
             if (!outf)
             {
                 yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", bfs->cache_fname);
             if (!outf)
             {
                 yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", bfs->cache_fname);
-                exit(1);
+                bf_close(bf);
+                return 0;
             }
             fprintf(outf, "%s %d\n", name, block_size);
             }
             fprintf(outf, "%s %d\n", name, block_size);
-            fclose(outf);
+            if (fclose(outf))
+            {
+                yaz_log(YLOG_FATAL|YLOG_ERRNO, "fclose %s", bfs->cache_fname);
+                bf_close(bf);
+                return 0;
+            }
         }
     }
     else
     {
         bf->mf = mf_open(bfs->register_area, name, block_size, wflag);
         }
     }
     else
     {
         bf->mf = mf_open(bfs->register_area, name, block_size, wflag);
-        bf->cf = NULL;
     }
     if (!bf->mf)
     {
         yaz_log(YLOG_FATAL, "mf_open failed for %s", name);
     }
     if (!bf->mf)
     {
         yaz_log(YLOG_FATAL, "mf_open failed for %s", name);
-        xfree(bf);
+        bf_close(bf);
         return 0;
     }
         return 0;
     }
-    zebra_lock_rdwr_init(&bf->rdwr_lock);
     return bf;
 }
 
     return bf;
 }
 
-int bf_read (BFile bf, zint no, int offset, int nbytes, void *buf)
+int bf_read(BFile bf, zint no, int offset, int nbytes, void *buf)
 {
 {
-    int r;
+    int ret = bf_read2(bf, no, offset, nbytes, buf);
 
 
-    zebra_lock_rdwr_rlock (&bf->rdwr_lock);
+    if (ret == -1)
+    {
+        exit(1);
+    }
+    return ret;
+}
+
+int bf_read2(BFile bf, zint no, int offset, int nbytes, void *buf)
+{
+    int ret;
+
+    zebra_lock_rdwr_rlock(&bf->rdwr_lock);
     if (bf->cf)
     {
     if (bf->cf)
     {
-       if ((r = cf_read (bf->cf, no, offset, nbytes, buf)) == -1)
-           r = mf_read (bf->mf, no, offset, nbytes, buf);
+       if ((ret = cf_read(bf->cf, no, offset, nbytes, buf)) == 0)
+           ret = mf_read(bf->mf, no, offset, nbytes, buf);
     }
     else 
     }
     else 
-       r = mf_read (bf->mf, no, offset, nbytes, buf);
-    zebra_lock_rdwr_runlock (&bf->rdwr_lock);
-    return r;
+       ret = mf_read(bf->mf, no, offset, nbytes, buf);
+    zebra_lock_rdwr_runlock(&bf->rdwr_lock);
+    return ret;
+}
+
+int bf_write(BFile bf, zint no, int offset, int nbytes, const void *buf)
+{
+    int ret = bf_write2(bf, no, offset, nbytes, buf);
+
+    if (ret == -1)
+    {
+        exit(1);
+    }
+    return ret;
 }
 
 }
 
-int bf_write (BFile bf, zint no, int offset, int nbytes, const void *buf)
+int bf_write2(BFile bf, zint no, int offset, int nbytes, const void *buf)
 {
     int r;
 {
     int r;
-    zebra_lock_rdwr_wlock (&bf->rdwr_lock);
+    zebra_lock_rdwr_wlock(&bf->rdwr_lock);
     if (bf->cf)
     if (bf->cf)
-        r = cf_write (bf->cf, no, offset, nbytes, buf);
+        r = cf_write(bf->cf, no, offset, nbytes, buf);
     else
     else
-       r = mf_write (bf->mf, no, offset, nbytes, buf);
-    zebra_lock_rdwr_wunlock (&bf->rdwr_lock);
+       r = mf_write(bf->mf, no, offset, nbytes, buf);
+    zebra_lock_rdwr_wunlock(&bf->rdwr_lock);
     return r;
 }
 
     return r;
 }
 
-int bf_commitExists (BFiles bfs)
+int bf_commitExists(BFiles bfs)
 {
     FILE *inf;
 
 {
     FILE *inf;
 
-    inf = open_cache (bfs, "rb");
+    inf = open_cache(bfs, "rb");
     if (inf)
     {
     if (inf)
     {
-        fclose (inf);
+        fclose(inf);
         return 1;
     }
     return 0;
 }
 
         return 1;
     }
     return 0;
 }
 
-void bf_reset (BFiles bfs)
+void bf_reset(BFiles bfs)
 {
     if (!bfs)
        return;
     mf_reset(bfs->commit_area, 1);
     mf_reset(bfs->register_area, 1);
 {
     if (!bfs)
        return;
     mf_reset(bfs->commit_area, 1);
     mf_reset(bfs->register_area, 1);
+    unlink_cache(bfs);
 }
 
 }
 
-void bf_commitExec (BFiles bfs)
+void bf_commitExec(BFiles bfs)
 {
     FILE *inf;
     int block_size;
 {
     FILE *inf;
     int block_size;
@@ -342,40 +380,40 @@ void bf_commitExec (BFiles bfs)
     CFile cf;
     int first_time;
 
     CFile cf;
     int first_time;
 
-    assert (bfs->commit_area);
-    if (!(inf = open_cache (bfs, "rb")))
+    assert(bfs->commit_area);
+    if (!(inf = open_cache(bfs, "rb")))
     {
     {
-        yaz_log (YLOG_LOG, "No commit file");
+        yaz_log(YLOG_LOG, "No commit file");
         return ;
     }
         return ;
     }
-    while (fscanf (inf, "%s %d", path, &block_size) == 2)
+    while (fscanf(inf, "%s %d", path, &block_size) == 2)
     {
     {
-        mf = mf_open (bfs->register_area, path, block_size, 1);
-        cf = cf_open (mf, bfs->commit_area, path, block_size, 0, &first_time);
+        mf = mf_open(bfs->register_area, path, block_size, 1);
+        cf = cf_open(mf, bfs->commit_area, path, block_size, 0, &first_time);
 
 
-        cf_commit (cf);
+        cf_commit(cf);
 
 
-        cf_close (cf);
-        mf_close (mf);
+        cf_close(cf);
+        mf_close(mf);
     }
     }
-    fclose (inf);
+    fclose(inf);
 }
 
 }
 
-void bf_commitClean (BFiles bfs, const char *spec)
+void bf_commitClean(BFiles bfs, const char *spec)
 {
     int mustDisable = 0;
 
     if (!bfs->commit_area)
     {
 {
     int mustDisable = 0;
 
     if (!bfs->commit_area)
     {
-        bf_cache (bfs, spec);
+        bf_cache(bfs, spec);
         mustDisable = 1;
     }
 
     mf_reset(bfs->commit_area, 1);
 
         mustDisable = 1;
     }
 
     mf_reset(bfs->commit_area, 1);
 
-    unlink_cache (bfs);
+    unlink_cache(bfs);
     if (mustDisable)
     if (mustDisable)
-        bf_cache (bfs, 0);
+        bf_cache(bfs, 0);
 }
 
 int bf_alloc(BFile bf, int no, zint *blocks)
 }
 
 int bf_alloc(BFile bf, int no, zint *blocks)
index 766127e..f84d395 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cfile.c,v 1.37 2006-08-14 10:40:05 adam Exp $
+/* $Id: cfile.c,v 1.38 2006-11-08 22:08:27 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -29,26 +29,29 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include "mfile.h"
 #include "cfile.h"
 
 #include "mfile.h"
 #include "cfile.h"
 
-static int write_head (CFile cf)
+static int write_head(CFile cf)
 {
     int left = cf->head.hash_size * sizeof(zint);
     int bno = 1;
 {
     int left = cf->head.hash_size * sizeof(zint);
     int bno = 1;
+    int r = 0;
     const char *tab = (char*) cf->array;
 
     if (!tab)
         return 0;
     while (left >= (int) HASH_BSIZE)
     {
     const char *tab = (char*) cf->array;
 
     if (!tab)
         return 0;
     while (left >= (int) HASH_BSIZE)
     {
-        mf_write (cf->hash_mf, bno++, 0, 0, tab);
+        r = mf_write(cf->hash_mf, bno++, 0, 0, tab);
+        if (r)
+            return r;
         tab += HASH_BSIZE;
         left -= HASH_BSIZE;
     }
     if (left > 0)
         tab += HASH_BSIZE;
         left -= HASH_BSIZE;
     }
     if (left > 0)
-        mf_write (cf->hash_mf, bno, 0, left, tab);
-    return 0;
+        r = mf_write(cf->hash_mf, bno, 0, left, tab);
+    return r;
 }
 
 }
 
-static int read_head (CFile cf)
+static int read_head(CFile cf)
 {
     int left = cf->head.hash_size * sizeof(zint);
     int bno = 1;
 {
     int left = cf->head.hash_size * sizeof(zint);
     int bno = 1;
@@ -58,41 +61,74 @@ static int read_head (CFile cf)
         return 0;
     while (left >= (int) HASH_BSIZE)
     {
         return 0;
     while (left >= (int) HASH_BSIZE)
     {
-        mf_read (cf->hash_mf, bno++, 0, 0, tab);
+        if (mf_read(cf->hash_mf, bno++, 0, 0, tab) == -1)
+            return -1;
         tab += HASH_BSIZE;
         left -= HASH_BSIZE;
     }
     if (left > 0)
         tab += HASH_BSIZE;
         left -= HASH_BSIZE;
     }
     if (left > 0)
-        mf_read (cf->hash_mf, bno, 0, left, tab);
-    return 0;
+    {
+        if (mf_read(cf->hash_mf, bno, 0, left, tab) == -1)
+            return -1;
+    }
+    return 1;
 }
 
 
 }
 
 
-CFile cf_open (MFile mf, MFile_area area, const char *fname,
-               int block_size, int wflag, int *firstp)
+CFile cf_open(MFile mf, MFile_area area, const char *fname,
+              int block_size, int wflag, int *firstp)
 {
     char path[1024];
 {
     char path[1024];
-    int i;
-    CFile cf = (CFile) xmalloc (sizeof(*cf));
+    int i, ret;
+    CFile cf = (CFile) xmalloc(sizeof(*cf));
     int hash_bytes;
     int hash_bytes;
+
+    yaz_log(YLOG_DEBUG, "cf: open %s %s", cf->rmf->name,
+            wflag ? "rdwr" : "rd");
    
    
+    cf->block_mf = 0;
+    cf->hash_mf = 0;
     cf->rmf = mf; 
     cf->rmf = mf; 
-    yaz_log (YLOG_DEBUG, "cf: open %s %s", cf->rmf->name, wflag ? "rdwr" : "rd");
-    sprintf (path, "%s-b", fname);
-    if (!(cf->block_mf = mf_open (area, path, block_size, wflag)))
+
+    assert(firstp);
+
+    cf->bucket_lru_front = cf->bucket_lru_back = NULL;
+    cf->bucket_in_memory = 0;
+    cf->max_bucket_in_memory = 100;
+    cf->dirty = 0;
+    cf->iobuf = (char *) xmalloc(block_size);
+    memset(cf->iobuf, 0, block_size);
+    cf->no_hits = 0;
+    cf->no_miss = 0;
+    cf->parray = 0;
+    cf->array = 0;
+    cf->block_mf = 0;
+    cf->hash_mf = 0;
+
+    zebra_mutex_init(&cf->mutex);
+
+    sprintf(path, "%s-b", fname);
+    if (!(cf->block_mf = mf_open(area, path, block_size, wflag)))
     {
     {
-        yaz_log (YLOG_FATAL|YLOG_ERRNO, "Failed to open %s", path);
-        exit (1);
+        yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to open %s", path);
+        cf_close(cf);
+        return 0;
     }
     }
-    sprintf (path, "%s-i", fname);
-    if (!(cf->hash_mf = mf_open (area, path, HASH_BSIZE, wflag)))
+    sprintf(path, "%s-i", fname);
+    if (!(cf->hash_mf = mf_open(area, path, HASH_BSIZE, wflag)))
     {
     {
-        yaz_log (YLOG_FATAL|YLOG_ERRNO, "Failed to open %s", path);
-        exit (1);
+        yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to open %s", path);
+        cf_close(cf);
+        return 0;
     }
     }
-    assert (firstp);
-    if (!mf_read (cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head) ||
-        !cf->head.state)
+    ret = mf_read(cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head);
+
+    if (ret == -1)
+    {
+        cf_close(cf);
+        return 0;
+    }
+    if (ret == 0 || !cf->head.state)
     {
         *firstp = 1;
         cf->head.state = 1;
     {
         *firstp = 1;
         cf->head.state = 1;
@@ -102,55 +138,57 @@ CFile cf_open (MFile mf, MFile_area area, const char *fname,
         cf->head.flat_bucket = cf->head.next_bucket = cf->head.first_bucket = 
             (hash_bytes+sizeof(cf->head))/HASH_BSIZE + 2;
         cf->head.next_block = 1;
         cf->head.flat_bucket = cf->head.next_bucket = cf->head.first_bucket = 
             (hash_bytes+sizeof(cf->head))/HASH_BSIZE + 2;
         cf->head.next_block = 1;
-        if (wflag)
-            mf_write (cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head);
-        cf->array = (zint *) xmalloc (hash_bytes);
+        cf->array = (zint *) xmalloc(hash_bytes);
         for (i = 0; i<cf->head.hash_size; i++)
             cf->array[i] = 0;
         if (wflag)
         for (i = 0; i<cf->head.hash_size; i++)
             cf->array[i] = 0;
         if (wflag)
-            write_head (cf);
+        {
+            if (mf_write(cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head))
+            {
+                cf_close(cf);
+                return 0;
+            }
+            if (write_head(cf))
+            {
+                cf_close(cf);
+                return 0;
+            }
+        }
     }
     else
     {
         *firstp = 0;
     }
     else
     {
         *firstp = 0;
-        assert (cf->head.block_size == block_size);
-        assert (cf->head.hash_size > 2);
+        assert(cf->head.block_size == block_size);
+        assert(cf->head.hash_size > 2);
         hash_bytes = cf->head.hash_size * sizeof(zint);
         hash_bytes = cf->head.hash_size * sizeof(zint);
-        assert (cf->head.next_bucket > 0);
-        assert (cf->head.next_block > 0);
+        assert(cf->head.next_bucket > 0);
+        assert(cf->head.next_block > 0);
         if (cf->head.state == 1)
         if (cf->head.state == 1)
-            cf->array = (zint *) xmalloc (hash_bytes);
+            cf->array = (zint *) xmalloc(hash_bytes);
         else
             cf->array = NULL;
         else
             cf->array = NULL;
-        read_head (cf);
+        if (read_head(cf) == -1)
+        {
+            cf_close(cf);
+            return 0;
+        }
     }
     if (cf->head.state == 1)
     {
         cf->parray = (struct CFile_hash_bucket **)
     }
     if (cf->head.state == 1)
     {
         cf->parray = (struct CFile_hash_bucket **)
-           xmalloc (cf->head.hash_size * sizeof(*cf->parray));
+           xmalloc(cf->head.hash_size * sizeof(*cf->parray));
         for (i = 0; i<cf->head.hash_size; i++)
             cf->parray[i] = NULL;
     }
         for (i = 0; i<cf->head.hash_size; i++)
             cf->parray[i] = NULL;
     }
-    else
-        cf->parray = NULL;
-    cf->bucket_lru_front = cf->bucket_lru_back = NULL;
-    cf->bucket_in_memory = 0;
-    cf->max_bucket_in_memory = 100;
-    cf->dirty = 0;
-    cf->iobuf = (char *) xmalloc (cf->head.block_size);
-    memset (cf->iobuf, 0, cf->head.block_size);
-    cf->no_hits = 0;
-    cf->no_miss = 0;
-    zebra_mutex_init (&cf->mutex);
     return cf;
 }
 
     return cf;
 }
 
-static int cf_hash (CFile cf, zint no)
+static int cf_hash(CFile cf, zint no)
 {
     return (int) (((no >> 3) % cf->head.hash_size));
 }
 
 {
     return (int) (((no >> 3) % cf->head.hash_size));
 }
 
-static void release_bucket (CFile cf, struct CFile_hash_bucket *p)
+static void release_bucket(CFile cf, struct CFile_hash_bucket *p)
 {
     if (p->lru_prev)
         p->lru_prev->lru_next = p->lru_next;
 {
     if (p->lru_prev)
         p->lru_prev->lru_next = p->lru_next;
@@ -166,10 +204,10 @@ static void release_bucket (CFile cf, struct CFile_hash_bucket *p)
         p->h_next->h_prev = p->h_prev;
     
     --(cf->bucket_in_memory);
         p->h_next->h_prev = p->h_prev;
     
     --(cf->bucket_in_memory);
-    xfree (p);
+    xfree(p);
 }
 
 }
 
-static void flush_bucket (CFile cf, int no_to_flush)
+static void flush_bucket(CFile cf, int no_to_flush)
 {
     int i;
     struct CFile_hash_bucket *p;
 {
     int i;
     struct CFile_hash_bucket *p;
@@ -181,22 +219,22 @@ static void flush_bucket (CFile cf, int no_to_flush)
             break;
         if (p->dirty)
         {
             break;
         if (p->dirty)
         {
-            mf_write (cf->hash_mf, p->ph.this_bucket, 0, 0, &p->ph);
+            mf_write(cf->hash_mf, p->ph.this_bucket, 0, 0, &p->ph);
             cf->dirty = 1;
         }
             cf->dirty = 1;
         }
-        release_bucket (cf, p);
+        release_bucket(cf, p);
     }
 }
 
     }
 }
 
-static struct CFile_hash_bucket *alloc_bucket (CFile cf, zint block_no, int hno)
+static struct CFile_hash_bucket *alloc_bucket(CFile cf, zint block_no, int hno)
 {
     struct CFile_hash_bucket *p, **pp;
 
     if (cf->bucket_in_memory == cf->max_bucket_in_memory)
 {
     struct CFile_hash_bucket *p, **pp;
 
     if (cf->bucket_in_memory == cf->max_bucket_in_memory)
-        flush_bucket (cf, 1);
-    assert (cf->bucket_in_memory < cf->max_bucket_in_memory);
+        flush_bucket(cf, 1);
+    assert(cf->bucket_in_memory < cf->max_bucket_in_memory);
     ++(cf->bucket_in_memory);
     ++(cf->bucket_in_memory);
-    p = (struct CFile_hash_bucket *) xmalloc (sizeof(*p));
+    p = (struct CFile_hash_bucket *) xmalloc(sizeof(*p));
 
     p->lru_next = NULL;
     p->lru_prev = cf->bucket_lru_front;
 
     p->lru_next = NULL;
     p->lru_prev = cf->bucket_lru_front;
@@ -215,29 +253,31 @@ static struct CFile_hash_bucket *alloc_bucket (CFile cf, zint block_no, int hno)
     return p;
 }
 
     return p;
 }
 
-static struct CFile_hash_bucket *get_bucket (CFile cf, zint block_no, int hno)
+static struct CFile_hash_bucket *get_bucket(CFile cf, zint block_no, int hno)
 {
     struct CFile_hash_bucket *p;
 
 {
     struct CFile_hash_bucket *p;
 
-    p = alloc_bucket (cf, block_no, hno);
-    if (!mf_read (cf->hash_mf, block_no, 0, 0, &p->ph))
+    p = alloc_bucket(cf, block_no, hno);
+    p->dirty = 0;
+    if (!mf_read(cf->hash_mf, block_no, 0, 0, &p->ph))
     {
     {
-        yaz_log (YLOG_FATAL|YLOG_ERRNO, "read get_bucket");
-        exit (1);
+        yaz_log(YLOG_FATAL|YLOG_ERRNO, "read get_bucket");
+        release_bucket(cf, p);
+        return 0;
     }
     }
-    assert (p->ph.this_bucket == block_no);
-    p->dirty = 0;
+    assert(p->ph.this_bucket == block_no);
     return p;
 }
 
     return p;
 }
 
-static struct CFile_hash_bucket *new_bucket (CFile cf, zint *block_nop, int hno)
+static struct CFile_hash_bucket *new_bucket(CFile cf, zint *block_nop, int hno)
 {
     struct CFile_hash_bucket *p;
     int i;
     zint block_no;
 
     block_no = *block_nop = cf->head.next_bucket++;
 {
     struct CFile_hash_bucket *p;
     int i;
     zint block_no;
 
     block_no = *block_nop = cf->head.next_bucket++;
-    p = alloc_bucket (cf, block_no, hno);
+    p = alloc_bucket(cf, block_no, hno);
+    p->dirty = 1;
 
     for (i = 0; i<HASH_BUCKET; i++)
     {
 
     for (i = 0; i<HASH_BUCKET; i++)
     {
@@ -246,23 +286,24 @@ static struct CFile_hash_bucket *new_bucket (CFile cf, zint *block_nop, int hno)
     }
     p->ph.next_bucket = 0;
     p->ph.this_bucket = block_no;
     }
     p->ph.next_bucket = 0;
     p->ph.this_bucket = block_no;
-    p->dirty = 1;
     return p;
 }
 
     return p;
 }
 
-static zint cf_lookup_flat (CFile cf, zint no)
+static int cf_lookup_flat(CFile cf, zint no, zint *vno)
 {
     zint hno = (no*sizeof(zint))/HASH_BSIZE;
     int off = (int) ((no*sizeof(zint)) - hno*HASH_BSIZE);
 {
     zint hno = (no*sizeof(zint))/HASH_BSIZE;
     int off = (int) ((no*sizeof(zint)) - hno*HASH_BSIZE);
-    zint vno = 0;
 
 
-    mf_read (cf->hash_mf, hno+cf->head.next_bucket, off, sizeof(zint), &vno);
-    return vno;
+    *vno = 0;
+    mf_read(cf->hash_mf, hno+cf->head.next_bucket, off, sizeof(zint), vno);
+    if (*vno)
+        return 1;
+    return 0;
 }
 
 }
 
-static zint cf_lookup_hash (CFile cf, zint no)
+static int cf_lookup_hash(CFile cf, zint no, zint *vno)
 {
 {
-    int hno = cf_hash (cf, no);
+    int hno = cf_hash(cf, no);
     struct CFile_hash_bucket *hb;
     zint block_no;
     int i;
     struct CFile_hash_bucket *hb;
     zint block_no;
     int i;
@@ -273,7 +314,8 @@ static zint cf_lookup_hash (CFile cf, zint no)
             if (hb->ph.no[i] == no)
             {
                 (cf->no_hits)++;
             if (hb->ph.no[i] == no)
             {
                 (cf->no_hits)++;
-                return hb->ph.vno[i];
+                *vno = hb->ph.vno[i];
+                return 1;
             }
     }
     for (block_no = cf->array[hno]; block_no; block_no = hb->ph.next_bucket)
             }
     }
     for (block_no = cf->array[hno]; block_no; block_no = hb->ph.next_bucket)
@@ -291,27 +333,32 @@ static zint cf_lookup_hash (CFile cf, zint no)
         {
             if (hb->ph.this_bucket == block_no)
             {
         {
             if (hb->ph.this_bucket == block_no)
             {
-                yaz_log (YLOG_FATAL, "Found hash bucket on other chain (1)");
-                abort ();
+                yaz_log(YLOG_FATAL, "Found hash bucket on other chain(1)");
+                abort();
             }
             for (i = 0; i<HASH_BUCKET && hb->ph.vno[i]; i++)
                 if (hb->ph.no[i] == no)
                 {
             }
             for (i = 0; i<HASH_BUCKET && hb->ph.vno[i]; i++)
                 if (hb->ph.no[i] == no)
                 {
-                    yaz_log (YLOG_FATAL, "Found hash bucket on other chain (2)");
-                    abort ();
+                    yaz_log(YLOG_FATAL, "Found hash bucket on other chain (2)");
+                    abort();
                 }
         }
 #endif
         (cf->no_miss)++;
                 }
         }
 #endif
         (cf->no_miss)++;
-        hb = get_bucket (cf, block_no, hno);
+        hb = get_bucket(cf, block_no, hno);
+        if (!hb)
+            return -1;
         for (i = 0; i<HASH_BUCKET && hb->ph.vno[i]; i++)
             if (hb->ph.no[i] == no)
         for (i = 0; i<HASH_BUCKET && hb->ph.vno[i]; i++)
             if (hb->ph.no[i] == no)
-                return hb->ph.vno[i];
+            {
+                *vno = hb->ph.vno[i];
+                return 1;
+            }
     }
     return 0;
 }
 
     }
     return 0;
 }
 
-static void cf_write_flat (CFile cf, zint no, zint vno)
+static int cf_write_flat(CFile cf, zint no, zint vno)
 {
     zint hno = (no*sizeof(zint))/HASH_BSIZE;
     int off = (int) ((no*sizeof(zint)) - hno*HASH_BSIZE);
 {
     zint hno = (no*sizeof(zint))/HASH_BSIZE;
     int off = (int) ((no*sizeof(zint)) - hno*HASH_BSIZE);
@@ -320,61 +367,70 @@ static void cf_write_flat (CFile cf, zint no, zint vno)
     if (hno >= cf->head.flat_bucket)
         cf->head.flat_bucket = hno+1;
     cf->dirty = 1;
     if (hno >= cf->head.flat_bucket)
         cf->head.flat_bucket = hno+1;
     cf->dirty = 1;
-    mf_write (cf->hash_mf, hno, off, sizeof(zint), &vno);
+    return mf_write(cf->hash_mf, hno, off, sizeof(zint), &vno);
 }
 
 }
 
-static void cf_moveto_flat (CFile cf)
+static int cf_moveto_flat(CFile cf)
 {
     struct CFile_hash_bucket *p;
     int j;
     zint i;
 
 {
     struct CFile_hash_bucket *p;
     int j;
     zint i;
 
-    yaz_log (YLOG_DEBUG, "cf: Moving to flat shadow: %s", cf->rmf->name);
-    yaz_log (YLOG_DEBUG, "cf: hits=%d miss=%d bucket_in_memory=" ZINT_FORMAT " total="
+    yaz_log(YLOG_LOG, "cf: Moving to flat shadow: %s", cf->rmf->name);
+    yaz_log(YLOG_DEBUG, "cf: Moving to flat shadow: %s", cf->rmf->name);
+    yaz_log(YLOG_DEBUG, "cf: hits=%d miss=%d bucket_in_memory=" ZINT_FORMAT " total="
          ZINT_FORMAT,
        cf->no_hits, cf->no_miss, cf->bucket_in_memory, 
         cf->head.next_bucket - cf->head.first_bucket);
          ZINT_FORMAT,
        cf->no_hits, cf->no_miss, cf->bucket_in_memory, 
         cf->head.next_bucket - cf->head.first_bucket);
-    assert (cf->head.state == 1);
-    flush_bucket (cf, -1);
-    assert (cf->bucket_in_memory == 0);
-    p = (struct CFile_hash_bucket *) xmalloc (sizeof(*p));
+    assert(cf->head.state == 1);
+    flush_bucket(cf, -1);
+    assert(cf->bucket_in_memory == 0);
+    p = (struct CFile_hash_bucket *) xmalloc(sizeof(*p));
     for (i = cf->head.first_bucket; i < cf->head.next_bucket; i++)
     {
     for (i = cf->head.first_bucket; i < cf->head.next_bucket; i++)
     {
-        if (!mf_read (cf->hash_mf, i, 0, 0, &p->ph))
+        if (mf_read(cf->hash_mf, i, 0, 0, &p->ph) != 1)
         {
         {
-            yaz_log (YLOG_FATAL|YLOG_ERRNO, "read bucket moveto flat");
-            exit (1);
+            yaz_log(YLOG_FATAL|YLOG_ERRNO, "read bucket moveto flat");
+            xfree(p);
+            return -1;
         }
         for (j = 0; j < HASH_BUCKET && p->ph.vno[j]; j++)
         }
         for (j = 0; j < HASH_BUCKET && p->ph.vno[j]; j++)
-            cf_write_flat (cf, p->ph.no[j], p->ph.vno[j]);
+        {
+            if (cf_write_flat(cf, p->ph.no[j], p->ph.vno[j]))
+            {
+                xfree(p);
+                return -1;
+            }
+        }
     }
     }
-    xfree (p);
-    xfree (cf->array);
+    xfree(p);
+    xfree(cf->array);
     cf->array = NULL;
     cf->array = NULL;
-    xfree (cf->parray);
+    xfree(cf->parray);
     cf->parray = NULL;
     cf->head.state = 2;
     cf->dirty = 1;
     cf->parray = NULL;
     cf->head.state = 2;
     cf->dirty = 1;
+    return 0;
 }
 
 }
 
-static zint cf_lookup (CFile cf, zint no)
+static int cf_lookup(CFile cf, zint no, zint *vno)
 {
     if (cf->head.state > 1)
 {
     if (cf->head.state > 1)
-        return cf_lookup_flat (cf, no);
-    return cf_lookup_hash (cf, no);
+        return cf_lookup_flat(cf, no, vno);
+    return cf_lookup_hash(cf, no, vno);
 }
 
 }
 
-static zint cf_new_flat (CFile cf, zint no)
+static zint cf_new_flat(CFile cf, zint no)
 {
     zint vno = (cf->head.next_block)++;
 
 {
     zint vno = (cf->head.next_block)++;
 
-    cf_write_flat (cf, no, vno);
+    cf_write_flat(cf, no, vno);
     return vno;
 }
 
     return vno;
 }
 
-static zint cf_new_hash (CFile cf, zint no)
+static zint cf_new_hash(CFile cf, zint no)
 {
 {
-    int hno = cf_hash (cf, no);
+    int hno = cf_hash(cf, no);
     struct CFile_hash_bucket *hbprev = NULL, *hb = cf->parray[hno];
     zint *bucketpp = &cf->array[hno]; 
     int i;
     struct CFile_hash_bucket *hbprev = NULL, *hb = cf->parray[hno];
     zint *bucketpp = &cf->array[hno]; 
     int i;
@@ -410,14 +466,15 @@ static zint cf_new_hash (CFile cf, zint no)
         {
             if (hb->ph.this_bucket == *bucketpp)
             {
         {
             if (hb->ph.this_bucket == *bucketpp)
             {
-                yaz_log (YLOG_FATAL, "Found hash bucket on other chain");
-                abort ();
+                yaz_log(YLOG_FATAL, "Found hash bucket on other chain");
+                abort();
             }
         }
 #endif
         (cf->no_miss)++;
             }
         }
 #endif
         (cf->no_miss)++;
-        hb = get_bucket (cf, *bucketpp, hno);
-        assert (hb);
+        hb = get_bucket(cf, *bucketpp, hno);
+        if (!hb)
+            return 0;
         for (i = 0; i<HASH_BUCKET; i++)
             if (!hb->ph.vno[i])
             {
         for (i = 0; i<HASH_BUCKET; i++)
             if (!hb->ph.vno[i])
             {
@@ -431,93 +488,127 @@ static zint cf_new_hash (CFile cf, zint no)
     }
     if (hbprev)
         hbprev->dirty = 1;
     }
     if (hbprev)
         hbprev->dirty = 1;
-    hb = new_bucket (cf, bucketpp, hno);
+    hb = new_bucket(cf, bucketpp, hno);
     hb->ph.no[0] = no;
     hb->ph.vno[0] = vno;
     return vno;
 }
 
     hb->ph.no[0] = no;
     hb->ph.vno[0] = vno;
     return vno;
 }
 
-zint cf_new (CFile cf, zint no)
+zint cf_new(CFile cf, zint no)
 {
     if (cf->head.state > 1)
 {
     if (cf->head.state > 1)
-        return cf_new_flat (cf, no);
+        return cf_new_flat(cf, no);
     if (cf->no_miss*2 > cf->no_hits)
     {
     if (cf->no_miss*2 > cf->no_hits)
     {
-        cf_moveto_flat (cf);
-        assert (cf->head.state > 1);
-        return cf_new_flat (cf, no);
+        if (cf_moveto_flat(cf))
+            return -1;
+        assert(cf->head.state > 1);
+        return cf_new_flat(cf, no);
     }
     }
-    return cf_new_hash (cf, no);
+    return cf_new_hash(cf, no);
 }
 
 
 }
 
 
-int cf_read (CFile cf, zint no, int offset, int nbytes, void *buf)
+/** \brief reads block from commit area
+    \param cf commit file
+    \param no block number
+    \param offset offset in block
+    \param nbytes number of bytes to read
+    \param buf buffer for content (if read was succesful)
+    \retval 0 block could not be fully read
+    \retval 1 block could be read
+    \retval -1 error
+*/
+int cf_read(CFile cf, zint no, int offset, int nbytes, void *buf)
 {
     zint block;
 {
     zint block;
+    int ret;
     
     
-    assert (cf);
-    zebra_mutex_lock (&cf->mutex);
-    if (!(block = cf_lookup (cf, no)))
+    assert(cf);
+    zebra_mutex_lock(&cf->mutex);
+    ret = cf_lookup(cf, no, &block);
+    zebra_mutex_unlock(&cf->mutex);
+    if (ret != 1)
     {
     {
-       zebra_mutex_unlock (&cf->mutex);
-        return -1;
+        /* block could not be read or error */
+        return ret;
     }
     }
-    zebra_mutex_unlock (&cf->mutex);
-    if (!mf_read (cf->block_mf, block, offset, nbytes, buf))
+    if (mf_read(cf->block_mf, block, offset, nbytes, buf) != 1)
     {
     {
-        yaz_log (YLOG_FATAL|YLOG_ERRNO, "cf_read no=" ZINT_FORMAT " block=" ZINT_FORMAT, no, block);
-        exit (1);
+        yaz_log(YLOG_FATAL|YLOG_ERRNO, "cf_read no=" ZINT_FORMAT " block=" ZINT_FORMAT, no, block);
+        return -1;
     }
     return 1;
 }
 
     }
     return 1;
 }
 
-int cf_write (CFile cf, zint no, int offset, int nbytes, const void *buf)
+/** \brief writes block to commit area
+    \param cf commit file
+    \param no block number
+    \param offset offset in block
+    \param nbytes number of bytes to be written
+    \param buf buffer to be written
+    \retval 0 block written
+    \retval -1 error
+*/
+int cf_write(CFile cf, zint no, int offset, int nbytes, const void *buf)
 {
     zint block;
 {
     zint block;
+    int ret;
+
+    assert(cf);
+    zebra_mutex_lock(&cf->mutex);
 
 
-    assert (cf);
-    zebra_mutex_lock (&cf->mutex);
-    if (!(block = cf_lookup (cf, no)))
+    ret = cf_lookup(cf, no, &block);
+
+    if (ret == -1)
     {
     {
-        block = cf_new (cf, no);
+        zebra_mutex_unlock(&cf->mutex);
+        return ret;
+    }
+    if (ret == 0)
+    {
+        block = cf_new(cf, no);
+        if (!block)
+        {
+            zebra_mutex_unlock(&cf->mutex);
+            return -1;
+        }
         if (offset || nbytes)
         {
         if (offset || nbytes)
         {
-            mf_read (cf->rmf, no, 0, 0, cf->iobuf);
-            memcpy (cf->iobuf + offset, buf, nbytes);
+            mf_read(cf->rmf, no, 0, 0, cf->iobuf);
+            memcpy(cf->iobuf + offset, buf, nbytes);
             buf = cf->iobuf;
             offset = 0;
             nbytes = 0;
         }
     }
             buf = cf->iobuf;
             offset = 0;
             nbytes = 0;
         }
     }
-    zebra_mutex_unlock (&cf->mutex);
-    if (mf_write (cf->block_mf, block, offset, nbytes, buf))
-    {
-        yaz_log (YLOG_FATAL|YLOG_ERRNO, "cf_write no=" ZINT_FORMAT
-             " block=" ZINT_FORMAT, no, block);
-        exit (1);
-    }
-    return 0;
+    zebra_mutex_unlock(&cf->mutex);
+    return mf_write(cf->block_mf, block, offset, nbytes, buf);
 }
 
 }
 
-int cf_close (CFile cf)
+int cf_close(CFile cf)
 {
 {
-    yaz_log (YLOG_DEBUG, "cf: close hits=%d miss=%d bucket_in_memory=" ZINT_FORMAT
+    yaz_log(YLOG_DEBUG, "cf: close hits=%d miss=%d bucket_in_memory=" ZINT_FORMAT
          " total=" ZINT_FORMAT,
           cf->no_hits, cf->no_miss, cf->bucket_in_memory,
           cf->head.next_bucket - cf->head.first_bucket);
          " total=" ZINT_FORMAT,
           cf->no_hits, cf->no_miss, cf->bucket_in_memory,
           cf->head.next_bucket - cf->head.first_bucket);
-    flush_bucket (cf, -1);
-    if (cf->dirty)
+    flush_bucket(cf, -1);
+    if (cf->hash_mf)
     {
     {
-        mf_write (cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head);
-        write_head (cf);
+        if (cf->dirty)
+        {
+            mf_write(cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head);
+            write_head(cf);
+        }
+        mf_close(cf->hash_mf);
     }
     }
-    mf_close (cf->hash_mf);
-    mf_close (cf->block_mf);
-    xfree (cf->array);
-    xfree (cf->parray);
-    xfree (cf->iobuf);
-    zebra_mutex_destroy (&cf->mutex);
-    xfree (cf);
+    if (cf->block_mf)
+        mf_close(cf->block_mf);
+    xfree(cf->array);
+    xfree(cf->parray);
+    xfree(cf->iobuf);
+    zebra_mutex_destroy(&cf->mutex);
+    xfree(cf);
     return 0;
 }
 
     return 0;
 }
 
index 5f05473..9d8a3fb 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mfile.c,v 1.69 2006-10-10 10:19:28 adam Exp $
+/* $Id: mfile.c,v 1.70 2006-11-08 22:08:27 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -20,14 +20,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 */
 
 
 */
 
-
-
-
- /*
-  * TODO: The size estimates in init may not be accurate due to
-  * only partially written final blocks.
-  */
-
 #include <sys/types.h>
 #include <fcntl.h>
 #ifdef WIN32
 #include <sys/types.h>
 #include <fcntl.h>
 #ifdef WIN32
@@ -70,13 +62,13 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
             break;
         if (!yaz_is_abspath(ad) && base)
         {
             break;
         if (!yaz_is_abspath(ad) && base)
         {
-            strcpy (dirname, base);
+            strcpy(dirname, base);
             i = strlen(dirname);
             dirname[i++] = '/';
         }
         while (*ad)
         {
             i = strlen(dirname);
             dirname[i++] = '/';
         }
         while (*ad)
         {
-           if (*ad == ':' && strchr ("+-0123456789", ad[1]))
+           if (*ad == ':' && strchr("+-0123456789", ad[1]))
                break;
             if (i < FILENAME_MAX)
                 dirname[i++] = *ad;
                break;
             if (i < FILENAME_MAX)
                 dirname[i++] = *ad;
@@ -85,12 +77,12 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
         dirname[i] = '\0';
         if (*ad++ != ':')
         {
         dirname[i] = '\0';
         if (*ad++ != ':')
         {
-           yaz_log (YLOG_WARN, "Missing colon after path: %s", ad0);
+           yaz_log(YLOG_WARN, "Missing colon after path: %s", ad0);
             return -1;
         }
         if (i == 0)
         {
             return -1;
         }
         if (i == 0)
         {
-           yaz_log (YLOG_WARN, "Empty path: %s", ad0);
+           yaz_log(YLOG_WARN, "Empty path: %s", ad0);
             return -1;
         }
         while (*ad == ' ' || *ad == '\t')
             return -1;
         }
         while (*ad == ' ' || *ad == '\t')
@@ -105,7 +97,7 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
         size = 0;
         if (*ad < '0' || *ad > '9')
         {
         size = 0;
         if (*ad < '0' || *ad > '9')
         {
-           yaz_log (YLOG_FATAL, "Missing size after path: %s", ad0);
+           yaz_log(YLOG_FATAL, "Missing size after path: %s", ad0);
             return -1;
         }
         size = 0;
             return -1;
         }
         size = 0;
@@ -118,10 +110,10 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
        case 'M': case 'm': multi = 1048576; break;
        case 'G': case 'g': multi = 1073741824; break;
         case '\0':
        case 'M': case 'm': multi = 1048576; break;
        case 'G': case 'g': multi = 1073741824; break;
         case '\0':
-            yaz_log (YLOG_FATAL, "Missing unit: %s", ad0);
+            yaz_log(YLOG_FATAL, "Missing unit: %s", ad0);
             return -1;
         default:
             return -1;
         default:
-            yaz_log (YLOG_FATAL, "Illegal unit: %c in %s", *ad, ad0);
+            yaz_log(YLOG_FATAL, "Illegal unit: %c in %s", *ad, ad0);
             return -1;
        }
         ad++;
             return -1;
        }
         ad++;
@@ -134,6 +126,15 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
     return 0;
 }
 
     return 0;
 }
 
+/** \brief position within metafile (perform seek)
+    \param mf metafile handle
+    \param pos block position
+    \param offset offset within block
+    \retval 0 OK
+    \retval -1 ERROR
+    \retval -2 OK, but file does not created (read-only)
+*/
+   
 static zint file_position(MFile mf, zint pos, int offset)
 {
     zint off = 0, ps;
 static zint file_position(MFile mf, zint pos, int offset)
 {
     zint off = 0, ps;
@@ -160,16 +161,19 @@ static zint file_position(MFile mf, zint pos, int offset)
                                         (O_BINARY|O_RDONLY), 0666)) < 0)
         {
             if (!mf->wr && errno == ENOENT && off == 0)
                                         (O_BINARY|O_RDONLY), 0666)) < 0)
         {
             if (!mf->wr && errno == ENOENT && off == 0)
+            {
+                /* we can't open it for reading. But not really an error */
                 return -2;
                 return -2;
-           yaz_log (YLOG_WARN|YLOG_ERRNO, "Failed to open %s", mf->files[c].path);
+            }
+           yaz_log(YLOG_WARN|YLOG_ERRNO, "Failed to open %s", mf->files[c].path);
            return -1;
         }
     }
     ps = pos - off;
            return -1;
         }
     }
     ps = pos - off;
-    if (mfile_seek(mf->files[c].fd, ps * (mfile_off_t) mf->blocksize + offset,
+    if (mfile_seek(mf->files[c].fd, ps *(mfile_off_t) mf->blocksize + offset,
        SEEK_SET) < 0)
     {
        SEEK_SET) < 0)
     {
-       yaz_log (YLOG_WARN|YLOG_ERRNO, "Failed to seek in %s", mf->files[c].path);
+       yaz_log(YLOG_WARN|YLOG_ERRNO, "Failed to seek in %s", mf->files[c].path);
         yaz_log(YLOG_WARN, "pos=" ZINT_FORMAT " off=" ZINT_FORMAT " blocksize=%d offset=%d",
                        pos, off, mf->blocksize, offset);
        return -1;
         yaz_log(YLOG_WARN, "pos=" ZINT_FORMAT " off=" ZINT_FORMAT " blocksize=%d offset=%d",
                        pos, off, mf->blocksize, offset);
        return -1;
@@ -188,10 +192,12 @@ static int cmp_part_file(const void *p1, const void *p2)
     return 0;
 }
 
     return 0;
 }
 
-/*
- * Create a new area, cotaining metafiles in directories.
- * Find the part-files in each directory, and inventory the existing metafiles.
- */
+/** \brief creates a metafile area
+    \param name of area (does not show up on disk - purely for notation)
+    \param spec area specification (e.g. "/a:1G dir /b:2000M"
+    \param base base directory (NULL for no base)
+    \returns metafile area handle or NULL if error occurs
+*/
 MFile_area mf_init(const char *name, const char *spec, const char *base)
 {
     MFile_area ma = (MFile_area) xmalloc(sizeof(*ma));
 MFile_area mf_init(const char *name, const char *spec, const char *base)
 {
     MFile_area ma = (MFile_area) xmalloc(sizeof(*ma));
@@ -203,13 +209,13 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
     int fd, number;
     char metaname[FILENAME_MAX+1], tmpnam[FILENAME_MAX+1];
     
     int fd, number;
     char metaname[FILENAME_MAX+1], tmpnam[FILENAME_MAX+1];
     
-    yaz_log (YLOG_DEBUG, "mf_init(%s)", name);
+    yaz_log(YLOG_DEBUG, "mf_init(%s)", name);
     strcpy(ma->name, name);
     ma->mfiles = 0;
     ma->dirs = 0;
     if (scan_areadef(ma, spec, base) < 0)
     {
     strcpy(ma->name, name);
     ma->mfiles = 0;
     ma->dirs = 0;
     if (scan_areadef(ma, spec, base) < 0)
     {
-       yaz_log (YLOG_WARN, "Failed to access description of '%s'", name);
+       yaz_log(YLOG_WARN, "Failed to access description of '%s'", name);
        return 0;
     }
     /* look at each directory */
        return 0;
     }
     /* look at each directory */
@@ -217,7 +223,7 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
     {
        if (!(dd = opendir(dirp->name)))
        {
     {
        if (!(dd = opendir(dirp->name)))
        {
-           yaz_log (YLOG_WARN|YLOG_ERRNO, "Failed to open directory %s",
+           yaz_log(YLOG_WARN|YLOG_ERRNO, "Failed to open directory %s",
                                      dirp->name);
            return 0;
        }
                                      dirp->name);
            return 0;
        }
@@ -225,13 +231,13 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
        while ((dent = readdir(dd)))
        {
            int len = strlen(dent->d_name);
        while ((dent = readdir(dd)))
        {
            int len = strlen(dent->d_name);
-           const char *cp = strrchr (dent->d_name, '-');
-           if (strchr (".-", *dent->d_name))
+           const char *cp = strrchr(dent->d_name, '-');
+           if (strchr(".-", *dent->d_name))
                continue;
                continue;
-           if (len < 5 || !cp || strcmp (dent->d_name + len - 3, ".mf"))
+           if (len < 5 || !cp || strcmp(dent->d_name + len - 3, ".mf"))
                continue;
            number = atoi(cp+1);
                continue;
            number = atoi(cp+1);
-           memcpy (metaname, dent->d_name, cp - dent->d_name);
+           memcpy(metaname, dent->d_name, cp - dent->d_name);
            metaname[ cp - dent->d_name] = '\0';
 
            for (meta_f = ma->mfiles; meta_f; meta_f = meta_f->next)
            metaname[ cp - dent->d_name] = '\0';
 
            for (meta_f = ma->mfiles; meta_f; meta_f = meta_f->next)
@@ -247,7 +253,7 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
            if (!meta_f)
            {
                meta_f = (meta_file *) xmalloc(sizeof(*meta_f));
            if (!meta_f)
            {
                meta_f = (meta_file *) xmalloc(sizeof(*meta_f));
-               zebra_mutex_init (&meta_f->mutex);
+               zebra_mutex_init(&meta_f->mutex);
                meta_f->ma = ma;
                meta_f->next = ma->mfiles;
                meta_f->open = 0;
                meta_f->ma = ma;
                meta_f->next = ma->mfiles;
                meta_f->open = 0;
@@ -265,13 +271,13 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
            /* get size */
            if ((fd = open(part_f->path, O_BINARY|O_RDONLY)) < 0)
            {
            /* get size */
            if ((fd = open(part_f->path, O_BINARY|O_RDONLY)) < 0)
            {
-               yaz_log (YLOG_FATAL|YLOG_ERRNO, "Failed to access %s",
+               yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to access %s",
                       dent->d_name);
                return 0;
            }
            if ((part_f->bytes = mfile_seek(fd, 0, SEEK_END)) < 0)
            {
                       dent->d_name);
                return 0;
            }
            if ((part_f->bytes = mfile_seek(fd, 0, SEEK_END)) < 0)
            {
-               yaz_log (YLOG_FATAL|YLOG_ERRNO, "Failed to seek in %s",
+               yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to seek in %s",
                       dent->d_name);
                return 0;
            }
                       dent->d_name);
                return 0;
            }
@@ -286,7 +292,7 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
     }
     for (meta_f = ma->mfiles; meta_f; meta_f = meta_f->next)
     {
     }
     for (meta_f = ma->mfiles; meta_f; meta_f = meta_f->next)
     {
-       yaz_log (YLOG_DEBUG, "mf_init: %s consists of %d part(s)", meta_f->name,
+       yaz_log(YLOG_DEBUG, "mf_init: %s consists of %d part(s)", meta_f->name,
               meta_f->no_files);
        qsort(meta_f->files, meta_f->no_files, sizeof(part_file),
               cmp_part_file);
               meta_f->no_files);
        qsort(meta_f->files, meta_f->no_files, sizeof(part_file),
               cmp_part_file);
@@ -294,6 +300,9 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
     return ma;
 }
 
     return ma;
 }
 
+/** \brief destroys metafile area handle
+    \param ma metafile area handle
+*/
 void mf_destroy(MFile_area ma)
 {
     mf_dir *dp;
 void mf_destroy(MFile_area ma)
 {
     mf_dir *dp;
@@ -305,12 +314,16 @@ void mf_destroy(MFile_area ma)
     {
        mf_dir *d = dp;
        dp = dp->next;
     {
        mf_dir *d = dp;
        dp = dp->next;
-       xfree (d);
+       xfree(d);
     }
     mf_reset(ma, 0);
     }
     mf_reset(ma, 0);
-    xfree (ma);
+    xfree(ma);
 }
 
 }
 
+/** \brief reset all files in a metafile area (optionally delete them as well)
+    \param ma metafile area
+    \param unlink_flag if unlink_flag=1 all files are removed from FS
+*/
 void mf_reset(MFile_area ma, int unlink_flag)
 {
     meta_file *meta_f;
 void mf_reset(MFile_area ma, int unlink_flag)
 {
     meta_file *meta_f;
@@ -325,21 +338,25 @@ void mf_reset(MFile_area ma, int unlink_flag)
 
        meta_f = meta_f->next;
 
 
        meta_f = meta_f->next;
 
-       assert (!m->open);
+       assert(!m->open);
        for (i = 0; i<m->no_files; i++)
        {
             if (unlink_flag)
        for (i = 0; i<m->no_files; i++)
        {
             if (unlink_flag)
-                unlink (m->files[i].path);
-           xfree (m->files[i].path);
+                unlink(m->files[i].path);
+           xfree(m->files[i].path);
        }
        }
-       zebra_mutex_destroy (&m->mutex);
-       xfree (m);
+       zebra_mutex_destroy(&m->mutex);
+       xfree(m);
     }
     ma->mfiles = 0;
 }
 
     }
     ma->mfiles = 0;
 }
 
-/*
- * Open a metafile.
+/** \brief opens metafile
+    \param ma metafile area handle
+    \param name pseudo filename (name*.mf)
+    \param block_size block size for this file
+    \param wflag write flag, 0=read, 1=write&read
+    \returns metafile handle, or NULL for error (could not be opened)
  */
 MFile mf_open(MFile_area ma, const char *name, int block_size, int wflag)
 {
  */
 MFile mf_open(MFile_area ma, const char *name, int block_size, int wflag)
 {
@@ -350,21 +367,22 @@ MFile mf_open(MFile_area ma, const char *name, int block_size, int wflag)
 
     yaz_log(YLOG_DEBUG, "mf_open(%s bs=%d, %s)", name, block_size,
          wflag ? "RW" : "RDONLY");
 
     yaz_log(YLOG_DEBUG, "mf_open(%s bs=%d, %s)", name, block_size,
          wflag ? "RW" : "RDONLY");
-    assert (ma);
+    assert(ma);
     for (mnew = ma->mfiles; mnew; mnew = mnew->next)
        if (!strcmp(name, mnew->name))
        {
            if (mnew->open)
     for (mnew = ma->mfiles; mnew; mnew = mnew->next)
        if (!strcmp(name, mnew->name))
        {
            if (mnew->open)
-               abort();
-           else
-               break;
+            {
+                yaz_log(YLOG_WARN, "metafile %s already open", name);
+                return 0;
+            }
        }
     if (!mnew)
     {
        mnew = (meta_file *) xmalloc(sizeof(*mnew));
        strcpy(mnew->name, name);
        /* allocate one, empty file */
        }
     if (!mnew)
     {
        mnew = (meta_file *) xmalloc(sizeof(*mnew));
        strcpy(mnew->name, name);
        /* allocate one, empty file */
-       zebra_mutex_init (&mnew->mutex);
+       zebra_mutex_init(&mnew->mutex);
        mnew->no_files = 1;
        mnew->files[0].bytes = 0;
        mnew->files[0].blocks = 0;
        mnew->no_files = 1;
        mnew->files[0].bytes = 0;
        mnew->files[0].blocks = 0;
@@ -376,7 +394,7 @@ MFile mf_open(MFile_area ma, const char *name, int block_size, int wflag)
            mnew->min_bytes_creat; dp = dp->next);
        if (!dp)
        {
            mnew->min_bytes_creat; dp = dp->next);
        if (!dp)
        {
-           yaz_log (YLOG_FATAL, "Insufficient space for new mfile.");
+           yaz_log(YLOG_FATAL, "Insufficient space for new mfile.");
            return 0;
        }
        mnew->files[0].dir = dp;
            return 0;
        }
        mnew->files[0].dir = dp;
@@ -416,14 +434,15 @@ MFile mf_open(MFile_area ma, const char *name, int block_size, int wflag)
     return mnew;
 }
 
     return mnew;
 }
 
-/*
- * Close a metafile.
- */
+/** \brief closes metafile
+    \param mf metafile handle
+    \retval 0 OK
+*/
 int mf_close(MFile mf)
 {
     int i;
 
 int mf_close(MFile mf)
 {
     int i;
 
-    yaz_log (YLOG_DEBUG, "mf_close(%s)", mf->name);
+    yaz_log(YLOG_DEBUG, "mf_close(%s)", mf->name);
     assert(mf->open);
     for (i = 0; i < mf->no_files; i++)
     {
     assert(mf->open);
     for (i = 0; i < mf->no_files; i++)
     {
@@ -440,44 +459,58 @@ int mf_close(MFile mf)
     return 0;
 }
 
     return 0;
 }
 
-/*
- * Read one block from a metafile. Interface mirrors bfile.
+/** \brief reads block from metafile
+    \param mf metafile handle
+    \param no block position
+    \param offset offset within block
+    \param nbytes no of bytes to read (0 for whole block)
+    \param buf content (filled with data if OK)
+    \retval 0 block partially read
+    \retval 1 block fully read
+    \retval -1 block could not be read due to error
  */
 int mf_read(MFile mf, zint no, int offset, int nbytes, void *buf)
 {
     zint rd;
     int toread;
 
  */
 int mf_read(MFile mf, zint no, int offset, int nbytes, void *buf)
 {
     zint rd;
     int toread;
 
-    zebra_mutex_lock (&mf->mutex);
+    zebra_mutex_lock(&mf->mutex);
     if ((rd = file_position(mf, no, offset)) < 0)
     {
         if (rd == -2)
        {
     if ((rd = file_position(mf, no, offset)) < 0)
     {
         if (rd == -2)
        {
-           zebra_mutex_unlock (&mf->mutex);
+           zebra_mutex_unlock(&mf->mutex);
             return 0;
        }
         else
         {
             return 0;
        }
         else
         {
-            yaz_log (YLOG_FATAL, "mf_read %s internal error", mf->name);
-            exit(1);
+            yaz_log(YLOG_FATAL, "mf_read2 %s internal error", mf->name);
+            return -1;
         }
     }
     toread = nbytes ? nbytes : mf->blocksize;
     if ((rd = read(mf->files[mf->cur_file].fd, buf, toread)) < 0)
     {
         }
     }
     toread = nbytes ? nbytes : mf->blocksize;
     if ((rd = read(mf->files[mf->cur_file].fd, buf, toread)) < 0)
     {
-       yaz_log (YLOG_FATAL|YLOG_ERRNO, "mf_read: Read failed (%s)",
+       yaz_log(YLOG_FATAL|YLOG_ERRNO, "mf_read2: Read failed (%s)",
               mf->files[mf->cur_file].path);
               mf->files[mf->cur_file].path);
-       exit(1);
+        return -1;
     }
     }
-    zebra_mutex_unlock (&mf->mutex);
+    zebra_mutex_unlock(&mf->mutex);
     if (rd < toread)
        return 0;
     else
        return 1;
 }
 
     if (rd < toread)
        return 0;
     else
        return 1;
 }
 
-/*
- * Write.
+
+/** \brief writes block to metafile
+    \param mf metafile handle
+    \param no block position
+    \param offset offset within block
+    \param nbytes no of bytes to write (0 for whole block)
+    \param buf content to be written
+    \retval 0 block written
+    \retval -1 error (block not written)
  */
 int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
 {
  */
 int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
 {
@@ -488,11 +521,11 @@ int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
     char tmp[FILENAME_MAX+1];
     unsigned char dummych = '\xff';
 
     char tmp[FILENAME_MAX+1];
     unsigned char dummych = '\xff';
 
-    zebra_mutex_lock (&mf->mutex);
+    zebra_mutex_lock(&mf->mutex);
     if ((ps = file_position(mf, no, offset)) < 0)
     {
     if ((ps = file_position(mf, no, offset)) < 0)
     {
-        yaz_log (YLOG_FATAL, "mf_write %s internal error (1)", mf->name);
-       exit(1);
+        yaz_log(YLOG_FATAL, "mf_write %s internal error (1)", mf->name);
+        return -1;
     }
     /* file needs to grow */
     while (ps >= mf->files[mf->cur_file].blocks)
     }
     /* file needs to grow */
     while (ps >= mf->files[mf->cur_file].blocks)
@@ -507,22 +540,22 @@ int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
            if ((nblocks = (int) (mf->files[mf->cur_file].dir->avail_bytes /
                mf->blocksize)) > 0)
            {
            if ((nblocks = (int) (mf->files[mf->cur_file].dir->avail_bytes /
                mf->blocksize)) > 0)
            {
-               yaz_log (YLOG_DEBUG, "Capping off file %s at pos " ZINT_FORMAT,
+               yaz_log(YLOG_DEBUG, "Capping off file %s at pos " ZINT_FORMAT,
                    mf->files[mf->cur_file].path, nblocks);
                if ((ps = file_position(mf,
                    (mf->cur_file ? mf->files[mf->cur_file-1].top : 0) +
                    mf->files[mf->cur_file].blocks + nblocks - 1, 0)) < 0)
                 {
                    mf->files[mf->cur_file].path, nblocks);
                if ((ps = file_position(mf,
                    (mf->cur_file ? mf->files[mf->cur_file-1].top : 0) +
                    mf->files[mf->cur_file].blocks + nblocks - 1, 0)) < 0)
                 {
-                    yaz_log (YLOG_FATAL, "mf_write %s internal error (2)",
+                    yaz_log(YLOG_FATAL, "mf_write %s internal error (2)",
                                 mf->name);
                                 mf->name);
-                   exit(1);
+                    return -1;
                 }
                 }
-               yaz_log (YLOG_DEBUG, "ps = " ZINT_FORMAT, ps);
+               yaz_log(YLOG_DEBUG, "ps = " ZINT_FORMAT, ps);
                if (write(mf->files[mf->cur_file].fd, &dummych, 1) < 1)
                {
                if (write(mf->files[mf->cur_file].fd, &dummych, 1) < 1)
                {
-                   yaz_log (YLOG_ERRNO|YLOG_FATAL, "mf_write %s internal error (3)",
+                   yaz_log(YLOG_ERRNO|YLOG_FATAL, "mf_write %s internal error (3)",
                                      mf->name);
                                      mf->name);
-                   exit(1);
+                    return -1;
                }
                mf->files[mf->cur_file].blocks += nblocks;
                mf->files[mf->cur_file].bytes += nblocks * mf->blocksize;
                }
                mf->files[mf->cur_file].blocks += nblocks;
                mf->files[mf->cur_file].bytes += nblocks * mf->blocksize;
@@ -530,14 +563,14 @@ int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
                    mf->blocksize;
            }
            /* get other bit */
                    mf->blocksize;
            }
            /* get other bit */
-           yaz_log (YLOG_DEBUG, "Creating new file.");
+           yaz_log(YLOG_DEBUG, "Creating new file.");
            for (dp = mf->ma->dirs; dp && dp->max_bytes >= 0 &&
                dp->avail_bytes < needed; dp = dp->next);
            if (!dp)
            {
            for (dp = mf->ma->dirs; dp && dp->max_bytes >= 0 &&
                dp->avail_bytes < needed; dp = dp->next);
            if (!dp)
            {
-               yaz_log (YLOG_FATAL, "Cannot allocate more space for %s",
+               yaz_log(YLOG_FATAL, "Cannot allocate more space for %s",
                       mf->name);
                       mf->name);
-               exit(1);
+                return -1;
            }
            mf->files[mf->cur_file].top = (mf->cur_file ?
                mf->files[mf->cur_file-1].top : -1) +
            }
            mf->files[mf->cur_file].top = (mf->cur_file ?
                mf->files[mf->cur_file-1].top : -1) +
@@ -556,9 +589,9 @@ int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
            /* open new file and position at beginning */
            if ((ps = file_position(mf, no, offset)) < 0)
             {
            /* open new file and position at beginning */
            if ((ps = file_position(mf, no, offset)) < 0)
             {
-                yaz_log (YLOG_FATAL, "mf_write %s internal error (4)",
+                yaz_log(YLOG_FATAL, "mf_write %s internal error (4)",
                                 mf->name);
                                 mf->name);
-               exit(1);
+                return -1;
             }  
        }
        else
             }  
        }
        else
@@ -574,14 +607,23 @@ int mf_write(MFile mf, zint no, int offset, int nbytes, const void *buf)
     towrite = nbytes ? nbytes : mf->blocksize;
     if (write(mf->files[mf->cur_file].fd, buf, towrite) < towrite)
     {
     towrite = nbytes ? nbytes : mf->blocksize;
     if (write(mf->files[mf->cur_file].fd, buf, towrite) < towrite)
     {
-       yaz_log (YLOG_FATAL|YLOG_ERRNO, "Write failed for file %s part %d",
+       yaz_log(YLOG_FATAL|YLOG_ERRNO, "Write failed for file %s part %d",
                mf->name, mf->cur_file);
                mf->name, mf->cur_file);
-       exit(1);
+        return -1;
     }
     }
-    zebra_mutex_unlock (&mf->mutex);
+    zebra_mutex_unlock(&mf->mutex);
     return 0;
 }
 
     return 0;
 }
 
+/** \brief metafile area statistics 
+    \param ma metafile area handle
+    \param no area number (0=first, 1=second, ..)
+    \param directory holds directory upon completion (if non-NULL)
+    \param used_bytes holds used bytes upon completion (if non-NULL)
+    \param max_bytes holds max size bytes upon completion (if non-NULL)
+    \retval 0 area number does not exist
+    \retval 1 area number exists (and directory,used_bytes,.. are set)
+*/
 int mf_area_directory_stat(MFile_area ma, int no, const char **directory,
                           double *used_bytes, double *max_bytes)
 {
 int mf_area_directory_stat(MFile_area ma, int no, const char **directory,
                           double *used_bytes, double *max_bytes)
 {
index 3161f04..de1acc6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bfile.h,v 1.10 2006-08-14 10:40:14 adam Exp $
+/* $Id: bfile.h,v 1.11 2006-11-08 22:08:26 adam Exp $
    Copyright (C) 1995-2006
    Index Data ApS
 
    Copyright (C) 1995-2006
    Index Data ApS
 
@@ -101,6 +101,18 @@ BFile bf_xopen(BFiles bfs, const char *name, int block_size, int wflag,
               const char *magic, int *read_version,
               const char **more_info);
 
               const char *magic, int *read_version,
               const char **more_info);
 
+/** \brief read from block file (may call exit)
+    \param bf block file handle
+    \param no block no (first block is 0, second is 1..)
+    \param offset offset within block to be read
+    \param nbytes number of bytes to read (0 for whole block)
+    \param buf raw bytes with content (at least nbytes of size)
+    \retval 1 whole block could be read
+    \retval 0 whole block could not be read
+ */
+YAZ_EXPORT
+int bf_read(BFile bf, zint no, int offset, int nbytes, void *buf);
+
 /** \brief read from block file
     \param bf block file handle
     \param no block no (first block is 0, second is 1..)
 /** \brief read from block file
     \param bf block file handle
     \param no block no (first block is 0, second is 1..)
@@ -109,9 +121,26 @@ BFile bf_xopen(BFiles bfs, const char *name, int block_size, int wflag,
     \param buf raw bytes with content (at least nbytes of size)
     \retval 1 whole block could be read
     \retval 0 whole block could not be read
     \param buf raw bytes with content (at least nbytes of size)
     \retval 1 whole block could be read
     \retval 0 whole block could not be read
+    \retval -1 error
+ */
+YAZ_EXPORT
+int bf_read2(BFile bf, zint no, int offset, int nbytes, void *buf);
+
+
+/** \brief writes block of bytes to file (may call exit)
+    \param bf block file handle
+    \param no block no
+    \param offset within block
+    \param nbytes number of bytes to write
+    \param buf buffer to write
+    \retval 0 success (block could be written)
+
+    This function can not return a failure. System calls exit(1)
+    if write failed.
  */
 YAZ_EXPORT
  */
 YAZ_EXPORT
-int bf_read (BFile bf, zint no, int offset, int nbytes, void *buf);
+int bf_write(BFile bf, zint no, int offset, int nbytes, const void *buf);
+
 
 /** \brief writes block of bytes to file
     \param bf block file handle
 
 /** \brief writes block of bytes to file
     \param bf block file handle
@@ -119,13 +148,15 @@ int bf_read (BFile bf, zint no, int offset, int nbytes, void *buf);
     \param offset within block
     \param nbytes number of bytes to write
     \param buf buffer to write
     \param offset within block
     \param nbytes number of bytes to write
     \param buf buffer to write
-    \retval 0 succes (block could be written)
+    \retval 0 success (block written)
+    \retval -1 error
 
     This function can not return a failure. System calls exit(1)
     if write failed.
  */
 YAZ_EXPORT
 
     This function can not return a failure. System calls exit(1)
     if write failed.
  */
 YAZ_EXPORT
-int bf_write (BFile bf, zint no, int offset, int nbytes, const void *buf);
+int bf_write2(BFile bf, zint no, int offset, int nbytes, const void *buf);
+
 
 /** \brief enables or disables shadow for block files
     \param bfs block files
 
 /** \brief enables or disables shadow for block files
     \param bfs block files