X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=blobdiff_plain;f=bfile%2Fcfile.c;h=2d39e045a7ebd198c314a8e05d37b15f374c03d7;hp=f84d395a1bd32d702af2afcc22171a293b95cb80;hb=aeea139423b8eaf28a4de53b3d7b2ad1f22284e7;hpb=91c31916bd40829afa20cd4e104ffc764ea116bf diff --git a/bfile/cfile.c b/bfile/cfile.c index f84d395..2d39e04 100644 --- a/bfile/cfile.c +++ b/bfile/cfile.c @@ -1,8 +1,5 @@ -/* $Id: cfile.c,v 1.38 2006-11-08 22:08:27 adam Exp $ - Copyright (C) 1995-2006 - Index Data ApS - -This file is part of the Zebra server. +/* This file is part of the Zebra server. + Copyright (C) 1994-2011 Index Data Zebra is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -20,6 +17,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#if HAVE_CONFIG_H +#include +#endif #include #include #include @@ -29,6 +29,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "mfile.h" #include "cfile.h" +/** \brief set to 1 if extra commit/shadow check is to be performed */ +#define EXTRA_CHECK 0 + static int write_head(CFile cf) { int left = cf->head.hash_size * sizeof(zint); @@ -83,12 +86,14 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname, CFile cf = (CFile) xmalloc(sizeof(*cf)); int hash_bytes; - yaz_log(YLOG_DEBUG, "cf: open %s %s", cf->rmf->name, - wflag ? "rdwr" : "rd"); - + /* avoid valgrind warnings, but set to something nasty */ + memset(cf, 'Z', sizeof(*cf)); + + yaz_log(YLOG_DEBUG, "cf: open %s %s", fname, wflag ? "rdwr" : "rd"); + cf->block_mf = 0; cf->hash_mf = 0; - cf->rmf = mf; + cf->rmf = mf; assert(firstp); @@ -110,14 +115,12 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname, 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); cf_close(cf); return 0; } 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); cf_close(cf); return 0; } @@ -131,11 +134,11 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname, if (ret == 0 || !cf->head.state) { *firstp = 1; - cf->head.state = 1; + cf->head.state = CFILE_STATE_HASH; cf->head.block_size = block_size; cf->head.hash_size = 199; hash_bytes = cf->head.hash_size * sizeof(zint); - cf->head.flat_bucket = cf->head.next_bucket = cf->head.first_bucket = + 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->array = (zint *) xmalloc(hash_bytes); @@ -163,7 +166,7 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname, hash_bytes = cf->head.hash_size * sizeof(zint); assert(cf->head.next_bucket > 0); assert(cf->head.next_block > 0); - if (cf->head.state == 1) + if (cf->head.state == CFILE_STATE_HASH) cf->array = (zint *) xmalloc(hash_bytes); else cf->array = NULL; @@ -173,7 +176,7 @@ CFile cf_open(MFile mf, MFile_area area, const char *fname, return 0; } } - if (cf->head.state == 1) + if (cf->head.state == CFILE_STATE_HASH) { cf->parray = (struct CFile_hash_bucket **) xmalloc(cf->head.hash_size * sizeof(*cf->parray)); @@ -202,14 +205,15 @@ static void release_bucket(CFile cf, struct CFile_hash_bucket *p) *p->h_prev = p->h_next; if (p->h_next) p->h_next->h_prev = p->h_prev; - + --(cf->bucket_in_memory); xfree(p); } -static void flush_bucket(CFile cf, int no_to_flush) +static int flush_bucket(CFile cf, int no_to_flush) { int i; + int ret = 0; struct CFile_hash_bucket *p; for (i = 0; i != no_to_flush; i++) @@ -219,11 +223,16 @@ 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); + if (ret == 0) + { + if (mf_write(cf->hash_mf, p->ph.this_bucket, 0, 0, &p->ph)) + ret = -1; + } cf->dirty = 1; } release_bucket(cf, p); } + return ret; } static struct CFile_hash_bucket *alloc_bucket(CFile cf, zint block_no, int hno) @@ -231,7 +240,10 @@ 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); + { + if (flush_bucket(cf, 1)) + return 0; + } assert(cf->bucket_in_memory < cf->max_bucket_in_memory); ++(cf->bucket_in_memory); p = (struct CFile_hash_bucket *) xmalloc(sizeof(*p)); @@ -242,7 +254,7 @@ static struct CFile_hash_bucket *alloc_bucket(CFile cf, zint block_no, int hno) cf->bucket_lru_front->lru_next = p; else cf->bucket_lru_back = p; - cf->bucket_lru_front = p; + cf->bucket_lru_front = p; pp = cf->parray + hno; p->h_next = *pp; @@ -258,10 +270,12 @@ 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 (!p) + return 0; p->dirty = 0; - if (!mf_read(cf->hash_mf, block_no, 0, 0, &p->ph)) + if (mf_read(cf->hash_mf, block_no, 0, 0, &p->ph) != 1) { - yaz_log(YLOG_FATAL|YLOG_ERRNO, "read get_bucket"); + yaz_log(YLOG_FATAL, "read get_bucket"); release_bucket(cf, p); return 0; } @@ -277,6 +291,8 @@ static struct CFile_hash_bucket *new_bucket(CFile cf, zint *block_nop, int hno) block_no = *block_nop = cf->head.next_bucket++; p = alloc_bucket(cf, block_no, hno); + if (!p) + return 0; p->dirty = 1; for (i = 0; ihash_mf, hno+cf->head.next_bucket, off, sizeof(zint), vno); + if (mf_read(cf->hash_mf, hno+cf->head.next_bucket, off, sizeof(zint), vno) + == -1) + return -1; if (*vno) return 1; return 0; @@ -327,20 +345,19 @@ static int cf_lookup_hash(CFile cf, zint no, zint *vno) } if (hb) continue; -#if 0 - /* extra check ... */ +#if EXTRA_CHECK for (hb = cf->bucket_lru_back; hb; hb = hb->lru_next) { if (hb->ph.this_bucket == block_no) { yaz_log(YLOG_FATAL, "Found hash bucket on other chain(1)"); - abort(); + return -1; } for (i = 0; iph.vno[i]; i++) if (hb->ph.no[i] == no) { yaz_log(YLOG_FATAL, "Found hash bucket on other chain (2)"); - abort(); + return -1; } } #endif @@ -376,14 +393,14 @@ static int cf_moveto_flat(CFile cf) int j; zint i; - 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->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->head.state == CFILE_STATE_HASH); + if (flush_bucket(cf, -1)) + return -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++) @@ -408,7 +425,7 @@ static int cf_moveto_flat(CFile cf) cf->array = NULL; xfree(cf->parray); cf->parray = NULL; - cf->head.state = 2; + cf->head.state = CFILE_STATE_FLAT; cf->dirty = 1; return 0; } @@ -432,10 +449,10 @@ static zint cf_new_hash(CFile cf, zint no) { int hno = cf_hash(cf, no); struct CFile_hash_bucket *hbprev = NULL, *hb = cf->parray[hno]; - zint *bucketpp = &cf->array[hno]; + zint *bucketpp = &cf->array[hno]; int i; zint vno = (cf->head.next_block)++; - + for (hb = cf->parray[hno]; hb; hb = hb->h_next) if (!hb->ph.vno[HASH_BUCKET-1]) for (i = 0; ibucket_lru_back; hb; hb = hb->lru_next) { if (hb->ph.this_bucket == *bucketpp) { yaz_log(YLOG_FATAL, "Found hash bucket on other chain"); - abort(); + return 0; } } #endif @@ -489,6 +505,9 @@ static zint cf_new_hash(CFile cf, zint no) if (hbprev) hbprev->dirty = 1; hb = new_bucket(cf, bucketpp, hno); + if (!hb) + return 0; + hb->ph.no[0] = no; hb->ph.vno[0] = vno; return vno; @@ -523,19 +542,25 @@ int cf_read(CFile cf, zint no, int offset, int nbytes, void *buf) { zint block; int ret; - + assert(cf); zebra_mutex_lock(&cf->mutex); ret = cf_lookup(cf, no, &block); zebra_mutex_unlock(&cf->mutex); - if (ret != 1) + if (ret == -1) { - /* block could not be read or error */ + /* error */ + yaz_log(YLOG_FATAL, "cf_lookup failed"); + return -1; + } + else if (ret == 0) + { + /* block could not be read */ return ret; } - if (mf_read(cf->block_mf, block, offset, nbytes, buf) != 1) + else 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); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "mf_read no=" ZINT_FORMAT " block=" ZINT_FORMAT, no, block); return -1; } return 1; @@ -575,7 +600,8 @@ int cf_write(CFile cf, zint no, int offset, int nbytes, const void *buf) } if (offset || nbytes) { - mf_read(cf->rmf, no, 0, 0, cf->iobuf); + if (mf_read(cf->rmf, no, 0, 0, cf->iobuf) == -1) + return -1; memcpy(cf->iobuf + offset, buf, nbytes); buf = cf->iobuf; offset = 0; @@ -588,17 +614,21 @@ int cf_write(CFile cf, zint no, int offset, int nbytes, const void *buf) int cf_close(CFile cf) { + int ret = 0; 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 (flush_bucket(cf, -1)) + ret = -1; if (cf->hash_mf) { if (cf->dirty) { - mf_write(cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head); - write_head(cf); + if (mf_write(cf->hash_mf, 0, 0, sizeof(cf->head), &cf->head)) + ret = -1; + if (write_head(cf)) + ret = -1; } mf_close(cf->hash_mf); } @@ -609,12 +639,13 @@ int cf_close(CFile cf) xfree(cf->iobuf); zebra_mutex_destroy(&cf->mutex); xfree(cf); - return 0; + return ret; } /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab