diff options
Diffstat (limited to 'db2/btree/bt_put.c')
-rw-r--r-- | db2/btree/bt_put.c | 571 |
1 files changed, 121 insertions, 450 deletions
diff --git a/db2/btree/bt_put.c b/db2/btree/bt_put.c index a93faac98c..0d7a69889a 100644 --- a/db2/btree/bt_put.c +++ b/db2/btree/bt_put.c @@ -47,7 +47,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)bt_put.c 10.45 (Sleepycat) 5/25/98"; +static const char sccsid[] = "@(#)bt_put.c 10.54 (Sleepycat) 12/6/98"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -61,372 +61,23 @@ static const char sccsid[] = "@(#)bt_put.c 10.45 (Sleepycat) 5/25/98"; #include "db_page.h" #include "btree.h" -static int __bam_fixed __P((BTREE *, DBT *)); -static int __bam_isdeleted __P((DB *, PAGE *, u_int32_t, int *)); -static int __bam_lookup __P((DB *, DBT *, int *)); -static int __bam_ndup __P((DB *, PAGE *, u_int32_t)); -static int __bam_ovput __P((DB *, PAGE *, u_int32_t, DBT *)); -static int __bam_partial __P((DB *, DBT *, PAGE *, u_int32_t, u_int32_t)); +static int __bam_fixed __P((DBC *, DBT *)); +static int __bam_ndup __P((DBC *, PAGE *, u_int32_t)); +static int __bam_ovput __P((DBC *, PAGE *, u_int32_t, DBT *)); +static int __bam_partial __P((DBC *, + DBT *, PAGE *, u_int32_t, u_int32_t, u_int32_t)); static u_int32_t __bam_partsize __P((DBT *, PAGE *, u_int32_t)); /* - * __bam_put -- - * Add a new key/data pair or replace an existing pair (btree). - * - * PUBLIC: int __bam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); - */ -int -__bam_put(argdbp, txn, key, data, flags) - DB *argdbp; - DB_TXN *txn; - DBT *key, *data; - u_int32_t flags; -{ - BTREE *t; - CURSOR c; - DB *dbp; - PAGE *h; - db_indx_t indx; - u_int32_t iitem_flags, insert_flags; - int exact, isdeleted, newkey, ret, stack; - - DEBUG_LWRITE(argdbp, txn, "bam_put", key, data, flags); - - /* Check flags. */ - if ((ret = __db_putchk(argdbp, key, data, flags, - F_ISSET(argdbp, DB_AM_RDONLY), F_ISSET(argdbp, DB_AM_DUP))) != 0) - return (ret); - - GETHANDLE(argdbp, txn, &dbp, ret); - t = dbp->internal; - -retry: /* - * Find the location at which to insert. The call to __bam_lookup - * leaves the returned page pinned. - */ - if ((ret = __bam_lookup(dbp, key, &exact)) != 0) { - PUTHANDLE(dbp); - return (ret); - } - h = t->bt_csp->page; - indx = t->bt_csp->indx; - stack = 1; - - /* - * If DB_NOOVERWRITE is set and there's an identical key in the tree, - * return an error unless the data item has already been marked for - * deletion, or, all the remaining data items have already been marked - * for deletion in the case of duplicates. If all the data items have - * been marked for deletion, we do a replace, otherwise, it has to be - * a set of duplicates, and we simply append a new one to the set. - */ - isdeleted = 0; - if (exact) { - if ((ret = __bam_isdeleted(dbp, h, indx, &isdeleted)) != 0) - goto err; - if (isdeleted) - __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP); - else - if (flags == DB_NOOVERWRITE) { - ret = DB_KEYEXIST; - goto err; - } - } - - /* - * If we're inserting into the first or last page of the tree, - * remember where we did it so we can do fast lookup next time. - * - * XXX - * Does reverse order still work (did it ever!?!?) - */ - t->bt_lpgno = - h->next_pgno == PGNO_INVALID || h->prev_pgno == PGNO_INVALID ? - h->pgno : PGNO_INVALID; - - /* - * Select the arguments for __bam_iitem() and do the insert. If the - * key is an exact match, we're either adding a new duplicate at the - * end of the duplicate set, or we're replacing the data item with a - * new data item. If the key isn't an exact match, we're inserting - * a new key/data pair, before the search location. - */ - newkey = dbp->type == DB_BTREE && !exact; - if (exact) { - if (!isdeleted && F_ISSET(dbp, DB_AM_DUP)) { - /* - * Make sure that we're not looking at a page of - * duplicates -- if so, move to the last entry on - * that page. - */ - c.page = h; - c.pgno = h->pgno; - c.indx = indx; - c.dpgno = PGNO_INVALID; - c.dindx = 0; - if ((ret = - __bam_ovfl_chk(dbp, &c, indx + O_INDX, 1)) != 0) - goto err; - if (c.dpgno != PGNO_INVALID) { - /* - * XXX - * The __bam_ovfl_chk() routine memp_fput() the - * current page and acquired a new one, but did - * not do anything about the lock we're holding. - */ - t->bt_csp->page = h = c.page; - indx = c.dindx; - } - insert_flags = DB_AFTER; - } else - insert_flags = DB_CURRENT; - } else - insert_flags = DB_BEFORE; - - /* - * The pages we're using may be modified by __bam_iitem(), so make - * sure we reset the stack. - */ - iitem_flags = 0; - if (newkey) - iitem_flags |= BI_NEWKEY; - if (isdeleted) - iitem_flags |= BI_DOINCR; - ret = __bam_iitem(dbp, &h, &indx, key, data, insert_flags, iitem_flags); - t->bt_csp->page = h; - t->bt_csp->indx = indx; - - switch (ret) { - case 0: - /* Done. Clean up the cursor. */ - if (isdeleted) - __bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS); - break; - case DB_NEEDSPLIT: - /* - * We have to split the page. Back out the cursor setup, - * discard the stack of pages, and do the split. - */ - if (isdeleted) - __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED); - - (void)__bam_stkrel(dbp); - stack = 0; - - if ((ret = __bam_split(dbp, key)) != 0) - break; - - goto retry; - /* NOTREACHED */ - default: - if (isdeleted) - __bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED); - break; - } - -err: if (stack) - (void)__bam_stkrel(dbp); - - PUTHANDLE(dbp); - return (ret); -} - -/* - * __bam_isdeleted -- - * Return if the only remaining data item for the element has been - * deleted. - */ -static int -__bam_isdeleted(dbp, h, indx, isdeletedp) - DB *dbp; - PAGE *h; - u_int32_t indx; - int *isdeletedp; -{ - BKEYDATA *bk; - db_pgno_t pgno; - int ret; - - *isdeletedp = 1; - for (;;) { - bk = GET_BKEYDATA(h, indx + O_INDX); - switch (B_TYPE(bk->type)) { - case B_KEYDATA: - case B_OVERFLOW: - if (!B_DISSET(bk->type)) { - *isdeletedp = 0; - return (0); - } - break; - case B_DUPLICATE: - /* - * If the data item referencing the off-page duplicates - * is flagged as deleted, we're done. Else, we have to - * walk the chain of duplicate pages. - */ - if (B_DISSET(bk->type)) - return (0); - goto dupchk; - default: - return (__db_pgfmt(dbp, h->pgno)); - } - - /* - * If there are no more on-page duplicate items, then every - * data item for this key must have been deleted. - */ - if (indx + P_INDX >= (u_int32_t)NUM_ENT(h)) - return (0); - if (h->inp[indx] != h->inp[indx + P_INDX]) - return (0); - - /* Check the next item. */ - indx += P_INDX; - } - /* NOTREACHED */ - -dupchk: /* Check a chain of duplicate pages. */ - pgno = ((BOVERFLOW *)bk)->pgno; - for (;;) { - /* Acquire the next page in the duplicate chain. */ - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) - return (ret); - - /* Check each item for a delete flag. */ - for (indx = 0; indx < NUM_ENT(h); ++indx) - if (!B_DISSET(GET_BKEYDATA(h, indx)->type)) { - *isdeletedp = 0; - goto done; - } - /* - * If we reach the end of the duplicate pages, then every - * item we reviewed must have been deleted. - */ - if ((pgno = NEXT_PGNO(h)) == PGNO_INVALID) - goto done; - - (void)memp_fput(dbp->mpf, h, 0); - } - /* NOTREACHED */ - -done: (void)memp_fput(dbp->mpf, h, 0); - return (0); -} - -/* - * __bam_lookup -- - * Find the right location in the tree for the key. - */ -static int -__bam_lookup(dbp, key, exactp) - DB *dbp; - DBT *key; - int *exactp; -{ - BTREE *t; - DB_LOCK lock; - EPG e; - PAGE *h; - db_indx_t indx; - int cmp, ret; - - t = dbp->internal; - h = NULL; - - /* - * Record numbers can't be fast-tracked, we have to lock the entire - * tree. - */ - if (F_ISSET(dbp, DB_BT_RECNUM)) - goto slow; - - /* Check to see if we've been seeing sorted input. */ - if (t->bt_lpgno == PGNO_INVALID) - goto slow; - - /* - * Retrieve the page on which we did the last insert. It's okay if - * it doesn't exist, or if it's not the page type we expect, it just - * means that the world changed. - */ - if (__bam_lget(dbp, 0, t->bt_lpgno, DB_LOCK_WRITE, &lock)) - goto miss; - if (__bam_pget(dbp, &h, &t->bt_lpgno, 0)) { - (void)__BT_LPUT(dbp, lock); - goto miss; - } - if (TYPE(h) != P_LBTREE) - goto miss; - if (NUM_ENT(h) == 0) - goto miss; - - /* - * We have to be at the end or beginning of the tree to know that - * we're inserting in a sort order. If that's the case and we're - * in the right order in comparison to the first/last key/data pair, - * we have the right position. - */ - if (h->next_pgno == PGNO_INVALID) { - e.page = h; - e.indx = NUM_ENT(h) - P_INDX; - if ((cmp = __bam_cmp(dbp, key, &e)) >= 0) { - if (cmp > 0) - e.indx += P_INDX; - goto fast; - } - } - if (h->prev_pgno == PGNO_INVALID) { - e.page = h; - e.indx = 0; - if ((cmp = __bam_cmp(dbp, key, &e)) <= 0) { - /* - * We're doing a put, so we want to insert as the last - * of any set of duplicates. - */ - if (cmp == 0) { - for (indx = 0; - indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && - h->inp[indx] == h->inp[indx + P_INDX]; - indx += P_INDX) - ; - e.indx = indx; - } - goto fast; - } - } - goto miss; - - /* Set the exact match flag in case we've already inserted this key. */ -fast: *exactp = cmp == 0; - - /* Enter the entry in the stack. */ - BT_STK_CLR(t); - BT_STK_ENTER(t, e.page, e.indx, lock, ret); - if (ret != 0) - return (ret); - - ++t->lstat.bt_cache_hit; - return (0); - -miss: ++t->lstat.bt_cache_miss; - if (h != NULL) { - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbp, lock); - } - -slow: return (__bam_search(dbp, key, S_INSERT, 1, NULL, exactp)); -} - -/* * __bam_iitem -- * Insert an item into the tree. * - * PUBLIC: int __bam_iitem __P((DB *, + * PUBLIC: int __bam_iitem __P((DBC *, * PUBLIC: PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t)); */ int -__bam_iitem(dbp, hp, indxp, key, data, op, flags) - DB *dbp; +__bam_iitem(dbc, hp, indxp, key, data, op, flags) + DBC *dbc; PAGE **hp; db_indx_t *indxp; DBT *key, *data; @@ -434,6 +85,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) { BTREE *t; BKEYDATA *bk; + DB *dbp; DBT tdbt; PAGE *h; db_indx_t indx, nbytes; @@ -442,6 +94,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) COMPQUIET(bk, NULL); + dbp = dbc->dbp; t = dbp->internal; h = *hp; indx = *indxp; @@ -473,21 +126,21 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) default: return (__db_pgfmt(dbp, h->pgno)); } - if ((ret = __db_ditem(dbp, *hp, *indxp, nbytes)) != 0) + if ((ret = __db_ditem(dbc, *hp, *indxp, nbytes)) != 0) return (ret); } /* Put the new/replacement item onto the page. */ - if ((ret = __db_dput(dbp, data, hp, indxp, __bam_new)) != 0) + if ((ret = __db_dput(dbc, data, hp, indxp, __bam_new)) != 0) return (ret); goto done; } /* Handle fixed-length records: build the real record. */ - if (F_ISSET(dbp, DB_RE_FIXEDLEN) && data->size != t->bt_recno->re_len) { + if (F_ISSET(dbp, DB_RE_FIXEDLEN) && data->size != t->recno->re_len) { tdbt = *data; - if ((ret = __bam_fixed(t, &tdbt)) != 0) + if ((ret = __bam_fixed(dbc, &tdbt)) != 0) return (ret); data = &tdbt; } @@ -554,7 +207,8 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) /* Handle partial puts: build the real record. */ if (F_ISSET(data, DB_DBT_PARTIAL)) { tdbt = *data; - if ((ret = __bam_partial(dbp, &tdbt, h, indx, data_size)) != 0) + if ((ret = __bam_partial(dbc, + &tdbt, h, indx, data_size, flags)) != 0) return (ret); data = &tdbt; } @@ -583,10 +237,10 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) /* Add the key. */ if (bigkey) { - if ((ret = __bam_ovput(dbp, h, indx, key)) != 0) + if ((ret = __bam_ovput(dbc, h, indx, key)) != 0) return (ret); } else - if ((ret = __db_pitem(dbp, h, indx, + if ((ret = __db_pitem(dbc, h, indx, BKEYDATA_SIZE(key->size), NULL, key)) != 0) return (ret); ++indx; @@ -598,7 +252,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) * Adjust the cursor and copy in the key for * the duplicate. */ - if ((ret = __bam_adjindx(dbp, + if ((ret = __bam_adjindx(dbc, h, indx + P_INDX, indx, 1)) != 0) return (ret); @@ -620,7 +274,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) * the duplicate. */ if ((ret = - __bam_adjindx(dbp, h, indx, indx, 1)) != 0) + __bam_adjindx(dbc, h, indx, indx, 1)) != 0) return (ret); ++indx; @@ -639,7 +293,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) * delete and then re-add the item. */ if (bigdata || B_TYPE(bk->type) != B_KEYDATA) { - if ((ret = __bam_ditem(dbp, h, indx)) != 0) + if ((ret = __bam_ditem(dbc, h, indx)) != 0) return (ret); break; } @@ -654,7 +308,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) /* Add the data. */ if (bigdata) { - if ((ret = __bam_ovput(dbp, h, indx, data)) != 0) + if ((ret = __bam_ovput(dbc, h, indx, data)) != 0) return (ret); } else { BKEYDATA __bk; @@ -665,12 +319,12 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) __bk.len = data->size; __hdr.data = &__bk; __hdr.size = SSZA(BKEYDATA, data); - ret = __db_pitem(dbp, h, indx, + ret = __db_pitem(dbc, h, indx, BKEYDATA_SIZE(data->size), &__hdr, data); } else if (replace) - ret = __bam_ritem(dbp, h, indx, data); + ret = __bam_ritem(dbc, h, indx, data); else - ret = __db_pitem(dbp, h, indx, + ret = __db_pitem(dbc, h, indx, BKEYDATA_SIZE(data->size), NULL, data); if (ret != 0) return (ret); @@ -686,7 +340,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) */ if (dupadjust && P_FREESPACE(h) <= dbp->pgsize / 2) { --indx; - if ((ret = __bam_ndup(dbp, h, indx)) != 0) + if ((ret = __bam_ndup(dbc, h, indx)) != 0) return (ret); } @@ -700,14 +354,12 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags) done: if (LF_ISSET(BI_DOINCR) || (op != DB_CURRENT && (F_ISSET(dbp, DB_BT_RECNUM) || dbp->type == DB_RECNO))) - if ((ret = __bam_adjust(dbp, t, 1)) != 0) + if ((ret = __bam_adjust(dbc, 1)) != 0) return (ret); /* If we've modified a recno file, set the flag */ - if (t->bt_recno != NULL) - F_SET(t->bt_recno, RECNO_MODIFIED); - - ++t->lstat.bt_added; + if (t->recno != NULL) + F_SET(t->recno, RECNO_MODIFIED); return (ret); } @@ -770,7 +422,7 @@ __bam_partsize(data, h, indx) memset(&__hdr, 0, sizeof(__hdr)); \ __hdr.data = &bo; \ __hdr.size = BOVERFLOW_SIZE; \ - if ((ret = __db_pitem(dbp, \ + if ((ret = __db_pitem(dbc, \ h, indx, BOVERFLOW_SIZE, &__hdr, NULL)) != 0) \ return (ret); \ } while (0) @@ -780,8 +432,8 @@ __bam_partsize(data, h, indx) * Build an overflow item and put it on the page. */ static int -__bam_ovput(dbp, h, indx, item) - DB *dbp; +__bam_ovput(dbc, h, indx, item) + DBC *dbc; PAGE *h; u_int32_t indx; DBT *item; @@ -789,10 +441,12 @@ __bam_ovput(dbp, h, indx, item) BOVERFLOW bo; int ret; + UMRW(bo.unused1); B_TSET(bo.type, B_OVERFLOW, 0); - bo.tlen = item->size; - if ((ret = __db_poff(dbp, item, &bo.pgno, __bam_new)) != 0) + UMRW(bo.unused2); + if ((ret = __db_poff(dbc, item, &bo.pgno, __bam_new)) != 0) return (ret); + bo.tlen = item->size; OVPUT(h, indx, bo); @@ -803,22 +457,25 @@ __bam_ovput(dbp, h, indx, item) * __bam_ritem -- * Replace an item on a page. * - * PUBLIC: int __bam_ritem __P((DB *, PAGE *, u_int32_t, DBT *)); + * PUBLIC: int __bam_ritem __P((DBC *, PAGE *, u_int32_t, DBT *)); */ int -__bam_ritem(dbp, h, indx, data) - DB *dbp; +__bam_ritem(dbc, h, indx, data) + DBC *dbc; PAGE *h; u_int32_t indx; DBT *data; { BKEYDATA *bk; + DB *dbp; DBT orig, repl; db_indx_t cnt, lo, ln, min, off, prefix, suffix; int32_t nbytes; int ret; u_int8_t *p, *t; + dbp = dbc->dbp; + /* * Replace a single item onto a page. The logic figuring out where * to insert and whether it fits is handled in the caller. All we do @@ -827,7 +484,7 @@ __bam_ritem(dbp, h, indx, data) bk = GET_BKEYDATA(h, indx); /* Log the change. */ - if (DB_LOGGING(dbp)) { + if (DB_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 @@ -851,7 +508,7 @@ __bam_ritem(dbp, 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->lg_info, dbp->txn, + if ((ret = __bam_repl_log(dbp->dbenv->lg_info, dbc->txn, &LSN(h), 0, dbp->log_fileid, 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) @@ -907,18 +564,21 @@ __bam_ritem(dbp, h, indx, data) * If it should, create it. */ static int -__bam_ndup(dbp, h, indx) - DB *dbp; +__bam_ndup(dbc, h, indx) + DBC *dbc; PAGE *h; u_int32_t indx; { BKEYDATA *bk; BOVERFLOW bo; + DB *dbp; DBT hdr; PAGE *cp; db_indx_t cnt, cpindx, first, sz; int ret; + dbp = dbc->dbp; + while (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX]) indx -= P_INDX; for (cnt = 0, sz = 0, first = indx;; ++cnt, indx += P_INDX) { @@ -941,7 +601,7 @@ __bam_ndup(dbp, h, indx) return (0); /* Get a new page. */ - if ((ret = __bam_new(dbp, P_DUPLICATE, &cp)) != 0) + if ((ret = __bam_new(dbc, P_DUPLICATE, &cp)) != 0) return (ret); /* @@ -957,7 +617,7 @@ __bam_ndup(dbp, h, indx) hdr.size = B_TYPE(bk->type) == B_KEYDATA ? BKEYDATA_SIZE(bk->len) : BOVERFLOW_SIZE; if ((ret = - __db_pitem(dbp, cp, cpindx, hdr.size, &hdr, NULL)) != 0) + __db_pitem(dbc, cp, cpindx, hdr.size, &hdr, NULL)) != 0) goto err; /* @@ -970,18 +630,20 @@ __bam_ndup(dbp, h, indx) PGNO(h), first, indx - O_INDX, PGNO(cp), cpindx); /* Delete the data item. */ - if ((ret = __db_ditem(dbp, h, indx, hdr.size)) != 0) + if ((ret = __db_ditem(dbc, h, indx, hdr.size)) != 0) goto err; /* Delete all but the first reference to the key. */ if (--cnt == 0) break; - if ((ret = __bam_adjindx(dbp, h, indx, first, 0)) != 0) + if ((ret = __bam_adjindx(dbc, h, indx, first, 0)) != 0) goto err; } /* Put in a new data item that points to the duplicates page. */ + UMRW(bo.unused1); B_TSET(bo.type, B_DUPLICATE, 0); + UMRW(bo.unused2); bo.pgno = cp->pgno; bo.tlen = 0; @@ -989,7 +651,7 @@ __bam_ndup(dbp, h, indx) return (memp_fput(dbp->mpf, cp, DB_MPOOL_DIRTY)); -err: (void)__bam_free(dbp, cp); +err: (void)__bam_free(dbc, cp); return (ret); } @@ -998,13 +660,16 @@ err: (void)__bam_free(dbp, cp); * Build the real record for a fixed length put. */ static int -__bam_fixed(t, dbt) - BTREE *t; +__bam_fixed(dbc, dbt) + DBC *dbc; DBT *dbt; { + DB *dbp; RECNO *rp; + int ret; - rp = t->bt_recno; + dbp = dbc->dbp; + rp = ((BTREE *)dbp->internal)->recno; /* * If database contains fixed-length records, and the record is long, @@ -1018,29 +683,27 @@ __bam_fixed(t, dbt) * short. Pad it out. We use the record data return memory, it's * only a short-term use. */ - if (t->bt_rdata.ulen < rp->re_len) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - (void *)__db_malloc(rp->re_len) : - (void *)__db_realloc(t->bt_rdata.data, rp->re_len); - if (t->bt_rdata.data == NULL) { - t->bt_rdata.ulen = 0; - return (ENOMEM); + if (dbc->rdata.ulen < rp->re_len) { + if ((ret = __os_realloc(&dbc->rdata.data, rp->re_len)) != 0) { + dbc->rdata.ulen = 0; + dbc->rdata.data = NULL; + return (ret); } - t->bt_rdata.ulen = rp->re_len; + dbc->rdata.ulen = rp->re_len; } - memcpy(t->bt_rdata.data, dbt->data, dbt->size); - memset((u_int8_t *)t->bt_rdata.data + dbt->size, + memcpy(dbc->rdata.data, dbt->data, dbt->size); + memset((u_int8_t *)dbc->rdata.data + dbt->size, rp->re_pad, rp->re_len - dbt->size); /* * Clean up our flags and other information just in case, and * change the caller's DBT to reference our created record. */ - t->bt_rdata.size = rp->re_len; - t->bt_rdata.dlen = 0; - t->bt_rdata.doff = 0; - t->bt_rdata.flags = 0; - *dbt = t->bt_rdata; + dbc->rdata.size = rp->re_len; + dbc->rdata.dlen = 0; + dbc->rdata.doff = 0; + dbc->rdata.flags = 0; + *dbt = dbc->rdata; return (0); } @@ -1050,15 +713,15 @@ __bam_fixed(t, dbt) * Build the real record for a partial put. */ static int -__bam_partial(dbp, dbt, h, indx, nbytes) - DB *dbp; +__bam_partial(dbc, dbt, h, indx, nbytes, flags) + DBC *dbc; DBT *dbt; PAGE *h; - u_int32_t indx, nbytes; + u_int32_t indx, nbytes, flags; { - BTREE *t; BKEYDATA *bk, tbk; BOVERFLOW *bo; + DB *dbp; DBT copy; u_int32_t len, tlen; u_int8_t *p; @@ -1066,18 +729,34 @@ __bam_partial(dbp, dbt, h, indx, nbytes) COMPQUIET(bo, NULL); - t = dbp->internal; + dbp = dbc->dbp; /* We use the record data return memory, it's only a short-term use. */ - if (t->bt_rdata.ulen < nbytes) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - (void *)__db_malloc(nbytes) : - (void *)__db_realloc(t->bt_rdata.data, nbytes); - if (t->bt_rdata.data == NULL) { - t->bt_rdata.ulen = 0; - return (ENOMEM); + if (dbc->rdata.ulen < nbytes) { + if ((ret = __os_realloc(&dbc->rdata.data, nbytes)) != 0) { + dbc->rdata.ulen = 0; + dbc->rdata.data = NULL; + return (ret); } - t->bt_rdata.ulen = nbytes; + dbc->rdata.ulen = nbytes; + } + + /* + * We use nul bytes for any part of the record that isn't specified; + * get it over with. + */ + memset(dbc->rdata.data, 0, nbytes); + + /* + * In the next clauses, we need to do three things: a) set p to point + * to the place at which to copy the user's data, b) set tlen to the + * total length of the record, not including the bytes contributed by + * the user, and c) copy any valid data from an existing record. + */ + if (LF_ISSET(BI_NEWKEY)) { + tlen = dbt->doff; + p = (u_int8_t *)dbc->rdata.data + dbt->doff; + goto ucopy; } /* Find the current record. */ @@ -1089,13 +768,6 @@ __bam_partial(dbp, dbt, h, indx, nbytes) B_TSET(bk->type, B_KEYDATA, 0); bk->len = 0; } - - /* - * We use nul bytes for any part of the record that isn't specified, - * get it over with. - */ - memset(t->bt_rdata.data, 0, nbytes); - if (B_TYPE(bk->type) == B_OVERFLOW) { /* * In the case of an overflow record, we shift things around @@ -1103,12 +775,12 @@ __bam_partial(dbp, dbt, h, indx, nbytes) */ memset(©, 0, sizeof(copy)); if ((ret = __db_goff(dbp, ©, bo->tlen, - bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen)) != 0) + bo->pgno, &dbc->rdata.data, &dbc->rdata.ulen)) != 0) return (ret); /* Skip any leading data from the original record. */ tlen = dbt->doff; - p = (u_int8_t *)t->bt_rdata.data + dbt->doff; + p = (u_int8_t *)dbc->rdata.data + dbt->doff; /* * Copy in any trailing data from the original record. @@ -1127,20 +799,12 @@ __bam_partial(dbp, dbt, h, indx, nbytes) memmove(p + dbt->size, p + dbt->dlen, len); tlen += len; } - - /* Copy in the application provided data. */ - memcpy(p, dbt->data, dbt->size); - tlen += dbt->size; } else { /* Copy in any leading data from the original record. */ - memcpy(t->bt_rdata.data, + memcpy(dbc->rdata.data, bk->data, dbt->doff > bk->len ? bk->len : dbt->doff); tlen = dbt->doff; - p = (u_int8_t *)t->bt_rdata.data + dbt->doff; - - /* Copy in the application provided data. */ - memcpy(p, dbt->data, dbt->size); - tlen += dbt->size; + p = (u_int8_t *)dbc->rdata.data + dbt->doff; /* Copy in any trailing data from the original record. */ len = dbt->doff + dbt->dlen; @@ -1150,11 +814,18 @@ __bam_partial(dbp, dbt, h, indx, nbytes) } } +ucopy: /* + * Copy in the application provided data -- p and tlen must have been + * initialized above. + */ + memcpy(p, dbt->data, dbt->size); + tlen += dbt->size; + /* Set the DBT to reference our new record. */ - t->bt_rdata.size = tlen; - t->bt_rdata.dlen = 0; - t->bt_rdata.doff = 0; - t->bt_rdata.flags = 0; - *dbt = t->bt_rdata; + dbc->rdata.size = tlen; + dbc->rdata.dlen = 0; + dbc->rdata.doff = 0; + dbc->rdata.flags = 0; + *dbt = dbc->rdata; return (0); } |