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

📄 bt_cursor.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
							space = *spacep + size;						}						break;					}					memcpy(dp,					    (u_int8_t *)pg + HOFFSET(pg), size);					need_pg = 0;					space -= size;					np += size;				}				if (first == 0 && keyoff != NULL) {					*offp-- = keyoff[0];					*offp-- = keyoff[-1];				}				size = bk->len;				*offp-- = (int32_t)(inp[indx] - HOFFSET(pg)				    + dp - dbuf + SSZA(BKEYDATA, data));			}			*offp-- = size;			first = 0;			if (no_dup)				break;contin:			indx++;			if (opd->dbtype == DB_RECNO)				cp->recno++;		} while (indx < NUM_ENT(pg));		if (no_dup)			break;		cp->indx = indx;	} while (ret == 0);	/* Return the updated information. */	*spacep = space;	*offpp = offp;	*dpp = np;	/*	 * If we ran out of space back up the pointer.	 * If we did not return any dups or reached the end, close the opd.	 */	if (ret == ENOMEM) {		if (opd->dbtype == DB_RECNO) {			if (--cp->recno == 0)				goto close_opd;		} else if (indx != 0)			cp->indx--;		else {			t_ret = __bam_c_prev(opd);			if (t_ret == DB_NOTFOUND)				goto close_opd;			if (t_ret != 0)				ret = t_ret;		}	} else if (keyoff == NULL && ret == DB_NOTFOUND) {		cp->indx--;		if (opd->dbtype == DB_RECNO)			--cp->recno;	} else if (indx == 0 || ret == DB_NOTFOUND) {close_opd:		opd->c_close(opd);		((BTREE_CURSOR *)dbc->internal)->opd = NULL;	}	if (ret == DB_NOTFOUND)		ret = 0;	return (ret);}/* * __bam_getbothc -- *	Search for a matching data item on a join. */static int__bam_getbothc(dbc, data)	DBC *dbc;	DBT *data;{	BTREE_CURSOR *cp;	DB *dbp;	DB_MPOOLFILE *mpf;	int cmp, exact, ret;	dbp = dbc->dbp;	mpf = dbp->mpf;	cp = (BTREE_CURSOR *)dbc->internal;	/*	 * 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)		return (ret);	/*	 * An off-page duplicate cursor.  Search the remaining duplicates	 * for one which matches (do a normal btree search, then verify	 * that the retrieved record is greater than the original one).	 */	if (F_ISSET(dbc, DBC_OPD)) {		/*		 * Check to make sure the desired item comes strictly after		 * the current position;  if it doesn't, return DB_NOTFOUND.		 */		if ((ret = __bam_cmp(dbp, data, cp->page, cp->indx,		    dbp->dup_compare == NULL ? __bam_defcmp : dbp->dup_compare,		    &cmp)) != 0)			return (ret);		if (cmp <= 0)			return (DB_NOTFOUND);		/* Discard the current page, we're going to do a full search. */		if ((ret = mpf->put(mpf, cp->page, 0)) != 0)			return (ret);		cp->page = NULL;		return (__bam_c_search(dbc,		    PGNO_INVALID, data, DB_GET_BOTH, &exact));	}	/*	 * We're doing a DBC->c_get(DB_GET_BOTHC) and we're already searching	 * a set of on-page duplicates (either sorted or unsorted).  Continue	 * a linear search from after the current position.	 *	 * (Note that we could have just finished a "set" of one duplicate,	 * i.e. not a duplicate at all, but the following check will always	 * return DB_NOTFOUND in this case, which is the desired behavior.)	 */	if (cp->indx + P_INDX >= NUM_ENT(cp->page) ||	    !IS_DUPLICATE(dbc, cp->indx, cp->indx + P_INDX))		return (DB_NOTFOUND);	cp->indx += P_INDX;	return (__bam_getboth_finddatum(dbc, data, DB_GET_BOTH));}/* * __bam_getboth_finddatum -- *	Find a matching on-page data item. */static int__bam_getboth_finddatum(dbc, data, flags)	DBC *dbc;	DBT *data;	u_int32_t flags;{	BTREE_CURSOR *cp;	DB *dbp;	db_indx_t base, lim, top;	int cmp, ret;	dbp = dbc->dbp;	cp = (BTREE_CURSOR *)dbc->internal;	/*	 * Called (sometimes indirectly) from DBC->get to search on-page data	 * item(s) for a matching value.  If the original flag was DB_GET_BOTH	 * or DB_GET_BOTH_RANGE, the cursor is set to the first undeleted data	 * item for the key.  If the original flag was DB_GET_BOTHC, the cursor	 * argument is set to the first data item we can potentially return.	 * In both cases, there may or may not be additional duplicate data	 * items to search.	 *	 * If the duplicates are not sorted, do a linear search.	 */	if (dbp->dup_compare == NULL) {		for (;; cp->indx += P_INDX) {			if (!IS_CUR_DELETED(dbc) &&			    (ret = __bam_cmp(dbp, data, cp->page,			    cp->indx + O_INDX, __bam_defcmp, &cmp)) != 0)				return (ret);			if (cmp == 0)				return (0);			if (cp->indx + P_INDX >= NUM_ENT(cp->page) ||			    !IS_DUPLICATE(dbc, cp->indx, cp->indx + P_INDX))				break;		}		return (DB_NOTFOUND);	}	/*	 * If the duplicates are sorted, do a binary search.  The reason for	 * this is that large pages and small key/data pairs result in large	 * numbers of on-page duplicates before they get pushed off-page.	 *	 * Find the top and bottom of the duplicate set.  Binary search	 * requires at least two items, don't loop if there's only one.	 */	for (base = top = cp->indx; top < NUM_ENT(cp->page); top += P_INDX)		if (!IS_DUPLICATE(dbc, cp->indx, top))			break;	if (base == (top - P_INDX)) {		if  ((ret = __bam_cmp(dbp, data,		    cp->page, cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0)			return (ret);		return (cmp == 0 ||		    (cmp < 0 && flags == DB_GET_BOTH_RANGE) ? 0 : DB_NOTFOUND);	}	for (lim = (top - base) / (db_indx_t)P_INDX; lim != 0; lim >>= 1) {		cp->indx = base + ((lim >> 1) * P_INDX);		if ((ret = __bam_cmp(dbp, data, cp->page,		    cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0)			return (ret);		if (cmp == 0) {			/*			 * XXX			 * No duplicate duplicates in sorted duplicate sets,			 * so there can be only one.			 */			if (!IS_CUR_DELETED(dbc))				return (0);			break;		}		if (cmp > 0) {			base = cp->indx + P_INDX;			--lim;		}	}	/* No match found; if we're looking for an exact match, we're done. */	if (flags == DB_GET_BOTH)		return (DB_NOTFOUND);	/*	 * Base is the smallest index greater than the data item, may be zero	 * or a last + O_INDX index, and may be deleted.  Find an undeleted	 * item.	 */	cp->indx = base;	while (cp->indx < top && IS_CUR_DELETED(dbc))		cp->indx += P_INDX;	return (cp->indx < top ? 0 : DB_NOTFOUND);}/* * __bam_c_put -- *	Put using a cursor. */static int__bam_c_put(dbc, key, data, flags, pgnop)	DBC *dbc;	DBT *key, *data;	u_int32_t flags;	db_pgno_t *pgnop;{	BTREE_CURSOR *cp;	DB *dbp;	DBT dbt;	DB_MPOOLFILE *mpf;	db_pgno_t root_pgno;	u_int32_t iiop;	int cmp, exact, ret, stack;	void *arg;	dbp = dbc->dbp;	mpf = dbp->mpf;	cp = (BTREE_CURSOR *)dbc->internal;	root_pgno = cp->root;split:	ret = stack = 0;	switch (flags) {	case DB_AFTER:	case DB_BEFORE:	case DB_CURRENT:		iiop = flags;		/*		 * If the Btree has record numbers (and we're not replacing an		 * existing record), we need a complete stack so that we can		 * adjust the record counts.  The check for flags == DB_CURRENT		 * is superfluous but left in for clarity.  (If C_RECNUM is set		 * we know that flags must be DB_CURRENT, as DB_AFTER/DB_BEFORE		 * are illegal in a Btree unless it's configured for duplicates		 * and you cannot configure a Btree for both record renumbering		 * and duplicates.)		 */		if (flags == DB_CURRENT &&		    F_ISSET(cp, C_RECNUM) && F_ISSET(cp, C_DELETED)) {			if ((ret = __bam_c_getstack(dbc)) != 0)				goto err;			/*			 * Initialize the cursor from the stack.  Don't take			 * the page number or page index, they should already			 * be set.			 */			cp->page = cp->csp->page;			cp->lock = cp->csp->lock;			cp->lock_mode = cp->csp->lock_mode;			stack = 1;			break;		}		/* Acquire the current page with a write lock. */		ACQUIRE_WRITE_LOCK(dbc, ret);		if (ret != 0)			goto err;		if ((ret = mpf->get(mpf, &cp->pgno, 0, &cp->page)) != 0)			goto err;		break;	case DB_KEYFIRST:	case DB_KEYLAST:	case DB_NODUPDATA:		/*		 * Searching off-page, sorted duplicate tree: do a tree search		 * for the correct item; __bam_c_search returns the smallest		 * slot greater than the key, use it.		 *		 * See comment below regarding where we can start the search.		 */		if (F_ISSET(dbc, DBC_OPD)) {			if ((ret = __bam_c_search(dbc,			    F_ISSET(cp, C_RECNUM) ? cp->root : root_pgno,			    data, flags, &exact)) != 0)				goto err;			stack = 1;			/* Disallow "sorted" duplicate duplicates. */			if (exact) {				if (IS_DELETED(dbp, cp->page, cp->indx)) {					iiop = DB_CURRENT;					break;				}				ret = __db_duperr(dbp, flags);				goto err;			}			iiop = DB_BEFORE;			break;		}		/*		 * Searching a btree.		 *		 * If we've done a split, we can start the search from the		 * parent of the split page, which __bam_split returned		 * for us in root_pgno, unless we're in a Btree with record		 * numbering.  In that case, we'll need the true root page		 * in order to adjust the record count.		 */		if ((ret = __bam_c_search(dbc,		    F_ISSET(cp, C_RECNUM) ? cp->root : root_pgno, key,		    flags == DB_KEYFIRST || dbp->dup_compare != NULL ?		    DB_KEYFIRST : DB_KEYLAST, &exact)) != 0)			goto err;		stack = 1;		/*		 * If we don't have an exact match, __bam_c_search returned		 * the smallest slot greater than the key, use it.		 */		if (!exact) {			iiop = DB_KEYFIRST;			break;		}		/*		 * If duplicates aren't supported, replace the current item.		 * (If implementing the DB->put function, our caller already		 * checked the DB_NOOVERWRITE flag.)		 */		if (!F_ISSET(dbp, DB_AM_DUP)) {			iiop = DB_CURRENT;			break;		}		/*		 * If we find a matching entry, it may be an off-page duplicate		 * tree.  Return the page number to our caller, we need a new		 * cursor.		 */		if (pgnop != NULL && __bam_isopd(dbc, pgnop))			goto done;		/* If the duplicates aren't sorted, move to the right slot. */		if (dbp->dup_compare == NULL) {			if (flags == DB_KEYFIRST)				iiop = DB_BEFORE;			else				for (;; cp->indx += P_INDX)					if (cp->indx + P_INDX >=					    NUM_ENT(cp->page) ||					    !IS_DUPLICATE(dbc, cp->indx,					    cp->indx + P_INDX)) {						iiop = DB_AFTER;						break;					}			break;		}		/*		 * We know that we're looking at the first of a set of sorted		 * on-page duplicates.  Walk the list to find the right slot.		 */		for (;; cp->indx += P_INDX) {			if ((ret = __bam_cmp(dbp, data, cp->page,			    cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0)				goto err;			if (cmp < 0) {				iiop = DB_BEFORE;				break;			}			/* Disallow "sorted" duplicate duplicates. */			if (cmp == 0) {				if (IS_DELETED(dbp, cp->page, cp->indx)) {					iiop = DB_CURRENT;					break;				}				ret = __db_duperr(dbp, flags);				goto err;			}			if (cp->indx + P_INDX >= NUM_ENT(cp->page) ||			    P_INP(dbp, ((PAGE *)cp->page))[cp->indx] !=			    P_INP(dbp, ((PAGE *)cp->page))[cp->indx + P_INDX]) {				iiop = DB_AFTER;				break;			}		}		break;	default:		ret = __db_unknown_flag(dbp->dbenv, "__bam_c_put", flags);		goto err;	}	switch (ret = __bam_iitem(dbc, key, data, iiop, 0)) {	case 0:		break;	case DB_NEEDSPLIT:		/*		 * To split, we need a key for the page.  Either use the key		 * argument or get a copy of the key from the page.		 */		if (flags == DB_AFTER ||		    flags == DB_BEFORE || flags == DB_CURRENT) {			memset(&dbt, 0, sizeof(DBT));			if ((ret = __db_ret(dbp, cp->page, 0, &dbt,			    &dbc->rkey->data, &dbc->rkey->ulen)) != 0)				goto err;			arg = &dbt;		} else			arg = F_ISSET(dbc, DBC_OPD) ? data : key;		/*		 * Discard any locks and pinned pages (the locks are discarded		 * even if we're running with transactions, as they lock pages		 * that we're sorry we ever acquired).  If stack is set and the		 * cursor entries are valid, they point to the same entries as		 * the stack, don't free them twice.		 */		if (stack)			ret = __bam_stkrel(dbc, STK_CLRDBC | STK_NOLOCK);		else			DISCARD_CUR(dbc, ret);		if (ret != 0)			goto err;		/* Split the tree. */		if ((ret = __bam_split(dbc, arg, &root_pgno)) != 0)			return (ret);		goto split;	default:		goto err;	}err:done:	/*	 * Discard any pages pinned in the tree and their locks, except for	 * the leaf page.  Note, the leaf page participated in any stack we	 * acquired, and so we have to adjust the stack as necessary.  If	 * there was only a single page on the stack, we don't have to free	 * further stack pages.	 */	if (stack && BT_STK_POP(cp) != NULL)		(void)__bam_stkrel(dbc, 0);	/*	 * Regardless of whether we were successful or not, clear the delete	 * flag.  If we're successful, we either moved the cursor or the item	 * is no longer deleted.  If we're not successful, then we're just a	 * copy, no need to have the flag set.	 */	F_CLR(cp, C_DELETED);	return (ret);}/* * __bam_c_rget -- *	Return the record number for a cursor. * * PUBLIC: int __bam_c_rget __P((DBC *, DBT *)); */int__bam_c_rget(dbc, data)	DBC *dbc;

⌨️ 快捷键说明

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