* have to coalesce of memory to satisfy the request, don't
* will have to coalesce memory to satisfy the request, don't
__memp_ralloc(dbmp, len, offsetp, retp)	DB_MPOOL *dbmp;	size_t len, *offsetp;	void *retp;{	BH *bhp, *nbhp;	MPOOL *mp;	MPOOLFILE *mfp;	size_t fsize, total;	int nomore, restart, ret, wrote;	void *p;	mp = dbmp->mp;	nomore = 0;alloc:	if ((ret = __db_shalloc(dbmp->addr, len, MUTEX_ALIGNMENT, &p)) == 0) {		if (offsetp != NULL)			*offsetp = R_OFFSET(dbmp, p);		*(void **)retp = p;		return (0);	}	if (nomore) {		__db_err(dbmp->dbenv, "%s", strerror(ret));		return (ret);	}	/* Look for a buffer on the free list that's the right size. */	for (bhp =	    SH_TAILQ_FIRST(&mp->bhfq, __bh); bhp != NULL; bhp = nbhp) {		nbhp = SH_TAILQ_NEXT(bhp, q, __bh);		if (__db_shsizeof(bhp) == len) {			SH_TAILQ_REMOVE(&mp->bhfq, bhp, q, __bh);			if (offsetp != NULL)				*offsetp = R_OFFSET(dbmp, bhp);			*(void **)retp = bhp;			return (0);		}	}	/* Discard from the free list until we've freed enough memory. */	total = 0;	for (bhp =	    SH_TAILQ_FIRST(&mp->bhfq, __bh); bhp != NULL; bhp = nbhp) {		nbhp = SH_TAILQ_NEXT(bhp, q, __bh);		SH_TAILQ_REMOVE(&mp->bhfq, bhp, q, __bh);		__db_shalloc_free(dbmp->addr, bhp);		--mp->stat.st_page_clean;		/*		 * Retry as soon as we've freed up sufficient space.  If we		 * have to coalesce of memory to satisfy the request, don't		 * try until it's likely (possible?) that we'll succeed.		 */		total += fsize = __db_shsizeof(bhp);		if (fsize >= len || total >= 3 * len)			goto alloc;	}retry:	/* Find a buffer we can flush; pure LRU. */	total = 0;	for (bhp =	    SH_TAILQ_FIRST(&mp->bhq, __bh); bhp != NULL; bhp = nbhp) {		nbhp = SH_TAILQ_NEXT(bhp, q, __bh);		/* Ignore pinned or locked (I/O in progress) buffers. */		if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED))			continue;		/* Find the associated MPOOLFILE. */		mfp = R_ADDR(dbmp, bhp->mf_offset);		/*		 * Write the page if it's dirty.		 *		 * If we wrote the page, fall through and free the buffer.  We		 * don't have to rewalk the list to acquire the buffer because		 * it was never available for any other process to modify it.		 * If we didn't write the page, but we discarded and reacquired		 * the region lock, restart the buffer list walk.  If we neither		 * wrote the buffer nor discarded the region lock, continue down		 * the buffer list.		 */		if (F_ISSET(bhp, BH_DIRTY)) {			if ((ret = __memp_bhwrite(dbmp,			    mfp, bhp, &restart, &wrote)) != 0)				return (ret);			/*			 * It's possible that another process wants this buffer			 * and incremented the ref count while we were writing			 * it.			 */			if (bhp->ref != 0)				goto retry;			if (wrote)				++mp->stat.st_rw_evict;			else {				if (restart)					goto retry;				continue;			}		} else			++mp->stat.st_ro_evict;		/*		 * Check to see if the buffer is the size we're looking for.		 * If it is, simply reuse it.		 */		total += fsize = __db_shsizeof(bhp);		if (fsize == len) {			__memp_bhfree(dbmp, mfp, bhp, 0);			if (offsetp != NULL)				*offsetp = R_OFFSET(dbmp, bhp);			*(void **)retp = bhp;			return (0);		}		/* Free the buffer. */		__memp_bhfree(dbmp, mfp, bhp, 1);		/*		 * Retry as soon as we've freed up sufficient space.  If we		 * have to coalesce of memory to satisfy the request, don't		 * try until it's likely (possible?) that we'll succeed.		 */		if (fsize >= len || total >= 3 * len)			goto alloc;		/* Restart the walk if we discarded the region lock. */		if (restart)			goto retry;	}	nomore = 1;	goto alloc;}