diff options
Diffstat (limited to 'debian/htdig/htdig-3.2.0b6/db/mp_alloc.c')
-rw-r--r-- | debian/htdig/htdig-3.2.0b6/db/mp_alloc.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/debian/htdig/htdig-3.2.0b6/db/mp_alloc.c b/debian/htdig/htdig-3.2.0b6/db/mp_alloc.c new file mode 100644 index 00000000..ea0e3aa2 --- /dev/null +++ b/debian/htdig/htdig-3.2.0b6/db/mp_alloc.c @@ -0,0 +1,154 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 1997, 1998, 1999 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char sccsid[] = "@(#)mp_alloc.c 11.3 (Sleepycat) 9/29/99"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> +#endif + +#include "db_int.h" +#include "db_shash.h" +#include "mp.h" + +/* + * CDB___memp_alloc -- + * Allocate some space in the mpool region. + * + * PUBLIC: int CDB___memp_alloc __P((DB_MPOOL *, + * PUBLIC: REGINFO *, MPOOLFILE *, size_t, roff_t *, void *)); + */ +int +CDB___memp_alloc(dbmp, memreg, mfp, len, offsetp, retp) + DB_MPOOL *dbmp; + REGINFO *memreg; + MPOOLFILE *mfp; + size_t len; + roff_t *offsetp; + void *retp; +{ + BH *bhp, *nbhp; + MCACHE *mc; + MPOOL *mp; + MPOOLFILE *bh_mfp; + size_t total; + int nomore, restart, ret, wrote; + void *p; + + mp = dbmp->reginfo.primary; + mc = memreg->primary; + + /* + * If we're allocating a buffer, and the one we're discarding is the + * same size, we don't want to waste the time to re-integrate it into + * the shared memory free list. If the DB_MPOOLFILE argument isn't + * NULL, we'll compare the underlying page sizes of the two buffers + * before free-ing and re-allocating buffers. + */ + if (mfp != NULL) + len = (sizeof(BH) - sizeof(u_int8_t)) + mfp->stat.st_pagesize; + + nomore = 0; +alloc: if ((ret = CDB___db_shalloc(memreg->addr, len, MUTEX_ALIGN, &p)) == 0) { + if (offsetp != NULL) + *offsetp = R_OFFSET(memreg, p); + *(void **)retp = p; + return (0); + } + if (nomore) { + CDB___db_err(dbmp->dbenv, + "Unable to allocate %lu bytes from mpool shared region: %s\n", + (u_long)len, CDB_db_strerror(ret)); + return (ret); + } + +retry: /* Find a buffer we can flush; pure LRU. */ + restart = total = 0; + for (bhp = + SH_TAILQ_FIRST(&mc->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. */ + bh_mfp = R_ADDR(&dbmp->reginfo, bhp->mf_offset); + + /* Write the page if it's dirty. */ + if (F_ISSET(bhp, BH_DIRTY)) { + ++bhp->ref; + if ((ret = CDB___memp_bhwrite(dbmp, + bh_mfp, bhp, &restart, &wrote)) != 0) + return (ret); + --bhp->ref; + + /* + * Another process may have acquired this buffer and + * incremented the ref count after we wrote it. + */ + if (bhp->ref != 0) + goto retry; + + /* + * If we wrote the page, continue 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 list walk. + * + * If we neither wrote the buffer nor discarded the + * region lock, continue down the buffer list. + */ + if (wrote) + ++mc->stat.st_rw_evict; + else { + if (restart) + goto retry; + continue; + } + } else + ++mc->stat.st_ro_evict; + + /* + * Check to see if the buffer is the size we're looking for. + * If it is, simply reuse it. + */ + if (mfp != NULL && + mfp->stat.st_pagesize == bh_mfp->stat.st_pagesize) { + CDB___memp_bhfree(dbmp, bhp, 0); + + if (offsetp != NULL) + *offsetp = R_OFFSET(memreg, bhp); + *(void **)retp = bhp; + return (0); + } + + /* Note how much space we've freed, and free the buffer. */ + total += CDB___db_shsizeof(bhp); + CDB___memp_bhfree(dbmp, 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 (total >= 3 * len) + goto alloc; + + /* Restart the walk if we discarded the region lock. */ + if (restart) + goto retry; + } + nomore = 1; + goto alloc; +} |