aboutsummaryrefslogtreecommitdiff
path: root/db2/hash/hash_page.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/hash/hash_page.c')
-rw-r--r--db2/hash/hash_page.c1088
1 files changed, 573 insertions, 515 deletions
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 */