X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=blobdiff_plain;f=bfile%2Fbfile.c;h=facec01ef09c48fb7c1a32342f9178e7c2a4c4c4;hp=41b8a62a8a180c6420d3b9d17038239eb5adeb39;hb=deff57cfa9d9b39c4a4f1c9b82a64c6e61d821a4;hpb=8374209906a1ff4f2b0f9a855f67af2b460dfea4 diff --git a/bfile/bfile.c b/bfile/bfile.c index 41b8a62..facec01 100644 --- a/bfile/bfile.c +++ b/bfile/bfile.c @@ -1,4 +1,4 @@ -/* $Id: bfile.c,v 1.39 2005-01-15 19:38:17 adam Exp $ +/* $Id: bfile.c,v 1.40 2005-03-30 09:25:23 adam Exp $ Copyright (C) 1995-2005 Index Data ApS @@ -30,7 +30,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include #endif -#include +#include #include #include "mfile.h" #include "cfile.h" @@ -40,6 +40,14 @@ struct BFile_struct MFile mf; Zebra_lock_rdwr rdwr_lock; struct CFile_struct *cf; + char *alloc_buf; + int block_size; + int alloc_buf_size; + zint last_block; + zint free_list; + zint root_block; + char *magic; + int header_dirty; }; struct BFiles_struct { @@ -116,48 +124,153 @@ int bf_close (BFile bf) if (bf->cf) cf_close (bf->cf); mf_close (bf->mf); - xfree (bf); + xfree(bf->alloc_buf); + xfree(bf->magic); + xfree(bf); return 0; } +#define HEADER_SIZE 256 + +BFile bf_xopen(BFiles bfs, const char *name, int block_size, int wrflag, + const char *magic, int *read_version, + const char **more_info) +{ + char read_magic[40]; + int l = 0; + int i = 0; + char *hbuf; + zint pos = 0; + BFile bf = bf_open(bfs, name, block_size, wrflag); + + if (!bf) + return 0; + /* HEADER_SIZE is considered enough for our header */ + if (bf->alloc_buf_size < HEADER_SIZE) + bf->alloc_buf_size = HEADER_SIZE; + else + bf->alloc_buf_size = bf->block_size; + + hbuf = bf->alloc_buf = xmalloc(bf->alloc_buf_size); + + /* fill-in default values */ + bf->free_list = 0; + bf->root_block = bf->last_block = HEADER_SIZE / bf->block_size + 1; + bf->magic = xstrdup(magic); + + if (!bf_read(bf, pos, 0, 0, hbuf + pos * bf->block_size)) + { + if (wrflag) + bf->header_dirty = 1; + return bf; + } + while(hbuf[pos * bf->block_size + i] != '\0') + { + if (i == bf->block_size) + { /* end of block at pos reached .. */ + if (bf->alloc_buf_size < (pos+1) * bf->block_size) + { + /* not room for all in alloc_buf_size */ + yaz_log(YLOG_WARN, "bad header for %s (3)", magic); + bf_close(bf); + return 0; + } + /* read next block in header */ + pos++; + if (!bf_read(bf, pos, 0, 0, hbuf + pos * bf->block_size)) + { + yaz_log(YLOG_WARN, "missing header block %s (4)", magic); + bf_close(bf); + return 0; + } + i = 0; /* pos within block is reset */ + } + else + i++; + } + if (sscanf(hbuf, "%39s %d " ZINT_FORMAT " " ZINT_FORMAT "%n", + read_magic, read_version, &bf->last_block, + &bf->free_list, &l) < 4 && l) /* if %n is counted, it's 5 */ + { + yaz_log(YLOG_WARN, "bad header for %s (1)", magic); + bf_close(bf); + return 0; + } + if (strcmp(read_magic, magic)) + { + yaz_log(YLOG_WARN, "bad header for %s (2)", magic); + bf_close(bf); + return 0; + } + if (more_info) + *more_info = hbuf + l; + return bf; +} + +int bf_xclose (BFile bf, int version, const char *more_info) +{ + if (bf->header_dirty) + { + assert(bf->alloc_buf); + zint pos = 0; + assert(bf->magic); + sprintf(bf->alloc_buf, "%s %d " ZINT_FORMAT " " ZINT_FORMAT " ", + bf->magic, version, bf->last_block, bf->free_list); + if (more_info) + strcat(bf->alloc_buf, more_info); + while (1) + { + bf_write(bf, pos, 0, 0, bf->alloc_buf + pos * bf->block_size); + pos++; + if (pos * bf->block_size > strlen(bf->alloc_buf)) + break; + } + } + return bf_close(bf); +} + BFile bf_open (BFiles bfs, const char *name, int block_size, int wflag) { - BFile tmp = (BFile) xmalloc(sizeof(struct BFile_struct)); + BFile bf = (BFile) xmalloc(sizeof(struct BFile_struct)); + bf->alloc_buf = 0; + bf->magic = 0; + bf->block_size = block_size; + bf->header_dirty = 0; if (bfs->commit_area) { int first_time; - tmp->mf = mf_open (bfs->register_area, name, block_size, 0); - tmp->cf = cf_open (tmp->mf, bfs->commit_area, name, block_size, + 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 (first_time) { FILE *outf; - outf = open_cache (bfs, "ab"); + outf = open_cache(bfs, "ab"); if (!outf) { - yaz_log (YLOG_FATAL|YLOG_ERRNO, "open %s", bfs->cache_fname); - exit (1); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", bfs->cache_fname); + exit(1); } - fprintf (outf, "%s %d\n", name, block_size); - fclose (outf); + fprintf(outf, "%s %d\n", name, block_size); + fclose(outf); } } else { - tmp->mf = mf_open(bfs->register_area, name, block_size, wflag); - tmp->cf = NULL; + bf->mf = mf_open(bfs->register_area, name, block_size, wflag); + bf->cf = NULL; } - if (!tmp->mf) + if (!bf->mf) { - yaz_log (YLOG_FATAL, "mf_open failed for %s", name); - xfree (tmp); + yaz_log(YLOG_FATAL, "mf_open failed for %s", name); + xfree(bf); return 0; } - zebra_lock_rdwr_init (&tmp->rdwr_lock); - return(tmp); + zebra_lock_rdwr_init(&bf->rdwr_lock); + return bf; } int bf_read (BFile bf, zint no, int offset, int nbytes, void *buf) @@ -268,3 +381,48 @@ void bf_commitClean (BFiles bfs, const char *spec) 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)) + { + yaz_log(YLOG_WARN, "Bad freelist entry " ZINT_FORMAT, + bf->free_list); + exit(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; +}