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

📄 db_cam.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
	int ret, t_ret;	sdbp = sdbc->dbp;	pdbp = sdbp->s_primary;	dbenv = sdbp->dbenv;	pdbc = NULL;	ret = t_ret = 0;	rmw = LF_ISSET(DB_RMW);	memset(&discardme, 0, sizeof(DBT));	F_SET(&discardme, DB_DBT_USERMEM | DB_DBT_PARTIAL);	oob = RECNO_OOB;	/*	 * If the primary is an rbtree, we want its record number, whether	 * or not the secondary is one too.  Fetch the recno into "data".	 *	 * If it's not an rbtree, return RECNO_OOB in "data".	 */	if (F_ISSET(pdbp, DB_AM_RECNUM)) {		/*		 * Get the primary key, so we can find the record number		 * in the primary. (We're uninterested in the secondary key.)		 */		memset(&primary_key, 0, sizeof(DBT));		F_SET(&primary_key, DB_DBT_MALLOC);		if ((ret = sdbc->c_real_get(sdbc,		    &discardme, &primary_key, rmw | DB_CURRENT)) != 0)			return (ret);		/*		 * Open a cursor on the primary, set it to the right record,		 * and fetch its recno into "data".		 *		 * (See __db_c_pget for a comment on the use of __db_icursor.)		 *		 * SET_RET_MEM so that the secondary DBC owns any returned-data		 * memory.		 */		if ((ret = __db_icursor(pdbp, sdbc->txn,		    pdbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)			goto perr;		SET_RET_MEM(pdbc, sdbc);		if ((ret = pdbc->c_get(pdbc,		    &primary_key, &discardme, rmw | DB_SET)) != 0)			goto perr;		ret = pdbc->c_get(pdbc, &discardme, data, rmw | DB_GET_RECNO);perr:		__os_ufree(sdbp->dbenv, primary_key.data);		if (pdbc != NULL &&		    (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)			ret = t_ret;		if (ret != 0)			return (ret);	} else if ((ret = __db_retcopy(dbenv, data, &oob,		    sizeof(oob), &sdbc->rkey->data, &sdbc->rkey->ulen)) != 0)			return (ret);	/*	 * If the secondary is an rbtree, we want its record number, whether	 * or not the primary is one too.  Fetch the recno into "pkey".	 *	 * If it's not an rbtree, return RECNO_OOB in "pkey".	 */	if (F_ISSET(sdbp, DB_AM_RECNUM))		return (sdbc->c_real_get(sdbc, &discardme, pkey, flags));	else		return (__db_retcopy(dbenv, pkey, &oob,		    sizeof(oob), &sdbc->rdata->data, &sdbc->rdata->ulen));}/* * __db_wrlock_err -- do not have a write lock. */static int__db_wrlock_err(dbenv)	DB_ENV *dbenv;{	__db_err(dbenv, "Write attempted on read-only cursor");	return (EPERM);}/* * __db_c_del_secondary -- *	Perform a delete operation on a secondary index:  call through *	to the primary and delete the primary record that this record *	points to. * *	Note that deleting the primary record will call c_del on all *	the secondaries, including this one;  thus, it is not necessary *	to execute both this function and an actual delete. * */static int__db_c_del_secondary(dbc)	DBC *dbc;{	DB *pdbp;	DBC *pdbc;	DBT skey, pkey;	int ret, t_ret;	memset(&skey, 0, sizeof(DBT));	memset(&pkey, 0, sizeof(DBT));	/*	 * Get the current item that we're pointing at.	 * We don't actually care about the secondary key, just	 * the primary.	 */	F_SET(&skey, DB_DBT_PARTIAL | DB_DBT_USERMEM);	if ((ret = dbc->c_real_get(dbc,	    &skey, &pkey, DB_CURRENT)) != 0)		return (ret);	/*	 * Create a cursor on the primary with our locker ID,	 * so that when it calls back, we don't conflict.	 *	 * We create a cursor explicitly because there's no	 * way to specify the same locker ID if we're using	 * locking but not transactions if we use the DB->del	 * interface.  This shouldn't be any less efficient	 * anyway.	 */	pdbp = dbc->dbp->s_primary;	if ((ret = __db_icursor(pdbp, dbc->txn,	    pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)		return (ret);	/*	 * See comment in __db_c_put--if we're in CDB,	 * we already hold the locks we need, and we need to flag	 * the cursor as a WRITER so we don't run into errors	 * when we try to delete.	 */	if (CDB_LOCKING(pdbp->dbenv)) {		DB_ASSERT(pdbc->mylock.off == LOCK_INVALID);		F_SET(pdbc, DBC_WRITER);	}	/*	 * Set the new cursor to the correct primary key.  Then	 * delete it.  We don't really care about the datum;	 * just reuse our skey DBT.	 *	 * If the primary get returns DB_NOTFOUND, something is amiss--	 * every record in the secondary should correspond to some record	 * in the primary.	 */	if ((ret = pdbc->c_get(pdbc, &pkey, &skey,	    (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_SET)) == 0)		ret = pdbc->c_del(pdbc, 0);	else if (ret == DB_NOTFOUND)		ret = __db_secondary_corrupt(pdbp);	if ((t_ret = pdbc->c_close(pdbc)) != 0 && ret != 0)		ret = t_ret;	return (ret);}/* * __db_c_del_primary -- *	Perform a delete operation on a primary index.  Loop through *	all the secondary indices which correspond to this primary *	database, and delete any secondary keys that point at the current *	record. * * PUBLIC: int __db_c_del_primary __P((DBC *)); */int__db_c_del_primary(dbc)	DBC *dbc;{	DB *dbp, *sdbp;	DBC *sdbc;	DBT data, pkey, skey, temp;	int ret, t_ret;	dbp = dbc->dbp;	/*	 * If we're called at all, we have at least one secondary.	 * (Unfortunately, we can't assert this without grabbing the mutex.)	 * Get the current record so that we can construct appropriate	 * secondary keys as needed.	 */	memset(&pkey, 0, sizeof(DBT));	memset(&data, 0, sizeof(DBT));	if ((ret = dbc->c_get(dbc, &pkey, &data, DB_CURRENT)) != 0)		return (ret);	for (sdbp = __db_s_first(dbp);	    sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {		/*		 * Get the secondary key for this secondary and the current		 * item.		 */		memset(&skey, 0, sizeof(DBT));		if ((ret = sdbp->s_callback(sdbp, &pkey, &data, &skey)) != 0) {			/*			 * If the current item isn't in this index, we			 * have no work to do.  Proceed.			 */			if (ret == DB_DONOTINDEX)				continue;			/* We had a substantive error.  Bail. */			FREE_IF_NEEDED(sdbp, &skey);			goto done;		}		/* Open a secondary cursor. */		if ((ret = __db_icursor(sdbp, dbc->txn, sdbp->type,		    PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0)			goto done;		/* See comment above and in __db_c_put. */		if (CDB_LOCKING(sdbp->dbenv)) {			DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);			F_SET(sdbc, DBC_WRITER);		}		/*		 * Set the secondary cursor to the appropriate item.		 * Delete it.		 *		 * We want to use DB_RMW if locking is on;  it's only		 * legal then, though.		 *		 * !!!		 * Don't stomp on any callback-allocated buffer in skey		 * when we do a c_get(DB_GET_BOTH);  use a temp DBT instead.		 */		memset(&temp, 0, sizeof(DBT));		temp.data = skey.data;		temp.size = skey.size;		if ((ret = sdbc->c_real_get(sdbc, &temp, &pkey,		    (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_GET_BOTH)) == 0)			ret = sdbc->c_del(sdbc, DB_UPDATE_SECONDARY);		FREE_IF_NEEDED(sdbp, &skey);		if ((t_ret = sdbc->c_close(sdbc)) != 0 || ret != 0) {			if (ret == 0)				ret = t_ret;			goto done;		}	}done:	if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)		return (t_ret);	return (ret);}/* * __db_s_first -- *	Get the first secondary, if any are present, from the primary. * * PUBLIC: DB *__db_s_first __P((DB *)); */DB *__db_s_first(pdbp)	DB *pdbp;{	DB *sdbp;	MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);	sdbp = LIST_FIRST(&pdbp->s_secondaries);	/* See __db_s_next. */	if (sdbp != NULL)		sdbp->s_refcnt++;	MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);	return (sdbp);}/* * __db_s_next -- *	Get the next secondary in the list. * * PUBLIC: int __db_s_next __P((DB **)); */int__db_s_next(sdbpp)	DB **sdbpp;{	DB *sdbp, *pdbp, *closeme;	int ret;	/*	 * Secondary indices are kept in a linked list, s_secondaries,	 * off each primary DB handle.  If a primary is free-threaded,	 * this list may only be traversed or modified while the primary's	 * thread mutex is held.	 *	 * The tricky part is that we don't want to hold the thread mutex	 * across the full set of secondary puts necessary for each primary	 * put, or we'll wind up essentially single-threading all the puts	 * to the handle;  the secondary puts will each take about as	 * long as the primary does, and may require I/O.  So we instead	 * hold the thread mutex only long enough to follow one link to the	 * next secondary, and then we release it before performing the	 * actual secondary put.	 *	 * The only danger here is that we might legitimately close a	 * secondary index in one thread while another thread is performing	 * a put and trying to update that same secondary index.  To	 * prevent this from happening, we refcount the secondary handles.	 * If close is called on a secondary index handle while we're putting	 * to it, it won't really be closed--the refcount will simply drop,	 * and we'll be responsible for closing it here.	 */	sdbp = *sdbpp;	pdbp = sdbp->s_primary;	closeme = NULL;	MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);	DB_ASSERT(sdbp->s_refcnt != 0);	if (--sdbp->s_refcnt == 0) {		LIST_REMOVE(sdbp, s_links);		closeme = sdbp;	}	sdbp = LIST_NEXT(sdbp, s_links);	if (sdbp != NULL)		sdbp->s_refcnt++;	MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);	*sdbpp = sdbp;	/*	 * closeme->close() is a wrapper;  call __db_close explicitly.	 */	ret = closeme != NULL ? __db_close(closeme, 0) : 0;	return (ret);}/* * __db_s_done -- *	Properly decrement the refcount on a secondary database handle we're *	using, without calling __db_s_next. * * PUBLIC: int __db_s_done __P((DB *)); */int__db_s_done(sdbp)	DB *sdbp;{	DB *pdbp;	int doclose;	pdbp = sdbp->s_primary;	doclose = 0;	MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);	DB_ASSERT(sdbp->s_refcnt != 0);	if (--sdbp->s_refcnt == 0) {		LIST_REMOVE(sdbp, s_links);		doclose = 1;	}	MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);	return (doclose ? __db_close(sdbp, 0) : 0);}/* * __db_buildpartial -- *	Build the record that will result after a partial put is applied to *	an existing record. * *	This should probably be merged with __bam_build, but that requires *	a little trickery if we plan to keep the overflow-record optimization *	in that function. */static int__db_buildpartial(dbp, oldrec, partial, newrec)	DB *dbp;	DBT *oldrec, *partial, *newrec;{	int ret;	u_int8_t *buf;	u_int32_t len, nbytes;	DB_ASSERT(F_ISSET(partial, DB_DBT_PARTIAL));	memset(newrec, 0, sizeof(DBT));	nbytes = __db_partsize(oldrec->size, partial);	newrec->size = nbytes;	if ((ret = __os_malloc(dbp->dbenv, nbytes, &buf)) != 0)		return (ret);	newrec->data = buf;	/* Nul or pad out the buffer, for any part that isn't specified. */	memset(buf,	    F_ISSET(dbp, DB_AM_FIXEDLEN) ? ((BTREE *)dbp->bt_internal)->re_pad :	    0, nbytes);	/* Copy in any leading data from the original record. */	memcpy(buf, oldrec->data,	    partial->doff > oldrec->size ? oldrec->size : partial->doff);	/* Copy the data from partial. */	memcpy(buf + partial->doff, partial->data, partial->size);	/* Copy any trailing data from the original record. */	len = partial->doff + partial->dlen;	if (oldrec->size > len)		memcpy(buf + partial->doff + partial->size,		    (u_int8_t *)oldrec->data + len, oldrec->size - len);	return (0);}/* * __db_partsize -- *	Given the number of bytes in an existing record and a DBT that *	is about to be partial-put, calculate the size of the record *	after the put. * *	This code is called from __bam_partsize. * * PUBLIC: u_int32_t __db_partsize __P((u_int32_t, DBT *)); */u_int32_t__db_partsize(nbytes, data)	u_int32_t nbytes;	DBT *data;{	/*	 * There are really two cases here:	 *	 * Case 1: We are replacing some bytes that do not exist (i.e., they	 * are past the end of the record).  In this case the number of bytes	 * we are replacing is irrelevant and all we care about is how many	 * bytes we are going to add from offset.  So, the new record length	 * is going to be the size of the new bytes (size) plus wherever those	 * new bytes begin (doff).	 *	 * Case 2: All the bytes we are replacing exist.  Therefore, the new	 * size is the oldsize (nbytes) minus the bytes we are replacing (dlen)	 * plus the bytes we are adding (size).	 */	if (nbytes < data->doff + data->dlen)		/* Case 1 */		return (data->doff + data->size);	return (nbytes + data->size - data->dlen);	/* Case 2 */}

⌨️ 快捷键说明

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