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
 
@@ -62,12 +62,12 @@ struct BFiles_struct {
 
 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 = xstrdup (base);
+        bfs->base = xstrdup(base);
     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;
 }
 
-void bfs_destroy (BFiles bfs)
+void bfs_destroy(BFiles bfs)
 {
     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 = fopen (bfs->cache_fname, flags);
+    file = fopen(bfs->cache_fname, flags);
     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)
     {
-        yaz_log (YLOG_LOG, "enabling shadow spec=%s", spec);
+        yaz_log(YLOG_LOG, "enabling shadow spec=%s", spec);
         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)
         {
-            bfs->cache_fname = xmalloc (strlen(bfs->commit_area->dirs->name)+
+            bfs->cache_fname = xmalloc(strlen(bfs->commit_area->dirs->name)+
                                        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
        {
@@ -123,16 +123,17 @@ ZEBRA_RES bf_cache (BFiles bfs, const char *spec)
        }
     }
     else
-        bfs->commit_area = NULL;
+        bfs->commit_area = 0;
     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)
-        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);
@@ -218,7 +219,7 @@ BFile bf_xopen(BFiles bfs, const char *name, int block_size, int wrflag,
     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)
     {
@@ -240,21 +241,31 @@ int bf_xclose (BFile bf, int version, const char *more_info)
     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->cf = 0;
+    bf->mf = 0;
+    zebra_lock_rdwr_init(&bf->rdwr_lock);
+
     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;
@@ -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);
-                exit(1);
+                bf_close(bf);
+                return 0;
             }
             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);
-        bf->cf = NULL;
     }
     if (!bf->mf)
     {
         yaz_log(YLOG_FATAL, "mf_open failed for %s", name);
-        xfree(bf);
+        bf_close(bf);
         return 0;
     }
-    zebra_lock_rdwr_init(&bf->rdwr_lock);
     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 ((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 
-       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;
-    zebra_lock_rdwr_wlock (&bf->rdwr_lock);
+    zebra_lock_rdwr_wlock(&bf->rdwr_lock);
     if (bf->cf)
-        r = cf_write (bf->cf, no, offset, nbytes, buf);
+        r = cf_write(bf->cf, no, offset, nbytes, buf);
     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;
 }
 
-int bf_commitExists (BFiles bfs)
+int bf_commitExists(BFiles bfs)
 {
     FILE *inf;
 
-    inf = open_cache (bfs, "rb");
+    inf = open_cache(bfs, "rb");
     if (inf)
     {
-        fclose (inf);
+        fclose(inf);
         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);
+    unlink_cache(bfs);
 }
 
-void bf_commitExec (BFiles bfs)
+void bf_commitExec(BFiles bfs)
 {
     FILE *inf;
     int block_size;
@@ -342,40 +380,40 @@ void bf_commitExec (BFiles bfs)
     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 ;
     }
-    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)
     {
-        bf_cache (bfs, spec);
+        bf_cache(bfs, spec);
         mustDisable = 1;
     }
 
     mf_reset(bfs->commit_area, 1);
 
-    unlink_cache (bfs);
+    unlink_cache(bfs);
     if (mustDisable)
-        bf_cache (bfs, 0);
+        bf_cache(bfs, 0);
 }
 
 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
 
@@ -29,26 +29,29 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #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 r = 0;
     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)
-        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;
@@ -58,41 +61,74 @@ static int read_head (CFile cf)
         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)
-        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];
-    int i;
-    CFile cf = (CFile) xmalloc (sizeof(*cf));
+    int i, ret;
+    CFile cf = (CFile) xmalloc(sizeof(*cf));
     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; 
-    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;
@@ -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;
-        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)
-            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;
-        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);
-        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)
-            cf->array = (zint *) xmalloc (hash_bytes);
+            cf->array = (zint *) xmalloc(hash_bytes);
         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 **)
-           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;
     }
-    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;
 }
 
-static int cf_hash (CFile cf, zint no)
+static int cf_hash(CFile cf, zint no)
 {
     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;
@@ -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);
-    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;
@@ -181,22 +219,22 @@ static void flush_bucket (CFile cf, int no_to_flush)
             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;
         }
-        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)
-        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);
-    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;
@@ -215,29 +253,31 @@ static struct CFile_hash_bucket *alloc_bucket (CFile cf, zint block_no, int hno)
     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;
 
-    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;
 }
 
-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++;
-    p = alloc_bucket (cf, block_no, hno);
+    p = alloc_bucket(cf, block_no, hno);
+    p->dirty = 1;
 
     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->dirty = 1;
     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 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;
@@ -273,7 +314,8 @@ static zint cf_lookup_hash (CFile cf, zint no)
             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)
@@ -291,27 +333,32 @@ static zint cf_lookup_hash (CFile cf, zint 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)
                 {
-                    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)++;
-        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)
-                return hb->ph.vno[i];
+            {
+                *vno = hb->ph.vno[i];
+                return 1;
+            }
     }
     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);
@@ -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;
-    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;
 
-    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);
-    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++)
     {
-        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++)
-            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;
-    xfree (cf->parray);
+    xfree(cf->parray);
     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)
