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

📄 bt_put.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, 1995, 1996 *	Keith Bostic.  All rights reserved. *//* * Copyright (c) 1990, 1993, 1994, 1995 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Olson. * * 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: bt_put.c,v 11.69 2002/08/06 06:11:12 bostic Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/btree.h"static int __bam_build	       __P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t));static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t));static int __bam_ovput	       __P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *));static u_int32_t	   __bam_partsize __P((DB *, u_int32_t, DBT *, PAGE *, u_int32_t));/* * __bam_iitem -- *	Insert an item into the tree. * * PUBLIC: int __bam_iitem __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t)); */int__bam_iitem(dbc, key, data, op, flags)	DBC *dbc;	DBT *key, *data;	u_int32_t op, flags;{	BKEYDATA *bk, bk_tmp;	BTREE *t;	BTREE_CURSOR *cp;	DB *dbp;	DBT bk_hdr, tdbt;	DB_MPOOLFILE *mpf;	PAGE *h;	db_indx_t indx;	u_int32_t data_size, have_bytes, need_bytes, needed;	int cmp, bigkey, bigdata, dupadjust, padrec, replace, ret, was_deleted;	COMPQUIET(bk, NULL);	dbp = dbc->dbp;	mpf = dbp->mpf;	cp = (BTREE_CURSOR *)dbc->internal;	t = dbp->bt_internal;	h = cp->page;	indx = cp->indx;	dupadjust = replace = was_deleted = 0;	/*	 * Fixed-length records with partial puts: it's an error to specify	 * anything other simple overwrite.	 */	if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&	    F_ISSET(data, DB_DBT_PARTIAL) && data->dlen != data->size) {		data_size = data->size;		goto len_err;	}	/*	 * Figure out how much space the data will take, including if it's a	 * partial record.	 *	 * Fixed-length records: it's an error to specify a record that's	 * longer than the fixed-length, and we never require less than	 * the fixed-length record size.	 */	data_size = F_ISSET(data, DB_DBT_PARTIAL) ?	    __bam_partsize(dbp, op, data, h, indx) : data->size;	padrec = 0;	if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {		if (data_size > t->re_len) {len_err:		__db_err(dbp->dbenv,			    "Length improper for fixed length record %lu",			    (u_long)data_size);			return (EINVAL);		}		/* Records that are deleted anyway needn't be padded out. */		if (!LF_ISSET(BI_DELETED) && data_size < t->re_len) {			padrec = 1;			data_size = t->re_len;		}	}	/*	 * Handle partial puts or short fixed-length records: build the	 * real record.	 */	if (padrec || F_ISSET(data, DB_DBT_PARTIAL)) {		tdbt = *data;		if ((ret =		    __bam_build(dbc, op, &tdbt, h, indx, data_size)) != 0)			return (ret);		data = &tdbt;	}	/*	 * If the user has specified a duplicate comparison function, return	 * an error if DB_CURRENT was specified and the replacement data	 * doesn't compare equal to the current data.  This stops apps from	 * screwing up the duplicate sort order.  We have to do this after	 * we build the real record so that we're comparing the real items.	 */	if (op == DB_CURRENT && dbp->dup_compare != NULL) {		if ((ret = __bam_cmp(dbp, data, h,		    indx + (TYPE(h) == P_LBTREE ? O_INDX : 0),		    dbp->dup_compare, &cmp)) != 0)			return (ret);		if (cmp != 0) {			__db_err(dbp->dbenv,			    "Current data differs from put data");			return (EINVAL);		}	}	/*	 * If the key or data item won't fit on a page, we'll have to store	 * them on overflow pages.	 */	needed = 0;	bigdata = data_size > cp->ovflsize;	switch (op) {	case DB_KEYFIRST:		/* We're adding a new key and data pair. */		bigkey = key->size > cp->ovflsize;		if (bigkey)			needed += BOVERFLOW_PSIZE;		else			needed += BKEYDATA_PSIZE(key->size);		if (bigdata)			needed += BOVERFLOW_PSIZE;		else			needed += BKEYDATA_PSIZE(data_size);		break;	case DB_AFTER:	case DB_BEFORE:	case DB_CURRENT:		/*		 * We're either overwriting the data item of a key/data pair		 * or we're creating a new on-page duplicate and only adding		 * a data item.		 *		 * !!!		 * We're not currently correcting for space reclaimed from		 * already deleted items, but I don't think it's worth the		 * complexity.		 */		bigkey = 0;		if (op == DB_CURRENT) {			bk = GET_BKEYDATA(dbp, h,			    indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));			if (B_TYPE(bk->type) == B_KEYDATA)				have_bytes = BKEYDATA_PSIZE(bk->len);			else				have_bytes = BOVERFLOW_PSIZE;			need_bytes = 0;		} else {			have_bytes = 0;			need_bytes = sizeof(db_indx_t);		}		if (bigdata)			need_bytes += BOVERFLOW_PSIZE;		else			need_bytes += BKEYDATA_PSIZE(data_size);		if (have_bytes < need_bytes)			needed += need_bytes - have_bytes;		break;	default:		return (__db_unknown_flag(dbp->dbenv, "__bam_iitem", op));	}	/*	 * If there's not enough room, or the user has put a ceiling on the	 * number of keys permitted in the page, split the page.	 *	 * XXX	 * The t->bt_maxkey test here may be insufficient -- do we have to	 * check in the btree split code, so we don't undo it there!?!?	 */	if (P_FREESPACE(dbp, h) < needed ||	    (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey))		return (DB_NEEDSPLIT);	/*	 * The code breaks it up into five cases:	 *	 * 1. Insert a new key/data pair.	 * 2. Append a new data item (a new duplicate).	 * 3. Insert a new data item (a new duplicate).	 * 4. Delete and re-add the data item (overflow item).	 * 5. Overwrite the data item.	 */	switch (op) {	case DB_KEYFIRST:		/* 1. Insert a new key/data pair. */		if (bigkey) {			if ((ret = __bam_ovput(dbc,			    B_OVERFLOW, PGNO_INVALID, h, indx, key)) != 0)				return (ret);		} else			if ((ret = __db_pitem(dbc, h, indx,			    BKEYDATA_SIZE(key->size), NULL, key)) != 0)				return (ret);		if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0)			return (ret);		++indx;		break;	case DB_AFTER:			/* 2. Append a new data item. */		if (TYPE(h) == P_LBTREE) {			/* Copy the key for the duplicate and adjust cursors. */			if ((ret =			    __bam_adjindx(dbc, h, indx + P_INDX, indx, 1)) != 0)				return (ret);			if ((ret =			    __bam_ca_di(dbc, PGNO(h), indx + P_INDX, 1)) != 0)				return (ret);			indx += 3;			dupadjust = 1;			cp->indx += 2;		} else {			++indx;			cp->indx += 1;		}		break;	case DB_BEFORE:			/* 3. Insert a new data item. */		if (TYPE(h) == P_LBTREE) {			/* Copy the key for the duplicate and adjust cursors. */			if ((ret = __bam_adjindx(dbc, h, indx, indx, 1)) != 0)				return (ret);			if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0)				return (ret);			++indx;			dupadjust = 1;		}		break;	case DB_CURRENT:		 /*		  * Clear the cursor's deleted flag.  The problem is that if		  * we deadlock or fail while deleting the overflow item or		  * replacing the non-overflow item, a subsequent cursor close		  * will try and remove the item because the cursor's delete		  * flag is set		  */		(void)__bam_ca_delete(dbp, PGNO(h), indx, 0);		if (TYPE(h) == P_LBTREE) {			++indx;			dupadjust = 1;			/*			 * In a Btree deleted records aren't counted (deleted			 * records are counted in a Recno because all accesses			 * are based on record number).  If it's a Btree and			 * it's a DB_CURRENT operation overwriting a previously			 * deleted record, increment the record count.			 */			was_deleted = B_DISSET(bk->type);		}		/*		 * 4. Delete and re-add the data item.		 *		 * If we're changing the type of the on-page structure, or we		 * are referencing offpage items, we have to delete and then		 * re-add the item.  We do not do any cursor adjustments here		 * because we're going to immediately re-add the item into the		 * same slot.		 */		if (bigdata || B_TYPE(bk->type) != B_KEYDATA) {			if ((ret = __bam_ditem(dbc, h, indx)) != 0)				return (ret);			break;		}		/* 5. Overwrite the data item. */		replace = 1;		break;	default:		return (__db_unknown_flag(dbp->dbenv, "__bam_iitem", op));	}	/* Add the data. */	if (bigdata) {		/*		 * We do not have to handle deleted (BI_DELETED) records		 * in this case; the actual records should never be created.		 */		DB_ASSERT(!LF_ISSET(BI_DELETED));		if ((ret = __bam_ovput(dbc,		    B_OVERFLOW, PGNO_INVALID, h, indx, data)) != 0)			return (ret);	} else {		if (LF_ISSET(BI_DELETED)) {			B_TSET(bk_tmp.type, B_KEYDATA, 1);			bk_tmp.len = data->size;			bk_hdr.data = &bk_tmp;			bk_hdr.size = SSZA(BKEYDATA, data);			ret = __db_pitem(dbc, h, indx,			    BKEYDATA_SIZE(data->size), &bk_hdr, data);		} else if (replace)			ret = __bam_ritem(dbc, h, indx, data);		else			ret = __db_pitem(dbc, h, indx,			    BKEYDATA_SIZE(data->size), NULL, data);		if (ret != 0)			return (ret);	}	if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)		return (ret);	/*	 * Re-position the cursors if necessary and reset the current cursor	 * to point to the new item.	 */	if (op != DB_CURRENT) {		if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0)			return (ret);		cp->indx = TYPE(h) == P_LBTREE ? indx - O_INDX : indx;	}	/*	 * If we've changed the record count, update the tree.  There's no	 * need to adjust the count if the operation not performed on the	 * current record or when the current record was previously deleted.	 */	if (F_ISSET(cp, C_RECNUM) && (op != DB_CURRENT || was_deleted))		if ((ret = __bam_adjust(dbc, 1)) != 0)			return (ret);	/*	 * If a Btree leaf page is at least 50% full and we may have added or	 * modified a duplicate data item, see if the set of duplicates takes	 * up at least 25% of the space on the page.  If it does, move it onto	 * its own page.	 */	if (dupadjust && P_FREESPACE(dbp, h) <= dbp->pgsize / 2) {		if ((ret = __bam_dup_convert(dbc, h, indx - O_INDX)) != 0)			return (ret);	}	/* If we've modified a recno file, set the flag. */	if (dbc->dbtype == DB_RECNO)		t->re_modified = 1;	return (ret);}/* * __bam_partsize -- *	Figure out how much space a partial data item is in total. */static u_int32_t__bam_partsize(dbp, op, data, h, indx)	DB *dbp;	u_int32_t op, indx;	DBT *data;	PAGE *h;{	BKEYDATA *bk;	u_int32_t nbytes;	/*	 * If the record doesn't already exist, it's simply the data we're	 * provided.	 */	if (op != DB_CURRENT)		return (data->doff + data->size);	/*	 * Otherwise, it's the data provided plus any already existing data	 * that we're not replacing.	 */	bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));

⌨️ 快捷键说明

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