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

📄 mp_bh.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 *	Sleepycat Software.  All rights reserved. * * $Id: mp_bh.c,v 11.99 2004/10/15 16:59:42 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_shash.h"#include "dbinc/mp.h"#include "dbinc/log.h"#include "dbinc/db_page.h"static int __memp_pgwrite	       __P((DB_ENV *, DB_MPOOLFILE *, DB_MPOOL_HASH *, BH *));/* * __memp_bhwrite -- *	Write the page associated with a given buffer header. * * PUBLIC: int __memp_bhwrite __P((DB_MPOOL *, * PUBLIC:      DB_MPOOL_HASH *, MPOOLFILE *, BH *, int)); */int__memp_bhwrite(dbmp, hp, mfp, bhp, open_extents)	DB_MPOOL *dbmp;	DB_MPOOL_HASH *hp;	MPOOLFILE *mfp;	BH *bhp;	int open_extents;{	DB_ENV *dbenv;	DB_MPOOLFILE *dbmfp;	DB_MPREG *mpreg;	int ret;	dbenv = dbmp->dbenv;	/*	 * If the file has been removed or is a closed temporary file, we're	 * done -- the page-write function knows how to handle the fact that	 * we don't have (or need!) any real file descriptor information.	 */	if (mfp->deadfile)		return (__memp_pgwrite(dbenv, NULL, hp, bhp));	/*	 * Walk the process' DB_MPOOLFILE list and find a file descriptor for	 * the file.  We also check that the descriptor is open for writing.	 */	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);	for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);	    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))		if (dbmfp->mfp == mfp && !F_ISSET(dbmfp, MP_READONLY)) {			++dbmfp->ref;			break;		}	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);	if (dbmfp != NULL) {		/*		 * Temporary files may not have been created.  We only handle		 * temporary files in this path, because only the process that		 * created a temporary file will ever flush buffers to it.		 */		if (dbmfp->fhp == NULL) {			/* We may not be allowed to create backing files. */			if (mfp->no_backing_file)				return (EPERM);			MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);			if (dbmfp->fhp == NULL)				ret = __db_appname(dbenv, DB_APP_TMP, NULL,				    F_ISSET(dbenv, DB_ENV_DIRECT_DB) ?				    DB_OSO_DIRECT : 0, &dbmfp->fhp, NULL);			else				ret = 0;			MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);			if (ret != 0) {				__db_err(dbenv,				    "unable to create temporary backing file");				return (ret);			}		}		goto pgwrite;	}	/*	 * There's no file handle for this file in our process.	 *	 * !!!	 * It's the caller's choice if we're going to open extent files.	 */	if (!open_extents && F_ISSET(mfp, MP_EXTENT))		return (EPERM);	/*	 * !!!	 * Don't try to attach to temporary files.  There are two problems in	 * trying to do that.  First, if we have different privileges than the	 * process that "owns" the temporary file, we might create the backing	 * disk file such that the owning process couldn't read/write its own	 * buffers, e.g., memp_trickle running as root creating a file owned	 * as root, mode 600.  Second, if the temporary file has already been	 * created, we don't have any way of finding out what its real name is,	 * and, even if we did, it was already unlinked (so that it won't be	 * left if the process dies horribly).  This decision causes a problem,	 * however: if the temporary file consumes the entire buffer cache,	 * and the owner doesn't flush the buffers to disk, we could end up	 * with resource starvation, and the memp_trickle thread couldn't do	 * anything about it.  That's a pretty unlikely scenario, though.	 *	 * Note we should never get here when the temporary file in question	 * has already been closed in another process, in which case it should	 * be marked dead.	 */	if (F_ISSET(mfp, MP_TEMP))		return (EPERM);	/*	 * It's not a page from a file we've opened.  If the file requires	 * input/output processing, see if this process has ever registered	 * information as to how to write this type of file.  If not, there's	 * nothing we can do.	 */	if (mfp->ftype != 0) {		MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);		for (mpreg = LIST_FIRST(&dbmp->dbregq);		    mpreg != NULL; mpreg = LIST_NEXT(mpreg, q))			if (mpreg->ftype == mfp->ftype)				break;		MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);		if (mpreg == NULL)			return (EPERM);	}	/*	 * Try and open the file, specifying the known underlying shared area.	 *	 * !!!	 * There's no negative cache, so we may repeatedly try and open files	 * that we have previously tried (and failed) to open.	 */	if ((ret = __memp_fcreate(dbenv, &dbmfp)) != 0)		return (ret);	if ((ret = __memp_fopen(dbmfp,	    mfp, NULL, DB_DURABLE_UNKNOWN, 0, mfp->stat.st_pagesize)) != 0) {		(void)__memp_fclose(dbmfp, 0);		/*		 * Ignore any error if the file is marked dead, assume the file		 * was removed from under us.		 */		if (!mfp->deadfile)			return (ret);		dbmfp = NULL;	}pgwrite:	ret = __memp_pgwrite(dbenv, dbmfp, hp, bhp);	if (dbmfp == NULL)		return (ret);	/*	 * Discard our reference, and, if we're the last reference, make sure	 * the file eventually gets closed.	 */	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);	if (dbmfp->ref == 1)		F_SET(dbmfp, MP_FLUSH);	else		--dbmfp->ref;	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);	return (ret);}/* * __memp_pgread -- *	Read a page from a file. * * PUBLIC: int __memp_pgread __P((DB_MPOOLFILE *, DB_MUTEX *, BH *, int)); */int__memp_pgread(dbmfp, mutexp, bhp, can_create)	DB_MPOOLFILE *dbmfp;	DB_MUTEX *mutexp;	BH *bhp;	int can_create;{	DB_ENV *dbenv;	MPOOLFILE *mfp;	size_t len, nr;	u_int32_t pagesize;	int ret;	dbenv = dbmfp->dbenv;	mfp = dbmfp->mfp;	pagesize = mfp->stat.st_pagesize;	/* We should never be called with a dirty or a locked buffer. */	DB_ASSERT(!F_ISSET(bhp, BH_DIRTY | BH_DIRTY_CREATE | BH_LOCKED));	/* Lock the buffer and swap the hash bucket lock for the buffer lock. */	F_SET(bhp, BH_LOCKED | BH_TRASH);	MUTEX_LOCK(dbenv, &bhp->mutex);	MUTEX_UNLOCK(dbenv, mutexp);	/*	 * Temporary files may not yet have been created.  We don't create	 * them now, we create them when the pages have to be flushed.	 */	nr = 0;	if (dbmfp->fhp != NULL)		if ((ret = __os_io(dbenv, DB_IO_READ,		    dbmfp->fhp, bhp->pgno, pagesize, bhp->buf, &nr)) != 0)			goto err;	/*	 * The page may not exist; if it doesn't, nr may well be 0, but we	 * expect the underlying OS calls not to return an error code in	 * this case.	 */	if (nr < pagesize) {		/*		 * Don't output error messages for short reads.  In particular,		 * DB recovery processing may request pages never written to		 * disk or for which only some part have been written to disk,		 * in which case we won't find the page.  The caller must know		 * how to handle the error.		 */		if (can_create == 0) {			ret = DB_PAGE_NOTFOUND;			goto err;		}		/* Clear any bytes that need to be cleared. */		len = mfp->clear_len == 0 ? pagesize : mfp->clear_len;		memset(bhp->buf, 0, len);#if defined(DIAGNOSTIC) || defined(UMRW)		/*		 * If we're running in diagnostic mode, corrupt any bytes on		 * the page that are unknown quantities for the caller.		 */		if (len < pagesize)			memset(bhp->buf + len, CLEAR_BYTE, pagesize - len);#endif		++mfp->stat.st_page_create;	} else		++mfp->stat.st_page_in;	/* Call any pgin function. */	ret = mfp->ftype == 0 ? 0 : __memp_pg(dbmfp, bhp, 1);	/* Unlock the buffer and reacquire the hash bucket lock. */err:	MUTEX_UNLOCK(dbenv, &bhp->mutex);	MUTEX_LOCK(dbenv, mutexp);	/*	 * If no errors occurred, the data is now valid, clear the BH_TRASH	 * flag; regardless, clear the lock bit and let other threads proceed.	 */	F_CLR(bhp, BH_LOCKED);	if (ret == 0)		F_CLR(bhp, BH_TRASH);	return (ret);}/* * __memp_pgwrite -- *	Write a page to a file. */static int__memp_pgwrite(dbenv, dbmfp, hp, bhp)	DB_ENV *dbenv;	DB_MPOOLFILE *dbmfp;

⌨️ 快捷键说明

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