From 3b69446cc3a0a05152253db576566dab9a5836c8 Mon Sep 17 00:00:00 2001 From: teodor Date: Tue, 5 Oct 2004 08:03:06 +0000 Subject: [PATCH 1/1] test program, flatdb tested --- Makefile | 4 +- flatdb.c | 32 ++++++++---- flatdb.h | 2 +- flatdbtest.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 flatdbtest.c diff --git a/Makefile b/Makefile index e58d726..7184bef 100644 --- a/Makefile +++ b/Makefile @@ -5,12 +5,12 @@ LD=ld -x -shared INCLUDE=-I. CFLAGS=-Wall -g -O2 -pedantic -ansi -DASSERT_CORE -D_GNU_SOURCE -DHAVE_POLL_H -DHAVE_SYS_POLL_H -DHAVE_HSTRERROR -LIB=-L. -ltedtools -lm +LIB=-g -L. -ltedtools -lm OBJS=tlog.o tmalloc.o tools.o prs_hmap.o sfxstr.o \ regis.o prs_inf.o shmem.o tcp.o udp.o connpool.o \ psort.o flatdb.o -PROGS=sfxtest hextest inftest kilter psortex +PROGS=sfxtest hextest inftest kilter psortex flatdbtest .SUFFIXES: .o.c diff --git a/flatdb.c b/flatdb.c index b591041..3ee3472 100644 --- a/flatdb.c +++ b/flatdb.c @@ -74,24 +74,33 @@ cmpFS(const void* a, const void* b) { void FDBVacuumFreeSpace(FDB *db) { FDBFreeSpace *ptr=db->space+1, *ok=db->space; + if ( db->listcur < 2 ) return; qsort( db->space, db->listcur, sizeof(FDBFreeSpace), cmpFS); + /* merge spaces */ while( ptr - db->space < db->listcur ) { - tassert( ok->offset + ok->length <= ptr->offset ); if ( ok->offset + ok->length == ptr->offset || ptr->length==0 ) { ok->length += ptr->length; - } else { + ptr->length=0; + } else ok++; - if ( ok != ptr-1 ) - memcpy(ok, ptr, sizeof(FDBFreeSpace)); - } ptr++; } - db->listcur = ok - db->space + 1; + /* remove void spaces */ + ptr = ok = db->space; + while( ptr - db->space < db->listcur ) { + if ( ptr->length != 0 ) { + if ( ok != ptr ) + memcpy(ok,ptr,sizeof(FDBFreeSpace)); + ok++; + } + ptr++; + } + db->listcur = ok - db->space; } int @@ -247,7 +256,7 @@ FDBGet(FDB *db, off_t offset, size_t length, FDBRecord **record) { *record=NULL; - if ( db->readonly ) + if ( offset < sizeof(FDBHeader) ) return FDB_ERROR; if ( length==0 ) @@ -288,10 +297,13 @@ FDBPut(FDB *db, FDBRecord *record, off_t *offset ) { ptr = findFreeSpace( db, record->length ); if ( ptr ) { *offset = ptr->offset; - ptr->offset += record->length; ptr->length -= record->length; - if ( ptr->length == 0 ) - FDBVacuumFreeSpace(db); + if ( ptr->length == 0 ) { + if ( (ptr - db->space) + 1 != db->listcur ) + memmove(ptr, ptr+1, (db->listcur - (ptr - db->space) + 1) * sizeof(FDBFreeSpace)); + db->listcur--; + } else + ptr->offset += record->length; if ( lseek(db->fd, *offset, SEEK_SET) != *offset ) tlog(TL_CRIT|TL_EXIT,"FDBPut: lseek failed: %s", strerror(errno)); } else { diff --git a/flatdb.h b/flatdb.h index 5130258..5c3a4da 100644 --- a/flatdb.h +++ b/flatdb.h @@ -41,7 +41,7 @@ typedef struct { typedef struct { size_t length; - char *data; + char data[1]; } FDBRecord; #define RECHDRSZ (sizeof(size_t)) diff --git a/flatdbtest.c b/flatdbtest.c new file mode 100644 index 0000000..ec6fb69 --- /dev/null +++ b/flatdbtest.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2004 Teodor Sigaev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "tlog.h" +#include "tmalloc.h" +#include "flatdb.h" + +static void +usage() { + puts( + "Usage:\n" + "flatdbtest [-r] -f FILE [ -p INFO | -g OFFSET | -d OFFSET | -v [ ... ] ]\n" + "flatdbtest -f FILE -s" + ); + exit(1); +} + +extern char *optarg; +extern int opterr; + +int +main(int argn, char *argv[]) { + FDB db; + int i; + int isopened=0, readonly=0; + off_t offset; + int len,rc; + FDBRecord *record; + + opentlog(TL_OPEN_STDERR,TL_DEBUG, NULL); + opterr=0; + + while((i=getopt(argn,argv,"srf:p:g:d:vh")) != EOF) { + switch(i) { + case 'r': + if (isopened) {FDBClose(&db); usage();} + readonly=1; + break; + case 'f': + if (isopened) {FDBClose(&db); usage();} + if ( (rc=FDBOpen(&db, optarg, readonly)) != FDB_OK ) + tlog(TL_CRIT|TL_EXIT, "FDBOpen failed: %d", rc); + isopened=1; + break; + case 'v': + if (!isopened) {usage();} + FDBVacuumFreeSpace(&db); + puts("Vacuum"); + break; + case 'p': + if (!isopened) {usage();} + len = RECHDRSZ + strlen(optarg); + record = (FDBRecord*)tmalloc( len ); + record->length = (size_t)len; + memcpy( record->data, optarg, len-RECHDRSZ ); + if ( (rc=FDBPut(&db, record, &offset)) != FDB_OK ) { + FDBClose(&db); + tlog(TL_CRIT|TL_EXIT, "FDBPut failed: %d", rc); + } + tfree(record); + printf("Put: off:%d len:%d '%s'\n", (int)offset, len-RECHDRSZ, optarg); + break; + case 'g': + if (!isopened) {usage();} + offset = atoi(optarg); + if ( (rc=FDBGet(&db, offset, 0, &record)) != FDB_OK ) { + FDBClose(&db); + tlog(TL_CRIT|TL_EXIT, "FDBGet failed: %d", rc); + } + printf("Get: off:%d len:%d '", (int)offset, record->length - RECHDRSZ); + fwrite(record->data, record->length - RECHDRSZ, 1, stdout); + puts("'"); + tfree(record); + break; + case 'd': + if (!isopened) {usage();} + offset = atoi(optarg); + if ( (rc=FDBDelete(&db, offset, 0)) != FDB_OK ) { + FDBClose(&db); + tlog(TL_CRIT|TL_EXIT, "FDBDelete failed: %d", rc); + } + printf("Del: off:%d\n", (int)offset); + break; + case 's': + if (!isopened) {usage();} + if ( db.listcur ) { + puts("List of free space:"); + for(i=0;i