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

📄 bt_cursor.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
delete:	/*	 * If the delete occurred in a Btree, we're going to look at the page	 * to see if the item has to be physically deleted.  Otherwise, we do	 * not need the actual page (and it may not even exist, it might have	 * been truncated from the file after an allocation aborted).	 *	 * Delete the on-page physical item referenced by the cursor.	 */	if (dbc_c->dbtype == DB_BTREE) {		if ((ret = __memp_fget(mpf, &cp_c->pgno, 0, &cp_c->page)) != 0)			goto err;		if ((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 = __memp_fget(mpf, &root_pgno, 0, &h)) != 0)		goto err;	if (NUM_ENT(h) == 0) {		DISCARD_CUR(dbc_c, ret);		if (ret != 0)			goto err;		if ((ret = __db_free(dbc, h)) != 0)			goto err;	} else {		if ((ret = __memp_fput(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 = __memp_fget(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, ret);	DISCARD_CUR(dbc, 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 tree.  We don't have to acquire any new locks, we have	 * to have a read lock to even get here.	 */	if (cp->opd == NULL) {		/*		 * On-page duplicates, get the page and count.		 */		if ((ret = __memp_fget(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 = 0,		    top = NUM_ENT(cp->page) - P_INDX;; indx += P_INDX) {			if (!IS_DELETED(dbp, cp->page, indx))				++recno;			if (indx == top ||			    !IS_DUPLICATE(dbc, indx, indx + P_INDX))				break;		}	} else {		/*		 * Off-page duplicates tree, get the root page of the off-page		 * duplicate tree.		 */		if ((ret = __memp_fget(		    mpf, &cp->opd->internal->root, 0, &cp->page)) != 0)			return (ret);		/*		 * If the page is an internal page use the page's count as it's		 * up-to-date and reflects the status of cursors in the tree.		 * If the page is a leaf page for unsorted duplicates, use the		 * page's count as cursors don't mark items deleted on the page		 * and wait, cursor delete items immediately.		 * If the page is a leaf page for sorted duplicates, there may		 * be cursors on the page marking deleted items -- count.		 */		if (TYPE(cp->page) == P_LDUP)			for (recno = 0, indx = 0,			    top = NUM_ENT(cp->page) - O_INDX;; indx += O_INDX) {				if (!IS_DELETED(dbp, cp->page, indx))					++recno;				if (indx == top)					break;			}		else			recno = RE_NREC(cp->page);	}	*recnop = recno;	ret = __memp_fput(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 = __memp_fset(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 = __memp_fput(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 (orig_dbc->txn == NULL && LOCK_ISSET(orig->lock))		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 = __memp_fget(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

⌨️ 快捷键说明

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