summaryrefslogtreecommitdiff
path: root/bdb/btree/bt_recno.c
diff options
context:
space:
mode:
Diffstat (limited to 'bdb/btree/bt_recno.c')
-rw-r--r--bdb/btree/bt_recno.c430
1 files changed, 194 insertions, 236 deletions
diff --git a/bdb/btree/bt_recno.c b/bdb/btree/bt_recno.c
index 6ac0cac350d..fab684f3a5f 100644
--- a/bdb/btree/bt_recno.c
+++ b/bdb/btree/bt_recno.c
@@ -1,36 +1,31 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997, 1998, 1999, 2000
+ * Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: bt_recno.c,v 11.65 2001/01/18 14:33:22 bostic Exp $";
+static const char revid[] = "$Id: bt_recno.c,v 11.106 2002/08/16 04:56:30 ubell Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <limits.h>
+#include <stdio.h>
#include <string.h>
#endif
#include "db_int.h"
-#include "db_page.h"
-#include "btree.h"
-#include "db_ext.h"
-#include "db_shash.h"
-#include "lock.h"
-#include "lock_ext.h"
-#include "qam.h"
-#include "txn.h"
+#include "dbinc/db_page.h"
+#include "dbinc/btree.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
static int __ram_add __P((DBC *, db_recno_t *, DBT *, u_int32_t, u_int32_t));
-static int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
-static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
static int __ram_source __P((DB *));
static int __ram_sread __P((DBC *, db_recno_t));
static int __ram_update __P((DBC *, db_recno_t, int));
@@ -90,17 +85,32 @@ static int __ram_update __P((DBC *, db_recno_t, int));
* Do we need to log the current cursor adjustment?
*/
#define CURADJ_LOG(dbc) \
- (DB_LOGGING((dbc)) && (dbc)->txn != NULL && (dbc)->txn->parent != NULL)
+ (DBC_LOGGING((dbc)) && (dbc)->txn != NULL && (dbc)->txn->parent != NULL)
+
+/*
+ * After a search, copy the found page into the cursor, discarding any
+ * currently held lock.
+ */
+#define STACK_TO_CURSOR(cp) { \
+ (cp)->page = (cp)->csp->page; \
+ (cp)->pgno = (cp)->csp->page->pgno; \
+ (cp)->indx = (cp)->csp->indx; \
+ (void)__TLPUT(dbc, (cp)->lock); \
+ (cp)->lock = (cp)->csp->lock; \
+ (cp)->lock_mode = (cp)->csp->lock_mode; \
+}
/*
* __ram_open --
* Recno open function.
*
- * PUBLIC: int __ram_open __P((DB *, const char *, db_pgno_t, u_int32_t));
+ * PUBLIC: int __ram_open __P((DB *,
+ * PUBLIC: DB_TXN *, const char *, db_pgno_t, u_int32_t));
*/
int
-__ram_open(dbp, name, base_pgno, flags)
+__ram_open(dbp, txn, name, base_pgno, flags)
DB *dbp;
+ DB_TXN *txn;
const char *name;
db_pgno_t base_pgno;
u_int32_t flags;
@@ -109,15 +119,14 @@ __ram_open(dbp, name, base_pgno, flags)
DBC *dbc;
int ret, t_ret;
+ COMPQUIET(name, NULL);
t = dbp->bt_internal;
/* Initialize the remaining fields/methods of the DB. */
- dbp->del = __ram_delete;
- dbp->put = __ram_put;
dbp->stat = __bam_stat;
/* Start up the tree. */
- if ((ret = __bam_read_root(dbp, name, base_pgno, flags)) != 0)
+ if ((ret = __bam_read_root(dbp, txn, base_pgno, flags)) != 0)
return (ret);
/*
@@ -132,7 +141,7 @@ __ram_open(dbp, name, base_pgno, flags)
return (ret);
/* If we're snapshotting an underlying source file, do it now. */
- if (F_ISSET(dbp, DB_RE_SNAPSHOT)) {
+ if (F_ISSET(dbp, DB_AM_SNAPSHOT)) {
/* Allocate a cursor. */
if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
return (ret);
@@ -147,104 +156,38 @@ __ram_open(dbp, name, base_pgno, flags)
ret = t_ret;
}
- return (0);
-}
-
-/*
- * __ram_delete --
- * Recno db->del function.
- */
-static int
-__ram_delete(dbp, txn, key, flags)
- DB *dbp;
- DB_TXN *txn;
- DBT *key;
- u_int32_t flags;
-{
- BTREE_CURSOR *cp;
- DBC *dbc;
- db_recno_t recno;
- int ret, t_ret;
-
- PANIC_CHECK(dbp->dbenv);
-
- /* Check for invalid flags. */
- if ((ret = __db_delchk(dbp,
- key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
- return (ret);
-
- /* Acquire a cursor. */
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
-
- DEBUG_LWRITE(dbc, txn, "ram_delete", key, NULL, flags);
-
- /* Check the user's record number and fill in as necessary. */
- if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0)
- goto err;
-
- /* Do the delete. */
- cp = (BTREE_CURSOR *)dbc->internal;
- cp->recno = recno;
-
- ret = __ram_c_del(dbc);
-
- /* Release the cursor. */
-err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
-
return (ret);
}
/*
- * __ram_put --
- * Recno db->put function.
+ * __ram_append --
+ * Recno append function.
+ *
+ * PUBLIC: int __ram_append __P((DBC *, DBT *, DBT *));
*/
-static int
-__ram_put(dbp, txn, key, data, flags)
- DB *dbp;
- DB_TXN *txn;
+int
+__ram_append(dbc, key, data)
+ DBC *dbc;
DBT *key, *data;
- u_int32_t flags;
{
- DBC *dbc;
- db_recno_t recno;
- int ret, t_ret;
-
- PANIC_CHECK(dbp->dbenv);
-
- /* Check for invalid flags. */
- if ((ret = __db_putchk(dbp,
- key, data, flags, F_ISSET(dbp, DB_AM_RDONLY), 0)) != 0)
- return (ret);
-
- /* Allocate a cursor. */
- if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
- return (ret);
+ BTREE_CURSOR *cp;
+ int ret;
- DEBUG_LWRITE(dbc, txn, "ram_put", key, data, flags);
+ cp = (BTREE_CURSOR *)dbc->internal;
/*
- * If we're appending to the tree, make sure we've read in all of
- * the backing source file. Otherwise, check the user's record
- * number and fill in as necessary. If we found the record or it
- * simply didn't exist, add the user's record.
+ * Make sure we've read in all of the backing source file. If
+ * we found the record or it simply didn't exist, add the
+ * user's record.
*/
- if (flags == DB_APPEND)
- ret = __ram_update(dbc, DB_MAX_RECORDS, 0);
- else
- ret = __ram_getno(dbc, key, &recno, 1);
+ ret = __ram_update(dbc, DB_MAX_RECORDS, 0);
if (ret == 0 || ret == DB_NOTFOUND)
- ret = __ram_add(dbc, &recno, data, flags, 0);
-
- /* Discard the cursor. */
- if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
- ret = t_ret;
+ ret = __ram_add(dbc, &cp->recno, data, DB_APPEND, 0);
- /* Return the record number if we're appending to the tree. */
- if (ret == 0 && flags == DB_APPEND)
- ret = __db_retcopy(dbp, key, &recno, sizeof(recno),
- &dbc->rkey.data, &dbc->rkey.ulen);
+ /* Return the record number. */
+ if (ret == 0)
+ ret = __db_retcopy(dbc->dbp->dbenv, key, &cp->recno,
+ sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen);
return (ret);
}
@@ -295,9 +238,9 @@ __ram_c_del(dbc)
goto err;
}
stack = 1;
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
+
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
/*
* If re-numbering records, the on-page deleted flag can only mean
@@ -310,7 +253,7 @@ __ram_c_del(dbc)
* delete records they never created, the latter is an error because
* if the record was "deleted", we could never have found it.
*/
- if (B_DISSET(GET_BKEYDATA(cp->page, cp->indx)->type)) {
+ if (B_DISSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type)) {
ret = DB_KEYEMPTY;
goto err;
}
@@ -321,9 +264,8 @@ __ram_c_del(dbc)
goto err;
__bam_adjust(dbc, -1);
if (__ram_ca(dbc, CA_DELETE) > 0 &&
- CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_DELETE,
- cp->root, cp->recno, cp->order)) != 0)
+ CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp, dbc->txn,
+ &lsn, 0, CA_DELETE, cp->root, cp->recno, cp->order)) != 0)
goto err;
/*
@@ -346,15 +288,15 @@ __ram_c_del(dbc)
* going to be emptied by removing the single reference
* to the emptied page (or one of its parents).
*/
- for (epg = cp->sp; epg <= cp->csp; ++epg)
- if (NUM_ENT(epg->page) <= 1)
+ for (epg = cp->csp; epg >= cp->sp; --epg)
+ if (NUM_ENT(epg->page) > 1)
break;
/*
* We want to delete a single item out of the last page
- * that we're not deleting, back up to that page.
+ * that we're not deleting.
*/
- ret = __bam_dpages(dbc, --epg);
+ ret = __bam_dpages(dbc, epg);
/*
* Regardless of the return from __bam_dpages, it will
@@ -412,6 +354,7 @@ __ram_c_get(dbc, key, data, flags, pgnop)
dbp = dbc->dbp;
cp = (BTREE_CURSOR *)dbc->internal;
+ LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);
retry: switch (flags) {
case DB_CURRENT:
/*
@@ -504,6 +447,7 @@ retry: switch (flags) {
goto err;
/* NOTREACHED */
case DB_GET_BOTH:
+ case DB_GET_BOTH_RANGE:
/*
* If we're searching a set of off-page dups, we start
* a new linear search from the first record. Otherwise,
@@ -531,6 +475,8 @@ retry: switch (flags) {
* read from the backing source file. Do it now for DB_CURRENT (if
* the current record was deleted we may need more records from the
* backing file for a DB_CURRENT operation), DB_FIRST and DB_NEXT.
+ * (We don't have to test for flags == DB_FIRST, because the switch
+ * statement above re-set flags to DB_NEXT in that case.)
*/
if ((flags == DB_NEXT || flags == DB_CURRENT) && ((ret =
__ram_update(dbc, cp->recno, 0)) != 0) && ret != DB_NOTFOUND)
@@ -547,16 +493,8 @@ retry: switch (flags) {
goto err;
}
- /*
- * Copy the page into the cursor, discarding any lock we
- * are currently holding.
- */
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
- (void)__TLPUT(dbc, cp->lock);
- cp->lock = cp->csp->lock;
- cp->lock_mode = cp->csp->lock_mode;
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
/*
* If re-numbering records, the on-page deleted flag means this
@@ -567,21 +505,34 @@ retry: switch (flags) {
* walking through off-page duplicates, and fail if they were
* requested explicitly by the application.
*/
- if (B_DISSET(GET_BKEYDATA(cp->page, cp->indx)->type))
+ if (B_DISSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type))
switch (flags) {
case DB_NEXT:
case DB_PREV:
(void)__bam_stkrel(dbc, STK_CLRDBC);
goto retry;
case DB_GET_BOTH:
- (void)__bam_stkrel(dbc, STK_CLRDBC);
- continue;
+ case DB_GET_BOTH_RANGE:
+ /*
+ * If we're an OPD tree, we don't care about
+ * matching a record number on a DB_GET_BOTH
+ * -- everything belongs to the same tree. A
+ * normal recno should give up and return
+ * DB_NOTFOUND if the matching recno is deleted.
+ */
+ if (F_ISSET(dbc, DBC_OPD)) {
+ (void)__bam_stkrel(dbc, STK_CLRDBC);
+ continue;
+ }
+ ret = DB_NOTFOUND;
+ goto err;
default:
ret = DB_KEYEMPTY;
goto err;
}
- if (flags == DB_GET_BOTH || flags == DB_GET_BOTHC) {
+ if (flags == DB_GET_BOTH ||
+ flags == DB_GET_BOTHC || flags == DB_GET_BOTH_RANGE) {
if ((ret = __bam_cmp(dbp, data,
cp->page, cp->indx, __bam_defcmp, &cmp)) != 0)
return (ret);
@@ -598,10 +549,11 @@ retry: switch (flags) {
/* Return the key if the user didn't give us one. */
if (!F_ISSET(dbc, DBC_OPD)) {
- if (flags != DB_SET && flags != DB_SET_RANGE)
- ret = __db_retcopy(dbp,
- key, &cp->recno, sizeof(cp->recno),
- &dbc->rkey.data, &dbc->rkey.ulen);
+ if (flags != DB_GET_BOTH && flags != DB_GET_BOTH_RANGE &&
+ flags != DB_SET && flags != DB_SET_RANGE)
+ ret = __db_retcopy(dbp->dbenv,
+ key, &cp->recno, sizeof(cp->recno),
+ &dbc->rkey->data, &dbc->rkey->ulen);
F_SET(key, DB_DBT_ISSET);
}
@@ -637,23 +589,43 @@ __ram_c_put(dbc, key, data, flags, pgnop)
cp = (BTREE_CURSOR *)dbc->internal;
/*
- * DB_KEYFIRST and DB_KEYLAST will only be set if we're dealing with
- * an off-page duplicate tree, they can't be specified at user level.
- * Translate them into something else.
+ * DB_KEYFIRST and DB_KEYLAST mean different things if they're
+ * used in an off-page duplicate tree. If we're an off-page
+ * duplicate tree, they really mean "put at the beginning of the
+ * tree" and "put at the end of the tree" respectively, so translate
+ * them to something else.
*/
- switch (flags) {
- case DB_KEYFIRST:
- cp->recno = 1;
- flags = DB_BEFORE;
- break;
- case DB_KEYLAST:
- if ((ret = __ram_add(dbc, &cp->recno, data, DB_APPEND, 0)) != 0)
- return (ret);
- if (CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_ICURRENT,
- cp->root, cp->recno, cp->order)))
- return (ret);
- return (0);
+ if (F_ISSET(dbc, DBC_OPD))
+ switch (flags) {
+ case DB_KEYFIRST:
+ cp->recno = 1;
+ flags = DB_BEFORE;
+ break;
+ case DB_KEYLAST:
+ if ((ret = __ram_add(dbc,
+ &cp->recno, data, DB_APPEND, 0)) != 0)
+ return (ret);
+ if (CURADJ_LOG(dbc) &&
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0,
+ CA_ICURRENT, cp->root, cp->recno, cp->order)))
+ return (ret);
+ return (0);
+ }
+
+ /*
+ * Handle normal DB_KEYFIRST/DB_KEYLAST; for a recno, which has
+ * no duplicates, these are identical and mean "put the given
+ * datum at the given recno".
+ *
+ * Note that the code here used to be in __ram_put; now, we
+ * go through the access-method-common __db_put function, which
+ * handles DB_NOOVERWRITE, so we and __ram_add don't have to.
+ */
+ if (flags == DB_KEYFIRST || flags == DB_KEYLAST) {
+ ret = __ram_getno(dbc, key, &cp->recno, 1);
+ if (ret == 0 || ret == DB_NOTFOUND)
+ ret = __ram_add(dbc, &cp->recno, data, 0, 0);
+ return (ret);
}
/*
@@ -677,9 +649,8 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
*/
DB_ASSERT(exact || CD_ISSET(cp));
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
ret = __bam_iitem(dbc, key, data, iiflags, 0);
t_ret = __bam_stkrel(dbc, STK_CLRDBC);
@@ -688,7 +659,7 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
ret = t_ret;
else if (ret == DB_NEEDSPLIT) {
arg = &cp->recno;
- if ((ret = __bam_split(dbc, arg)) != 0)
+ if ((ret = __bam_split(dbc, arg, NULL)) != 0)
goto err;
goto split;
}
@@ -709,8 +680,7 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
/* Only log if __ram_ca found any relevant cursors. */
if (nc > 0 && CURADJ_LOG(dbc) &&
- (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_IAFTER,
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0, CA_IAFTER,
cp->root, cp->recno, cp->order)) != 0)
goto err;
break;
@@ -720,8 +690,7 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
/* Only log if __ram_ca found any relevant cursors. */
if (nc > 0 && CURADJ_LOG(dbc) &&
- (ret = __bam_rcuradj_log(dbp->dbenv,
- dbc->txn, &lsn, 0, dbp->log_fileid, CA_IBEFORE,
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0, CA_IBEFORE,
cp->root, cp->recno, cp->order)) != 0)
goto err;
break;
@@ -734,8 +703,8 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
* Only log if __ram_ca found any relevant cursors.
*/
if (CD_ISSET(cp) && __ram_ca(dbc, CA_ICURRENT) > 0 &&
- CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(
- dbp->dbenv, dbc->txn, &lsn, 0, dbp->log_fileid,
+ CURADJ_LOG(dbc) &&
+ (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0,
CA_ICURRENT, cp->root, cp->recno, cp->order)) != 0)
goto err;
break;
@@ -743,8 +712,8 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
/* Return the key if we've created a new record. */
if (!F_ISSET(dbc, DBC_OPD) && (flags == DB_AFTER || flags == DB_BEFORE))
- ret = __db_retcopy(dbp, key, &cp->recno,
- sizeof(cp->recno), &dbc->rkey.data, &dbc->rkey.ulen);
+ ret = __db_retcopy(dbp->dbenv, key, &cp->recno,
+ sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen);
/* The cursor was reset, no further delete adjustment is necessary. */
err: CD_CLR(cp);
@@ -940,13 +909,12 @@ __ram_update(dbc, recno, can_create)
int can_create;
{
BTREE *t;
- BTREE_CURSOR *cp;
DB *dbp;
+ DBT *rdata;
db_recno_t nrecs;
int ret;
dbp = dbc->dbp;
- cp = (BTREE_CURSOR *)dbc->internal;
t = dbp->bt_internal;
/*
@@ -976,27 +944,13 @@ __ram_update(dbc, recno, can_create)
if (!can_create || recno <= nrecs + 1)
return (0);
- dbc->rdata.dlen = 0;
- dbc->rdata.doff = 0;
- dbc->rdata.flags = 0;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
- if (dbc->rdata.ulen < t->re_len) {
- if ((ret = __os_realloc(dbp->dbenv,
- t->re_len, NULL, &dbc->rdata.data)) != 0) {
- dbc->rdata.ulen = 0;
- dbc->rdata.data = NULL;
- return (ret);
- }
- dbc->rdata.ulen = t->re_len;
- }
- dbc->rdata.size = t->re_len;
- memset(dbc->rdata.data, t->re_pad, t->re_len);
- } else
- dbc->rdata.size = 0;
+ rdata = &dbc->my_rdata;
+ rdata->flags = 0;
+ rdata->size = 0;
while (recno > ++nrecs)
if ((ret = __ram_add(dbc,
- &nrecs, &dbc->rdata, 0, BI_DELETED)) != 0)
+ &nrecs, rdata, 0, BI_DELETED)) != 0)
return (ret);
return (0);
}
@@ -1017,9 +971,9 @@ __ram_source(dbp)
/* Find the real name, and swap out the one we had before. */
if ((ret = __db_appname(dbp->dbenv,
- DB_APP_DATA, NULL, t->re_source, 0, NULL, &source)) != 0)
+ DB_APP_DATA, t->re_source, 0, NULL, &source)) != 0)
return (ret);
- __os_freestr(t->re_source);
+ __os_free(dbp->dbenv, t->re_source);
t->re_source = source;
/*
@@ -1060,6 +1014,7 @@ __ram_writeback(dbp)
t = dbp->bt_internal;
dbenv = dbp->dbenv;
fp = NULL;
+ pad = NULL;
/* If the file wasn't modified, we're done. */
if (!t->re_modified)
@@ -1119,40 +1074,45 @@ __ram_writeback(dbp)
/*
* We step through the records, writing each one out. Use the record
* number and the dbp->get() function, instead of a cursor, so we find
- * and write out "deleted" or non-existent records.
+ * and write out "deleted" or non-existent records. The DB handle may
+ * be threaded, so allocate memory as we go.
*/
memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
key.size = sizeof(db_recno_t);
key.data = &keyno;
+ memset(&data, 0, sizeof(data));
+ F_SET(&data, DB_DBT_REALLOC);
/*
* We'll need the delimiter if we're doing variable-length records,
* and the pad character if we're doing fixed-length records.
*/
delim = t->re_delim;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
- if ((ret = __os_malloc(dbenv, t->re_len, NULL, &pad)) != 0)
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
+ if ((ret = __os_malloc(dbenv, t->re_len, &pad)) != 0)
goto err;
memset(pad, t->re_pad, t->re_len);
- } else
- COMPQUIET(pad, NULL);
+ }
for (keyno = 1;; ++keyno) {
switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
case 0:
- if (fwrite(data.data, 1, data.size, fp) != data.size)
+ if (data.size != 0 && (u_int32_t)fwrite(
+ data.data, 1, data.size, fp) != data.size)
goto write_err;
break;
case DB_KEYEMPTY:
- if (F_ISSET(dbp, DB_RE_FIXEDLEN) &&
- fwrite(pad, 1, t->re_len, fp) != t->re_len)
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
+ (u_int32_t)fwrite(pad, 1, t->re_len, fp) !=
+ t->re_len)
goto write_err;
break;
case DB_NOTFOUND:
ret = 0;
goto done;
+ default:
+ goto err;
}
- if (!F_ISSET(dbp, DB_RE_FIXEDLEN) &&
+ if (!F_ISSET(dbp, DB_AM_FIXEDLEN) &&
fwrite(&delim, 1, 1, fp) != 1) {
write_err: ret = errno;
__db_err(dbp->dbenv,
@@ -1174,6 +1134,12 @@ done: /* Close the file descriptor. */
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
+ /* Discard memory allocated to hold the data items. */
+ if (data.data != NULL)
+ __os_ufree(dbenv, data.data);
+ if (pad != NULL)
+ __os_free(dbenv, pad);
+
if (ret == 0)
t->re_modified = 0;
@@ -1191,7 +1157,7 @@ __ram_sread(dbc, top)
{
BTREE *t;
DB *dbp;
- DBT data;
+ DBT data, *rdata;
db_recno_t recno;
size_t len;
int ch, ret, was_modified;
@@ -1203,45 +1169,56 @@ __ram_sread(dbc, top)
if ((ret = __bam_nrecs(dbc, &recno)) != 0)
return (ret);
- /* Use the record data return memory, it's only a short-term use. */
- len = F_ISSET(dbp, DB_RE_FIXEDLEN) ? t->re_len : 256;
- if (dbc->rdata.ulen < len) {
+ /*
+ * Use the record key return memory, it's only a short-term use.
+ * The record data return memory is used by __bam_iitem, which
+ * we'll indirectly call, so use the key so as not to collide.
+ */
+ len = F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_len : 256;
+ rdata = &dbc->my_rkey;
+ if (rdata->ulen < len) {
if ((ret = __os_realloc(
- dbp->dbenv, len, NULL, &dbc->rdata.data)) != 0) {
- dbc->rdata.ulen = 0;
- dbc->rdata.data = NULL;
+ dbp->dbenv, len, &rdata->data)) != 0) {
+ rdata->ulen = 0;
+ rdata->data = NULL;
return (ret);
}
- dbc->rdata.ulen = len;
+ rdata->ulen = (u_int32_t)len;
}
memset(&data, 0, sizeof(data));
while (recno < top) {
- data.data = dbc->rdata.data;
+ data.data = rdata->data;
data.size = 0;
- if (F_ISSET(dbp, DB_RE_FIXEDLEN))
+ if (F_ISSET(dbp, DB_AM_FIXEDLEN))
for (len = t->re_len; len > 0; --len) {
- if ((ch = getc(t->re_fp)) == EOF)
- goto eof;
+ if ((ch = getc(t->re_fp)) == EOF) {
+ if (data.size == 0)
+ goto eof;
+ break;
+ }
((u_int8_t *)data.data)[data.size++] = ch;
}
else
for (;;) {
- if ((ch = getc(t->re_fp)) == EOF)
- goto eof;
+ if ((ch = getc(t->re_fp)) == EOF) {
+ if (data.size == 0)
+ goto eof;
+ break;
+ }
if (ch == t->re_delim)
break;
((u_int8_t *)data.data)[data.size++] = ch;
- if (data.size == dbc->rdata.ulen) {
+ if (data.size == rdata->ulen) {
if ((ret = __os_realloc(dbp->dbenv,
- dbc->rdata.ulen *= 2,
- NULL, &dbc->rdata.data)) != 0) {
- dbc->rdata.ulen = 0;
- dbc->rdata.data = NULL;
+ rdata->ulen *= 2,
+ &rdata->data)) != 0) {
+ rdata->ulen = 0;
+ rdata->data = NULL;
return (ret);
} else
- data.data = dbc->rdata.data;
+ data.data = rdata->data;
}
}
@@ -1281,7 +1258,6 @@ __ram_add(dbc, recnop, data, flags, bi_flags)
DBT *data;
u_int32_t flags, bi_flags;
{
- BKEYDATA *bk;
BTREE_CURSOR *cp;
int exact, ret, stack;
@@ -1292,9 +1268,9 @@ retry: /* Find the slot for insertion. */
S_INSERT | (flags == DB_APPEND ? S_APPEND : 0), 1, &exact)) != 0)
return (ret);
stack = 1;
- cp->page = cp->csp->page;
- cp->pgno = cp->csp->page->pgno;
- cp->indx = cp->csp->indx;
+
+ /* Copy the page into the cursor. */
+ STACK_TO_CURSOR(cp);
/*
* The application may modify the data based on the selected record
@@ -1305,24 +1281,6 @@ retry: /* Find the slot for insertion. */
goto err;
/*
- * If re-numbering records, the on-page deleted flag means this record
- * was implicitly created. If not re-numbering records, the on-page
- * deleted flag means this record was implicitly created, or, it was
- * deleted at some time.
- *
- * If DB_NOOVERWRITE is set and the item already exists in the tree,
- * return an error unless the item was either marked for deletion or
- * only implicitly created.
- */
- if (exact) {
- bk = GET_BKEYDATA(cp->page, cp->indx);
- if (!B_DISSET(bk->type) && flags == DB_NOOVERWRITE) {
- ret = DB_KEYEXIST;
- goto err;
- }
- }
-
- /*
* Select the arguments for __bam_iitem() and do the insert. If the
* key is an exact match, or we're replacing the data item with a
* new data item, replace the current item. If the key isn't an exact
@@ -1353,7 +1311,7 @@ retry: /* Find the slot for insertion. */
(void)__bam_stkrel(dbc, STK_CLRDBC);
stack = 0;
- if ((ret = __bam_split(dbc, recnop)) != 0)
+ if ((ret = __bam_split(dbc, recnop, NULL)) != 0)
goto err;
goto retry;