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

📄 bt_recno.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1997-2002 *	Sleepycat Software.  All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: bt_recno.c,v 11.106 2002/08/16 04:56:30 ubell Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <limits.h>#include <stdio.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/btree.h"#include "dbinc/db_shash.h"#include "dbinc/lock.h"static int  __ram_add __P((DBC *, db_recno_t *, DBT *, u_int32_t, u_int32_t));static int  __ram_source __P((DB *));static int  __ram_sread __P((DBC *, db_recno_t));static int  __ram_update __P((DBC *, db_recno_t, int));/* * In recno, there are two meanings to the on-page "deleted" flag.  If we're * re-numbering records, it means the record was implicitly created.  We skip * over implicitly created records if doing a cursor "next" or "prev", and * return DB_KEYEMPTY if they're explicitly requested..  If not re-numbering * records, it means that the record was implicitly created, or was deleted. * We skip over implicitly created or deleted records if doing a cursor "next" * or "prev", and return DB_KEYEMPTY if they're explicitly requested. * * If we're re-numbering records, then we have to detect in the cursor that * a record was deleted, and adjust the cursor as necessary on the next get. * If we're not re-numbering records, then we can detect that a record has * been deleted by looking at the actual on-page record, so we completely * ignore the cursor's delete flag.  This is different from the B+tree code. * It also maintains whether the cursor references a deleted record in the * cursor, and it doesn't always check the on-page value. */#define	CD_SET(cp) {							\	if (F_ISSET(cp, C_RENUMBER))					\		F_SET(cp, C_DELETED);					\}#define	CD_CLR(cp) {							\	if (F_ISSET(cp, C_RENUMBER)) {					\		F_CLR(cp, C_DELETED);					\		cp->order = INVALID_ORDER;				\	}								\}#define	CD_ISSET(cp)							\	(F_ISSET(cp, C_RENUMBER) && F_ISSET(cp, C_DELETED))/* * Macros for comparing the ordering of two cursors. * cp1 comes before cp2 iff one of the following holds: *	cp1's recno is less than cp2's recno *	recnos are equal, both deleted, and cp1's order is less than cp2's *	recnos are equal, cp1 deleted, and cp2 not deleted */#define	C_LESSTHAN(cp1, cp2)						\    (((cp1)->recno < (cp2)->recno) ||					\    (((cp1)->recno == (cp2)->recno) &&					\    ((CD_ISSET((cp1)) && CD_ISSET((cp2)) && (cp1)->order < (cp2)->order) || \    (CD_ISSET((cp1)) && !CD_ISSET((cp2))))))/* * cp1 is equal to cp2 iff their recnos and delete flags are identical, * and if the delete flag is set their orders are also identical. */#define	C_EQUAL(cp1, cp2)						\    ((cp1)->recno == (cp2)->recno && CD_ISSET((cp1)) == CD_ISSET((cp2)) && \    (!CD_ISSET((cp1)) || (cp1)->order == (cp2)->order))/* * Do we need to log the current cursor adjustment? */#define	CURADJ_LOG(dbc)							\	(DBC_LOGGING((dbc)) && (dbc)->txn != NULL && (dbc)->txn->parent != NULL)/* * After a search, copy the found page into the cursor, discarding any * currently held lock. */#define	STACK_TO_CURSOR(cp) {						\	(cp)->page = (cp)->csp->page;					\	(cp)->pgno = (cp)->csp->page->pgno;				\	(cp)->indx = (cp)->csp->indx;					\	(void)__TLPUT(dbc, (cp)->lock);					\	(cp)->lock = (cp)->csp->lock;					\	(cp)->lock_mode = (cp)->csp->lock_mode;				\}/* * __ram_open -- *	Recno open function. * * PUBLIC: int __ram_open __P((DB *, * PUBLIC:      DB_TXN *, const char *, db_pgno_t, u_int32_t)); */int__ram_open(dbp, txn, name, base_pgno, flags)	DB *dbp;	DB_TXN *txn;	const char *name;	db_pgno_t base_pgno;	u_int32_t flags;{	BTREE *t;	DBC *dbc;	int ret, t_ret;	COMPQUIET(name, NULL);	t = dbp->bt_internal;	/* Initialize the remaining fields/methods of the DB. */	dbp->stat = __bam_stat;	/* Start up the tree. */	if ((ret = __bam_read_root(dbp, txn, base_pgno, flags)) != 0)		return (ret);	/*	 * If the user specified a source tree, open it and map it in.	 *	 * !!!	 * We don't complain if the user specified transactions or threads.	 * It's possible to make it work, but you'd better know what you're	 * doing!	 */	if (t->re_source != NULL && (ret = __ram_source(dbp)) != 0)		return (ret);	/* If we're snapshotting an underlying source file, do it now. */	if (F_ISSET(dbp, DB_AM_SNAPSHOT)) {		/* Allocate a cursor. */		if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)			return (ret);		/* Do the snapshot. */		if ((ret = __ram_update(dbc,		    DB_MAX_RECORDS, 0)) != 0 && ret == DB_NOTFOUND)			ret = 0;		/* Discard the cursor. */		if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)			ret = t_ret;	}	return (ret);}/* * __ram_append -- *	Recno append function. * * PUBLIC: int __ram_append __P((DBC *, DBT *, DBT *)); */int__ram_append(dbc, key, data)	DBC *dbc;	DBT *key, *data;{	BTREE_CURSOR *cp;	int ret;	cp = (BTREE_CURSOR *)dbc->internal;	/*	 * Make sure we've read in all of the backing source file.  If	 * we found the record or it simply didn't exist, add the	 * user's record.	 */	ret = __ram_update(dbc, DB_MAX_RECORDS, 0);	if (ret == 0 || ret == DB_NOTFOUND)		ret = __ram_add(dbc, &cp->recno, data, DB_APPEND, 0);	/* Return the record number. */	if (ret == 0)		ret = __db_retcopy(dbc->dbp->dbenv, key, &cp->recno,		    sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen);	return (ret);}/* * __ram_c_del -- *	Recno cursor->c_del function. * * PUBLIC: int __ram_c_del __P((DBC *)); */int__ram_c_del(dbc)	DBC *dbc;{	BKEYDATA bk;	BTREE *t;	BTREE_CURSOR *cp;	DB *dbp;	DB_LSN lsn;	DBT hdr, data;	EPG *epg;	int exact, ret, stack;	dbp = dbc->dbp;	cp = (BTREE_CURSOR *)dbc->internal;	t = dbp->bt_internal;	stack = 0;	/*	 * The semantics of cursors during delete are as follows: in	 * non-renumbering recnos, records are replaced with a marker	 * containing a delete flag.  If the record referenced by this cursor	 * has already been deleted, we will detect that as part of the delete	 * operation, and fail.	 *	 * In renumbering recnos, cursors which represent deleted items	 * are flagged with the C_DELETED flag, and it is an error to	 * call c_del a second time without an intervening cursor motion.	 */	if (CD_ISSET(cp))		return (DB_KEYEMPTY);	/* Search the tree for the key; delete only deletes exact matches. */	if ((ret = __bam_rsearch(dbc, &cp->recno, S_DELETE, 1, &exact)) != 0)		goto err;	if (!exact) {		ret = DB_NOTFOUND;		goto err;	}	stack = 1;	/* Copy the page into the cursor. */	STACK_TO_CURSOR(cp);	/*	 * If re-numbering records, the on-page deleted flag can only mean	 * that this record was implicitly created.  Applications aren't	 * permitted to delete records they never created, return an error.	 *	 * If not re-numbering records, the on-page deleted flag means that	 * this record was implicitly created, or, was deleted at some time.	 * The former is an error because applications aren't permitted to	 * delete records they never created, the latter is an error because	 * if the record was "deleted", we could never have found it.	 */	if (B_DISSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type)) {		ret = DB_KEYEMPTY;		goto err;	}	if (F_ISSET(cp, C_RENUMBER)) {		/* Delete the item, adjust the counts, adjust the cursors. */		if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0)			goto err;		__bam_adjust(dbc, -1);		if (__ram_ca(dbc, CA_DELETE) > 0 &&		    CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp, dbc->txn,		    &lsn, 0, CA_DELETE, cp->root, cp->recno, cp->order)) != 0)			goto err;		/*		 * If the page is empty, delete it.		 *		 * We never delete a root page.  First, root pages of primary		 * databases never go away, recno or otherwise.  However, if		 * it's the root page of an off-page duplicates database, then		 * it can be deleted.   We don't delete it here because we have		 * no way of telling the primary database page holder (e.g.,		 * the hash access method) that its page element should cleaned		 * up because the underlying tree is gone.  So, we keep the page		 * around until the last cursor referencing the empty tree is		 * are closed, and then clean it up.		 */		if (NUM_ENT(cp->page) == 0 && PGNO(cp->page) != cp->root) {			/*			 * We already have a locked stack of pages.  However,			 * there are likely entries in the stack that aren't			 * going to be emptied by removing the single reference			 * to the emptied page (or one of its parents).			 */			for (epg = cp->csp; epg >= cp->sp; --epg)				if (NUM_ENT(epg->page) > 1)					break;			/*			 * We want to delete a single item out of the last page			 * that we're not deleting.			 */			ret = __bam_dpages(dbc, epg);			/*			 * Regardless of the return from __bam_dpages, it will			 * discard our stack and pinned page.			 */			stack = 0;			cp->page = NULL;		}	} else {		/* Use a delete/put pair to replace the record with a marker. */		if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0)			goto err;		B_TSET(bk.type, B_KEYDATA, 1);		bk.len = 0;		memset(&hdr, 0, sizeof(hdr));		hdr.data = &bk;		hdr.size = SSZA(BKEYDATA, data);		memset(&data, 0, sizeof(data));		data.data = (void *)"";		data.size = 0;		if ((ret = __db_pitem(dbc,		    cp->page, cp->indx, BKEYDATA_SIZE(0), &hdr, &data)) != 0)			goto err;	}	t->re_modified = 1;err:	if (stack)		__bam_stkrel(dbc, STK_CLRDBC);	return (ret);}/* * __ram_c_get -- *	Recno cursor->c_get function. * * PUBLIC: int __ram_c_get * PUBLIC:     __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); */int__ram_c_get(dbc, key, data, flags, pgnop)	DBC *dbc;	DBT *key, *data;	u_int32_t flags;	db_pgno_t *pgnop;{	BTREE_CURSOR *cp;	DB *dbp;	int cmp, exact, ret;	COMPQUIET(pgnop, NULL);	dbp = dbc->dbp;	cp = (BTREE_CURSOR *)dbc->internal;	LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);retry:	switch (flags) {	case DB_CURRENT:		/*		 * If we're using mutable records and the deleted flag is		 * set, the cursor is pointing at a nonexistent record;		 * return an error.		 */		if (CD_ISSET(cp))			return (DB_KEYEMPTY);		break;	case DB_NEXT_DUP:		/*		 * If we're not in an off-page dup set, we know there's no		 * next duplicate since recnos don't have them.  If we		 * are in an off-page dup set, the next item assuredly is		 * a dup, so we set flags to DB_NEXT and keep going.		 */		if (!F_ISSET(dbc, DBC_OPD))			return (DB_NOTFOUND);		/* FALLTHROUGH */	case DB_NEXT_NODUP:		/*		 * Recno databases don't have duplicates, set flags to DB_NEXT		 * and keep going.		 */		/* FALLTHROUGH */	case DB_NEXT:		flags = DB_NEXT;		/*		 * If record numbers are mutable: if we just deleted a record,		 * we have to avoid incrementing the record number so that we		 * return the right record by virtue of renumbering the tree.		 */		if (CD_ISSET(cp))			break;		if (cp->recno != RECNO_OOB) {			++cp->recno;			break;		}		/* FALLTHROUGH */	case DB_FIRST:		flags = DB_NEXT;		cp->recno = 1;		break;	case DB_PREV_NODUP:		/*		 * Recno databases don't have duplicates, set flags to DB_PREV		 * and keep going.		 */		/* FALLTHROUGH */	case DB_PREV:		flags = DB_PREV;		if (cp->recno != RECNO_OOB) {			if (cp->recno == 1) {				ret = DB_NOTFOUND;				goto err;			}			--cp->recno;			break;		}		/* FALLTHROUGH */	case DB_LAST:		flags = DB_PREV;		if (((ret = __ram_update(dbc,		    DB_MAX_RECORDS, 0)) != 0) && ret != DB_NOTFOUND)			goto err;		if ((ret = __bam_nrecs(dbc, &cp->recno)) != 0)			goto err;		if (cp->recno == 0) {			ret = DB_NOTFOUND;			goto err;		}		break;	case DB_GET_BOTHC:		/*		 * If we're doing a join and these are offpage dups,		 * we want to keep searching forward from after the		 * current cursor position.  Increment the recno by 1,		 * then proceed as for a DB_SET.		 *		 * Otherwise, we know there are no additional matching		 * data, as recnos don't have dups.  return DB_NOTFOUND.		 */		if (F_ISSET(dbc, DBC_OPD)) {			cp->recno++;

⌨️ 快捷键说明

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