aboutsummaryrefslogtreecommitdiff
path: root/db2/btree/bt_put.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/btree/bt_put.c')
-rw-r--r--db2/btree/bt_put.c176
1 files changed, 102 insertions, 74 deletions
diff --git a/db2/btree/bt_put.c b/db2/btree/bt_put.c
index 87f3fd9aff..a93faac98c 100644
--- a/db2/btree/bt_put.c
+++ b/db2/btree/bt_put.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
* Sleepycat Software. All rights reserved.
*/
/*
@@ -47,15 +47,13 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)bt_put.c 10.38 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)bt_put.c 10.45 (Sleepycat) 5/25/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#endif
@@ -75,21 +73,22 @@ 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 *, int));
+ * 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;
- int flags;
+ u_int32_t flags;
{
BTREE *t;
CURSOR c;
DB *dbp;
PAGE *h;
db_indx_t indx;
- int exact, iflags, isdeleted, newkey, replace, ret, stack;
+ u_int32_t iitem_flags, insert_flags;
+ int exact, isdeleted, newkey, ret, stack;
DEBUG_LWRITE(argdbp, txn, "bam_put", key, data, flags);
@@ -121,14 +120,13 @@ retry: /*
* 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 = replace = 0;
+ isdeleted = 0;
if (exact) {
if ((ret = __bam_isdeleted(dbp, h, indx, &isdeleted)) != 0)
goto err;
- if (isdeleted) {
- replace = 1;
+ if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SETUP);
- } else
+ else
if (flags == DB_NOOVERWRITE) {
ret = DB_KEYEXIST;
goto err;
@@ -179,42 +177,38 @@ retry: /*
t->bt_csp->page = h = c.page;
indx = c.dindx;
}
- iflags = DB_AFTER;
+ insert_flags = DB_AFTER;
} else
- iflags = DB_CURRENT;
+ insert_flags = DB_CURRENT;
} else
- iflags = DB_BEFORE;
+ insert_flags = DB_BEFORE;
/*
* The pages we're using may be modified by __bam_iitem(), so make
* sure we reset the stack.
*/
- ret = __bam_iitem(dbp,
- &h, &indx, key, data, iflags, newkey ? BI_NEWKEY : 0);
+ 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, and, if we're doing record
- * numbers, adjust the internal page counts.
- */
- if (replace)
+ /* Done. Clean up the cursor. */
+ if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_SUCCESS);
-
- if (!replace && F_ISSET(dbp, DB_BT_RECNUM))
- ret = __bam_adjust(dbp, t, 1);
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 (replace) {
- replace = 0;
+ if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
- }
(void)__bam_stkrel(dbp);
stack = 0;
@@ -225,7 +219,7 @@ retry: /*
goto retry;
/* NOTREACHED */
default:
- if (replace)
+ if (isdeleted)
__bam_ca_replace(dbp, h->pgno, indx, REPLACE_FAILED);
break;
}
@@ -393,7 +387,8 @@ __bam_lookup(dbp, key, exactp)
for (indx = 0;
indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
h->inp[indx] == h->inp[indx + P_INDX];
- indx += P_INDX);
+ indx += P_INDX)
+ ;
e.indx = indx;
}
goto fast;
@@ -427,7 +422,7 @@ slow: return (__bam_search(dbp, key, S_INSERT, 1, NULL, exactp));
* Insert an item into the tree.
*
* PUBLIC: int __bam_iitem __P((DB *,
- * PUBLIC: PAGE **, db_indx_t *, DBT *, DBT *, int, int));
+ * PUBLIC: PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t));
*/
int
__bam_iitem(dbp, hp, indxp, key, data, op, flags)
@@ -435,13 +430,13 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
PAGE **hp;
db_indx_t *indxp;
DBT *key, *data;
- int op, flags;
+ u_int32_t op, flags;
{
BTREE *t;
BKEYDATA *bk;
DBT tdbt;
PAGE *h;
- db_indx_t indx;
+ db_indx_t indx, nbytes;
u_int32_t data_size, have_bytes, need_bytes, needed;
int bigkey, bigdata, dupadjust, replace, ret;
@@ -466,12 +461,27 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
++*indxp;
/* Remove the current item if it's a DB_CURRENT op. */
- if (op == DB_CURRENT && (ret = __db_ditem(dbp, *hp, *indxp,
- BKEYDATA_SIZE(GET_BKEYDATA(*hp, *indxp)->len))) != 0)
- return (ret);
+ if (op == DB_CURRENT) {
+ bk = GET_BKEYDATA(*hp, *indxp);
+ switch (B_TYPE(bk->type)) {
+ case B_KEYDATA:
+ nbytes = BKEYDATA_SIZE(bk->len);
+ break;
+ case B_OVERFLOW:
+ nbytes = BOVERFLOW_SIZE;
+ break;
+ default:
+ return (__db_pgfmt(dbp, h->pgno));
+ }
+ if ((ret = __db_ditem(dbp, *hp, *indxp, nbytes)) != 0)
+ return (ret);
+ }
/* Put the new/replacement item onto the page. */
- return (__db_dput(dbp, data, hp, indxp, __bam_new));
+ if ((ret = __db_dput(dbp, data, hp, indxp, __bam_new)) != 0)
+ return (ret);
+
+ goto done;
}
/* Handle fixed-length records: build the real record. */
@@ -568,7 +578,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
case DB_BEFORE: /* 2. Insert a new key/data pair. */
break;
default:
- abort();
+ return (EINVAL);
}
/* Add the key. */
@@ -638,7 +648,7 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
replace = 1;
break;
default:
- abort();
+ return (EINVAL);
}
}
@@ -666,9 +676,8 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
return (ret);
}
- ++t->lstat.bt_added;
-
- ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
+ if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
+ return (ret);
/*
* If the page is at least 50% full, and we added a duplicate, see if
@@ -681,9 +690,25 @@ __bam_iitem(dbp, hp, indxp, key, data, op, flags)
return (ret);
}
+ /*
+ * If we've changed the record count, update the tree. Record counts
+ * need to be updated in recno databases and in btree databases where
+ * we are supporting records. In both cases, adjust the count if the
+ * operation wasn't performed on the current record or when the caller
+ * overrides and wants the adjustment made regardless.
+ */
+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)
+ 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;
+
return (ret);
}
@@ -1036,8 +1061,8 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
BOVERFLOW *bo;
DBT copy;
u_int32_t len, tlen;
- int ret;
u_int8_t *p;
+ int ret;
COMPQUIET(bo, NULL);
@@ -1065,59 +1090,62 @@ __bam_partial(dbp, dbt, h, indx, nbytes)
bk->len = 0;
}
- /* We use nul bytes for extending the record, get it over with. */
+ /*
+ * 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);
- tlen = 0;
if (B_TYPE(bk->type) == B_OVERFLOW) {
- /* Take up to doff bytes from the record. */
+ /*
+ * In the case of an overflow record, we shift things around
+ * in the current record rather than allocate a separate copy.
+ */
memset(&copy, 0, sizeof(copy));
if ((ret = __db_goff(dbp, &copy, bo->tlen,
bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen)) != 0)
return (ret);
- tlen += dbt->doff;
+
+ /* Skip any leading data from the original record. */
+ tlen = dbt->doff;
+ p = (u_int8_t *)t->bt_rdata.data + dbt->doff;
/*
- * If the original record was larger than the offset:
- * If dlen > size, shift the remaining data down.
- * If dlen < size, shift the remaining data up.
+ * Copy in any trailing data from the original record.
+ *
+ * If the original record was larger than the original offset
+ * plus the bytes being deleted, there is trailing data in the
+ * original record we need to preserve. If we aren't deleting
+ * the same number of bytes as we're inserting, copy it up or
+ * down, into place.
+ *
* Use memmove(), the regions may overlap.
*/
- p = t->bt_rdata.data;
- if (bo->tlen > dbt->doff)
- if (dbt->dlen > dbt->size) {
- tlen += len = bo->tlen -
- dbt->doff - (dbt->dlen - dbt->size);
- memmove(p + dbt->doff + dbt->size,
- p + dbt->doff + dbt->dlen, len);
- } else if (dbt->dlen < dbt->size) {
- tlen += len = bo->tlen -
- dbt->doff - (dbt->size - dbt->dlen);
- memmove(p + dbt->doff + dbt->dlen,
- p + dbt->doff + dbt->size, len);
- } else
- tlen += bo->tlen - dbt->doff;
+ if (bo->tlen > dbt->doff + dbt->dlen) {
+ len = bo->tlen - (dbt->doff + dbt->dlen);
+ if (dbt->dlen != dbt->size)
+ memmove(p + dbt->size, p + dbt->dlen, len);
+ tlen += len;
+ }
- /* Copy in the user's data. */
- memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff,
- dbt->data, dbt->size);
+ /* Copy in the application provided data. */
+ memcpy(p, dbt->data, dbt->size);
tlen += dbt->size;
} else {
- /* Take up to doff bytes from the record. */
+ /* Copy in any leading data from the original record. */
memcpy(t->bt_rdata.data,
bk->data, dbt->doff > bk->len ? bk->len : dbt->doff);
- tlen += dbt->doff;
+ tlen = dbt->doff;
+ p = (u_int8_t *)t->bt_rdata.data + dbt->doff;
- /* Copy in the user's data. */
- memcpy((u_int8_t *)t->bt_rdata.data +
- dbt->doff, dbt->data, dbt->size);
+ /* Copy in the application provided data. */
+ memcpy(p, dbt->data, dbt->size);
tlen += dbt->size;
- /* Copy in any remaining data. */
+ /* Copy in any trailing data from the original record. */
len = dbt->doff + dbt->dlen;
if (bk->len > len) {
- memcpy((u_int8_t *)t->bt_rdata.data + dbt->doff +
- dbt->size, bk->data + len, bk->len - len);
+ memcpy(p + dbt->size, bk->data + len, bk->len - len);
tlen += bk->len - len;
}
}