X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=isam%2Fmemory.c;h=800d74ed490ca496ea844f5e43d0bb729bc23d3c;hb=bad06dda453543b8dd716ee54e9b7cb2b015b6e5;hp=ba39802e9068751e6e39a7f9b81f89f6261d3f7f;hpb=8fa8b7c5d10dd87654e5c219cceebe1a9664544a;p=idzebra-moved-to-github.git diff --git a/isam/memory.c b/isam/memory.c index ba39802..800d74e 100644 --- a/isam/memory.c +++ b/isam/memory.c @@ -1,40 +1,64 @@ -/* - * Copyright (C) 1994, Index Data I/S - * All rights reserved. - * Sebastian Hammer, Adam Dickmeiss - * - * $Log: memory.c,v $ - * Revision 1.2 1994-09-26 17:06:35 quinn - * Back again... - * - * Revision 1.1 1994/09/26 16:07:56 quinn - * Most of the functionality in place. - * - */ +/* $Id: memory.c,v 1.18 2002-08-02 19:26:56 adam Exp $ + Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002 + Index Data Aps + +This file is part of the Zebra server. + +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 +Software Foundation; either version 2, or (at your option) any later +version. + +Zebra is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Zebra; see the file LICENSE.zebra. If not, write to the +Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. +*/ + + /* * This module accesses and rearranges the records of the tables. */ #include +#include +#include +#include -#include -#include -#include "physical.h" +#include #include 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 = (is_mblock *) + 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; } @@ -42,8 +66,16 @@ is_mbuf *xmalloc_mbuf(int type) { 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 = (is_mbuf*) 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); @@ -51,19 +83,48 @@ is_mbuf *xmalloc_mbuf(int type) 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; +} + +void xrelease_mblock(is_mblock *p) +{ + p->next = mblock_tmplist; + mblock_tmplist = p; } -#endif -#if 0 -void xfree_mbuf(is_mblock *p) +void xfree_mblocks(is_mblock *l) { - xfree(p); + 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) { @@ -78,6 +139,7 @@ void is_m_establish_tab(ISAM is, is_mtable *tab, ISAM_P pos) tab->data->data = 0; tab->cur_mblock = tab->data; tab->cur_mblock->cur_mbuf = 0; + tab->last_mbuf = 0; } else /* new block */ { @@ -90,10 +152,18 @@ void is_m_establish_tab(ISAM is, is_mtable *tab, ISAM_P pos) tab->cur_mblock = tab->data; tab->cur_mblock->cur_mbuf = tab->data->data; tab->cur_mblock->cur_mbuf->cur_record = 0; + tab->last_mbuf = 0; } 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; @@ -145,7 +215,7 @@ void is_m_replace_record(is_mtable *tab, const void *rec) */ void is_m_delete_record(is_mtable *tab) { - is_mbuf *mbuf, *new; + is_mbuf *mbuf, *inew; mbuf = tab->cur_mblock->cur_mbuf; if (mbuf->cur_record >= mbuf->num) /* top of mbuf */ @@ -153,18 +223,28 @@ void is_m_delete_record(is_mtable *tab) mbuf->num--; mbuf->cur_record--; } - else /* middle of a block */ + else if (mbuf->cur_record == 1) /* beginning of mbuf */ + { + mbuf->num--; + mbuf->offset +=is_keysize(tab->is); + mbuf->cur_record = 0; + } + else /* middle of mbuf */ { - new = xmalloc_mbuf(IS_MBUF_TYPE_SMALL); - new->next = mbuf->next; - mbuf->next = new; - new->data = mbuf->data; + /* insert block after current one */ + inew = xmalloc_mbuf(IS_MBUF_TYPE_SMALL); + inew->next = mbuf->next; + mbuf->next = inew; + + /* virtually transfer everything after current record to new one. */ + inew->data = mbuf->data; mbuf->refcount++; - new->offset = mbuf->offset + mbuf->cur_record * is_keysize(tab->is); - new->num = mbuf->num - mbuf->cur_record; + inew->offset = mbuf->offset + mbuf->cur_record * is_keysize(tab->is); + inew->num = mbuf->num - mbuf->cur_record; + + /* old buf now only contains stuff before current record */ mbuf->num = mbuf->cur_record -1; - mbuf = mbuf->next; - mbuf->cur_record = 0; + tab->cur_mblock->cur_mbuf = inew; } tab->num_records--; tab->cur_mblock->num_records--; @@ -208,7 +288,9 @@ int is_m_write_record(is_mtable *tab, const void *rec) mbuf = tab->cur_mblock->cur_mbuf = mbuf->next; mbuf->cur_record = 0; } - log(LOG_DEBUG, "is_m_write_rec(rec == %d)", mbuf->cur_record); + /* + logf (LOG_DEBUG, "is_m_write_rec(rec == %d)", mbuf->cur_record); + */ memcpy(mbuf->data + mbuf->offset + mbuf->cur_record * is_keysize(tab->is), rec, is_keysize(tab->is)); mbuf->num++; @@ -222,7 +304,10 @@ int is_m_write_record(is_mtable *tab, const void *rec) void is_m_unread_record(is_mtable *tab) { assert(tab->cur_mblock->cur_mbuf->cur_record); - tab->cur_mblock->cur_mbuf->cur_record--; + if (tab->last_mbuf) + tab->cur_mblock->cur_mbuf = tab->last_mbuf; + else + tab->cur_mblock->cur_mbuf->cur_record--; } /* @@ -231,23 +316,25 @@ void is_m_unread_record(is_mtable *tab) 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 */ @@ -261,7 +348,7 @@ int is_m_peek_record(is_mtable *tab, void *rec) return 1; } -int is_m_read_record(is_mtable *tab, void *buf) +int is_m_read_record(is_mtable *tab, void *buf, int keep) { is_mbuf *mbuf; @@ -274,6 +361,13 @@ int is_m_read_record(is_mtable *tab, void *buf) { if (!mbuf->next) /* end of mblock */ { + if (!keep && tab->cur_mblock->state == IS_MBSTATE_CLEAN && + tab->cur_mblock->diskpos > 0) + { + xfree_mbufs(tab->cur_mblock->data); + tab->cur_mblock->data = 0; + tab->cur_mblock->state = IS_MBSTATE_UNREAD; + } if (tab->cur_mblock->next) { tab->cur_mblock = tab->cur_mblock->next; @@ -281,14 +375,20 @@ int is_m_read_record(is_mtable *tab, void *buf) if (read_current_full(tab, tab->cur_mblock) < 0) return -1; tab->cur_mblock->cur_mbuf = mbuf = tab->cur_mblock->data; + tab->last_mbuf = 0; } else return 0; /* EOTable */ } else + { + tab->last_mbuf = mbuf; tab->cur_mblock->cur_mbuf = mbuf = mbuf->next; + } mbuf->cur_record = 0; } + else + tab->last_mbuf = 0; memcpy(buf, mbuf->data + mbuf->offset + mbuf->cur_record * is_keysize(tab->is), is_keysize(tab->is)); mbuf->cur_record++; @@ -305,14 +405,25 @@ int is_m_seek_record(is_mtable *tab, const void *rec) for (;;) { - if (is_m_read_record(tab, &peek) <= 0) + if (is_m_read_record(tab, &peek, 1) <= 0) return 1; if ((rs = (*tab->is->cmp)(peek, rec)) > 0) { is_m_unread_record(tab); - return 1; + return rs; } else if (rs == 0) return 0; } } + +int is_m_num_records(is_mtable *tab) +{ + if (tab->data->state < IS_MBSTATE_PARTIAL) + if (read_current_full(tab, tab->data) < 0) + { + logf (LOG_FATAL, "read full failed"); + exit(1); + } + return tab->num_records; +}