-        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)++;
 
-    cf_write_flat (cf, no, vno);
+    cf_write_flat(cf, no, 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;
@@ -410,14 +466,15 @@ static zint cf_new_hash (CFile cf, zint no)
         {
             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)++;
-        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])
             {
@@ -431,93 +488,127 @@ static zint cf_new_hash (CFile cf, zint no)
     }
     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;
 }
 
-zint cf_new (CFile cf, zint no)
+zint cf_new(CFile cf, zint no)
 {
     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)
     {
-        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;
+    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;
 }
 
-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;
+    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)
         {
-            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;
         }
     }
-    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);
-    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;
 }
 
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
 
@@ -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
@@ -70,13 +62,13 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
             break;
         if (!yaz_is_abspath(ad) && base)
         {
-            strcpy (dirname, base);
+            strcpy(dirname, base);
             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;
@@ -85,12 +77,12 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
         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)
         {
-           yaz_log (YLOG_WARN, "Empty path: %s", ad0);
+           yaz_log(YLOG_WARN, "Empty path: %s", ad0);
             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')
         {
-           yaz_log (YLOG_FATAL, "Missing size after path: %s", ad0);
+           yaz_log(YLOG_FATAL, "Missing size after path: %s", ad0);
             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':
-            yaz_log (YLOG_FATAL, "Missing unit: %s", ad0);
+            yaz_log(YLOG_FATAL, "Missing unit: %s", ad0);
             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++;
@@ -134,6 +126,15 @@ static int scan_areadef(MFile_area ma, const char *ad, const char *base)
     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;
@@ -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)
+            {
+                /* we can't open it for reading. But not really an error */
                 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;
-    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)
     {
-       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;
@@ -188,10 +192,12 @@ static int cmp_part_file(const void *p1, const void *p2)
     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));
@@ -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];
     
-    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)
     {
-       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 */
@@ -217,7 +223,7 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
     {
        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;
        }
@@ -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);
-           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;
-           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);
-           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)
@@ -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));
-               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;
@@ -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)
            {
-               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)
            {
-               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;
            }
@@ -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)
     {
-       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);
@@ -294,6 +300,9 @@ MFile_area mf_init(const char *name, const char *spec, const char *base)
     return ma;
 }
 
+/** \brief destroys metafile area handle
+    \param ma metafile area handle
+*/
 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;
-       xfree (d);
+       xfree(d);
     }
     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;
@@ -325,21 +338,25 @@ void mf_reset(MFile_area ma, int unlink_flag)
 
        meta_f = meta_f->next;
 
-       assert (!m->open);
+       assert(!m->open);
        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;
 }
 
-/*
- * 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)
 {
@@ -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");
-    assert (ma);
+    assert(ma);
     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 */
-       zebra_mutex_init (&mnew->mutex);
+       zebra_mutex_init(&mnew->mutex);
        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)
        {
-           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;
@@ -416,14 +434,15 @@ MFile mf_open(MFile_area ma, const char *name, int block_size, int wflag)
     return mnew;
 }
 
-/*
- * Close a metafile.
- */
+/** \brief closes metafile
+    \param mf metafile handle
+    \retval 0 OK
+*/
 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++)
     {
@@ -440,44 +459,58 @@ int mf_close(MFile mf)
     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;
 
-    zebra_mutex_lock (&mf->mutex);
+    zebra_mutex_lock(&mf->mutex);
     if ((rd = file_position(mf, no, offset)) < 0)
     {
         if (rd == -2)
        {
-           zebra_mutex_unlock (&mf->mutex);
+           zebra_mutex_unlock(&mf->mutex);
             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)
     {
-       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);
-       exit(1);
+        return -1;
     }
-    zebra_mutex_unlock (&mf->mutex);
+    zebra_mutex_unlock(&mf->mutex);
     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)
 {
@@ -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';
 
-    zebra_mutex_lock (&mf->mutex);
+    zebra_mutex_lock(&mf->mutex);
     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)
@@ -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)
            {
-               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)
                 {
-                    yaz_log (YLOG_FATAL, "mf_write %s internal error (2)",
+                    yaz_log(YLOG_FATAL, "mf_write %s internal error (2)",
                                 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)
                {
-                   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);
-                   exit(1);
+                    return -1;
                }
                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 */
-           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)
            {
-               yaz_log (YLOG_FATAL, "Cannot allocate more space for %s",
+               yaz_log(YLOG_FATAL, "Cannot allocate more space for %s",
                       mf->name);
-               exit(1);
+                return -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)
             {
-                yaz_log (YLOG_FATAL, "mf_write %s internal error (4)",
+                yaz_log(YLOG_FATAL, "mf_write %s internal error (4)",
                                 mf->name);
-               exit(1);
+                return -1;
             }  
        }
        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)
     {
-       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);
-       exit(1);
+        return -1;
     }
-    zebra_mutex_unlock (&mf->mutex);
+    zebra_mutex_unlock(&mf->mutex);
     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)
 {
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
 
@@ -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);
 
+/** \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..)
@@ -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
+    \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
-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
@@ -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
-    \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
-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