diff options
Diffstat (limited to 'db/hash/hash.c')
-rw-r--r-- | db/hash/hash.c | 294 |
1 files changed, 143 insertions, 151 deletions
diff --git a/db/hash/hash.c b/db/hash/hash.c index 71c2f5e06..56ad1a25d 100644 --- a/db/hash/hash.c +++ b/db/hash/hash.c @@ -1,8 +1,8 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1996-2006 + * Oracle Corporation. All rights reserved. */ /* * Copyright (c) 1990, 1993, 1994 @@ -39,20 +39,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hash.c,v 11.200 2004/10/14 18:11:36 bostic Exp $ + * $Id: hash.c,v 12.25 2006/08/24 14:46:04 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - #include "db_int.h" #include "dbinc/db_page.h" -#include "dbinc/db_shash.h" #include "dbinc/btree.h" #include "dbinc/hash.h" #include "dbinc/lock.h" @@ -73,21 +66,8 @@ static int __ham_overwrite __P((DBC *, DBT *, u_int32_t)); /* * __ham_quick_delete -- - * When performing a DB->del operation that does not involve secondary - * indices and is not removing an off-page duplicate tree, we can - * speed things up substantially by removing the entire duplicate - * set, if any is present, in one operation, rather than by conjuring - * up and deleting each of the items individually. (All are stored - * in one big HKEYDATA structure.) We don't bother to distinguish - * on-page duplicate sets from single, non-dup items; they're deleted - * in exactly the same way. - * - * This function is called by __db_delete when the appropriate - * conditions are met, and it performs the delete in the optimized way. - * - * The cursor should be set to the first item in the duplicate - * set, or to the sole key/data pair when the key does not have a - * duplicate set, before the function is called. + * This function is called by __db_del when the appropriate conditions + * are met, and it performs the delete in the optimized way. * * PUBLIC: int __ham_quick_delete __P((DBC *)); */ @@ -97,19 +77,33 @@ __ham_quick_delete(dbc) { int ret, t_ret; - if ((ret = __ham_get_meta(dbc)) != 0) - return (ret); - - /* Assert that we're not using secondary indices. */ - DB_ASSERT(!F_ISSET(dbc->dbp, DB_AM_SECONDARY)); /* - * We should assert that we're not a primary either, but that - * would require grabbing the dbp's mutex, so we don't bother. + * When performing a DB->del operation not involving secondary indices + * and not removing an off-page duplicate tree, we can speed things up + * substantially by removing the entire duplicate set, if any is + * present, in one operation, rather than by conjuring up and deleting + * each of the items individually. (All are stored in one big HKEYDATA + * structure.) We don't bother to distinguish on-page duplicate sets + * from single, non-dup items; they're deleted in exactly the same way. + * + * The cursor should be set to the first item in the duplicate set, or + * to the sole key/data pair when the key does not have a duplicate set, + * before the function is called. + * + * We do not need to call CDB_LOCKING_INIT, __db_del calls here with + * a write cursor. + * + * Assert we're initialized, but not to an off-page duplicate. + * Assert we're not using secondary indices. */ + DB_ASSERT(dbc->dbp->dbenv, IS_INITIALIZED(dbc)); + DB_ASSERT(dbc->dbp->dbenv, dbc->internal->opd == NULL); + DB_ASSERT(dbc->dbp->dbenv, !F_ISSET(dbc->dbp, DB_AM_SECONDARY)); + DB_ASSERT(dbc->dbp->dbenv, + LIST_FIRST(&dbc->dbp->s_secondaries) == NULL); - /* Assert that we're set, but not to an off-page duplicate. */ - DB_ASSERT(IS_INITIALIZED(dbc)); - DB_ASSERT(((HASH_CURSOR *)dbc->internal)->opd == NULL); + if ((ret = __ham_get_meta(dbc)) != 0) + return (ret); if ((ret = __ham_c_writelock(dbc)) == 0) ret = __ham_del_pair(dbc, 1); @@ -146,7 +140,7 @@ __ham_c_init(dbc) } dbc->internal = (DBC_INTERNAL *) new_curs; - dbc->c_close = __db_c_close; + dbc->c_close = __db_c_close_pp; dbc->c_count = __db_c_count_pp; dbc->c_del = __db_c_del_pp; dbc->c_dup = __db_c_dup_pp; @@ -179,11 +173,9 @@ __ham_c_close(dbc, root_pgno, rmroot) HKEYDATA *dp; db_lockmode_t lock_mode; int doroot, gotmeta, ret, t_ret; - u_int32_t dirty; COMPQUIET(rmroot, 0); mpf = dbc->dbp->mpf; - dirty = 0; doroot = gotmeta = ret = 0; hcp = (HASH_CURSOR *) dbc->internal; @@ -195,7 +187,7 @@ __ham_c_close(dbc, root_pgno, rmroot) lock_mode = DB_LOCK_READ; /* To support dirty reads we must reget the write lock. */ - if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && + if (F_ISSET(dbc->dbp, DB_AM_READ_UNCOMMITTED) && F_ISSET((BTREE_CURSOR *) dbc->internal->opd->internal, C_DELETED)) lock_mode = DB_LOCK_WRITE; @@ -215,14 +207,16 @@ __ham_c_close(dbc, root_pgno, rmroot) hcp->opd->c_am_close(hcp->opd, root_pgno, &doroot)) != 0) goto out; if (doroot != 0) { + if ((ret = __memp_dirty(mpf, &hcp->page, + dbc->txn, 0)) != 0) + goto out; if ((ret = __ham_del_pair(dbc, 1)) != 0) goto out; - dirty = DB_MPOOL_DIRTY; } } -out: if (hcp->page != NULL && (t_ret = - __memp_fput(mpf, hcp->page, dirty)) != 0 && ret == 0) +out: if (hcp->page != NULL && + (t_ret = __memp_fput(mpf, hcp->page, 0)) != 0 && ret == 0) ret = t_ret; if (gotmeta != 0 && (t_ret = __ham_release_meta(dbc)) != 0 && ret == 0) ret = t_ret; @@ -338,6 +332,9 @@ __ham_c_del(dbc) if (HPAGE_TYPE(dbp, hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP) goto out; + if ((ret = __memp_dirty(mpf, &hcp->page, dbc->txn, 0)) != 0) + goto out; + if (F_ISSET(hcp, H_ISDUP)) { /* On-page duplicate. */ if (hcp->dup_off == 0 && DUP_SIZE(hcp->dup_len) == LEN_HDATA(dbp, hcp->page, @@ -358,13 +355,11 @@ __ham_c_del(dbc) DUP_SIZE(hcp->dup_len), 0, 1); } } - } else /* Not a duplicate */ ret = __ham_del_pair(dbc, 1); out: if (hcp->page != NULL) { - if ((t_ret = __memp_fput(mpf, - hcp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0) + if ((t_ret = __memp_fput(mpf, hcp->page, 0)) != 0 && ret == 0) ret = t_ret; hcp->page = NULL; } @@ -385,7 +380,6 @@ __ham_c_dup(orig_dbc, new_dbc) DBC *orig_dbc, *new_dbc; { HASH_CURSOR *orig, *new; - int ret; orig = (HASH_CURSOR *)orig_dbc->internal; new = (HASH_CURSOR *)new_dbc->internal; @@ -401,20 +395,6 @@ __ham_c_dup(orig_dbc, new_dbc) if (F_ISSET(orig, H_ISDUP)) F_SET(new, H_ISDUP); - /* - * If the old cursor held a lock and we're not in transactions, get one - * for the new one. The reason that we don't need a new lock if we're - * in a transaction is because we already hold a lock and will continue - * to do so until commit, so there is no point in re-acquiring it. We - * don't know if the old lock was a read or write lock, but it doesn't - * matter. We'll get a read lock. We know that this locker already - * holds a lock of the correct type, so if we need a write lock and - * request it, we know that we'll get it. - */ - if (orig_dbc->txn == NULL && LOCK_ISSET(orig->lock)) - if ((ret = __ham_lock_bucket(new_dbc, DB_LOCK_READ)) != 0) - return (ret); - return (0); } @@ -427,13 +407,15 @@ __ham_c_get(dbc, key, data, flags, pgnop) db_pgno_t *pgnop; { DB *dbp; + DB_ENV *dbenv; DB_MPOOLFILE *mpf; HASH_CURSOR *hcp; db_lockmode_t lock_type; - int get_key, ret, t_ret; + int ret, t_ret; hcp = (HASH_CURSOR *)dbc->internal; dbp = dbc->dbp; + dbenv = dbp->dbenv; mpf = dbp->mpf; /* Clear OR'd in additional bits so we can check for flag equality. */ @@ -447,7 +429,6 @@ __ham_c_get(dbc, key, data, flags, pgnop) hcp->seek_size = 0; ret = 0; - get_key = 1; switch (flags) { case DB_PREV_NODUP: F_SET(hcp, H_NEXT_NODUP); @@ -483,13 +464,11 @@ __ham_c_get(dbc, key, data, flags, pgnop) case DB_GET_BOTH: case DB_GET_BOTH_RANGE: ret = __ham_lookup(dbc, key, 0, lock_type, pgnop); - get_key = 0; break; case DB_GET_BOTHC: F_SET(hcp, H_DUPONLY); ret = __ham_item_next(dbc, lock_type, pgnop); - get_key = 0; break; case DB_CURRENT: /* cgetchk has already determined that the cursor is set. */ @@ -501,7 +480,7 @@ __ham_c_get(dbc, key, data, flags, pgnop) ret = __ham_item(dbc, lock_type, pgnop); break; default: - ret = __db_unknown_flag(dbp->dbenv, "__ham_c_get", flags); + ret = __db_unknown_flag(dbenv, "__ham_c_get", flags); break; } @@ -517,8 +496,7 @@ __ham_c_get(dbc, key, data, flags, pgnop) ret = __ham_dup_return(dbc, data, flags); break; } else if (!F_ISSET(hcp, H_NOMORE)) { - __db_err(dbp->dbenv, - "H_NOMORE returned to __ham_c_get"); + __db_errx(dbenv, "H_NOMORE returned to __ham_c_get"); ret = EINVAL; break; } @@ -583,13 +561,10 @@ __ham_c_get(dbc, key, data, flags, pgnop) ret = DB_KEYEMPTY; goto err; default: - DB_ASSERT(0); + DB_ASSERT(dbenv, 0); } } - if (get_key == 0) - F_SET(key, DB_DBT_ISSET); - err: if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0) ret = t_ret; @@ -1031,13 +1006,13 @@ __ham_c_put(dbc, key, data, flags, pgnop) case DB_KEYLAST: case DB_KEYFIRST: case DB_NODUPDATA: + case DB_NOOVERWRITE: nbytes = (ISBIG(hcp, key->size) ? HOFFPAGE_PSIZE : HKEYDATA_PSIZE(key->size)) + (ISBIG(hcp, data->size) ? HOFFPAGE_PSIZE : HKEYDATA_PSIZE(data->size)); if ((ret = __ham_lookup(dbc, key, nbytes, DB_LOCK_WRITE, pgnop)) == DB_NOTFOUND) { - ret = 0; if (hcp->seek_found_page != PGNO_INVALID && hcp->seek_found_page != hcp->pgno) { if ((ret = __memp_fput(mpf, hcp->page, 0)) != 0) @@ -1058,18 +1033,26 @@ __ham_c_put(dbc, key, data, flags, pgnop) if ((ret = __ham_init_dbt(dbp->dbenv, &tmp_val, data->size + data->doff, &dbc->my_rdata.data, - &dbc->my_rdata.ulen)) == 0) { - memset(tmp_val.data, 0, data->doff); - memcpy((u_int8_t *)tmp_val.data + - data->doff, data->data, data->size); - myval = &tmp_val; - } + &dbc->my_rdata.ulen)) != 0) + goto err2; + + memset(tmp_val.data, 0, data->doff); + memcpy((u_int8_t *)tmp_val.data + + data->doff, data->data, data->size); + myval = &tmp_val; } else myval = (DBT *)data; - if (ret == 0) - ret = __ham_add_el(dbc, key, myval, H_KEYDATA); + ret = __ham_add_el(dbc, key, myval, H_KEYDATA); goto done; + } else if (flags == DB_NOOVERWRITE && + !F_ISSET(hcp, H_DELETED)) { + if (*pgnop == PGNO_INVALID) + ret = DB_KEYEXIST; + else + ret = __bam_opd_exists(dbc, *pgnop); + if (ret != 0) + goto done; } break; case DB_BEFORE: @@ -1083,6 +1066,8 @@ __ham_c_put(dbc, key, data, flags, pgnop) } if (*pgnop == PGNO_INVALID && ret == 0) { + if ((ret = __memp_dirty(mpf, &hcp->page, dbc->txn, 0)) != 0) + goto done; if (flags == DB_CURRENT || ((flags == DB_KEYFIRST || flags == DB_KEYLAST || flags == DB_NODUPDATA) && @@ -1093,8 +1078,7 @@ __ham_c_put(dbc, key, data, flags, pgnop) } done: if (hcp->page != NULL) { - if ((t_ret = __memp_fput(mpf, - hcp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0) + if ((t_ret = __memp_fput(mpf, hcp->page, 0)) != 0 && ret == 0) ret = t_ret; if (t_ret == 0) hcp->page = NULL; @@ -1103,6 +1087,9 @@ done: if (hcp->page != NULL) { if (ret == 0 && F_ISSET(hcp, H_EXPAND)) { ret = __ham_expand_table(dbc); F_CLR(hcp, H_EXPAND); + /* If we are out of space, ignore the error. */ + if (ret == ENOSPC && dbc->txn == NULL) + ret = 0; } err2: if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0) @@ -1128,20 +1115,20 @@ __ham_expand_table(dbc) HASH_CURSOR *hcp; PAGE *h; db_pgno_t pgno, mpgno; - u_int32_t dirty_meta, logn, newalloc, new_bucket, old_bucket; + u_int32_t logn, newalloc, new_bucket, old_bucket; int got_meta, new_double, ret, t_ret; dbp = dbc->dbp; mpf = dbp->mpf; hcp = (HASH_CURSOR *)dbc->internal; - if ((ret = __ham_dirty_meta(dbc)) != 0) + if ((ret = __ham_dirty_meta(dbc, 0)) != 0) return (ret); LOCK_INIT(metalock); mmeta = (DBMETA *) hcp->hdr; mpgno = mmeta->pgno; h = NULL; - dirty_meta = newalloc = 0; + newalloc = 0; got_meta = 0; /* @@ -1171,8 +1158,8 @@ __ham_expand_table(dbc) if (!new_double || hcp->hdr->spares[logn + 1] != PGNO_INVALID) { /* Page exists; get it so we can get its LSN */ pgno = BUCKET_TO_PAGE(hcp, new_bucket); - if ((ret = - __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0) + if ((ret = __memp_fget(mpf, &pgno, dbc->txn, + DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &h)) != 0) goto err; lsn = h->lsn; } else { @@ -1182,7 +1169,8 @@ __ham_expand_table(dbc) if ((ret = __db_lget(dbc, 0, mpgno, DB_LOCK_WRITE, 0, &metalock)) != 0) goto err; - if ((ret = __memp_fget(mpf, &mpgno, 0, &mmeta)) != 0) + if ((ret = __memp_fget(mpf, &mpgno, dbc->txn, + DB_MPOOL_DIRTY, &mmeta)) != 0) goto err; got_meta = 1; } @@ -1221,15 +1209,16 @@ __ham_expand_table(dbc) * that, we calculate the last pgno. */ - hcp->hdr->spares[logn + 1] = pgno - new_bucket; pgno += hcp->hdr->max_bucket; - if ((ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &h)) != 0) + if ((ret = __memp_fget(mpf, &pgno, dbc->txn, + DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &h)) != 0) goto err; + hcp->hdr->spares[logn + 1] = + (pgno - new_bucket) - hcp->hdr->max_bucket; mmeta->last_pgno = pgno; mmeta->lsn = lsn; - dirty_meta = DB_MPOOL_DIRTY; P_INIT(h, dbp->pgsize, pgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH); @@ -1237,7 +1226,7 @@ __ham_expand_table(dbc) /* Write out whatever page we ended up modifying. */ h->lsn = lsn; - if ((ret = __memp_fput(mpf, h, DB_MPOOL_DIRTY)) != 0) + if ((ret = __memp_fput(mpf, h, 0)) != 0) goto err; h = NULL; @@ -1255,7 +1244,7 @@ __ham_expand_table(dbc) err: if (got_meta) if ((t_ret = - __memp_fput(mpf, mmeta, dirty_meta)) != 0 && ret == 0) + __memp_fput(mpf, mmeta, 0)) != 0 && ret == 0) ret = t_ret; if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0) ret = t_ret; @@ -1331,7 +1320,7 @@ __ham_dup_return(dbc, val, flags) */ /* We should never get here with off-page dups. */ - DB_ASSERT(type != H_OFFDUP); + DB_ASSERT(dbp->dbenv, type != H_OFFDUP); /* Case 1 */ if (type != H_DUPLICATE && flags != DB_GET_BOTH && @@ -1396,7 +1385,7 @@ __ham_dup_return(dbc, val, flags) HOFFPAGE_TLEN(hk), sizeof(u_int32_t)); memcpy(&pgno, HOFFPAGE_PGNO(hk), sizeof(db_pgno_t)); - if ((ret = __db_moff(dbp, val, + if ((ret = __db_moff(dbp, dbc->txn, val, pgno, tlen, dbp->dup_compare, &cmp)) != 0) return (ret); } else { @@ -1418,15 +1407,11 @@ __ham_dup_return(dbc, val, flags) } /* - * If we're doing a bulk get, we don't want to actually return - * the data: __ham_bulk will take care of cracking out the - * duplicates appropriately. - * - * The rest of this function calculates partial offsets and - * handles the actual __db_ret, so just return if - * DB_MULTIPLE(_KEY) is set. + * If we've already got the data for this value, or we're doing a bulk + * get, we don't want to return the data. */ - if (F_ISSET(dbc, DBC_MULTIPLE | DBC_MULTIPLE_KEY)) + if (F_ISSET(dbc, DBC_MULTIPLE | DBC_MULTIPLE_KEY) || + F_ISSET(val, DB_DBT_ISSET)) return (0); /* @@ -1442,27 +1427,31 @@ __ham_dup_return(dbc, val, flags) * duplicate which is itself a partial. */ memcpy(&tmp_val, val, sizeof(*val)); + if (F_ISSET(&tmp_val, DB_DBT_PARTIAL)) { /* * Take the user's length unless it would go * beyond the end of the duplicate. */ - if (tmp_val.doff + hcp->dup_off > hcp->dup_len) + if (tmp_val.doff > hcp->dup_len) tmp_val.dlen = 0; - else if (tmp_val.dlen + tmp_val.doff > - hcp->dup_len) - tmp_val.dlen = - hcp->dup_len - tmp_val.doff; + else if (tmp_val.dlen + tmp_val.doff > hcp->dup_len) + tmp_val.dlen = hcp->dup_len - tmp_val.doff; - /* - * Calculate the new offset. - */ - tmp_val.doff += hcp->dup_off; } else { F_SET(&tmp_val, DB_DBT_PARTIAL); tmp_val.dlen = hcp->dup_len; - tmp_val.doff = hcp->dup_off + sizeof(db_indx_t); + tmp_val.doff = 0; } + + /* + * Set offset to the appropriate place within the + * current duplicate -- need to take into account + * both the dup_off and the current duplicate's + * length. + */ + tmp_val.doff += hcp->dup_off + sizeof(db_indx_t); + myval = &tmp_val; } @@ -1470,8 +1459,8 @@ __ham_dup_return(dbc, val, flags) * Finally, if we had a duplicate, pp, ndx, and myval should be * set appropriately. */ - if ((ret = __db_ret(dbp, pp, ndx, myval, &dbc->rdata->data, - &dbc->rdata->ulen)) != 0) + if ((ret = __db_ret(dbp, dbc->txn, + pp, ndx, myval, &dbc->rdata->data, &dbc->rdata->ulen)) != 0) return (ret); /* @@ -1510,7 +1499,7 @@ __ham_overwrite(dbc, nval, flags) * This is an overwrite of a duplicate. We should never * be off-page at this point. */ - DB_ASSERT(hcp->opd == NULL); + DB_ASSERT(dbenv, hcp->opd == NULL); /* On page dups */ if (F_ISSET(nval, DB_DBT_PARTIAL)) { /* @@ -1647,7 +1636,7 @@ __ham_overwrite(dbc, nval, flags) tmp_val2.size = hcp->dup_len; if (dbp->dup_compare( dbp, nval, &tmp_val2) != 0) { - __db_err(dbenv, + __db_errx(dbenv, "Existing data sorts differently from put data"); return (EINVAL); } @@ -1696,7 +1685,7 @@ __ham_overwrite(dbc, nval, flags) * If the key is not found, the H_OK flag is not set. If the sought * field is non-0, the pagep, bndx, pgno (dpagep, dndx, dpgno) fields * are set indicating where an add might take place. If it is 0, - * non of the cursor pointer field are valid. + * none of the cursor pointer field are valid. */ static int __ham_lookup(dbc, key, sought, mode, pgnop) @@ -1741,7 +1730,7 @@ __ham_lookup(dbc, key, sought, mode, pgnop) if (tlen == key->size) { memcpy(&pgno, HOFFPAGE_PGNO(hk), sizeof(db_pgno_t)); - if ((ret = __db_moff(dbp, + if ((ret = __db_moff(dbp, dbc->txn, key, pgno, tlen, NULL, &match)) != 0) return (ret); if (match == 0) @@ -1856,7 +1845,7 @@ __ham_c_update(dbc, len, add, is_dup) my_txn = IS_SUBTRANSACTION(dbc->txn) ? dbc->txn : NULL; found = 0; - MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); + MUTEX_LOCK(dbenv, dbenv->mtx_dblist); /* * Calculate the order of this deleted record. @@ -1865,13 +1854,12 @@ __ham_c_update(dbc, len, add, is_dup) */ order = 0; if (!add) { - order = 1; - for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); + FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp); + for (order = 1; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; - ldbp = LIST_NEXT(ldbp, dblistlinks)) { - MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); - for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL; - cp = TAILQ_NEXT(cp, links)) { + ldbp = TAILQ_NEXT(ldbp, dblistlinks)) { + MUTEX_LOCK(dbenv, dbp->mutex); + TAILQ_FOREACH(cp, &ldbp->active_queue, links) { if (cp == dbc || cp->dbtype != DB_HASH) continue; lcp = (HASH_CURSOR *)cp->internal; @@ -1879,26 +1867,29 @@ __ham_c_update(dbc, len, add, is_dup) hcp->pgno == lcp->pgno && hcp->indx == lcp->indx && order <= lcp->order && - (!is_dup || hcp->dup_off == lcp->dup_off)) + (!is_dup || hcp->dup_off == lcp->dup_off) && + !MVCC_SKIP_CURADJ(cp, lcp->pgno)) order = lcp->order + 1; } - MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); + MUTEX_UNLOCK(dbenv, dbp->mutex); } hcp->order = order; } - for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); + FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp); + for (; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; - ldbp = LIST_NEXT(ldbp, dblistlinks)) { - MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); - for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL; - cp = TAILQ_NEXT(cp, links)) { + ldbp = TAILQ_NEXT(ldbp, dblistlinks)) { + MUTEX_LOCK(dbenv, dbp->mutex); + TAILQ_FOREACH(cp, &ldbp->active_queue, links) { if (cp == dbc || cp->dbtype != DB_HASH) continue; lcp = (HASH_CURSOR *)cp->internal; - if (lcp->pgno != hcp->pgno || lcp->indx == NDX_INVALID) + if (lcp->pgno != hcp->pgno || + lcp->indx == NDX_INVALID || + MVCC_SKIP_CURADJ(cp, lcp->pgno)) continue; if (my_txn != NULL && cp->txn != my_txn) @@ -1992,9 +1983,9 @@ __ham_c_update(dbc, len, add, is_dup) } } } - MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); + MUTEX_UNLOCK(dbenv, dbp->mutex); } - MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); + MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist); if (found != 0 && DBC_LOGGING(dbc)) { if ((ret = __ham_curadj_log(dbp, my_txn, &lsn, 0, hcp->pgno, @@ -2028,21 +2019,21 @@ __ham_get_clist(dbp, pgno, indx, listp) u_int nalloc, nused; int ret; + *listp = NULL; + dbenv = dbp->dbenv; + nalloc = nused = 0; + /* * Assume that finding anything is the exception, so optimize for * the case where there aren't any. */ - nalloc = nused = 0; - *listp = NULL; - dbenv = dbp->dbenv; - - MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); - for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); + MUTEX_LOCK(dbenv, dbenv->mtx_dblist); + FIND_FIRST_DB_MATCH(dbenv, dbp, ldbp); + for (; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; - ldbp = LIST_NEXT(ldbp, dblistlinks)) { - MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); - for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL; - cp = TAILQ_NEXT(cp, links)) + ldbp = TAILQ_NEXT(ldbp, dblistlinks)) { + MUTEX_LOCK(dbenv, dbp->mutex); + TAILQ_FOREACH(cp, &ldbp->active_queue, links) /* * We match if cp->pgno matches the specified * pgno, and if either the cp->indx matches @@ -2050,7 +2041,8 @@ __ham_get_clist(dbp, pgno, indx, listp) */ if (cp->internal->pgno == pgno && (indx == NDX_INVALID || - cp->internal->indx == indx)) { + cp->internal->indx == indx) && + !MVCC_SKIP_CURADJ(cp, pgno)) { if (nused >= nalloc) { nalloc += 10; if ((ret = __os_realloc(dbp->dbenv, @@ -2061,9 +2053,9 @@ __ham_get_clist(dbp, pgno, indx, listp) (*listp)[nused++] = cp; } - MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp); + MUTEX_UNLOCK(dbp->dbenv, dbp->mutex); } - MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); + MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist); if (listp != NULL) { if (nused >= nalloc) { @@ -2076,8 +2068,8 @@ __ham_get_clist(dbp, pgno, indx, listp) } return (0); err: - MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp); - MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); + MUTEX_UNLOCK(dbp->dbenv, dbp->mutex); + MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist); return (ret); } |