* Sebastian Hammer, Adam Dickmeiss
*
* $Log: isam.h,v $
- * Revision 1.4 1994-09-26 17:05:54 quinn
+ * Revision 1.5 1994-09-27 20:03:36 quinn
+ * Seems relatively bug-free.
+ *
+ * Revision 1.4 1994/09/26 17:05:54 quinn
* Trivial.
*
* Revision 1.3 1994/09/26 16:08:42 quinn
#include <bfile.h>
+#include "../isam/memory.h"
+#include "../isam/physical.h"
+
#define IS_MAX_BLOCKTYPES 4
#define IS_MAX_RECORD 512
#define IS_DEF_REPACK_PERCENT "30" /* how much relative change before repack */
typedef unsigned int SYSNO; /* should be somewhere else */
-typedef unsigned int ISAM_P;
/*
* Description of a blocktype (part of an isam file)
int max_keys_block0; /* max num of keys in first block */
int nice_keys_block; /* nice number of keys per block */
int max_keys; /* max number of keys per table */
- int freelist; /* fist free block */
+ int freelist; /* first free block */
int top; /* first unused block */
int index; /* placeholder. Always 0. */
char *dbuf; /* buffer for use in I/O operations */
int keysize; /* size of the keys (records) used */
int repack; /* how many percent to grow before repack */
int (*cmp)(const void *k1, const void *k2); /* compare function */
-} isam_struct, *ISAM;
+} isam_struct;
-struct is_mtable;
typedef struct ispt_struct
{
struct is_mtable *tab;
# Copyright (C) 1994, Index Data I/S
# All rights reserved.
# Sebastian Hammer, Adam Dickmeiss
-# $Id: Makefile,v 1.10 1994-09-27 16:31:40 adam Exp $
+# $Id: Makefile,v 1.11 1994-09-27 20:03:50 quinn Exp $
SHELL=/bin/sh
INCLUDE=-I../include
all: $(LIB)
+alll: $(LIB) isam-test issh
+
test: test.c $(LIB)
$(CC) -g -o test -I../include test.c \
../lib/isam.a ../lib/bfile.a ../lib/util.a
$(CC) -c $(DEFS) $(CFLAGS) $<
clean:
- rm -f *.[oa] $(TPROG) core mon.out gmon.out errlist isam-test issh
+ rm -f *.[oa] $(TPROG) core mon.out gmon.out errlist test isam-test issh
depend: depend2
* Sebastian Hammer, Adam Dickmeiss
*
* $Log: isam.c,v $
- * Revision 1.4 1994-09-26 17:11:29 quinn
+ * Revision 1.5 1994-09-27 20:03:50 quinn
+ * Seems relatively bug-free.
+ *
+ * Revision 1.4 1994/09/26 17:11:29 quinn
* Trivial
*
* Revision 1.3 1994/09/26 17:06:35 quinn
#include <common.h>
#include "isutil.h"
#include "rootblk.h"
-#include "memory.h"
-#include "physical.h"
#include "keyops.h"
static int splitargs(const char *s, char *bf[], int max)
is_mtable tab;
int res;
char keybuf[IS_MAX_RECORD];
- int oldnum, oldtype;
+ int oldnum, oldtype, i;
char operation, *record;
is_m_establish_tab(is, &tab, pos);
while (num)
{
operation = *(data)++;
- record = (char*)data;
+ record = (char*) data;
data += is_keysize(is);
num--;
- while (num && !memcmp(record, data, is_keysize(tab.is) + 1))
+ while (num && !memcmp(record - 1, data, is_keysize(tab.is) + 1))
{
data += 1 + is_keysize(is);
num--;
}
}
}
- while (tab.pos_type < tab.is->num_types - 1 && tab.num_records >
- tab.is->types[tab.pos_type].max_keys)
- tab.pos_type++;
+ i = tab.pos_type;
+ while (i < tab.is->num_types - 1 && tab.num_records >
+ tab.is->types[i].max_keys)
+ i++;
+ if (i != tab.pos_type)
+ {
+ is_p_unmap(&tab);
+ tab.pos_type = i;
+ }
if (!oldnum || tab.pos_type != oldtype || (abs(oldnum - tab.num_records) *
100) / oldnum > tab.is->repack)
is_p_remap(&tab);
else
is_p_align(&tab);
- is_p_sync(&tab);
- return is_address(tab.pos_type, tab.data->diskpos);
+ if (tab.data)
+ {
+ is_p_sync(&tab);
+ pos = is_address(tab.pos_type, tab.data->diskpos);
+ }
+ else
+ pos = 0;
+ is_m_release_tab(&tab);
+ return pos;
}
/*
#include <strings.h>
#include <assert.h>
-#include <common.h>
#include <isam.h>
static ISAM is = 0;
* Sebastian Hammer, Adam Dickmeiss
*
* $Log: memory.c,v $
- * Revision 1.3 1994-09-26 17:11:30 quinn
+ * Revision 1.4 1994-09-27 20:03:52 quinn
+ * Seems relatively bug-free.
+ *
+ * Revision 1.3 1994/09/26 17:11:30 quinn
* Trivial
*
* Revision 1.2 1994/09/26 17:06:35 quinn
#include <assert.h>
#include <util.h>
-#include "memory.h"
-#include "physical.h"
#include <isam.h>
int is_mbuf_size[3] = { 0, 1024, 4096 };
-/*
- * TODO: make internal memory-management scheme for these units.
- */
+static is_mblock *mblock_tmplist = 0, *mblock_freelist = 0;
+static is_mbuf *mbuf_freelist[3] = {0, 0, 0};
+
+#define MALLOC_CHUNK 20
is_mblock *xmalloc_mblock()
{
is_mblock *tmp;
+ int i;
- tmp = xmalloc(sizeof(is_mblock));
+ if (!mblock_freelist)
+ {
+ mblock_freelist = xmalloc(sizeof(is_mblock) * MALLOC_CHUNK);
+ for (i = 0; i < MALLOC_CHUNK - 1; i++)
+ mblock_freelist[i].next = &mblock_freelist[i+1];
+ mblock_freelist[i].next = 0;
+ }
+ tmp = mblock_freelist;
+ mblock_freelist = mblock_freelist->next;
tmp->next = 0;
+ tmp->state = IS_MBSTATE_UNREAD;
+ tmp->data = 0;
return tmp;
}
{
is_mbuf *tmp;
- tmp = xmalloc(sizeof(is_mbuf) + is_mbuf_size[type]);
- tmp->type = type;
+ if (mbuf_freelist[type])
+ {
+ tmp = mbuf_freelist[type];
+ mbuf_freelist[type] = tmp->next;
+ }
+ else
+ {
+ tmp = xmalloc(sizeof(is_mbuf) + is_mbuf_size[type]);
+ tmp->type = type;
+ }
tmp->refcount = type ? 1 : 0;
tmp->offset = tmp->num = tmp->cur_record = 0;
tmp->data = (char*) tmp + sizeof(is_mbuf);
return tmp;
}
-#if 0
+void xfree_mbuf(is_mbuf *p)
+{
+ p->next = mbuf_freelist[p->type];
+ mbuf_freelist[p->type] = p;
+}
+
+void xfree_mbufs(is_mbuf *l)
+{
+ is_mbuf *p;
+
+ while (l)
+ {
+ p = l->next;
+ xfree_mbuf(l);
+ l = p;
+ }
+}
+
void xfree_mblock(is_mblock *p)
{
- xfree(p);
+ xfree_mbufs(p->data);
+ p->next = mblock_freelist;
+ mblock_freelist = p;
}
-#endif
-#if 0
-void xfree_mbuf(is_mblock *p)
+void xrelease_mblock(is_mblock *p)
{
- xfree(p);
+ p->next = mblock_tmplist;
+ mblock_tmplist = p;
+}
+
+void xfree_mblocks(is_mblock *l)
+{
+ is_mblock *p;
+
+ while (l)
+ {
+ p = l->next;
+ xfree_mblock(l);
+ l = p;
+ }
}
-#endif
void is_m_establish_tab(ISAM is, is_mtable *tab, ISAM_P pos)
{
tab->is = is;
}
+void is_m_release_tab(is_mtable *tab)
+{
+ xfree_mblocks(tab->data);
+ xfree_mblocks(mblock_tmplist);
+ mblock_tmplist = 0;
+}
+
void is_m_rewind(is_mtable *tab)
{
tab->cur_mblock = tab->data;
int is_m_peek_record(is_mtable *tab, void *rec)
{
is_mbuf *mbuf;
+ is_mblock *mblock;
/* make sure block is all in memory */
if (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL)
if (read_current_full(tab, tab->cur_mblock) < 0)
return -1;
- mbuf = tab->cur_mblock->cur_mbuf;
+ mblock = tab->cur_mblock;
+ mbuf = mblock->cur_mbuf;
if (mbuf->cur_record >= mbuf->num) /* are we at end of mbuf? */
{
if (!mbuf->next) /* end of mblock */
{
- if (tab->cur_mblock->next)
+ if (mblock->next)
{
- tab->cur_mblock = tab->cur_mblock->next;
- if (tab->cur_mblock->next->state <= IS_MBSTATE_PARTIAL)
- if (read_current_full(tab, tab->cur_mblock->next) < 0)
+ mblock = mblock->next;
+ if (mblock->state <= IS_MBSTATE_PARTIAL)
+ if (read_current_full(tab, mblock) < 0)
return -1;
- mbuf = tab->cur_mblock->next->data;
+ mbuf = mblock->data;
}
else
return 0; /* EOTable */
* Sebastian Hammer, Adam Dickmeiss
*
* $Log: memory.h,v $
- * Revision 1.1 1994-09-26 17:12:32 quinn
+ * Revision 1.2 1994-09-27 20:03:52 quinn
+ * Seems relatively bug-free.
+ *
+ * Revision 1.1 1994/09/26 17:12:32 quinn
* Back again
*
* Revision 1.1 1994/09/26 16:07:57 quinn
#ifndef MEMORY_H
#define MEMORY_H
-#include <isam.h>
-
extern int is_mbuf_size[3];
+typedef unsigned int ISAM_P;
+
/*
* Memory buffer. Used to manage records (keys) in memory for
* reading and insertion/deletion.
struct is_mblock *next; /* next diskblock */
} is_mblock;
+typedef struct isam_struct *ISAM;
/*
* Descriptor for a specific table.
*/
is_mblock *xmalloc_mblock();
is_mbuf *xmalloc_mbuf(int type);
void xfree_mblock(is_mblock *p);
-void xfree_mbuf(is_mblock *p);
+void xfree_mblocks(is_mblock *l);
+void xfree_mbuf(is_mbuf *p);
+void xfree_mbufs(is_mbuf *l);
+void xrelease_mblock(is_mblock *p);
void is_m_establish_tab(ISAM is, is_mtable *tab, ISAM_P pos);
+void is_m_release_tab(is_mtable *tab);
void is_m_rewind(is_mtable *tab);
void is_m_replace_record(is_mtable *tab, const void *rec);
int is_m_write_record(is_mtable *tab, const void *rec);
* Sebastian Hammer, Adam Dickmeiss
*
* $Log: physical.c,v $
- * Revision 1.3 1994-09-26 17:11:31 quinn
+ * Revision 1.4 1994-09-27 20:03:53 quinn
+ * Seems relatively bug-free.
+ *
+ * Revision 1.3 1994/09/26 17:11:31 quinn
* Trivial
*
* Revision 1.2 1994/09/26 17:06:36 quinn
#include <assert.h>
#include <isam.h>
-#include "memory.h"
static int is_freestore_alloc(ISAM is, int type)
{
else
tmp = is->types[type].top++;
+ log(LOG_DEBUG, "Allocating block #%d", tmp);
return tmp;
}
{
int tmp;
+ log(LOG_DEBUG, "Releasing block #%d", block);
tmp = is->types[type].freelist;
is->types[type].freelist = block;
if (bf_write(is->types[type].bf, block, 0, sizeof(tmp), &tmp) < 0)
block->bread += toread * is_keysize(tab->is);
}
}
+ log(LOG_DEBUG, "R: Block #%d contains %d records.", block->diskpos, block->num_records);
return 0;
}
type = &tab->is->types[tab->pos_type];
for (p = tab->data; p; p = p->next)
{
+ int fummy;
+/*
+if (p->num_records == 0)
+ fummy = 1/0;
+*/
+ if (p->state < IS_MBSTATE_DIRTY)
+ continue;
/* make sure that blocks are allocated. */
if (p->diskpos < 0)
p->diskpos = is_freestore_alloc(tab->is, tab->pos_type);
else
p->nextpos = p->next->diskpos;
}
+ else
+ p->nextpos = 0;
sum = 0;
memcpy(type->dbuf, &p->num_records, sizeof(p->num_records));
sum += sizeof(p->num_records);
log(LOG_FATAL, "Failed to write block.");
exit(1);
}
+ log(LOG_DEBUG, "W: Block #%d contains %d records.", p->diskpos, p->num_records);
}
}
is_mbuf *p = 0, **pp = &p, *new;
int toget = *num;
+ if (!toget)
+ return 0;
while (*mb && toget >= (*mb)->num)
{
toget -= (*mb)->num;
*/
void is_p_align(is_mtable *tab)
{
- is_mblock *mblock, *new;
+ is_mblock *mblock, *new, *last = 0, *next;
is_mbuf *mbufs, *mbp;
int blocks, recsblock;
log(LOG_DEBUG, "Realigning table.");
- for (mblock = tab->data; mblock; mblock = mblock->next)
+ for (mblock = tab->data; mblock; mblock = next)
{
- if (mblock->state == IS_MBSTATE_DIRTY && mblock->num_records >
+ next = mblock->next;
+ if (mblock->state == IS_MBSTATE_DIRTY && mblock->num_records == 0)
+ {
+ if (last)
+ {
+ last->next = mblock->next;
+ last->state = IS_MBSTATE_DIRTY;
+ next = mblock->next;
+ }
+ else
+ {
+ tab->data = tab->data->next;
+ tab->data->state = IS_MBSTATE_DIRTY;
+ next = tab->data;
+ }
+ if (mblock->diskpos >= 0)
+ is_freestore_free(tab->is, tab->pos_type, mblock->diskpos);
+ xrelease_mblock(mblock);
+ }
+ else if (mblock->state == IS_MBSTATE_DIRTY && mblock->num_records >
(mblock == tab->data ?
tab->is->types[tab->pos_type].max_keys_block0 :
tab->is->types[tab->pos_type].max_keys_block))
recsblock = 1;
mbufs = mblock->data;
while ((mbp = mbuf_takehead(&mbufs, &recsblock,
- is_keysize(tab->is))))
+ is_keysize(tab->is))) && recsblock)
{
- new = xmalloc_mblock();
- new->diskpos = -1;
- new->state = IS_MBSTATE_DIRTY;
- new->next = mblock->next;
- mblock->next = new;
+ if (mbufs)
+ {
+ new = xmalloc_mblock();
+ new->diskpos = -1;
+ new->state = IS_MBSTATE_DIRTY;
+ new->next = mblock->next;
+ mblock->next = new;
+ }
mblock->data = mbp;
mblock->num_records = recsblock;
+ last = mblock;
mblock = mblock->next;
}
+ next = mblock;
}
+ else
+ last = mblock;
}
}
bufpp = &mbufs;
for (blockp = tab->data; blockp; blockp = blockp->next)
{
+ if (blockp->state < IS_MBSTATE_CLEAN && is_m_read_full(tab, blockp) < 0)
+ {
+ log(LOG_FATAL, "Read-full failed in remap.");
+ exit(1);
+ }
*bufpp = blockp->data;
while (*bufpp)
bufpp = &(*bufpp)->next;
blocks = tab->num_records / tab->is->types[tab->pos_type].nice_keys_block;
if (tab->num_records % tab->is->types[tab->pos_type].nice_keys_block)
blocks++;
- recsblock = tab->num_records / blocks;
- if (recsblock < 1)
- recsblock = 1;
+ if (blocks == 0)
+ blocks = 1;
+ recsblock = tab->num_records / blocks + 1;
+ if (recsblock > tab->is->types[tab->pos_type].nice_keys_block)
+ recsblock--;
blockpp = &tab->data;
- while ((mbp = mbuf_takehead(&mbufs, &recsblock, is_keysize(tab->is))))
+ while ((mbp = mbuf_takehead(&mbufs, &recsblock, is_keysize(tab->is))) &&
+ recsblock)
{
if (!*blockpp)
{
(*blockpp)->state = IS_MBSTATE_DIRTY;
blockpp = &(*blockpp)->next;
}
+ if (mbp)
+ xfree_mbufs(mbp);
+ if (*blockpp)
+ {
+ for (blockp = *blockpp; blockp; blockp = blockp->next)
+ if (blockp->diskpos >= 0)
+ is_freestore_free(tab->is, tab->pos_type, blockp->diskpos);
+ xfree_mblocks(*blockpp);
+ *blockpp = 0;
+ }
}