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

📄 mp_fopen.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
		if ((ret = __memp_alloc(dbmp, dbmp->reginfo,		    NULL, strlen(path) + 1, &mfp->path_off, &p)) != 0)			goto err;		memcpy(p, path, strlen(path) + 1);		/* Copy the file identification string into shared memory. */		if ((ret = __memp_alloc(dbmp, dbmp->reginfo,		    NULL, DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0)			goto err;		memcpy(p, dbmfp->fileid, DB_FILE_ID_LEN);	}	/* Copy the page cookie into shared memory. */	if (dbmfp->pgcookie == NULL || dbmfp->pgcookie->size == 0) {		mfp->pgcookie_len = 0;		mfp->pgcookie_off = 0;	} else {		if ((ret = __memp_alloc(dbmp, dbmp->reginfo,		    NULL, dbmfp->pgcookie->size, &mfp->pgcookie_off, &p)) != 0)			goto err;		memcpy(p, dbmfp->pgcookie->data, dbmfp->pgcookie->size);		mfp->pgcookie_len = dbmfp->pgcookie->size;	}	/*	 * Prepend the MPOOLFILE to the list of MPOOLFILE's.	 */	R_LOCK(dbenv, dbmp->reginfo);	ret = __db_mutex_setup(dbenv, dbmp->reginfo, &mfp->mutex,	    MUTEX_NO_RLOCK);	if (ret == 0)		SH_TAILQ_INSERT_HEAD(&mp->mpfq, mfp, q, __mpoolfile);	R_UNLOCK(dbenv, dbmp->reginfo);	if (ret != 0)		goto err;have_mfp:	/*	 * We need to verify that all handles open a file either durable or not	 * durable.  This needs to be cross process and cross sub-databases, so	 * mpool is the place to do it.	 */	if (!LF_ISSET(DB_DURABLE_UNKNOWN | DB_RDONLY)) {		if (F_ISSET(mfp, MP_DURABLE_UNKNOWN)) {			if (LF_ISSET(MP_NOT_DURABLE))				F_SET(mfp, MP_NOT_DURABLE);			F_CLR(mfp, MP_DURABLE_UNKNOWN);		} else if (!LF_ISSET(DB_TXN_NOT_DURABLE) !=		    !F_ISSET(mfp, MP_NOT_DURABLE)) {			__db_err(dbenv,	     "Cannot open DURABLE and NOT DURABLE handles in the same file");			ret = EINVAL;			goto err;		}	}	/*	 * All paths to here have initialized the mfp variable to reference	 * the selected (or allocated) MPOOLFILE.	 */	dbmfp->mfp = mfp;	/*	 * Check to see if we can mmap the file.  If a file:	 *	+ isn't temporary	 *	+ is read-only	 *	+ doesn't require any pgin/pgout support	 *	+ the DB_NOMMAP flag wasn't set (in either the file open or	 *	  the environment in which it was opened)	 *	+ and is less than mp_mmapsize bytes in size	 *	 * we can mmap it instead of reading/writing buffers.  Don't do error	 * checking based on the mmap call failure.  We want to do normal I/O	 * on the file if the reason we failed was because the file was on an	 * NFS mounted partition, and we can fail in buffer I/O just as easily	 * as here.	 *	 * We'd like to test to see if the file is too big to mmap.  Since we	 * don't know what size or type off_t's or size_t's are, or the largest	 * unsigned integral type is, or what random insanity the local C	 * compiler will perpetrate, doing the comparison in a portable way is	 * flatly impossible.  Hope that mmap fails if the file is too large.	 */#define	DB_MAXMMAPSIZE	(10 * 1024 * 1024)	/* 10 MB. */	if (F_ISSET(mfp, MP_CAN_MMAP)) {		if (path == NULL)			F_CLR(mfp, MP_CAN_MMAP);		else if (!F_ISSET(dbmfp, MP_READONLY))			F_CLR(mfp, MP_CAN_MMAP);		else if (dbmfp->ftype != 0)			F_CLR(mfp, MP_CAN_MMAP);		else if (LF_ISSET(DB_NOMMAP) || F_ISSET(dbenv, DB_ENV_NOMMAP))			F_CLR(mfp, MP_CAN_MMAP);		else {			R_LOCK(dbenv, dbmp->reginfo);			maxmap = mp->mp_mmapsize == 0 ?			    DB_MAXMMAPSIZE : mp->mp_mmapsize;			R_UNLOCK(dbenv, dbmp->reginfo);			if (mbytes > maxmap / MEGABYTE ||			    (mbytes == maxmap / MEGABYTE &&			    bytes >= maxmap % MEGABYTE))				F_CLR(mfp, MP_CAN_MMAP);		}		dbmfp->addr = NULL;		if (F_ISSET(mfp, MP_CAN_MMAP)) {			dbmfp->len = (size_t)mbytes * MEGABYTE + bytes;			if (__os_mapfile(dbenv, rpath,			    dbmfp->fhp, dbmfp->len, 1, &dbmfp->addr) != 0) {				dbmfp->addr = NULL;				F_CLR(mfp, MP_CAN_MMAP);			}		}	}	F_SET(dbmfp, MP_OPEN_CALLED);	/*	 * Share the underlying file descriptor if that's possible.	 *	 * Add the file to the process' list of DB_MPOOLFILEs.	 */	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);	for (tmp_dbmfp = TAILQ_FIRST(&dbmp->dbmfq);	    tmp_dbmfp != NULL; tmp_dbmfp = TAILQ_NEXT(tmp_dbmfp, q))		if (dbmfp->mfp == tmp_dbmfp->mfp &&		    (F_ISSET(dbmfp, MP_READONLY) ||		    !F_ISSET(tmp_dbmfp, MP_READONLY))) {			if (dbmfp->fhp->mutexp != NULL)				__db_mutex_free(				    dbenv, dbmp->reginfo, dbmfp->fhp->mutexp);			(void)__os_closehandle(dbenv, dbmfp->fhp);			++tmp_dbmfp->fhp->ref;			dbmfp->fhp = tmp_dbmfp->fhp;			break;		}	TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);	if (0) {err:		if (refinc) {			/*			 * If mpf_cnt goes to zero here and unlink_on_close is			 * set, then we missed the last close, but there was an			 * error trying to open the file, so we probably cannot			 * unlink it anyway.			 */			MUTEX_LOCK(dbenv, &mfp->mutex);			--mfp->mpf_cnt;			MUTEX_UNLOCK(dbenv, &mfp->mutex);		}	}	if (rpath != NULL)		__os_free(dbenv, rpath);	return (ret);}/* * memp_fclose_pp -- *	DB_MPOOLFILE->close pre/post processing. * * PUBLIC: int __memp_fclose_pp __P((DB_MPOOLFILE *, u_int32_t)); */int__memp_fclose_pp(dbmfp, flags)	DB_MPOOLFILE *dbmfp;	u_int32_t flags;{	DB_ENV *dbenv;	int rep_check, ret, t_ret;	dbenv = dbmfp->dbenv;	/*	 * Validate arguments, but as a handle destructor, we can't fail.	 *	 * !!!	 * DB_MPOOL_DISCARD: Undocumented flag: DB private.	 */	ret = __db_fchk(dbenv, "DB_MPOOLFILE->close", flags, DB_MPOOL_DISCARD);	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;	if (rep_check)		__env_rep_enter(dbenv);	if ((t_ret = __memp_fclose(dbmfp, flags)) != 0 && ret == 0)		ret = t_ret;	if (rep_check)		__env_db_rep_exit(dbenv);	return (ret);}/* * __memp_fclose -- *	DB_MPOOLFILE->close. * * PUBLIC: int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t)); */int__memp_fclose(dbmfp, flags)	DB_MPOOLFILE *dbmfp;	u_int32_t flags;{	DB_ENV *dbenv;	DB_MPOOL *dbmp;	MPOOLFILE *mfp;	char *rpath;	u_int32_t ref;	int deleted, ret, t_ret;	dbenv = dbmfp->dbenv;	dbmp = dbenv->mp_handle;	ret = 0;	/*	 * Remove the DB_MPOOLFILE from the process' list.	 *	 * It's possible the underlying mpool cache may never have been created.	 * In that case, all we have is a structure, discard it.	 *	 * It's possible the DB_MPOOLFILE was never added to the DB_MPOOLFILE	 * file list, check the MP_OPEN_CALLED flag to be sure.	 */	if (dbmp == NULL)		goto done;	MUTEX_THREAD_LOCK(dbenv, dbmp->mutexp);	DB_ASSERT(dbmfp->ref >= 1);	if ((ref = --dbmfp->ref) == 0 && F_ISSET(dbmfp, MP_OPEN_CALLED))		TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q);	/*	 * Decrement the file descriptor's ref count -- if we're the last ref,	 * we'll discard the file descriptor.	 */	if (ref == 0 && dbmfp->fhp != NULL && --dbmfp->fhp->ref > 0)		dbmfp->fhp = NULL;	MUTEX_THREAD_UNLOCK(dbenv, dbmp->mutexp);	if (ref != 0)		return (0);	/* Complain if pinned blocks never returned. */	if (dbmfp->pinref != 0) {		__db_err(dbenv, "%s: close: %lu blocks left pinned",		    __memp_fn(dbmfp), (u_long)dbmfp->pinref);		ret = __db_panic(dbenv, DB_RUNRECOVERY);	}	/* Discard any mmap information. */	if (dbmfp->addr != NULL &&	    (ret = __os_unmapfile(dbenv, dbmfp->addr, dbmfp->len)) != 0)		__db_err(dbenv, "%s: %s", __memp_fn(dbmfp), db_strerror(ret));	/*	 * Close the file and discard the descriptor structure; temporary	 * files may not yet have been created.	 */	if (dbmfp->fhp != NULL) {		if (dbmfp->fhp->mutexp != NULL) {			__db_mutex_free(			    dbenv, dbmp->reginfo, dbmfp->fhp->mutexp);			dbmfp->fhp->mutexp = NULL;		}		if ((t_ret = __os_closehandle(dbenv, dbmfp->fhp)) != 0) {			__db_err(dbenv, "%s: %s",			    __memp_fn(dbmfp), db_strerror(t_ret));			if (ret == 0)				ret = t_ret;		}		dbmfp->fhp = NULL;	}	/*	 * Discard our reference on the underlying MPOOLFILE, and close it	 * if it's no longer useful to anyone.  It possible the open of the	 * file never happened or wasn't successful, in which case, mpf will	 * be NULL and MP_OPEN_CALLED will not be set.	 */	mfp = dbmfp->mfp;	DB_ASSERT((F_ISSET(dbmfp, MP_OPEN_CALLED) && mfp != NULL) ||	    (!F_ISSET(dbmfp, MP_OPEN_CALLED) && mfp == NULL));	if (!F_ISSET(dbmfp, MP_OPEN_CALLED))		goto done;	/*	 * If it's a temp file, all outstanding references belong to unflushed	 * buffers.  (A temp file can only be referenced by one DB_MPOOLFILE).	 * We don't care about preserving any of those buffers, so mark the	 * MPOOLFILE as dead so that even the dirty ones just get discarded	 * when we try to flush them.	 */	deleted = 0;	MUTEX_LOCK(dbenv, &mfp->mutex);	if (--mfp->mpf_cnt == 0 || LF_ISSET(DB_MPOOL_DISCARD)) {		if (LF_ISSET(DB_MPOOL_DISCARD) ||		    F_ISSET(mfp, MP_TEMP) || mfp->unlink_on_close)			mfp->deadfile = 1;		if (mfp->unlink_on_close) {			if ((t_ret = __db_appname(dbmp->dbenv,			    DB_APP_DATA, R_ADDR(dbmp->reginfo,			    mfp->path_off), 0, NULL, &rpath)) != 0 && ret == 0)				ret = t_ret;			if (t_ret == 0) {				if ((t_ret = __os_unlink(				    dbmp->dbenv, rpath)) != 0 && ret == 0)					ret = t_ret;				__os_free(dbenv, rpath);			}		}		if (mfp->block_cnt == 0) {			if ((t_ret =			    __memp_mf_discard(dbmp, mfp)) != 0 && ret == 0)				ret = t_ret;			deleted = 1;		}	}	if (deleted == 0)		MUTEX_UNLOCK(dbenv, &mfp->mutex);done:	/* Discard the DB_MPOOLFILE structure. */	if (dbmfp->pgcookie != NULL) {		__os_free(dbenv, dbmfp->pgcookie->data);		__os_free(dbenv, dbmfp->pgcookie);	}	__os_free(dbenv, dbmfp);	return (ret);}/* * __memp_mf_discard -- *	Discard an MPOOLFILE. * * PUBLIC: int __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *)); */int__memp_mf_discard(dbmp, mfp)	DB_MPOOL *dbmp;	MPOOLFILE *mfp;{	DB_ENV *dbenv;	DB_MPOOL_STAT *sp;	MPOOL *mp;	int need_sync, ret;	dbenv = dbmp->dbenv;	mp = dbmp->reginfo[0].primary;	/*	 * Expects caller to be holding the MPOOLFILE mutex.	 *	 * When discarding a file, we have to flush writes from it to disk.	 * The scenario is that dirty buffers from this file need to be	 * flushed to satisfy a future checkpoint, but when the checkpoint	 * calls mpool sync, the sync code won't know anything about them.	 * Ignore files not written, discarded, or only temporary.	 */	need_sync =	   mfp->file_written && !mfp->deadfile && !F_ISSET(mfp, MP_TEMP);	/*	 * We have to release the MPOOLFILE mutex before acquiring the region	 * mutex so we don't deadlock.  Make sure nobody ever looks at this	 * structure again.	 */	mfp->deadfile = 1;	/* Discard the mutex we're holding. */	MUTEX_UNLOCK(dbenv, &mfp->mutex);	/* Lock the region and delete from the list of MPOOLFILEs. */	R_LOCK(dbenv, dbmp->reginfo);	SH_TAILQ_REMOVE(&mp->mpfq, mfp, q, __mpoolfile);	ret = need_sync ? __memp_mf_sync(dbmp, mfp) : 0;	/* Copy the statistics into the region. */	sp = &mp->stat;	sp->st_cache_hit += mfp->stat.st_cache_hit;	sp->st_cache_miss += mfp->stat.st_cache_miss;	sp->st_map += mfp->stat.st_map;	sp->st_page_create += mfp->stat.st_page_create;	sp->st_page_in += mfp->stat.st_page_in;	sp->st_page_out += mfp->stat.st_page_out;	/* Clear the mutex this MPOOLFILE recorded. */	__db_shlocks_clear(&mfp->mutex, dbmp->reginfo,	    R_ADDR(dbmp->reginfo, mp->maint_off));	/* Free the space. */	if (mfp->path_off != 0)		__db_shalloc_free(&dbmp->reginfo[0],		    R_ADDR(dbmp->reginfo, mfp->path_off));	if (mfp->fileid_off != 0)		__db_shalloc_free(&dbmp->reginfo[0],		    R_ADDR(dbmp->reginfo, mfp->fileid_off));	if (mfp->pgcookie_off != 0)		__db_shalloc_free(&dbmp->reginfo[0],		    R_ADDR(dbmp->reginfo, mfp->pgcookie_off));	__db_shalloc_free(&dbmp->reginfo[0], mfp);	R_UNLOCK(dbenv, dbmp->reginfo);	return (ret);}

⌨️ 快捷键说明

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