diff options
Diffstat (limited to 'bdb/btree/bt_recno.c')
-rw-r--r-- | bdb/btree/bt_recno.c | 430 |
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; |