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

📄 db_am.c

📁 File system using stacked.
💻 C
📖 第 1 页 / 共 3 页
字号:
	DB_FH *fhp;	int ret;	PANIC_CHECK(dbp->dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->fd");	/*	 * XXX	 * Truly spectacular layering violation.	 */	if ((ret = __mp_xxx_fh(dbp->mpf, &fhp)) != 0)		return (ret);	if (F_ISSET(fhp, DB_FH_VALID)) {		*fdp = fhp->fd;		return (0);	} else {#ifdef KBDB		*fdp = NULL;#else		*fdp = -1;#endif		__db_err(dbp->dbenv, "DB does not have a valid file handle");		return (ENOENT);	}}/* * __db_get -- *	Return a key/data pair. * * PUBLIC: int __db_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); */int__db_get(dbp, txn, key, data, flags)	DB *dbp;	DB_TXN *txn;	DBT *key, *data;	u_int32_t flags;{	DBC *dbc;	int mode, ret, t_ret;	PANIC_CHECK(dbp->dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get");	if ((ret = __db_getchk(dbp, key, data, flags)) != 0)		return (ret);	/* Check for consistent transaction usage. */	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)		return (ret);	mode = 0;	if (LF_ISSET(DB_DIRTY_READ)) {		mode = DB_DIRTY_READ;		LF_CLR(DB_DIRTY_READ);	}	else if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)		mode = DB_WRITELOCK;	if ((ret = dbp->cursor(dbp, txn, &dbc, mode)) != 0)		return (ret);	DEBUG_LREAD(dbc, txn, "__db_get", key, NULL, flags);	/*	 * The DBC_TRANSIENT flag indicates that we're just doing a	 * single operation with this cursor, and that in case of	 * error we don't need to restore it to its old position--we're	 * going to close it right away.  Thus, we can perform the get	 * without duplicating the cursor, saving some cycles in this	 * common case.	 *	 * SET_RET_MEM indicates that if key and/or data have no DBT	 * flags set and DB manages the returned-data memory, that memory	 * will belong to this handle, not to the underlying cursor.	 */	F_SET(dbc, DBC_TRANSIENT);	SET_RET_MEM(dbc, dbp);	if (LF_ISSET(~(DB_RMW | DB_MULTIPLE)) == 0)		LF_SET(DB_SET);	ret = dbc->c_get(dbc, key, data, flags);	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* * __db_put -- *	Store a key/data pair. * * PUBLIC: int __db_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); */int__db_put(dbp, txn, key, data, flags)	DB *dbp;	DB_TXN *txn;	DBT *key, *data;	u_int32_t flags;{	DBC *dbc;	DBT tdata;	DB_ENV *dbenv;	int ret, t_ret, txn_local;	dbc = NULL;	dbenv = dbp->dbenv;	txn_local = 0;	PANIC_CHECK(dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->put");	/* Validate arguments. */	if ((ret = __db_putchk(dbp, key, data,	    flags, F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) != 0)		return (ret);	/* Create local transaction as necessary. */	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {		if ((ret = __db_txn_auto(dbp, &txn)) != 0)			return (ret);		txn_local = 1;		LF_CLR(DB_AUTO_COMMIT);	}	/* Check for consistent transaction usage. */	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)		goto err;	if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)		goto err;	DEBUG_LWRITE(dbc, txn, "db_put", key, data, flags);	SET_RET_MEM(dbc, dbp);	/*	 * See the comment in __db_get().	 *	 * Note that the c_get in the DB_NOOVERWRITE case is safe to	 * do with this flag set;  if it errors in any way other than	 * DB_NOTFOUND, we're going to close the cursor without doing	 * anything else, and if it returns DB_NOTFOUND then it's safe	 * to do a c_put(DB_KEYLAST) even if an access method moved the	 * cursor, since that's not position-dependent.	 */	F_SET(dbc, DBC_TRANSIENT);	switch (flags) {	case DB_APPEND:		/*		 * If there is an append callback, the value stored in		 * data->data may be replaced and then freed.  To avoid		 * passing a freed pointer back to the user, just operate		 * on a copy of the data DBT.		 */		tdata = *data;		/*		 * Append isn't a normal put operation;  call the appropriate		 * access method's append function.		 */		switch (dbp->type) {		case DB_QUEUE:			if ((ret = __qam_append(dbc, key, &tdata)) != 0)				goto err;			break;		case DB_RECNO:			if ((ret = __ram_append(dbc, key, &tdata)) != 0)				goto err;			break;		default:			/* The interface should prevent this. */			DB_ASSERT(0);			ret = __db_ferr(dbenv, "__db_put", flags);			goto err;		}		/*		 * Secondary indices:  since we've returned zero from		 * an append function, we've just put a record, and done		 * so outside __db_c_put.  We know we're not a secondary--		 * the interface prevents puts on them--but we may be a		 * primary.  If so, update our secondary indices		 * appropriately.		 */		DB_ASSERT(!F_ISSET(dbp, DB_AM_SECONDARY));		if (LIST_FIRST(&dbp->s_secondaries) != NULL)			ret = __db_append_primary(dbc, key, &tdata);		/*		 * The append callback, if one exists, may have allocated		 * a new tdata.data buffer.  If so, free it.		 */		FREE_IF_NEEDED(dbp, &tdata);		/* No need for a cursor put;  we're done. */		goto err;	case DB_NOOVERWRITE:		flags = 0;		/*		 * Set DB_DBT_USERMEM, this might be a threaded application and		 * the flags checking will catch us.  We don't want the actual		 * data, so request a partial of length 0.		 */		memset(&tdata, 0, sizeof(tdata));		F_SET(&tdata, DB_DBT_USERMEM | DB_DBT_PARTIAL);		/*		 * If we're doing page-level locking, set the read-modify-write		 * flag, we're going to overwrite immediately.		 */		if ((ret = dbc->c_get(dbc, key, &tdata,		    DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0))) == 0)			ret = DB_KEYEXIST;		else if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)			ret = 0;		break;	default:		/* Fall through to normal cursor put. */		break;	}	if (ret == 0)		ret = dbc->c_put(dbc,		    key, data, flags == 0 ? DB_KEYLAST : flags);err:	/* Close the cursor. */	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)		ret = t_ret;	/* Commit for DB_AUTO_COMMIT. */	if (txn_local) {		if (ret == 0)			ret = txn->commit(txn, 0);		else			if ((t_ret = txn->abort(txn)) != 0)				ret = __db_panic(dbenv, t_ret);	}	return (ret);}/* * __db_delete -- *	Delete the items referenced by a key. * * PUBLIC: int __db_delete __P((DB *, DB_TXN *, DBT *, u_int32_t)); */int__db_delete(dbp, txn, key, flags)	DB *dbp;	DB_TXN *txn;	DBT *key;	u_int32_t flags;{	DBC *dbc;	DBT data, lkey;	DB_ENV *dbenv;	u_int32_t f_init, f_next;	int ret, t_ret, txn_local;	dbc = NULL;	dbenv = dbp->dbenv;	txn_local = 0;	PANIC_CHECK(dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");	/* Check for invalid flags. */	if ((ret = __db_delchk(dbp, key, flags)) != 0)		return (ret);	/* Create local transaction as necessary. */	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {		if ((ret = __db_txn_auto(dbp, &txn)) != 0)			return (ret);		txn_local = 1;		LF_CLR(DB_AUTO_COMMIT);	}	/* Check for consistent transaction usage. */	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)		goto err;	/* Allocate a cursor. */	if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)		goto err;	DEBUG_LWRITE(dbc, txn, "db_delete", key, NULL, flags);	/*	 * Walk a cursor through the key/data pairs, deleting as we go.  Set	 * the DB_DBT_USERMEM flag, as this might be a threaded application	 * and the flags checking will catch us.  We don't actually want the	 * keys or data, so request a partial of length 0.	 */	memset(&lkey, 0, sizeof(lkey));	F_SET(&lkey, DB_DBT_USERMEM | DB_DBT_PARTIAL);	memset(&data, 0, sizeof(data));	F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);	/*	 * If locking (and we haven't already acquired CDB locks), set the	 * read-modify-write flag.	 */	f_init = DB_SET;	f_next = DB_NEXT_DUP;	if (STD_LOCKING(dbc)) {		f_init |= DB_RMW;		f_next |= DB_RMW;	}	/* Walk through the set of key/data pairs, deleting as we go. */	if ((ret = dbc->c_get(dbc, key, &data, f_init)) != 0)		goto err;	/*	 * Hash permits an optimization in DB->del:  since on-page	 * duplicates are stored in a single HKEYDATA structure, it's	 * possible to delete an entire set of them at once, and as	 * the HKEYDATA has to be rebuilt and re-put each time it	 * changes, this is much faster than deleting the duplicates	 * one by one.  Thus, if we're not pointing at an off-page	 * duplicate set, and we're not using secondary indices (in	 * which case we'd have to examine the items one by one anyway),	 * let hash do this "quick delete".	 *	 * !!!	 * Note that this is the only application-executed delete call in	 * Berkeley DB that does not go through the __db_c_del function.	 * If anything other than the delete itself (like a secondary index	 * update) has to happen there in a particular situation, the	 * conditions here should be modified not to call __ham_quick_delete.	 * The ordinary AM-independent alternative will work just fine with	 * a hash;  it'll just be slower.	 */	if (dbp->type == DB_HASH) {		if (LIST_FIRST(&dbp->s_secondaries) == NULL &&		    !F_ISSET(dbp, DB_AM_SECONDARY) &&		    dbc->internal->opd == NULL) {			ret = __ham_quick_delete(dbc);			goto err;		}	}	for (;;) {		if ((ret = dbc->c_del(dbc, 0)) != 0)			goto err;		if ((ret = dbc->c_get(dbc, &lkey, &data, f_next)) != 0) {			if (ret == DB_NOTFOUND) {				ret = 0;				break;			}			goto err;		}	}err:	/* Discard the cursor. */	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)		ret = t_ret;	/* Commit for DB_AUTO_COMMIT. */	if (txn_local) {		if (ret == 0)			ret = txn->commit(txn, 0);		else			if ((t_ret = txn->abort(txn)) != 0)				ret = __db_panic(dbenv, t_ret);	}	return (ret);}/* * __db_sync -- *	Flush the database cache. * * PUBLIC: int __db_sync __P((DB *, u_int32_t)); */int__db_sync(dbp, flags)	DB *dbp;	u_int32_t flags;{	int ret, t_ret;	PANIC_CHECK(dbp->dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync");	if ((ret = __db_syncchk(dbp, flags)) != 0)		return (ret);	/* Read-only trees never need to be sync'd. */	if (F_ISSET(dbp, DB_AM_RDONLY))		return (0);	/* If it's a Recno tree, write the backing source text file. */	if (dbp->type == DB_RECNO)		ret = __ram_writeback(dbp);	/* If the tree was never backed by a database file, we're done. */	if (F_ISSET(dbp, DB_AM_INMEM))		return (0);	/* Flush any dirty pages from the cache to the backing file. */	if ((t_ret = dbp->mpf->sync(dbp->mpf)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* * __db_associate -- *	Associate another database as a secondary index to this one. * * PUBLIC: int __db_associate __P((DB *, DB_TXN *, DB *, * PUBLIC:     int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); */int__db_associate(dbp, txn, sdbp, callback, flags)	DB *dbp, *sdbp;	DB_TXN *txn;	int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));

⌨️ 快捷键说明

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