📄 memory.c
字号:
/* $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 ApsThis file is part of the Zebra server.Zebra is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.Zebra is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with Zebra; see the file LICENSE.zebra. If not, write to theFree Software Foundation, 59 Temple Place - Suite 330, Boston, MA02111-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 <zebrautl.h>#include <isam.h>int is_mbuf_size[3] = { 0, 1024, 4096 };static is_mblock *mblock_tmplist = 0, *mblock_freelist = 0;static is_mbuf *mbuf_freelist[3] = {0, 0, 0};#define MALLOC_CHUNK 20is_mblock *xmalloc_mblock(){ is_mblock *tmp; int i; 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 *xmalloc_mbuf(int type){ is_mbuf *tmp; 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); tmp->next = 0; return tmp;}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_mbufs(p->data); p->next = mblock_freelist; mblock_freelist = p;}void xrelease_mblock(is_mblock *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; }}void is_m_establish_tab(ISAM is, is_mtable *tab, ISAM_P pos){ tab->data = xmalloc_mblock(); if (pos > 0) { tab->pos_type = is_type(pos); tab->num_records = -1; tab->data->num_records = -1; tab->data->diskpos = is_block(pos); tab->data->state = IS_MBSTATE_UNREAD; tab->data->data = 0; tab->cur_mblock = tab->data; tab->cur_mblock->cur_mbuf = 0; tab->last_mbuf = 0; } else /* new block */ { tab->pos_type = 0; tab->num_records = 0; tab->data->num_records = 0; tab->data->diskpos = -1; tab->data->state = IS_MBSTATE_CLEAN; tab->data->data = xmalloc_mbuf(IS_MBUF_TYPE_LARGE); 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; if (tab->data) { tab->data->cur_mbuf = tab->data->data; if (tab->data->data) tab->data->data->cur_record = 0; }}static int read_current_full(is_mtable *tab, is_mblock *mblock){ if (is_p_read_full(tab, mblock) < 0) return -1; if (mblock->nextpos && !mblock->next) { mblock->next = xmalloc_mblock(); mblock->next->diskpos = mblock->nextpos; mblock->next->state = IS_MBSTATE_UNREAD; mblock->next->data = 0; } mblock->cur_mbuf = mblock->data; mblock->data->cur_record = 0; return 0;}int is_m_read_full(is_mtable *tab, is_mblock *mblock){ return read_current_full(tab, mblock);}/* * replace the record right behind the pointer. */void is_m_replace_record(is_mtable *tab, const void *rec){ is_mbuf *mbuf = tab->cur_mblock->cur_mbuf; /* we assume that block is already in memory and that we are in the * right mbuf, and that it has space for us. */ memcpy(mbuf->data + mbuf->offset + (mbuf->cur_record - 1) * is_keysize(tab->is), rec, is_keysize(tab->is)); tab->cur_mblock->state = IS_MBSTATE_DIRTY;}/* * Delete the record right behind the pointer. */void is_m_delete_record(is_mtable *tab){ 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 if (mbuf->cur_record == 1) /* beginning of mbuf */ { mbuf->num--; mbuf->offset +=is_keysize(tab->is); mbuf->cur_record = 0; } else /* middle of mbuf */ { /* 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++; 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; tab->cur_mblock->cur_mbuf = inew; } tab->num_records--; tab->cur_mblock->num_records--; tab->cur_mblock->state = tab->data->state = IS_MBSTATE_DIRTY;}int is_m_write_record(is_mtable *tab, const void *rec){ is_mbuf *mbuf, *oldnext, *dmbuf; /* 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; if (mbuf->cur_record >= mbuf->num) /* top of mbuf */ { /* mbuf is reference or full */ if (mbuf->refcount != 1 || mbuf->offset + (mbuf->num + 1) * is_keysize(tab->is) > is_mbuf_size[mbuf->type]) { oldnext = mbuf->next; mbuf->next = xmalloc_mbuf(IS_MBUF_TYPE_LARGE); mbuf->next->next = oldnext; mbuf = mbuf->next; tab->cur_mblock->cur_mbuf = mbuf; mbuf->cur_record = 0; } } else { oldnext = mbuf->next; mbuf->next = xmalloc_mbuf(IS_MBUF_TYPE_MEDIUM); mbuf->next->next = dmbuf = xmalloc_mbuf(IS_MBUF_TYPE_SMALL); dmbuf->data = mbuf->data; dmbuf->next = oldnext; dmbuf->offset = mbuf->offset + mbuf->cur_record * is_keysize(tab->is); dmbuf->num = mbuf->num - mbuf->cur_record; mbuf->num -= dmbuf->num; mbuf->refcount++; mbuf = tab->cur_mblock->cur_mbuf = mbuf->next; mbuf->cur_record = 0; } /* 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++; mbuf->cur_record++; tab->num_records++; tab->cur_mblock->num_records++; tab->cur_mblock->state = tab->data->state = IS_MBSTATE_DIRTY; return 0;}void is_m_unread_record(is_mtable *tab){ assert(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--;}/* * non-destructive read. */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; 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 (mblock->next) { mblock = mblock->next; if (mblock->state <= IS_MBSTATE_PARTIAL) if (read_current_full(tab, mblock) < 0) return -1; mbuf = mblock->data; } else return 0; /* EOTable */ } else mbuf = mbuf->next; mbuf->cur_record = 0; } memcpy(rec, mbuf->data + mbuf->offset + mbuf->cur_record * is_keysize(tab->is), is_keysize(tab->is)); return 1;}int is_m_read_record(is_mtable *tab, void *buf, int keep){ is_mbuf *mbuf; /* 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; if (mbuf->cur_record >= mbuf->num) /* are we at end of 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 (tab->cur_mblock->state <= IS_MBSTATE_PARTIAL) 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++; return 1;}/* * TODO: optimize this function by introducing a higher-level search. */int is_m_seek_record(is_mtable *tab, const void *rec){ char peek[IS_MAX_RECORD]; int rs; for (;;) { 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 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -