diff options
Diffstat (limited to 'debian/htdig/htdig-3.2.0b6/db/mp_fput.c')
-rw-r--r-- | debian/htdig/htdig-3.2.0b6/db/mp_fput.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/debian/htdig/htdig-3.2.0b6/db/mp_fput.c b/debian/htdig/htdig-3.2.0b6/db/mp_fput.c new file mode 100644 index 00000000..5d2933f6 --- /dev/null +++ b/debian/htdig/htdig-3.2.0b6/db/mp_fput.c @@ -0,0 +1,165 @@ +/*- + * 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_fput.c 11.3 (Sleepycat) 10/29/99"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <errno.h> +#endif + +#include "db_int.h" +#include "db_shash.h" +#include "mp.h" + +/* + * CDB_memp_fput -- + * Mpool file put function. + */ +int +CDB_memp_fput(dbmfp, pgaddr, flags) + DB_MPOOLFILE *dbmfp; + void *pgaddr; + u_int32_t flags; +{ + BH *bhp; + DB_ENV *dbenv; + DB_MPOOL *dbmp; + MCACHE *mc; + MPOOL *mp; + int ret, wrote; + + dbmp = dbmfp->dbmp; + dbenv = dbmp->dbenv; + mp = dbmp->reginfo.primary; + + PANIC_CHECK(dbenv); + + /* Validate arguments. */ + if (flags) { + if ((ret = CDB___db_fchk(dbenv, "CDB_memp_fput", flags, + DB_MPOOL_CLEAN | DB_MPOOL_DIRTY | DB_MPOOL_DISCARD)) != 0) + return (ret); + if ((ret = CDB___db_fcchk(dbenv, "CDB_memp_fput", + flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0) + return (ret); + + if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) { + CDB___db_err(dbenv, + "%s: dirty flag set for readonly file page", + CDB___memp_fn(dbmfp)); + return (EACCES); + } + } + + R_LOCK(dbenv, &dbmp->reginfo); + + /* Decrement the pinned reference count. */ + if (dbmfp->pinref == 0) + CDB___db_err(dbenv, "%s: put: more blocks returned than retrieved", + CDB___memp_fn(dbmfp)); + else + --dbmfp->pinref; + + /* + * If we're mapping the file, there's nothing to do. Because we can + * stop mapping the file at any time, we have to check on each buffer + * to see if the address we gave the application was part of the map + * region. + */ + if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr && + (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len) { + R_UNLOCK(dbenv, &dbmp->reginfo); + return (0); + } + + /* Convert the page address to a buffer header. */ + bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf)); + + /* Convert the buffer header to a cache. */ + mc = BH_TO_CACHE(dbmp, bhp); + +/* UNLOCK THE REGION, LOCK THE CACHE. */ + + /* Set/clear the page bits. */ + if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) { + ++mc->stat.st_page_clean; + --mc->stat.st_page_dirty; + F_CLR(bhp, BH_DIRTY); + } + if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) { + --mc->stat.st_page_clean; + ++mc->stat.st_page_dirty; + F_SET(bhp, BH_DIRTY); + } + if (LF_ISSET(DB_MPOOL_DISCARD)) + F_SET(bhp, BH_DISCARD); + + /* + * Check for a reference count going to zero. This can happen if the + * application returns a page twice. + */ + if (bhp->ref == 0) { + CDB___db_err(dbenv, "%s: page %lu: unpinned page returned", + CDB___memp_fn(dbmfp), (u_long)bhp->pgno); + R_UNLOCK(dbenv, &dbmp->reginfo); + return (EINVAL); + } + + /* + * If more than one reference to the page, we're done. Ignore the + * discard flags (for now) and leave it at its position in the LRU + * chain. The rest gets done at last reference close. + */ + if (--bhp->ref > 0) { + R_UNLOCK(dbenv, &dbmp->reginfo); + return (0); + } + + /* + * Move the buffer to the head/tail of the LRU chain. We do this + * before writing the buffer for checkpoint purposes, as the write + * can discard the region lock and allow another process to acquire + * buffer. We could keep that from happening, but there seems no + * reason to do so. + */ + SH_TAILQ_REMOVE(&mc->bhq, bhp, q, __bh); + if (F_ISSET(bhp, BH_DISCARD)) + SH_TAILQ_INSERT_HEAD(&mc->bhq, bhp, q, __bh); + else + SH_TAILQ_INSERT_TAIL(&mc->bhq, bhp, q); + + /* + * If this buffer is scheduled for writing because of a checkpoint, we + * need to write it (if it's dirty), or update the checkpoint counters + * (if it's not dirty). If we try to write it and can't, that's not + * necessarily an error as it's not completely unreasonable that the + * application have permission to write the underlying file, but set a + * flag so that the next time the CDB_memp_sync function is called we try + * writing it there, as the checkpoint thread of control better be able + * to write all of the files. + */ + if (F_ISSET(bhp, BH_WRITE)) { + if (F_ISSET(bhp, BH_DIRTY)) { + if (CDB___memp_bhwrite(dbmp, + dbmfp->mfp, bhp, NULL, &wrote) != 0 || !wrote) + F_SET(mp, MP_LSN_RETRY); + } else { + F_CLR(bhp, BH_WRITE); + + --mp->lsn_cnt; + --dbmfp->mfp->lsn_cnt; + } + } + + R_UNLOCK(dbenv, &dbmp->reginfo); + return (0); +} |