summaryrefslogtreecommitdiff
path: root/db2/hash
diff options
context:
space:
mode:
Diffstat (limited to 'db2/hash')
-rw-r--r--db2/hash/hash.c135
-rw-r--r--db2/hash/hash.src24
-rw-r--r--db2/hash/hash_auto.c274
-rw-r--r--db2/hash/hash_dup.c4
-rw-r--r--db2/hash/hash_page.c101
-rw-r--r--db2/hash/hash_rec.c146
6 files changed, 567 insertions, 117 deletions
diff --git a/db2/hash/hash.c b/db2/hash/hash.c
index d986e08087..c08495378e 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.27 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash.c 10.33 (Sleepycat) 11/2/97";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -79,7 +79,7 @@ static int __ham_cursor __P((DB *, DB_TXN *, DBC **));
static int __ham_delete __P((DB *, DB_TXN *, DBT *, int));
static int __ham_dup_return __P((HTAB *, HASH_CURSOR *, DBT *, int));
static int __ham_get __P((DB *, DB_TXN *, DBT *, DBT *, int));
-static void __ham_init_htab __P((HTAB *));
+static void __ham_init_htab __P((HTAB *, u_int));
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 *));
@@ -106,7 +106,7 @@ __ham_open(dbp, dbinfo)
dbenv = dbp->dbenv;
- if ((hashp = (HTAB *)calloc(1, sizeof(HTAB))) == NULL)
+ if ((hashp = (HTAB *)__db_calloc(1, sizeof(HTAB))) == NULL)
return (ENOMEM);
hashp->dbp = dbp;
@@ -175,10 +175,9 @@ __ham_open(dbp, dbinfo)
goto out;
}
- hashp->hdr->nelem = dbinfo != NULL ? dbinfo->h_nelem : 0;
hashp->hdr->ffactor =
dbinfo != NULL && dbinfo->h_ffactor ? dbinfo->h_ffactor : 0;
- __ham_init_htab(hashp);
+ __ham_init_htab(hashp, dbinfo != NULL ? dbinfo->h_nelem : 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)
@@ -190,7 +189,7 @@ __ham_open(dbp, dbinfo)
TAILQ_INSERT_TAIL(&dbp->curs_queue, curs, links);
/* Allocate memory for our split buffer. */
- if ((hashp->split_buf = (PAGE *)malloc(dbp->pgsize)) == NULL) {
+ if ((hashp->split_buf = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) {
ret = ENOMEM;
goto out;
}
@@ -265,13 +264,13 @@ __ham_close(dbp)
* Returns 0 on No Error
*/
static void
-__ham_init_htab(hashp)
+__ham_init_htab(hashp, nelem)
HTAB *hashp;
+ u_int nelem;
{
- u_int32_t nelem;
int32_t l2, nbuckets;
- nelem = hashp->hdr->nelem;
+ hashp->hdr->nelem = 0;
hashp->hdr->pagesize = hashp->dbp->pgsize;
ZERO_LSN(hashp->hdr->lsn);
hashp->hdr->magic = DB_HASHMAGIC;
@@ -502,11 +501,11 @@ __ham_c_init(dbp, txnid, dbcp)
DBC *db_curs;
HASH_CURSOR *new_curs;
- if ((db_curs = (DBC *)calloc(sizeof(DBC), 1)) == NULL)
+ if ((db_curs = (DBC *)__db_calloc(sizeof(DBC), 1)) == NULL)
return (ENOMEM);
if ((new_curs =
- (HASH_CURSOR *)calloc(sizeof(struct cursor_t), 1)) == NULL) {
+ (HASH_CURSOR *)__db_calloc(sizeof(struct cursor_t), 1)) == NULL) {
FREE(db_curs, sizeof(DBC));
return (ENOMEM);
}
@@ -555,7 +554,7 @@ __ham_delete(dbp, txn, key, flags)
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);
+ ret = __ham_del_pair(hashp, hcp, 1);
else
ret = DB_NOTFOUND;
@@ -669,30 +668,41 @@ __ham_c_del(cursor, flags)
if ((ret = __ham_get_cpage(hashp, hcp, DB_LOCK_WRITE)) != 0)
goto out;
if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno != PGNO_INVALID) {
- ppgno = PREV_PGNO(hcp->dpagep);
-
- /* Remove item from duplicate page. */
- chg_pgno = hcp->dpgno;
- if ((ret = __db_drem(hashp->dbp,
- &hcp->dpagep, hcp->dndx, __ham_del_page)) != 0)
- goto out;
-
/*
+ * We are about to remove a duplicate from offpage.
+ *
* There are 4 cases.
- * 1. We removed an item on a page, but nothing else changed.
- * 2. We removed the last item on a page, but there is a
+ * 1. We will remove an item on a page, but there are more
+ * items on that page.
+ * 2. We will remove the last item on a page, but there is a
* following page of duplicates.
- * 3. We removed the last item on a page, this page was the
+ * 3. We will remove the last item on a page, this page was the
* last page in a duplicate set, but there were dups before
* it.
- * 4. We removed the last item on a page, removing the last
+ * 4. We will remove the last item on a page, removing the last
* duplicate.
* In case 1 hcp->dpagep is unchanged.
* In case 2 hcp->dpagep comes back pointing to the next dup
* page.
* In case 3 hcp->dpagep comes back NULL.
* In case 4 hcp->dpagep comes back NULL.
+ *
+ * Case 4 results in deleting the pair off the master page.
+ * The normal code for doing this knows how to delete the
+ * duplicates, so we will handle this case in the normal code.
*/
+ ppgno = PREV_PGNO(hcp->dpagep);
+ if (ppgno == PGNO_INVALID &&
+ NEXT_PGNO(hcp->dpagep) == PGNO_INVALID &&
+ NUM_ENT(hcp->dpagep) == 1)
+ goto normal;
+
+ /* Remove item from duplicate page. */
+ chg_pgno = hcp->dpgno;
+ if ((ret = __db_drem(hashp->dbp,
+ &hcp->dpagep, hcp->dndx, __ham_del_page)) != 0)
+ goto out;
+
if (hcp->dpagep == NULL) {
if (ppgno != PGNO_INVALID) { /* Case 3 */
hcp->dpgno = ppgno;
@@ -702,7 +712,7 @@ __ham_c_del(cursor, flags)
hcp->dndx = NUM_ENT(hcp->dpagep);
F_SET(hcp, H_DELETED);
} else { /* Case 4 */
- ret = __ham_del_pair(hashp, hcp);
+ ret = __ham_del_pair(hashp, hcp, 1);
hcp->dpgno = PGNO_INVALID;
/*
* Delpair updated the cursor queue, so we
@@ -718,14 +728,14 @@ __ham_c_del(cursor, flags)
H_DATAINDEX(hcp->bndx))),
&hcp->dpgno, sizeof(db_pgno_t));
F_SET(hcp, H_DELETED);
- } else /* Case 1 */
+ } else /* Case 1 */
F_SET(hcp, H_DELETED);
if (chg_pgno != PGNO_INVALID)
__ham_c_update(hashp, 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);
+ ret = __ham_del_pair(hashp, hcp, 1);
else {
DBT repldbt;
@@ -736,14 +746,14 @@ __ham_c_del(cursor, flags)
repldbt.size = 0;
ret = __ham_replpair(hashp, hcp, &repldbt, 0);
hcp->dup_tlen -= DUP_SIZE(hcp->dup_len);
+ F_SET(hcp, H_DELETED);
__ham_c_update(hashp, hcp, hcp->pgno,
DUP_SIZE(hcp->dup_len), 0, 1);
- F_SET(hcp, H_DELETED);
}
} else
/* Not a duplicate */
- ret = __ham_del_pair(hashp, hcp);
+normal: ret = __ham_del_pair(hashp, hcp, 1);
out: if ((t_ret = __ham_item_done(hashp, hcp, ret == 0)) != 0 && ret == 0)
t_ret = ret;
@@ -975,8 +985,8 @@ int
__ham_expand_table(hashp)
HTAB *hashp;
{
- u_int32_t old_bucket, new_bucket;
- u_int32_t spare_ndx;
+ DB_LSN new_lsn;
+ u_int32_t old_bucket, new_bucket, spare_ndx;
int ret;
ret = 0;
@@ -984,9 +994,30 @@ __ham_expand_table(hashp)
if (ret)
return (ret);
- if (DB_LOGGING(hashp->dbp)) {
- DB_LSN new_lsn;
+ /*
+ * If the split point is about to increase, make sure that we
+ * have enough extra pages. The calculation here is weird.
+ * We'd like to do this after we've upped max_bucket, but it's
+ * too late then because we've logged the meta-data split. What
+ * we'll do between then and now is increment max bucket and then
+ * 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) {
+ /*
+ * 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);
+ }
+ /* 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,
@@ -1003,22 +1034,11 @@ __ham_expand_table(hashp)
old_bucket = (hashp->hdr->max_bucket & hashp->hdr->low_mask);
/*
- * If the split point is increasing (hdr.max_bucket's log base 2
- * increases), max sure that we have enough extra pages, then
- * copy the current contents of the spare split bucket to the
- * next bucket.
+ * 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) {
- /*
- * 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->spares[hashp->hdr->ovfl_point] == 0 &&
- new_bucket >= 8)
- __ham_init_ovflpages(hashp);
-
hashp->hdr->spares[spare_ndx] =
hashp->hdr->spares[hashp->hdr->ovfl_point];
hashp->hdr->ovfl_point = spare_ndx;
@@ -1306,7 +1326,7 @@ __ham_init_dbt(dbt, size, bufp, sizep)
memset(dbt, 0, sizeof(*dbt));
if (*sizep < size) {
if ((*bufp = (void *)(*bufp == NULL ?
- malloc(size) : realloc(*bufp, size))) == NULL) {
+ __db_malloc(size) : __db_realloc(*bufp, size))) == NULL) {
*sizep = 0;
return (ENOMEM);
}
@@ -1352,9 +1372,20 @@ __ham_c_update(hashp, hcp, chg_pgno, len, add, dup)
if (!dup && add)
return;
- page_deleted = chg_pgno != PGNO_INVALID &&
- ((!dup && chg_pgno != hcp->pgno) ||
- (dup && chg_pgno != hcp->dpgno));
+ /*
+ * Determine if a page was deleted. If this is a regular update
+ * (i.e., not dup) then the deleted page's number will be that in
+ * chg_pgno, and the pgno in the cursor will be different. If this
+ * was an onpage-duplicate, then the same conditions apply. If this
+ * was an off-page duplicate, then we need to verify if hcp->dpgno
+ * is the same (no delete) or different (delete) than chg_pgno.
+ */
+ if (!dup || hcp->dpgno == PGNO_INVALID)
+ page_deleted =
+ chg_pgno != PGNO_INVALID && chg_pgno != hcp->pgno;
+ else
+ page_deleted =
+ chg_pgno != PGNO_INVALID && chg_pgno != hcp->dpgno;
hp = hcp->db_cursor->dbp->master->internal;
DB_THREAD_LOCK(hp->dbp);
@@ -1432,7 +1463,7 @@ __ham_hdup(orig, new)
DBC *curs;
int ret;
- if ((hashp = (HTAB *)malloc(sizeof(HTAB))) == NULL)
+ if ((hashp = (HTAB *)__db_malloc(sizeof(HTAB))) == NULL)
return (ENOMEM);
new->internal = hashp;
@@ -1441,7 +1472,7 @@ __ham_hdup(orig, new)
hashp->hlock = 0;
hashp->hdr = NULL;
hashp->hash = ((HTAB *)orig->internal)->hash;
- if ((hashp->split_buf = (PAGE *)malloc(orig->pgsize)) == NULL)
+ if ((hashp->split_buf = (PAGE *)__db_malloc(orig->pgsize)) == NULL)
return (ENOMEM);
hashp->local_errno = 0;
hashp->hash_accesses = 0;
diff --git a/db2/hash/hash.src b/db2/hash/hash.src
index 04a98d3cb3..8cbcee73f7 100644
--- a/db2/hash/hash.src
+++ b/db2/hash/hash.src
@@ -43,7 +43,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)hash.src 10.1 (Sleepycat) 4/12/97
+ * @(#)hash.src 10.2 (Sleepycat) 11/2/97
*/
#include "config.h"
@@ -207,5 +207,27 @@ ARG fileid u_int32_t lu
ARG start_pgno db_pgno_t lu
ARG npages u_int32_t lu
ARG free_pgno db_pgno_t lu
+ARG ovflpoint u_int32_t lu
POINTER metalsn DB_LSN * lu
END
+
+/*
+ * Used when we empty the first page in a bucket and there are pages
+ * after it. The page after it gets copied into the bucket page (since
+ * bucket pages have to be in fixed locations).
+ * pgno: the bucket page
+ * pagelsn: the old LSN on the bucket page
+ * next_pgno: the page number of the next page
+ * nnext_pgno: page after next_pgno (may need to change its prev)
+ * nnextlsn: the LSN of nnext_pgno.
+ */
+BEGIN copypage
+ARG fileid u_int32_t lu
+ARG pgno db_pgno_t lu
+POINTER pagelsn DB_LSN * lu
+ARG next_pgno db_pgno_t lu
+POINTER nextlsn DB_LSN * lu
+ARG nnext_pgno db_pgno_t lu
+POINTER nnextlsn DB_LSN * lu
+DBT page DBT s
+END
diff --git a/db2/hash/hash_auto.c b/db2/hash/hash_auto.c
index 2279de9668..4820eb8611 100644
--- a/db2/hash/hash_auto.c
+++ b/db2/hash/hash_auto.c
@@ -61,7 +61,7 @@ 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 *)malloc(logrec.size)) == NULL)
+ if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM);
bp = logrec.data;
@@ -111,7 +111,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;
- free(logrec.data);
+ __db_free(logrec.data);
return (ret);
}
@@ -172,7 +172,7 @@ __ham_insdel_print(notused1, dbtp, lsnp, notused3, notused4)
}
printf("\n");
printf("\n");
- free(argp);
+ __db_free(argp);
return (0);
}
@@ -187,7 +187,7 @@ __ham_insdel_read(recbuf, argpp)
__ham_insdel_args *argp;
u_int8_t *bp;
- argp = (__ham_insdel_args *)malloc(sizeof(__ham_insdel_args) +
+ argp = (__ham_insdel_args *)__db_malloc(sizeof(__ham_insdel_args) +
sizeof(DB_TXN));
if (argp == NULL)
return (ENOMEM);
@@ -266,7 +266,7 @@ int __ham_newpage_log(logp, txnid, ret_lsnp, flags,
+ sizeof(*pagelsn)
+ sizeof(next_pgno)
+ sizeof(*nextlsn);
- if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+ if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM);
bp = logrec.data;
@@ -308,7 +308,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;
- free(logrec.data);
+ __db_free(logrec.data);
return (ret);
}
@@ -356,7 +356,7 @@ __ham_newpage_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tnextlsn: [%lu][%lu]\n",
(u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
printf("\n");
- free(argp);
+ __db_free(argp);
return (0);
}
@@ -371,7 +371,7 @@ __ham_newpage_read(recbuf, argpp)
__ham_newpage_args *argp;
u_int8_t *bp;
- argp = (__ham_newpage_args *)malloc(sizeof(__ham_newpage_args) +
+ argp = (__ham_newpage_args *)__db_malloc(sizeof(__ham_newpage_args) +
sizeof(DB_TXN));
if (argp == NULL)
return (ENOMEM);
@@ -441,7 +441,7 @@ int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags,
+ sizeof(ovflpoint)
+ sizeof(spares)
+ sizeof(*metalsn);
- if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+ if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM);
bp = logrec.data;
@@ -471,7 +471,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;
- free(logrec.data);
+ __db_free(logrec.data);
return (ret);
}
@@ -514,7 +514,7 @@ __ham_splitmeta_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tmetalsn: [%lu][%lu]\n",
(u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
printf("\n");
- free(argp);
+ __db_free(argp);
return (0);
}
@@ -529,7 +529,7 @@ __ham_splitmeta_read(recbuf, argpp)
__ham_splitmeta_args *argp;
u_int8_t *bp;
- argp = (__ham_splitmeta_args *)malloc(sizeof(__ham_splitmeta_args) +
+ argp = (__ham_splitmeta_args *)__db_malloc(sizeof(__ham_splitmeta_args) +
sizeof(DB_TXN));
if (argp == NULL)
return (ENOMEM);
@@ -594,7 +594,7 @@ 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 *)malloc(logrec.size)) == NULL)
+ if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM);
bp = logrec.data;
@@ -632,7 +632,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;
- free(logrec.data);
+ __db_free(logrec.data);
return (ret);
}
@@ -683,7 +683,7 @@ __ham_splitdata_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tpagelsn: [%lu][%lu]\n",
(u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
printf("\n");
- free(argp);
+ __db_free(argp);
return (0);
}
@@ -698,7 +698,7 @@ __ham_splitdata_read(recbuf, argpp)
__ham_splitdata_args *argp;
u_int8_t *bp;
- argp = (__ham_splitdata_args *)malloc(sizeof(__ham_splitdata_args) +
+ argp = (__ham_splitdata_args *)__db_malloc(sizeof(__ham_splitdata_args) +
sizeof(DB_TXN));
if (argp == NULL)
return (ENOMEM);
@@ -772,7 +772,7 @@ 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 *)malloc(logrec.size)) == NULL)
+ if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM);
bp = logrec.data;
@@ -824,7 +824,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;
- free(logrec.data);
+ __db_free(logrec.data);
return (ret);
}
@@ -886,7 +886,7 @@ __ham_replace_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\n");
printf("\tmakedup: %lu\n", (u_long)argp->makedup);
printf("\n");
- free(argp);
+ __db_free(argp);
return (0);
}
@@ -901,7 +901,7 @@ __ham_replace_read(recbuf, argpp)
__ham_replace_args *argp;
u_int8_t *bp;
- argp = (__ham_replace_args *)malloc(sizeof(__ham_replace_args) +
+ argp = (__ham_replace_args *)__db_malloc(sizeof(__ham_replace_args) +
sizeof(DB_TXN));
if (argp == NULL)
return (ENOMEM);
@@ -985,7 +985,7 @@ int __ham_newpgno_log(logp, txnid, ret_lsnp, flags,
+ sizeof(new_type)
+ sizeof(*pagelsn)
+ sizeof(*metalsn);
- if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+ if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM);
bp = logrec.data;
@@ -1026,7 +1026,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;
- free(logrec.data);
+ __db_free(logrec.data);
return (ret);
}
@@ -1074,7 +1074,7 @@ __ham_newpgno_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tmetalsn: [%lu][%lu]\n",
(u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
printf("\n");
- free(argp);
+ __db_free(argp);
return (0);
}
@@ -1089,7 +1089,7 @@ __ham_newpgno_read(recbuf, argpp)
__ham_newpgno_args *argp;
u_int8_t *bp;
- argp = (__ham_newpgno_args *)malloc(sizeof(__ham_newpgno_args) +
+ argp = (__ham_newpgno_args *)__db_malloc(sizeof(__ham_newpgno_args) +
sizeof(DB_TXN));
if (argp == NULL)
return (ENOMEM);
@@ -1127,10 +1127,10 @@ __ham_newpgno_read(recbuf, argpp)
* PUBLIC: int __ham_ovfl_log
* PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
* PUBLIC: u_int32_t, db_pgno_t, u_int32_t, db_pgno_t,
- * PUBLIC: DB_LSN *));
+ * PUBLIC: u_int32_t, DB_LSN *));
*/
int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
- fileid, start_pgno, npages, free_pgno, metalsn)
+ fileid, start_pgno, npages, free_pgno, ovflpoint, metalsn)
DB_LOG *logp;
DB_TXN *txnid;
DB_LSN *ret_lsnp;
@@ -1139,6 +1139,7 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
db_pgno_t start_pgno;
u_int32_t npages;
db_pgno_t free_pgno;
+ u_int32_t ovflpoint;
DB_LSN * metalsn;
{
DBT logrec;
@@ -1160,8 +1161,9 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
+ sizeof(start_pgno)
+ sizeof(npages)
+ sizeof(free_pgno)
+ + sizeof(ovflpoint)
+ sizeof(*metalsn);
- if ((logrec.data = (void *)malloc(logrec.size)) == NULL)
+ if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
return (ENOMEM);
bp = logrec.data;
@@ -1179,6 +1181,8 @@ int __ham_ovfl_log(logp, txnid, ret_lsnp, flags,
bp += sizeof(npages);
memcpy(bp, &free_pgno, sizeof(free_pgno));
bp += sizeof(free_pgno);
+ memcpy(bp, &ovflpoint, sizeof(ovflpoint));
+ bp += sizeof(ovflpoint);
if (metalsn != NULL)
memcpy(bp, metalsn, sizeof(*metalsn));
else
@@ -1191,7 +1195,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;
- free(logrec.data);
+ __db_free(logrec.data);
return (ret);
}
@@ -1231,10 +1235,11 @@ __ham_ovfl_print(notused1, dbtp, lsnp, notused3, notused4)
printf("\tstart_pgno: %lu\n", (u_long)argp->start_pgno);
printf("\tnpages: %lu\n", (u_long)argp->npages);
printf("\tfree_pgno: %lu\n", (u_long)argp->free_pgno);
+ printf("\tovflpoint: %lu\n", (u_long)argp->ovflpoint);
printf("\tmetalsn: [%lu][%lu]\n",
(u_long)argp->metalsn.file, (u_long)argp->metalsn.offset);
printf("\n");
- free(argp);
+ __db_free(argp);
return (0);
}
@@ -1249,7 +1254,7 @@ __ham_ovfl_read(recbuf, argpp)
__ham_ovfl_args *argp;
u_int8_t *bp;
- argp = (__ham_ovfl_args *)malloc(sizeof(__ham_ovfl_args) +
+ argp = (__ham_ovfl_args *)__db_malloc(sizeof(__ham_ovfl_args) +
sizeof(DB_TXN));
if (argp == NULL)
return (ENOMEM);
@@ -1269,6 +1274,8 @@ __ham_ovfl_read(recbuf, argpp)
bp += sizeof(argp->npages);
memcpy(&argp->free_pgno, bp, sizeof(argp->free_pgno));
bp += sizeof(argp->free_pgno);
+ memcpy(&argp->ovflpoint, bp, sizeof(argp->ovflpoint));
+ bp += sizeof(argp->ovflpoint);
memcpy(&argp->metalsn, bp, sizeof(argp->metalsn));
bp += sizeof(argp->metalsn);
*argpp = argp;
@@ -1276,6 +1283,207 @@ __ham_ovfl_read(recbuf, argpp)
}
/*
+ * PUBLIC: int __ham_copypage_log
+ * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t,
+ * PUBLIC: DB_LSN *, db_pgno_t, DB_LSN *, DBT *));
+ */
+int __ham_copypage_log(logp, txnid, ret_lsnp, flags,
+ fileid, pgno, pagelsn, next_pgno, nextlsn, nnext_pgno,
+ nnextlsn, page)
+ DB_LOG *logp;
+ DB_TXN *txnid;
+ DB_LSN *ret_lsnp;
+ u_int32_t flags;
+ u_int32_t fileid;
+ db_pgno_t pgno;
+ DB_LSN * pagelsn;
+ db_pgno_t next_pgno;
+ DB_LSN * nextlsn;
+ db_pgno_t nnext_pgno;
+ DB_LSN * nnextlsn;
+ DBT *page;
+{
+ DBT logrec;
+ DB_LSN *lsnp, null_lsn;
+ u_int32_t zero;
+ u_int32_t rectype, txn_num;
+ int ret;
+ u_int8_t *bp;
+
+ rectype = DB_ham_copypage;
+ txn_num = txnid == NULL ? 0 : txnid->txnid;
+ if (txnid == NULL) {
+ null_lsn.file = 0;
+ null_lsn.offset = 0;
+ lsnp = &null_lsn;
+ } else
+ lsnp = &txnid->last_lsn;
+ logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+ + sizeof(fileid)
+ + sizeof(pgno)
+ + sizeof(*pagelsn)
+ + sizeof(next_pgno)
+ + sizeof(*nextlsn)
+ + 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);
+
+ bp = logrec.data;
+ memcpy(bp, &rectype, sizeof(rectype));
+ bp += sizeof(rectype);
+ memcpy(bp, &txn_num, sizeof(txn_num));
+ bp += sizeof(txn_num);
+ memcpy(bp, lsnp, sizeof(DB_LSN));
+ bp += sizeof(DB_LSN);
+ memcpy(bp, &fileid, sizeof(fileid));
+ bp += sizeof(fileid);
+ memcpy(bp, &pgno, sizeof(pgno));
+ bp += sizeof(pgno);
+ if (pagelsn != NULL)
+ memcpy(bp, pagelsn, sizeof(*pagelsn));
+ else
+ memset(bp, 0, sizeof(*pagelsn));
+ bp += sizeof(*pagelsn);
+ memcpy(bp, &next_pgno, sizeof(next_pgno));
+ bp += sizeof(next_pgno);
+ if (nextlsn != NULL)
+ memcpy(bp, nextlsn, sizeof(*nextlsn));
+ else
+ memset(bp, 0, sizeof(*nextlsn));
+ bp += sizeof(*nextlsn);
+ memcpy(bp, &nnext_pgno, sizeof(nnext_pgno));
+ bp += sizeof(nnext_pgno);
+ if (nnextlsn != NULL)
+ memcpy(bp, nnextlsn, sizeof(*nnextlsn));
+ else
+ memset(bp, 0, sizeof(*nnextlsn));
+ bp += sizeof(*nnextlsn);
+ if (page == NULL) {
+ zero = 0;
+ memcpy(bp, &zero, sizeof(u_int32_t));
+ bp += sizeof(u_int32_t);
+ } else {
+ memcpy(bp, &page->size, sizeof(page->size));
+ bp += sizeof(page->size);
+ memcpy(bp, page->data, page->size);
+ bp += page->size;
+ }
+#ifdef DEBUG
+ if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
+ fprintf(stderr, "Error in log record length");
+#endif
+ ret = log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
+ if (txnid != NULL)
+ txnid->last_lsn = *ret_lsnp;
+ __db_free(logrec.data);
+ return (ret);
+}
+
+/*
+ * PUBLIC: int __ham_copypage_print
+ * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+
+int
+__ham_copypage_print(notused1, dbtp, lsnp, notused3, notused4)
+ DB_LOG *notused1;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ int notused3;
+ void *notused4;
+{
+ __ham_copypage_args *argp;
+ u_int32_t i;
+ int c, ret;
+
+ i = 0;
+ c = 0;
+ notused1 = NULL;
+ notused3 = 0;
+ notused4 = NULL;
+
+ if ((ret = __ham_copypage_read(dbtp->data, &argp)) != 0)
+ return (ret);
+ printf("[%lu][%lu]ham_copypage: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+ (u_long)lsnp->file,
+ (u_long)lsnp->offset,
+ (u_long)argp->type,
+ (u_long)argp->txnid->txnid,
+ (u_long)argp->prev_lsn.file,
+ (u_long)argp->prev_lsn.offset);
+ printf("\tfileid: %lu\n", (u_long)argp->fileid);
+ printf("\tpgno: %lu\n", (u_long)argp->pgno);
+ printf("\tpagelsn: [%lu][%lu]\n",
+ (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset);
+ printf("\tnext_pgno: %lu\n", (u_long)argp->next_pgno);
+ printf("\tnextlsn: [%lu][%lu]\n",
+ (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset);
+ printf("\tnnext_pgno: %lu\n", (u_long)argp->nnext_pgno);
+ printf("\tnnextlsn: [%lu][%lu]\n",
+ (u_long)argp->nnextlsn.file, (u_long)argp->nnextlsn.offset);
+ printf("\tpage: ");
+ for (i = 0; i < argp->page.size; i++) {
+ c = ((char *)argp->page.data)[i];
+ if (isprint(c) || c == 0xa)
+ putchar(c);
+ else
+ printf("%#x ", c);
+ }
+ printf("\n");
+ printf("\n");
+ __db_free(argp);
+ return (0);
+}
+
+/*
+ * PUBLIC: int __ham_copypage_read __P((void *, __ham_copypage_args **));
+ */
+int
+__ham_copypage_read(recbuf, argpp)
+ void *recbuf;
+ __ham_copypage_args **argpp;
+{
+ __ham_copypage_args *argp;
+ u_int8_t *bp;
+
+ argp = (__ham_copypage_args *)__db_malloc(sizeof(__ham_copypage_args) +
+ sizeof(DB_TXN));
+ if (argp == NULL)
+ return (ENOMEM);
+ argp->txnid = (DB_TXN *)&argp[1];
+ bp = recbuf;
+ memcpy(&argp->type, bp, sizeof(argp->type));
+ bp += sizeof(argp->type);
+ memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid));
+ bp += sizeof(argp->txnid->txnid);
+ memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+ bp += sizeof(DB_LSN);
+ memcpy(&argp->fileid, bp, sizeof(argp->fileid));
+ bp += sizeof(argp->fileid);
+ memcpy(&argp->pgno, bp, sizeof(argp->pgno));
+ bp += sizeof(argp->pgno);
+ memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn));
+ bp += sizeof(argp->pagelsn);
+ memcpy(&argp->next_pgno, bp, sizeof(argp->next_pgno));
+ bp += sizeof(argp->next_pgno);
+ memcpy(&argp->nextlsn, bp, sizeof(argp->nextlsn));
+ bp += sizeof(argp->nextlsn);
+ memcpy(&argp->nnext_pgno, bp, sizeof(argp->nnext_pgno));
+ bp += sizeof(argp->nnext_pgno);
+ memcpy(&argp->nnextlsn, bp, sizeof(argp->nnextlsn));
+ bp += sizeof(argp->nnextlsn);
+ memcpy(&argp->page.size, bp, sizeof(u_int32_t));
+ bp += sizeof(u_int32_t);
+ argp->page.data = bp;
+ bp += argp->page.size;
+ *argpp = argp;
+ return (0);
+}
+
+/*
* PUBLIC: int __ham_init_print __P((DB_ENV *));
*/
int
@@ -1305,6 +1513,9 @@ __ham_init_print(dbenv)
if ((ret = __db_add_recovery(dbenv,
__ham_ovfl_print, DB_ham_ovfl)) != 0)
return (ret);
+ if ((ret = __db_add_recovery(dbenv,
+ __ham_copypage_print, DB_ham_copypage)) != 0)
+ return (ret);
return (0);
}
@@ -1338,6 +1549,9 @@ __ham_init_recover(dbenv)
if ((ret = __db_add_recovery(dbenv,
__ham_ovfl_recover, DB_ham_ovfl)) != 0)
return (ret);
+ if ((ret = __db_add_recovery(dbenv,
+ __ham_copypage_recover, DB_ham_copypage)) != 0)
+ return (ret);
return (0);
}
diff --git a/db2/hash/hash_dup.c b/db2/hash/hash_dup.c
index 71bd1c5eb0..22444e4966 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.7 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash_dup.c 10.8 (Sleepycat) 10/14/97";
#endif /* not lint */
/*
@@ -480,7 +480,7 @@ __ham_check_move(hashp, hcp, add_len)
__ham_copy_item(hashp, hcp->pagep, H_DATAINDEX(hcp->bndx), next_pagep);
/* Now delete the pair from the current page. */
- ret = __ham_del_pair(hashp, hcp);
+ ret = __ham_del_pair(hashp, hcp, 0);
(void)__ham_put_page(hashp->dbp, hcp->pagep, 1);
hcp->pagep = next_pagep;
diff --git a/db2/hash/hash_page.c b/db2/hash/hash_page.c
index 8ba42da1a4..0a12c14546 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.24 (Sleepycat) 9/17/97";
+static const char sccsid[] = "@(#)hash_page.c 10.29 (Sleepycat) 11/2/97";
#endif /* not lint */
/*
@@ -489,19 +489,20 @@ __ham_putitem(p, dbt, type)
/*
- * PUBLIC: int __ham_del_pair __P((HTAB *, HASH_CURSOR *));
+ * 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.
*/
int
-__ham_del_pair(hashp, cursorp)
+__ham_del_pair(hashp, cursorp, reclaim_page)
HTAB *hashp;
HASH_CURSOR *cursorp;
+ int reclaim_page;
{
DBT data_dbt, key_dbt;
DB_ENV *dbenv;
- DB_LSN new_lsn, *n_lsn;
+ DB_LSN new_lsn, *n_lsn, tmp_lsn;
PAGE *p;
db_indx_t ndx;
db_pgno_t chg_pgno, pgno;
@@ -542,6 +543,15 @@ __ham_del_pair(hashp, cursorp)
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);
+ break;
+ case H_DUPLICATE:
+ /*
+ * If we delete a pair that is/was a duplicate, then
+ * we had better clear the flag so that we update the
+ * cursor appropriately.
+ */
+ F_CLR(cursorp, H_ISDUP);
break;
}
@@ -578,13 +588,13 @@ __ham_del_pair(hashp, cursorp)
--hashp->hdr->nelem;
/*
- * Check if the page is empty. There are two cases. If it's
- * empty and it's not the first chain in the bucket (i.e., the
- * bucket page) then we can simply remove it. If it is the first
- * chain in the bucket, then we need to copy the second page into
- * it and remove the second page.
+ * If we need to reclaim the page, then check if the page is empty.
+ * There are two cases. If it's empty and it's not the first page
+ * in the bucket (i.e., the bucket page) then we can simply remove
+ * it. If it is the first chain in the bucket, then we need to copy
+ * the second page into it and remove the second page.
*/
- if (NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID &&
+ if (reclaim_page && NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID &&
NEXT_PGNO(p) != PGNO_INVALID) {
PAGE *n_pagep, *nn_pagep;
db_pgno_t tmp_pgno;
@@ -592,7 +602,6 @@ __ham_del_pair(hashp, cursorp)
/*
* First page in chain is empty and we know that there
* are more pages in the chain.
- * XXX Need to log this.
*/
if ((ret =
__ham_get_page(hashp->dbp, NEXT_PGNO(p), &n_pagep)) != 0)
@@ -605,13 +614,35 @@ __ham_del_pair(hashp, cursorp)
(void) __ham_put_page(hashp->dbp, n_pagep, 0);
return (ret);
}
+ }
+
+ if (DB_LOGGING(hashp->dbp)) {
+ key_dbt.data = n_pagep;
+ key_dbt.size = hashp->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),
+ NEXT_PGNO(n_pagep) == PGNO_INVALID ? NULL :
+ &LSN(nn_pagep), &key_dbt)) != 0)
+ return (ret);
+
+ /* Move lsn onto page. */
+ LSN(p) = new_lsn; /* Structure assignment. */
+ LSN(n_pagep) = new_lsn;
+ if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
+ LSN(nn_pagep) = new_lsn;
+ }
+ if (NEXT_PGNO(n_pagep) != PGNO_INVALID) {
PREV_PGNO(nn_pagep) = PGNO(p);
(void)__ham_put_page(hashp->dbp, nn_pagep, 1);
}
tmp_pgno = PGNO(p);
+ tmp_lsn = LSN(p);
memcpy(p, n_pagep, hashp->hdr->pagesize);
PGNO(p) = tmp_pgno;
+ LSN(p) = tmp_lsn;
PREV_PGNO(p) = PGNO_INVALID;
/*
@@ -623,7 +654,8 @@ __ham_del_pair(hashp, cursorp)
if ((ret = __ham_dirty_page(hashp, p)) != 0 ||
(ret = __ham_del_page(hashp->dbp, n_pagep)) != 0)
return (ret);
- } else if (NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {
+ } else if (reclaim_page &&
+ NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {
PAGE *n_pagep, *p_pagep;
if ((ret =
@@ -690,13 +722,22 @@ __ham_del_pair(hashp, cursorp)
}
__ham_c_update(hashp, cursorp, chg_pgno, 0, 0, 0);
+ /*
+ * Since we just deleted a pair from the master page, anything
+ * in cursorp->dpgno should be cleared.
+ */
+ cursorp->dpgno = PGNO_INVALID;
+
F_CLR(cursorp, H_OK);
return (ret);
}
+
/*
+ * __ham_replpair --
+ * 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));
- * Given the key data indicated by the cursor, replace part/all of it
- * according to the fields in the dbt.
*/
int
__ham_replpair(hashp, hcp, dbt, make_dup)
@@ -768,7 +809,7 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
return (ret);
if (dbt->doff == 0 && dbt->dlen == len) {
- ret = __ham_del_pair(hashp, hcp);
+ ret = __ham_del_pair(hashp, hcp, 0);
if (ret == 0)
ret = __ham_add_el(hashp,
hcp, &tmp, dbt, H_KEYDATA);
@@ -784,15 +825,15 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
goto err;
/* Now we can delete the item. */
- if ((ret = __ham_del_pair(hashp, hcp)) != 0) {
- free(tdata.data);
+ if ((ret = __ham_del_pair(hashp, hcp, 0)) != 0) {
+ __db_free(tdata.data);
goto err;
}
/* Now shift old data around to make room for new. */
if (change > 0) {
- tdata.data = (void *)
- realloc(tdata.data, tdata.size + change);
+ tdata.data = (void *)__db_realloc(tdata.data,
+ tdata.size + change);
memset((u_int8_t *)tdata.data + tdata.size,
0, change);
}
@@ -812,9 +853,9 @@ __ham_replpair(hashp, hcp, dbt, make_dup)
/* Now add the pair. */
ret = __ham_add_el(hashp, hcp, &tmp, &tdata, type);
- free(tdata.data);
+ __db_free(tdata.data);
}
-err: free(tmp.data);
+err: __db_free(tmp.data);
return (ret);
}
@@ -1025,7 +1066,7 @@ __ham_split_page(hashp, obucket, nbucket)
}
}
if (big_buf != NULL)
- free(big_buf);
+ __db_free(big_buf);
/*
* If the original bucket spanned multiple pages, then we've got
@@ -1549,17 +1590,20 @@ __ham_init_ovflpages(hp)
{
DB_LSN new_lsn;
PAGE *p;
- db_pgno_t last_pgno;
- u_int32_t i, numpages;
+ db_pgno_t last_pgno, new_pgno;
+ u_int32_t i, curpages, numpages;
- numpages = hp->hdr->ovfl_point + 1;
+ 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, PGNO_OF(hp, hp->hdr->ovfl_point, 1),
- numpages, last_pgno, &hp->hdr->lsn);
+ hp->dbp->log_fileid, new_pgno,
+ numpages, last_pgno, hp->hdr->ovfl_point, &hp->hdr->lsn);
hp->hdr->lsn = new_lsn;
} else
ZERO_LSN(new_lsn);
@@ -1567,7 +1611,8 @@ __ham_init_ovflpages(hp)
hp->hdr->spares[hp->hdr->ovfl_point] += numpages;
for (i = numpages; i > 0; i--) {
if (__ham_new_page(hp,
- PGNO_OF(hp, hp->hdr->ovfl_point, i), P_INVALID, &p) != 0)
+ PGNO_OF(hp, hp->hdr->ovfl_point, curpages + i),
+ P_INVALID, &p) != 0)
break;
LSN(p) = new_lsn;
NEXT_PGNO(p) = last_pgno;
diff --git a/db2/hash/hash_rec.c b/db2/hash/hash_rec.c
index 1b30be337d..d239e3d0df 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.13 (Sleepycat) 9/15/97";
+static const char sccsid[] = "@(#)hash_rec.c 10.14 (Sleepycat) 11/2/97";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -756,7 +756,6 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
hashp = (HTAB *)file_dbp->internal;
GET_META(file_dbp, hashp);
getmeta = 1;
- file_dbp = NULL;
cmp_n = log_compare(lsnp, &hashp->hdr->lsn);
cmp_p = log_compare(&hashp->hdr->lsn, &argp->metalsn);
@@ -764,12 +763,12 @@ __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
if (cmp_p == 0 && redo) {
/* Redo the allocation. */
hashp->hdr->last_freed = argp->start_pgno;
- hashp->hdr->spares[argp->npages - 1] += argp->npages;
+ hashp->hdr->spares[argp->ovflpoint] += argp->npages;
hashp->hdr->lsn = *lsnp;
F_SET(file_dbp, DB_HS_DIRTYMETA);
} else if (cmp_n == 0 && !redo) {
hashp->hdr->last_freed = argp->free_pgno;
- hashp->hdr->spares[argp->npages - 1] -= argp->npages;
+ hashp->hdr->spares[argp->ovflpoint] -= argp->npages;
hashp->hdr->lsn = argp->metalsn;
F_SET(file_dbp, DB_HS_DIRTYMETA);
}
@@ -808,3 +807,142 @@ out: if (getmeta)
RELEASE_META(file_dbp, hashp);
REC_CLOSE;
}
+
+/*
+ * __ham_copypage_recover --
+ * Recovery function for copypage.
+ *
+ * PUBLIC: int __ham_copypage_recover
+ * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
+ */
+int
+__ham_copypage_recover(logp, dbtp, lsnp, redo, info)
+ DB_LOG *logp;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ int redo;
+ void *info;
+{
+ __ham_copypage_args *argp;
+ DB *file_dbp, *mdbp;
+ DB_MPOOLFILE *mpf;
+ HTAB *hashp;
+ PAGE *pagep;
+ int cmp_n, cmp_p, getmeta, modified, ret;
+
+ getmeta = 0;
+ hashp = NULL; /* XXX: shut the compiler up. */
+ REC_PRINT(__ham_copypage_print);
+ REC_INTRO(__ham_copypage_read);
+
+ hashp = (HTAB *)file_dbp->internal;
+ GET_META(file_dbp, hashp);
+ getmeta = 1;
+ modified = 0;
+
+ /* This is the bucket page. */
+ ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
+ if (ret != 0)
+ if (!redo) {
+ /*
+ * We are undoing and the page doesn't exist. That
+ * is equivalent to having a pagelsn of 0, so we
+ * would not have to undo anything. In this case,
+ * don't bother creating a page.
+ */
+ ret = 0;
+ goto donext;
+ } else if ((ret = memp_fget(mpf, &argp->pgno,
+ DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+
+ cmp_n = log_compare(lsnp, &LSN(pagep));
+ cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
+
+ if (cmp_p == 0 && redo) {
+ /* Need to redo update described. */
+ memcpy(pagep, argp->page.data, argp->page.size);
+ LSN(pagep) = *lsnp;
+ modified = 1;
+ } else if (cmp_n == 0 && !redo) {
+ /* Need to undo update described. */
+ P_INIT(pagep, hashp->hdr->pagesize, argp->pgno, PGNO_INVALID,
+ argp->next_pgno, 0, P_HASH);
+ LSN(pagep) = argp->pagelsn;
+ modified = 1;
+ }
+ if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+
+ /* Now fix up the "next" page. */
+donext: ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep);
+ if (ret != 0)
+ if (!redo) {
+ /*
+ * We are undoing and the page doesn't exist. That
+ * is equivalent to having a pagelsn of 0, so we
+ * would not have to undo anything. In this case,
+ * don't bother creating a page.
+ */
+ ret = 0;
+ goto do_nn;
+ } else if ((ret = memp_fget(mpf, &argp->next_pgno,
+ DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+
+ /* There is nothing to do in the REDO case; only UNDO. */
+
+ cmp_n = log_compare(lsnp, &LSN(pagep));
+ if (cmp_n == 0 && !redo) {
+ /* Need to undo update described. */
+ memcpy(pagep, argp->page.data, argp->page.size);
+ modified = 1;
+ }
+ if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+
+ /* Now fix up the next's next page. */
+do_nn: if (argp->nnext_pgno == PGNO_INVALID) {
+ *lsnp = argp->prev_lsn;
+ goto out;
+ }
+
+ ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep);
+ if (ret != 0)
+ if (!redo) {
+ /*
+ * We are undoing and the page doesn't exist. That
+ * is equivalent to having a pagelsn of 0, so we
+ * would not have to undo anything. In this case,
+ * don't bother creating a page.
+ */
+ ret = 0;
+ *lsnp = argp->prev_lsn;
+ goto out;
+ } else if ((ret = memp_fget(mpf, &argp->nnext_pgno,
+ DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+
+ cmp_n = log_compare(lsnp, &LSN(pagep));
+ cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn);
+
+ if (cmp_p == 0 && redo) {
+ /* Need to redo update described. */
+ PREV_PGNO(pagep) = argp->pgno;
+ LSN(pagep) = *lsnp;
+ modified = 1;
+ } else if (cmp_n == 0 && !redo) {
+ /* Need to undo update described. */
+ PREV_PGNO(pagep) = argp->next_pgno;
+ LSN(pagep) = argp->nnextlsn;
+ modified = 1;
+ }
+ if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+
+ *lsnp = argp->prev_lsn;
+
+out: if (getmeta)
+ RELEASE_META(file_dbp, hashp);
+ REC_CLOSE;
+}