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

📄 hash.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 4 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2002 *	Sleepycat Software.  All rights reserved. *//* * Copyright (c) 1990, 1993, 1994 *	Margo Seltzer.  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.c,v 11.166 2002/08/06 06:11:25 bostic Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <stdlib.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/db_shash.h"#include "dbinc/btree.h"#include "dbinc/hash.h"#include "dbinc/lock.h"static int  __ham_bulk __P((DBC *, DBT *, u_int32_t));static int  __ham_c_close __P((DBC *, db_pgno_t, int *));static int  __ham_c_del __P((DBC *));static int  __ham_c_destroy __P((DBC *));static int  __ham_c_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));static int  __ham_c_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));static int  __ham_c_writelock __P((DBC *));static int  __ham_dup_return __P((DBC *, DBT *, u_int32_t));static int  __ham_expand_table __P((DBC *));static int  __ham_lookup __P((DBC *,		const DBT *, u_int32_t, db_lockmode_t, db_pgno_t *));static int  __ham_overwrite __P((DBC *, DBT *, u_int32_t));/* * __ham_quick_delete -- *	When performing a DB->del operation that does not involve secondary *	indices and is not removing an off-page duplicate tree, we can *	speed things up substantially by removing the entire duplicate *	set, if any is present, in one operation, rather than by conjuring *	up and deleting each of the items individually.  (All are stored *	in one big HKEYDATA structure.)  We don't bother to distinguish *	on-page duplicate sets from single, non-dup items;  they're deleted *	in exactly the same way. * *	This function is called by __db_delete when the appropriate *	conditions are met, and it performs the delete in the optimized way. * *	The cursor should be set to the first item in the duplicate *	set, or to the sole key/data pair when the key does not have a *	duplicate set, before the function is called. * * PUBLIC: int __ham_quick_delete __P((DBC *)); */int__ham_quick_delete(dbc)	DBC *dbc;{	int ret, t_ret;	if ((ret = __ham_get_meta(dbc)) != 0)		return (ret);	/* Assert that we're not using secondary indices. */	DB_ASSERT(!F_ISSET(dbc->dbp, DB_AM_SECONDARY));	/*	 * We should assert that we're not a primary either, but that	 * would require grabbing the dbp's mutex, so we don't bother.	 */	/* Assert that we're set, but not to an off-page duplicate. */	DB_ASSERT(IS_INITIALIZED(dbc));	DB_ASSERT(((HASH_CURSOR *)dbc->internal)->opd == NULL);	ret = __ham_del_pair(dbc, 1);	if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* ****************** CURSORS ********************************** *//* * __ham_c_init -- *	Initialize the hash-specific portion of a cursor. * * PUBLIC: int __ham_c_init __P((DBC *)); */int__ham_c_init(dbc)	DBC *dbc;{	DB_ENV *dbenv;	HASH_CURSOR *new_curs;	int ret;	dbenv = dbc->dbp->dbenv;	if ((ret = __os_calloc(dbenv,	    1, sizeof(struct cursor_t), &new_curs)) != 0)		return (ret);	if ((ret = __os_malloc(dbenv,	    dbc->dbp->pgsize, &new_curs->split_buf)) != 0) {		__os_free(dbenv, new_curs);		return (ret);	}	dbc->internal = (DBC_INTERNAL *) new_curs;	dbc->c_close = __db_c_close;	dbc->c_count = __db_c_count;	dbc->c_del = __db_c_del;	dbc->c_dup = __db_c_dup;	dbc->c_get = dbc->c_real_get = __db_c_get;	dbc->c_pget = __db_c_pget;	dbc->c_put = __db_c_put;	dbc->c_am_bulk = __ham_bulk;	dbc->c_am_close = __ham_c_close;	dbc->c_am_del = __ham_c_del;	dbc->c_am_destroy = __ham_c_destroy;	dbc->c_am_get = __ham_c_get;	dbc->c_am_put = __ham_c_put;	dbc->c_am_writelock = __ham_c_writelock;	__ham_item_init(dbc);	return (0);}/* * __ham_c_close -- *	Close down the cursor from a single use. */static int__ham_c_close(dbc, root_pgno, rmroot)	DBC *dbc;	db_pgno_t root_pgno;	int *rmroot;{	DB_MPOOLFILE *mpf;	HASH_CURSOR *hcp;	HKEYDATA *dp;	int doroot, gotmeta, ret, t_ret;	u_int32_t dirty;	COMPQUIET(rmroot, 0);	mpf = dbc->dbp->mpf;	dirty = 0;	doroot = gotmeta = ret = 0;	hcp = (HASH_CURSOR *) dbc->internal;	/* Check for off page dups. */	if (dbc->internal->opd != NULL) {		if ((ret = __ham_get_meta(dbc)) != 0)			goto done;		gotmeta = 1;		if ((ret = __ham_get_cpage(dbc, DB_LOCK_READ)) != 0)			goto out;		dp = (HKEYDATA *)H_PAIRDATA(dbc->dbp, hcp->page, hcp->indx);		/* If its not a dup we aborted before we changed it. */		if (HPAGE_PTYPE(dp) == H_OFFDUP)			memcpy(&root_pgno,			    HOFFPAGE_PGNO(dp), sizeof(db_pgno_t));		else			root_pgno = PGNO_INVALID;		if ((ret =		    hcp->opd->c_am_close(hcp->opd, root_pgno, &doroot)) != 0)			goto out;		if (doroot != 0) {			if ((ret = __ham_del_pair(dbc, 1)) != 0)				goto out;			dirty = DB_MPOOL_DIRTY;		}	}out:	if (hcp->page != NULL && (t_ret =	    mpf->put(mpf, hcp->page, dirty)) != 0 && ret == 0)		ret = t_ret;	if (gotmeta != 0 && (t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)		ret = t_ret;done:	__ham_item_init(dbc);	return (ret);}/* * __ham_c_destroy -- *	Cleanup the access method private part of a cursor. */static int__ham_c_destroy(dbc)	DBC *dbc;{	HASH_CURSOR *hcp;	hcp = (HASH_CURSOR *)dbc->internal;	if (hcp->split_buf != NULL)		__os_free(dbc->dbp->dbenv, hcp->split_buf);	__os_free(dbc->dbp->dbenv, hcp);	return (0);}/* * __ham_c_count -- *	Return a count of on-page duplicates. * * PUBLIC: int __ham_c_count __P((DBC *, db_recno_t *)); */int__ham_c_count(dbc, recnop)	DBC *dbc;	db_recno_t *recnop;{	DB *dbp;	DB_MPOOLFILE *mpf;	HASH_CURSOR *hcp;	db_indx_t len;	db_recno_t recno;	int ret, t_ret;	u_int8_t *p, *pend;	dbp = dbc->dbp;	mpf = dbp->mpf;	hcp = (HASH_CURSOR *)dbc->internal;	recno = 0;	if ((ret = __ham_get_cpage(dbc, DB_LOCK_READ)) != 0)		return (ret);	switch (HPAGE_PTYPE(H_PAIRDATA(dbp, hcp->page, hcp->indx))) {	case H_KEYDATA:	case H_OFFPAGE:		recno = 1;		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);		for (; p < pend; recno++) {			/* p may be odd, so copy rather than just dereffing */			memcpy(&len, p, sizeof(db_indx_t));			p += 2 * sizeof(db_indx_t) + len;		}		break;	default:		ret = __db_pgfmt(dbp->dbenv, hcp->pgno);		goto err;	}	*recnop = recno;err:	if ((t_ret = mpf->put(mpf, hcp->page, 0)) != 0 && ret == 0)		ret = t_ret;	hcp->page = NULL;	return (ret);}static int__ham_c_del(dbc)	DBC *dbc;{	DB *dbp;	DBT repldbt;	DB_MPOOLFILE *mpf;	HASH_CURSOR *hcp;	int ret, t_ret;	dbp = dbc->dbp;	mpf = dbp->mpf;	hcp = (HASH_CURSOR *)dbc->internal;	if (F_ISSET(hcp, H_DELETED))		return (DB_NOTFOUND);	if ((ret = __ham_get_meta(dbc)) != 0)		goto out;	if ((ret = __ham_get_cpage(dbc, DB_LOCK_WRITE)) != 0)		goto out;	/* Off-page duplicates. */	if (HPAGE_TYPE(dbp, hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP)		goto out;	if (F_ISSET(hcp, H_ISDUP)) { /* On-page duplicate. */		if (hcp->dup_off == 0 &&		    DUP_SIZE(hcp->dup_len) == LEN_HDATA(dbp, hcp->page,		    hcp->hdr->dbmeta.pagesize, hcp->indx))			ret = __ham_del_pair(dbc, 1);		else {			repldbt.flags = 0;			F_SET(&repldbt, DB_DBT_PARTIAL);			repldbt.doff = hcp->dup_off;			repldbt.dlen = DUP_SIZE(hcp->dup_len);			repldbt.size = 0;			repldbt.data = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page,			    hcp->indx));			if ((ret = __ham_replpair(dbc, &repldbt, 0)) == 0) {				hcp->dup_tlen -= DUP_SIZE(hcp->dup_len);				F_SET(hcp, H_DELETED);				ret = __ham_c_update(dbc,				    DUP_SIZE(hcp->dup_len), 0, 1);			}		}	} else /* Not a duplicate */		ret = __ham_del_pair(dbc, 1);out:	if (hcp->page != NULL) {		if ((t_ret = mpf->put(mpf,		    hcp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) && ret == 0)			ret = t_ret;		hcp->page = NULL;	}	if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* * __ham_c_dup -- *	Duplicate a hash cursor, such that the new one holds appropriate *	locks for the position of the original. * * PUBLIC: int __ham_c_dup __P((DBC *, DBC *)); */int__ham_c_dup(orig_dbc, new_dbc)	DBC *orig_dbc, *new_dbc;{	HASH_CURSOR *orig, *new;	orig = (HASH_CURSOR *)orig_dbc->internal;	new = (HASH_CURSOR *)new_dbc->internal;	new->bucket = orig->bucket;	new->lbucket = orig->lbucket;	new->dup_off = orig->dup_off;	new->dup_len = orig->dup_len;	new->dup_tlen = orig->dup_tlen;	if (F_ISSET(orig, H_DELETED))		F_SET(new, H_DELETED);	if (F_ISSET(orig, H_ISDUP))		F_SET(new, H_ISDUP);	/*	 * If the old cursor held a lock and we're not in transactions, get one	 * for the new one.   The reason that we don't need a new lock if we're	 * in a transaction is because we already hold a lock and will continue	 * to do so until commit, so there is no point in reaquiring it. We	 * don't know if the old lock was a read or write lock, but it doesn't	 * matter. We'll get a read lock.  We know that this locker already	 * holds a lock of the correct type, so if we need a write lock and	 * request it, we know that we'll get it.	 */	if (!LOCK_ISSET(orig->lock) || orig_dbc->txn != NULL)		return (0);	return (__ham_lock_bucket(new_dbc, DB_LOCK_READ));}static int__ham_c_get(dbc, key, data, flags, pgnop)	DBC *dbc;	DBT *key;	DBT *data;	u_int32_t flags;	db_pgno_t *pgnop;{	DB *dbp;	DB_MPOOLFILE *mpf;	HASH_CURSOR *hcp;	db_lockmode_t lock_type;	int get_key, ret, t_ret;	hcp = (HASH_CURSOR *)dbc->internal;	dbp = dbc->dbp;	mpf = dbp->mpf;	/* Clear OR'd in additional bits so we can check for flag equality. */	if (F_ISSET(dbc, DBC_RMW))		lock_type = DB_LOCK_WRITE;	else		lock_type = DB_LOCK_READ;	if ((ret = __ham_get_meta(dbc)) != 0)		return (ret);	hcp->seek_size = 0;	ret = 0;	get_key = 1;	switch (flags) {	case DB_PREV_NODUP:		F_SET(hcp, H_NEXT_NODUP);		/* FALLTHROUGH */	case DB_PREV:		if (IS_INITIALIZED(dbc)) {			ret = __ham_item_prev(dbc, lock_type, pgnop);			break;		}		/* FALLTHROUGH */	case DB_LAST:		ret = __ham_item_last(dbc, lock_type, pgnop);		break;	case DB_NEXT_NODUP:		F_SET(hcp, H_NEXT_NODUP);		/* FALLTHROUGH */	case DB_NEXT:		if (IS_INITIALIZED(dbc)) {			ret = __ham_item_next(dbc, lock_type, pgnop);			break;		}		/* FALLTHROUGH */	case DB_FIRST:		ret = __ham_item_first(dbc, lock_type, pgnop);		break;	case DB_NEXT_DUP:		/* cgetchk has already determined that the cursor is set. */		F_SET(hcp, H_DUPONLY);		ret = __ham_item_next(dbc, lock_type, pgnop);		break;	case DB_SET:	case DB_SET_RANGE:	case DB_GET_BOTH:	case DB_GET_BOTH_RANGE:		ret = __ham_lookup(dbc, key, 0, lock_type, pgnop);		get_key = 0;		break;	case DB_GET_BOTHC:		F_SET(hcp, H_DUPONLY);		ret = __ham_item_next(dbc, lock_type, pgnop);		get_key = 0;		break;	case DB_CURRENT:		/* cgetchk has already determined that the cursor is set. */		if (F_ISSET(hcp, H_DELETED)) {			ret = DB_KEYEMPTY;			goto err;		}		ret = __ham_item(dbc, lock_type, pgnop);		break;	}	/*	 * Must always enter this loop to do error handling and	 * check for big key/data pair.	 */	for (;;) {		if (ret != 0 && ret != DB_NOTFOUND)			goto err;		else if (F_ISSET(hcp, H_OK)) {			if (*pgnop == PGNO_INVALID)				ret = __ham_dup_return(dbc, data, flags);			break;		} else if (!F_ISSET(hcp, H_NOMORE)) {			__db_err(dbp->dbenv,			    "H_NOMORE returned to __ham_c_get");			ret = EINVAL;			break;		}		/*		 * Ran out of entries in a bucket; change buckets.		 */		switch (flags) {			case DB_LAST:			case DB_PREV:

⌨️ 快捷键说明

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