⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory.c

📁 harvest是一个下载html网页得机器人
💻 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 + -