+
+int bf_read(BFile bf, zint no, int offset, int nbytes, void *buf)
+{
+ int ret = bf_read2(bf, no, offset, nbytes, buf);
+
+ if (ret == -1)
+ {
+ zebra_exit("bf_read");
+ }
+ 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 ((ret = cf_read(bf->cf, no, offset, nbytes, buf)) == 0)
+ ret = mf_read(bf->mf, no, offset, nbytes, buf);
+ }
+ else
+ 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)
+ {
+ zebra_exit("bf_write");
+ }
+ return ret;
+}
+
+int bf_write2(BFile bf, zint no, int offset, int nbytes, const void *buf)
+{
+ int r;
+ zebra_lock_rdwr_wlock(&bf->rdwr_lock);
+ if (bf->cf)
+ 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);
+ return r;
+}
+
+int bf_commitExists(BFiles bfs)
+{
+ FILE *inf;
+
+ inf = open_cache(bfs, "rb");
+ if (inf)
+ {
+ fclose(inf);
+ return 1;
+ }
+ return 0;
+}
+
+void bf_reset(BFiles bfs)
+{
+ if (!bfs)
+ return;
+ mf_reset(bfs->commit_area, 1);
+ mf_reset(bfs->register_area, 1);
+ unlink_cache(bfs);
+}
+
+int bf_commitExec(BFiles bfs)
+{
+ FILE *inf;
+ int block_size;
+ char path[256];
+ MFile mf;
+ CFile cf;
+ int first_time;
+ int r = 0;
+
+ assert(bfs->commit_area);
+ if (!(inf = open_cache(bfs, "rb")))
+ {
+ yaz_log(YLOG_LOG, "No commit file");
+ return -1;
+ }
+ while (fscanf(inf, "%s %d", path, &block_size) == 2)
+ {
+ mf = mf_open(bfs->register_area, path, block_size, 1);
+ if (!mf)
+ {
+ r = -1;
+ break;
+ }
+ cf = cf_open(mf, bfs->commit_area, path, block_size, 0, &first_time);
+ if (!cf)
+ {
+ mf_close(mf);
+ r = -1;
+ break;
+ }
+
+ r = cf_commit(cf);
+
+ cf_close(cf);
+ mf_close(mf);
+
+ if (r)
+ break;
+ }
+ fclose(inf);
+ return r;
+}
+
+void bf_commitClean(BFiles bfs, const char *spec)
+{
+ int mustDisable = 0;
+
+ if (!bfs->commit_area)
+ {
+ bf_cache(bfs, spec);
+ mustDisable = 1;
+ }
+
+ mf_reset(bfs->commit_area, 1);
+
+ unlink_cache(bfs);
+ if (mustDisable)
+ bf_cache(bfs, 0);
+}
+
+int bf_alloc(BFile bf, int no, zint *blocks)
+{
+ int i;
+ assert(bf->alloc_buf);
+ bf->header_dirty = 1;
+ for (i = 0; i < no; i++)
+ {
+ if (!bf->free_list)
+ blocks[i] = bf->last_block++;
+ else
+ {
+ char buf[16];
+ const char *cp = buf;
+ memset(buf, '\0', sizeof(buf));
+
+ blocks[i] = bf->free_list;
+ if (bf_read(bf, bf->free_list, 0, sizeof(buf), buf) != 1)
+ {
+ yaz_log(YLOG_WARN, "Bad freelist entry " ZINT_FORMAT,
+ bf->free_list);
+ return -1;
+ }
+ zebra_zint_decode(&cp, &bf->free_list);
+ }
+ }
+ return 0;
+}
+
+int bf_free(BFile bf, int no, const zint *blocks)
+{
+ int i;
+ assert(bf->alloc_buf);
+ bf->header_dirty = 1;
+ for (i = 0; i < no; i++)
+ {
+ char buf[16];
+ char *cp = buf;
+ memset(buf, '\0', sizeof(buf));
+ zebra_zint_encode(&cp, bf->free_list);
+ bf->free_list = blocks[i];
+ bf_write(bf, bf->free_list, 0, sizeof(buf), buf);
+ }
+ return 0;
+}
+
+int bfs_register_directory_stat(BFiles bfs, int no, const char **directory,
+ double *used_bytes, double *max_bytes)
+{
+ return mf_area_directory_stat(bfs->register_area, no, directory,
+ used_bytes, max_bytes);
+}
+
+
+int bfs_shadow_directory_stat(BFiles bfs, int no, const char **directory,
+ double *used_bytes, double *max_bytes)
+{
+ if (!bfs->commit_area)
+ return 0;
+ return mf_area_directory_stat(bfs->commit_area, no, directory,
+ used_bytes, max_bytes);
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+