-/*
- * Copyright (C) 1994, Index Data I/S
- * All rights reserved.
- * Sebastian Hammer, Adam Dickmeiss
- *
- * $Log: memory.c,v $
- * Revision 1.3 1994-09-26 17:11:30 quinn
- * Trivial
- *
- * 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-#include <util.h>
-#include "memory.h"
-#include "physical.h"
+#include <zebrautl.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 = (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;
}
{
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);
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)
{
tab->data->data = 0;
tab->cur_mblock = tab->data;
tab->cur_mblock->cur_mbuf = 0;
+ tab->last_mbuf = 0;
}
else /* new block */
{
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;
*/
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 */
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--;
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++;
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--;
}
/*
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 */
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;
{
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;
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++;
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;
+}