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

📄 hash_dup.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2002 *	Sleepycat Software.  All rights reserved. *//* * Copyright (c) 1990, 1993, 1994 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Margo Seltzer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: hash_dup.c,v 11.76 2002/08/06 05:34:40 bostic Exp $";#endif /* not lint *//* * PACKAGE:  hashing * * DESCRIPTION: *	Manipulation of duplicates for the hash package. */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/hash.h"#include "dbinc/btree.h"static int __ham_c_chgpg __P((DBC *,    db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));static int __ham_check_move __P((DBC *, u_int32_t));static int __ham_dcursor __P((DBC *, db_pgno_t, u_int32_t));static int __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t));/* * Called from hash_access to add a duplicate key. nval is the new * value that we want to add.  The flags correspond to the flag values * to cursor_put indicating where to add the new element. * There are 4 cases. * Case 1: The existing duplicate set already resides on a separate page. *	   We return and let the common code handle this. * Case 2: The element is small enough to just be added to the existing set. * Case 3: The element is large enough to be a big item, so we're going to *	   have to push the set onto a new page. * Case 4: The element is large enough to push the duplicate set onto a *	   separate page. * * PUBLIC: int __ham_add_dup __P((DBC *, DBT *, u_int32_t, db_pgno_t *)); */int__ham_add_dup(dbc, nval, flags, pgnop)	DBC *dbc;	DBT *nval;	u_int32_t flags;	db_pgno_t *pgnop;{	DB *dbp;	DBT pval, tmp_val;	DB_MPOOLFILE *mpf;	HASH_CURSOR *hcp;	u_int32_t add_bytes, new_size;	int cmp, ret;	u_int8_t *hk;	dbp = dbc->dbp;	mpf = dbp->mpf;	hcp = (HASH_CURSOR *)dbc->internal;	DB_ASSERT(flags != DB_CURRENT);	add_bytes = nval->size +	    (F_ISSET(nval, DB_DBT_PARTIAL) ? nval->doff : 0);	add_bytes = DUP_SIZE(add_bytes);	if ((ret = __ham_check_move(dbc, add_bytes)) != 0)		return (ret);	/*	 * Check if resulting duplicate set is going to need to go	 * onto a separate duplicate page.  If so, convert the	 * duplicate set and add the new one.  After conversion,	 * hcp->dndx is the first free ndx or the index of the	 * current pointer into the duplicate set.	 */	hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);	/* Add the len bytes to the current singleton. */	if (HPAGE_PTYPE(hk) != H_DUPLICATE)		add_bytes += DUP_SIZE(0);	new_size =	    LEN_HKEYDATA(dbp, hcp->page, dbp->pgsize, H_DATAINDEX(hcp->indx)) +	    add_bytes;	/*	 * We convert to off-page duplicates if the item is a big item,	 * the addition of the new item will make the set large, or	 * if there isn't enough room on this page to add the next item.	 */	if (HPAGE_PTYPE(hk) != H_OFFDUP &&	    (HPAGE_PTYPE(hk) == H_OFFPAGE || ISBIG(hcp, new_size) ||	    add_bytes > P_FREESPACE(dbp, hcp->page))) {		if ((ret = __ham_dup_convert(dbc)) != 0)			return (ret);		return (hcp->opd->c_am_put(hcp->opd,		    NULL, nval, flags, NULL));	}	/* There are two separate cases here: on page and off page. */	if (HPAGE_PTYPE(hk) != H_OFFDUP) {		if (HPAGE_PTYPE(hk) != H_DUPLICATE) {			pval.flags = 0;			pval.data = HKEYDATA_DATA(hk);			pval.size = LEN_HDATA(dbp, hcp->page, dbp->pgsize,			    hcp->indx);			if ((ret = __ham_make_dup(dbp->dbenv,			    &pval, &tmp_val, &dbc->my_rdata.data,			    &dbc->my_rdata.ulen)) != 0 || (ret =			    __ham_replpair(dbc, &tmp_val, 1)) != 0)				return (ret);			hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);			HPAGE_PTYPE(hk) = H_DUPLICATE;			/*			 * Update the cursor position since we now are in			 * duplicates.			 */			F_SET(hcp, H_ISDUP);			hcp->dup_off = 0;			hcp->dup_len = pval.size;			hcp->dup_tlen = DUP_SIZE(hcp->dup_len);		}		/* Now make the new entry a duplicate. */		if ((ret = __ham_make_dup(dbp->dbenv, nval,		    &tmp_val, &dbc->my_rdata.data, &dbc->my_rdata.ulen)) != 0)			return (ret);		tmp_val.dlen = 0;		switch (flags) {			/* On page. */		case DB_KEYFIRST:		case DB_KEYLAST:		case DB_NODUPDATA:			if (dbp->dup_compare != NULL) {				__ham_dsearch(dbc,				    nval, &tmp_val.doff, &cmp, flags);				/* dup dups are not supported w/ sorted dups */				if (cmp == 0)					return (__db_duperr(dbp, flags));			} else {				hcp->dup_tlen = LEN_HDATA(dbp, hcp->page,				    dbp->pgsize, hcp->indx);				hcp->dup_len = nval->size;				F_SET(hcp, H_ISDUP);				if (flags == DB_KEYFIRST)					hcp->dup_off = tmp_val.doff = 0;				else					hcp->dup_off =					    tmp_val.doff = hcp->dup_tlen;			}			break;		case DB_BEFORE:			tmp_val.doff = hcp->dup_off;			break;		case DB_AFTER:			tmp_val.doff = hcp->dup_off + DUP_SIZE(hcp->dup_len);			break;		}		/* Add the duplicate. */		ret = __ham_replpair(dbc, &tmp_val, 0);		if (ret == 0)			ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);		if (ret != 0)			return (ret);		/* Now, update the cursor if necessary. */		switch (flags) {		case DB_AFTER:			hcp->dup_off += DUP_SIZE(hcp->dup_len);			hcp->dup_len = nval->size;			hcp->dup_tlen += (db_indx_t)DUP_SIZE(nval->size);			break;		case DB_KEYFIRST:		case DB_KEYLAST:		case DB_BEFORE:			hcp->dup_tlen += (db_indx_t)DUP_SIZE(nval->size);			hcp->dup_len = nval->size;			break;		}		ret = __ham_c_update(dbc, tmp_val.size, 1, 1);		return (ret);	}	/*	 * If we get here, then we're on duplicate pages; set pgnop and	 * return so the common code can handle it.	 */	memcpy(pgnop, HOFFDUP_PGNO(H_PAIRDATA(dbp, hcp->page, hcp->indx)),	    sizeof(db_pgno_t));	return (ret);}/* * Convert an on-page set of duplicates to an offpage set of duplicates. * * PUBLIC: int __ham_dup_convert __P((DBC *)); */int__ham_dup_convert(dbc)	DBC *dbc;{	BOVERFLOW bo;	DB *dbp;	DBC **hcs;	DBT dbt;	DB_LSN lsn;	DB_MPOOLFILE *mpf;	HASH_CURSOR *hcp;	HOFFPAGE ho;	PAGE *dp;	db_indx_t i, len, off;	int c, ret, t_ret;	u_int8_t *p, *pend;	dbp = dbc->dbp;	mpf = dbp->mpf;	hcp = (HASH_CURSOR *)dbc->internal;	/*	 * Create a new page for the duplicates.	 */	if ((ret = __db_new(dbc,	    dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &dp)) != 0)		return (ret);	P_INIT(dp, dbp->pgsize,	    dp->pgno, PGNO_INVALID, PGNO_INVALID, LEAFLEVEL, TYPE(dp));	/*	 * Get the list of cursors that may need to be updated.	 */	if ((ret = __ham_get_clist(dbp,	    PGNO(hcp->page), (u_int32_t)hcp->indx, &hcs)) != 0)		goto err;	/*	 * Now put the duplicates onto the new page.	 */	dbt.flags = 0;	switch (HPAGE_PTYPE(H_PAIRDATA(dbp, hcp->page, hcp->indx))) {	case H_KEYDATA:		/* Simple case, one key on page; move it to dup page. */		dbt.size = LEN_HDATA(dbp, hcp->page, dbp->pgsize, hcp->indx);		dbt.data = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));		ret = __db_pitem(dbc,		    dp, 0, BKEYDATA_SIZE(dbt.size), NULL, &dbt);		goto finish;	case H_OFFPAGE:		/* Simple case, one key on page; move it to dup page. */		memcpy(&ho, P_ENTRY(dbp, hcp->page, H_DATAINDEX(hcp->indx)),		    HOFFPAGE_SIZE);		UMRW_SET(bo.unused1);		B_TSET(bo.type, ho.type, 0);		UMRW_SET(bo.unused2);		bo.pgno = ho.pgno;		bo.tlen = ho.tlen;		dbt.size = BOVERFLOW_SIZE;		dbt.data = &bo;		ret = __db_pitem(dbc, dp, 0, dbt.size, &dbt, NULL);finish:		if (ret == 0) {			if ((ret = mpf->set(mpf, dp, DB_MPOOL_DIRTY)) != 0)				break;			/* Update any other cursors. */			if (hcs != NULL && DBC_LOGGING(dbc) &&			    IS_SUBTRANSACTION(dbc->txn)) {				if ((ret = __ham_chgpg_log(dbp, dbc->txn,				    &lsn, 0, DB_HAM_DUP, PGNO(hcp->page),				    PGNO(dp), hcp->indx, 0)) != 0)					break;			}			for (c = 0; hcs != NULL && hcs[c] != NULL; c++)				if ((ret = __ham_dcursor(hcs[c],				    PGNO(dp), 0)) != 0)					break;		}		break;	case H_DUPLICATE:		p = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));		pend = p +		    LEN_HDATA(dbp, hcp->page, dbp->pgsize, hcp->indx);		/*		 * We need to maintain the duplicate cursor position.		 * Keep track of where we are in the duplicate set via		 * the offset, and when it matches the one in the cursor,		 * set the off-page duplicate cursor index to the current		 * index.		 */		for (off = 0, i = 0; p < pend; i++) {			memcpy(&len, p, sizeof(db_indx_t));			dbt.size = len;			p += sizeof(db_indx_t);			dbt.data = p;			p += len + sizeof(db_indx_t);			if ((ret = __db_pitem(dbc, dp,			    i, BKEYDATA_SIZE(dbt.size), NULL, &dbt)) != 0)				break;			/* Update any other cursors */			if (hcs != NULL && DBC_LOGGING(dbc) &&			    IS_SUBTRANSACTION(dbc->txn)) {				if ((ret = __ham_chgpg_log(dbp, dbc->txn,				    &lsn, 0, DB_HAM_DUP, PGNO(hcp->page),				    PGNO(dp), hcp->indx, i)) != 0)					break;			}			for (c = 0; hcs != NULL && hcs[c] != NULL; c++)				if (((HASH_CURSOR *)(hcs[c]->internal))->dup_off				    == off && (ret = __ham_dcursor(hcs[c],				    PGNO(dp), i)) != 0)					goto err;			off += len + 2 * sizeof(db_indx_t);		}		break;	default:		ret = __db_pgfmt(dbp->dbenv, (u_long)hcp->pgno);		break;	}	/*	 * Now attach this to the source page in place of the old duplicate	 * item.	 */	if (ret == 0)		ret = __ham_move_offpage(dbc, hcp->page,		    (u_int32_t)H_DATAINDEX(hcp->indx), PGNO(dp));err:	if (ret == 0)		ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);	if ((t_ret =	    mpf->put(mpf, dp, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)		ret = t_ret;	if (ret == 0)		hcp->dup_tlen = hcp->dup_off = hcp->dup_len = 0;	if (hcs != NULL)		__os_free(dbp->dbenv, hcs);	return (ret);}/* * __ham_make_dup * * Take a regular dbt and make it into a duplicate item with all the partial * information set appropriately. If the incoming dbt is a partial, assume * we are creating a new entry and make sure that we do any initial padding. * * PUBLIC: int __ham_make_dup __P((DB_ENV *, * PUBLIC:     const DBT *, DBT *d, void **, u_int32_t *)); */int__ham_make_dup(dbenv, notdup, duplicate, bufp, sizep)	DB_ENV *dbenv;	const DBT *notdup;	DBT *duplicate;	void **bufp;	u_int32_t *sizep;{	db_indx_t tsize, item_size;	int ret;	u_int8_t *p;	item_size = (db_indx_t)notdup->size;	if (F_ISSET(notdup, DB_DBT_PARTIAL))		item_size += notdup->doff;	tsize = DUP_SIZE(item_size);	if ((ret = __ham_init_dbt(dbenv, duplicate, tsize, bufp, sizep)) != 0)		return (ret);	duplicate->dlen = 0;	duplicate->flags = notdup->flags;	F_SET(duplicate, DB_DBT_PARTIAL);	p = duplicate->data;	memcpy(p, &item_size, sizeof(db_indx_t));	p += sizeof(db_indx_t);	if (F_ISSET(notdup, DB_DBT_PARTIAL)) {		memset(p, 0, notdup->doff);		p += notdup->doff;	}	memcpy(p, notdup->data, notdup->size);	p += notdup->size;	memcpy(p, &item_size, sizeof(db_indx_t));	duplicate->doff = 0;	duplicate->dlen = notdup->size;	return (0);}/* * __ham_check_move -- * * Check if we can do whatever we need to on this page.  If not, * then we'll have to move the current element to a new page. */static int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -