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

📄 bt_cursor.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
	 *	 * Lock the primary database page, regardless of whether we're deleting	 * an item on a primary database page or an off-page duplicates page.	 */	ACQUIRE(dbc, DB_LOCK_WRITE,	    cp->pgno, cp_c->lock, cp_c->pgno, cp_c->page, ret);	if (ret != 0)		goto err;delete:	/*	 * If the delete occurred in a btree, delete the on-page physical item	 * referenced by the cursor.	 */	if (dbc_c->dbtype == DB_BTREE && (ret = __bam_c_physdel(dbc_c)) != 0)		goto err;	/*	 * If we're not working in an off-page duplicate tree, then we're	 * done.	 */	if (!F_ISSET(dbc_c, DBC_OPD) || root_pgno == PGNO_INVALID)		goto done;	/*	 * We may have just deleted the last element in the off-page duplicate	 * tree, and closed the last cursor in the tree.  For an off-page btree	 * there are no other cursors in the tree by definition, if the tree is	 * empty.  For an off-page recno we know we have closed the last cursor	 * in the tree because the __ram_ca_delete call above returned 0 only	 * in that case.  So, if the off-page duplicate tree is empty at this	 * point, we want to remove it.	 */	if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0)		goto err;	if (NUM_ENT(h) == 0) {		if ((ret = __db_free(dbc, h)) != 0)			goto err;	} else {		if ((ret = mpf->put(mpf, h, 0)) != 0)			goto err;		goto done;	}	/*	 * When removing the tree, we have to do one of two things.  If this is	 * case #2, that is, the primary tree is a btree, delete the key that's	 * associated with the tree from the btree leaf page.  We know we are	 * the only reference to it and we already have the correct lock.  We	 * detect this case because the cursor that was passed to us references	 * an off-page duplicate cursor.	 *	 * If this is case #3, that is, the primary tree isn't a btree, pass	 * the information back to our caller, it's their job to do cleanup on	 * the primary page.	 */	if (dbc_opd != NULL) {		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)			goto err;		if ((ret = __bam_c_physdel(dbc)) != 0)			goto err;	} else		*rmroot = 1;err:done:	/*	 * Discard the page references and locks, and confirm that the stack	 * has been emptied.	 */	if (dbc_opd != NULL) {		DISCARD_CUR(dbc_opd, t_ret);		if (t_ret != 0 && ret == 0)			ret = t_ret;	}	DISCARD_CUR(dbc, t_ret);	if (t_ret != 0 && ret == 0)		ret = t_ret;	/* Downgrade any CDB lock we acquired. */	if (cdb_lock)		(void)__lock_downgrade(		    dbp->dbenv, &dbc->mylock, DB_LOCK_IWRITE, 0);	return (ret);}/* * __bam_c_destroy -- *	Close a single cursor -- internal version. */static int__bam_c_destroy(dbc)	DBC *dbc;{	/* Discard the structures. */	__os_free(dbc->dbp->dbenv, dbc->internal);	return (0);}/* * __bam_c_count -- *	Return a count of on and off-page duplicates. * * PUBLIC: int __bam_c_count __P((DBC *, db_recno_t *)); */int__bam_c_count(dbc, recnop)	DBC *dbc;	db_recno_t *recnop;{	BTREE_CURSOR *cp;	DB *dbp;	DB_MPOOLFILE *mpf;	db_indx_t indx, top;	db_recno_t recno;	int ret;	dbp = dbc->dbp;	mpf = dbp->mpf;	cp = (BTREE_CURSOR *)dbc->internal;	/*	 * Called with the top-level cursor that may reference an off-page	 * duplicates page.  If it's a set of on-page duplicates, get the	 * page and count.  Otherwise, get the root page of the off-page	 * duplicate tree, and use the count.  We don't have to acquire any	 * new locks, we have to have a read lock to even get here.	 */	if (cp->opd == NULL) {		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)			return (ret);		/*		 * Move back to the beginning of the set of duplicates and		 * then count forward.		 */		for (indx = cp->indx;; indx -= P_INDX)			if (indx == 0 ||			    !IS_DUPLICATE(dbc, indx, indx - P_INDX))				break;		for (recno = 1, top = NUM_ENT(cp->page) - P_INDX;		    indx < top; ++recno, indx += P_INDX)			if (!IS_DUPLICATE(dbc, indx, indx + P_INDX))				break;		*recnop = recno;	} else {		if ((ret =		    mpf->get(mpf, &cp->opd->internal->root, 0, &cp->page)) != 0)			return (ret);		*recnop = RE_NREC(cp->page);	}	ret = mpf->put(mpf, cp->page, 0);	cp->page = NULL;	return (ret);}/* * __bam_c_del -- *	Delete using a cursor. */static int__bam_c_del(dbc)	DBC *dbc;{	BTREE_CURSOR *cp;	DB *dbp;	DB_MPOOLFILE *mpf;	int ret, t_ret;	dbp = dbc->dbp;	mpf = dbp->mpf;	cp = (BTREE_CURSOR *)dbc->internal;	ret = 0;	/* If the item was already deleted, return failure. */	if (F_ISSET(cp, C_DELETED))		return (DB_KEYEMPTY);	/*	 * This code is always called with a page lock but no page.	 */	DB_ASSERT(cp->page == NULL);	/*	 * We don't physically delete the record until the cursor moves, so	 * we have to have a long-lived write lock on the page instead of a	 * a long-lived read lock.  Note, we have to have a read lock to even	 * get here.	 *	 * If we're maintaining record numbers, we lock the entire tree, else	 * we lock the single page.	 */	if (F_ISSET(cp, C_RECNUM)) {		if ((ret = __bam_c_getstack(dbc)) != 0)			goto err;		cp->page = cp->csp->page;	} else {		ACQUIRE_CUR(dbc, DB_LOCK_WRITE, cp->pgno, ret);		if (ret != 0)			goto err;	}	/* Log the change. */	if (DBC_LOGGING(dbc)) {		if ((ret = __bam_cdel_log(dbp, dbc->txn, &LSN(cp->page), 0,		    PGNO(cp->page), &LSN(cp->page), cp->indx)) != 0)			goto err;	} else		LSN_NOT_LOGGED(LSN(cp->page));	/* Set the intent-to-delete flag on the page. */	if (TYPE(cp->page) == P_LBTREE)		B_DSET(GET_BKEYDATA(dbp, cp->page, cp->indx + O_INDX)->type);	else		B_DSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type);	/* Mark the page dirty. */	ret = mpf->set(mpf, cp->page, DB_MPOOL_DIRTY);err:	/*	 * If we've been successful so far and the tree has record numbers,	 * adjust the record counts.  Either way, release acquired page(s).	 */	if (F_ISSET(cp, C_RECNUM)) {		if (ret == 0)			ret = __bam_adjust(dbc, -1);		(void)__bam_stkrel(dbc, 0);	} else		if (cp->page != NULL &&		    (t_ret = mpf->put(mpf, cp->page, 0)) != 0 && ret == 0)			ret = t_ret;	cp->page = NULL;	/* Update the cursors last, after all chance of failure is past. */	if (ret == 0)		(void)__bam_ca_delete(dbp, cp->pgno, cp->indx, 1);	return (ret);}/* * __bam_c_dup -- *	Duplicate a btree cursor, such that the new one holds appropriate *	locks for the position of the original. * * PUBLIC: int __bam_c_dup __P((DBC *, DBC *)); */int__bam_c_dup(orig_dbc, new_dbc)	DBC *orig_dbc, *new_dbc;{	BTREE_CURSOR *orig, *new;	int ret;	orig = (BTREE_CURSOR *)orig_dbc->internal;	new = (BTREE_CURSOR *)new_dbc->internal;	/*	 * If we're holding a lock we need to acquire a copy of it, unless	 * we're in a transaction.  We don't need to copy any lock we're	 * holding inside a transaction because all the locks are retained	 * until the transaction commits or aborts.	 */	if (LOCK_ISSET(orig->lock) && orig_dbc->txn == NULL) {		if ((ret = __db_lget(new_dbc,		    0, new->pgno, new->lock_mode, 0, &new->lock)) != 0)			return (ret);	}	new->ovflsize = orig->ovflsize;	new->recno = orig->recno;	new->flags = orig->flags;	return (0);}/* * __bam_c_get -- *	Get using a cursor (btree). */static int__bam_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;	DB_MPOOLFILE *mpf;	db_pgno_t orig_pgno;	db_indx_t orig_indx;	int exact, newopd, ret;	dbp = dbc->dbp;	mpf = dbp->mpf;	cp = (BTREE_CURSOR *)dbc->internal;	orig_pgno = cp->pgno;	orig_indx = cp->indx;	newopd = 0;	switch (flags) {	case DB_CURRENT:		/* It's not possible to return a deleted record. */		if (F_ISSET(cp, C_DELETED)) {			ret = DB_KEYEMPTY;			goto err;		}		/*		 * Acquire the current page.  We have at least a read-lock		 * already.  The caller may have set DB_RMW asking for a		 * write lock, but upgrading to a write lock has no better		 * chance of succeeding now instead of later, so don't try.		 */		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)			goto err;		break;	case DB_FIRST:		newopd = 1;		if ((ret = __bam_c_first(dbc)) != 0)			goto err;		break;	case DB_GET_BOTH:	case DB_GET_BOTH_RANGE:		/*		 * There are two ways to get here based on DBcursor->c_get		 * with the DB_GET_BOTH/DB_GET_BOTH_RANGE flags set:		 *		 * 1. Searching a sorted off-page duplicate tree: do a tree		 * search.		 *		 * 2. Searching btree: do a tree search.  If it returns a		 * reference to off-page duplicate tree, return immediately		 * and let our caller deal with it.  If the search doesn't		 * return a reference to off-page duplicate tree, continue		 * with an on-page search.		 */		if (F_ISSET(dbc, DBC_OPD)) {			if ((ret = __bam_c_search(			    dbc, PGNO_INVALID, data, flags, &exact)) != 0)				goto err;			if (flags == DB_GET_BOTH) {				if (!exact) {					ret = DB_NOTFOUND;					goto err;				}				break;			}			/*			 * We didn't require an exact match, so the search may			 * may have returned an entry past the end of the page,			 * or we may be referencing a deleted record.  If so,			 * move to the next entry.			 */			if ((cp->indx == NUM_ENT(cp->page) ||			    IS_CUR_DELETED(dbc)) &&			    (ret = __bam_c_next(dbc, 1, 0)) != 0)				goto err;		} else {			if ((ret = __bam_c_search(			    dbc, PGNO_INVALID, key, flags, &exact)) != 0)				return (ret);			if (!exact) {				ret = DB_NOTFOUND;				goto err;			}			if (pgnop != NULL && __bam_isopd(dbc, pgnop)) {				newopd = 1;				break;			}			if ((ret =			    __bam_getboth_finddatum(dbc, data, flags)) != 0)				goto err;		}		break;	case DB_GET_BOTHC:		if ((ret = __bam_getbothc(dbc, data)) != 0)			goto err;		break;	case DB_LAST:		newopd = 1;		if ((ret = __bam_c_last(dbc)) != 0)			goto err;		break;	case DB_NEXT:		newopd = 1;		if (cp->pgno == PGNO_INVALID) {			if ((ret = __bam_c_first(dbc)) != 0)				goto err;		} else			if ((ret = __bam_c_next(dbc, 1, 0)) != 0)				goto err;		break;	case DB_NEXT_DUP:		if ((ret = __bam_c_next(dbc, 1, 0)) != 0)			goto err;		if (!IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx)) {			ret = DB_NOTFOUND;			goto err;		}		break;	case DB_NEXT_NODUP:		newopd = 1;		if (cp->pgno == PGNO_INVALID) {			if ((ret = __bam_c_first(dbc)) != 0)				goto err;		} else			do {				if ((ret = __bam_c_next(dbc, 1, 0)) != 0)					goto err;			} while (IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx));		break;	case DB_PREV:		newopd = 1;		if (cp->pgno == PGNO_INVALID) {			if ((ret = __bam_c_last(dbc)) != 0)				goto err;		} else			if ((ret = __bam_c_prev(dbc)) != 0)				goto err;		break;	case DB_PREV_NODUP:		newopd = 1;		if (cp->pgno == PGNO_INVALID) {			if ((ret = __bam_c_last(dbc)) != 0)				goto err;		} else			do {				if ((ret = __bam_c_prev(dbc)) != 0)					goto err;			} while (IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx));		break;	case DB_SET:	case DB_SET_RECNO:		newopd = 1;		if ((ret = __bam_c_search(dbc,		    PGNO_INVALID, key, flags, &exact)) != 0)			goto err;		break;	case DB_SET_RANGE:		newopd = 1;		if ((ret = __bam_c_search(dbc,		    PGNO_INVALID, key, flags, &exact)) != 0)			goto err;		/*		 * As we didn't require an exact match, the search function		 * may have returned an entry past the end of the page.  Or,		 * we may be referencing a deleted record.  If so, move to		 * the next entry.		 */		if (cp->indx == NUM_ENT(cp->page) || IS_CUR_DELETED(dbc))			if ((ret = __bam_c_next(dbc, 0, 0)) != 0)				goto err;		break;	default:		ret = __db_unknown_flag(dbp->dbenv, "__bam_c_get", flags);		goto err;	}	/*	 * We may have moved to an off-page duplicate tree.  Return that	 * information to our caller.	 */	if (newopd && pgnop != NULL)		(void)__bam_isopd(dbc, pgnop);	/*	 * Don't return the key, it was passed to us (this is true even if the	 * application defines a compare function returning equality for more	 * than one key value, since in that case which actual value we store	 * in the database is undefined -- and particularly true in the case of	 * duplicates where we only store one key value).	 */	if (flags == DB_GET_BOTH ||	    flags == DB_GET_BOTH_RANGE || flags == DB_SET)		F_SET(key, DB_DBT_ISSET);err:	/*	 * Regardless of whether we were successful or not, if the cursor	 * moved, clear the delete flag, DBcursor->c_get never references	 * a deleted key, if it moved at all.	 */	if (F_ISSET(cp, C_DELETED) &&	    (cp->pgno != orig_pgno || cp->indx != orig_indx))		F_CLR(cp, C_DELETED);	return (ret);}static int__bam_get_prev(dbc)	DBC *dbc;{	BTREE_CURSOR *cp;	DBT key, data;	db_pgno_t pgno;	int ret;

⌨️ 快捷键说明

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