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

📄 db_cam.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
skip_s_update:	/*	 * If we have an off-page duplicates cursor, and the operation applies	 * to it, perform the operation.  Duplicate the cursor and call the	 * underlying function.	 *	 * Off-page duplicate trees are locked in the primary tree, that is,	 * we acquire a write lock in the primary tree and no locks in the	 * off-page dup tree.  If the put operation is done in an off-page	 * duplicate tree, call the primary cursor's upgrade routine first.	 */	if (dbc_arg->internal->opd != NULL &&	    (flags == DB_AFTER || flags == DB_BEFORE || flags == DB_CURRENT)) {		/*		 * A special case for hash off-page duplicates.  Hash doesn't		 * support (and is documented not to support) put operations		 * relative to a cursor which references an already deleted		 * item.  For consistency, apply the same criteria to off-page		 * duplicates as well.		 */		if (dbc_arg->dbtype == DB_HASH && F_ISSET(		    ((BTREE_CURSOR *)(dbc_arg->internal->opd->internal)),		    C_DELETED)) {			ret = DB_NOTFOUND;			goto err;		}		if ((ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)			return (ret);		if ((ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITIONI)) != 0)			goto err;		opd = dbc_n->internal->opd;		if ((ret = opd->c_am_put(		    opd, key, data, flags, NULL)) != 0)			goto err;		goto done;	}	/*	 * Perform an operation on the main cursor.  Duplicate the cursor,	 * and call the underlying function.	 *	 * XXX: MARGO	 *	tmp_flags = flags == DB_AFTER ||	    flags == DB_BEFORE || flags == DB_CURRENT ? DB_POSITIONI : 0;	 */	tmp_flags = DB_POSITIONI;	/*	 * If this cursor is going to be closed immediately, we don't	 * need to take precautions to clean it up on error.	 */	if (F_ISSET(dbc_arg, DBC_TRANSIENT))		dbc_n = dbc_arg;	else if ((ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags)) != 0)		goto err;	pgno = PGNO_INVALID;	if ((ret = dbc_n->c_am_put(dbc_n, key, data, flags, &pgno)) != 0)		goto err;	/*	 * We may be referencing a new off-page duplicates tree.  Acquire	 * a new cursor and call the underlying function.	 */	if (pgno != PGNO_INVALID) {		oldopd = dbc_n->internal->opd;		if ((ret = __db_c_newopd(dbc_arg, pgno, oldopd, &opd)) != 0) {			dbc_n->internal->opd = opd;			goto err;		}		dbc_n->internal->opd = opd;		if ((ret = opd->c_am_put(		    opd, key, data, flags, NULL)) != 0)			goto err;	}done:err:	/* Cleanup and cursor resolution. */	if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)		ret = t_ret;	/* If newdata was used, free its buffer. */	if (newdata.data != NULL)		__os_free(dbp->dbenv, newdata.data);	CDB_LOCKING_DONE(dbp, dbc_arg);	if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0)		return (t_ret);	return (ret);}/* * __db_duperr() *	Error message: we don't currently support sorted duplicate duplicates. * PUBLIC: int __db_duperr __P((DB *, u_int32_t)); */int__db_duperr(dbp, flags)	DB *dbp;	u_int32_t flags;{	/*	 * If we run into this error while updating a secondary index,	 * don't yell--there's no clean way to pass DB_NODUPDATA in along	 * with DB_UPDATE_SECONDARY, but we may run into this problem	 * in a normal, non-error course of events.	 *	 * !!!	 * If and when we ever permit duplicate duplicates in sorted-dup	 * databases, we need to either change the secondary index code	 * to check for dup dups, or we need to maintain the implicit	 * "DB_NODUPDATA" behavior for databases with DB_AM_SECONDARY set.	 */	if (flags != DB_NODUPDATA && !F_ISSET(dbp, DB_AM_SECONDARY))		__db_err(dbp->dbenv,		    "Duplicate data items are not supported with sorted data");	return (DB_KEYEXIST);}/* * __db_c_cleanup -- *	Clean up duplicate cursors. */static int__db_c_cleanup(dbc, dbc_n, failed)	DBC *dbc, *dbc_n;	int failed;{	DB *dbp;	DBC *opd;	DBC_INTERNAL *internal;	DB_MPOOLFILE *mpf;	int ret, t_ret;	dbp = dbc->dbp;	mpf = dbp->mpf;	internal = dbc->internal;	ret = 0;	/* Discard any pages we're holding. */	if (internal->page != NULL) {		if ((t_ret = mpf->put(mpf, internal->page, 0)) != 0 && ret == 0)			ret = t_ret;		internal->page = NULL;	}	opd = internal->opd;	if (opd != NULL && opd->internal->page != NULL) {		if ((t_ret =		    mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)			ret = t_ret;		 opd->internal->page = NULL;	}	/*	 * If dbc_n is NULL, there's no internal cursor swapping to be done	 * and no dbc_n to close--we probably did the entire operation on an	 * offpage duplicate cursor.  Just return.	 *	 * If dbc and dbc_n are the same, we're either inside a DB->{put/get}	 * operation, and as an optimization we performed the operation on	 * the main cursor rather than on a duplicated one, or we're in a	 * bulk get that can't have moved the cursor (DB_MULTIPLE with the	 * initial c_get operation on an off-page dup cursor).  Just	 * return--either we know we didn't move the cursor, or we're going	 * to close it before we return to application code, so we're sure	 * not to visibly violate the "cursor stays put on error" rule.	 */	if (dbc_n == NULL || dbc == dbc_n)		return (ret);	if (dbc_n->internal->page != NULL) {		if ((t_ret =		    mpf->put(mpf, dbc_n->internal->page, 0)) != 0 && ret == 0)			ret = t_ret;		dbc_n->internal->page = NULL;	}	opd = dbc_n->internal->opd;	if (opd != NULL && opd->internal->page != NULL) {		if ((t_ret =		    mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)			ret = t_ret;		opd->internal->page = NULL;	}	/*	 * If we didn't fail before entering this routine or just now when	 * freeing pages, swap the interesting contents of the old and new	 * cursors.	 */	if (!failed && ret == 0) {		dbc->internal = dbc_n->internal;		dbc_n->internal = internal;	}	/*	 * Close the cursor we don't care about anymore.  The close can fail,	 * but we only expect DB_LOCK_DEADLOCK failures.  This violates our	 * "the cursor is unchanged on error" semantics, but since all you can	 * do with a DB_LOCK_DEADLOCK failure is close the cursor, I believe	 * that's OK.	 *	 * XXX	 * There's no way to recover from failure to close the old cursor.	 * All we can do is move to the new position and return an error.	 *	 * XXX	 * We might want to consider adding a flag to the cursor, so that any	 * subsequent operations other than close just return an error?	 */	if ((t_ret = dbc_n->c_close(dbc_n)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* * __db_c_secondary_get -- *	This wrapper function for DBC->c_pget() is the DBC->c_get() function *	for a secondary index cursor. * * PUBLIC: int __db_c_secondary_get __P((DBC *, DBT *, DBT *, u_int32_t)); */int__db_c_secondary_get(dbc, skey, data, flags)	DBC *dbc;	DBT *skey, *data;	u_int32_t flags;{	DB_ASSERT(F_ISSET(dbc->dbp, DB_AM_SECONDARY));	return (dbc->c_pget(dbc, skey, NULL, data, flags));}/* * __db_c_pget -- *	Get a primary key/data pair through a secondary index. * * PUBLIC: int __db_c_pget __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); */int__db_c_pget(dbc, skey, pkey, data, flags)	DBC *dbc;	DBT *skey, *pkey, *data;	u_int32_t flags;{	DB *pdbp, *sdbp;	DBC *pdbc;	DBT *save_rdata, nullpkey;	int pkeymalloc, ret, save_pkey_flags, t_ret;	sdbp = dbc->dbp;	pdbp = sdbp->s_primary;	pkeymalloc = t_ret = 0;	PANIC_CHECK(sdbp->dbenv);	if ((ret = __db_cpgetchk(sdbp,	    skey, pkey, data, flags, IS_INITIALIZED(dbc))) != 0)		return (ret);	/*	 * The challenging part of this function is getting the behavior	 * right for all the various permutations of DBT flags.  The	 * next several blocks handle the various cases we need to	 * deal with specially.	 */	/*	 * We may be called with a NULL pkey argument, if we've been	 * wrapped by a 2-DBT get call.  If so, we need to use our	 * own DBT.	 */	if (pkey == NULL) {		memset(&nullpkey, 0, sizeof(DBT));		pkey = &nullpkey;	}	/*	 * DB_GET_RECNO is a special case, because we're interested not in	 * the primary key/data pair, but rather in the primary's record	 * number.	 */	if ((flags & DB_OPFLAGS_MASK) == DB_GET_RECNO)		return (__db_c_pget_recno(dbc, pkey, data, flags));	/*	 * If the DBTs we've been passed don't have any of the	 * user-specified memory management flags set, we want to make sure	 * we return values using the DBTs dbc->rskey, dbc->rkey, and	 * dbc->rdata, respectively.	 *	 * There are two tricky aspects to this:  first, we need to pass	 * skey and pkey *in* to the initial c_get on the secondary key,	 * since either or both may be looked at by it (depending on the	 * get flag).  Second, we must not use a normal DB->get call	 * on the secondary, even though that's what we want to accomplish,	 * because the DB handle may be free-threaded.  Instead,	 * we open a cursor, then take steps to ensure that we actually use	 * the rkey/rdata from the *secondary* cursor.	 *	 * We accomplish all this by passing in the DBTs we started out	 * with to the c_get, but having swapped the contents of rskey and	 * rkey, respectively, into rkey and rdata;  __db_ret will treat	 * them like the normal key/data pair in a c_get call, and will	 * realloc them as need be (this is "step 1").  Then, for "step 2",	 * we swap back rskey/rkey/rdata to normal, and do a get on the primary	 * with the secondary dbc appointed as the owner of the returned-data	 * memory.	 *	 * Note that in step 2, we copy the flags field in case we need to	 * pass down a DB_DBT_PARTIAL or other flag that is compatible with	 * letting DB do the memory management.	 */	/* Step 1. */	save_rdata = dbc->rdata;	dbc->rdata = dbc->rkey;	dbc->rkey = dbc->rskey;	/*	 * It is correct, though slightly sick, to attempt a partial get	 * of a primary key.  However, if we do so here, we'll never find the	 * primary record;  clear the DB_DBT_PARTIAL field of pkey just	 * for the duration of the next call.	 */	save_pkey_flags = pkey->flags;	F_CLR(pkey, DB_DBT_PARTIAL);	/*	 * Now we can go ahead with the meat of this call.  First, get the	 * primary key from the secondary index.  (What exactly we get depends	 * on the flags, but the underlying cursor get will take care of the	 * dirty work.)	 */	if ((ret = dbc->c_real_get(dbc, skey, pkey, flags)) != 0) {		/* Restore rskey/rkey/rdata and return. */		pkey->flags = save_pkey_flags;		dbc->rskey = dbc->rkey;		dbc->rkey = dbc->rdata;		dbc->rdata = save_rdata;		goto err;	}	/* Restore pkey's flags in case we stomped the PARTIAL flag. */	pkey->flags = save_pkey_flags;	/*	 * Restore the cursor's rskey, rkey, and rdata DBTs.  If DB	 * is handling the memory management, we now have newly	 * reallocated buffers and ulens in rkey and rdata which we want	 * to put in rskey and rkey.  save_rdata contains the old value	 * of dbc->rdata.	 */	dbc->rskey = dbc->rkey;	dbc->rkey = dbc->rdata;	dbc->rdata = save_rdata;	/*	 * Now we're ready for "step 2".  If either or both of pkey and	 * data do not have memory management flags set--that is, if DB is	 * managing their memory--we need to swap around the rkey/rdata	 * structures so that we don't wind up trying to use memory managed	 * by the primary database cursor, which we'll close before we return.	 *	 * !!!	 * If you're carefully following the bouncing ball, you'll note	 * that in the DB-managed case, the buffer hanging off of pkey is	 * the same as dbc->rkey->data.  This is just fine;  we may well	 * realloc and stomp on it when we return, if we're going a	 * DB_GET_BOTH and need to return a different partial or key	 * (depending on the comparison function), but this is safe.	 *	 * !!!	 * We need to use __db_icursor here rather than simply calling	 * pdbp->cursor, because otherwise, if we're in CDB, we'll	 * allocate a new locker ID and leave ourselves open to deadlocks.	 * (Even though we're only acquiring read locks, we'll still block	 * if there are any waiters.)	 */	if ((ret = __db_icursor(pdbp,	    dbc->txn, pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)		goto err;	/*	 * We're about to use pkey a second time.  If DB_DBT_MALLOC	 * is set on it, we'll leak the memory we allocated the first time.	 * Thus, set DB_DBT_REALLOC instead so that we reuse that memory	 * instead of leaking it.	 *	 * !!!	 * This assumes that the user must always specify a compatible	 * realloc function if a malloc function is specified.  I think	 * this is a reasonable requirement.	 */	if (F_ISSET(pkey, DB_DBT_MALLOC)) {		F_CLR(pkey, DB_DBT_MALLOC);		F_SET(pkey, DB_DBT_REALLOC);		pkeymalloc = 1;	}	/*	 * Do the actual get.  Set DBC_TRANSIENT since we don't care	 * about preserving the position on error, and it's faster.	 * SET_RET_MEM so that the secondary DBC owns any returned-data	 * memory.	 */	F_SET(pdbc, DBC_TRANSIENT);	SET_RET_MEM(pdbc, dbc);	ret = pdbc->c_get(pdbc, pkey, data, DB_SET);	/*	 * If the item wasn't found in the primary, this is a bug;	 * our secondary has somehow gotten corrupted, and contains	 * elements that don't correspond to anything in the primary.	 * Complain.	 */	if (ret == DB_NOTFOUND)		ret = __db_secondary_corrupt(pdbp);	/* Now close the primary cursor. */	t_ret = pdbc->c_close(pdbc);err:	if (pkeymalloc) {		/*		 * If pkey had a MALLOC flag, we need to restore it;		 * otherwise, if the user frees the buffer but reuses		 * the DBT without NULL'ing its data field or changing		 * the flags, we may drop core.		 */		F_CLR(pkey, DB_DBT_REALLOC);		F_SET(pkey, DB_DBT_MALLOC);	}	return (t_ret == 0 ? ret : t_ret);}/* * __db_c_pget_recno -- *	Perform a DB_GET_RECNO c_pget on a secondary index.  Returns * the secondary's record number in the pkey field and the primary's * in the data field. */static int__db_c_pget_recno(sdbc, pkey, data, flags)	DBC *sdbc;	DBT *pkey, *data;	u_int32_t flags;{	DB *pdbp, *sdbp;	DB_ENV *dbenv;	DBC *pdbc;	DBT discardme, primary_key;	db_recno_t oob;	u_int32_t rmw;

⌨️ 快捷键说明

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