aboutsummaryrefslogtreecommitdiff
path: root/db2/hash
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-06-13 13:36:34 +0000
committerUlrich Drepper <drepper@redhat.com>1999-06-13 13:36:34 +0000
commitec239360d13518a13f572b635d036c7d10028010 (patch)
treebdb5111363f45d2107849c2456b575d72779174c /db2/hash
parentUpdate. (diff)
downloadglibc-ec239360d13518a13f572b635d036c7d10028010.tar.gz
glibc-ec239360d13518a13f572b635d036c7d10028010.tar.bz2
glibc-ec239360d13518a13f572b635d036c7d10028010.zip
Update.
* db2/Makefile (distribute): Remove files which do not exist anymore.
Diffstat (limited to 'db2/hash')
-rw-r--r--db2/hash/hash.c1151
-rw-r--r--db2/hash/hash_auto.c161
-rw-r--r--db2/hash/hash_debug.c92
-rw-r--r--db2/hash/hash_dup.c295
-rw-r--r--db2/hash/hash_page.c1088
-rw-r--r--db2/hash/hash_rec.c281
-rw-r--r--db2/hash/hash_stat.c37
7 files changed, 1524 insertions, 1581 deletions
diff --git a/db2/hash/hash.c b/db2/hash/hash.c
index 0265f19659..0d202fce20 100644
--- a/db2/hash/hash.c
+++ b/db2/hash/hash.c
@@ -47,7 +47,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)hash.c 10.45 (Sleepycat) 5/11/98";
+static const char sccsid[] = "@(#)hash.c 10.63 (Sleepycat) 12/11/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -64,23 +64,23 @@ static const char sccsid[] = "@(#)hash.c 10.45 (Sleepycat) 5/11/98";
#include "db_am.h"
#include "db_ext.h"
#include "hash.h"
+#include "btree.h"
#include "log.h"
+#include "db_shash.h"
+#include "lock.h"
+#include "lock_ext.h"
static int __ham_c_close __P((DBC *));
static int __ham_c_del __P((DBC *, u_int32_t));
+static int __ham_c_destroy __P((DBC *));
static int __ham_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
static int __ham_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
-static int __ham_c_init __P((DB *, DB_TXN *, DBC **));
-static int __ham_cursor __P((DB *, DB_TXN *, DBC **));
static int __ham_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
-static int __ham_dup_return __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
-static int __ham_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
-static void __ham_init_htab __P((HTAB *, u_int32_t, u_int32_t));
-static int __ham_lookup __P((HTAB *,
- HASH_CURSOR *, const DBT *, u_int32_t, db_lockmode_t));
-static int __ham_overwrite __P((HTAB *, HASH_CURSOR *, DBT *));
-static int __ham_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
-static int __ham_sync __P((DB *, u_int32_t));
+static int __ham_dup_return __P((DBC *, DBT *, u_int32_t));
+static int __ham_expand_table __P((DBC *));
+static void __ham_init_htab __P((DBC *, u_int32_t, u_int32_t));
+static int __ham_lookup __P((DBC *, const DBT *, u_int32_t, db_lockmode_t));
+static int __ham_overwrite __P((DBC *, DBT *));
/************************** INTERFACE ROUTINES ***************************/
/* OPEN/CLOSE */
@@ -96,65 +96,53 @@ __ham_open(dbp, dbinfo)
DB_INFO *dbinfo;
{
DB_ENV *dbenv;
- DBC *curs;
- HTAB *hashp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
int file_existed, ret;
+ dbc = NULL;
dbenv = dbp->dbenv;
- if ((hashp = (HTAB *)__db_calloc(1, sizeof(HTAB))) == NULL)
- return (ENOMEM);
- hashp->dbp = dbp;
-
/* Set the hash function if specified by the user. */
if (dbinfo != NULL && dbinfo->h_hash != NULL)
- hashp->hash = dbinfo->h_hash;
+ dbp->h_hash = dbinfo->h_hash;
/*
- * Initialize the remaining fields of the dbp. The type, close and
- * fd functions are all set in db_open.
+ * Initialize the remaining fields of the dbp. The only function
+ * that differs from the default set is __ham_stat().
*/
- dbp->internal = hashp;
- dbp->cursor = __ham_cursor;
+ dbp->internal = NULL;
+ dbp->am_close = __ham_close;
dbp->del = __ham_delete;
- dbp->get = __ham_get;
- dbp->put = __ham_put;
- dbp->sync = __ham_sync;
-
- /* If locking is turned on, lock the meta data page. */
- if (F_ISSET(dbp, DB_AM_LOCKING)) {
- dbp->lock.pgno = BUCKET_INVALID;
- if ((ret = lock_get(dbenv->lk_info, dbp->locker,
- 0, &dbp->lock_dbt, DB_LOCK_READ, &hashp->hlock)) != 0) {
- if (ret < 0)
- ret = EAGAIN;
- goto out;
- }
- }
+ dbp->stat = __ham_stat;
+
+ /* Get a cursor we can use for the rest of this function. */
+ if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
+ goto out;
+
+ hcp = (HASH_CURSOR *)dbc->internal;
+ GET_META(dbp, hcp, ret);
+ if (ret != 0)
+ goto out;
/*
- * Now, we can try to read the meta-data page and figure out
- * if we set up locking and get the meta-data page properly.
* If this is a new file, initialize it, and put it back dirty.
*/
- if ((ret = __ham_get_page(hashp->dbp, 0, (PAGE **)&hashp->hdr)) != 0)
- goto out;
- /* Initialize the hashp structure */
- if (hashp->hdr->magic == DB_HASHMAGIC) {
+ /* Initialize the hdr structure */
+ if (hcp->hdr->magic == DB_HASHMAGIC) {
file_existed = 1;
/* File exists, verify the data in the header. */
- if (hashp->hash == NULL)
- hashp->hash =
- hashp->hdr->version < 5 ? __ham_func4 : __ham_func5;
- if (hashp->hash(CHARKEY, sizeof(CHARKEY)) !=
- hashp->hdr->h_charkey) {
- __db_err(hashp->dbp->dbenv,
- "hash: incompatible hash function");
+ if (dbp->h_hash == NULL)
+ dbp->h_hash =
+ hcp->hdr->version < 5 ? __ham_func4 : __ham_func5;
+ if (dbp->h_hash(CHARKEY, sizeof(CHARKEY)) !=
+ hcp->hdr->h_charkey) {
+ __db_err(dbp->dbenv, "hash: incompatible hash function");
ret = EINVAL;
goto out;
}
- if (F_ISSET(hashp->hdr, DB_HASH_DUP))
+ if (F_ISSET(hcp->hdr, DB_HASH_DUP))
F_SET(dbp, DB_AM_DUP);
} else {
/*
@@ -163,59 +151,27 @@ __ham_open(dbp, dbinfo)
*/
file_existed = 0;
if (F_ISSET(dbp, DB_AM_LOCKING) &&
- ((ret = lock_put(dbenv->lk_info, hashp->hlock)) != 0 ||
- (ret = lock_get(dbenv->lk_info, dbp->locker, 0,
- &dbp->lock_dbt, DB_LOCK_WRITE, &hashp->hlock)) != 0)) {
+ ((ret = lock_put(dbenv->lk_info, hcp->hlock)) != 0 ||
+ (ret = lock_get(dbenv->lk_info, dbc->locker, 0,
+ &dbc->lock_dbt, DB_LOCK_WRITE, &hcp->hlock)) != 0)) {
if (ret < 0)
ret = EAGAIN;
goto out;
}
- __ham_init_htab(hashp,
- dbinfo != NULL ? dbinfo->h_nelem : 0,
+ __ham_init_htab(dbc, dbinfo != NULL ? dbinfo->h_nelem : 0,
dbinfo != NULL ? dbinfo->h_ffactor : 0);
if (F_ISSET(dbp, DB_AM_DUP))
- F_SET(hashp->hdr, DB_HASH_DUP);
- if ((ret = __ham_dirty_page(hashp, (PAGE *)hashp->hdr)) != 0)
+ F_SET(hcp->hdr, DB_HASH_DUP);
+ if ((ret = __ham_dirty_page(dbp, (PAGE *)hcp->hdr)) != 0)
goto out;
}
- /* Initialize the default cursor. */
- __ham_c_init(dbp, NULL, &curs);
- TAILQ_INSERT_TAIL(&dbp->curs_queue, curs, links);
-
- /* Allocate memory for our split buffer. */
- if ((hashp->split_buf = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) {
- ret = ENOMEM;
- goto out;
- }
-
-#ifdef NO_STATISTICS_FOR_DB_ERR
- __db_err(dbp->dbenv,
- "%s%lx\n%s%ld\n%s%ld\n%s%ld\n%s%ld\n%s0x%lx\n%s0x%lx\n%s%ld\n%s%ld\n%s0x%lx",
- "TABLE POINTER ", (long)hashp,
- "BUCKET SIZE ", (long)hashp->hdr->pagesize,
- "FILL FACTOR ", (long)hashp->hdr->ffactor,
- "MAX BUCKET ", (long)hashp->hdr->max_bucket,
- "OVFL POINT ", (long)hashp->hdr->ovfl_point,
- "LAST FREED ", (long)hashp->hdr->last_freed,
- "HIGH MASK ", (long)hashp->hdr->high_mask,
- "LOW MASK ", (long)hashp->hdr->low_mask,
- "NELEM ", (long)hashp->hdr->nelem,
- "FLAGS ", (long)hashp->hdr->flags);
-#endif
-
/* Release the meta data page */
- (void)__ham_put_page(hashp->dbp, (PAGE *)hashp->hdr, 0);
- if (F_ISSET(dbp, DB_AM_LOCKING) &&
- (ret = lock_put(dbenv->lk_info, hashp->hlock)) != 0) {
- if (ret < 0)
- ret = EAGAIN;
+ RELEASE_META(dbp, hcp);
+ if ((ret = dbc->c_close(dbc)) != 0)
goto out;
- }
- hashp->hlock = 0;
- hashp->hdr = NULL;
/* Sync the file so that we know that the meta data goes to disk. */
if (!file_existed && (ret = dbp->sync(dbp, 0)) != 0)
goto out;
@@ -232,27 +188,8 @@ int
__ham_close(dbp)
DB *dbp;
{
- HTAB *hashp;
- int ret, t_ret;
-
- DEBUG_LWRITE(dbp, NULL, "ham_close", NULL, NULL, 0);
- hashp = (HTAB *)dbp->internal;
- ret = 0;
-
- /* Free the split page. */
- if (hashp->split_buf)
- FREE(hashp->split_buf, dbp->pgsize);
-
- if (hashp->hdr && (t_ret = __ham_put_page(hashp->dbp,
- (PAGE *)hashp->hdr, 0)) != 0 && ret == 0)
- ret = t_ret;
- if (hashp->hlock && (t_ret = lock_put(hashp->dbp->dbenv->lk_info,
- hashp->hlock)) != 0 && ret == 0)
- ret = t_ret;
-
- FREE(hashp, sizeof(HTAB));
- dbp->internal = NULL;
- return (ret);
+ COMPQUIET(dbp, NULL);
+ return (0);
}
/************************** LOCAL CREATION ROUTINES **********************/
@@ -260,408 +197,204 @@ __ham_close(dbp)
* Returns 0 on No Error
*/
static void
-__ham_init_htab(hashp, nelem, ffactor)
- HTAB *hashp;
+__ham_init_htab(dbc, nelem, ffactor)
+ DBC *dbc;
u_int32_t nelem, ffactor;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
int32_t l2, nbuckets;
- memset(hashp->hdr, 0, sizeof(HASHHDR));
- hashp->hdr->ffactor = ffactor;
- hashp->hdr->pagesize = hashp->dbp->pgsize;
- ZERO_LSN(hashp->hdr->lsn);
- hashp->hdr->magic = DB_HASHMAGIC;
- hashp->hdr->version = DB_HASHVERSION;
- if (hashp->hash == NULL)
- hashp->hash =
- hashp->hdr->version < 5 ? __ham_func4 : __ham_func5;
- hashp->hdr->h_charkey = hashp->hash(CHARKEY, sizeof(CHARKEY));
- if (nelem != 0 && hashp->hdr->ffactor != 0) {
- nelem = (nelem - 1) / hashp->hdr->ffactor + 1;
+ hcp = (HASH_CURSOR *)dbc->internal;
+ dbp = dbc->dbp;
+ memset(hcp->hdr, 0, sizeof(HASHHDR));
+ hcp->hdr->ffactor = ffactor;
+ hcp->hdr->pagesize = dbp->pgsize;
+ ZERO_LSN(hcp->hdr->lsn);
+ hcp->hdr->magic = DB_HASHMAGIC;
+ hcp->hdr->version = DB_HASHVERSION;
+
+ if (dbp->h_hash == NULL)
+ dbp->h_hash = hcp->hdr->version < 5 ? __ham_func4 : __ham_func5;
+ hcp->hdr->h_charkey = dbp->h_hash(CHARKEY, sizeof(CHARKEY));
+ if (nelem != 0 && hcp->hdr->ffactor != 0) {
+ nelem = (nelem - 1) / hcp->hdr->ffactor + 1;
l2 = __db_log2(nelem > 2 ? nelem : 2);
} else
l2 = 2;
nbuckets = 1 << l2;
- hashp->hdr->ovfl_point = l2;
- hashp->hdr->last_freed = PGNO_INVALID;
+ hcp->hdr->ovfl_point = l2;
+ hcp->hdr->last_freed = PGNO_INVALID;
- hashp->hdr->max_bucket = hashp->hdr->high_mask = nbuckets - 1;
- hashp->hdr->low_mask = (nbuckets >> 1) - 1;
- memcpy(hashp->hdr->uid, hashp->dbp->lock.fileid, DB_FILE_ID_LEN);
+ hcp->hdr->max_bucket = hcp->hdr->high_mask = nbuckets - 1;
+ hcp->hdr->low_mask = (nbuckets >> 1) - 1;
+ memcpy(hcp->hdr->uid, dbp->fileid, DB_FILE_ID_LEN);
}
-/********************** DESTROY/CLOSE ROUTINES ************************/
-
-
-/*
- * Write modified pages to disk
- *
- * Returns:
- * 0 == OK
- * -1 ERROR
- */
static int
-__ham_sync(dbp, flags)
- DB *dbp;
- u_int32_t flags;
-{
- int ret;
-
- DEBUG_LWRITE(dbp, NULL, "ham_sync", NULL, NULL, flags);
- if ((ret = __db_syncchk(dbp, flags)) != 0)
- return (ret);
- if (F_ISSET(dbp, DB_AM_RDONLY))
- return (0);
-
- if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE)
- ret = 0;
-
- return (ret);
-}
-
-/*******************************SEARCH ROUTINES *****************************/
-/*
- * All the access routines return
- *
- * Returns:
- * 0 on SUCCESS
- * 1 to indicate an external ERROR (i.e. key not found, etc)
- * -1 to indicate an internal ERROR (i.e. out of memory, etc)
- */
-
-static int
-__ham_get(dbp, txn, key, data, flags)
+__ham_delete(dbp, txn, key, flags)
DB *dbp;
DB_TXN *txn;
DBT *key;
- DBT *data;
u_int32_t flags;
{
- DB *ldbp;
- HTAB *hashp;
+ DBC *dbc;
HASH_CURSOR *hcp;
- int ret, t_ret;
+ int ret, tret;
- DEBUG_LREAD(dbp, txn, "ham_get", key, NULL, flags);
- if ((ret = __db_getchk(dbp, key, data, flags)) != 0)
- return (ret);
+ DB_PANIC_CHECK(dbp);
- ldbp = dbp;
- if (F_ISSET(dbp, DB_AM_THREAD) &&
- (ret = __db_gethandle(dbp, __ham_hdup, &ldbp)) != 0)
+ if ((ret =
+ __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
return (ret);
- hashp = (HTAB *)ldbp->internal;
- SET_LOCKER(ldbp, txn);
- GET_META(ldbp, hashp);
-
- hashp->hash_accesses++;
- hcp = (HASH_CURSOR *)TAILQ_FIRST(&ldbp->curs_queue)->internal;
- if ((ret = __ham_lookup(hashp, hcp, key, 0, DB_LOCK_READ)) == 0) {
- if (F_ISSET(hcp, H_OK))
- ret = __ham_dup_return(hashp, hcp, data, DB_FIRST);
- else /* Key was not found */
- ret = DB_NOTFOUND;
- }
-
- if ((t_ret = __ham_item_done(hashp, hcp, 0)) != 0 && ret == 0)
- ret = t_ret;
- RELEASE_META(ldbp, hashp);
- if (F_ISSET(dbp, DB_AM_THREAD))
- __db_puthandle(ldbp);
- return (ret);
-}
-
-static int
-__ham_put(dbp, txn, key, data, flags)
- DB *dbp;
- DB_TXN *txn;
- DBT *key;
- DBT *data;
- u_int32_t flags;
-{
- DB *ldbp;
- DBT tmp_val, *myval;
- HASH_CURSOR *hcp;
- HTAB *hashp;
- u_int32_t nbytes;
- int ret, t_ret;
-
- DEBUG_LWRITE(dbp, txn, "ham_put", key, data, flags);
- if ((ret = __db_putchk(dbp, key, data,
- flags, F_ISSET(dbp, DB_AM_RDONLY), F_ISSET(dbp, DB_AM_DUP))) != 0)
+ if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
return (ret);
- ldbp = dbp;
- if (F_ISSET(dbp, DB_AM_THREAD) &&
- (ret = __db_gethandle(dbp, __ham_hdup, &ldbp)) != 0)
- return (ret);
+ DEBUG_LWRITE(dbc, txn, "ham_delete", key, NULL, flags);
- hashp = (HTAB *)ldbp->internal;
- SET_LOCKER(ldbp, txn);
- GET_META(ldbp, hashp);
- hcp = TAILQ_FIRST(&ldbp->curs_queue)->internal;
-
- nbytes = (ISBIG(hashp, key->size) ? HOFFPAGE_PSIZE :
- HKEYDATA_PSIZE(key->size)) +
- (ISBIG(hashp, data->size) ? HOFFPAGE_PSIZE :
- HKEYDATA_PSIZE(data->size));
-
- hashp->hash_accesses++;
- ret = __ham_lookup(hashp, hcp, key, nbytes, DB_LOCK_WRITE);
-
- if (ret == DB_NOTFOUND) {
- ret = 0;
- if (hcp->seek_found_page != PGNO_INVALID &&
- hcp->seek_found_page != hcp->pgno) {
- if ((ret = __ham_item_done(hashp, hcp, 0)) != 0)
- goto out;
- hcp->pgno = hcp->seek_found_page;
- hcp->bndx = NDX_INVALID;
- }
+ hcp = (HASH_CURSOR *)dbc->internal;
+ GET_META(dbp, hcp, ret);
+ if (ret != 0)
+ goto out;
- if (F_ISSET(data, DB_DBT_PARTIAL) && data->doff != 0) {
- /*
- * Doing a partial put, but the key does not exist
- * and we are not beginning the write at 0. We
- * must create a data item padded up to doff and
- * then write the new bytes represented by val.
- */
- ret = __ham_init_dbt(&tmp_val, data->size + data->doff,
- &hcp->big_data, &hcp->big_datalen);
- if (ret == 0) {
- memset(tmp_val.data, 0, data->doff);
- memcpy((u_int8_t *)tmp_val.data + data->doff,
- data->data, data->size);
- myval = &tmp_val;
- }
- } else
- myval = (DBT *)data;
-
- if (ret == 0)
- ret = __ham_add_el(hashp, hcp, key, myval, H_KEYDATA);
- } else if (ret == 0 && F_ISSET(hcp, H_OK)) {
- if (flags == DB_NOOVERWRITE)
- ret = DB_KEYEXIST;
- else if (F_ISSET(ldbp, DB_AM_DUP))
- ret = __ham_add_dup(hashp, hcp, data, DB_KEYLAST);
+ hcp->stats.hash_deleted++;
+ if ((ret = __ham_lookup(dbc, key, 0, DB_LOCK_WRITE)) == 0) {
+ if (F_ISSET(hcp, H_OK))
+ ret = __ham_del_pair(dbc, 1);
else
- ret = __ham_overwrite(hashp, hcp, data);
- }
-
- /* Free up all the cursor pages. */
- if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
- ret = t_ret;
- /* Now check if we have to grow. */
-out: if (ret == 0 && F_ISSET(hcp, H_EXPAND)) {
- ret = __ham_expand_table(hashp);
- F_CLR(hcp, H_EXPAND);
+ ret = DB_NOTFOUND;
}
- if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
- ret = t_ret;
- RELEASE_META(ldbp, hashp);
- if (F_ISSET(dbp, DB_AM_THREAD))
- __db_puthandle(ldbp);
+ RELEASE_META(dbp, hcp);
+out: if ((tret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = tret;
return (ret);
}
-static int
-__ham_cursor(dbp, txnid, dbcp)
- DB *dbp;
- DB_TXN *txnid;
- DBC **dbcp;
-{
+/* ****************** CURSORS ********************************** */
+/*
+ * __ham_c_init --
+ * Initialize the hash-specific portion of a cursor.
+ *
+ * PUBLIC: int __ham_c_init __P((DBC *));
+ */
+int
+__ham_c_init(dbc)
+ DBC *dbc;
+ {
+ HASH_CURSOR *new_curs;
int ret;
- DEBUG_LWRITE(dbp, txnid, "ham_cursor", NULL, NULL, 0);
- if ((ret = __ham_c_init(dbp, txnid, dbcp)) != 0)
+ if ((ret = __os_calloc(1, sizeof(struct cursor_t), &new_curs)) != 0)
+ return (ret);
+ if ((ret =
+ __os_malloc(dbc->dbp->pgsize, NULL, &new_curs->split_buf)) != 0) {
+ __os_free(new_curs, sizeof(*new_curs));
return (ret);
-
- DB_THREAD_LOCK(dbp);
- TAILQ_INSERT_TAIL(&dbp->curs_queue, *dbcp, links);
- DB_THREAD_UNLOCK(dbp);
- return (ret);
-}
-
-static int
-__ham_c_init(dbp, txnid, dbcp)
- DB *dbp;
- DB_TXN *txnid;
- DBC **dbcp;
-{
- DBC *db_curs;
- HASH_CURSOR *new_curs;
-
- if ((db_curs = (DBC *)__db_calloc(sizeof(DBC), 1)) == NULL)
- return (ENOMEM);
-
- if ((new_curs =
- (HASH_CURSOR *)__db_calloc(sizeof(struct cursor_t), 1)) == NULL) {
- FREE(db_curs, sizeof(DBC));
- return (ENOMEM);
}
- db_curs->internal = new_curs;
- db_curs->c_close = __ham_c_close;
- db_curs->c_del = __ham_c_del;
- db_curs->c_get = __ham_c_get;
- db_curs->c_put = __ham_c_put;
- db_curs->txn = txnid;
- db_curs->dbp = dbp;
+ new_curs->dbc = dbc;
+
+ dbc->internal = new_curs;
+ dbc->c_am_close = __ham_c_close;
+ dbc->c_am_destroy = __ham_c_destroy;
+ dbc->c_del = __ham_c_del;
+ dbc->c_get = __ham_c_get;
+ dbc->c_put = __ham_c_put;
- new_curs->db_cursor = db_curs;
__ham_item_init(new_curs);
- if (dbcp != NULL)
- *dbcp = db_curs;
return (0);
}
+/*
+ * __ham_c_close --
+ * Close down the cursor from a single use.
+ */
static int
-__ham_delete(dbp, txn, key, flags)
- DB *dbp;
- DB_TXN *txn;
- DBT *key;
- u_int32_t flags;
-{
- DB *ldbp;
- HTAB *hashp;
- HASH_CURSOR *hcp;
- int ret, t_ret;
-
- DEBUG_LWRITE(dbp, txn, "ham_delete", key, NULL, flags);
- if ((ret =
- __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
- return (ret);
-
- ldbp = dbp;
- if (F_ISSET(dbp, DB_AM_THREAD) &&
- (ret = __db_gethandle(dbp, __ham_hdup, &ldbp)) != 0)
- return (ret);
- hashp = (HTAB *)ldbp->internal;
- SET_LOCKER(ldbp, txn);
- GET_META(ldbp, hashp);
- hcp = TAILQ_FIRST(&ldbp->curs_queue)->internal;
-
- hashp->hash_accesses++;
- if ((ret = __ham_lookup(hashp, hcp, key, 0, DB_LOCK_WRITE)) == 0) {
- if (F_ISSET(hcp, H_OK))
- ret = __ham_del_pair(hashp, hcp, 1);
- else
- ret = DB_NOTFOUND;
- }
-
- if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
- ret = t_ret;
- RELEASE_META(ldbp, hashp);
- if (F_ISSET(dbp, DB_AM_THREAD))
- __db_puthandle(ldbp);
- return (ret);
-}
-
-/* ****************** CURSORS ********************************** */
-static int
-__ham_c_close(cursor)
- DBC *cursor;
+__ham_c_close(dbc)
+ DBC *dbc;
{
- DB *ldbp;
int ret;
- DEBUG_LWRITE(cursor->dbp, cursor->txn, "ham_c_close", NULL, NULL, 0);
- /*
- * If the pagep, dpagep, and lock fields of the cursor are all NULL,
- * then there really isn't a need to get a handle here. However,
- * the normal case is that at least one of those fields is non-NULL,
- * and putting those checks in here would couple the ham_item_done
- * functionality with cursor close which would be pretty disgusting.
- * Instead, we pay the overhead here of always getting the handle.
- */
- ldbp = cursor->dbp;
- if (F_ISSET(cursor->dbp, DB_AM_THREAD) &&
- (ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0)
+ if ((ret = __ham_item_done(dbc, 0)) != 0)
return (ret);
- ret = __ham_c_iclose(ldbp, cursor);
-
- if (F_ISSET(ldbp, DB_AM_THREAD))
- __db_puthandle(ldbp);
- return (ret);
+ __ham_item_init((HASH_CURSOR *)dbc->internal);
+ return (0);
}
+
/*
- * __ham_c_iclose --
- *
- * Internal cursor close routine; assumes it is being passed the correct
- * handle, rather than getting and putting a handle.
- *
- * PUBLIC: int __ham_c_iclose __P((DB *, DBC *));
+ * __ham_c_destroy --
+ * Cleanup the access method private part of a cursor.
*/
-int
-__ham_c_iclose(dbp, dbc)
- DB *dbp;
+static int
+__ham_c_destroy(dbc)
DBC *dbc;
{
HASH_CURSOR *hcp;
- HTAB *hashp;
- int ret;
- hashp = (HTAB *)dbp->internal;
hcp = (HASH_CURSOR *)dbc->internal;
- ret = __ham_item_done(hashp, hcp, 0);
-
- if (hcp->big_key)
- FREE(hcp->big_key, hcp->big_keylen);
- if (hcp->big_data)
- FREE(hcp->big_data, hcp->big_datalen);
+ if (hcp->split_buf != NULL)
+ __os_free(hcp->split_buf, dbc->dbp->pgsize);
+ __os_free(hcp, sizeof(HASH_CURSOR));
- /*
- * All cursors (except the default ones) are linked off the master.
- * Therefore, when we close the cursor, we have to remove it from
- * the master, not the local one.
- * XXX I am always removing from the master; what about local cursors?
- */
- DB_THREAD_LOCK(dbc->dbp);
- TAILQ_REMOVE(&dbc->dbp->curs_queue, dbc, links);
- DB_THREAD_UNLOCK(dbc->dbp);
-
- FREE(hcp, sizeof(HASH_CURSOR));
- FREE(dbc, sizeof(DBC));
-
- return (ret);
+ return (0);
}
static int
-__ham_c_del(cursor, flags)
- DBC *cursor;
+__ham_c_del(dbc, flags)
+ DBC *dbc;
u_int32_t flags;
{
- DB *ldbp;
+ DB *dbp;
+ DBT repldbt;
HASH_CURSOR *hcp;
HASH_CURSOR save_curs;
- HTAB *hashp;
db_pgno_t ppgno, chg_pgno;
int ret, t_ret;
- DEBUG_LWRITE(cursor->dbp, cursor->txn, "ham_c_del", NULL, NULL, flags);
- ldbp = cursor->dbp;
- if (F_ISSET(cursor->dbp, DB_AM_THREAD) &&
- (ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0)
- return (ret);
- hashp = (HTAB *)ldbp->internal;
- hcp = (HASH_CURSOR *)cursor->internal;
- save_curs = *hcp;
- if ((ret = __db_cdelchk(ldbp, flags,
- F_ISSET(ldbp, DB_AM_RDONLY), IS_VALID(hcp))) != 0)
+ DEBUG_LWRITE(dbc, dbc->txn, "ham_c_del", NULL, NULL, flags);
+ dbp = dbc->dbp;
+ DB_PANIC_CHECK(dbp);
+ hcp = (HASH_CURSOR *)dbc->internal;
+
+ if ((ret = __db_cdelchk(dbc->dbp, flags,
+ F_ISSET(dbc->dbp, DB_AM_RDONLY), IS_VALID(hcp))) != 0)
return (ret);
+
if (F_ISSET(hcp, H_DELETED))
return (DB_NOTFOUND);
- SET_LOCKER(hashp->dbp, cursor->txn);
- GET_META(hashp->dbp, hashp);
- hashp->hash_accesses++;
- if ((ret = __ham_get_cpage(hashp, hcp, DB_LOCK_WRITE)) != 0)
+ /*
+ * If we are in the concurrent DB product and this cursor
+ * is not a write cursor, then this request is invalid.
+ * If it is a simple write cursor, then we need to upgrade its
+ * lock.
+ */
+ if (F_ISSET(dbp, DB_AM_CDB)) {
+ /* Make sure it's a valid update cursor. */
+ if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER))
+ return (EINVAL);
+
+ if (F_ISSET(dbc, DBC_RMW) &&
+ (ret = lock_get(dbp->dbenv->lk_info, dbc->locker,
+ DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE,
+ &dbc->mylock)) != 0)
+ return (EAGAIN);
+ }
+
+ GET_META(dbp, hcp, ret);
+ if (ret != 0)
+ return (ret);
+
+ SAVE_CURSOR(hcp, &save_curs);
+ hcp->stats.hash_deleted++;
+
+ if ((ret = __ham_get_cpage(dbc, DB_LOCK_WRITE)) != 0)
goto out;
if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno != PGNO_INVALID) {
/*
@@ -695,20 +428,20 @@ __ham_c_del(cursor, flags)
/* Remove item from duplicate page. */
chg_pgno = hcp->dpgno;
- if ((ret = __db_drem(hashp->dbp,
+ if ((ret = __db_drem(dbc,
&hcp->dpagep, hcp->dndx, __ham_del_page)) != 0)
goto out;
if (hcp->dpagep == NULL) {
if (ppgno != PGNO_INVALID) { /* Case 3 */
hcp->dpgno = ppgno;
- if ((ret = __ham_get_cpage(hashp, hcp,
+ if ((ret = __ham_get_cpage(dbc,
DB_LOCK_READ)) != 0)
goto out;
hcp->dndx = NUM_ENT(hcp->dpagep);
F_SET(hcp, H_DELETED);
} else { /* Case 4 */
- ret = __ham_del_pair(hashp, hcp, 1);
+ ret = __ham_del_pair(dbc, 1);
hcp->dpgno = PGNO_INVALID;
/*
* Delpair updated the cursor queue, so we
@@ -723,6 +456,15 @@ __ham_c_del(cursor, flags)
memcpy(HOFFDUP_PGNO(P_ENTRY(hcp->pagep,
H_DATAINDEX(hcp->bndx))),
&hcp->dpgno, sizeof(db_pgno_t));
+ /*
+ * We need to put the master page here, because
+ * although we have a duplicate page, the master
+ * page is dirty, and ham_item_done assumes that
+ * if you have a duplicate page, it's the only one
+ * that can be dirty.
+ */
+ ret = __ham_put_page(dbp, hcp->pagep, 1);
+ hcp->pagep = NULL;
F_SET(hcp, H_DELETED);
} else /* Case 1 */
F_SET(hcp, H_DELETED);
@@ -730,17 +472,17 @@ __ham_c_del(cursor, flags)
__ham_c_update(hcp, chg_pgno, 0, 0, 1);
} else if (F_ISSET(hcp, H_ISDUP)) { /* on page */
if (hcp->dup_off == 0 && DUP_SIZE(hcp->dup_len) ==
- LEN_HDATA(hcp->pagep, hashp->hdr->pagesize, hcp->bndx))
- ret = __ham_del_pair(hashp, hcp, 1);
+ LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx))
+ ret = __ham_del_pair(dbc, 1);
else {
- DBT repldbt;
-
repldbt.flags = 0;
F_SET(&repldbt, DB_DBT_PARTIAL);
repldbt.doff = hcp->dup_off;
repldbt.dlen = DUP_SIZE(hcp->dup_len);
repldbt.size = 0;
- ret = __ham_replpair(hashp, hcp, &repldbt, 0);
+ repldbt.data =
+ HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
+ ret = __ham_replpair(dbc, &repldbt, 0);
hcp->dup_tlen -= DUP_SIZE(hcp->dup_len);
F_SET(hcp, H_DELETED);
__ham_c_update(hcp, hcp->pgno,
@@ -749,48 +491,53 @@ __ham_c_del(cursor, flags)
} else
/* Not a duplicate */
-normal: ret = __ham_del_pair(hashp, hcp, 1);
+normal: ret = __ham_del_pair(dbc, 1);
-out: if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
+out: if ((t_ret = __ham_item_done(dbc, ret == 0)) != 0 && ret == 0)
ret = t_ret;
- if (ret != 0)
- *hcp = save_curs;
- RELEASE_META(hashp->dbp, hashp);
- if (F_ISSET(cursor->dbp, DB_AM_THREAD))
- __db_puthandle(ldbp);
+ RELEASE_META(dbp, hcp);
+ RESTORE_CURSOR(dbp, hcp, &save_curs, ret);
+ if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW))
+ (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock,
+ DB_LOCK_IWRITE, 0);
return (ret);
}
static int
-__ham_c_get(cursor, key, data, flags)
- DBC *cursor;
+__ham_c_get(dbc, key, data, flags)
+ DBC *dbc;
DBT *key;
DBT *data;
u_int32_t flags;
{
- DB *ldbp;
- HTAB *hashp;
+ DB *dbp;
HASH_CURSOR *hcp, save_curs;
+ db_lockmode_t lock_type;
int get_key, ret, t_ret;
- DEBUG_LREAD(cursor->dbp, cursor->txn, "ham_c_get",
+ DEBUG_LREAD(dbc, dbc->txn, "ham_c_get",
flags == DB_SET || flags == DB_SET_RANGE ? key : NULL,
NULL, flags);
- ldbp = cursor->dbp;
- if (F_ISSET(cursor->dbp, DB_AM_THREAD) &&
- (ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0)
- return (ret);
- hashp = (HTAB *)(ldbp->internal);
- hcp = (HASH_CURSOR *)cursor->internal;
- save_curs = *hcp;
+
+ hcp = (HASH_CURSOR *)dbc->internal;
+ dbp = dbc->dbp;
+ DB_PANIC_CHECK(dbp);
+ SAVE_CURSOR(hcp, &save_curs);
if ((ret =
- __db_cgetchk(hashp->dbp, key, data, flags, IS_VALID(hcp))) != 0)
+ __db_cgetchk(dbp, key, data, flags, IS_VALID(hcp))) != 0)
return (ret);
- SET_LOCKER(hashp->dbp, cursor->txn);
- GET_META(hashp->dbp, hashp);
- hashp->hash_accesses++;
+ /* Clear OR'd in additional bits so we can check for flag equality. */
+ if (LF_ISSET(DB_RMW)) {
+ lock_type = DB_LOCK_WRITE;
+ LF_CLR(DB_RMW);
+ } else
+ lock_type = DB_LOCK_READ;
+ GET_META(dbp, hcp, ret);
+ if (ret != 0)
+ return (ret);
+ hcp->stats.hash_get++;
hcp->seek_size = 0;
ret = 0;
@@ -798,24 +545,39 @@ __ham_c_get(cursor, key, data, flags)
switch (flags) {
case DB_PREV:
if (hcp->bucket != BUCKET_INVALID) {
- ret = __ham_item_prev(hashp, hcp, DB_LOCK_READ);
+ ret = __ham_item_prev(dbc, lock_type);
break;
}
/* FALLTHROUGH */
case DB_LAST:
- ret = __ham_item_last(hashp, hcp, DB_LOCK_READ);
+ ret = __ham_item_last(dbc, lock_type);
break;
case DB_FIRST:
- ret = __ham_item_first(hashp, hcp, DB_LOCK_READ);
+ ret = __ham_item_first(dbc, lock_type);
+ break;
+ case DB_NEXT_DUP:
+ if (hcp->bucket == BUCKET_INVALID)
+ ret = EINVAL;
+ else {
+ F_SET(hcp, H_DUPONLY);
+ ret = __ham_item_next(dbc, lock_type);
+ }
break;
case DB_NEXT:
if (hcp->bucket == BUCKET_INVALID)
hcp->bucket = 0;
- ret = __ham_item_next(hashp, hcp, DB_LOCK_READ);
+ ret = __ham_item_next(dbc, lock_type);
break;
case DB_SET:
case DB_SET_RANGE:
- ret = __ham_lookup(hashp, hcp, key, 0, DB_LOCK_READ);
+ case DB_GET_BOTH:
+ if (F_ISSET(dbc, DBC_CONTINUE)) {
+ F_SET(hcp, H_DUPONLY);
+ ret = __ham_item_next(dbc, lock_type);
+ } else if (F_ISSET(dbc, DBC_KEYSET))
+ ret = __ham_item(dbc, lock_type);
+ else
+ ret = __ham_lookup(dbc, key, 0, lock_type);
get_key = 0;
break;
case DB_CURRENT:
@@ -824,7 +586,7 @@ __ham_c_get(cursor, key, data, flags)
goto out;
}
- ret = __ham_item(hashp, hcp, DB_LOCK_READ);
+ ret = __ham_item(dbc, lock_type);
break;
}
@@ -837,12 +599,12 @@ __ham_c_get(cursor, key, data, flags)
goto out1;
else if (F_ISSET(hcp, H_OK)) {
/* Get the key. */
- if (get_key && (ret = __db_ret(hashp->dbp, hcp->pagep,
- H_KEYINDEX(hcp->bndx), key, &hcp->big_key,
- &hcp->big_keylen)) != 0)
+ if (get_key && (ret = __db_ret(dbp, hcp->pagep,
+ H_KEYINDEX(hcp->bndx), key, &dbc->rkey.data,
+ &dbc->rkey.size)) != 0)
goto out1;
- ret = __ham_dup_return(hashp, hcp, data, flags);
+ ret = __ham_dup_return(dbc, data, flags);
break;
} else if (!F_ISSET(hcp, H_NOMORE)) {
abort();
@@ -855,7 +617,7 @@ __ham_c_get(cursor, key, data, flags)
switch (flags) {
case DB_LAST:
case DB_PREV:
- ret = __ham_item_done(hashp, hcp, 0);
+ ret = __ham_item_done(dbc, 0);
if (hcp->bucket == 0) {
ret = DB_NOTFOUND;
goto out1;
@@ -863,24 +625,24 @@ __ham_c_get(cursor, key, data, flags)
hcp->bucket--;
hcp->bndx = NDX_INVALID;
if (ret == 0)
- ret = __ham_item_prev(hashp,
- hcp, DB_LOCK_READ);
+ ret = __ham_item_prev(dbc, lock_type);
break;
case DB_FIRST:
case DB_NEXT:
- ret = __ham_item_done(hashp, hcp, 0);
+ ret = __ham_item_done(dbc, 0);
hcp->bndx = NDX_INVALID;
hcp->bucket++;
hcp->pgno = PGNO_INVALID;
hcp->pagep = NULL;
- if (hcp->bucket > hashp->hdr->max_bucket) {
+ if (hcp->bucket > hcp->hdr->max_bucket) {
ret = DB_NOTFOUND;
goto out1;
}
if (ret == 0)
- ret = __ham_item_next(hashp,
- hcp, DB_LOCK_READ);
+ ret = __ham_item_next(dbc, lock_type);
break;
+ case DB_GET_BOTH:
+ case DB_NEXT_DUP:
case DB_SET:
case DB_SET_RANGE:
/* Key not found. */
@@ -888,85 +650,137 @@ __ham_c_get(cursor, key, data, flags)
goto out1;
}
}
-out1: if ((t_ret = __ham_item_done(hashp, hcp, 0)) != 0 && ret == 0)
+out1: if ((t_ret = __ham_item_done(dbc, 0)) != 0 && ret == 0)
ret = t_ret;
-out: if (ret)
- *hcp = save_curs;
- RELEASE_META(hashp->dbp, hashp);
- if (F_ISSET(cursor->dbp, DB_AM_THREAD))
- __db_puthandle(ldbp);
+out: RELEASE_META(dbp, hcp);
+ RESTORE_CURSOR(dbp, hcp, &save_curs, ret);
return (ret);
}
static int
-__ham_c_put(cursor, key, data, flags)
- DBC *cursor;
+__ham_c_put(dbc, key, data, flags)
+ DBC *dbc;
DBT *key;
DBT *data;
u_int32_t flags;
{
- DB *ldbp;
+ DB *dbp;
+ DBT tmp_val, *myval;
HASH_CURSOR *hcp, save_curs;
- HTAB *hashp;
u_int32_t nbytes;
int ret, t_ret;
- DEBUG_LWRITE(cursor->dbp, cursor->txn, "ham_c_put",
+ dbp = dbc->dbp;
+ DB_PANIC_CHECK(dbp);
+ DEBUG_LWRITE(dbc, dbc->txn, "ham_c_put",
flags == DB_KEYFIRST || flags == DB_KEYLAST ? key : NULL,
data, flags);
- ldbp = cursor->dbp;
- if (F_ISSET(cursor->dbp, DB_AM_THREAD) &&
- (ret = __db_gethandle(cursor->dbp, __ham_hdup, &ldbp)) != 0)
- return (ret);
- hashp = (HTAB *)(ldbp->internal);
- hcp = (HASH_CURSOR *)cursor->internal;
- save_curs = *hcp;
+ hcp = (HASH_CURSOR *)dbc->internal;
- if ((ret = __db_cputchk(hashp->dbp, key, data, flags,
- F_ISSET(ldbp, DB_AM_RDONLY), IS_VALID(hcp))) != 0)
+ if ((ret = __db_cputchk(dbp, key, data, flags,
+ F_ISSET(dbp, DB_AM_RDONLY), IS_VALID(hcp))) != 0)
return (ret);
- if (F_ISSET(hcp, H_DELETED))
+
+ if (F_ISSET(hcp, H_DELETED) &&
+ flags != DB_KEYFIRST && flags != DB_KEYLAST)
return (DB_NOTFOUND);
- SET_LOCKER(hashp->dbp, cursor->txn);
- GET_META(hashp->dbp, hashp);
- ret = 0;
+ /*
+ * If we are in the concurrent DB product and this cursor
+ * is not a write cursor, then this request is invalid.
+ * If it is a simple write cursor, then we need to upgrade its
+ * lock.
+ */
+ if (F_ISSET(dbp, DB_AM_CDB)) {
+ /* Make sure it's a valid update cursor. */
+ if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER))
+ return (EINVAL);
+
+ if (F_ISSET(dbc, DBC_RMW) &&
+ (ret = lock_get(dbp->dbenv->lk_info, dbc->locker,
+ DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE,
+ &dbc->mylock)) != 0)
+ return (EAGAIN);
+ }
+
+ GET_META(dbp, hcp, ret);
+ if (ret != 0)
+ return (ret);
+
+ SAVE_CURSOR(hcp, &save_curs);
+ hcp->stats.hash_put++;
switch (flags) {
case DB_KEYLAST:
case DB_KEYFIRST:
- nbytes = (ISBIG(hashp, key->size) ? HOFFPAGE_PSIZE :
+ nbytes = (ISBIG(hcp, key->size) ? HOFFPAGE_PSIZE :
HKEYDATA_PSIZE(key->size)) +
- (ISBIG(hashp, data->size) ? HOFFPAGE_PSIZE :
+ (ISBIG(hcp, data->size) ? HOFFPAGE_PSIZE :
HKEYDATA_PSIZE(data->size));
- ret = __ham_lookup(hashp, hcp, key, nbytes, DB_LOCK_WRITE);
+ if ((ret = __ham_lookup(dbc,
+ key, nbytes, DB_LOCK_WRITE)) == DB_NOTFOUND) {
+ ret = 0;
+ if (hcp->seek_found_page != PGNO_INVALID &&
+ hcp->seek_found_page != hcp->pgno) {
+ if ((ret = __ham_item_done(dbc, 0)) != 0)
+ goto out;
+ hcp->pgno = hcp->seek_found_page;
+ hcp->bndx = NDX_INVALID;
+ }
+
+ if (F_ISSET(data, DB_DBT_PARTIAL) && data->doff != 0) {
+ /*
+ * A partial put, but the key does not exist
+ * and we are not beginning the write at 0.
+ * We must create a data item padded up to doff
+ * and then write the new bytes represented by
+ * val.
+ */
+ if ((ret = __ham_init_dbt(&tmp_val,
+ data->size + data->doff,
+ &dbc->rdata.data, &dbc->rdata.size)) == 0) {
+ memset(tmp_val.data, 0, data->doff);
+ memcpy((u_int8_t *)tmp_val.data +
+ data->doff, data->data, data->size);
+ myval = &tmp_val;
+ }
+ } else
+ myval = (DBT *)data;
+
+ if (ret == 0)
+ ret = __ham_add_el(dbc, key, myval, H_KEYDATA);
+ goto done;
+ }
break;
case DB_BEFORE:
case DB_AFTER:
case DB_CURRENT:
- ret = __ham_item(hashp, hcp, DB_LOCK_WRITE);
+ ret = __ham_item(dbc, DB_LOCK_WRITE);
break;
}
if (ret == 0) {
- if (flags == DB_CURRENT && !F_ISSET(ldbp, DB_AM_DUP))
- ret = __ham_overwrite(hashp, hcp, data);
+ if ((flags == DB_CURRENT && !F_ISSET(hcp, H_ISDUP)) ||
+ ((flags == DB_KEYFIRST || flags == DB_KEYLAST) &&
+ !F_ISSET(dbp, DB_AM_DUP)))
+ ret = __ham_overwrite(dbc, data);
else
- ret = __ham_add_dup(hashp, hcp, data, flags);
+ ret = __ham_add_dup(dbc, data, flags);
}
- if (ret == 0 && F_ISSET(hcp, H_EXPAND)) {
- ret = __ham_expand_table(hashp);
+done: if (ret == 0 && F_ISSET(hcp, H_EXPAND)) {
+ ret = __ham_expand_table(dbc);
F_CLR(hcp, H_EXPAND);
}
- if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
+ if ((t_ret = __ham_item_done(dbc, ret == 0)) != 0 && ret == 0)
ret = t_ret;
- if (ret != 0)
- *hcp = save_curs;
- RELEASE_META(hashp->dbp, hashp);
- if (F_ISSET(cursor->dbp, DB_AM_THREAD))
- __db_puthandle(ldbp);
+
+out: RELEASE_META(dbp, hcp);
+ RESTORE_CURSOR(dbp, hcp, &save_curs, ret);
+ if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW))
+ (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock,
+ DB_LOCK_IWRITE, 0);
return (ret);
}
@@ -974,19 +788,21 @@ __ham_c_put(cursor, key, data, flags)
/*
* __ham_expand_table --
- *
- * PUBLIC: int __ham_expand_table __P((HTAB *));
*/
-int
-__ham_expand_table(hashp)
- HTAB *hashp;
+static int
+__ham_expand_table(dbc)
+ DBC *dbc;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DB_LSN new_lsn;
u_int32_t old_bucket, new_bucket, spare_ndx;
int ret;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
ret = 0;
- DIRTY_META(hashp, ret);
+ DIRTY_META(dbp, hcp, ret);
if (ret)
return (ret);
@@ -999,78 +815,78 @@ __ham_expand_table(hashp)
* see what the log of one greater than that is; here we have to
* look at the log of max + 2. VERY NASTY STUFF.
*/
- if (__db_log2(hashp->hdr->max_bucket + 2) > hashp->hdr->ovfl_point) {
+ if (__db_log2(hcp->hdr->max_bucket + 2) > hcp->hdr->ovfl_point) {
/*
* We are about to shift the split point. Make sure that
* if the next doubling is going to be big (more than 8
* pages), we have some extra pages around.
*/
- if (hashp->hdr->max_bucket + 1 >= 8 &&
- hashp->hdr->spares[hashp->hdr->ovfl_point] <
- hashp->hdr->spares[hashp->hdr->ovfl_point - 1] +
- hashp->hdr->ovfl_point + 1)
- __ham_init_ovflpages(hashp);
+ if (hcp->hdr->max_bucket + 1 >= 8 &&
+ hcp->hdr->spares[hcp->hdr->ovfl_point] <
+ hcp->hdr->spares[hcp->hdr->ovfl_point - 1] +
+ hcp->hdr->ovfl_point + 1)
+ __ham_init_ovflpages(dbc);
}
/* Now we can log the meta-data split. */
- if (DB_LOGGING(hashp->dbp)) {
- if ((ret = __ham_splitmeta_log(hashp->dbp->dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
- hashp->dbp->log_fileid,
- hashp->hdr->max_bucket, hashp->hdr->ovfl_point,
- hashp->hdr->spares[hashp->hdr->ovfl_point],
- &hashp->hdr->lsn)) != 0)
+ if (DB_LOGGING(dbc)) {
+ if ((ret = __ham_splitmeta_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, dbp->log_fileid,
+ hcp->hdr->max_bucket, hcp->hdr->ovfl_point,
+ hcp->hdr->spares[hcp->hdr->ovfl_point],
+ &hcp->hdr->lsn)) != 0)
return (ret);
- hashp->hdr->lsn = new_lsn;
+ hcp->hdr->lsn = new_lsn;
}
- hashp->hash_expansions++;
- new_bucket = ++hashp->hdr->max_bucket;
- old_bucket = (hashp->hdr->max_bucket & hashp->hdr->low_mask);
+ hcp->stats.hash_expansions++;
+ new_bucket = ++hcp->hdr->max_bucket;
+ old_bucket = (hcp->hdr->max_bucket & hcp->hdr->low_mask);
/*
* If the split point is increasing, copy the current contents
* of the spare split bucket to the next bucket.
*/
- spare_ndx = __db_log2(hashp->hdr->max_bucket + 1);
- if (spare_ndx > hashp->hdr->ovfl_point) {
- hashp->hdr->spares[spare_ndx] =
- hashp->hdr->spares[hashp->hdr->ovfl_point];
- hashp->hdr->ovfl_point = spare_ndx;
+ spare_ndx = __db_log2(hcp->hdr->max_bucket + 1);
+ if (spare_ndx > hcp->hdr->ovfl_point) {
+ hcp->hdr->spares[spare_ndx] =
+ hcp->hdr->spares[hcp->hdr->ovfl_point];
+ hcp->hdr->ovfl_point = spare_ndx;
}
- if (new_bucket > hashp->hdr->high_mask) {
+ if (new_bucket > hcp->hdr->high_mask) {
/* Starting a new doubling */
- hashp->hdr->low_mask = hashp->hdr->high_mask;
- hashp->hdr->high_mask = new_bucket | hashp->hdr->low_mask;
+ hcp->hdr->low_mask = hcp->hdr->high_mask;
+ hcp->hdr->high_mask = new_bucket | hcp->hdr->low_mask;
}
- if (BUCKET_TO_PAGE(hashp, new_bucket) > MAX_PAGES(hashp)) {
- __db_err(hashp->dbp->dbenv,
+ if (BUCKET_TO_PAGE(hcp, new_bucket) > MAX_PAGES(hcp)) {
+ __db_err(dbp->dbenv,
"hash: Cannot allocate new bucket. Pages exhausted.");
return (ENOSPC);
}
/* Relocate records to the new bucket */
- return (__ham_split_page(hashp, old_bucket, new_bucket));
+ return (__ham_split_page(dbc, old_bucket, new_bucket));
}
/*
- * PUBLIC: u_int32_t __ham_call_hash __P((HTAB *, u_int8_t *, int32_t));
+ * PUBLIC: u_int32_t __ham_call_hash __P((HASH_CURSOR *, u_int8_t *, int32_t));
*/
u_int32_t
-__ham_call_hash(hashp, k, len)
- HTAB *hashp;
+__ham_call_hash(hcp, k, len)
+ HASH_CURSOR *hcp;
u_int8_t *k;
int32_t len;
{
u_int32_t n, bucket;
- n = (u_int32_t)hashp->hash(k, len);
- bucket = n & hashp->hdr->high_mask;
- if (bucket > hashp->hdr->max_bucket)
- bucket = bucket & hashp->hdr->low_mask;
+ n = (u_int32_t)(hcp->dbc->dbp->h_hash(k, len));
+
+ bucket = n & hcp->hdr->high_mask;
+ if (bucket > hcp->hdr->max_bucket)
+ bucket = bucket & hcp->hdr->low_mask;
return (bucket);
}
@@ -1079,31 +895,36 @@ __ham_call_hash(hashp, k, len)
* everything held by the cursor.
*/
static int
-__ham_dup_return(hashp, hcp, val, flags)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_dup_return(dbc, val, flags)
+ DBC *dbc;
DBT *val;
u_int32_t flags;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
PAGE *pp;
DBT *myval, tmp_val;
db_indx_t ndx;
db_pgno_t pgno;
+ u_int32_t off, tlen;
u_int8_t *hk, type;
- int ret;
+ int cmp, ret;
db_indx_t len;
/* Check for duplicate and return the first one. */
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
ndx = H_DATAINDEX(hcp->bndx);
type = HPAGE_TYPE(hcp->pagep, ndx);
pp = hcp->pagep;
myval = val;
/*
- * There are 3 cases:
+ * There are 4 cases:
* 1. We are not in duplicate, simply call db_ret.
* 2. We are looking at keys and stumbled onto a duplicate.
* 3. We are in the middle of a duplicate set. (ISDUP set)
+ * 4. This is a duplicate and we need to return a specific item.
*/
/*
@@ -1115,7 +936,7 @@ __ham_dup_return(hashp, hcp, val, flags)
if (type == H_DUPLICATE) {
F_SET(hcp, H_ISDUP);
hcp->dup_tlen = LEN_HDATA(hcp->pagep,
- hashp->hdr->pagesize, hcp->bndx);
+ hcp->hdr->pagesize, hcp->bndx);
hk = H_PAIRDATA(hcp->pagep, hcp->bndx);
if (flags == DB_LAST || flags == DB_PREV) {
hcp->dndx = 0;
@@ -1141,18 +962,63 @@ __ham_dup_return(hashp, hcp, val, flags)
memcpy(&pgno, HOFFDUP_PGNO(P_ENTRY(hcp->pagep, ndx)),
sizeof(db_pgno_t));
if (flags == DB_LAST || flags == DB_PREV) {
- if ((ret = __db_dend(hashp->dbp,
+ if ((ret = __db_dend(dbc,
pgno, &hcp->dpagep)) != 0)
return (ret);
hcp->dpgno = PGNO(hcp->dpagep);
hcp->dndx = NUM_ENT(hcp->dpagep) - 1;
- } else if ((ret = __ham_next_cpage(hashp,
- hcp, pgno, 0, H_ISDUP)) != 0)
+ } else if ((ret = __ham_next_cpage(dbc,
+ pgno, 0, H_ISDUP)) != 0)
return (ret);
}
}
/*
+ * If we are retrieving a specific key/data pair, then we
+ * may need to adjust the cursor before returning data.
+ */
+ if (flags == DB_GET_BOTH) {
+ if (F_ISSET(hcp, H_ISDUP)) {
+ if (hcp->dpgno != PGNO_INVALID) {
+ if ((ret = __db_dsearch(dbc, 0, val,
+ hcp->dpgno, &hcp->dndx, &hcp->dpagep, &cmp))
+ != 0)
+ return (ret);
+ if (cmp == 0)
+ hcp->dpgno = PGNO(hcp->dpagep);
+ } else {
+ __ham_dsearch(dbc, val, &off, &cmp);
+ hcp->dup_off = off;
+ }
+ } else {
+ hk = H_PAIRDATA(hcp->pagep, hcp->bndx);
+ if (((HKEYDATA *)hk)->type == H_OFFPAGE) {
+ memcpy(&tlen,
+ HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
+ memcpy(&pgno,
+ HOFFPAGE_PGNO(hk), sizeof(db_pgno_t));
+ if ((ret = __db_moff(dbp, val,
+ pgno, tlen, dbp->dup_compare, &cmp)) != 0)
+ return (ret);
+ } else {
+ /*
+ * We do not zero tmp_val since the comparison
+ * routines may only look at data and size.
+ */
+ tmp_val.data = HKEYDATA_DATA(hk);
+ tmp_val.size = LEN_HDATA(hcp->pagep,
+ dbp->pgsize, hcp->bndx);
+ cmp = dbp->dup_compare == NULL ?
+ __bam_defcmp(&tmp_val, val) :
+ dbp->dup_compare(&tmp_val, val);
+ }
+ }
+
+ if (cmp != 0)
+ return (DB_NOTFOUND);
+ }
+
+ /*
* Now, everything is initialized, grab a duplicate if
* necessary.
*/
@@ -1162,14 +1028,34 @@ __ham_dup_return(hashp, hcp, val, flags)
ndx = hcp->dndx;
} else {
/*
- * Copy the DBT in case we are retrieving into
- * user memory and we need the parameters for
- * it.
+ * Copy the DBT in case we are retrieving into user
+ * memory and we need the parameters for it. If the
+ * user requested a partial, then we need to adjust
+ * the user's parameters to get the partial of the
+ * duplicate which is itself a partial.
*/
memcpy(&tmp_val, val, sizeof(*val));
- F_SET(&tmp_val, DB_DBT_PARTIAL);
- tmp_val.dlen = hcp->dup_len;
- tmp_val.doff = hcp->dup_off + sizeof(db_indx_t);
+ if (F_ISSET(&tmp_val, DB_DBT_PARTIAL)) {
+ /*
+ * Take the user's length unless it would go
+ * beyond the end of the duplicate.
+ */
+ if (tmp_val.doff + hcp->dup_off > hcp->dup_len)
+ tmp_val.dlen = 0;
+ else if (tmp_val.dlen + tmp_val.doff >
+ hcp->dup_len)
+ tmp_val.dlen =
+ hcp->dup_len - tmp_val.doff;
+
+ /*
+ * Calculate the new offset.
+ */
+ tmp_val.doff += hcp->dup_off;
+ } else {
+ F_SET(&tmp_val, DB_DBT_PARTIAL);
+ tmp_val.dlen = hcp->dup_len;
+ tmp_val.doff = hcp->dup_off + sizeof(db_indx_t);
+ }
myval = &tmp_val;
}
}
@@ -1178,8 +1064,8 @@ __ham_dup_return(hashp, hcp, val, flags)
* Finally, if we had a duplicate, pp, ndx, and myval should be
* set appropriately.
*/
- if ((ret = __db_ret(hashp->dbp, pp, ndx, myval, &hcp->big_data,
- &hcp->big_datalen)) != 0)
+ if ((ret = __db_ret(dbp, pp, ndx, myval, &dbc->rdata.data,
+ &dbc->rdata.size)) != 0)
return (ret);
/*
@@ -1193,16 +1079,17 @@ __ham_dup_return(hashp, hcp, val, flags)
}
static int
-__ham_overwrite(hashp, hcp, nval)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_overwrite(dbc, nval)
+ DBC *dbc;
DBT *nval;
{
+ HASH_CURSOR *hcp;
DBT *myval, tmp_val;
u_int8_t *hk;
- if (F_ISSET(hashp->dbp, DB_AM_DUP))
- return (__ham_add_dup(hashp, hcp, nval, DB_KEYLAST));
+ hcp = (HASH_CURSOR *)dbc->internal;
+ if (F_ISSET(dbc->dbp, DB_AM_DUP))
+ return (__ham_add_dup(dbc, nval, DB_KEYLAST));
else if (!F_ISSET(nval, DB_DBT_PARTIAL)) {
/* Put/overwrite */
memcpy(&tmp_val, nval, sizeof(*nval));
@@ -1214,12 +1101,12 @@ __ham_overwrite(hashp, hcp, nval)
HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
else
tmp_val.dlen = LEN_HDATA(hcp->pagep,
- hashp->hdr->pagesize,hcp->bndx);
+ hcp->hdr->pagesize,hcp->bndx);
myval = &tmp_val;
} else /* Regular partial put */
myval = nval;
- return (__ham_replpair(hashp, hcp, myval, 0));
+ return (__ham_replpair(dbc, myval, 0));
}
/*
@@ -1232,29 +1119,32 @@ __ham_overwrite(hashp, hcp, nval)
* non of the cursor pointer field are valid.
*/
static int
-__ham_lookup(hashp, hcp, key, sought, mode)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_lookup(dbc, key, sought, mode)
+ DBC *dbc;
const DBT *key;
u_int32_t sought;
db_lockmode_t mode;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
db_pgno_t pgno;
u_int32_t tlen;
int match, ret, t_ret;
u_int8_t *hk;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
/*
* Set up cursor so that we're looking for space to add an item
* as we cycle through the pages looking for the key.
*/
- if ((ret = __ham_item_reset(hashp, hcp)) != 0)
+ if ((ret = __ham_item_reset(dbc)) != 0)
return (ret);
hcp->seek_size = sought;
- hcp->bucket = __ham_call_hash(hashp, (u_int8_t *)key->data, key->size);
+ hcp->bucket = __ham_call_hash(hcp, (u_int8_t *)key->data, key->size);
while (1) {
- if ((ret = __ham_item_next(hashp, hcp, mode)) != 0)
+ if ((ret = __ham_item_next(dbc, mode)) != 0)
return (ret);
if (F_ISSET(hcp, H_NOMORE))
@@ -1267,7 +1157,9 @@ __ham_lookup(hashp, hcp, key, sought, mode)
if (tlen == key->size) {
memcpy(&pgno,
HOFFPAGE_PGNO(hk), sizeof(db_pgno_t));
- match = __db_moff(hashp->dbp, key, pgno);
+ if ((ret = __db_moff(dbp,
+ key, pgno, tlen, NULL, &match)) != 0)
+ return (ret);
if (match == 0) {
F_SET(hcp, H_OK);
return (0);
@@ -1276,7 +1168,7 @@ __ham_lookup(hashp, hcp, key, sought, mode)
break;
case H_KEYDATA:
if (key->size == LEN_HKEY(hcp->pagep,
- hashp->hdr->pagesize, hcp->bndx) &&
+ hcp->hdr->pagesize, hcp->bndx) &&
memcmp(key->data,
HKEYDATA_DATA(hk), key->size) == 0) {
F_SET(hcp, H_OK);
@@ -1289,9 +1181,9 @@ __ham_lookup(hashp, hcp, key, sought, mode)
* These are errors because keys are never
* duplicated, only data items are.
*/
- return (__db_pgfmt(hashp->dbp, PGNO(hcp->pagep)));
+ return (__db_pgfmt(dbp, PGNO(hcp->pagep)));
}
- hashp->hash_collisions++;
+ hcp->stats.hash_collisions++;
}
/*
@@ -1301,7 +1193,7 @@ __ham_lookup(hashp, hcp, key, sought, mode)
if (sought != 0)
return (ret);
- if ((t_ret = __ham_item_done(hashp, hcp, 0)) != 0 && ret == 0)
+ if ((t_ret = __ham_item_done(dbc, 0)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
@@ -1318,12 +1210,13 @@ __ham_init_dbt(dbt, size, bufp, sizep)
void **bufp;
u_int32_t *sizep;
{
+ int ret;
+
memset(dbt, 0, sizeof(*dbt));
if (*sizep < size) {
- if ((*bufp = (void *)(*bufp == NULL ?
- __db_malloc(size) : __db_realloc(*bufp, size))) == NULL) {
+ if ((ret = __os_realloc(bufp, size)) != 0) {
*sizep = 0;
- return (ENOMEM);
+ return (ret);
}
*sizep = size;
}
@@ -1352,8 +1245,8 @@ __ham_c_update(hcp, chg_pgno, len, add, is_dup)
u_int32_t len;
int add, is_dup;
{
+ DB *dbp;
DBC *cp;
- HTAB *hp;
HASH_CURSOR *lcp;
int page_deleted;
@@ -1379,10 +1272,10 @@ __ham_c_update(hcp, chg_pgno, len, add, is_dup)
page_deleted =
chg_pgno != PGNO_INVALID && chg_pgno != hcp->dpgno;
- hp = hcp->db_cursor->dbp->master->internal;
- DB_THREAD_LOCK(hp->dbp);
+ dbp = hcp->dbc->dbp;
+ DB_THREAD_LOCK(dbp);
- for (cp = TAILQ_FIRST(&hp->dbp->curs_queue); cp != NULL;
+ for (cp = TAILQ_FIRST(&dbp->active_queue); cp != NULL;
cp = TAILQ_NEXT(cp, links)) {
if (cp->internal == hcp)
continue;
@@ -1440,43 +1333,5 @@ __ham_c_update(hcp, chg_pgno, len, add, is_dup)
}
}
}
- DB_THREAD_UNLOCK(hp->dbp);
-}
-
-/*
- * __ham_hdup --
- * This function gets called when we create a duplicate handle for a
- * threaded DB. It should create the private part of the DB structure.
- *
- * PUBLIC: int __ham_hdup __P((DB *, DB *));
- */
-int
-__ham_hdup(orig, new)
- DB *orig, *new;
-{
- DBC *curs;
- HTAB *hashp;
- int ret;
-
- if ((hashp = (HTAB *)__db_malloc(sizeof(HTAB))) == NULL)
- return (ENOMEM);
-
- new->internal = hashp;
-
- hashp->dbp = new;
- hashp->hlock = 0;
- hashp->hdr = NULL;
- hashp->hash = ((HTAB *)orig->internal)->hash;
- if ((hashp->split_buf = (PAGE *)__db_malloc(orig->pgsize)) == NULL)
- return (ENOMEM);
- hashp->local_errno = 0;
- hashp->hash_accesses = 0;
- hashp->hash_collisions = 0;
- hashp->hash_expansions = 0;
- hashp->hash_overflows = 0;
- hashp->hash_bigpages = 0;
- /* Initialize the cursor queue. */
- ret = __ham_c_init(new, NULL, &curs);
- TAILQ_INSERT_TAIL(&new->curs_queue, curs, links);
- return (ret);
+ DB_THREAD_UNLOCK(dbp);
}
diff --git a/db2/hash/hash_auto.c b/db2/hash/hash_auto.c
index 41b1ebed01..94a1dff6ed 100644
--- a/db2/hash/hash_auto.c
+++ b/db2/hash/hash_auto.c
@@ -10,7 +10,6 @@
#endif
#include "db_int.h"
-#include "shqueue.h"
#include "db_page.h"
#include "db_dispatch.h"
#include "hash.h"
@@ -46,8 +45,7 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_insdel;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -59,8 +57,8 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
+ sizeof(*pagelsn)
+ sizeof(u_int32_t) + (key == NULL ? 0 : key->size)
+ sizeof(u_int32_t) + (data == NULL ? 0 : data->size);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -109,7 +107,7 @@ int __ham_insdel_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -170,7 +168,7 @@ __ham_insdel_print(notused1, dbtp, lsnp, notused2, notused3)
}
printf("\n");
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -184,11 +182,12 @@ __ham_insdel_read(recbuf, argpp)
{
__ham_insdel_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_insdel_args *)__db_malloc(sizeof(__ham_insdel_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_insdel_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
@@ -250,8 +249,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_newpage;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -264,8 +262,8 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
+ sizeof(*pagelsn)
+ sizeof(next_pgno)
+ sizeof(*nextlsn);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -306,7 +304,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -354,7 +352,7 @@ __ham_newpage_print(notused1, dbtp, lsnp, notused2, notused3)
printf("\tnextlsn: [%lu][%lu]\n",
(u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -368,11 +366,12 @@ __ham_newpage_read(recbuf, argpp)
{
__ham_newpage_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_newpage_args *)__db_malloc(sizeof(__ham_newpage_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_newpage_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
@@ -428,8 +427,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_splitmeta;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -439,8 +437,8 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
+ sizeof(ovflpoint)
+ sizeof(spares)
+ sizeof(*metalsn);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -469,7 +467,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -512,7 +510,7 @@ __ham_splitmeta_print(notused1, dbtp, lsnp, notused2, notused3)
printf("\tmetalsn: [%lu][%lu]\n",
(u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -526,11 +524,12 @@ __ham_splitmeta_read(recbuf, argpp)
{
__ham_splitmeta_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_splitmeta_args *)__db_malloc(sizeof(__ham_splitmeta_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_splitmeta_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
@@ -581,8 +580,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_splitdata;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -592,8 +590,8 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
+ sizeof(pgno)
+ sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size)
+ sizeof(*pagelsn);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -630,7 +628,7 @@ int __ham_splitdata_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -681,7 +679,7 @@ __ham_splitdata_print(notused1, dbtp, lsnp, notused2, notused3)
printf("\tpagelsn: [%lu][%lu]\n",
(u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -695,11 +693,12 @@ __ham_splitdata_read(recbuf, argpp)
{
__ham_splitdata_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_splitdata_args *)__db_malloc(sizeof(__ham_splitdata_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_splitdata_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
@@ -756,8 +755,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_replace;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -770,8 +768,8 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
+ sizeof(u_int32_t) + (olditem == NULL ? 0 : olditem->size)
+ sizeof(u_int32_t) + (newitem == NULL ? 0 : newitem->size)
+ sizeof(makedup);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -822,7 +820,7 @@ int __ham_replace_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -884,7 +882,7 @@ __ham_replace_print(notused1, dbtp, lsnp, notused2, notused3)
printf("\n");
printf("\tmakedup: %lu\n", (u_long)argp->makedup);
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -898,11 +896,12 @@ __ham_replace_read(recbuf, argpp)
{
__ham_replace_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_replace_args *)__db_malloc(sizeof(__ham_replace_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_replace_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
@@ -968,8 +967,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_newpgno;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -983,8 +981,8 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
+ sizeof(new_type)
+ sizeof(*pagelsn)
+ sizeof(*metalsn);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -1024,7 +1022,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -1072,7 +1070,7 @@ __ham_newpgno_print(notused1, dbtp, lsnp, notused2, notused3)
printf("\tmetalsn: [%lu][%lu]\n",
(u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -1086,11 +1084,12 @@ __ham_newpgno_read(recbuf, argpp)
{
__ham_newpgno_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_newpgno_args *)__db_malloc(sizeof(__ham_newpgno_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_newpgno_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
@@ -1149,8 +1148,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_ovfl;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -1161,8 +1159,8 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
+ sizeof(free_pgno)
+ sizeof(ovflpoint)
+ sizeof(*metalsn);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -1193,7 +1191,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -1237,7 +1235,7 @@ __ham_ovfl_print(notused1, dbtp, lsnp, notused2, notused3)
printf("\tmetalsn: [%lu][%lu]\n",
(u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -1251,11 +1249,12 @@ __ham_ovfl_read(recbuf, argpp)
{
__ham_ovfl_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_ovfl_args *)__db_malloc(sizeof(__ham_ovfl_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_ovfl_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
@@ -1312,8 +1311,7 @@ int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
rectype = DB_ham_copypage;
txn_num = txnid == NULL ? 0 : txnid->txnid;
if (txnid == NULL) {
- null_lsn.file = 0;
- null_lsn.offset = 0;
+ ZERO_LSN(null_lsn);
lsnp = &null_lsn;
} else
lsnp = &txnid->last_lsn;
@@ -1326,8 +1324,8 @@ int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
+ sizeof(nnext_pgno)
+ sizeof(*nnextlsn)
+ sizeof(u_int32_t) + (page == NULL ? 0 : page->size);
- if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
- return (ENOMEM);
+ if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0)
+ return (ret);
bp = logrec.data;
memcpy(bp, &rectype, sizeof(rectype));
@@ -1376,7 +1374,7 @@ int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
if (txnid != NULL)
txnid->last_lsn = *ret_lsnp;
- __db_free(logrec.data);
+ __os_free(logrec.data, 0);
return (ret);
}
@@ -1432,7 +1430,7 @@ __ham_copypage_print(notused1, dbtp, lsnp, notused2, notused3)
}
printf("\n");
printf("\n");
- __db_free(argp);
+ __os_free(argp, 0);
return (0);
}
@@ -1446,11 +1444,12 @@ __ham_copypage_read(recbuf, argpp)
{
__ham_copypage_args *argp;
u_int8_t *bp;
+ int ret;
- argp = (__ham_copypage_args *)__db_malloc(sizeof(__ham_copypage_args) +
- sizeof(DB_TXN));
- if (argp == NULL)
- return (ENOMEM);
+ ret = __os_malloc(sizeof(__ham_copypage_args) +
+ sizeof(DB_TXN), NULL, &argp);
+ if (ret != 0)
+ return (ret);
argp->txnid = (DB_TXN *)&argp[1];
bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
diff --git a/db2/hash/hash_debug.c b/db2/hash/hash_debug.c
deleted file mode 100644
index 232906ae34..0000000000
--- a/db2/hash/hash_debug.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * See the file LICENSE for redistribution information.
- *
- * Copyright (c) 1996, 1997, 1998
- * Sleepycat Software. All rights reserved.
- */
-/*
- * Copyright (c) 1995
- * The President and Fellows of Harvard University. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jeremy Rassen.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)hash_debug.c 10.6 (Sleepycat) 5/7/98";
-#endif /* not lint */
-
-#ifdef DEBUG
-/*
- * PACKAGE: hashing
- *
- * DESCRIPTION:
- * Debug routines.
- *
- * ROUTINES:
- *
- * External
- * __dump_bucket
- */
-#ifndef NO_SYSTEM_INCLUDES
-#include <sys/types.h>
-#endif
-
-#include "db_int.h"
-#include "db_page.h"
-#include "hash.h"
-
-/*
- * __ham_dump_bucket --
- *
- * PUBLIC: #ifdef DEBUG
- * PUBLIC: void __ham_dump_bucket __P((HTAB *, u_int32_t));
- * PUBLIC: #endif
- */
-void
-__ham_dump_bucket(hashp, bucket)
- HTAB *hashp;
- u_int32_t bucket;
-{
- PAGE *p;
- db_pgno_t pgno;
-
- for (pgno = BUCKET_TO_PAGE(hashp, bucket); pgno != PGNO_INVALID;) {
- if (memp_fget(hashp->dbp->mpf, &pgno, 0, &p) != 0)
- break;
- (void)__db_prpage(p, 1);
- pgno = p->next_pgno;
- (void)memp_fput(hashp->dbp->mpf, p, 0);
- }
-}
-#endif /* DEBUG */
diff --git a/db2/hash/hash_dup.c b/db2/hash/hash_dup.c
index ba248ddb17..bb3466428d 100644
--- a/db2/hash/hash_dup.c
+++ b/db2/hash/hash_dup.c
@@ -42,7 +42,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)hash_dup.c 10.14 (Sleepycat) 5/7/98";
+static const char sccsid[] = "@(#)hash_dup.c 10.27 (Sleepycat) 12/6/98";
#endif /* not lint */
/*
@@ -61,15 +61,17 @@ static const char sccsid[] = "@(#)hash_dup.c 10.14 (Sleepycat) 5/7/98";
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#include <errno.h>
#include <string.h>
#endif
#include "db_int.h"
#include "db_page.h"
#include "hash.h"
+#include "btree.h"
-static int __ham_check_move __P((HTAB *, HASH_CURSOR *, int32_t));
-static int __ham_dup_convert __P((HTAB *, HASH_CURSOR *));
+static int __ham_check_move __P((DBC *, int32_t));
+static int __ham_dup_convert __P((DBC *));
static int __ham_make_dup __P((const DBT *, DBT *d, void **, u_int32_t *));
/*
@@ -85,26 +87,29 @@ static int __ham_make_dup __P((const DBT *, DBT *d, void **, u_int32_t *));
* Case 4: The element is large enough to push the duplicate set onto a
* separate page.
*
- * PUBLIC: int __ham_add_dup __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
+ * PUBLIC: int __ham_add_dup __P((DBC *, DBT *, u_int32_t));
*/
int
-__ham_add_dup(hashp, hcp, nval, flags)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_add_dup(dbc, nval, flags)
+ DBC *dbc;
DBT *nval;
u_int32_t flags;
{
- DBT pval, tmp_val;
+ DB *dbp;
+ HASH_CURSOR *hcp;
+ DBT dbt, pval, tmp_val;
u_int32_t del_len, new_size;
- int ret;
+ int cmp, ret;
u_int8_t *hk;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
if (flags == DB_CURRENT && hcp->dpgno == PGNO_INVALID)
del_len = hcp->dup_len;
else
del_len = 0;
- if ((ret = __ham_check_move(hashp, hcp,
+ if ((ret = __ham_check_move(dbc,
(int32_t)DUP_SIZE(nval->size) - (int32_t)del_len)) != 0)
return (ret);
@@ -117,7 +122,7 @@ __ham_add_dup(hashp, hcp, nval, flags)
*/
hk = H_PAIRDATA(hcp->pagep, hcp->bndx);
new_size = DUP_SIZE(nval->size) - del_len + LEN_HKEYDATA(hcp->pagep,
- hashp->hdr->pagesize, H_DATAINDEX(hcp->bndx));
+ hcp->hdr->pagesize, H_DATAINDEX(hcp->bndx));
/*
* We convert to off-page duplicates if the item is a big item,
@@ -125,10 +130,10 @@ __ham_add_dup(hashp, hcp, nval, flags)
* if there isn't enough room on this page to add the next item.
*/
if (HPAGE_PTYPE(hk) != H_OFFDUP &&
- (HPAGE_PTYPE(hk) == H_OFFPAGE || ISBIG(hashp, new_size) ||
+ (HPAGE_PTYPE(hk) == H_OFFPAGE || ISBIG(hcp, new_size) ||
DUP_SIZE(nval->size) - del_len > P_FREESPACE(hcp->pagep))) {
- if ((ret = __ham_dup_convert(hashp, hcp)) != 0)
+ if ((ret = __ham_dup_convert(dbc)) != 0)
return (ret);
else
hk = H_PAIRDATA(hcp->pagep, hcp->bndx);
@@ -140,30 +145,44 @@ __ham_add_dup(hashp, hcp, nval, flags)
HPAGE_PTYPE(hk) = H_DUPLICATE;
pval.flags = 0;
pval.data = HKEYDATA_DATA(hk);
- pval.size = LEN_HDATA(hcp->pagep, hashp->hdr->pagesize,
+ pval.size = LEN_HDATA(hcp->pagep, dbp->pgsize,
hcp->bndx);
if ((ret =
- __ham_make_dup(&pval, &tmp_val, &hcp->big_data,
- &hcp->big_datalen)) != 0 || (ret =
- __ham_replpair(hashp, hcp, &tmp_val, 1)) != 0)
+ __ham_make_dup(&pval, &tmp_val, &dbc->rdata.data,
+ &dbc->rdata.size)) != 0 || (ret =
+ __ham_replpair(dbc, &tmp_val, 1)) != 0)
return (ret);
}
/* Now make the new entry a duplicate. */
if ((ret = __ham_make_dup(nval,
- &tmp_val, &hcp->big_data, &hcp->big_datalen)) != 0)
+ &tmp_val, &dbc->rdata.data, &dbc->rdata.size)) != 0)
return (ret);
tmp_val.dlen = 0;
switch (flags) { /* On page. */
case DB_KEYFIRST:
- tmp_val.doff = 0;
- break;
case DB_KEYLAST:
- tmp_val.doff = LEN_HDATA(hcp->pagep,
- hashp->hdr->pagesize, hcp->bndx);
+ if (dbp->dup_compare != NULL)
+ __ham_dsearch(dbc, nval, &tmp_val.doff, &cmp);
+ else if (flags == DB_KEYFIRST)
+ tmp_val.doff = 0;
+ else
+ tmp_val.doff = LEN_HDATA(hcp->pagep,
+ hcp->hdr->pagesize, hcp->bndx);
break;
case DB_CURRENT:
+ /*
+ * If we have a sort function, we need to verify that
+ * the new item sorts identically to the old item.
+ */
+ if (dbp->dup_compare != NULL) {
+ dbt.data = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep,
+ hcp->bndx)) + hcp->dup_off;
+ dbt.size = DUP_SIZE(hcp->dup_len);
+ if (dbp->dup_compare(nval, &dbt) != 0)
+ return (EINVAL);
+ }
tmp_val.doff = hcp->dup_off;
tmp_val.dlen = DUP_SIZE(hcp->dup_len);
break;
@@ -175,9 +194,9 @@ __ham_add_dup(hashp, hcp, nval, flags)
break;
}
/* Add the duplicate. */
- ret = __ham_replpair(hashp, hcp, &tmp_val, 0);
+ ret = __ham_replpair(dbc, &tmp_val, 0);
if (ret == 0)
- ret = __ham_dirty_page(hashp, hcp->pagep);
+ ret = __ham_dirty_page(dbp, hcp->pagep);
__ham_c_update(hcp, hcp->pgno, tmp_val.size, 1, 1);
return (ret);
}
@@ -190,27 +209,48 @@ __ham_add_dup(hashp, hcp, nval, flags)
switch (flags) {
case DB_KEYFIRST:
+ if (dbp->dup_compare != NULL)
+ goto sorted_dups;
/*
* The only way that we are already on a dup page is
* if we just converted the on-page representation.
* In that case, we've only got one page of duplicates.
*/
if (hcp->dpagep == NULL && (ret =
- __db_dend(hashp->dbp, hcp->dpgno, &hcp->dpagep)) != 0)
+ __db_dend(dbc, hcp->dpgno, &hcp->dpagep)) != 0)
return (ret);
hcp->dndx = 0;
break;
case DB_KEYLAST:
- if (hcp->dpagep == NULL && (ret =
- __db_dend(hashp->dbp, hcp->dpgno, &hcp->dpagep)) != 0)
- return (ret);
- hcp->dpgno = PGNO(hcp->dpagep);
- hcp->dndx = NUM_ENT(hcp->dpagep);
+ if (dbp->dup_compare != NULL) {
+sorted_dups: if ((ret = __db_dsearch(dbc, 1, nval,
+ hcp->dpgno, &hcp->dndx, &hcp->dpagep, &cmp)) != 0)
+ return (ret);
+ if (cmp == 0)
+ hcp->dpgno = PGNO(hcp->dpagep);
+ } else {
+ if (hcp->dpagep == NULL && (ret =
+ __db_dend(dbc, hcp->dpgno, &hcp->dpagep)) != 0)
+ return (ret);
+ hcp->dpgno = PGNO(hcp->dpagep);
+ hcp->dndx = NUM_ENT(hcp->dpagep);
+ }
break;
case DB_CURRENT:
- if ((ret = __db_ditem(hashp->dbp, hcp->dpagep, hcp->dndx,
- BKEYDATA_SIZE(GET_BKEYDATA(hcp->dpagep, hcp->dndx)->len)))
- != 0)
+ if (dbp->dup_compare != NULL && __bam_cmp(dbp,
+ nval, hcp->dpagep, hcp->dndx, dbp->dup_compare) != 0)
+ return (EINVAL);
+ switch (GET_BKEYDATA(hcp->dpagep, hcp->dndx)->type) {
+ case B_KEYDATA:
+ del_len = BKEYDATA_SIZE(GET_BKEYDATA(hcp->dpagep,
+ hcp->dndx)->len);
+ break;
+ case B_OVERFLOW:
+ del_len = BOVERFLOW_SIZE;
+ break;
+ }
+ if ((ret =
+ __db_ditem(dbc, hcp->dpagep, hcp->dndx, del_len)) != 0)
return (ret);
break;
case DB_BEFORE: /* The default behavior is correct. */
@@ -220,7 +260,7 @@ __ham_add_dup(hashp, hcp, nval, flags)
break;
}
- ret = __db_dput(hashp->dbp,
+ ret = __db_dput(dbc,
nval, &hcp->dpagep, &hcp->dndx, __ham_overflow_page);
hcp->pgno = PGNO(hcp->pagep);
__ham_c_update(hcp, hcp->pgno, nval->size, 1, 1);
@@ -231,22 +271,25 @@ __ham_add_dup(hashp, hcp, nval, flags)
* Convert an on-page set of duplicates to an offpage set of duplicates.
*/
static int
-__ham_dup_convert(hashp, hcp)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_dup_convert(dbc)
+ DBC *dbc;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
BOVERFLOW bo;
DBT dbt;
HOFFPAGE ho;
- db_indx_t dndx, len;
+ db_indx_t dndx, i, len, off;
int ret;
u_int8_t *p, *pend;
/*
* Create a new page for the duplicates.
*/
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
if ((ret =
- __ham_overflow_page(hashp->dbp, P_DUPLICATE, &hcp->dpagep)) != 0)
+ __ham_overflow_page(dbc, P_DUPLICATE, &hcp->dpagep)) != 0)
return (ret);
hcp->dpagep->type = P_DUPLICATE;
hcp->dpgno = PGNO(hcp->dpagep);
@@ -254,67 +297,80 @@ __ham_dup_convert(hashp, hcp)
/*
* Now put the duplicates onto the new page.
*/
+ dndx = 0;
dbt.flags = 0;
switch (HPAGE_PTYPE(H_PAIRDATA(hcp->pagep, hcp->bndx))) {
case H_KEYDATA:
/* Simple case, one key on page; move it to dup page. */
- dndx = 0;
dbt.size =
- LEN_HDATA(hcp->pagep, hashp->hdr->pagesize, hcp->bndx);
+ LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx);
dbt.data = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
- ret = __db_pitem(hashp->dbp, hcp->dpagep,
+ ret = __db_pitem(dbc, hcp->dpagep,
(u_int32_t)dndx, BKEYDATA_SIZE(dbt.size), NULL, &dbt);
if (ret == 0)
- __ham_dirty_page(hashp, hcp->dpagep);
+ __ham_dirty_page(dbp, hcp->dpagep);
break;
case H_OFFPAGE:
/* Simple case, one key on page; move it to dup page. */
- dndx = 0;
memcpy(&ho,
P_ENTRY(hcp->pagep, H_DATAINDEX(hcp->bndx)), HOFFPAGE_SIZE);
+ UMRW(bo.unused1);
B_TSET(bo.type, ho.type, 0);
+ UMRW(bo.unused2);
bo.pgno = ho.pgno;
bo.tlen = ho.tlen;
dbt.size = BOVERFLOW_SIZE;
dbt.data = &bo;
- ret = __db_pitem(hashp->dbp, hcp->dpagep,
+ ret = __db_pitem(dbc, hcp->dpagep,
(u_int32_t)dndx, dbt.size, &dbt, NULL);
if (ret == 0)
- __ham_dirty_page(hashp, hcp->dpagep);
+ __ham_dirty_page(dbp, hcp->dpagep);
break;
case H_DUPLICATE:
p = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
pend = p +
- LEN_HDATA(hcp->pagep, hashp->hdr->pagesize, hcp->bndx);
+ LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx);
- for (dndx = 0; p < pend; dndx++) {
+ /*
+ * We need to maintain the duplicate cursor position.
+ * Keep track of where we are in the duplicate set via
+ * the offset, and when it matches the one in the cursor,
+ * set the off-page duplicate cursor index to the current
+ * index.
+ */
+ for (off = 0, i = 0; p < pend; i++) {
+ if (off == hcp->dup_off)
+ dndx = i;
memcpy(&len, p, sizeof(db_indx_t));
dbt.size = len;
p += sizeof(db_indx_t);
dbt.data = p;
p += len + sizeof(db_indx_t);
- ret = __db_dput(hashp->dbp, &dbt,
- &hcp->dpagep, &dndx, __ham_overflow_page);
+ off += len + 2 * sizeof(db_indx_t);
+ ret = __db_dput(dbc, &dbt,
+ &hcp->dpagep, &i, __ham_overflow_page);
if (ret != 0)
break;
}
break;
default:
- ret = __db_pgfmt(hashp->dbp, (u_long)hcp->pgno);
+ ret = __db_pgfmt(dbp, (u_long)hcp->pgno);
+ break;
}
if (ret == 0) {
/*
* Now attach this to the source page in place of
* the old duplicate item.
*/
- __ham_move_offpage(hashp, hcp->pagep,
+ __ham_move_offpage(dbc, hcp->pagep,
(u_int32_t)H_DATAINDEX(hcp->bndx), hcp->dpgno);
/* Can probably just do a "put" here. */
- ret = __ham_dirty_page(hashp, hcp->pagep);
+ ret = __ham_dirty_page(dbp, hcp->pagep);
+ hcp->dndx = dndx;
} else {
- (void)__ham_del_page(hashp->dbp, hcp->dpagep);
+ (void)__ham_del_page(dbc, hcp->dpagep);
hcp->dpagep = NULL;
}
return (ret);
@@ -354,11 +410,12 @@ __ham_make_dup(notdup, duplicate, bufp, sizep)
}
static int
-__ham_check_move(hashp, hcp, add_len)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_check_move(dbc, add_len)
+ DBC *dbc;
int32_t add_len;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DBT k, d;
DB_LSN new_lsn;
PAGE *next_pagep;
@@ -367,6 +424,8 @@ __ham_check_move(hashp, hcp, add_len)
u_int8_t *hk;
int ret;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
/*
* Check if we can do whatever we need to on this page. If not,
* then we'll have to move the current element to a new page.
@@ -381,7 +440,7 @@ __ham_check_move(hashp, hcp, add_len)
return (0);
old_len =
- LEN_HITEM(hcp->pagep, hashp->hdr->pagesize, H_DATAINDEX(hcp->bndx));
+ LEN_HITEM(hcp->pagep, hcp->hdr->pagesize, H_DATAINDEX(hcp->bndx));
new_datalen = old_len - HKEYDATA_SIZE(0) + add_len;
/*
@@ -392,11 +451,11 @@ __ham_check_move(hashp, hcp, add_len)
* threshold, but the new data won't fit on the page.
* If neither of these is true, then we can return.
*/
- if (ISBIG(hashp, new_datalen) && (old_len > HOFFDUP_SIZE ||
+ if (ISBIG(hcp, new_datalen) && (old_len > HOFFDUP_SIZE ||
HOFFDUP_SIZE - old_len <= P_FREESPACE(hcp->pagep)))
return (0);
- if (!ISBIG(hashp, new_datalen) &&
+ if (!ISBIG(hcp, new_datalen) &&
add_len <= (int32_t)P_FREESPACE(hcp->pagep))
return (0);
@@ -405,18 +464,18 @@ __ham_check_move(hashp, hcp, add_len)
* Check if there are more pages in the chain.
*/
- new_datalen = ISBIG(hashp, new_datalen) ?
+ new_datalen = ISBIG(hcp, new_datalen) ?
HOFFDUP_SIZE : HKEYDATA_SIZE(new_datalen);
next_pagep = NULL;
for (next_pgno = NEXT_PGNO(hcp->pagep); next_pgno != PGNO_INVALID;
next_pgno = NEXT_PGNO(next_pagep)) {
if (next_pagep != NULL &&
- (ret = __ham_put_page(hashp->dbp, next_pagep, 0)) != 0)
+ (ret = __ham_put_page(dbp, next_pagep, 0)) != 0)
return (ret);
if ((ret =
- __ham_get_page(hashp->dbp, next_pgno, &next_pagep)) != 0)
+ __ham_get_page(dbp, next_pgno, &next_pagep)) != 0)
return (ret);
if (P_FREESPACE(next_pagep) >= new_datalen)
@@ -424,17 +483,17 @@ __ham_check_move(hashp, hcp, add_len)
}
/* No more pages, add one. */
- if (next_pagep == NULL &&
- (ret = __ham_add_ovflpage(hashp, hcp->pagep, 0, &next_pagep)) != 0)
+ if (next_pagep == NULL && (ret = __ham_add_ovflpage(dbc,
+ hcp->pagep, 0, &next_pagep)) != 0)
return (ret);
/* Add new page at the end of the chain. */
- if (P_FREESPACE(next_pagep) < new_datalen &&
- (ret = __ham_add_ovflpage(hashp, next_pagep, 1, &next_pagep)) != 0)
+ if (P_FREESPACE(next_pagep) < new_datalen && (ret =
+ __ham_add_ovflpage(dbc, next_pagep, 1, &next_pagep)) != 0)
return (ret);
/* Copy the item to the new page. */
- if (DB_LOGGING(hashp->dbp)) {
+ if (DB_LOGGING(hcp->dbc)) {
rectype = PUTPAIR;
k.flags = 0;
d.flags = 0;
@@ -447,7 +506,7 @@ __ham_check_move(hashp, hcp, add_len)
k.data =
HKEYDATA_DATA(H_PAIRKEY(hcp->pagep, hcp->bndx));
k.size = LEN_HKEY(hcp->pagep,
- hashp->hdr->pagesize, hcp->bndx);
+ hcp->hdr->pagesize, hcp->bndx);
}
if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
@@ -458,13 +517,13 @@ __ham_check_move(hashp, hcp, add_len)
d.data =
HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx));
d.size = LEN_HDATA(hcp->pagep,
- hashp->hdr->pagesize, hcp->bndx);
+ hcp->hdr->pagesize, hcp->bndx);
}
- if ((ret = __ham_insdel_log(hashp->dbp->dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, rectype,
- hashp->dbp->log_fileid, PGNO(next_pagep),
+ if ((ret = __ham_insdel_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, rectype,
+ dbp->log_fileid, PGNO(next_pagep),
(u_int32_t)H_NUMPAIRS(next_pagep), &LSN(next_pagep),
&k, &d)) != 0)
return (ret);
@@ -473,13 +532,15 @@ __ham_check_move(hashp, hcp, add_len)
LSN(next_pagep) = new_lsn; /* Structure assignment. */
}
- __ham_copy_item(hashp, hcp->pagep, H_KEYINDEX(hcp->bndx), next_pagep);
- __ham_copy_item(hashp, hcp->pagep, H_DATAINDEX(hcp->bndx), next_pagep);
+ __ham_copy_item(dbp->pgsize,
+ hcp->pagep, H_KEYINDEX(hcp->bndx), next_pagep);
+ __ham_copy_item(dbp->pgsize,
+ hcp->pagep, H_DATAINDEX(hcp->bndx), next_pagep);
/* Now delete the pair from the current page. */
- ret = __ham_del_pair(hashp, hcp, 0);
+ ret = __ham_del_pair(dbc, 0);
- (void)__ham_put_page(hashp->dbp, hcp->pagep, 1);
+ (void)__ham_put_page(dbp, hcp->pagep, 1);
hcp->pagep = next_pagep;
hcp->pgno = PGNO(hcp->pagep);
hcp->bndx = H_NUMPAIRS(hcp->pagep) - 1;
@@ -488,19 +549,25 @@ __ham_check_move(hashp, hcp, add_len)
}
/*
- * Replace an onpage set of duplicates with the OFFDUP structure that
- * references the duplicate page.
- * XXX This is really just a special case of __onpage_replace; we should
+ * __ham_move_offpage --
+ * Replace an onpage set of duplicates with the OFFDUP structure
+ * that references the duplicate page.
+ *
+ * XXX
+ * This is really just a special case of __onpage_replace; we should
* probably combine them.
- * PUBLIC: void __ham_move_offpage __P((HTAB *, PAGE *, u_int32_t, db_pgno_t));
+ *
+ * PUBLIC: void __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t));
*/
void
-__ham_move_offpage(hashp, pagep, ndx, pgno)
- HTAB *hashp;
+__ham_move_offpage(dbc, pagep, ndx, pgno)
+ DBC *dbc;
PAGE *pagep;
u_int32_t ndx;
db_pgno_t pgno;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DBT new_dbt;
DBT old_dbt;
HOFFDUP od;
@@ -508,22 +575,27 @@ __ham_move_offpage(hashp, pagep, ndx, pgno)
int32_t shrink;
u_int8_t *src;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
od.type = H_OFFDUP;
+ UMRW(od.unused[0]);
+ UMRW(od.unused[1]);
+ UMRW(od.unused[2]);
od.pgno = pgno;
- if (DB_LOGGING(hashp->dbp)) {
+ if (DB_LOGGING(dbc)) {
new_dbt.data = &od;
new_dbt.size = HOFFDUP_SIZE;
old_dbt.data = P_ENTRY(pagep, ndx);
- old_dbt.size = LEN_HITEM(pagep, hashp->hdr->pagesize, ndx);
- (void)__ham_replace_log(hashp->dbp->dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &LSN(pagep), 0,
- hashp->dbp->log_fileid, PGNO(pagep), (u_int32_t)ndx,
- &LSN(pagep), -1, &old_dbt, &new_dbt, 0);
+ old_dbt.size = LEN_HITEM(pagep, hcp->hdr->pagesize, ndx);
+ (void)__ham_replace_log(dbp->dbenv->lg_info,
+ dbc->txn, &LSN(pagep), 0, dbp->log_fileid,
+ PGNO(pagep), (u_int32_t)ndx, &LSN(pagep), -1,
+ &old_dbt, &new_dbt, 0);
}
shrink =
- LEN_HITEM(pagep, hashp->hdr->pagesize, ndx) - HOFFDUP_SIZE;
+ LEN_HITEM(pagep, hcp->hdr->pagesize, ndx) - HOFFDUP_SIZE;
if (shrink != 0) {
/* Copy data. */
@@ -539,3 +611,46 @@ __ham_move_offpage(hashp, pagep, ndx, pgno)
/* Now copy the offdup entry onto the page. */
memcpy(P_ENTRY(pagep, ndx), &od, HOFFDUP_SIZE);
}
+
+/*
+ * __ham_dsearch:
+ * Locate a particular duplicate in a duplicate set.
+ *
+ * PUBLIC: void __ham_dsearch __P((DBC *, DBT *, u_int32_t *, int *));
+ */
+void
+__ham_dsearch(dbc, dbt, offp, cmpp)
+ DBC *dbc;
+ DBT *dbt;
+ u_int32_t *offp;
+ int *cmpp;
+{
+ DB *dbp;
+ HASH_CURSOR *hcp;
+ DBT cur;
+ db_indx_t i, len;
+ int (*func) __P((const DBT *, const DBT *));
+ u_int8_t *data;
+
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+ if (dbp->dup_compare == NULL)
+ func = __bam_defcmp;
+ else
+ func = dbp->dup_compare;
+
+ i = F_ISSET(dbc, DBC_CONTINUE) ? hcp->dup_off: 0;
+ data = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)) + i;
+ while (i < LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx)) {
+ memcpy(&len, data, sizeof(db_indx_t));
+ data += sizeof(db_indx_t);
+ cur.data = data;
+ cur.size = (u_int32_t)len;
+ *cmpp = func(dbt, &cur);
+ if (*cmpp == 0 || (*cmpp < 0 && dbp->dup_compare != NULL))
+ break;
+ i += len + 2 * sizeof(db_indx_t);
+ data += len + sizeof(db_indx_t);
+ }
+ *offp = i;
+}
diff --git a/db2/hash/hash_page.c b/db2/hash/hash_page.c
index 5b3463947b..3419c1215c 100644
--- a/db2/hash/hash_page.c
+++ b/db2/hash/hash_page.c
@@ -47,7 +47,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)hash_page.c 10.40 (Sleepycat) 6/2/98";
+static const char sccsid[] = "@(#)hash_page.c 10.55 (Sleepycat) 1/3/99";
#endif /* not lint */
/*
@@ -77,107 +77,118 @@ static const char sccsid[] = "@(#)hash_page.c 10.40 (Sleepycat) 6/2/98";
#include "db_page.h"
#include "hash.h"
-static int __ham_lock_bucket __P((DB *, HASH_CURSOR *, db_lockmode_t));
+static int __ham_lock_bucket __P((DBC *, db_lockmode_t));
#ifdef DEBUG_SLOW
-static void __account_page(HTAB *, db_pgno_t, int);
+static void __account_page(DB *, db_pgno_t, int);
#endif
/*
- * PUBLIC: int __ham_item __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
+ * PUBLIC: int __ham_item __P((DBC *, db_lockmode_t));
*/
int
-__ham_item(hashp, cursorp, mode)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_item(dbc, mode)
+ DBC *dbc;
db_lockmode_t mode;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
db_pgno_t next_pgno;
int ret;
- if (F_ISSET(cursorp, H_DELETED))
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+
+ if (F_ISSET(hcp, H_DELETED))
return (EINVAL);
- F_CLR(cursorp, H_OK | H_NOMORE);
+ F_CLR(hcp, H_OK | H_NOMORE);
/* Check if we need to get a page for this cursor. */
- if ((ret = __ham_get_cpage(hashp, cursorp, mode)) != 0)
+ if ((ret = __ham_get_cpage(dbc, mode)) != 0)
return (ret);
/* Check if we are looking for space in which to insert an item. */
- if (cursorp->seek_size && cursorp->seek_found_page == PGNO_INVALID
- && cursorp->seek_size < P_FREESPACE(cursorp->pagep))
- cursorp->seek_found_page = cursorp->pgno;
+ if (hcp->seek_size && hcp->seek_found_page == PGNO_INVALID
+ && hcp->seek_size < P_FREESPACE(hcp->pagep))
+ hcp->seek_found_page = hcp->pgno;
/* Check if we need to go on to the next page. */
- if (F_ISSET(cursorp, H_ISDUP) && cursorp->dpgno == PGNO_INVALID)
+ if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno == PGNO_INVALID)
/*
* ISDUP is set, and offset is at the beginning of the datum.
* We need to grab the length of the datum, then set the datum
* pointer to be the beginning of the datum.
*/
- memcpy(&cursorp->dup_len,
- HKEYDATA_DATA(H_PAIRDATA(cursorp->pagep, cursorp->bndx)) +
- cursorp->dup_off, sizeof(db_indx_t));
- else if (F_ISSET(cursorp, H_ISDUP)) {
+ memcpy(&hcp->dup_len,
+ HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)) +
+ hcp->dup_off, sizeof(db_indx_t));
+ else if (F_ISSET(hcp, H_ISDUP)) {
/* Make sure we're not about to run off the page. */
- if (cursorp->dpagep == NULL && (ret = __ham_get_page(hashp->dbp,
- cursorp->dpgno, &cursorp->dpagep)) != 0)
+ if (hcp->dpagep == NULL && (ret = __ham_get_page(dbp,
+ hcp->dpgno, &hcp->dpagep)) != 0)
return (ret);
- if (cursorp->dndx >= NUM_ENT(cursorp->dpagep)) {
- if (NEXT_PGNO(cursorp->dpagep) == PGNO_INVALID) {
- if ((ret = __ham_put_page(hashp->dbp,
- cursorp->dpagep, 0)) != 0)
+ if (hcp->dndx >= NUM_ENT(hcp->dpagep)) {
+ if (NEXT_PGNO(hcp->dpagep) == PGNO_INVALID) {
+ if (F_ISSET(hcp, H_DUPONLY)) {
+ F_CLR(hcp, H_OK);
+ F_SET(hcp, H_NOMORE);
+ return (0);
+ }
+ if ((ret = __ham_put_page(dbp,
+ hcp->dpagep, 0)) != 0)
return (ret);
- F_CLR(cursorp, H_ISDUP);
- cursorp->dpagep = NULL;
- cursorp->dpgno = PGNO_INVALID;
- cursorp->dndx = NDX_INVALID;
- cursorp->bndx++;
- } else if ((ret = __ham_next_cpage(hashp, cursorp,
- NEXT_PGNO(cursorp->dpagep), 0, H_ISDUP)) != 0)
+ F_CLR(hcp, H_ISDUP);
+ hcp->dpagep = NULL;
+ hcp->dpgno = PGNO_INVALID;
+ hcp->dndx = NDX_INVALID;
+ hcp->bndx++;
+ } else if ((ret = __ham_next_cpage(dbc,
+ NEXT_PGNO(hcp->dpagep), 0, H_ISDUP)) != 0)
return (ret);
}
}
- if (cursorp->bndx >= (db_indx_t)H_NUMPAIRS(cursorp->pagep)) {
+ if (hcp->bndx >= (db_indx_t)H_NUMPAIRS(hcp->pagep)) {
/* Fetch next page. */
- if (NEXT_PGNO(cursorp->pagep) == PGNO_INVALID) {
- F_SET(cursorp, H_NOMORE);
- if (cursorp->dpagep != NULL &&
- (ret = __ham_put_page(hashp->dbp,
- cursorp->dpagep, 0)) != 0)
+ if (NEXT_PGNO(hcp->pagep) == PGNO_INVALID) {
+ F_SET(hcp, H_NOMORE);
+ if (hcp->dpagep != NULL &&
+ (ret = __ham_put_page(dbp, hcp->dpagep, 0)) != 0)
return (ret);
- cursorp->dpgno = PGNO_INVALID;
+ hcp->dpgno = PGNO_INVALID;
return (DB_NOTFOUND);
}
- next_pgno = NEXT_PGNO(cursorp->pagep);
- cursorp->bndx = 0;
- if ((ret = __ham_next_cpage(hashp,
- cursorp, next_pgno, 0, 0)) != 0)
+ next_pgno = NEXT_PGNO(hcp->pagep);
+ hcp->bndx = 0;
+ if ((ret = __ham_next_cpage(dbc, next_pgno, 0, 0)) != 0)
return (ret);
}
- F_SET(cursorp, H_OK);
+ F_SET(hcp, H_OK);
return (0);
}
/*
- * PUBLIC: int __ham_item_reset __P((HTAB *, HASH_CURSOR *));
+ * PUBLIC: int __ham_item_reset __P((DBC *));
*/
int
-__ham_item_reset(hashp, cursorp)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_item_reset(dbc)
+ DBC *dbc;
{
+ HASH_CURSOR *hcp;
+ DB *dbp;
int ret;
- if (cursorp->pagep)
- ret = __ham_put_page(hashp->dbp, cursorp->pagep, 0);
- else
- ret = 0;
-
- __ham_item_init(cursorp);
+ ret = 0;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+ if (hcp->pagep != NULL)
+ ret = __ham_put_page(dbp, hcp->pagep, 0);
+ if (ret == 0 && hcp->dpagep != NULL)
+ ret = __ham_put_page(dbp, hcp->dpagep, 0);
+
+ __ham_item_init(hcp);
return (ret);
}
@@ -185,57 +196,67 @@ __ham_item_reset(hashp, cursorp)
* PUBLIC: void __ham_item_init __P((HASH_CURSOR *));
*/
void
-__ham_item_init(cursorp)
- HASH_CURSOR *cursorp;
+__ham_item_init(hcp)
+ HASH_CURSOR *hcp;
{
- cursorp->pagep = NULL;
- cursorp->bucket = BUCKET_INVALID;
- cursorp->lock = 0;
- cursorp->bndx = NDX_INVALID;
- cursorp->pgno = PGNO_INVALID;
- cursorp->dpgno = PGNO_INVALID;
- cursorp->dndx = NDX_INVALID;
- cursorp->dpagep = NULL;
- cursorp->flags = 0;
- cursorp->seek_size = 0;
- cursorp->seek_found_page = PGNO_INVALID;
+ /*
+ * If this cursor still holds any locks, we must
+ * release them if we are not running with transactions.
+ */
+ if (hcp->lock && hcp->dbc->txn == NULL)
+ (void)lock_put(hcp->dbc->dbp->dbenv->lk_info, hcp->lock);
+
+ /*
+ * The following fields must *not* be initialized here
+ * because they may have meaning across inits.
+ * hlock, hdr, split_buf, stats
+ */
+ hcp->bucket = BUCKET_INVALID;
+ hcp->lbucket = BUCKET_INVALID;
+ hcp->lock = 0;
+ hcp->pagep = NULL;
+ hcp->pgno = PGNO_INVALID;
+ hcp->bndx = NDX_INVALID;
+ hcp->dpagep = NULL;
+ hcp->dpgno = PGNO_INVALID;
+ hcp->dndx = NDX_INVALID;
+ hcp->dup_off = 0;
+ hcp->dup_len = 0;
+ hcp->dup_tlen = 0;
+ hcp->seek_size = 0;
+ hcp->seek_found_page = PGNO_INVALID;
+ hcp->flags = 0;
}
/*
- * PUBLIC: int __ham_item_done __P((HTAB *, HASH_CURSOR *, int));
+ * PUBLIC: int __ham_item_done __P((DBC *, int));
*/
int
-__ham_item_done(hashp, cursorp, dirty)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_item_done(dbc, dirty)
+ DBC *dbc;
int dirty;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
int ret, t_ret;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
t_ret = ret = 0;
- if (cursorp->pagep)
- ret = __ham_put_page(hashp->dbp, cursorp->pagep,
- dirty && cursorp->dpagep == NULL);
- cursorp->pagep = NULL;
+ if (hcp->pagep)
+ ret = __ham_put_page(dbp, hcp->pagep,
+ dirty && hcp->dpagep == NULL);
+ hcp->pagep = NULL;
- if (cursorp->dpagep)
- t_ret = __ham_put_page(hashp->dbp, cursorp->dpagep, dirty);
- cursorp->dpagep = NULL;
+ if (hcp->dpagep)
+ t_ret = __ham_put_page(dbp, hcp->dpagep, dirty);
+ hcp->dpagep = NULL;
if (ret == 0 && t_ret != 0)
ret = t_ret;
/*
- * If we are running with transactions, then we must
- * not relinquish locks explicitly.
- */
- if (cursorp->lock && hashp->dbp->txn == NULL)
- t_ret = lock_put(hashp->dbp->dbenv->lk_info, cursorp->lock);
- cursorp->lock = 0;
-
-
- /*
* We don't throw out the page number since we might want to
* continue getting on this page.
*/
@@ -245,40 +266,42 @@ __ham_item_done(hashp, cursorp, dirty)
/*
* Returns the last item in a bucket.
*
- * PUBLIC: int __ham_item_last __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
+ * PUBLIC: int __ham_item_last __P((DBC *, db_lockmode_t));
*/
int
-__ham_item_last(hashp, cursorp, mode)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_item_last(dbc, mode)
+ DBC *dbc;
db_lockmode_t mode;
{
+ HASH_CURSOR *hcp;
int ret;
- if ((ret = __ham_item_reset(hashp, cursorp)) != 0)
+ hcp = (HASH_CURSOR *)dbc->internal;
+ if ((ret = __ham_item_reset(dbc)) != 0)
return (ret);
- cursorp->bucket = hashp->hdr->max_bucket;
- F_SET(cursorp, H_OK);
- return (__ham_item_prev(hashp, cursorp, mode));
+ hcp->bucket = hcp->hdr->max_bucket;
+ F_SET(hcp, H_OK);
+ return (__ham_item_prev(dbc, mode));
}
/*
- * PUBLIC: int __ham_item_first __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
+ * PUBLIC: int __ham_item_first __P((DBC *, db_lockmode_t));
*/
int
-__ham_item_first(hashp, cursorp, mode)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_item_first(dbc, mode)
+ DBC *dbc;
db_lockmode_t mode;
{
+ HASH_CURSOR *hcp;
int ret;
- if ((ret = __ham_item_reset(hashp, cursorp)) != 0)
+ hcp = (HASH_CURSOR *)dbc->internal;
+ if ((ret = __ham_item_reset(dbc)) != 0)
return (ret);
- F_SET(cursorp, H_OK);
- cursorp->bucket = 0;
- return (__ham_item_next(hashp, cursorp, mode));
+ F_SET(hcp, H_OK);
+ hcp->bucket = 0;
+ return (__ham_item_next(dbc, mode));
}
/*
@@ -287,17 +310,20 @@ __ham_item_first(hashp, cursorp, mode)
* bigkeys, just returns the page number and index of the bigkey
* pointer pair.
*
- * PUBLIC: int __ham_item_prev __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
+ * PUBLIC: int __ham_item_prev __P((DBC *, db_lockmode_t));
*/
int
-__ham_item_prev(hashp, cursorp, mode)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_item_prev(dbc, mode)
+ DBC *dbc;
db_lockmode_t mode;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
db_pgno_t next_pgno;
int ret;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
/*
* There are N cases for backing up in a hash file.
* Case 1: In the middle of a page, no duplicates, just dec the index.
@@ -307,52 +333,56 @@ __ham_item_prev(hashp, cursorp, mode)
* Case 4: At the beginning of a page; go to previous page.
* Case 5: At the beginning of a bucket; go to prev bucket.
*/
- F_CLR(cursorp, H_OK | H_NOMORE | H_DELETED);
+ F_CLR(hcp, H_OK | H_NOMORE | H_DELETED);
/*
* First handle the duplicates. Either you'll get the key here
* or you'll exit the duplicate set and drop into the code below
* to handle backing up through keys.
*/
- if (F_ISSET(cursorp, H_ISDUP)) {
- if (cursorp->dpgno == PGNO_INVALID) {
+ if (F_ISSET(hcp, H_ISDUP)) {
+ if (hcp->dpgno == PGNO_INVALID) {
/* Duplicates are on-page. */
- if (cursorp->dup_off != 0) {
- if ((ret = __ham_get_cpage(hashp,
- cursorp, mode)) != 0)
+ if (hcp->dup_off != 0) {
+ if ((ret = __ham_get_cpage(dbc, mode)) != 0)
return (ret);
else {
HASH_CURSOR *h;
- h = cursorp;
+ h = hcp;
memcpy(&h->dup_len, HKEYDATA_DATA(
H_PAIRDATA(h->pagep, h->bndx))
+ h->dup_off - sizeof(db_indx_t),
sizeof(db_indx_t));
- cursorp->dup_off -=
- DUP_SIZE(cursorp->dup_len);
- cursorp->dndx--;
- return (__ham_item(hashp,
- cursorp, mode));
+ hcp->dup_off -=
+ DUP_SIZE(hcp->dup_len);
+ hcp->dndx--;
+ return (__ham_item(dbc, mode));
}
}
- } else if (cursorp->dndx > 0) { /* Duplicates are off-page. */
- cursorp->dndx--;
- return (__ham_item(hashp, cursorp, mode));
- } else if ((ret = __ham_get_cpage(hashp, cursorp, mode)) != 0)
+ } else if (hcp->dndx > 0) { /* Duplicates are off-page. */
+ hcp->dndx--;
+ return (__ham_item(dbc, mode));
+ } else if ((ret = __ham_get_cpage(dbc, mode)) != 0)
return (ret);
- else if (PREV_PGNO(cursorp->dpagep) == PGNO_INVALID) {
- F_CLR(cursorp, H_ISDUP); /* End of dups */
- cursorp->dpgno = PGNO_INVALID;
- if (cursorp->dpagep != NULL)
- (void)__ham_put_page(hashp->dbp,
- cursorp->dpagep, 0);
- cursorp->dpagep = NULL;
- } else if ((ret = __ham_next_cpage(hashp, cursorp,
- PREV_PGNO(cursorp->dpagep), 0, H_ISDUP)) != 0)
+ else if (PREV_PGNO(hcp->dpagep) == PGNO_INVALID) {
+ if (F_ISSET(hcp, H_DUPONLY)) {
+ F_CLR(hcp, H_OK);
+ F_SET(hcp, H_NOMORE);
+ return (0);
+ } else {
+ F_CLR(hcp, H_ISDUP); /* End of dups */
+ hcp->dpgno = PGNO_INVALID;
+ if (hcp->dpagep != NULL)
+ (void)__ham_put_page(dbp,
+ hcp->dpagep, 0);
+ hcp->dpagep = NULL;
+ }
+ } else if ((ret = __ham_next_cpage(dbc,
+ PREV_PGNO(hcp->dpagep), 0, H_ISDUP)) != 0)
return (ret);
else {
- cursorp->dndx = NUM_ENT(cursorp->pagep) - 1;
- return (__ham_item(hashp, cursorp, mode));
+ hcp->dndx = NUM_ENT(hcp->pagep) - 1;
+ return (__ham_item(dbc, mode));
}
}
@@ -362,95 +392,123 @@ __ham_item_prev(hashp, cursorp, mode)
* midpage, beginning of page, beginning of bucket.
*/
- if (cursorp->bndx == 0) { /* Beginning of page. */
- if ((ret = __ham_get_cpage(hashp, cursorp, mode)) != 0)
+ if (F_ISSET(hcp, H_DUPONLY)) {
+ F_CLR(hcp, H_OK);
+ F_SET(hcp, H_NOMORE);
+ return (0);
+ }
+
+ if (hcp->bndx == 0) { /* Beginning of page. */
+ if ((ret = __ham_get_cpage(dbc, mode)) != 0)
return (ret);
- cursorp->pgno = PREV_PGNO(cursorp->pagep);
- if (cursorp->pgno == PGNO_INVALID) {
+ hcp->pgno = PREV_PGNO(hcp->pagep);
+ if (hcp->pgno == PGNO_INVALID) {
/* Beginning of bucket. */
- F_SET(cursorp, H_NOMORE);
+ F_SET(hcp, H_NOMORE);
return (DB_NOTFOUND);
- } else if ((ret = __ham_next_cpage(hashp,
- cursorp, cursorp->pgno, 0, 0)) != 0)
+ } else if ((ret =
+ __ham_next_cpage(dbc, hcp->pgno, 0, 0)) != 0)
return (ret);
else
- cursorp->bndx = H_NUMPAIRS(cursorp->pagep);
+ hcp->bndx = H_NUMPAIRS(hcp->pagep);
}
/*
* Either we've got the cursor set up to be decremented, or we
* have to find the end of a bucket.
*/
- if (cursorp->bndx == NDX_INVALID) {
- if (cursorp->pagep == NULL)
- next_pgno = BUCKET_TO_PAGE(hashp, cursorp->bucket);
+ if (hcp->bndx == NDX_INVALID) {
+ if (hcp->pagep == NULL)
+ next_pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
else
goto got_page;
do {
- if ((ret = __ham_next_cpage(hashp,
- cursorp, next_pgno, 0, 0)) != 0)
+ if ((ret = __ham_next_cpage(dbc, next_pgno, 0, 0)) != 0)
return (ret);
-got_page: next_pgno = NEXT_PGNO(cursorp->pagep);
- cursorp->bndx = H_NUMPAIRS(cursorp->pagep);
+got_page: next_pgno = NEXT_PGNO(hcp->pagep);
+ hcp->bndx = H_NUMPAIRS(hcp->pagep);
} while (next_pgno != PGNO_INVALID);
- if (cursorp->bndx == 0) {
+ if (hcp->bndx == 0) {
/* Bucket was empty. */
- F_SET(cursorp, H_NOMORE);
+ F_SET(hcp, H_NOMORE);
return (DB_NOTFOUND);
}
}
- cursorp->bndx--;
+ hcp->bndx--;
- return (__ham_item(hashp, cursorp, mode));
+ return (__ham_item(dbc, mode));
}
/*
* Sets the cursor to the next key/data pair on a page.
*
- * PUBLIC: int __ham_item_next __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
+ * PUBLIC: int __ham_item_next __P((DBC *, db_lockmode_t));
*/
int
-__ham_item_next(hashp, cursorp, mode)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_item_next(dbc, mode)
+ DBC *dbc;
db_lockmode_t mode;
{
+ HASH_CURSOR *hcp;
+
+ hcp = (HASH_CURSOR *)dbc->internal;
/*
* Deleted on-page duplicates are a weird case. If we delete the last
* one, then our cursor is at the very end of a duplicate set and
* we actually need to go on to the next key.
*/
- if (F_ISSET(cursorp, H_DELETED)) {
- if (cursorp->bndx != NDX_INVALID &&
- F_ISSET(cursorp, H_ISDUP) &&
- cursorp->dpgno == PGNO_INVALID &&
- cursorp->dup_tlen == cursorp->dup_off) {
- F_CLR(cursorp, H_ISDUP);
- cursorp->dpgno = PGNO_INVALID;
- cursorp->bndx++;
+ if (F_ISSET(hcp, H_DELETED)) {
+ if (hcp->bndx != NDX_INVALID &&
+ F_ISSET(hcp, H_ISDUP) &&
+ hcp->dpgno == PGNO_INVALID &&
+ hcp->dup_tlen == hcp->dup_off) {
+ if (F_ISSET(hcp, H_DUPONLY)) {
+ F_CLR(hcp, H_OK);
+ F_SET(hcp, H_NOMORE);
+ return (0);
+ } else {
+ F_CLR(hcp, H_ISDUP);
+ hcp->dpgno = PGNO_INVALID;
+ hcp->bndx++;
+ }
+ } else if (!F_ISSET(hcp, H_ISDUP) &&
+ F_ISSET(hcp, H_DUPONLY)) {
+ F_CLR(hcp, H_OK);
+ F_SET(hcp, H_NOMORE);
+ return (0);
}
- F_CLR(cursorp, H_DELETED);
- } else if (cursorp->bndx == NDX_INVALID) {
- cursorp->bndx = 0;
- cursorp->dpgno = PGNO_INVALID;
- F_CLR(cursorp, H_ISDUP);
- } else if (F_ISSET(cursorp, H_ISDUP) && cursorp->dpgno != PGNO_INVALID)
- cursorp->dndx++;
- else if (F_ISSET(cursorp, H_ISDUP)) {
- cursorp->dndx++;
- cursorp->dup_off += DUP_SIZE(cursorp->dup_len);
- if (cursorp->dup_off >= cursorp->dup_tlen) {
- F_CLR(cursorp, H_ISDUP);
- cursorp->dpgno = PGNO_INVALID;
- cursorp->bndx++;
+ F_CLR(hcp, H_DELETED);
+ } else if (hcp->bndx == NDX_INVALID) {
+ hcp->bndx = 0;
+ hcp->dpgno = PGNO_INVALID;
+ F_CLR(hcp, H_ISDUP);
+ } else if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno != PGNO_INVALID)
+ hcp->dndx++;
+ else if (F_ISSET(hcp, H_ISDUP)) {
+ if (hcp->dup_off + DUP_SIZE(hcp->dup_len) >=
+ hcp->dup_tlen && F_ISSET(hcp, H_DUPONLY)) {
+ F_CLR(hcp, H_OK);
+ F_SET(hcp, H_NOMORE);
+ return (0);
+ }
+ hcp->dndx++;
+ hcp->dup_off += DUP_SIZE(hcp->dup_len);
+ if (hcp->dup_off >= hcp->dup_tlen) {
+ F_CLR(hcp, H_ISDUP);
+ hcp->dpgno = PGNO_INVALID;
+ hcp->bndx++;
}
+ } else if (F_ISSET(hcp, H_DUPONLY)) {
+ F_CLR(hcp, H_OK);
+ F_SET(hcp, H_NOMORE);
+ return (0);
} else
- cursorp->bndx++;
+ hcp->bndx++;
- return (__ham_item(hashp, cursorp, mode));
+ return (__ham_item(dbc, mode));
}
/*
@@ -537,18 +595,15 @@ __ham_reputpair(p, psize, ndx, key, data)
/*
- * PUBLIC: int __ham_del_pair __P((HTAB *, HASH_CURSOR *, int));
- *
- * XXX
- * TODO: if the item is an offdup, delete the other pages and then remove
- * the pair. If the offpage page is 0, then you can just remove the pair.
+ * PUBLIC: int __ham_del_pair __P((DBC *, int));
*/
int
-__ham_del_pair(hashp, cursorp, reclaim_page)
- HTAB *hashp;
- HASH_CURSOR *cursorp;
+__ham_del_pair(dbc, reclaim_page)
+ DBC *dbc;
int reclaim_page;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DBT data_dbt, key_dbt;
DB_ENV *dbenv;
DB_LSN new_lsn, *n_lsn, tmp_lsn;
@@ -557,13 +612,16 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
db_pgno_t chg_pgno, pgno;
int ret, tret;
- dbenv = hashp->dbp->dbenv;
- ndx = cursorp->bndx;
- if (cursorp->pagep == NULL && (ret =
- __ham_get_page(hashp->dbp, cursorp->pgno, &cursorp->pagep)) != 0)
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+
+ dbenv = dbp->dbenv;
+ ndx = hcp->bndx;
+ if (hcp->pagep == NULL &&
+ (ret = __ham_get_page(dbp, hcp->pgno, &hcp->pagep)) != 0)
return (ret);
- p = cursorp->pagep;
+ p = hcp->pagep;
/*
* We optimize for the normal case which is when neither the key nor
@@ -576,7 +634,7 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
if (HPAGE_PTYPE(H_PAIRKEY(p, ndx)) == H_OFFPAGE) {
memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(p, H_KEYINDEX(ndx))),
sizeof(db_pgno_t));
- ret = __db_doff(hashp->dbp, pgno, __ham_del_page);
+ ret = __db_doff(dbc, pgno, __ham_del_page);
}
if (ret == 0)
@@ -585,14 +643,14 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
memcpy(&pgno,
HOFFPAGE_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),
sizeof(db_pgno_t));
- ret = __db_doff(hashp->dbp, pgno, __ham_del_page);
+ ret = __db_doff(dbc, pgno, __ham_del_page);
break;
case H_OFFDUP:
memcpy(&pgno,
HOFFDUP_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),
sizeof(db_pgno_t));
- ret = __db_ddup(hashp->dbp, pgno, __ham_del_page);
- F_CLR(cursorp, H_ISDUP);
+ ret = __db_ddup(dbc, pgno, __ham_del_page);
+ F_CLR(hcp, H_ISDUP);
break;
case H_DUPLICATE:
/*
@@ -600,7 +658,7 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
* we had better clear the flag so that we update the
* cursor appropriately.
*/
- F_CLR(cursorp, H_ISDUP);
+ F_CLR(hcp, H_ISDUP);
break;
}
@@ -608,17 +666,17 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
return (ret);
/* Now log the delete off this page. */
- if (DB_LOGGING(hashp->dbp)) {
+ if (DB_LOGGING(dbc)) {
key_dbt.data = P_ENTRY(p, H_KEYINDEX(ndx));
key_dbt.size =
- LEN_HITEM(p, hashp->hdr->pagesize, H_KEYINDEX(ndx));
+ LEN_HITEM(p, hcp->hdr->pagesize, H_KEYINDEX(ndx));
data_dbt.data = P_ENTRY(p, H_DATAINDEX(ndx));
data_dbt.size =
- LEN_HITEM(p, hashp->hdr->pagesize, H_DATAINDEX(ndx));
+ LEN_HITEM(p, hcp->hdr->pagesize, H_DATAINDEX(ndx));
if ((ret = __ham_insdel_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, DELPAIR,
- hashp->dbp->log_fileid, PGNO(p), (u_int32_t)ndx,
+ dbc->txn, &new_lsn, 0, DELPAIR,
+ dbp->log_fileid, PGNO(p), (u_int32_t)ndx,
&LSN(p), &key_dbt, &data_dbt)) != 0)
return (ret);
@@ -626,15 +684,16 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
LSN(p) = new_lsn;
}
- __ham_dpair(hashp->dbp, p, ndx);
+ __ham_dpair(dbp, p, ndx);
/*
- * If we are locking, we will not maintain this.
- * XXXX perhaps we can retain incremental numbers and apply them
+ * If we are locking, we will not maintain this, because it is
+ * a hot spot.
+ * XXX perhaps we can retain incremental numbers and apply them
* later.
*/
- if (!F_ISSET(hashp->dbp, DB_AM_LOCKING))
- --hashp->hdr->nelem;
+ if (!F_ISSET(dbp, DB_AM_LOCKING))
+ --hcp->hdr->nelem;
/*
* If we need to reclaim the page, then check if the page is empty.
@@ -653,25 +712,25 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
* are more pages in the chain.
*/
if ((ret =
- __ham_get_page(hashp->dbp, NEXT_PGNO(p), &n_pagep)) != 0)
+ __ham_get_page(dbp, NEXT_PGNO(p), &n_pagep)) != 0)
return (ret);
if (NEXT_PGNO(n_pagep) != PGNO_INVALID) {
if ((ret =
- __ham_get_page(hashp->dbp, NEXT_PGNO(n_pagep),
+ __ham_get_page(dbp, NEXT_PGNO(n_pagep),
&nn_pagep)) != 0) {
- (void) __ham_put_page(hashp->dbp, n_pagep, 0);
+ (void) __ham_put_page(dbp, n_pagep, 0);
return (ret);
}
}
- if (DB_LOGGING(hashp->dbp)) {
+ if (DB_LOGGING(dbc)) {
key_dbt.data = n_pagep;
- key_dbt.size = hashp->hdr->pagesize;
+ key_dbt.size = hcp->hdr->pagesize;
if ((ret = __ham_copypage_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
- hashp->dbp->log_fileid, PGNO(p), &LSN(p),
- PGNO(n_pagep), &LSN(n_pagep), NEXT_PGNO(n_pagep),
+ dbc->txn, &new_lsn, 0, dbp->log_fileid, PGNO(p),
+ &LSN(p), PGNO(n_pagep), &LSN(n_pagep),
+ NEXT_PGNO(n_pagep),
NEXT_PGNO(n_pagep) == PGNO_INVALID ? NULL :
&LSN(nn_pagep), &key_dbt)) != 0)
return (ret);
@@ -684,12 +743,12 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
}
if (NEXT_PGNO(n_pagep) != PGNO_INVALID) {
PREV_PGNO(nn_pagep) = PGNO(p);
- (void)__ham_put_page(hashp->dbp, nn_pagep, 1);
+ (void)__ham_put_page(dbp, nn_pagep, 1);
}
tmp_pgno = PGNO(p);
tmp_lsn = LSN(p);
- memcpy(p, n_pagep, hashp->hdr->pagesize);
+ memcpy(p, n_pagep, hcp->hdr->pagesize);
PGNO(p) = tmp_pgno;
LSN(p) = tmp_lsn;
PREV_PGNO(p) = PGNO_INVALID;
@@ -697,25 +756,25 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
/*
* Cursor is advanced to the beginning of the next page.
*/
- cursorp->bndx = 0;
- cursorp->pgno = PGNO(p);
- F_SET(cursorp, H_DELETED);
+ hcp->bndx = 0;
+ hcp->pgno = PGNO(p);
+ F_SET(hcp, H_DELETED);
chg_pgno = PGNO(p);
- if ((ret = __ham_dirty_page(hashp, p)) != 0 ||
- (ret = __ham_del_page(hashp->dbp, n_pagep)) != 0)
+ if ((ret = __ham_dirty_page(dbp, p)) != 0 ||
+ (ret = __ham_del_page(dbc, n_pagep)) != 0)
return (ret);
} else if (reclaim_page &&
NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {
PAGE *n_pagep, *p_pagep;
if ((ret =
- __ham_get_page(hashp->dbp, PREV_PGNO(p), &p_pagep)) != 0)
+ __ham_get_page(dbp, PREV_PGNO(p), &p_pagep)) != 0)
return (ret);
if (NEXT_PGNO(p) != PGNO_INVALID) {
- if ((ret = __ham_get_page(hashp->dbp,
+ if ((ret = __ham_get_page(dbp,
NEXT_PGNO(p), &n_pagep)) != 0) {
- (void)__ham_put_page(hashp->dbp, p_pagep, 0);
+ (void)__ham_put_page(dbp, p_pagep, 0);
return (ret);
}
n_lsn = &LSN(n_pagep);
@@ -728,10 +787,10 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
if (n_pagep != NULL)
PREV_PGNO(n_pagep) = PGNO(p_pagep);
- if (DB_LOGGING(hashp->dbp)) {
+ if (DB_LOGGING(dbc)) {
if ((ret = __ham_newpage_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, DELOVFL,
- hashp->dbp->log_fileid, PREV_PGNO(p), &LSN(p_pagep),
+ dbc->txn, &new_lsn, 0, DELOVFL,
+ dbp->log_fileid, PREV_PGNO(p), &LSN(p_pagep),
PGNO(p), &LSN(p), NEXT_PGNO(p), n_lsn)) != 0)
return (ret);
@@ -741,21 +800,21 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
LSN(n_pagep) = new_lsn;
LSN(p) = new_lsn;
}
- cursorp->pgno = NEXT_PGNO(p);
- cursorp->bndx = 0;
+ hcp->pgno = NEXT_PGNO(p);
+ hcp->bndx = 0;
/*
* Since we are about to delete the cursor page and we have
* just moved the cursor, we need to make sure that the
* old page pointer isn't left hanging around in the cursor.
*/
- cursorp->pagep = NULL;
+ hcp->pagep = NULL;
chg_pgno = PGNO(p);
- ret = __ham_del_page(hashp->dbp, p);
- if ((tret = __ham_put_page(hashp->dbp, p_pagep, 1)) != 0 &&
+ ret = __ham_del_page(dbc, p);
+ if ((tret = __ham_put_page(dbp, p_pagep, 1)) != 0 &&
ret == 0)
ret = tret;
if (n_pagep != NULL &&
- (tret = __ham_put_page(hashp->dbp, n_pagep, 1)) != 0 &&
+ (tret = __ham_put_page(dbp, n_pagep, 1)) != 0 &&
ret == 0)
ret = tret;
if (ret != 0)
@@ -766,19 +825,19 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
* so that we update the cursor correctly on the next call
* to next.
*/
- F_SET(cursorp, H_DELETED);
- chg_pgno = cursorp->pgno;
- ret = __ham_dirty_page(hashp, p);
+ F_SET(hcp, H_DELETED);
+ chg_pgno = hcp->pgno;
+ ret = __ham_dirty_page(dbp, p);
}
- __ham_c_update(cursorp, chg_pgno, 0, 0, 0);
+ __ham_c_update(hcp, chg_pgno, 0, 0, 0);
/*
* Since we just deleted a pair from the master page, anything
- * in cursorp->dpgno should be cleared.
+ * in hcp->dpgno should be cleared.
*/
- cursorp->dpgno = PGNO_INVALID;
+ hcp->dpgno = PGNO_INVALID;
- F_CLR(cursorp, H_OK);
+ F_CLR(hcp, H_OK);
return (ret);
}
@@ -787,15 +846,16 @@ __ham_del_pair(hashp, cursorp, reclaim_page)
* Given the key data indicated by the cursor, replace part/all of it
* according to the fields in the dbt.
*
- * PUBLIC: int __ham_replpair __P((HTAB *, HASH_CURSOR *, DBT *, u_int32_t));
+ * PUBLIC: int __ham_replpair __P((DBC *, DBT *, u_int32_t));
*/
int
-__ham_replpair(hashp, hcp, dbt, make_dup)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_replpair(dbc, dbt, make_dup)
+ DBC *dbc;
DBT *dbt;
u_int32_t make_dup;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DBT old_dbt, tdata, tmp;
DB_LSN new_lsn;
int32_t change; /* XXX: Possible overflow. */
@@ -814,6 +874,8 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
* be the common case). We handle case 3 as a delete and
* add.
*/
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
/*
* We need to compute the number of bytes that we are adding or
@@ -833,7 +895,7 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
memcpy(&len, HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
else
len = LEN_HKEYDATA(hcp->pagep,
- hashp->dbp->pgsize, H_DATAINDEX(hcp->bndx));
+ dbp->pgsize, H_DATAINDEX(hcp->bndx));
if (dbt->doff + dbt->dlen > len)
change += dbt->doff + dbt->dlen - len;
@@ -854,41 +916,39 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
tmp.flags = 0;
F_SET(&tmp, DB_DBT_MALLOC | DB_DBT_INTERNAL);
if ((ret =
- __db_ret(hashp->dbp, hcp->pagep, H_KEYINDEX(hcp->bndx),
- &tmp, &hcp->big_key, &hcp->big_keylen)) != 0)
+ __db_ret(dbp, hcp->pagep, H_KEYINDEX(hcp->bndx),
+ &tmp, &dbc->rkey.data, &dbc->rkey.size)) != 0)
return (ret);
if (dbt->doff == 0 && dbt->dlen == len) {
- ret = __ham_del_pair(hashp, hcp, 0);
+ ret = __ham_del_pair(dbc, 0);
if (ret == 0)
- ret = __ham_add_el(hashp,
- hcp, &tmp, dbt, H_KEYDATA);
+ ret = __ham_add_el(dbc, &tmp, dbt, H_KEYDATA);
} else { /* Case B */
type = HPAGE_PTYPE(hk) != H_OFFPAGE ?
HPAGE_PTYPE(hk) : H_KEYDATA;
tdata.flags = 0;
F_SET(&tdata, DB_DBT_MALLOC | DB_DBT_INTERNAL);
- if ((ret = __db_ret(hashp->dbp, hcp->pagep,
- H_DATAINDEX(hcp->bndx), &tdata, &hcp->big_data,
- &hcp->big_datalen)) != 0)
+ if ((ret = __db_ret(dbp, hcp->pagep,
+ H_DATAINDEX(hcp->bndx), &tdata, &dbc->rdata.data,
+ &dbc->rdata.size)) != 0)
goto err;
/* Now we can delete the item. */
- if ((ret = __ham_del_pair(hashp, hcp, 0)) != 0) {
- __db_free(tdata.data);
+ if ((ret = __ham_del_pair(dbc, 0)) != 0) {
+ __os_free(tdata.data, tdata.size);
goto err;
}
/* Now shift old data around to make room for new. */
if (change > 0) {
- tdata.data = (void *)__db_realloc(tdata.data,
- tdata.size + change);
+ if ((ret = __os_realloc(&tdata.data,
+ tdata.size + change)) != 0)
+ return (ret);
memset((u_int8_t *)tdata.data + tdata.size,
0, change);
}
- if (tdata.data == NULL)
- return (ENOMEM);
end = (u_int8_t *)tdata.data + tdata.size;
src = (u_int8_t *)tdata.data + dbt->doff + dbt->dlen;
@@ -902,10 +962,10 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
tdata.size += change;
/* Now add the pair. */
- ret = __ham_add_el(hashp, hcp, &tmp, &tdata, type);
- __db_free(tdata.data);
+ ret = __ham_add_el(dbc, &tmp, &tdata, type);
+ __os_free(tdata.data, tdata.size);
}
-err: __db_free(tmp.data);
+err: __os_free(tmp.data, tmp.size);
return (ret);
}
@@ -921,12 +981,11 @@ err: __db_free(tmp.data);
* all the parameters here. Then log the call before moving
* anything around.
*/
- if (DB_LOGGING(hashp->dbp)) {
+ if (DB_LOGGING(dbc)) {
old_dbt.data = beg;
old_dbt.size = dbt->dlen;
- if ((ret = __ham_replace_log(hashp->dbp->dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
- hashp->dbp->log_fileid, PGNO(hcp->pagep),
+ if ((ret = __ham_replace_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, dbp->log_fileid, PGNO(hcp->pagep),
(u_int32_t)H_DATAINDEX(hcp->bndx), &LSN(hcp->pagep),
(u_int32_t)dbt->doff, &old_dbt, dbt, make_dup)) != 0)
return (ret);
@@ -934,7 +993,7 @@ err: __db_free(tmp.data);
LSN(hcp->pagep) = new_lsn; /* Structure assignment. */
}
- __ham_onpage_replace(hcp->pagep, hashp->dbp->pgsize,
+ __ham_onpage_replace(hcp->pagep, dbp->pgsize,
(u_int32_t)H_DATAINDEX(hcp->bndx), (int32_t)dbt->doff, change, dbt);
return (0);
@@ -997,13 +1056,15 @@ __ham_onpage_replace(pagep, pgsize, ndx, off, change, dbt)
}
/*
- * PUBLIC: int __ham_split_page __P((HTAB *, u_int32_t, u_int32_t));
+ * PUBLIC: int __ham_split_page __P((DBC *, u_int32_t, u_int32_t));
*/
int
-__ham_split_page(hashp, obucket, nbucket)
- HTAB *hashp;
+__ham_split_page(dbc, obucket, nbucket)
+ DBC *dbc;
u_int32_t obucket, nbucket;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DBT key, page_dbt;
DB_ENV *dbenv;
DB_LSN new_lsn;
@@ -1014,33 +1075,34 @@ __ham_split_page(hashp, obucket, nbucket)
int ret, tret;
void *big_buf;
- dbenv = hashp->dbp->dbenv;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+ dbenv = dbp->dbenv;
temp_pagep = old_pagep = new_pagep = NULL;
- bucket_pgno = BUCKET_TO_PAGE(hashp, obucket);
- if ((ret = __ham_get_page(hashp->dbp, bucket_pgno, &old_pagep)) != 0)
+ bucket_pgno = BUCKET_TO_PAGE(hcp, obucket);
+ if ((ret = __ham_get_page(dbp, bucket_pgno, &old_pagep)) != 0)
return (ret);
- if ((ret = __ham_new_page(hashp, BUCKET_TO_PAGE(hashp, nbucket), P_HASH,
+ if ((ret = __ham_new_page(dbp, BUCKET_TO_PAGE(hcp, nbucket), P_HASH,
&new_pagep)) != 0)
goto err;
- temp_pagep = hashp->split_buf;
- memcpy(temp_pagep, old_pagep, hashp->hdr->pagesize);
+ temp_pagep = hcp->split_buf;
+ memcpy(temp_pagep, old_pagep, hcp->hdr->pagesize);
- if (DB_LOGGING(hashp->dbp)) {
- page_dbt.size = hashp->hdr->pagesize;
+ if (DB_LOGGING(dbc)) {
+ page_dbt.size = hcp->hdr->pagesize;
page_dbt.data = old_pagep;
if ((ret = __ham_splitdata_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
- hashp->dbp->log_fileid, SPLITOLD, PGNO(old_pagep),
- &page_dbt, &LSN(old_pagep))) != 0)
+ dbc->txn, &new_lsn, 0, dbp->log_fileid, SPLITOLD,
+ PGNO(old_pagep), &page_dbt, &LSN(old_pagep))) != 0)
goto err;
}
- P_INIT(old_pagep, hashp->hdr->pagesize, PGNO(old_pagep), PGNO_INVALID,
+ P_INIT(old_pagep, hcp->hdr->pagesize, PGNO(old_pagep), PGNO_INVALID,
PGNO_INVALID, 0, P_HASH);
- if (DB_LOGGING(hashp->dbp))
+ if (DB_LOGGING(dbc))
LSN(old_pagep) = new_lsn; /* Structure assignment. */
big_len = 0;
@@ -1049,11 +1111,11 @@ __ham_split_page(hashp, obucket, nbucket)
while (temp_pagep != NULL) {
for (n = 0; n < (db_indx_t)H_NUMPAIRS(temp_pagep); n++) {
if ((ret =
- __db_ret(hashp->dbp, temp_pagep, H_KEYINDEX(n),
+ __db_ret(dbp, temp_pagep, H_KEYINDEX(n),
&key, &big_buf, &big_len)) != 0)
goto err;
- if (__ham_call_hash(hashp, key.data, key.size)
+ if (__ham_call_hash(hcp, key.data, key.size)
== obucket)
pp = &old_pagep;
else
@@ -1064,59 +1126,59 @@ __ham_split_page(hashp, obucket, nbucket)
* page to store the key/data pair.
*/
- len = LEN_HITEM(temp_pagep, hashp->hdr->pagesize,
+ len = LEN_HITEM(temp_pagep, hcp->hdr->pagesize,
H_DATAINDEX(n)) +
- LEN_HITEM(temp_pagep, hashp->hdr->pagesize,
+ LEN_HITEM(temp_pagep, hcp->hdr->pagesize,
H_KEYINDEX(n)) +
2 * sizeof(db_indx_t);
if (P_FREESPACE(*pp) < len) {
- if (DB_LOGGING(hashp->dbp)) {
- page_dbt.size = hashp->hdr->pagesize;
+ if (DB_LOGGING(dbc)) {
+ page_dbt.size = hcp->hdr->pagesize;
page_dbt.data = *pp;
if ((ret = __ham_splitdata_log(
- dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn,
- &new_lsn, 0,
- hashp->dbp->log_fileid, SPLITNEW,
- PGNO(*pp), &page_dbt,
+ dbenv->lg_info, dbc->txn,
+ &new_lsn, 0, dbp->log_fileid,
+ SPLITNEW, PGNO(*pp), &page_dbt,
&LSN(*pp))) != 0)
goto err;
LSN(*pp) = new_lsn;
}
- if ((ret = __ham_add_ovflpage(hashp,
- *pp, 1, pp)) != 0)
+ if ((ret =
+ __ham_add_ovflpage(dbc, *pp, 1, pp)) != 0)
goto err;
}
- __ham_copy_item(hashp, temp_pagep, H_KEYINDEX(n), *pp);
- __ham_copy_item(hashp, temp_pagep, H_DATAINDEX(n), *pp);
+ __ham_copy_item(dbp->pgsize,
+ temp_pagep, H_KEYINDEX(n), *pp);
+ __ham_copy_item(dbp->pgsize,
+ temp_pagep, H_DATAINDEX(n), *pp);
}
next_pgno = NEXT_PGNO(temp_pagep);
/* Clear temp_page; if it's a link overflow page, free it. */
if (PGNO(temp_pagep) != bucket_pgno && (ret =
- __ham_del_page(hashp->dbp, temp_pagep)) != 0)
+ __ham_del_page(dbc, temp_pagep)) != 0)
goto err;
if (next_pgno == PGNO_INVALID)
temp_pagep = NULL;
else if ((ret =
- __ham_get_page(hashp->dbp, next_pgno, &temp_pagep)) != 0)
+ __ham_get_page(dbp, next_pgno, &temp_pagep)) != 0)
goto err;
- if (temp_pagep != NULL && DB_LOGGING(hashp->dbp)) {
- page_dbt.size = hashp->hdr->pagesize;
+ if (temp_pagep != NULL && DB_LOGGING(dbc)) {
+ page_dbt.size = hcp->hdr->pagesize;
page_dbt.data = temp_pagep;
if ((ret = __ham_splitdata_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
- hashp->dbp->log_fileid, SPLITOLD, PGNO(temp_pagep),
+ dbc->txn, &new_lsn, 0, dbp->log_fileid,
+ SPLITOLD, PGNO(temp_pagep),
&page_dbt, &LSN(temp_pagep))) != 0)
goto err;
LSN(temp_pagep) = new_lsn;
}
}
if (big_buf != NULL)
- __db_free(big_buf);
+ __os_free(big_buf, big_len);
/*
* If the original bucket spanned multiple pages, then we've got
@@ -1124,42 +1186,41 @@ __ham_split_page(hashp, obucket, nbucket)
* should be deleted.
*/
if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno &&
- (ret = __ham_del_page(hashp->dbp, temp_pagep)) != 0)
+ (ret = __ham_del_page(dbc, temp_pagep)) != 0)
goto err;
/*
* Write new buckets out.
*/
- if (DB_LOGGING(hashp->dbp)) {
- page_dbt.size = hashp->hdr->pagesize;
+ if (DB_LOGGING(dbc)) {
+ page_dbt.size = hcp->hdr->pagesize;
page_dbt.data = old_pagep;
if ((ret = __ham_splitdata_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
- hashp->dbp->log_fileid, SPLITNEW, PGNO(old_pagep),
+ dbc->txn, &new_lsn, 0, dbp->log_fileid,
+ SPLITNEW, PGNO(old_pagep),
&page_dbt, &LSN(old_pagep))) != 0)
goto err;
LSN(old_pagep) = new_lsn;
page_dbt.data = new_pagep;
if ((ret = __ham_splitdata_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,
- hashp->dbp->log_fileid, SPLITNEW, PGNO(new_pagep),
- &page_dbt, &LSN(new_pagep))) != 0)
+ dbc->txn, &new_lsn, 0, dbp->log_fileid,
+ SPLITNEW, PGNO(new_pagep), &page_dbt, &LSN(new_pagep))) != 0)
goto err;
LSN(new_pagep) = new_lsn;
}
- ret = __ham_put_page(hashp->dbp, old_pagep, 1);
- if ((tret = __ham_put_page(hashp->dbp, new_pagep, 1)) != 0 &&
+ ret = __ham_put_page(dbp, old_pagep, 1);
+ if ((tret = __ham_put_page(dbp, new_pagep, 1)) != 0 &&
ret == 0)
ret = tret;
if (0) {
err: if (old_pagep != NULL)
- (void)__ham_put_page(hashp->dbp, old_pagep, 1);
+ (void)__ham_put_page(dbp, old_pagep, 1);
if (new_pagep != NULL)
- (void)__ham_put_page(hashp->dbp, new_pagep, 1);
+ (void)__ham_put_page(dbp, new_pagep, 1);
if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno)
- (void)__ham_put_page(hashp->dbp, temp_pagep, 1);
+ (void)__ham_put_page(dbp, temp_pagep, 1);
}
return (ret);
}
@@ -1171,16 +1232,16 @@ err: if (old_pagep != NULL)
* to which we just added something. This allows us to link overflow
* pages and return the new page having correctly put the last page.
*
- * PUBLIC: int __ham_add_el
- * PUBLIC: __P((HTAB *, HASH_CURSOR *, const DBT *, const DBT *, int));
+ * PUBLIC: int __ham_add_el __P((DBC *, const DBT *, const DBT *, int));
*/
int
-__ham_add_el(hashp, hcp, key, val, type)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_add_el(dbc, key, val, type)
+ DBC *dbc;
const DBT *key, *val;
int type;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
const DBT *pkey, *pdata;
DBT key_dbt, data_dbt;
DB_LSN new_lsn;
@@ -1190,17 +1251,19 @@ __ham_add_el(hashp, hcp, key, val, type)
int do_expand, is_keybig, is_databig, ret;
int key_type, data_type;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
do_expand = 0;
- if (hcp->pagep == NULL && (ret = __ham_get_page(hashp->dbp,
+ if (hcp->pagep == NULL && (ret = __ham_get_page(dbp,
hcp->seek_found_page != PGNO_INVALID ? hcp->seek_found_page :
hcp->pgno, &hcp->pagep)) != 0)
return (ret);
key_size = HKEYDATA_PSIZE(key->size);
data_size = HKEYDATA_PSIZE(val->size);
- is_keybig = ISBIG(hashp, key->size);
- is_databig = ISBIG(hashp, val->size);
+ is_keybig = ISBIG(hcp, key->size);
+ is_databig = ISBIG(hcp, val->size);
if (is_keybig)
key_size = HOFFPAGE_PSIZE;
if (is_databig)
@@ -1220,7 +1283,7 @@ __ham_add_el(hashp, hcp, key, val, type)
break;
next_pgno = NEXT_PGNO(hcp->pagep);
if ((ret =
- __ham_next_cpage(hashp, hcp, next_pgno, 0, 0)) != 0)
+ __ham_next_cpage(dbc, next_pgno, 0, 0)) != 0)
return (ret);
}
@@ -1229,7 +1292,7 @@ __ham_add_el(hashp, hcp, key, val, type)
*/
if (P_FREESPACE(hcp->pagep) < pairsize) {
do_expand = 1;
- if ((ret = __ham_add_ovflpage(hashp,
+ if ((ret = __ham_add_ovflpage(dbc,
hcp->pagep, 1, &hcp->pagep)) != 0)
return (ret);
hcp->pgno = PGNO(hcp->pagep);
@@ -1241,10 +1304,13 @@ __ham_add_el(hashp, hcp, key, val, type)
hcp->bndx = H_NUMPAIRS(hcp->pagep);
F_CLR(hcp, H_DELETED);
if (is_keybig) {
- if ((ret = __db_poff(hashp->dbp,
+ koff.type = H_OFFPAGE;
+ UMRW(koff.unused[0]);
+ UMRW(koff.unused[1]);
+ UMRW(koff.unused[2]);
+ if ((ret = __db_poff(dbc,
key, &koff.pgno, __ham_overflow_page)) != 0)
return (ret);
- koff.type = H_OFFPAGE;
koff.tlen = key->size;
key_dbt.data = &koff;
key_dbt.size = sizeof(koff);
@@ -1256,10 +1322,13 @@ __ham_add_el(hashp, hcp, key, val, type)
}
if (is_databig) {
- if ((ret = __db_poff(hashp->dbp,
+ doff.type = H_OFFPAGE;
+ UMRW(doff.unused[0]);
+ UMRW(doff.unused[1]);
+ UMRW(doff.unused[2]);
+ if ((ret = __db_poff(dbc,
val, &doff.pgno, __ham_overflow_page)) != 0)
return (ret);
- doff.type = H_OFFPAGE;
doff.tlen = val->size;
data_dbt.data = &doff;
data_dbt.size = sizeof(doff);
@@ -1270,16 +1339,16 @@ __ham_add_el(hashp, hcp, key, val, type)
data_type = type;
}
- if (DB_LOGGING(hashp->dbp)) {
+ if (DB_LOGGING(dbc)) {
rectype = PUTPAIR;
if (is_databig)
rectype |= PAIR_DATAMASK;
if (is_keybig)
rectype |= PAIR_KEYMASK;
- if ((ret = __ham_insdel_log(hashp->dbp->dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, rectype,
- hashp->dbp->log_fileid, PGNO(hcp->pagep),
+ if ((ret = __ham_insdel_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, rectype,
+ dbp->log_fileid, PGNO(hcp->pagep),
(u_int32_t)H_NUMPAIRS(hcp->pagep),
&LSN(hcp->pagep), pkey, pdata)) != 0)
return (ret);
@@ -1303,11 +1372,11 @@ __ham_add_el(hashp, hcp, key, val, type)
/*
* XXX Maybe keep incremental numbers here
*/
- if (!F_ISSET(hashp->dbp, DB_AM_LOCKING))
- hashp->hdr->nelem++;
+ if (!F_ISSET(dbp, DB_AM_LOCKING))
+ hcp->hdr->nelem++;
- if (do_expand || (hashp->hdr->ffactor != 0 &&
- (u_int32_t)H_NUMPAIRS(hcp->pagep) > hashp->hdr->ffactor))
+ if (do_expand || (hcp->hdr->ffactor != 0 &&
+ (u_int32_t)H_NUMPAIRS(hcp->pagep) > hcp->hdr->ffactor))
F_SET(hcp, H_EXPAND);
return (0);
}
@@ -1319,11 +1388,11 @@ __ham_add_el(hashp, hcp, key, val, type)
* H_DUPLICATE, H_OFFDUP). Since we log splits at a high level, we
* do not need to do any logging here.
*
- * PUBLIC: void __ham_copy_item __P((HTAB *, PAGE *, u_int32_t, PAGE *));
+ * PUBLIC: void __ham_copy_item __P((size_t, PAGE *, u_int32_t, PAGE *));
*/
void
-__ham_copy_item(hashp, src_page, src_ndx, dest_page)
- HTAB *hashp;
+__ham_copy_item(pgsize, src_page, src_ndx, dest_page)
+ size_t pgsize;
PAGE *src_page;
u_int32_t src_ndx;
PAGE *dest_page;
@@ -1337,7 +1406,7 @@ __ham_copy_item(hashp, src_page, src_ndx, dest_page)
src = P_ENTRY(src_page, src_ndx);
/* Set up space on dest. */
- len = LEN_HITEM(src_page, hashp->hdr->pagesize, src_ndx);
+ len = LEN_HITEM(src_page, pgsize, src_ndx);
HOFFSET(dest_page) -= len;
dest_page->inp[NUM_ENT(dest_page)] = HOFFSET(dest_page);
dest = P_ENTRY(dest_page, NUM_ENT(dest_page));
@@ -1352,29 +1421,31 @@ __ham_copy_item(hashp, src_page, src_ndx, dest_page)
* pointer on success
* NULL on error
*
- * PUBLIC: int __ham_add_ovflpage __P((HTAB *, PAGE *, int, PAGE **));
+ * PUBLIC: int __ham_add_ovflpage __P((DBC *, PAGE *, int, PAGE **));
*/
int
-__ham_add_ovflpage(hashp, pagep, release, pp)
- HTAB *hashp;
+__ham_add_ovflpage(dbc, pagep, release, pp)
+ DBC *dbc;
PAGE *pagep;
int release;
PAGE **pp;
{
- DB_ENV *dbenv;
+ DB *dbp;
+ HASH_CURSOR *hcp;
DB_LSN new_lsn;
PAGE *new_pagep;
int ret;
- dbenv = hashp->dbp->dbenv;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
- if ((ret = __ham_overflow_page(hashp->dbp, P_HASH, &new_pagep)) != 0)
+ if ((ret = __ham_overflow_page(dbc, P_HASH, &new_pagep)) != 0)
return (ret);
- if (DB_LOGGING(hashp->dbp)) {
- if ((ret = __ham_newpage_log(dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, PUTOVFL,
- hashp->dbp->log_fileid, PGNO(pagep), &LSN(pagep),
+ if (DB_LOGGING(dbc)) {
+ if ((ret = __ham_newpage_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, PUTOVFL,
+ dbp->log_fileid, PGNO(pagep), &LSN(pagep),
PGNO(new_pagep), &LSN(new_pagep), PGNO_INVALID, NULL)) != 0)
return (ret);
@@ -1385,78 +1456,76 @@ __ham_add_ovflpage(hashp, pagep, release, pp)
PREV_PGNO(new_pagep) = PGNO(pagep);
if (release)
- ret = __ham_put_page(hashp->dbp, pagep, 1);
+ ret = __ham_put_page(dbp, pagep, 1);
- hashp->hash_overflows++;
+ hcp->stats.hash_overflows++;
*pp = new_pagep;
return (ret);
}
/*
- * PUBLIC: int __ham_new_page __P((HTAB *, u_int32_t, u_int32_t, PAGE **));
+ * PUBLIC: int __ham_new_page __P((DB *, u_int32_t, u_int32_t, PAGE **));
*/
int
-__ham_new_page(hashp, addr, type, pp)
- HTAB *hashp;
+__ham_new_page(dbp, addr, type, pp)
+ DB *dbp;
u_int32_t addr, type;
PAGE **pp;
{
PAGE *pagep;
int ret;
- if ((ret = memp_fget(hashp->dbp->mpf,
+ if ((ret = memp_fget(dbp->mpf,
&addr, DB_MPOOL_CREATE, &pagep)) != 0)
return (ret);
-#ifdef DEBUG_SLOW
- __account_page(hashp, addr, 1);
-#endif
/* This should not be necessary because page-in should do it. */
- P_INIT(pagep,
- hashp->hdr->pagesize, addr, PGNO_INVALID, PGNO_INVALID, 0, type);
+ P_INIT(pagep, dbp->pgsize, addr, PGNO_INVALID, PGNO_INVALID, 0, type);
*pp = pagep;
return (0);
}
/*
- * PUBLIC: int __ham_del_page __P((DB *, PAGE *));
+ * PUBLIC: int __ham_del_page __P((DBC *, PAGE *));
*/
int
-__ham_del_page(dbp, pagep)
- DB *dbp;
+__ham_del_page(dbc, pagep)
+ DBC *dbc;
PAGE *pagep;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DB_LSN new_lsn;
- HTAB *hashp;
int ret;
- hashp = (HTAB *)dbp->internal;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
ret = 0;
- DIRTY_META(hashp, ret);
+ DIRTY_META(dbp, hcp, ret);
if (ret != 0) {
if (ret != EAGAIN)
- __db_err(hashp->dbp->dbenv,
+ __db_err(dbp->dbenv,
"free_ovflpage: unable to lock meta data page %s\n",
strerror(ret));
/*
* If we are going to return an error, then we should free
* the page, so it doesn't stay pinned forever.
*/
- (void)__ham_put_page(hashp->dbp, pagep, 0);
+ (void)__ham_put_page(dbp, pagep, 0);
return (ret);
}
- if (DB_LOGGING(hashp->dbp)) {
- if ((ret = __ham_newpgno_log(hashp->dbp->dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, DELPGNO,
- hashp->dbp->log_fileid, PGNO(pagep), hashp->hdr->last_freed,
+ if (DB_LOGGING(dbc)) {
+ if ((ret = __ham_newpgno_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, DELPGNO,
+ dbp->log_fileid, PGNO(pagep), hcp->hdr->last_freed,
(u_int32_t)TYPE(pagep), NEXT_PGNO(pagep), P_INVALID,
- &LSN(pagep), &hashp->hdr->lsn)) != 0)
+ &LSN(pagep), &hcp->hdr->lsn)) != 0)
return (ret);
- hashp->hdr->lsn = new_lsn;
+ hcp->hdr->lsn = new_lsn;
LSN(pagep) = new_lsn;
}
@@ -1466,16 +1535,16 @@ __ham_del_page(dbp, pagep)
DB_LSN __lsn;
__pgno = pagep->pgno;
__lsn = pagep->lsn;
- memset(pagep, 0xff, dbp->pgsize);
+ memset(pagep, 0xdb, dbp->pgsize);
pagep->pgno = __pgno;
pagep->lsn = __lsn;
}
#endif
TYPE(pagep) = P_INVALID;
- NEXT_PGNO(pagep) = hashp->hdr->last_freed;
- hashp->hdr->last_freed = PGNO(pagep);
+ NEXT_PGNO(pagep) = hcp->hdr->last_freed;
+ hcp->hdr->last_freed = PGNO(pagep);
- return (__ham_put_page(hashp->dbp, pagep, 1));
+ return (__ham_put_page(dbp, pagep, 1));
}
@@ -1489,8 +1558,7 @@ __ham_put_page(dbp, pagep, is_dirty)
int32_t is_dirty;
{
#ifdef DEBUG_SLOW
- __account_page((HTAB *)dbp->cookie,
- ((BKT *)((char *)pagep - sizeof(BKT)))->pgno, -1);
+ __account_page(dbp, ((BKT *)((char *)pagep - sizeof(BKT)))->pgno, -1);
#endif
return (memp_fput(dbp->mpf, pagep, (is_dirty ? DB_MPOOL_DIRTY : 0)));
}
@@ -1499,14 +1567,14 @@ __ham_put_page(dbp, pagep, is_dirty)
* __ham_dirty_page --
* Mark a page dirty.
*
- * PUBLIC: int __ham_dirty_page __P((HTAB *, PAGE *));
+ * PUBLIC: int __ham_dirty_page __P((DB *, PAGE *));
*/
int
-__ham_dirty_page(hashp, pagep)
- HTAB *hashp;
+__ham_dirty_page(dbp, pagep)
+ DB *dbp;
PAGE *pagep;
{
- return (memp_fset(hashp->dbp->mpf, pagep, DB_MPOOL_DIRTY));
+ return (memp_fset(dbp->mpf, pagep, DB_MPOOL_DIRTY));
}
/*
@@ -1523,31 +1591,33 @@ __ham_get_page(dbp, addr, pagep)
ret = memp_fget(dbp->mpf, &addr, DB_MPOOL_CREATE, pagep);
#ifdef DEBUG_SLOW
if (*pagep != NULL)
- __account_page((HTAB *)dbp->internal, addr, 1);
+ __account_page(dbp, addr, 1);
#endif
return (ret);
}
/*
- * PUBLIC: int __ham_overflow_page __P((DB *, u_int32_t, PAGE **));
+ * PUBLIC: int __ham_overflow_page
+ * PUBLIC: __P((DBC *, u_int32_t, PAGE **));
*/
int
-__ham_overflow_page(dbp, type, pp)
- DB *dbp;
+__ham_overflow_page(dbc, type, pp)
+ DBC *dbc;
u_int32_t type;
PAGE **pp;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DB_LSN *lsnp, new_lsn;
- HTAB *hashp;
PAGE *p;
db_pgno_t new_addr, next_free, newalloc_flag;
u_int32_t offset, splitnum;
int ret;
- hashp = (HTAB *)dbp->internal;
-
ret = 0;
- DIRTY_META(hashp, ret);
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+ DIRTY_META(dbp, hcp, ret);
if (ret != 0)
return (ret);
@@ -1558,22 +1628,22 @@ __ham_overflow_page(dbp, type, pp)
* after the log do we get to complete allocation of the
* new page.
*/
- new_addr = hashp->hdr->last_freed;
+ new_addr = hcp->hdr->last_freed;
if (new_addr != PGNO_INVALID) {
- if ((ret = __ham_get_page(hashp->dbp, new_addr, &p)) != 0)
+ if ((ret = __ham_get_page(dbp, new_addr, &p)) != 0)
return (ret);
next_free = NEXT_PGNO(p);
lsnp = &LSN(p);
newalloc_flag = 0;
} else {
- splitnum = hashp->hdr->ovfl_point;
- hashp->hdr->spares[splitnum]++;
- offset = hashp->hdr->spares[splitnum] -
- (splitnum ? hashp->hdr->spares[splitnum - 1] : 0);
- new_addr = PGNO_OF(hashp, hashp->hdr->ovfl_point, offset);
- if (new_addr > MAX_PAGES(hashp)) {
- __db_err(hashp->dbp->dbenv, "hash: out of file pages");
- hashp->hdr->spares[splitnum]--;
+ splitnum = hcp->hdr->ovfl_point;
+ hcp->hdr->spares[splitnum]++;
+ offset = hcp->hdr->spares[splitnum] -
+ (splitnum ? hcp->hdr->spares[splitnum - 1] : 0);
+ new_addr = PGNO_OF(hcp, hcp->hdr->ovfl_point, offset);
+ if (new_addr > MAX_PAGES(hcp)) {
+ __db_err(dbp->dbenv, "hash: out of file pages");
+ hcp->hdr->spares[splitnum]--;
return (ENOMEM);
}
next_free = PGNO_INVALID;
@@ -1582,29 +1652,29 @@ __ham_overflow_page(dbp, type, pp)
newalloc_flag = 1;
}
- if (DB_LOGGING(hashp->dbp)) {
- if ((ret = __ham_newpgno_log(hashp->dbp->dbenv->lg_info,
- (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, ALLOCPGNO,
- hashp->dbp->log_fileid, new_addr, next_free,
- 0, newalloc_flag, type, lsnp, &hashp->hdr->lsn)) != 0)
+ if (DB_LOGGING(dbc)) {
+ if ((ret = __ham_newpgno_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, ALLOCPGNO,
+ dbp->log_fileid, new_addr, next_free,
+ 0, newalloc_flag, type, lsnp, &hcp->hdr->lsn)) != 0)
return (ret);
- hashp->hdr->lsn = new_lsn;
+ hcp->hdr->lsn = new_lsn;
if (lsnp != NULL)
*lsnp = new_lsn;
}
if (p != NULL) {
/* We just took something off the free list, initialize it. */
- hashp->hdr->last_freed = next_free;
- P_INIT(p, hashp->hdr->pagesize, PGNO(p), PGNO_INVALID,
+ hcp->hdr->last_freed = next_free;
+ P_INIT(p, hcp->hdr->pagesize, PGNO(p), PGNO_INVALID,
PGNO_INVALID, 0, (u_int8_t)type);
} else {
/* Get the new page. */
- if ((ret = __ham_new_page(hashp, new_addr, type, &p)) != 0)
+ if ((ret = __ham_new_page(dbp, new_addr, type, &p)) != 0)
return (ret);
}
- if (DB_LOGGING(hashp->dbp))
+ if (DB_LOGGING(dbc))
LSN(p) = new_lsn;
*pp = p;
@@ -1614,94 +1684,123 @@ __ham_overflow_page(dbp, type, pp)
#ifdef DEBUG
/*
* PUBLIC: #ifdef DEBUG
- * PUBLIC: db_pgno_t __bucket_to_page __P((HTAB *, db_pgno_t));
+ * PUBLIC: db_pgno_t __bucket_to_page __P((HASH_CURSOR *, db_pgno_t));
* PUBLIC: #endif
*/
db_pgno_t
-__bucket_to_page(hashp, n)
- HTAB *hashp;
+__bucket_to_page(hcp, n)
+ HASH_CURSOR *hcp;
db_pgno_t n;
{
int ret_val;
ret_val = n + 1;
if (n != 0)
- ret_val += hashp->hdr->spares[__db_log2(n + 1) - 1];
+ ret_val += hcp->hdr->spares[__db_log2(n + 1) - 1];
return (ret_val);
}
#endif
/*
* Create a bunch of overflow pages at the current split point.
- * PUBLIC: void __ham_init_ovflpages __P((HTAB *));
+ * PUBLIC: void __ham_init_ovflpages __P((DBC *));
*/
void
-__ham_init_ovflpages(hp)
- HTAB *hp;
+__ham_init_ovflpages(dbc)
+ DBC *dbc;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
DB_LSN new_lsn;
PAGE *p;
db_pgno_t last_pgno, new_pgno;
u_int32_t i, curpages, numpages;
- curpages = hp->hdr->spares[hp->hdr->ovfl_point] -
- hp->hdr->spares[hp->hdr->ovfl_point - 1];
- numpages = hp->hdr->ovfl_point + 1 - curpages;
-
- last_pgno = hp->hdr->last_freed;
- new_pgno = PGNO_OF(hp, hp->hdr->ovfl_point, curpages + 1);
- if (DB_LOGGING(hp->dbp)) {
- (void)__ham_ovfl_log(hp->dbp->dbenv->lg_info,
- (DB_TXN *)hp->dbp->txn, &new_lsn, 0,
- hp->dbp->log_fileid, new_pgno,
- numpages, last_pgno, hp->hdr->ovfl_point, &hp->hdr->lsn);
- hp->hdr->lsn = new_lsn;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+
+ curpages = hcp->hdr->spares[hcp->hdr->ovfl_point] -
+ hcp->hdr->spares[hcp->hdr->ovfl_point - 1];
+ numpages = hcp->hdr->ovfl_point + 1 - curpages;
+
+ last_pgno = hcp->hdr->last_freed;
+ new_pgno = PGNO_OF(hcp, hcp->hdr->ovfl_point, curpages + 1);
+ if (DB_LOGGING(dbc)) {
+ (void)__ham_ovfl_log(dbp->dbenv->lg_info,
+ dbc->txn, &new_lsn, 0, dbp->log_fileid, new_pgno,
+ numpages, last_pgno, hcp->hdr->ovfl_point, &hcp->hdr->lsn);
+ hcp->hdr->lsn = new_lsn;
} else
ZERO_LSN(new_lsn);
- hp->hdr->spares[hp->hdr->ovfl_point] += numpages;
+ hcp->hdr->spares[hcp->hdr->ovfl_point] += numpages;
for (i = numpages; i > 0; i--) {
- if (__ham_new_page(hp,
- PGNO_OF(hp, hp->hdr->ovfl_point, curpages + i),
+ if (__ham_new_page(dbp,
+ PGNO_OF(hcp, hcp->hdr->ovfl_point, curpages + i),
P_INVALID, &p) != 0)
break;
LSN(p) = new_lsn;
NEXT_PGNO(p) = last_pgno;
last_pgno = PGNO(p);
- (void)__ham_put_page(hp->dbp, p, 1);
+ (void)__ham_put_page(dbp, p, 1);
}
- hp->hdr->last_freed = last_pgno;
+ hcp->hdr->last_freed = last_pgno;
}
/*
- * PUBLIC: int __ham_get_cpage __P((HTAB *, HASH_CURSOR *, db_lockmode_t));
+ * PUBLIC: int __ham_get_cpage __P((DBC *, db_lockmode_t));
*/
int
-__ham_get_cpage(hashp, hcp, mode)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_get_cpage(dbc, mode)
+ DBC *dbc;
db_lockmode_t mode;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
int ret;
- if (hcp->lock == 0 && F_ISSET(hashp->dbp, DB_AM_LOCKING) &&
- (ret = __ham_lock_bucket(hashp->dbp, hcp, mode)) != 0)
- return (ret);
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
+
+ /*
+ * There are three cases with respect to buckets and locks. If there
+ * is no lock held, then if we are locking, we should get the lock.
+ * If there is a lock held and it's for the current bucket, we don't
+ * need to do anything. If there is a lock, but it's for a different
+ * bucket, then we need to release and get.
+ */
+ if (F_ISSET(dbp, DB_AM_LOCKING)) {
+ if (hcp->lock != 0 && hcp->lbucket != hcp->bucket) {
+ /*
+ * If this is the original lock, don't release it,
+ * because we may need to restore it upon exit.
+ */
+ if (dbc->txn == NULL &&
+ !F_ISSET(hcp, H_ORIGINAL) && (ret =
+ lock_put(dbp->dbenv->lk_info, hcp->lock)) != 0)
+ return (ret);
+ F_CLR(hcp, H_ORIGINAL);
+ hcp->lock = 0;
+ }
+ if (hcp->lock == 0 && (ret = __ham_lock_bucket(dbc, mode)) != 0)
+ return (ret);
+ hcp->lbucket = hcp->bucket;
+ }
if (hcp->pagep == NULL) {
if (hcp->pgno == PGNO_INVALID) {
- hcp->pgno = BUCKET_TO_PAGE(hashp, hcp->bucket);
+ hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
hcp->bndx = 0;
}
if ((ret =
- __ham_get_page(hashp->dbp, hcp->pgno, &hcp->pagep)) != 0)
+ __ham_get_page(dbp, hcp->pgno, &hcp->pagep)) != 0)
return (ret);
}
if (hcp->dpgno != PGNO_INVALID && hcp->dpagep == NULL)
if ((ret =
- __ham_get_page(hashp->dbp, hcp->dpgno, &hcp->dpagep)) != 0)
+ __ham_get_page(dbp, hcp->dpgno, &hcp->dpagep)) != 0)
return (ret);
return (0);
}
@@ -1711,28 +1810,30 @@ __ham_get_cpage(hashp, hcp, mode)
* If the flag is set to H_ISDUP, then we are talking about the
* duplicate page, not the main page.
*
- * PUBLIC: int __ham_next_cpage
- * PUBLIC: __P((HTAB *, HASH_CURSOR *, db_pgno_t, int, u_int32_t));
+ * PUBLIC: int __ham_next_cpage __P((DBC *, db_pgno_t, int, u_int32_t));
*/
int
-__ham_next_cpage(hashp, hcp, pgno, dirty, flags)
- HTAB *hashp;
- HASH_CURSOR *hcp;
+__ham_next_cpage(dbc, pgno, dirty, flags)
+ DBC *dbc;
db_pgno_t pgno;
int dirty;
u_int32_t flags;
{
+ DB *dbp;
+ HASH_CURSOR *hcp;
PAGE *p;
int ret;
+ dbp = dbc->dbp;
+ hcp = (HASH_CURSOR *)dbc->internal;
if (LF_ISSET(H_ISDUP) && hcp->dpagep != NULL &&
- (ret = __ham_put_page(hashp->dbp, hcp->dpagep, dirty)) != 0)
+ (ret = __ham_put_page(dbp, hcp->dpagep, dirty)) != 0)
return (ret);
else if (!LF_ISSET(H_ISDUP) && hcp->pagep != NULL &&
- (ret = __ham_put_page(hashp->dbp, hcp->pagep, dirty)) != 0)
+ (ret = __ham_put_page(dbp, hcp->pagep, dirty)) != 0)
return (ret);
- if ((ret = __ham_get_page(hashp->dbp, pgno, &p)) != 0)
+ if ((ret = __ham_get_page(dbp, pgno, &p)) != 0)
return (ret);
if (LF_ISSET(H_ISDUP)) {
@@ -1753,22 +1854,21 @@ __ham_next_cpage(hashp, hcp, pgno, dirty, flags)
* Get the lock on a particular bucket.
*/
static int
-__ham_lock_bucket(dbp, hcp, mode)
- DB *dbp;
- HASH_CURSOR *hcp;
+__ham_lock_bucket(dbc, mode)
+ DBC *dbc;
db_lockmode_t mode;
{
+ HASH_CURSOR *hcp;
int ret;
- /*
- * What a way to trounce on the memory system. It might be
- * worth copying the lk_info into the hashp.
- */
- ret = 0;
- dbp->lock.pgno = (db_pgno_t)(hcp->bucket);
- ret = lock_get(dbp->dbenv->lk_info,
- dbp->txn == NULL ? dbp->locker : dbp->txn->txnid, 0,
- &dbp->lock_dbt, mode, &hcp->lock);
+ hcp = (HASH_CURSOR *)dbc->internal;
+ dbc->lock.pgno = (db_pgno_t)(hcp->bucket);
+ if (dbc->txn == NULL)
+ ret = lock_get(dbc->dbp->dbenv->lk_info, dbc->locker, 0,
+ &dbc->lock_dbt, mode, &hcp->lock);
+ else
+ ret = lock_tget(dbc->dbp->dbenv->lk_info, dbc->txn, 0,
+ &dbc->lock_dbt, mode, &hcp->lock);
return (ret < 0 ? EAGAIN : ret);
}
@@ -1827,45 +1927,3 @@ __ham_dpair(dbp, p, pndx)
HOFFSET(p) = HOFFSET(p) + delta;
NUM_ENT(p) = NUM_ENT(p) - 2;
}
-
-#ifdef DEBUG_SLOW
-static void
-__account_page(hashp, pgno, inout)
- HTAB *hashp;
- db_pgno_t pgno;
- int inout;
-{
- static struct {
- db_pgno_t pgno;
- int times;
- } list[100];
- static int last;
- int i, j;
-
- if (inout == -1) /* XXX: Kluge */
- inout = 0;
-
- /* Find page in list. */
- for (i = 0; i < last; i++)
- if (list[i].pgno == pgno)
- break;
- /* Not found. */
- if (i == last) {
- list[last].times = inout;
- list[last].pgno = pgno;
- last++;
- }
- list[i].times = inout;
- if (list[i].times == 0) {
- for (j = i; j < last; j++)
- list[j] = list[j + 1];
- last--;
- }
- for (i = 0; i < last; i++, list[i].times++)
- if (list[i].times > 20 &&
- !__is_bitmap_pgno(hashp, list[i].pgno))
- (void)fprintf(stderr,
- "Warning: pg %lu has been out for %d times\n",
- (u_long)list[i].pgno, list[i].times);
-}
-#endif /* DEBUG_SLOW */
diff --git a/db2/hash/hash_rec.c b/db2/hash/hash_rec.c
index 727f615828..b58f2c6eb7 100644
--- a/db2/hash/hash_rec.c
+++ b/db2/hash/hash_rec.c
@@ -47,7 +47,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)hash_rec.c 10.19 (Sleepycat) 5/23/98";
+static const char sccsid[] = "@(#)hash_rec.c 10.22 (Sleepycat) 10/21/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -80,17 +80,19 @@ __ham_insdel_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_insdel_args *argp;
- DB *mdbp, *file_dbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
- HTAB *hashp;
PAGE *pagep;
u_int32_t op;
int cmp_n, cmp_p, getmeta, ret;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_insdel_print);
REC_INTRO(__ham_insdel_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
if (ret != 0) {
@@ -101,16 +103,15 @@ __ham_insdel_recover(logp, dbtp, lsnp, redo, info)
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
- *lsnp = argp->prev_lsn;
- ret = 0;
- goto out;
+ goto done;
} else if ((ret = memp_fget(mpf, &argp->pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, hcp, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -144,7 +145,7 @@ __ham_insdel_recover(logp, dbtp, lsnp, redo, info)
!redo || PAIR_ISDATABIG(argp->opcode) ?
H_OFFPAGE : H_KEYDATA);
} else
- (void) __ham_reputpair(pagep, hashp->hdr->pagesize,
+ (void) __ham_reputpair(pagep, hcp->hdr->pagesize,
argp->ndx, &argp->key, &argp->data);
LSN(pagep) = redo ? *lsnp : argp->pagelsn;
@@ -163,10 +164,11 @@ __ham_insdel_recover(logp, dbtp, lsnp, redo, info)
goto out;
/* Return the previous LSN. */
- *lsnp = argp->prev_lsn;
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
@@ -187,16 +189,18 @@ __ham_newpage_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_newpage_args *argp;
- DB *mdbp, *file_dbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
- HTAB *hashp;
PAGE *pagep;
int cmp_n, cmp_p, change, getmeta, ret;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_newpage_print);
REC_INTRO(__ham_newpage_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
ret = memp_fget(mpf, &argp->new_pgno, 0, &pagep);
if (ret != 0) {
@@ -214,8 +218,9 @@ __ham_newpage_recover(logp, dbtp, lsnp, redo, info)
goto out;
}
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
/*
@@ -289,11 +294,13 @@ ppage: if (argp->prev_pgno != PGNO_INVALID) {
}
if (!change) {
- if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0)
+ if ((ret =
+ __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0)
goto out;
} else {
LSN(pagep) = redo ? *lsnp : argp->prevlsn;
- if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0)
+ if ((ret =
+ __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0)
goto out;
}
}
@@ -310,9 +317,7 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
* so we would not have to undo anything. In
* this case, don't bother creating a page.
*/
- *lsnp = argp->prev_lsn;
- ret = 0;
- goto out;
+ goto done;
} else if ((ret =
memp_fget(mpf, &argp->next_pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
@@ -346,10 +351,11 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
goto out;
}
}
- *lsnp = argp->prev_lsn;
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
@@ -372,19 +378,21 @@ __ham_replace_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_replace_args *argp;
- DB *mdbp, *file_dbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
DBT dbt;
- HTAB *hashp;
PAGE *pagep;
int32_t grow;
int change, cmp_n, cmp_p, getmeta, ret;
u_int8_t *hk;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_replace_print);
REC_INTRO(__ham_replace_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
if (ret != 0) {
@@ -395,16 +403,15 @@ __ham_replace_recover(logp, dbtp, lsnp, redo, info)
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
- *lsnp = argp->prev_lsn;
- ret = 0;
- goto out;
+ goto done;
} else if ((ret = memp_fget(mpf, &argp->pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -444,10 +451,11 @@ __ham_replace_recover(logp, dbtp, lsnp, redo, info)
if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0)
goto out;
- *lsnp = argp->prev_lsn;
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
@@ -468,19 +476,22 @@ __ham_newpgno_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_newpgno_args *argp;
- DB *mdbp, *file_dbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
- HTAB *hashp;
PAGE *pagep;
int change, cmp_n, cmp_p, getmeta, ret;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_newpgno_print);
REC_INTRO(__ham_newpgno_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
/*
@@ -488,34 +499,34 @@ __ham_newpgno_recover(logp, dbtp, lsnp, redo, info)
* to update the meta data; then we need to update the page.
* We'll do the meta-data first.
*/
- cmp_n = log_compare(lsnp, &hashp->hdr->lsn);
- cmp_p = log_compare(&hashp->hdr->lsn, &argp->metalsn);
+ cmp_n = log_compare(lsnp, &hcp->hdr->lsn);
+ cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn);
change = 0;
if ((cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) ||
(cmp_n == 0 && !redo && argp->opcode == DELPGNO)) {
/* Need to redo an allocation or undo a deletion. */
- hashp->hdr->last_freed = argp->free_pgno;
+ hcp->hdr->last_freed = argp->free_pgno;
if (redo && argp->old_pgno != 0) /* Must be ALLOCPGNO */
- hashp->hdr->spares[hashp->hdr->ovfl_point]++;
+ hcp->hdr->spares[hcp->hdr->ovfl_point]++;
change = 1;
} else if (cmp_p == 0 && redo && argp->opcode == DELPGNO) {
/* Need to redo a deletion */
- hashp->hdr->last_freed = argp->pgno;
+ hcp->hdr->last_freed = argp->pgno;
change = 1;
} else if (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO) {
/* undo an allocation. */
if (argp->old_pgno == 0)
- hashp->hdr->last_freed = argp->pgno;
+ hcp->hdr->last_freed = argp->pgno;
else {
- hashp->hdr->spares[hashp->hdr->ovfl_point]--;
- hashp->hdr->last_freed = 0;
+ hcp->hdr->spares[hcp->hdr->ovfl_point]--;
+ hcp->hdr->last_freed = 0;
}
change = 1;
}
if (change) {
- hashp->hdr->lsn = redo ? *lsnp : argp->metalsn;
- F_SET(file_dbp, DB_HS_DIRTYMETA);
+ hcp->hdr->lsn = redo ? *lsnp : argp->metalsn;
+ F_SET(hcp, H_DIRTY);
}
@@ -530,9 +541,7 @@ __ham_newpgno_recover(logp, dbtp, lsnp, redo, info)
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
- *lsnp = argp->prev_lsn;
- ret = 0;
- goto out;
+ goto done;
} else if ((ret = memp_fget(mpf, &argp->pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
@@ -565,10 +574,11 @@ __ham_newpgno_recover(logp, dbtp, lsnp, redo, info)
if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0)
goto out;
- *lsnp = argp->prev_lsn;
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
@@ -590,19 +600,22 @@ __ham_splitmeta_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_splitmeta_args *argp;
- DB *mdbp, *file_dbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
- HTAB *hashp;
int change, cmp_n, cmp_p, getmeta, ret;
u_int32_t pow;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_splitmeta_print);
REC_INTRO(__ham_splitmeta_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
/*
@@ -610,43 +623,45 @@ __ham_splitmeta_recover(logp, dbtp, lsnp, redo, info)
* to update the meta data; then we need to update the page.
* We'll do the meta-data first.
*/
- cmp_n = log_compare(lsnp, &hashp->hdr->lsn);
- cmp_p = log_compare(&hashp->hdr->lsn, &argp->metalsn);
+ cmp_n = log_compare(lsnp, &hcp->hdr->lsn);
+ cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn);
change = 0;
if (cmp_p == 0 && redo) {
/* Need to redo the split information. */
- hashp->hdr->max_bucket = argp->bucket + 1;
- pow = __db_log2(hashp->hdr->max_bucket + 1);
- if (pow > hashp->hdr->ovfl_point) {
- hashp->hdr->spares[pow] =
- hashp->hdr->spares[hashp->hdr->ovfl_point];
- hashp->hdr->ovfl_point = pow;
+ hcp->hdr->max_bucket = argp->bucket + 1;
+ pow = __db_log2(hcp->hdr->max_bucket + 1);
+ if (pow > hcp->hdr->ovfl_point) {
+ hcp->hdr->spares[pow] =
+ hcp->hdr->spares[hcp->hdr->ovfl_point];
+ hcp->hdr->ovfl_point = pow;
}
- if (hashp->hdr->max_bucket > hashp->hdr->high_mask) {
- hashp->hdr->low_mask = hashp->hdr->high_mask;
- hashp->hdr->high_mask =
- hashp->hdr->max_bucket | hashp->hdr->low_mask;
+ if (hcp->hdr->max_bucket > hcp->hdr->high_mask) {
+ hcp->hdr->low_mask = hcp->hdr->high_mask;
+ hcp->hdr->high_mask =
+ hcp->hdr->max_bucket | hcp->hdr->low_mask;
}
change = 1;
} else if (cmp_n == 0 && !redo) {
/* Need to undo the split information. */
- hashp->hdr->max_bucket = argp->bucket;
- hashp->hdr->ovfl_point = argp->ovflpoint;
- hashp->hdr->spares[hashp->hdr->ovfl_point] = argp->spares;
- pow = 1 << __db_log2(hashp->hdr->max_bucket + 1);
- hashp->hdr->high_mask = pow - 1;
- hashp->hdr->low_mask = (pow >> 1) - 1;
+ hcp->hdr->max_bucket = argp->bucket;
+ hcp->hdr->ovfl_point = argp->ovflpoint;
+ hcp->hdr->spares[hcp->hdr->ovfl_point] = argp->spares;
+ pow = 1 << __db_log2(hcp->hdr->max_bucket + 1);
+ hcp->hdr->high_mask = pow - 1;
+ hcp->hdr->low_mask = (pow >> 1) - 1;
change = 1;
}
if (change) {
- hashp->hdr->lsn = redo ? *lsnp : argp->metalsn;
- F_SET(file_dbp, DB_HS_DIRTYMETA);
+ hcp->hdr->lsn = redo ? *lsnp : argp->metalsn;
+ F_SET(hcp, H_DIRTY);
}
- *lsnp = argp->prev_lsn;
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
@@ -665,16 +680,18 @@ __ham_splitdata_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_splitdata_args *argp;
- DB *mdbp, *file_dbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
- HTAB *hashp;
PAGE *pagep;
int change, cmp_n, cmp_p, getmeta, ret;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_splitdata_print);
REC_INTRO(__ham_splitdata_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
if (ret != 0) {
@@ -685,16 +702,15 @@ __ham_splitdata_recover(logp, dbtp, lsnp, redo, info)
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
- *lsnp = argp->prev_lsn;
- ret = 0;
- goto out;
+ goto done;
} else if ((ret = memp_fget(mpf, &argp->pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
cmp_n = log_compare(lsnp, &LSN(pagep));
@@ -732,10 +748,11 @@ __ham_splitdata_recover(logp, dbtp, lsnp, redo, info)
if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0)
goto out;
- *lsnp = argp->prev_lsn;
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
@@ -755,50 +772,52 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_ovfl_args *argp;
- DB *mdbp, *file_dbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
- HTAB *hashp;
PAGE *pagep;
db_pgno_t max_pgno, pgno;
int cmp_n, cmp_p, getmeta, ret;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_ovfl_print);
REC_INTRO(__ham_ovfl_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
- cmp_n = log_compare(lsnp, &hashp->hdr->lsn);
- cmp_p = log_compare(&hashp->hdr->lsn, &argp->metalsn);
+ cmp_n = log_compare(lsnp, &hcp->hdr->lsn);
+ cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn);
if (cmp_p == 0 && redo) {
/* Redo the allocation. */
- hashp->hdr->last_freed = argp->start_pgno;
- hashp->hdr->spares[argp->ovflpoint] += argp->npages;
- hashp->hdr->lsn = *lsnp;
- F_SET(file_dbp, DB_HS_DIRTYMETA);
+ hcp->hdr->last_freed = argp->start_pgno;
+ hcp->hdr->spares[argp->ovflpoint] += argp->npages;
+ hcp->hdr->lsn = *lsnp;
+ F_SET(hcp, H_DIRTY);
} else if (cmp_n == 0 && !redo) {
- hashp->hdr->last_freed = argp->free_pgno;
- hashp->hdr->spares[argp->ovflpoint] -= argp->npages;
- hashp->hdr->lsn = argp->metalsn;
- F_SET(file_dbp, DB_HS_DIRTYMETA);
+ hcp->hdr->last_freed = argp->free_pgno;
+ hcp->hdr->spares[argp->ovflpoint] -= argp->npages;
+ hcp->hdr->lsn = argp->metalsn;
+ F_SET(hcp, H_DIRTY);
}
max_pgno = argp->start_pgno + argp->npages - 1;
ret = 0;
for (pgno = argp->start_pgno; pgno <= max_pgno; pgno++) {
- ret = memp_fget(mpf, &pgno, 0, &pagep);
- if (ret != 0) {
- if (redo && (ret = memp_fget(mpf, &pgno,
- DB_MPOOL_CREATE, &pagep)) != 0)
- goto out;
- else if (!redo) {
- (void)__ham_put_page(file_dbp, pagep, 0);
+ if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) {
+ if (!redo) {
+ ret = 0;
continue;
}
+ if ((ret = memp_fget(mpf,
+ &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
}
if (redo && log_compare((const DB_LSN *)lsnp,
(const DB_LSN *)&LSN(pagep)) > 0) {
@@ -816,9 +835,11 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
goto out;
}
- *lsnp = argp->prev_lsn;
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
@@ -838,19 +859,22 @@ __ham_copypage_recover(logp, dbtp, lsnp, redo, info)
void *info;
{
__ham_copypage_args *argp;
- DB *file_dbp, *mdbp;
+ DB *file_dbp;
+ DBC *dbc;
+ HASH_CURSOR *hcp;
DB_MPOOLFILE *mpf;
- HTAB *hashp;
PAGE *pagep;
int cmp_n, cmp_p, getmeta, modified, ret;
getmeta = 0;
- hashp = NULL; /* XXX: shut the compiler up. */
+ hcp = NULL;
REC_PRINT(__ham_copypage_print);
REC_INTRO(__ham_copypage_read);
+ hcp = (HASH_CURSOR *)dbc->internal;
- hashp = (HTAB *)file_dbp->internal;
- GET_META(file_dbp, hashp);
+ GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
+ if (ret != 0)
+ goto out;
getmeta = 1;
modified = 0;
@@ -881,7 +905,7 @@ __ham_copypage_recover(logp, dbtp, lsnp, redo, info)
modified = 1;
} else if (cmp_n == 0 && !redo) {
/* Need to undo update described. */
- P_INIT(pagep, hashp->hdr->pagesize, argp->pgno, PGNO_INVALID,
+ P_INIT(pagep, hcp->hdr->pagesize, argp->pgno, PGNO_INVALID,
argp->next_pgno, 0, P_HASH);
LSN(pagep) = argp->pagelsn;
modified = 1;
@@ -918,10 +942,8 @@ donext: ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep);
goto out;
/* Now fix up the next's next page. */
-do_nn: if (argp->nnext_pgno == PGNO_INVALID) {
- *lsnp = argp->prev_lsn;
- goto out;
- }
+do_nn: if (argp->nnext_pgno == PGNO_INVALID)
+ goto done;
ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep);
if (ret != 0) {
@@ -932,9 +954,7 @@ do_nn: if (argp->nnext_pgno == PGNO_INVALID) {
* would not have to undo anything. In this case,
* don't bother creating a page.
*/
- ret = 0;
- *lsnp = argp->prev_lsn;
- goto out;
+ goto done;
} else if ((ret = memp_fget(mpf, &argp->nnext_pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
@@ -957,9 +977,10 @@ do_nn: if (argp->nnext_pgno == PGNO_INVALID) {
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
- *lsnp = argp->prev_lsn;
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
out: if (getmeta)
- RELEASE_META(file_dbp, hashp);
+ RELEASE_META(file_dbp, hcp);
REC_CLOSE;
}
diff --git a/db2/hash/hash_stat.c b/db2/hash/hash_stat.c
index b57ca0950d..1b493d5f40 100644
--- a/db2/hash/hash_stat.c
+++ b/db2/hash/hash_stat.c
@@ -8,7 +8,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)hash_stat.c 10.8 (Sleepycat) 4/26/98";
+static const char sccsid[] = "@(#)hash_stat.c 10.12 (Sleepycat) 12/19/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -23,35 +23,22 @@ static const char sccsid[] = "@(#)hash_stat.c 10.8 (Sleepycat) 4/26/98";
/*
* __ham_stat --
- * Gather/print the hash statistics.
+ * Gather/print the hash statistics
*
- * PUBLIC: int __ham_stat __P((DB *, FILE *));
+ * PUBLIC: int __ham_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
*/
int
-__ham_stat(dbp, fp)
+__ham_stat(dbp, spp, db_malloc, flags)
DB *dbp;
- FILE *fp;
+ void *spp;
+ void *(*db_malloc) __P((size_t));
+ u_int32_t flags;
{
- HTAB *hashp;
- int i;
+ COMPQUIET(spp, NULL);
+ COMPQUIET(db_malloc, NULL);
+ COMPQUIET(flags, 0);
- hashp = (HTAB *)dbp->internal;
+ DB_PANIC_CHECK(dbp);
- fprintf(fp, "hash: accesses %lu collisions %lu\n",
- hashp->hash_accesses, hashp->hash_collisions);
- fprintf(fp, "hash: expansions %lu\n", hashp->hash_expansions);
- fprintf(fp, "hash: overflows %lu\n", hashp->hash_overflows);
- fprintf(fp, "hash: big key/data pages %lu\n", hashp->hash_bigpages);
-
- SET_LOCKER(dbp, NULL);
- GET_META(dbp, hashp);
- fprintf(fp, "keys %lu maxp %lu\n",
- (u_long)hashp->hdr->nelem, (u_long)hashp->hdr->max_bucket);
-
- for (i = 0; i < NCACHED; i++)
- fprintf(fp,
- "spares[%d] = %lu\n", i, (u_long)hashp->hdr->spares[i]);
-
- RELEASE_META(dbp, hashp);
- return (0);
+ return (__db_eopnotsup(dbp->dbenv));
}