diff options
Diffstat (limited to 'bdb/btree/bt_put.c')
-rw-r--r-- | bdb/btree/bt_put.c | 165 |
1 files changed, 80 insertions, 85 deletions
diff --git a/bdb/btree/bt_put.c b/bdb/btree/bt_put.c index 19a04526d1b..39bd2024e76 100644 --- a/bdb/btree/bt_put.c +++ b/bdb/btree/bt_put.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 1997, 1998, 1999, 2000 + * Copyright (c) 1996-2002 * Sleepycat Software. All rights reserved. */ /* @@ -43,7 +43,7 @@ #include "db_config.h" #ifndef lint -static const char revid[] = "$Id: bt_put.c,v 11.46 2001/01/17 18:48:46 bostic Exp $"; +static const char revid[] = "$Id: bt_put.c,v 11.69 2002/08/06 06:11:12 bostic Exp $"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -53,12 +53,16 @@ static const char revid[] = "$Id: bt_put.c,v 11.46 2001/01/17 18:48:46 bostic Ex #endif #include "db_int.h" -#include "db_page.h" -#include "btree.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +static int __bam_build + __P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t)); static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t)); static int __bam_ovput __P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *)); +static u_int32_t + __bam_partsize __P((DB *, u_int32_t, DBT *, PAGE *, u_int32_t)); /* * __bam_iitem -- @@ -77,6 +81,7 @@ __bam_iitem(dbc, key, data, op, flags) BTREE_CURSOR *cp; DB *dbp; DBT bk_hdr, tdbt; + DB_MPOOLFILE *mpf; PAGE *h; db_indx_t indx; u_int32_t data_size, have_bytes, need_bytes, needed; @@ -85,6 +90,7 @@ __bam_iitem(dbc, key, data, op, flags) COMPQUIET(bk, NULL); dbp = dbc->dbp; + mpf = dbp->mpf; cp = (BTREE_CURSOR *)dbc->internal; t = dbp->bt_internal; h = cp->page; @@ -95,7 +101,7 @@ __bam_iitem(dbc, key, data, op, flags) * Fixed-length records with partial puts: it's an error to specify * anything other simple overwrite. */ - if (F_ISSET(dbp, DB_RE_FIXEDLEN) && + if (F_ISSET(dbp, DB_AM_FIXEDLEN) && F_ISSET(data, DB_DBT_PARTIAL) && data->dlen != data->size) { data_size = data->size; goto len_err; @@ -110,16 +116,18 @@ __bam_iitem(dbc, key, data, op, flags) * the fixed-length record size. */ data_size = F_ISSET(data, DB_DBT_PARTIAL) ? - __bam_partsize(op, data, h, indx) : data->size; + __bam_partsize(dbp, op, data, h, indx) : data->size; padrec = 0; - if (F_ISSET(dbp, DB_RE_FIXEDLEN)) { + if (F_ISSET(dbp, DB_AM_FIXEDLEN)) { if (data_size > t->re_len) { len_err: __db_err(dbp->dbenv, "Length improper for fixed length record %lu", (u_long)data_size); return (EINVAL); } - if (data_size < t->re_len) { + + /* Records that are deleted anyway needn't be padded out. */ + if (!LF_ISSET(BI_DELETED) && data_size < t->re_len) { padrec = 1; data_size = t->re_len; } @@ -146,8 +154,8 @@ len_err: __db_err(dbp->dbenv, */ if (op == DB_CURRENT && dbp->dup_compare != NULL) { if ((ret = __bam_cmp(dbp, data, h, - indx + (TYPE(h) == P_LBTREE ? O_INDX : 0), - dbp->dup_compare, &cmp)) != 0) + indx + (TYPE(h) == P_LBTREE ? O_INDX : 0), + dbp->dup_compare, &cmp)) != 0) return (ret); if (cmp != 0) { __db_err(dbp->dbenv, @@ -190,7 +198,7 @@ len_err: __db_err(dbp->dbenv, */ bigkey = 0; if (op == DB_CURRENT) { - bk = GET_BKEYDATA(h, + bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); if (B_TYPE(bk->type) == B_KEYDATA) have_bytes = BKEYDATA_PSIZE(bk->len); @@ -221,7 +229,7 @@ len_err: __db_err(dbp->dbenv, * The t->bt_maxkey test here may be insufficient -- do we have to * check in the btree split code, so we don't undo it there!?!? */ - if (P_FREESPACE(h) < needed || + if (P_FREESPACE(dbp, h) < needed || (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey)) return (DB_NEEDSPLIT); @@ -328,6 +336,11 @@ len_err: __db_err(dbp->dbenv, /* Add the data. */ if (bigdata) { + /* + * We do not have to handle deleted (BI_DELETED) records + * in this case; the actual records should never be created. + */ + DB_ASSERT(!LF_ISSET(BI_DELETED)); if ((ret = __bam_ovput(dbc, B_OVERFLOW, PGNO_INVALID, h, indx, data)) != 0) return (ret); @@ -347,7 +360,7 @@ len_err: __db_err(dbp->dbenv, if (ret != 0) return (ret); } - if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0) + if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0) return (ret); /* @@ -375,7 +388,7 @@ len_err: __db_err(dbp->dbenv, * up at least 25% of the space on the page. If it does, move it onto * its own page. */ - if (dupadjust && P_FREESPACE(h) <= dbp->pgsize / 2) { + if (dupadjust && P_FREESPACE(dbp, h) <= dbp->pgsize / 2) { if ((ret = __bam_dup_convert(dbc, h, indx - O_INDX)) != 0) return (ret); } @@ -390,11 +403,10 @@ len_err: __db_err(dbp->dbenv, /* * __bam_partsize -- * Figure out how much space a partial data item is in total. - * - * PUBLIC: u_int32_t __bam_partsize __P((u_int32_t, DBT *, PAGE *, u_int32_t)); */ -u_int32_t -__bam_partsize(op, data, h, indx) +static u_int32_t +__bam_partsize(dbp, op, data, h, indx) + DB *dbp; u_int32_t op, indx; DBT *data; PAGE *h; @@ -413,38 +425,18 @@ __bam_partsize(op, data, h, indx) * Otherwise, it's the data provided plus any already existing data * that we're not replacing. */ - bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); + bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); nbytes = B_TYPE(bk->type) == B_OVERFLOW ? ((BOVERFLOW *)bk)->tlen : bk->len; - /* - * There are really two cases here: - * - * Case 1: We are replacing some bytes that do not exist (i.e., they - * are past the end of the record). In this case the number of bytes - * we are replacing is irrelevant and all we care about is how many - * bytes we are going to add from offset. So, the new record length - * is going to be the size of the new bytes (size) plus wherever those - * new bytes begin (doff). - * - * Case 2: All the bytes we are replacing exist. Therefore, the new - * size is the oldsize (nbytes) minus the bytes we are replacing (dlen) - * plus the bytes we are adding (size). - */ - if (nbytes < data->doff + data->dlen) /* Case 1 */ - return (data->doff + data->size); - - return (nbytes + data->size - data->dlen); /* Case 2 */ + return (__db_partsize(nbytes, data)); } /* * __bam_build -- * Build the real record for a partial put, or short fixed-length record. - * - * PUBLIC: int __bam_build __P((DBC *, u_int32_t, - * PUBLIC: DBT *, PAGE *, u_int32_t, u_int32_t)); */ -int +static int __bam_build(dbc, op, dbt, h, indx, nbytes) DBC *dbc; u_int32_t op, indx, nbytes; @@ -454,9 +446,8 @@ __bam_build(dbc, op, dbt, h, indx, nbytes) BKEYDATA *bk, tbk; BOVERFLOW *bo; BTREE *t; - BTREE_CURSOR *cp; DB *dbp; - DBT copy; + DBT copy, *rdata; u_int32_t len, tlen; u_int8_t *p; int ret; @@ -464,26 +455,26 @@ __bam_build(dbc, op, dbt, h, indx, nbytes) COMPQUIET(bo, NULL); dbp = dbc->dbp; - cp = (BTREE_CURSOR *) dbc->internal; t = dbp->bt_internal; /* We use the record data return memory, it's only a short-term use. */ - if (dbc->rdata.ulen < nbytes) { + rdata = &dbc->my_rdata; + if (rdata->ulen < nbytes) { if ((ret = __os_realloc(dbp->dbenv, - nbytes, NULL, &dbc->rdata.data)) != 0) { - dbc->rdata.ulen = 0; - dbc->rdata.data = NULL; + nbytes, &rdata->data)) != 0) { + rdata->ulen = 0; + rdata->data = NULL; return (ret); } - dbc->rdata.ulen = nbytes; + rdata->ulen = nbytes; } /* * We use nul or pad bytes for any part of the record that isn't * specified; get it over with. */ - memset(dbc->rdata.data, - F_ISSET(dbp, DB_RE_FIXEDLEN) ? t->re_pad : 0, nbytes); + memset(rdata->data, + F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_pad : 0, nbytes); /* * In the next clauses, we need to do three things: a) set p to point @@ -495,14 +486,15 @@ __bam_build(dbc, op, dbt, h, indx, nbytes) * the chase. */ if (!F_ISSET(dbt, DB_DBT_PARTIAL) || op != DB_CURRENT) { - p = (u_int8_t *)dbc->rdata.data + dbt->doff; + p = (u_int8_t *)rdata->data + dbt->doff; tlen = dbt->doff; goto user_copy; } /* Find the current record. */ if (indx < NUM_ENT(h)) { - bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); + bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? + O_INDX : 0)); bo = (BOVERFLOW *)bk; } else { bk = &tbk; @@ -516,12 +508,12 @@ __bam_build(dbc, op, dbt, h, indx, nbytes) */ memset(©, 0, sizeof(copy)); if ((ret = __db_goff(dbp, ©, bo->tlen, - bo->pgno, &dbc->rdata.data, &dbc->rdata.ulen)) != 0) + bo->pgno, &rdata->data, &rdata->ulen)) != 0) return (ret); /* Skip any leading data from the original record. */ tlen = dbt->doff; - p = (u_int8_t *)dbc->rdata.data + dbt->doff; + p = (u_int8_t *)rdata->data + dbt->doff; /* * Copy in any trailing data from the original record. @@ -542,10 +534,10 @@ __bam_build(dbc, op, dbt, h, indx, nbytes) } } else { /* Copy in any leading data from the original record. */ - memcpy(dbc->rdata.data, + memcpy(rdata->data, bk->data, dbt->doff > bk->len ? bk->len : dbt->doff); tlen = dbt->doff; - p = (u_int8_t *)dbc->rdata.data + dbt->doff; + p = (u_int8_t *)rdata->data + dbt->doff; /* Copy in any trailing data from the original record. */ len = dbt->doff + dbt->dlen; @@ -564,11 +556,11 @@ user_copy: tlen += dbt->size; /* Set the DBT to reference our new record. */ - dbc->rdata.size = F_ISSET(dbp, DB_RE_FIXEDLEN) ? t->re_len : tlen; - dbc->rdata.dlen = 0; - dbc->rdata.doff = 0; - dbc->rdata.flags = 0; - *dbt = dbc->rdata; + rdata->size = F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_len : tlen; + rdata->dlen = 0; + rdata->doff = 0; + rdata->flags = 0; + *dbt = *rdata; return (0); } @@ -591,6 +583,7 @@ __bam_ritem(dbc, h, indx, data) db_indx_t cnt, lo, ln, min, off, prefix, suffix; int32_t nbytes; int ret; + db_indx_t *inp; u_int8_t *p, *t; dbp = dbc->dbp; @@ -600,10 +593,10 @@ __bam_ritem(dbc, h, indx, data) * to insert and whether it fits is handled in the caller. All we do * here is manage the page shuffling. */ - bk = GET_BKEYDATA(h, indx); + bk = GET_BKEYDATA(dbp, h, indx); /* Log the change. */ - if (DB_LOGGING(dbc)) { + if (DBC_LOGGING(dbc)) { /* * We might as well check to see if the two data items share * a common prefix and suffix -- it can save us a lot of log @@ -627,17 +620,18 @@ __bam_ritem(dbc, h, indx, data) orig.size = bk->len - (prefix + suffix); repl.data = (u_int8_t *)data->data + prefix; repl.size = data->size - (prefix + suffix); - if ((ret = __bam_repl_log(dbp->dbenv, dbc->txn, - &LSN(h), 0, dbp->log_fileid, PGNO(h), &LSN(h), - (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type), + if ((ret = __bam_repl_log(dbp, dbc->txn, &LSN(h), 0, PGNO(h), + &LSN(h), (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type), &orig, &repl, (u_int32_t)prefix, (u_int32_t)suffix)) != 0) return (ret); - } + } else + LSN_NOT_LOGGED(LSN(h)); /* * Set references to the first in-use byte on the page and the * first byte of the item being replaced. */ + inp = P_INP(dbp, h); p = (u_int8_t *)h + HOFFSET(h); t = (u_int8_t *)bk; @@ -648,19 +642,19 @@ __bam_ritem(dbc, h, indx, data) * the regions overlap. */ lo = BKEYDATA_SIZE(bk->len); - ln = BKEYDATA_SIZE(data->size); + ln = (db_indx_t)BKEYDATA_SIZE(data->size); if (lo != ln) { nbytes = lo - ln; /* Signed difference. */ if (p == t) /* First index is fast. */ - h->inp[indx] += nbytes; + inp[indx] += nbytes; else { /* Else, shift the page. */ memmove(p + nbytes, p, t - p); /* Adjust the indices' offsets. */ - off = h->inp[indx]; + off = inp[indx]; for (cnt = 0; cnt < NUM_ENT(h); ++cnt) - if (h->inp[cnt] <= off) - h->inp[cnt] += nbytes; + if (inp[cnt] <= off) + inp[cnt] += nbytes; } /* Clean up the page and adjust the item's reference. */ @@ -688,30 +682,31 @@ __bam_dup_convert(dbc, h, indx) PAGE *h; u_int32_t indx; { - BTREE_CURSOR *cp; BKEYDATA *bk; DB *dbp; DBT hdr; + DB_MPOOLFILE *mpf; PAGE *dp; - db_indx_t cnt, cpindx, dindx, first, sz; + db_indx_t cnt, cpindx, dindx, first, *inp, sz; int ret; dbp = dbc->dbp; - cp = (BTREE_CURSOR *)dbc->internal; + mpf = dbp->mpf; + inp = P_INP(dbp, h); /* * Count the duplicate records and calculate how much room they're * using on the page. */ - while (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX]) + while (indx > 0 && inp[indx] == inp[indx - P_INDX]) indx -= P_INDX; for (cnt = 0, sz = 0, first = indx;; ++cnt, indx += P_INDX) { - if (indx >= NUM_ENT(h) || h->inp[first] != h->inp[indx]) + if (indx >= NUM_ENT(h) || inp[first] != inp[indx]) break; - bk = GET_BKEYDATA(h, indx); + bk = GET_BKEYDATA(dbp, h, indx); sz += B_TYPE(bk->type) == B_KEYDATA ? BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE; - bk = GET_BKEYDATA(h, indx + O_INDX); + bk = GET_BKEYDATA(dbp, h, indx + O_INDX); sz += B_TYPE(bk->type) == B_KEYDATA ? BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE; } @@ -766,7 +761,7 @@ __bam_dup_convert(dbc, h, indx) * deleted entries are discarded (if the deleted entry is * overflow, then free up those pages). */ - bk = GET_BKEYDATA(h, dindx + 1); + bk = GET_BKEYDATA(dbp, h, dindx + 1); hdr.data = bk; hdr.size = B_TYPE(bk->type) == B_KEYDATA ? BKEYDATA_SIZE(bk->len) : BOVERFLOW_SIZE; @@ -778,7 +773,7 @@ __bam_dup_convert(dbc, h, indx) */ if (B_TYPE(bk->type) == B_OVERFLOW && (ret = __db_doff(dbc, - (GET_BOVERFLOW(h, dindx + 1))->pgno)) != 0) + (GET_BOVERFLOW(dbp, h, dindx + 1))->pgno)) != 0) goto err; } else { if ((ret = __db_pitem( @@ -802,7 +797,7 @@ __bam_dup_convert(dbc, h, indx) /* Put in a new data item that points to the duplicates page. */ if ((ret = __bam_ovput(dbc, - B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0) + B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0) goto err; /* Adjust cursors for all the above movments. */ @@ -810,9 +805,9 @@ __bam_dup_convert(dbc, h, indx) PGNO(h), first + P_INDX, first + P_INDX - indx)) != 0) goto err; - return (memp_fput(dbp->mpf, dp, DB_MPOOL_DIRTY)); + return (mpf->put(mpf, dp, DB_MPOOL_DIRTY)); -err: (void)__db_free(dbc, dp); +err: (void)mpf->put(mpf, dp, 0); return (ret); } |