size_t len; int fd, newregion, ret, retry_cnt;
int ret;
log_open(path, flags, mode, dbenv, lpp)	const char *path;	int flags;	int mode;	DB_ENV *dbenv;	DB_LOG **lpp;{	DB_LOG *dblp;	LOG *lp;	size_t len;	int fd, newregion, ret, retry_cnt;	/* Validate arguments. */#ifdef HAVE_SPINLOCKS#define	OKFLAGS	(DB_CREATE | DB_THREAD)#else#define	OKFLAGS	(DB_CREATE)#endif	if ((ret = __db_fchk(dbenv, "log_open", flags, OKFLAGS)) != 0)		return (ret);	/*	 * We store 4-byte offsets into the file, so the maximum file	 * size can't be larger than that.	 */	if (dbenv != NULL && dbenv->lg_max > UINT32_T_MAX) {		__db_err(dbenv, "log_open: maximum file size too large");		return (EINVAL);	}	/* Create and initialize the DB_LOG structure. */	if ((dblp = (DB_LOG *)__db_calloc(1, sizeof(DB_LOG))) == NULL)		return (ENOMEM);	if (path != NULL && (dblp->dir = __db_strdup(path)) == NULL) {		__db_free(dblp);		return (ENOMEM);	}	dblp->dbenv = dbenv;	dblp->lfd = -1;	ZERO_LSN(dblp->c_lsn);	dblp->c_fd = -1;	/*	 * The log region isn't fixed size because we store the registered	 * file names there.  Make it fairly large so that we don't have to	 * grow it.	 */	len = 30 * 1024;	/* Map in the region. */	retry_cnt = newregion = 0;retry:	if (LF_ISSET(DB_CREATE)) {		ret = __db_rcreate(dbenv, DB_APP_LOG, path,		    DB_DEFAULT_LOG_FILE, mode, len, 0, &fd, &dblp->maddr);		if (ret == 0) {			/* Put the LOG structure first in the region. */			lp = dblp->maddr;			/* Initialize the rest of the region as free space. */			dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);			__db_shalloc_init(dblp->addr, len - sizeof(LOG));			/* Initialize the LOG structure. */			lp->persist.lg_max = dbenv == NULL ? 0 : dbenv->lg_max;			if (lp->persist.lg_max == 0)				lp->persist.lg_max = DEFAULT_MAX;			lp->persist.magic = DB_LOGMAGIC;			lp->persist.version = DB_LOGVERSION;			lp->persist.mode = mode;			SH_TAILQ_INIT(&lp->fq);			/* Initialize LOG LSNs. */			lp->lsn.file = 1;			lp->lsn.offset = 0;			newregion = 1;		} else if (ret != EEXIST)			goto err;	}	/* If we didn't or couldn't create the region, try and join it. */	if (!newregion &&	    (ret = __db_ropen(dbenv, DB_APP_LOG,	    path, DB_DEFAULT_LOG_FILE, 0, &fd, &dblp->maddr)) != 0) {		/*		 * If we fail because the file isn't available, wait a		 * second and try again.		 */		if (ret == EAGAIN && ++retry_cnt < 3) {			(void)__db_sleep(1, 0);			goto retry;		}		goto err;	}	/* Set up the common information. */	dblp->lp = dblp->maddr;	dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);	dblp->fd = fd;	/* Initialize thread information. */	if (LF_ISSET(DB_THREAD)) {		F_SET(dblp, DB_AM_THREAD);		if (!newregion)			LOCK_LOGREGION(dblp);		if ((ret = __db_shalloc(dblp->addr,		    sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) == 0)			(void)__db_mutex_init(dblp->mutexp, -1);		if (!newregion)			UNLOCK_LOGREGION(dblp);		if (ret != 0) {			(void)log_close(dblp);			if (newregion)				(void)log_unlink(path, 1, dbenv);			return (ret);		}	}	/*	 * If doing recovery, try and recover any previous log files	 * before releasing the lock.	 */	if (newregion) {		ret = __log_recover(dblp);		UNLOCK_LOGREGION(dblp);		if (ret != 0) {			(void)log_close(dblp);			(void)log_unlink(path, 1, dbenv);			return (ret);		}	}	*lpp = dblp;	return (0);err:	/*	 * We never get here with an allocated thread-mutex, so we do	 * not have to worry about freeing it.	 */	FREE(dblp, sizeof(DB_LOG));	return (ret);}