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

📄 db_join.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
					 * that cursor is sorted, then any					 * other sorted cursors can be safely					 * reset to the first duplicate					 * duplicate in the current set if we					 * have a pointer to it (we can't just					 * leave them be, or we'll miss					 * duplicate duplicates in the outer					 * relation).					 *					 * If the first cursor is unsorted, or					 * if cursor j is unsorted, we can					 * make no assumptions about what					 * we're looking for next or where it					 * will be, so we reset to the very					 * beginning (setting workcurs NULL					 * will achieve this next go-round).					 *					 * XXX: This is likely to break					 * horribly if any two cursors are					 * both sorted, but have different					 * specified sort functions.  For,					 * now, we dismiss this as pathology					 * and let strange things happen--we					 * can't make rope childproof.					 */					if ((ret = jc->j_workcurs[j]->c_close(					    jc->j_workcurs[j])) != 0)						goto err;					if (!SORTED_SET(jc, 0) ||					    !SORTED_SET(jc, j) ||					    jc->j_fdupcurs[j] == NULL)						/*						 * Unsafe conditions;						 * reset fully.						 */						jc->j_workcurs[j] = NULL;					else						/* Partial reset suffices. */						if ((jc->j_fdupcurs[j]->c_dup(						    jc->j_fdupcurs[j],						    &jc->j_workcurs[j],						    DB_POSITIONI)) != 0)							goto err;					jc->j_exhausted[j] = 0;				}				goto retry;				/* NOTREACHED */			}			/*			 * We're about to advance the cursor and need to			 * reset all of the workcurs[j] where j>i, so that			 * we don't miss any duplicate duplicates.			 */			for (j = i + 1;			    jc->j_workcurs[j] != NULL;			    j++) {				if ((ret = jc->j_workcurs[j]->c_close(				    jc->j_workcurs[j])) != 0)					goto err;				jc->j_exhausted[j] = 0;				if (jc->j_fdupcurs[j] != NULL &&				    (ret = jc->j_fdupcurs[j]->c_dup(				    jc->j_fdupcurs[j], &jc->j_workcurs[j],				    DB_POSITIONI)) != 0)					goto err;				else					jc->j_workcurs[j] = NULL;			}			goto retry2;			/* NOTREACHED */		}		if (ret == ENOMEM) {			jc->j_key.ulen <<= 1;			if ((ret = __os_realloc(dbp->dbenv, jc->j_key.ulen,			    &jc->j_key.data)) != 0) {mem_err:			__db_err(dbp->dbenv,				    "Allocation failed for join key, len = %lu",				    (u_long)jc->j_key.ulen);				goto err;			}			goto retry2;		}		if (ret != 0)			goto err;		/*		 * If we made it this far, we've found a matching		 * datum in cursor i.  Mark the current cursor		 * unexhausted, so we don't miss any duplicate		 * duplicates the next go-round--unless this is the		 * very last cursor, in which case there are none to		 * miss, and we'll need that exhausted flag to finally		 * get a DB_NOTFOUND and move on to the next datum in		 * the outermost cursor.		 */		if (i + 1 != jc->j_ncurs)			jc->j_exhausted[i] = 0;		else			jc->j_exhausted[i] = 1;		/*		 * If jc->j_fdupcurs[i] is NULL and the ith cursor's dups are		 * sorted, then we're here for the first time since advancing		 * cursor 0, and we have a new datum of interest.		 * jc->j_workcurs[i] points to the beginning of a set of		 * duplicate duplicates;  store this into jc->j_fdupcurs[i].		 */		if (SORTED_SET(jc, i) && jc->j_fdupcurs[i] == NULL && (ret =		    cp->c_dup(cp, &jc->j_fdupcurs[i], DB_POSITIONI)) != 0)			goto err;	}err:	if (ret != 0)		return (ret);	if (0) {samekey:	/*		 * Get the key we tried and failed to return last time;		 * it should be the current datum of all the secondary cursors.		 */		if ((ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],		    &jc->j_key, key_n, DB_CURRENT | opmods)) != 0)			return (ret);		F_CLR(jc, JOIN_RETRY);	}	/*	 * ret == 0;  we have a key to return.	 *	 * If DB_DBT_USERMEM or DB_DBT_MALLOC is set, we need to copy the key	 * back into the dbt we were given for the key; call __db_retcopy.	 * Otherwise, assert that we do not need to copy anything and proceed.	 */	DB_ASSERT(F_ISSET(	    key_arg, DB_DBT_USERMEM | DB_DBT_MALLOC) || key_n == key_arg);	if (F_ISSET(key_arg, DB_DBT_USERMEM | DB_DBT_MALLOC) &&	    (ret = __db_retcopy(dbp->dbenv,	    key_arg, key_n->data, key_n->size, NULL, NULL)) != 0) {		/*		 * The retcopy failed, most commonly because we have a user		 * buffer for the key which is too small. Set things up to		 * retry next time, and return.		 */		F_SET(jc, JOIN_RETRY);		return (ret);	}	/*	 * If DB_JOIN_ITEM is set, we return it; otherwise we do the lookup	 * in the primary and then return.	 *	 * Note that we use key_arg here;  it is safe (and appropriate)	 * to do so.	 */	if (operation == DB_JOIN_ITEM)		return (0);	/*	 * If data_arg->flags == 0--that is, if DB is managing the	 * data DBT's memory--it's not safe to just pass the DBT	 * through to the primary get call, since we don't want that	 * memory to belong to the primary DB handle (and if the primary	 * is free-threaded, it can't anyway).	 *	 * Instead, use memory that is managed by the join cursor, in	 * jc->j_rdata.	 */	if (!F_ISSET(data_arg, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM))		db_manage_data = 1;	else		db_manage_data = 0;	if ((ret = __db_join_primget(jc->j_primary,	    jc->j_curslist[0]->txn, jc->j_curslist[0]->locker, key_arg,	    db_manage_data ? &jc->j_rdata : data_arg, opmods)) != 0) {		if (ret == DB_NOTFOUND)			/*			 * If ret == DB_NOTFOUND, the primary and secondary			 * are out of sync;  every item in each secondary			 * should correspond to something in the primary,			 * or we shouldn't have done the join this way.			 * Wail.			 */			ret = __db_secondary_corrupt(jc->j_primary);		else			/*			 * The get on the primary failed for some other			 * reason, most commonly because we're using a user			 * buffer that's not big enough.  Flag our failure			 * so we can return the same key next time.			 */			F_SET(jc, JOIN_RETRY);	}	if (db_manage_data && ret == 0) {		data_arg->data = jc->j_rdata.data;		data_arg->size = jc->j_rdata.size;	}	return (ret);}static int__db_join_close(dbc)	DBC *dbc;{	DB *dbp;	DB_ENV *dbenv;	JOIN_CURSOR *jc;	int ret, t_ret;	u_int32_t i;	jc = (JOIN_CURSOR *)dbc->internal;	dbp = dbc->dbp;	dbenv = dbp->dbenv;	ret = t_ret = 0;	/*	 * Remove from active list of join cursors.  Note that this	 * must happen before any action that can fail and return, or else	 * __db_close may loop indefinitely.	 */	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);	TAILQ_REMOVE(&dbp->join_queue, dbc, links);	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);	PANIC_CHECK(dbenv);	/*	 * Close any open scratch cursors.  In each case, there may	 * not be as many outstanding as there are cursors in	 * curslist, but we want to close whatever's there.	 *	 * If any close fails, there's no reason not to close everything else;	 * we'll just return the error code of the last one to fail.  There's	 * not much the caller can do anyway, since these cursors only exist	 * hanging off a db-internal data structure that they shouldn't be	 * mucking with.	 */	for (i = 0; i < jc->j_ncurs; i++) {		if (jc->j_workcurs[i] != NULL && (t_ret =		    jc->j_workcurs[i]->c_close(jc->j_workcurs[i])) != 0)			ret = t_ret;		if (jc->j_fdupcurs[i] != NULL && (t_ret =		    jc->j_fdupcurs[i]->c_close(jc->j_fdupcurs[i])) != 0)			ret = t_ret;	}	__os_free(dbenv, jc->j_exhausted);	__os_free(dbenv, jc->j_curslist);	__os_free(dbenv, jc->j_workcurs);	__os_free(dbenv, jc->j_fdupcurs);	__os_free(dbenv, jc->j_key.data);	if (jc->j_rdata.data != NULL)		__os_ufree(dbenv, jc->j_rdata.data);	__os_free(dbenv, jc);	__os_free(dbenv, dbc);	return (ret);}/* * __db_join_getnext -- *	This function replaces the DBC_CONTINUE and DBC_KEYSET *	functionality inside the various cursor get routines. * *	If exhausted == 0, we're not done with the current datum; *	return it if it matches "matching", otherwise search *	using DB_GET_BOTHC (which is faster than iteratively doing *	DB_NEXT_DUP) forward until we find one that does. * *	If exhausted == 1, we are done with the current datum, so just *	leap forward to searching NEXT_DUPs. * *	If no matching datum exists, returns DB_NOTFOUND, else 0. */static int__db_join_getnext(dbc, key, data, exhausted, opmods)	DBC *dbc;	DBT *key, *data;	u_int32_t exhausted, opmods;{	int ret, cmp;	DB *dbp;	DBT ldata;	int (*func) __P((DB *, const DBT *, const DBT *));	dbp = dbc->dbp;	func = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare;	switch (exhausted) {	case 0:		/*		 * We don't want to step on data->data;  use a new		 * DBT and malloc so we don't step on dbc's rdata memory.		 */		memset(&ldata, 0, sizeof(DBT));		F_SET(&ldata, DB_DBT_MALLOC);		if ((ret = dbc->c_real_get(dbc,		    key, &ldata, opmods | DB_CURRENT)) != 0)			break;		cmp = func(dbp, data, &ldata);		if (cmp == 0) {			/*			 * We have to return the real data value.  Copy			 * it into data, then free the buffer we malloc'ed			 * above.			 */			if ((ret = __db_retcopy(dbp->dbenv, data, ldata.data,			    ldata.size, &data->data, &data->size)) != 0)				return (ret);			__os_ufree(dbp->dbenv, ldata.data);			return (0);		}		/*		 * Didn't match--we want to fall through and search future		 * dups.  We just forget about ldata and free		 * its buffer--data contains the value we're searching for.		 */		__os_ufree(dbp->dbenv, ldata.data);		/* FALLTHROUGH */	case 1:		ret = dbc->c_real_get(dbc, key, data, opmods | DB_GET_BOTHC);		break;	default:		ret = EINVAL;		break;	}	return (ret);}/* * __db_join_cmp -- *	Comparison function for sorting DBCs in cardinality order. */static int__db_join_cmp(a, b)	const void *a, *b;{	DBC *dbca, *dbcb;	db_recno_t counta, countb;	/* In case c_count fails, pretend cursors are equal. */	counta = countb = 0;	dbca = *((DBC * const *)a);	dbcb = *((DBC * const *)b);	if (dbca->c_count(dbca, &counta, 0) != 0 ||	    dbcb->c_count(dbcb, &countb, 0) != 0)		return (0);	return (counta - countb);}/* * __db_join_primget -- *	Perform a DB->get in the primary, being careful not to use a new * locker ID if we're doing CDB locking. */static int__db_join_primget(dbp, txn, lockerid, key, data, flags)	DB *dbp;	DB_TXN *txn;	u_int32_t lockerid;	DBT *key, *data;	u_int32_t flags;{	DBC *dbc;	int dirty, ret, rmw, t_ret;	/*	 * The only allowable flags here are the two flags copied into	 * "opmods" in __db_join_get, DB_RMW and DB_DIRTY_READ.  The former	 * is an op on the c_get call, the latter on the cursor call.	 * It's a DB bug if we allow any other flags down in here.	 */	rmw = LF_ISSET(DB_RMW);	dirty = LF_ISSET(DB_DIRTY_READ);	LF_CLR(DB_RMW | DB_DIRTY_READ);	DB_ASSERT(flags == 0);	if ((ret = __db_icursor(dbp,	    txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)		return (ret);	if (dirty ||	    (txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))		F_SET(dbc, DBC_DIRTY_READ);	F_SET(dbc, DBC_TRANSIENT);	/*	 * This shouldn't be necessary, thanks to the fact that join cursors	 * swap in their own DB_DBT_REALLOC'ed buffers, but just for form's	 * sake, we mirror what __db_get does.	 */	SET_RET_MEM(dbc, dbp);	ret = dbc->c_get(dbc, key, data, DB_SET | rmw);	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)		ret = t_ret;	return (ret);}

⌨️ 快捷键说明

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