From 932697e4b6d6dd00a210b84b285bd8c0000f379f Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Tue, 29 Oct 1996 13:40:37 +0000 Subject: [PATCH] First work. --- include/isamc.h | 57 +++++++ isamc/Makefile | 52 ++++++ isamc/isamc-p.h | 45 +++++ isamc/isamc.c | 491 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 645 insertions(+) create mode 100644 include/isamc.h create mode 100644 isamc/Makefile create mode 100644 isamc/isamc-p.h create mode 100644 isamc/isamc.c diff --git a/include/isamc.h b/include/isamc.h new file mode 100644 index 0000000..8aa911b --- /dev/null +++ b/include/isamc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1995-1996, Index Data. + * See the file LICENSE for details. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: isamc.h,v $ + * Revision 1.1 1996-10-29 13:40:37 adam + * First work. + * + */ + +#ifndef ISAMC_H +#define ISAMC_H + +typedef struct ISAMC_s *ISAMC; +typedef int ISAMC_P; +typedef struct ISAMC_PP_s *ISAMC_PP; + +typedef struct ISAMC_filecat_s { + int bsize; /* block size */ + int ifill; /* initial fill */ + int mfill; /* minimum fill */ + int mblocks; /* maximum blocks */ +} *ISAMC_filecat; + +typedef struct ISAMC_M_s { + ISAMC_filecat filecat; + + int (*compare_item)(const void *a, const void *b); + +#define ISAMC_DECODE 0 +#define ISAMC_ENCODE 1 + void *(*code_start)(int mode); + void (*code_stop)(int mode, void *p); + void (*code_item)(int mode, void *p, char **dst, char **src); + + int debug; +} *ISAMC_M; + +typedef struct ISAMC_I_s { + int (*read_item)(void *clientData, char **dst, int *insertMode); + void *clientData; +} *ISAMC_I; + +ISAMC_M isc_getmethod (void); + +ISAMC isc_open (const char *name, int writeflag, ISAMC_M method); +int isc_close (ISAMC is); +ISAMC_P isc_merge (ISAMC is, ISAMC_P pos, ISAMC_I data); + +ISAMC_PP isc_pp_open (ISAMC is, ISAMC_P pos); +void isc_pp_close (ISAMC_PP pp); +int isc_read_item (ISAMC_PP pp, char **dst); +int isc_read_key (ISAMC_PP pp, void *buf); +int isc_numkeys (ISAMC_PP pp); + +#endif diff --git a/isamc/Makefile b/isamc/Makefile new file mode 100644 index 0000000..0c715f8 --- /dev/null +++ b/isamc/Makefile @@ -0,0 +1,52 @@ +# Copyright (C) 1996, Index Data I/S +# All rights reserved. +# Sebastian Hammer, Adam Dickmeiss +# $Id: Makefile,v 1.1 1996-10-29 13:40:46 adam Exp $ + +SHELL=/bin/sh +RANLIB=ranlib + +YAZLIB=../../yaz/lib/libyaz.a +YAZINC=-I../../yaz/include + +INCLUDE=-I../include $(YAZINC) +TPROG1=isamctst +DEFS=$(INCLUDE) +LIB=../lib/isamc.a +PO = isamc.o +CPP=$(CC) -E + +all: $(LIB) + +alll: $(LIB) + +$(TPROG1): $(TPROG1).o $(LIB) ../lib/bfile.a ../lib/zebrautl.a + $(CC) $(CFLAGS) -o $(TPROG1) $(TPROG1).o $(LIB) \ + ../lib/bfile.a ../lib/zebrautl.a $(YAZLIB) + +$(LIB): $(PO) + rm -f $(LIB) + ar qc $(LIB) $(PO) + $(RANLIB) $(LIB) + +.c.o: + $(CC) -c $(DEFS) $(CFLAGS) $< + +clean: + rm -f *.[oa] $(TPROG1) core mon.out gmon.out errlist + +depend: depend2 + +depend1: + sed '/^#Depend/q' Makefile.tmp + $(CPP) $(DEFS) -M *.c >>Makefile.tmp + mv -f Makefile.tmp Makefile + +depend2: + $(CPP) $(DEFS) -M *.c >.depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + +#Depend --- DOT NOT DELETE THIS LINE diff --git a/isamc/isamc-p.h b/isamc/isamc-p.h new file mode 100644 index 0000000..47015c0 --- /dev/null +++ b/isamc/isamc-p.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1995-1996, Index Data. + * See the file LICENSE for details. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: isamc-p.h,v $ + * Revision 1.1 1996-10-29 13:40:47 adam + * First work. + * + */ + +#include +#include + +typedef struct { + int lastblock; + int freelist; +} ISAMC_head; + +typedef struct ISAMC_file_s { + ISAMC_head head; + BFile bf; + int head_is_dirty; +} *ISAMC_file; + +struct ISAMC_s { + int no_files; + int max_cat; + char *r_buf; + ISAMC_M method; + ISAMC_file files; +}; + +struct ISAMC_PP_s { + char *buf; + int offset; + int size; + int cat; + int pos; + int next; + ISAMC is; + void *decodeClientData; +}; + +#define ISAMC_BLOCK_OFFSET (sizeof(int)+sizeof(int)) diff --git a/isamc/isamc.c b/isamc/isamc.c new file mode 100644 index 0000000..611f3fa --- /dev/null +++ b/isamc/isamc.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 1995-1996, Index Data. + * See the file LICENSE for details. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: isamc.c,v $ + * Revision 1.1 1996-10-29 13:40:48 adam + * First work. + * + */ + +#include +#include +#include +#include + +#include +#include "isamc-p.h" + +ISAMC_M isc_getmethod (void) +{ + static struct ISAMC_filecat_s def_cat[] = { + { 32, 28, 0, 20 }, + { 512, 490, 100, 20 }, + { 4096, 3950, 1000, 20 }, + {32768, 32000, 10000, 0 }, + { 0, 0, 0, 0 } + }; + ISAMC_M m = xmalloc (sizeof(*m)); + m->filecat = def_cat; + + m->code_start = NULL; + m->code_item = NULL; + m->code_stop = NULL; + + m->compare_item = NULL; + + m->debug = 0; + + return m; +} + + +ISAMC isc_open (const char *name, int writeflag, ISAMC_M method) +{ + ISAMC is; + ISAMC_filecat filecat; + int i; + int max_buf_size = 0; + + is = xmalloc (sizeof(*is)); + + is->method = xmalloc (sizeof(*is->method)); + memcpy (is->method, method, sizeof(*method)); + filecat = is->method->filecat; + assert (filecat); + + /* determine number of block categories */ + if (is->method->debug) + logf (LOG_LOG, "isc: bsize ifill mfill mblocks"); + for (i = 0; filecat[i].bsize; i++) + { + if (is->method->debug) + logf (LOG_LOG, "isc:%6d %6d %6d %6d", + filecat[i].bsize, filecat[i].ifill, + filecat[i].mfill, filecat[i].mblocks); + if (max_buf_size < filecat[i].mblocks * filecat[i].bsize) + max_buf_size = filecat[i].mblocks * filecat[i].bsize; + } + is->no_files = i; + is->max_cat = --i; + /* max_buf_size is the larget buffer to be used during merge */ + max_buf_size = (1 + max_buf_size / filecat[i].bsize) * filecat[i].bsize; + if (is->method->debug) + logf (LOG_LOG, "isc: max_buf_size %d", max_buf_size); + + assert (is->no_files > 0); + is->files = xmalloc (sizeof(*is->files)*i); + is->r_buf = xmalloc (max_buf_size+128); + for (i = 0; ino_files; i++) + { + char fname[512]; + + sprintf (fname, "%s%c", name, i+'A'); + is->files[i].bf = bf_open (fname, is->method->filecat[i].bsize, + writeflag); + is->files[i].head_is_dirty = 0; + if (!bf_read (is->files[i].bf, 0, 0, sizeof(ISAMC_head), + &is->files[i].head)) + { + is->files[i].head.lastblock = 1; + is->files[i].head.freelist = 0; + } + } + return is; +} + +int isc_close (ISAMC is) +{ + int i; + + for (i = 0; ino_files; i++) + if (is->files[i].bf) + { + if (is->files[i].head_is_dirty) + bf_write (is->files[i].bf, 0, 0, sizeof(ISAMC_head), + &is->files[i].head); + bf_close (is->files[i].bf); + } + xfree (is->files); + xfree (is->r_buf); + xfree (is); + return 0; +} + +void isc_catpos (ISAMC_P ipos, int *cat, int *pos) +{ + *pos = ipos >> 3; + *cat = ipos & 7; +} + +int isc_read_block (ISAMC is, int cat, int pos, char *dst) +{ + if (is->method->debug > 1) + logf (LOG_LOG, "isc: read_block %d %d", cat, pos); + return bf_read (is->files[cat].bf, pos, 0, 0, dst); +} + +int isc_write_block (ISAMC is, int cat, int pos, char *src) +{ + if (is->method->debug > 1) + logf (LOG_LOG, "isc: write_block %d %d", cat, pos); + return bf_write (is->files[cat].bf, pos, 0, 0, src); +} + +int isc_write_dblock (ISAMC is, int cat, int pos, char *src, + int nextpos, int offset) +{ + int xoffset = offset + 2*sizeof(int); + if (is->method->debug > 2) + logf (LOG_LOG, "isc: write_dblock. offset=%d nextpos=%d", + offset, nextpos); + memcpy (src - sizeof(int)*2, &nextpos, sizeof(int)); + memcpy (src - sizeof(int), &xoffset, sizeof(int)); + return isc_write_block (is, cat, pos, src - sizeof(int)*2); +} + +int isc_alloc_block (ISAMC is, int cat) +{ + int block; + char buf[sizeof(int)]; + + is->files[cat].head_is_dirty = 1; + if ((block = is->files[cat].head.freelist)) + { + bf_read (is->files[cat].bf, block, 0, sizeof(int), buf); + memcpy (&is->files[cat].head.freelist, buf, sizeof(int)); + } + else + block = (is->files[cat].head.lastblock)++; + if (is->method->debug > 2) + logf (LOG_LOG, "isc: alloc_block in cat %d -> %d", cat, block); + return block; +} + +void isc_release_block (ISAMC is, int cat, int pos) +{ + char buf[sizeof(int)]; + + is->files[cat].head_is_dirty = 1; + memcpy (buf, &is->files[cat].head.freelist, sizeof(int)); + is->files[cat].head.freelist = pos; + bf_write (is->files[cat].bf, pos, 0, sizeof(int), buf); +} + +static void isc_flush_blocks (ISAMC is, int *r_ptr, int r_ptri, char *r_buf, + int *nextpos, int *firstpos, int cat, int last) +{ + int i; + + for (i = 1; imethod->code_start)(ISAMC_ENCODE); + char *r_buf = is->r_buf + ISAMC_BLOCK_OFFSET; + + /* read first item from i */ + i_item_ptr = i_item; + i_more = (*data->read_item)(data->clientData, &i_item_ptr, &i_mode); + if (i_more) + r_ptr[r_ptri++] = 0; + while (i_more) + { + char *r_item = r_item_buf; + + memcpy (r_item, i_item, i_item_ptr - i_item); + + if (r_item) /* insert resulting item? */ + { + char *r_out_ptr = r_buf + r_offset; + int new_offset; + int border = r_ptr[r_ptri-1] + is->method->filecat[cat].ifill + -ISAMC_BLOCK_OFFSET; + + (*is->method->code_item)(ISAMC_ENCODE, r_clientData, + &r_out_ptr, &r_item); + new_offset = r_out_ptr - r_buf; + + if (border >= r_offset && border < new_offset) + { + /* Initial fill of current block category reached... + Save offset in r_ptr + */ + r_ptr[r_ptri++] = r_offset; + if (cat == is->max_cat) + { + /* We are dealing with block of max size. Block(s) + will be flushed. Note: the block(s) are surely not + the last one(s). + */ + if (is->method->debug > 1) + logf (LOG_LOG, "isc: flush %d sections", r_ptri-1); + isc_flush_blocks (is, r_ptr, r_ptri, r_buf, + &nextpos, &firstpos, cat, 0); + r_ptri = 0; + r_ptr[r_ptri++] = 0; + memcpy (r_buf, r_buf + r_offset, new_offset - r_offset); + new_offset = (new_offset - r_offset); + } + } + r_offset = new_offset; + if (cat < is->max_cat && + r_ptri>is->method->filecat[cat].mblocks) + { + /* Max number blocks in current category reached -> + must switch to next category (with larger block size) + */ + int j = 1; + cat++; + /* r_ptr[0] = r_ptr[0] = 0 true anyway.. */ + for (i = 2; i < r_ptri; i++) + { + border = is->method->filecat[cat].ifill - + ISAMC_BLOCK_OFFSET + r_ptr[j-1]; + if (r_ptr[i] > border && r_ptr[i-1] <= border) + r_ptr[j++] = r_ptr[i-1]; + } + r_ptri = j; + } + } + i_item_ptr = i_item; + i_more = (*data->read_item)(data->clientData, &i_item_ptr, &i_mode); + } + r_ptr[r_ptri++] = r_offset; + /* flush rest of block(s) in r_buf */ + if (is->method->debug > 1) + logf (LOG_LOG, "isc: flush rest, %d sections", r_ptri-1); + isc_flush_blocks (is, r_ptr, r_ptri, r_buf, &nextpos, &firstpos, cat, 1); + (*is->method->code_stop)(ISAMC_ENCODE, r_clientData); + return cat + firstpos * 8; +} + +ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) +{ + assert (ipos == 0); + return isc_merge_first (is, data); +} + + +#if 0 +ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data) +{ + ISAMC_PP pp; + char f_item[128], *f_item_ptr; + int f_more; + int cat = 0; + int nextpos; + + char i_item[128], *i_item_ptr; + int i_more, insertMode; + + char r_item_buf[128]; + int r_offset = ISAMC_BLOCK_OFFSET; + int r_dirty = 0; + char *r_ptr[100]; + int r_ptri = 0; + int r_start = 0; + void *r_clientData = (*is->method->code_start)(); + + /* rewind and read first item from file */ + pp = isc_position (is, ipos); + f_item_ptr = f_item; + f_more = isc_read_item (pp, &f_item_ptr); + cat = pp->cat; + + /* read first item from i */ + i_item_ptr = i_item; + i_more = (*data->read_item)(data->clientData, &i_item_ptr, &insertMode); + + while (f_more || i_more) + { + int cmp; + char *r_item = r_item_buf; + + if (!f_more) + cmp = -1; + else if (!i_more) + cmp = 1; + else + cmp = (*is->method->compare_item)(i_item, f_item); + if (cmp == 0) /* insert i=f */ + { + if (!insertMode) + { + r_item = NULL; + r_dirty = 1; + } + else + memcpy (r_item, f_item, f_item_ptr - f_item); + + /* move i */ + i_item_ptr = i_item; + i_more = (*data->read_item)(data->clientData, &i_item_ptr, + &insertMode); + /* move f */ + f_item_ptr = f_item; + f_more = isc_read_item (pp, &f_item_ptr); + } + else if (cmp > 0) /* insert f */ + { + memcpy (r_item, f_item, f_item_ptr - f_item); + /* move f */ + f_item_ptr = f_item; + f_more = isc_read_item (pp, &f_item_ptr); + } + else /* insert i */ + { + if (!insertMode) /* delete item which isn't there? */ + { + logf (LOG_FATAL, "Inconsistent register"); + abort (); + } + memcpy (r_item, i_item, i_item_ptr - i_item); + r_dirty = 1; + /* move i */ + i_item_ptr = i_item; + i_more = (*data->read_item)(data->clientData, &i_item_ptr, + &insertMode); + } + /* check for end of input block condition */ + + if (r_item) /* insert resulting item? */ + { + char *r_out_ptr = is->r_buf + r_offset; + int new_offset; + int border = is->method->filecat[cat].initsize - r_start; + + (*is->method->code_item)(r_clientData, &r_out_ptr, &r_item); + new_offset = r_out_ptr - is->r_buf; + + if (border >= r_offset && border < r_newoffset) + { + r_ptr[r_ptri++] = r_offset; + if (!is->method->filecat[cat].mblocks) + { + assert (r_ptri == 1); + /* dump block from 0 -> r_offset in max cat */ + r_ptri = 0; + r_offset = ISAMC_BLOCK_OFFSET; + } + } + r_offset = new_offset; + } + if (r_ptri && r_ptri == is->method->filecat[cat].mblocks) + { + int i, j = 0; + + /* dump previous blocks in chain */ + + /* recalc r_ptr's */ + cat++; + for (i = 1; i is->method->filecat[cat].ifill && + r_ptr[i-1] <= is->method->filecat[cat].ifill) + r_ptr[j++] = r_ptr[i-1]; + } + r_ptri = j; + } + } + (*is->method->code_stop)(r_clientData); + return ipos; +} +#endif + +void isc_pp_close (ISAMC_PP pp) +{ + ISAMC is = pp->is; + + (*is->method->code_stop)(ISAMC_DECODE, pp->decodeClientData); + xfree (pp->buf); + xfree (pp); +} + +ISAMC_PP isc_pp_open (ISAMC is, ISAMC_P ipos) +{ + ISAMC_PP pp = xmalloc (sizeof(*pp)); + char *src; + + isc_catpos (ipos, &pp->cat, &pp->next); + + src = pp->buf = xmalloc (is->method->filecat[pp->cat].bsize); + + pp->pos = 0; + pp->size = 0; + pp->offset = 0; + pp->is = is; + pp->decodeClientData = (*is->method->code_start)(ISAMC_DECODE); + return pp; +} + +/* returns 1 if item could be read; 0 otherwise */ +int isc_read_key (ISAMC_PP pp, void *buf) +{ + return isc_read_item (pp, (char **) &buf); +} + +/* returns 1 if item could be read; 0 otherwise */ +int isc_read_item (ISAMC_PP pp, char **dst) +{ + ISAMC is = pp->is; + char *src = pp->buf + pp->offset; + + if (pp->offset >= pp->size) + { + pp->pos = pp->next; + if (!pp->pos) + return 0; + src = pp->buf; + isc_read_block (is, pp->cat, pp->pos, src); + + memcpy (&pp->next, src, sizeof(pp->next)); + src += sizeof(pp->next); + memcpy (&pp->size, src, sizeof(pp->size)); + src += sizeof(pp->size); + /* assume block is non-empty */ + assert (pp->next != pp->pos); + } + (*is->method->code_item)(ISAMC_DECODE, pp->decodeClientData, dst, &src); + pp->offset = src - pp->buf; + return 1; +} + +int isc_read_islast (ISAMC_PP pp) +{ + return pp->offset >= pp->size; +} + +int isc_numkeys (ISAMC_PP pp) +{ + return 1; +} + -- 1.7.10.4