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

📄 db.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 *	Sleepycat Software.  All rights reserved. *//* * Copyright (c) 1990, 1993, 1994, 1995, 1996 *	Keith Bostic.  All rights reserved. *//* * Copyright (c) 1990, 1993, 1994, 1995 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: db.c,v 11.300 2004/10/26 17:38:41 bostic Exp $ */#include "db_config.h"#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/db_shash.h"#include "dbinc/db_swap.h"#include "dbinc/btree.h"#include "dbinc/hash.h"#include "dbinc/lock.h"#include "dbinc/log.h"#include "dbinc/mp.h"#include "dbinc/qam.h"#include "dbinc/txn.h"static int __db_disassociate __P((DB *));#ifdef CONFIG_TESTstatic void __db_makecopy __P((DB_ENV *, const char *, const char *));static int  __db_testdocopy __P((DB_ENV *, const char *));static int  __qam_testdocopy __P((DB *, const char *));#endif/* * DB.C -- *	This file contains the utility functions for the DBP layer. *//* * __db_master_open -- *	Open up a handle on a master database. * * PUBLIC: int __db_master_open __P((DB *, * PUBLIC:     DB_TXN *, const char *, u_int32_t, int, DB **)); */int__db_master_open(subdbp, txn, name, flags, mode, dbpp)	DB *subdbp;	DB_TXN *txn;	const char *name;	u_int32_t flags;	int mode;	DB **dbpp;{	DB *dbp;	int ret;	*dbpp = NULL;	/* Open up a handle on the main database. */	if ((ret = db_create(&dbp, subdbp->dbenv, 0)) != 0)		return (ret);	/*	 * It's always a btree.	 * Run in the transaction we've created.	 * Set the pagesize in case we're creating a new database.	 * Flag that we're creating a database with subdatabases.	 */	dbp->pgsize = subdbp->pgsize;	F_SET(dbp, DB_AM_SUBDB);	F_SET(dbp, F_ISSET(subdbp,	    DB_AM_RECOVER | DB_AM_SWAP |	    DB_AM_ENCRYPT | DB_AM_CHKSUM | DB_AM_NOT_DURABLE));	/*	 * If there was a subdb specified, then we only want to apply	 * DB_EXCL to the subdb, not the actual file.  We only got here	 * because there was a subdb specified.	 */	LF_CLR(DB_EXCL);	LF_SET(DB_RDWRMASTER);	if ((ret = __db_open(dbp,	    txn, name, NULL, DB_BTREE, flags, mode, PGNO_BASE_MD)) != 0)		goto err;	/*	 * Verify that pagesize is the same on both.  The items in dbp were now	 * initialized from the meta page.  The items in dbp were set in	 * __db_dbopen when we either read or created the master file.  Other	 * items such as checksum and encryption are checked when we read the	 * meta-page.  So we do not check those here.  However, if the	 * meta-page caused checksumming to be turned on and it wasn't already,	 * set it here.	 */	if (F_ISSET(dbp, DB_AM_CHKSUM))		F_SET(subdbp, DB_AM_CHKSUM);	if (subdbp->pgsize != 0 && dbp->pgsize != subdbp->pgsize) {		ret = EINVAL;		__db_err(dbp->dbenv,		    "Different pagesize specified on existent file");		goto err;	}err:	if (ret != 0 && !F_ISSET(dbp, DB_AM_DISCARD))		(void)__db_close(dbp, txn, 0);	else		*dbpp = dbp;	return (ret);}/* * __db_master_update -- *	Add/Open/Remove a subdatabase from a master database. * * PUBLIC: int __db_master_update __P((DB *, DB *, DB_TXN *, const char *, * PUBLIC:     DBTYPE, mu_action, const char *, u_int32_t)); */int__db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)	DB *mdbp, *sdbp;	DB_TXN *txn;	const char *subdb;	DBTYPE type;	mu_action action;	const char *newname;	u_int32_t flags;{	DB_ENV *dbenv;	DBC *dbc, *ndbc;	DBT key, data, ndata;	PAGE *p, *r;	db_pgno_t t_pgno;	int modify, ret, t_ret;	dbenv = mdbp->dbenv;	dbc = ndbc = NULL;	p = NULL;	memset(&key, 0, sizeof(key));	memset(&data, 0, sizeof(data));	/* Might we modify the master database?  If so, we'll need to lock. */	modify = (action != MU_OPEN || LF_ISSET(DB_CREATE)) ? 1 : 0;	/*	 * Open up a cursor.  If this is CDB and we're creating the database,	 * make it an update cursor.	 */	if ((ret = __db_cursor(mdbp, txn, &dbc,	    (CDB_LOCKING(dbenv) && modify) ? DB_WRITECURSOR : 0)) != 0)		goto err;	/*	 * Point the cursor at the record.	 *	 * If we're removing or potentially creating an entry, lock the page	 * with DB_RMW.	 *	 * We do multiple cursor operations with the cursor in some cases and	 * subsequently access the data DBT information.  Set DB_DBT_MALLOC so	 * we don't risk modification of the data between our uses of it.	 *	 * !!!	 * We don't include the name's nul termination in the database.	 */	key.data = (void *)subdb;	key.size = (u_int32_t)strlen(subdb);	F_SET(&data, DB_DBT_MALLOC);	ret = __db_c_get(dbc, &key, &data,	    DB_SET | ((STD_LOCKING(dbc) && modify) ? DB_RMW : 0));	/*	 * What we do next--whether or not we found a record for the	 * specified subdatabase--depends on what the specified action is.	 * Handle ret appropriately as the first statement of each case.	 */	switch (action) {	case MU_REMOVE:		/*		 * We should have found something if we're removing it.  Note		 * that in the common case where the DB we're asking to remove		 * doesn't exist, we won't get this far;  __db_subdb_remove		 * will already have returned an error from __db_open.		 */		if (ret != 0)			goto err;		/*		 * Delete the subdatabase entry first;  if this fails,		 * we don't want to touch the actual subdb pages.		 */		if ((ret = __db_c_del(dbc, 0)) != 0)			goto err;		/*		 * We're handling actual data, not on-page meta-data,		 * so it hasn't been converted to/from opposite		 * endian architectures.  Do it explicitly, now.		 */		memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t));		DB_NTOHL(&sdbp->meta_pgno);		if ((ret =		    __memp_fget(mdbp->mpf, &sdbp->meta_pgno, 0, &p)) != 0)			goto err;		/* Free the root on the master db. */		if (TYPE(p) == P_BTREEMETA) {			if ((ret = __memp_fget(mdbp->mpf,			     &((BTMETA *)p)->root, 0, &r)) != 0)				goto err;			/* Free and put the page. */			if ((ret = __db_free(dbc, r)) != 0) {				r = NULL;				goto err;			}		}		/* Free and put the page. */		if ((ret = __db_free(dbc, p)) != 0) {			p = NULL;			goto err;		}		p = NULL;		break;	case MU_RENAME:		/* We should have found something if we're renaming it. */		if (ret != 0)			goto err;		/*		 * Before we rename, we need to make sure we're not		 * overwriting another subdatabase, or else this operation		 * won't be undoable.  Open a second cursor and check		 * for the existence of newname;  it shouldn't appear under		 * us since we hold the metadata lock.		 */		if ((ret = __db_cursor(mdbp, txn, &ndbc, 0)) != 0)			goto err;		key.data = (void *)newname;		key.size = (u_int32_t)strlen(newname);		/*		 * We don't actually care what the meta page of the potentially-		 * overwritten DB is;  we just care about existence.		 */		memset(&ndata, 0, sizeof(ndata));		F_SET(&ndata, DB_DBT_USERMEM | DB_DBT_PARTIAL);		if ((ret = __db_c_get(ndbc, &key, &ndata, DB_SET)) == 0) {			/* A subdb called newname exists.  Bail. */			ret = EEXIST;			__db_err(dbenv, "rename: database %s exists", newname);			goto err;		} else if (ret != DB_NOTFOUND)			goto err;		/*		 * Now do the put first;  we don't want to lose our		 * sole reference to the subdb.  Use the second cursor		 * so that the first one continues to point to the old record.		 */		if ((ret = __db_c_put(ndbc, &key, &data, DB_KEYFIRST)) != 0)			goto err;		if ((ret = __db_c_del(dbc, 0)) != 0) {			/*			 * If the delete fails, try to delete the record			 * we just put, in case we're not txn-protected.			 */			(void)__db_c_del(ndbc, 0);			goto err;		}		break;	case MU_OPEN:		/*		 * Get the subdatabase information.  If it already exists,		 * copy out the page number and we're done.		 */		switch (ret) {		case 0:			if (LF_ISSET(DB_CREATE) && LF_ISSET(DB_EXCL)) {				ret = EEXIST;				goto err;			}			memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t));			DB_NTOHL(&sdbp->meta_pgno);			goto done;		case DB_NOTFOUND:			if (LF_ISSET(DB_CREATE))				break;			/*			 * No db_err, it is reasonable to remove a			 * nonexistent db.			 */			ret = ENOENT;			goto err;		default:			goto err;		}		/* Create a subdatabase. */		if ((ret = __db_new(dbc,		    type == DB_HASH ? P_HASHMETA : P_BTREEMETA, &p)) != 0)			goto err;		sdbp->meta_pgno = PGNO(p);		/*		 * XXX		 * We're handling actual data, not on-page meta-data, so it		 * hasn't been converted to/from opposite endian architectures.		 * Do it explicitly, now.		 */		t_pgno = PGNO(p);		DB_HTONL(&t_pgno);		memset(&ndata, 0, sizeof(ndata));		ndata.data = &t_pgno;		ndata.size = sizeof(db_pgno_t);		if ((ret = __db_c_put(dbc, &key, &ndata, DB_KEYLAST)) != 0)			goto err;		F_SET(sdbp, DB_AM_CREATED);		break;	}err:done:	/*	 * If we allocated a page: if we're successful, mark the page dirty	 * and return it to the cache, otherwise, discard/free it.	 */	if (p != NULL) {		if (ret == 0) {			if ((t_ret =			    __memp_fput(mdbp->mpf, p, DB_MPOOL_DIRTY)) != 0)				ret = t_ret;		} else			(void)__memp_fput(mdbp->mpf, p, 0);	}	/* Discard the cursor(s) and data. */	if (data.data != NULL)		__os_ufree(dbenv, data.data);	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)		ret = t_ret;	if (ndbc != NULL && (t_ret = __db_c_close(ndbc)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* * __db_dbenv_setup -- *	Set up the underlying environment during a db_open. * * PUBLIC: int __db_dbenv_setup __P((DB *, * PUBLIC:     DB_TXN *, const char *, u_int32_t, u_int32_t)); */int__db_dbenv_setup(dbp, txn, fname, id, flags)	DB *dbp;	DB_TXN *txn;	const char *fname;	u_int32_t id, flags;{	DB *ldbp;	DB_ENV *dbenv;	DB_MPOOL *dbmp;	u_int32_t maxid;	int ret;	dbenv = dbp->dbenv;	/* If we don't yet have an environment, it's time to create it. */	if (!F_ISSET(dbenv, DB_ENV_OPEN_CALLED)) {		/* Make sure we have at least DB_MINCACHE pages in our cache. */		if (dbenv->mp_gbytes == 0 &&		    dbenv->mp_bytes < dbp->pgsize * DB_MINPAGECACHE &&		    (ret = __memp_set_cachesize(		    dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0)			return (ret);		if ((ret = __dbenv_open(dbenv, NULL, DB_CREATE |		    DB_INIT_MPOOL | DB_PRIVATE | LF_ISSET(DB_THREAD), 0)) != 0)			return (ret);	}	/* Join the underlying cache. */	if ((ret = __db_dbenv_mpool(dbp, fname, flags)) != 0)		return (ret);	/*	 * We may need a per-thread mutex.  Allocate it from the mpool	 * region, there's supposed to be extra space there for that purpose.	 */	if (LF_ISSET(DB_THREAD)) {		dbmp = dbenv->mp_handle;		if ((ret = __db_mutex_setup(dbenv, dbmp->reginfo, &dbp->mutexp,		    MUTEX_ALLOC | MUTEX_THREAD)) != 0)			return (ret);	}	/*	 * Set up a bookkeeping entry for this database in the log region,	 * if such a region exists.  Note that even if we're in recovery	 * or a replication client, where we won't log registries, we'll	 * still need an FNAME struct, so LOGGING_ON is the correct macro.	 */	if (LOGGING_ON(dbenv) &&	    (ret = __dbreg_setup(dbp, fname, id)) != 0)		return (ret);	/*	 * If we're actively logging and our caller isn't a recovery function	 * that already did so, assign this dbp a log fileid.	 */	if (DBENV_LOGGING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER) &&#if !defined(DEBUG_ROP)	    !F_ISSET(dbp, DB_AM_RDONLY) &&#endif

⌨️ 快捷键说明

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