diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2007-07-16 16:48:14 +0300 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2007-07-16 16:48:14 +0300 |
commit | 2cfd3012bfcb5c5c61bbaf662ef084e0ab789d79 (patch) | |
tree | e12ee52087506ac8c7a5eee83b17497d98df2d40 /db/qam | |
parent | b754fe19fd387ca5fe8e7c00ddaa25c898fa192f (diff) | |
download | librpm-tizen-2cfd3012bfcb5c5c61bbaf662ef084e0ab789d79.tar.gz librpm-tizen-2cfd3012bfcb5c5c61bbaf662ef084e0ab789d79.tar.bz2 librpm-tizen-2cfd3012bfcb5c5c61bbaf662ef084e0ab789d79.zip |
Update internal BDB to version 4.5.20
Diffstat (limited to 'db/qam')
-rw-r--r-- | db/qam/qam.c | 529 | ||||
-rw-r--r-- | db/qam/qam.src | 23 | ||||
-rw-r--r-- | db/qam/qam_auto.c | 277 | ||||
-rw-r--r-- | db/qam/qam_autop.c | 67 | ||||
-rw-r--r-- | db/qam/qam_conv.c | 10 | ||||
-rw-r--r-- | db/qam/qam_files.c | 171 | ||||
-rw-r--r-- | db/qam/qam_method.c | 21 | ||||
-rw-r--r-- | db/qam/qam_open.c | 55 | ||||
-rw-r--r-- | db/qam/qam_rec.c | 279 | ||||
-rw-r--r-- | db/qam/qam_stat.c | 28 | ||||
-rw-r--r-- | db/qam/qam_stub.c | 14 | ||||
-rw-r--r-- | db/qam/qam_upgrade.c | 12 | ||||
-rw-r--r-- | db/qam/qam_verify.c | 21 |
13 files changed, 846 insertions, 661 deletions
diff --git a/db/qam/qam.c b/db/qam/qam.c index 3ae2f90d0..08c5e3417 100644 --- a/db/qam/qam.c +++ b/db/qam/qam.c @@ -1,23 +1,16 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam.c,v 11.187 2004/10/18 20:21:13 ubell Exp $ + * $Id: qam.c,v 12.38 2006/09/09 14:28:24 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/lock.h" #include "dbinc/log.h" @@ -33,18 +26,22 @@ static int __qam_c_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); static int __qam_consume __P((DBC *, QMETA *, db_recno_t)); static int __qam_getno __P((DB *, const DBT *, db_recno_t *)); +#define DONT_NEED_LOCKS(dbc) ((dbc)->txn == NULL || \ + F_ISSET(dbc, DBC_READ_COMMITTED | DBC_READ_UNCOMMITTED)) + /* * __qam_position -- * Position a queued access method cursor at a record. This returns * the page locked. *exactp will be set if the record is valid. * PUBLIC: int __qam_position - * PUBLIC: __P((DBC *, db_recno_t *, qam_position_mode, int *)); + * PUBLIC: __P((DBC *, db_recno_t *, db_lockmode_t, u_int32_t, int *)); */ int -__qam_position(dbc, recnop, mode, exactp) +__qam_position(dbc, recnop, lock_mode, get_mode, exactp) DBC *dbc; /* open cursor */ db_recno_t *recnop; /* pointer to recno to find */ - qam_position_mode mode;/* locking: read or write */ + db_lockmode_t lock_mode;/* locking: read or write */ + u_int32_t get_mode; /* flags to __memp_fget */ int *exactp; /* indicate if it was found */ { QUEUE_CURSOR *cp; @@ -59,14 +56,13 @@ __qam_position(dbc, recnop, mode, exactp) /* Fetch the page for this recno. */ pg = QAM_RECNO_PAGE(dbp, *recnop); - if ((ret = __db_lget(dbc, 0, pg, mode == QAM_READ ? - DB_LOCK_READ : DB_LOCK_WRITE, 0, &cp->lock)) != 0) + if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &cp->lock)) != 0) return (ret); cp->page = NULL; *exactp = 0; if ((ret = __qam_fget(dbp, &pg, - mode == QAM_WRITE ? DB_MPOOL_CREATE : 0, &cp->page)) != 0) { - if (mode != QAM_WRITE && + dbc->txn, get_mode, &cp->page)) != 0) { + if (!FLD_ISSET(get_mode, DB_MPOOL_CREATE) && (ret == DB_PAGE_NOTFOUND || ret == ENOENT)) ret = 0; @@ -79,10 +75,16 @@ __qam_position(dbc, recnop, mode, exactp) cp->indx = QAM_RECNO_INDEX(dbp, pg, *recnop); if (PGNO(cp->page) == 0) { - if (F_ISSET(dbp, DB_AM_RDONLY)) { + /* + * We have read an uninitialized page: set the page number if + * we're creating the page. Otherwise, we know that the record + * doesn't exist yet. + */ + if (!FLD_ISSET(get_mode, DB_MPOOL_CREATE)) { *exactp = 0; return (0); } + DB_ASSERT(dbp->dbenv, FLD_ISSET(get_mode, DB_MPOOL_CREATE)); PGNO(cp->page) = pg; TYPE(cp->page) = P_QAMDATA; } @@ -102,7 +104,7 @@ __qam_position(dbc, recnop, mode, exactp) * pagep must be write locked * * PUBLIC: int __qam_pitem - * PUBLIC: __P((DBC *, QPAGE *, u_int32_t, db_recno_t, DBT *)); + * PUBLIC: __P((DBC *, QPAGE *, u_int32_t, db_recno_t, DBT *)); */ int __qam_pitem(dbc, pagep, indx, recno, data) @@ -133,7 +135,7 @@ __qam_pitem(dbc, pagep, indx, recno, data) datap = data; if (F_ISSET(data, DB_DBT_PARTIAL)) { if (data->doff + data->dlen > t->re_len) { - __db_err(dbenv, + __db_errx(dbenv, "%s: data offset plus length larger than record size of %lu", "Record length error", (u_long)t->re_len); return (EINVAL); @@ -175,7 +177,7 @@ __qam_pitem(dbc, pagep, indx, recno, data) if (F_ISSET(qp, QAM_VALID)) memcpy(dest, p, t->re_len); else - memset(dest, t->re_pad, t->re_len); + memset(dest, (int)t->re_pad, t->re_len); dest += data->doff; memcpy(dest, data->data, data->size); @@ -202,7 +204,8 @@ no_partial: F_SET(qp, QAM_VALID | QAM_SET); memcpy(p, datap->data, datap->size); if (!F_ISSET(data, DB_DBT_PARTIAL)) - memset(p + datap->size, t->re_pad, t->re_len - datap->size); + memset(p + datap->size, + (int)t->re_pad, t->re_len - datap->size); err: if (allocated) __os_free(dbenv, datap->data); @@ -222,6 +225,7 @@ __qam_c_put(dbc, key, data, flags, pgnop) db_pgno_t *pgnop; { DB *dbp; + DB_ENV *dbenv; DB_LOCK lock; DB_MPOOLFILE *mpf; QMETA *meta; @@ -229,9 +233,10 @@ __qam_c_put(dbc, key, data, flags, pgnop) db_pgno_t pg; db_recno_t new_cur, new_first; u_int32_t opcode; - int exact, ret, t_ret; + int exact, ret, t_ret, writelock; dbp = dbc->dbp; + dbenv = dbp->dbenv; mpf = dbp->mpf; if (pgnop != NULL) *pgnop = PGNO_INVALID; @@ -241,6 +246,7 @@ __qam_c_put(dbc, key, data, flags, pgnop) switch (flags) { case DB_KEYFIRST: case DB_KEYLAST: + case DB_NOOVERWRITE: if ((ret = __qam_getno(dbp, key, &cp->recno)) != 0) return (ret); /* FALLTHROUGH */ @@ -248,29 +254,34 @@ __qam_c_put(dbc, key, data, flags, pgnop) break; default: /* The interface shouldn't let anything else through. */ - DB_ASSERT(0); - return (__db_ferr(dbp->dbenv, "DBC->put", 0)); + return (__db_ferr(dbenv, "DBC->put", 0)); } /* Write lock the record. */ - if ((ret = __db_lget(dbc, - 0, cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0) + if ((ret = __db_lget(dbc, LCK_COUPLE, + cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &cp->lock)) != 0) return (ret); - if ((ret = __qam_position(dbc, &cp->recno, QAM_WRITE, &exact)) != 0) { + lock = cp->lock; + + if ((ret = __qam_position(dbc, &cp->recno, DB_LOCK_WRITE, + DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &exact)) != 0) { /* We could not get the page, we can release the record lock. */ (void)__LPUT(dbc, lock); return (ret); } - /* Put the item on the page. */ - ret = __qam_pitem(dbc, (QPAGE *)cp->page, cp->indx, cp->recno, data); + if (exact != 0 && flags == DB_NOOVERWRITE) + ret = DB_KEYEXIST; + else + /* Put the item on the page. */ + ret = __qam_pitem(dbc, + (QPAGE *)cp->page, cp->indx, cp->recno, data); /* Doing record locking, release the page lock */ if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0) ret = t_ret; - if ((t_ret = __qam_fput( - dbp, cp->pgno, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0) + if ((t_ret = __qam_fput(dbp, cp->pgno, cp->page, 0)) != 0 && ret == 0) ret = t_ret; cp->page = NULL; cp->lock = lock; @@ -282,12 +293,14 @@ __qam_c_put(dbc, key, data, flags, pgnop) pg = ((QUEUE *)dbp->q_internal)->q_meta; /* - * Get the meta page first, we don't want to write lock it while - * trying to pin it. + * Get the meta page first, we don't want to lock it while trying + * to pin it. */ - if ((ret = __memp_fget(mpf, &pg, 0, &meta)) != 0) + writelock = 0; + if ((ret = __memp_fget(mpf, &pg, dbc->txn, 0, &meta)) != 0) return (ret); - if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0) { + if ((ret = __db_lget(dbc, LCK_COUPLE, + pg, DB_LOCK_READ, 0, &cp->lock)) != 0) { (void)__memp_fput(mpf, meta, 0); return (ret); } @@ -303,6 +316,7 @@ __qam_c_put(dbc, key, data, flags, pgnop) * insert is. */ +recheck: if (meta->first_recno == meta->cur_recno) { new_first = cp->recno; new_cur = cp->recno + 1; @@ -311,19 +325,12 @@ __qam_c_put(dbc, key, data, flags, pgnop) opcode |= QAM_SETFIRST; opcode |= QAM_SETCUR; } else { - if (QAM_BEFORE_FIRST(meta, cp->recno) && - (meta->first_recno <= meta->cur_recno || - meta->first_recno - cp->recno < - cp->recno - meta->cur_recno)) { + if (QAM_BEFORE_FIRST(meta, cp->recno)) { new_first = cp->recno; opcode |= QAM_SETFIRST; } - if (meta->cur_recno == cp->recno || - (QAM_AFTER_CURRENT(meta, cp->recno) && - (meta->first_recno <= meta->cur_recno || - cp->recno - meta->cur_recno <= - meta->first_recno - cp->recno))) { + if (QAM_AFTER_CURRENT(meta, cp->recno)) { new_cur = cp->recno + 1; if (new_cur == RECNO_OOB) new_cur++; @@ -331,25 +338,36 @@ __qam_c_put(dbc, key, data, flags, pgnop) } } - if (opcode != 0 && DBC_LOGGING(dbc)) { - ret = __qam_mvptr_log(dbp, dbc->txn, &meta->dbmeta.lsn, - 0, opcode, meta->first_recno, new_first, - meta->cur_recno, new_cur, &meta->dbmeta.lsn, PGNO_BASE_MD); - if (ret != 0) - opcode = 0; + if (opcode == 0) + goto done; + + /* Drop the read lock and get the a write lock on the meta page. */ + if (writelock == 0 && (ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, + pg, DB_LOCK_WRITE, 0, &cp->lock)) != 0) { + (void)__memp_fput(mpf, meta, 0); + return (ret); } + if (writelock++ == 0) + goto recheck; + + if (((ret = __memp_dirty(mpf, &meta, dbc->txn, DB_MPOOL_DIRTY)) != 0 || + (DBC_LOGGING(dbc) && + (ret = __qam_mvptr_log(dbp, dbc->txn, + &meta->dbmeta.lsn, 0, opcode, meta->first_recno, + new_first, meta->cur_recno, new_cur, + &meta->dbmeta.lsn, PGNO_BASE_MD)) != 0))) + opcode = 0; if (opcode & QAM_SETCUR) meta->cur_recno = new_cur; if (opcode & QAM_SETFIRST) meta->first_recno = new_first; - if ((t_ret = __memp_fput( - mpf, meta, opcode != 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0) +done: if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0) ret = t_ret; /* Don't hold the meta page long term. */ - if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) + if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0) ret = t_ret; return (ret); } @@ -385,7 +403,7 @@ __qam_append(dbc, key, data) * Get the meta page first, we don't want to write lock it while * trying to pin it. */ - if ((ret = __memp_fget(mpf, &pg, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &pg, dbc->txn, DB_MPOOL_DIRTY, &meta)) != 0) return (ret); /* Write lock the meta page. */ if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0) { @@ -443,7 +461,8 @@ __qam_append(dbc, key, data) /* Fetch and write lock the data page. */ if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &lock)) != 0) goto err; - if ((ret = __qam_fget(dbp, &pg, DB_MPOOL_CREATE, &page)) != 0) { + if ((ret = __qam_fget(dbp, &pg, dbc->txn, + DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &page)) != 0) { /* We did not fetch it, we can release the lock. */ (void)__LPUT(dbc, lock); goto err; @@ -464,7 +483,7 @@ __qam_append(dbc, key, data) ret = t_ret; if ((t_ret = - __qam_fput(dbp, pg, page, DB_MPOOL_DIRTY)) != 0 && ret == 0) + __qam_fput(dbp, pg, page, 0)) != 0 && ret == 0) ret = t_ret; /* Return the record number to the user. */ @@ -491,7 +510,7 @@ __qam_append(dbc, key, data) } err: /* Release the meta page. */ - if ((t_ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0 && ret == 0) + if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0) ret = t_ret; return (ret); @@ -514,19 +533,19 @@ __qam_c_del(dbc) QMETA *meta; QUEUE_CURSOR *cp; db_pgno_t pg; - db_recno_t first; int exact, ret, t_ret; dbp = dbc->dbp; mpf = dbp->mpf; cp = (QUEUE_CURSOR *)dbc->internal; + LOCK_INIT(lock); pg = ((QUEUE *)dbp->q_internal)->q_meta; /* * Get the meta page first, we don't want to write lock it while * trying to pin it. */ - if ((ret = __memp_fget(mpf, &pg, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &pg, dbc->txn, 0, &meta)) != 0) return (ret); /* Write lock the meta page. */ if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_READ, 0, &metalock)) != 0) { @@ -537,8 +556,6 @@ __qam_c_del(dbc) if (QAM_NOT_VALID(meta, cp->recno)) ret = DB_NOTFOUND; - first = meta->first_recno; - /* Don't hold the meta page long term. */ if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) ret = t_ret; @@ -546,13 +563,15 @@ __qam_c_del(dbc) if (ret != 0) goto err; - if ((ret = __db_lget(dbc, - 0, cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &lock)) != 0) + if ((ret = __db_lget(dbc, LCK_COUPLE, + cp->recno, DB_LOCK_WRITE, DB_LOCK_RECORD, &cp->lock)) != 0) goto err; cp->lock_mode = DB_LOCK_WRITE; + lock = cp->lock; /* Find the record ; delete only deletes exact matches. */ - if ((ret = __qam_position(dbc, &cp->recno, QAM_WRITE, &exact)) != 0) + if ((ret = __qam_position(dbc, &cp->recno, DB_LOCK_WRITE, + DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &exact)) != 0) goto err; if (!exact) { @@ -582,20 +601,30 @@ __qam_c_del(dbc) F_CLR(qp, QAM_VALID); - if (cp->recno == first) { + /* + * Peek at the first_recno before locking the meta page. + * Other threads cannot move first_recno past + * our position while we have the record locked. + * If it's pointing at the deleted record then lock + * the metapage and check again as lower numbered +recheck: + * record may have been inserted. + */ + if (cp->recno == meta->first_recno) { pg = ((QUEUE *)dbp->q_internal)->q_meta; if ((ret = __db_lget(dbc, 0, pg, DB_LOCK_WRITE, 0, &metalock)) != 0) goto err; - ret = __qam_consume(dbc, meta, first); + if (cp->recno == meta->first_recno) + ret = __qam_consume(dbc, meta, meta->first_recno); if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) ret = t_ret; } err: if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0) ret = t_ret; - if (cp->page != NULL && (t_ret = __qam_fput(dbp, cp->pgno, - cp->page, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0) + if (cp->page != NULL && + (t_ret = __qam_fput(dbp, cp->pgno, cp->page, 0)) != 0 && ret == 0) ret = t_ret; cp->page = NULL; @@ -633,37 +662,32 @@ __qam_c_get(dbc, key, data, flags, pgnop) QMETA *meta; QUEUE *t; QUEUE_CURSOR *cp; - db_lockmode_t lock_mode; + db_lockmode_t lock_mode, meta_mode; db_pgno_t metapno; db_recno_t first; - qam_position_mode mode; int exact, inorder, is_first, locked, ret, t_ret, wait, with_delete; - int put_mode, retrying; + int retrying; dbp = dbc->dbp; dbenv = dbp->dbenv; mpf = dbp->mpf; cp = (QUEUE_CURSOR *)dbc->internal; + LOCK_INIT(lock); + LOCK_INIT(pglock); PANIC_CHECK(dbenv); wait = 0; with_delete = 0; retrying = 0; - lock_mode = DB_LOCK_READ; + lock_mode = F_ISSET(dbc, DBC_RMW) ? DB_LOCK_WRITE : DB_LOCK_READ; + meta_mode = DB_LOCK_READ; meta = NULL; inorder = F_ISSET(dbp, DB_AM_INORDER); - put_mode = 0; t_ret = 0; *pgnop = 0; pg = NULL; - mode = QAM_READ; - if (F_ISSET(dbc, DBC_RMW)) { - lock_mode = DB_LOCK_WRITE; - mode = QAM_WRITE; - } - if (flags == DB_CONSUME_WAIT) { wait = 1; flags = DB_CONSUME; @@ -671,8 +695,7 @@ __qam_c_get(dbc, key, data, flags, pgnop) if (flags == DB_CONSUME) { with_delete = 1; flags = DB_FIRST; - lock_mode = DB_LOCK_WRITE; - mode = QAM_CONSUME; + meta_mode = lock_mode = DB_LOCK_WRITE; } DEBUG_LREAD(dbc, dbc->txn, "qam_c_get", @@ -682,22 +705,36 @@ __qam_c_get(dbc, key, data, flags, pgnop) locked = 0; is_first = 0; + first = 0; t = (QUEUE *)dbp->q_internal; metapno = t->q_meta; + LOCK_INIT(metalock); /* * Get the meta page first, we don't want to write lock it while * trying to pin it. This is because someone my have it pinned * but not locked. */ - if ((ret = __memp_fget(mpf, &metapno, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &metapno, dbc->txn, 0, &meta)) != 0) return (ret); - if ((ret = __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0) - goto err; - locked = 1; - first = 0; +get_next: + switch (flags) { + case DB_NEXT: + case DB_NEXT_NODUP: + case DB_FIRST: + case DB_PREV: + case DB_PREV_NODUP: + case DB_LAST: + if ((ret = __db_lget(dbc, + 0, metapno, meta_mode, 0, &metalock)) != 0) + goto err; + locked = 1; + break; + default: + break; + } /* Release any previous lock if not in a transaction. */ if ((ret = __TLPUT(dbc, cp->lock)) != 0) @@ -713,7 +750,7 @@ retry: /* Update the record number. */ /* NOTREACHED */ case DB_NEXT: case DB_NEXT_NODUP: -get_next: if (cp->recno != RECNO_OOB) { + if (cp->recno != RECNO_OOB) { ++cp->recno; /* Wrap around, skipping zero. */ if (cp->recno == RECNO_OOB) @@ -721,8 +758,7 @@ get_next: if (cp->recno != RECNO_OOB) { /* * Check to see if we are out of data. */ - if (cp->recno == meta->cur_recno || - QAM_AFTER_CURRENT(meta, cp->recno)) { + if (QAM_AFTER_CURRENT(meta, cp->recno)) { pg = NULL; if (!wait) { ret = DB_NOTFOUND; @@ -742,18 +778,18 @@ get_next: if (cp->recno != RECNO_OOB) { if (CDB_LOCKING(dbenv)) { /* Drop the metapage before we wait. */ - if ((ret = - __memp_fput(mpf, meta, 0)) != 0) - goto err; + ret = __memp_fput(mpf, meta, 0); meta = NULL; + if (ret != 0) + goto err; if ((ret = __lock_get( dbenv, dbc->locker, DB_LOCK_SWITCH, &dbc->lock_dbt, DB_LOCK_WAIT, &dbc->mylock)) != 0) goto err; - if ((ret = __memp_fget(mpf, - &metapno, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &metapno, + dbc->txn, 0, &meta)) != 0) goto err; if ((ret = __lock_get( dbenv, dbc->locker, @@ -770,31 +806,31 @@ get_next: if (cp->recno != RECNO_OOB) { */ if (locked == 0) { if ((ret = __db_lget(dbc, 0, metapno, - lock_mode, 0, &metalock)) != 0) + meta_mode, 0, &metalock)) != 0) goto err; locked = 1; - if (cp->recno != meta->cur_recno && - cp->recno != RECNO_OOB && + if (cp->recno != RECNO_OOB && !QAM_AFTER_CURRENT(meta, cp->recno)) goto retry; } /* Drop the metapage before we wait. */ - if ((ret = __memp_fput(mpf, meta, 0)) != 0) - goto err; + ret = __memp_fput(mpf, meta, 0); meta = NULL; + if (ret != 0) + goto err; if ((ret = __db_lget(dbc, - 0, metapno, DB_LOCK_WAIT, - DB_LOCK_SWITCH, &metalock)) != 0) { + 0, metapno, DB_LOCK_WAIT, + DB_LOCK_SWITCH, &metalock)) != 0) { if (ret == DB_LOCK_DEADLOCK) ret = DB_LOCK_NOTGRANTED; goto err; } - if ((ret = __memp_fget( - mpf, &metapno, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &metapno, dbc->txn, + 0, &meta)) != 0) goto err; if ((ret = __db_lget(dbc, 0, - PGNO_INVALID, DB_LOCK_WRITE, - DB_LOCK_UPGRADE, &metalock)) != 0) { + PGNO_INVALID, DB_LOCK_WRITE, + DB_LOCK_UPGRADE, &metalock)) != 0) { if (ret == DB_LOCK_DEADLOCK) ret = DB_LOCK_NOTGRANTED; goto err; @@ -843,10 +879,6 @@ get_next: if (cp->recno != RECNO_OOB) { case DB_GET_BOTH_RANGE: if ((ret = __qam_getno(dbp, key, &cp->recno)) != 0) goto err; - if (QAM_NOT_VALID(meta, cp->recno)) { - ret = DB_NOTFOUND; - goto err; - } break; default: ret = __db_unknown_flag(dbenv, "__qam_c_get", flags); @@ -861,18 +893,20 @@ get_next: if (cp->recno != RECNO_OOB) { } /* Lock the record. */ - if ((ret = __db_lget(dbc, 0, cp->recno, lock_mode, + if (((ret = __db_lget(dbc, LCK_COUPLE, cp->recno, lock_mode, (with_delete && !retrying) ? DB_LOCK_NOWAIT | DB_LOCK_RECORD : DB_LOCK_RECORD, - &lock)) == DB_LOCK_DEADLOCK && with_delete) { + &lock)) == DB_LOCK_DEADLOCK || ret == DB_LOCK_NOTGRANTED) && + with_delete) { #ifdef QDEBUG - __db_logmsg(dbenv, - dbc->txn, "Queue S", 0, "%x %d %d %d", - dbc->locker, cp->recno, first, meta->first_recno); + if (DBC_LOGGING(dbc)) + (void)__log_printf(dbenv, + dbc->txn, "Queue S: %x %d %d %d", + dbc->locker, cp->recno, first, meta->first_recno); #endif first = 0; if ((ret = - __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0) + __db_lget(dbc, 0, metapno, meta_mode, 0, &metalock)) != 0) goto err; locked = 1; goto retry; @@ -886,27 +920,55 @@ get_next: if (cp->recno != RECNO_OOB) { * since the first/last may have moved while we slept. * We release our locks and try again. */ - if (((inorder || !with_delete) && is_first) || flags == DB_LAST) { -get_first: + switch (flags) { + default: + if ((!inorder && with_delete) || !is_first) + break; + /* FALLTHROUGH */ + case DB_SET: + case DB_SET_RANGE: + case DB_GET_BOTH: + case DB_GET_BOTH_RANGE: + case DB_LAST: if ((ret = - __db_lget(dbc, 0, metapno, lock_mode, 0, &metalock)) != 0) - goto err; - if (cp->recno != - (is_first ? meta->first_recno : (meta->cur_recno - 1))) { + __db_lget(dbc, 0, metapno, meta_mode, 0, &metalock)) != 0) + goto lerr; + locked = 1; + if ((is_first && cp->recno != meta->first_recno) || + (flags == DB_LAST && cp->recno != meta->cur_recno - 1)) { if ((ret = __LPUT(dbc, lock)) != 0) goto err; if (is_first) flags = DB_FIRST; - locked = 1; goto retry; + } else if (!is_first && flags != DB_LAST) { + if (QAM_BEFORE_FIRST(meta, cp->recno)) { + if (flags == DB_SET_RANGE || + flags == DB_GET_BOTH_RANGE) { + if ((ret = __LPUT(dbc, metalock)) != 0) + goto err; + locked = 0; + cp->lock = lock; + LOCK_INIT(lock); + goto release_retry; + } + ret = DB_NOTFOUND; + goto lerr; + } + if (QAM_AFTER_CURRENT(meta, cp->recno)) { + ret = DB_NOTFOUND; + goto lerr; + } } /* Don't hold the meta page long term. */ if ((ret = __LPUT(dbc, metalock)) != 0) goto err; + locked = 0; } /* Position the cursor on the record. */ - if ((ret = __qam_position(dbc, &cp->recno, mode, &exact)) != 0) { + if ((ret = __qam_position(dbc, &cp->recno, + lock_mode, 0, &exact)) != 0) { /* We cannot get the page, release the record lock. */ (void)__LPUT(dbc, lock); goto err; @@ -916,6 +978,7 @@ get_first: pglock = cp->lock; cp->lock = lock; cp->lock_mode = lock_mode; + LOCK_INIT(lock); if (!exact) { release_retry: /* Release locks and retry, if possible. */ @@ -924,38 +987,53 @@ release_retry: /* Release locks and retry, if possible. */ cp->page = pg = NULL; if ((ret = __LPUT(dbc, pglock)) != 0) goto err1; + if (with_delete) { + if ((ret = __LPUT(dbc, cp->lock)) != 0) + goto err1; + } else if ((ret = __TLPUT(dbc, cp->lock)) != 0) + goto err1; + /* + * If we don't need locks and we are out of range + * then we can just skip to the FIRST/LAST record + * otherwise we must iterate to lock the records + * and get serializability. + */ switch (flags) { - case DB_GET_BOTH_RANGE: - flags = DB_SET_RANGE; - /* FALLTHROUGH */ case DB_NEXT: case DB_NEXT_NODUP: - case DB_SET_RANGE: if (!with_delete) is_first = 0; - /* Peek at the meta page unlocked. */ - if (QAM_BEFORE_FIRST(meta, cp->recno)) - goto get_first; - /* FALLTHROUGH */ + if (QAM_BEFORE_FIRST(meta, cp->recno) && + DONT_NEED_LOCKS(dbc)) + flags = DB_FIRST; + break; + case DB_LAST: case DB_PREV: case DB_PREV_NODUP: - case DB_LAST: - if (flags == DB_LAST) + if (QAM_AFTER_CURRENT(meta, cp->recno) && + DONT_NEED_LOCKS(dbc)) + flags = DB_LAST; + else flags = DB_PREV; - retrying = 0; - if ((ret = __LPUT(dbc, cp->lock)) != 0) - goto err1; - if (flags == DB_SET_RANGE) - goto get_next; + break; + + case DB_GET_BOTH_RANGE: + case DB_SET_RANGE: + if (QAM_BEFORE_FIRST(meta, cp->recno) && + DONT_NEED_LOCKS(dbc)) + flags = DB_FIRST; else - goto retry; + flags = DB_NEXT; + break; default: /* this is for the SET and GET_BOTH cases */ ret = DB_KEYEMPTY; goto err1; } + retrying = 0; + goto get_next; } qp = QAM_GET_RECORD(dbp, pg, cp->indx); @@ -976,18 +1054,18 @@ release_retry: /* Release locks and retry, if possible. */ } /* Return the key if the user didn't give us one. */ - if (key != NULL) { - if (flags != DB_GET_BOTH && flags != DB_SET && - (ret = __db_retcopy(dbp->dbenv, + if (key != NULL && !F_ISSET(key, DB_DBT_ISSET)) { + if ((ret = __db_retcopy(dbp->dbenv, key, &cp->recno, sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen)) != 0) goto err1; F_SET(key, DB_DBT_ISSET); } - if (data != NULL) { - if (!F_ISSET(dbc, DBC_MULTIPLE|DBC_MULTIPLE_KEY) && - (ret = __db_retcopy(dbp->dbenv, data, qp->data, t->re_len, + if (data != NULL && + !F_ISSET(dbc, DBC_MULTIPLE|DBC_MULTIPLE_KEY) && + !F_ISSET(data, DB_DBT_ISSET)) { + if ((ret = __db_retcopy(dbp->dbenv, data, qp->data, t->re_len, &dbc->rdata->data, &dbc->rdata->ulen)) != 0) goto err1; F_SET(data, DB_DBT_ISSET); @@ -1001,7 +1079,12 @@ release_retry: /* Release locks and retry, if possible. */ * DB_APPEND there; attempting one should be forbidden by * the interface. */ - DB_ASSERT(!F_ISSET(dbp, DB_AM_SECONDARY)); + DB_ASSERT(dbenv, !F_ISSET(dbp, DB_AM_SECONDARY)); + + if ((ret = __qam_dirty(dbp, cp->pgno, &cp->page, + dbc->txn, 0)) != 0) + goto err1; + pg = cp->page; /* * Check and see if we *have* any secondary indices. @@ -1048,7 +1131,6 @@ release_retry: /* Release locks and retry, if possible. */ } F_CLR(qp, QAM_VALID); - put_mode = DB_MPOOL_DIRTY; if ((ret = __LPUT(dbc, pglock)) != 0) goto err1; @@ -1066,14 +1148,15 @@ release_retry: /* Release locks and retry, if possible. */ */ if (locked == 0 && (ret = __db_lget( - dbc, 0, metapno, lock_mode, 0, &metalock)) != 0) + dbc, 0, metapno, meta_mode, 0, &metalock)) != 0) goto err1; locked = 1; #ifdef QDEBUG - __db_logmsg(dbenv, - dbc->txn, "Queue D", 0, "%x %d %d %d", - dbc->locker, cp->recno, first, meta->first_recno); + if (DBC_LOGGING(dbc)) + (void)__log_printf(dbenv, + dbc->txn, "Queue D: %x %d %d %d", + dbc->locker, cp->recno, first, meta->first_recno); #endif /* * See if we deleted the "first" record. If @@ -1092,8 +1175,8 @@ release_retry: /* Release locks and retry, if possible. */ done: err1: if (cp->page != NULL) { - if ((t_ret = __qam_fput( - dbp, cp->pgno, cp->page, put_mode)) != 0 && ret == 0) + if ((t_ret = __qam_fput(dbp, cp->pgno, cp->page, 0)) != 0 && + ret == 0) ret = t_ret; /* Doing record locking, release the page lock */ @@ -1101,6 +1184,9 @@ err1: if (cp->page != NULL) { ret = t_ret; cp->page = NULL; } + if (0) { +lerr: (void)__LPUT(dbc, lock); + } err: if (meta) { /* Release the meta page. */ @@ -1112,11 +1198,11 @@ err: if (meta) { if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) ret = t_ret; } - DB_ASSERT(!LOCK_ISSET(metalock)); + DB_ASSERT(dbenv, !LOCK_ISSET(metalock)); return ((ret == DB_LOCK_NOTGRANTED && - !F_ISSET(dbenv, DB_ENV_TIME_NOTGRANTED)) ? - DB_LOCK_DEADLOCK : ret); + !F_ISSET(dbenv, DB_ENV_TIME_NOTGRANTED)) ? + DB_LOCK_DEADLOCK : ret); } /* @@ -1142,7 +1228,7 @@ __qam_consume(dbc, meta, first) dbp = dbc->dbp; mpf = dbp->mpf; cp = (QUEUE_CURSOR *)dbc->internal; - put_mode = DB_MPOOL_DIRTY; + put_mode = 0; ret = 0; save_page = cp->pgno; @@ -1165,12 +1251,11 @@ __qam_consume(dbc, meta, first) if (ret != 0) goto done; if ((ret = - __qam_fput(dbp, cp->pgno, cp->page, put_mode)) != 0) + __qam_fput(dbp, cp->pgno, cp->page, 0)) != 0) goto done; cp->page = NULL; - put_mode = 0; if ((ret = __qam_position(dbc, - &first, QAM_READ, &exact)) != 0 || exact != 0) { + &first, DB_LOCK_READ, 0, &exact)) != 0 || exact != 0) { (void)__LPUT(dbc, lock); goto done; } @@ -1198,20 +1283,20 @@ __qam_consume(dbc, meta, first) */ if (cp->page != NULL && rec_extent != 0 && ((exact = (first % rec_extent == 0)) || - first % meta->rec_page == 0 || + (first % meta->rec_page == 0) || first == UINT32_MAX)) { if (exact == 1 && (ret = __db_lget(dbc, 0, cp->pgno, DB_LOCK_WRITE, 0, &cp->lock)) != 0) break; - #ifdef QDEBUG - __db_logmsg(dbp->dbenv, - dbc->txn, "Queue R", 0, "%x %d %d %d", - dbc->locker, cp->pgno, first, meta->first_recno); + if (DBC_LOGGING(dbc)) + (void)__log_printf(dbp->dbenv, dbc->txn, + "Queue R: %x %d %d %d", dbc->locker, + cp->pgno, first, meta->first_recno); #endif put_mode |= DB_MPOOL_DISCARD; - if ((ret = __qam_fput(dbp, - cp->pgno, cp->page, put_mode)) != 0) + if ((ret = + __qam_fput(dbp, cp->pgno, cp->page, put_mode)) != 0) break; cp->page = NULL; @@ -1250,7 +1335,7 @@ __qam_consume(dbc, meta, first) break; if ((ret = __qam_position(dbc, - &first, QAM_READ, &exact)) != 0) { + &first, DB_LOCK_READ, 0, &exact)) != 0) { (void)__LPUT(dbc, lock); break; } @@ -1275,10 +1360,13 @@ __qam_consume(dbc, meta, first) * Advance first_recno to this point. */ if (ret == 0 && meta->first_recno != first) { + if ((ret = __memp_dirty(mpf, &meta, dbc->txn, 0)) != 0) + goto done; #ifdef QDEBUG - __db_logmsg(dbp->dbenv, dbc->txn, "Queue M", - 0, "%x %d %d %d", dbc->locker, cp->recno, - first, meta->first_recno); + if (DBC_LOGGING(dbc)) + (void)__log_printf(dbp->dbenv, dbc->txn, + "Queue M: %x %d %d %d", dbc->locker, cp->recno, + first, meta->first_recno); #endif if (DBC_LOGGING(dbc)) if ((ret = __qam_incfirst_log(dbp, @@ -1286,7 +1374,6 @@ __qam_consume(dbc, meta, first) cp->recno, PGNO_BASE_MD)) != 0) goto done; meta->first_recno = first; - (void)__memp_fset(mpf, meta, DB_MPOOL_DIRTY); } done: @@ -1309,22 +1396,17 @@ __qam_bulk(dbc, data, flags) db_indx_t indx; db_lockmode_t lkmode; db_pgno_t metapno; - qam_position_mode mode; - int32_t *endp, *offp; + u_int32_t *endp, *offp; + u_int32_t pagesize, re_len, recs; u_int8_t *dbuf, *dp, *np; - int exact, recs, re_len, ret, t_ret, valid; - int is_key, need_pg, pagesize, size, space; + int exact, ret, t_ret, valid; + int is_key, need_pg, size, space; dbp = dbc->dbp; mpf = dbp->mpf; cp = (QUEUE_CURSOR *)dbc->internal; - mode = QAM_READ; - lkmode = DB_LOCK_READ; - if (F_ISSET(dbc, DBC_RMW)) { - mode = QAM_WRITE; - lkmode = DB_LOCK_WRITE; - } + lkmode = F_ISSET(dbc, DBC_RMW) ? DB_LOCK_WRITE : DB_LOCK_READ; pagesize = dbp->pgsize; re_len = ((QUEUE *)dbp->q_internal)->re_len; @@ -1336,7 +1418,7 @@ __qam_bulk(dbc, data, flags) if ((ret = __db_lget(dbc, 0, metapno, DB_LOCK_READ, 0, &metalock)) != 0) return (ret); - if ((ret = __memp_fget(mpf, &metapno, 0, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapno, dbc->txn, 0, &meta)) != 0) { /* We did not fetch it, we can release the lock. */ (void)__LPUT(dbc, metalock); return (ret); @@ -1346,11 +1428,11 @@ __qam_bulk(dbc, data, flags) np = dp = dbuf; /* Keep track of space that is left. There is an termination entry */ - space = data->ulen; - space -= sizeof(*offp); + space = (int)data->ulen; + space -= (int)sizeof(*offp); - /* Build the offset/size table form the end up. */ - endp = (int32_t *) ((u_int8_t *)dbuf + data->ulen); + /* Build the offset/size table from the end up. */ + endp = (u_int32_t *)((u_int8_t *)dbuf + data->ulen); endp--; offp = endp; /* Save the lock on the current position of the cursor. */ @@ -1361,7 +1443,7 @@ next_pg: /* Wrap around, skipping zero. */ if (cp->recno == RECNO_OOB) cp->recno++; - if ((ret = __qam_position(dbc, &cp->recno, mode, &exact)) != 0) + if ((ret = __qam_position(dbc, &cp->recno, lkmode, 0, &exact)) != 0) goto done; pg = cp->page; @@ -1379,23 +1461,24 @@ next_pg: if (pg != NULL) { if ((ret = __db_lget(dbc, LCK_COUPLE, - cp->recno, lkmode, DB_LOCK_RECORD, &rlock)) != 0) + cp->recno, lkmode, DB_LOCK_RECORD, &rlock)) != 0) goto done; qp = QAM_GET_RECORD(dbp, pg, indx); if (F_ISSET(qp, QAM_VALID)) { valid = 1; - space -= (is_key ? 3 : 2) * sizeof(*offp); + space -= (int) + ((is_key ? 3 : 2) * sizeof(*offp)); if (space < 0) goto get_space; if (need_pg) { dp = np; - size = pagesize - QPAGE_SZ(dbp); + size = (int)pagesize - QPAGE_SZ(dbp); if (space < size) { get_space: if (offp == endp) { data->size = (u_int32_t) - DB_ALIGN(size + - pagesize, + DB_ALIGN((u_int32_t) + size + pagesize, sizeof(u_int32_t)); ret = DB_BUFFER_SMALL; break; @@ -1407,16 +1490,17 @@ get_space: break; } memcpy(dp, - (char *)pg + QPAGE_SZ(dbp), size); + (u_int8_t *)pg + QPAGE_SZ(dbp), + (u_int)size); need_pg = 0; space -= size; np += size; } if (is_key) *offp-- = cp->recno; - *offp-- = (int32_t)((u_int8_t*)qp - - (u_int8_t*)pg - QPAGE_SZ(dbp) + - dp - dbuf + SSZA(QAMDATA, data)); + *offp-- = (u_int32_t)((((u_int8_t *)qp - + (u_int8_t *)pg) - QPAGE_SZ(dbp)) + + (dp - dbuf) + SSZA(QAMDATA, data)); *offp-- = re_len; } } @@ -1426,7 +1510,6 @@ get_space: } cp->recno++; } while (++indx < recs && cp->recno != RECNO_OOB && - cp->recno != meta->cur_recno && !QAM_AFTER_CURRENT(meta, cp->recno)); /* Drop the page lock. */ @@ -1442,7 +1525,6 @@ get_space: if (ret == 0 && space > 0 && (indx >= recs || cp->recno == RECNO_OOB) && - cp->recno != meta->cur_recno && !QAM_AFTER_CURRENT(meta, cp->recno)) goto next_pg; @@ -1457,7 +1539,7 @@ get_space: if (is_key == 1) *offp = RECNO_OOB; else - *offp = -1; + *offp = (u_int32_t)-1; done: /* Release the meta page. */ if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0) @@ -1514,19 +1596,12 @@ __qam_c_dup(orig_dbc, new_dbc) DBC *orig_dbc, *new_dbc; { QUEUE_CURSOR *orig, *new; - int ret; orig = (QUEUE_CURSOR *)orig_dbc->internal; new = (QUEUE_CURSOR *)new_dbc->internal; new->recno = orig->recno; - /* Acquire the long term lock if we are not in a transaction. */ - if (orig_dbc->txn == NULL && LOCK_ISSET(orig->lock)) - if ((ret = __db_lget(new_dbc, 0, new->recno, - new->lock_mode, DB_LOCK_RECORD, &new->lock)) != 0) - return (ret); - return (0); } @@ -1555,7 +1630,7 @@ __qam_c_init(dbc) } /* Initialize methods. */ - 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; @@ -1598,7 +1673,7 @@ __qam_getno(dbp, key, rep) db_recno_t *rep; { if ((*rep = *(db_recno_t *)key->data) == 0) { - __db_err(dbp->dbenv, "illegal record number of 0"); + __db_errx(dbp->dbenv, "illegal record number of 0"); return (EINVAL); } return (0); @@ -1639,7 +1714,8 @@ __qam_truncate(dbc, countp) return (ret); mpf = dbp->mpf; - if ((ret = __memp_fget(mpf, &metapno, 0, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapno, dbc->txn, + DB_MPOOL_DIRTY, &meta)) != 0) { /* We did not fetch it, we can release the lock. */ (void)__LPUT(dbc, metalock); return (ret); @@ -1647,7 +1723,7 @@ __qam_truncate(dbc, countp) /* Remove the last extent file. */ if (meta->cur_recno > 1 && ((QUEUE *)dbp->q_internal)->page_ext != 0) { if ((ret = __qam_fremove(dbp, - QAM_RECNO_PAGE(dbp, meta->cur_recno - 1))) != 0) + QAM_RECNO_PAGE(dbp, meta->cur_recno - 1))) != 0) return (ret); } @@ -1659,13 +1735,36 @@ __qam_truncate(dbc, countp) if (ret == 0) meta->first_recno = meta->cur_recno = 1; - if ((t_ret = __memp_fput(mpf, - meta, ret == 0 ? DB_MPOOL_DIRTY: 0)) != 0 && ret == 0) + if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0) ret = t_ret; if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) ret = t_ret; - *countp = count; + if (countp != NULL) + *countp = count; return (ret); } + +/* + * __qam_delete -- + * Queue fast delete function. + * + * PUBLIC: int __qam_delete __P((DBC *, DBT *)); + */ +int +__qam_delete(dbc, key) + DBC *dbc; + DBT *key; +{ + QUEUE_CURSOR *cp; + int ret; + + cp = (QUEUE_CURSOR *)dbc->internal; + if ((ret = __qam_getno(dbc->dbp, key, &cp->recno)) != 0) + goto err; + + ret = __qam_c_del(dbc); + +err: return (ret); +} diff --git a/db/qam/qam.src b/db/qam/qam.src index 71063f0b6..4e795e553 100644 --- a/db/qam/qam.src +++ b/db/qam/qam.src @@ -1,22 +1,15 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam.src,v 11.33 2004/06/17 17:35:22 bostic Exp $ + * $Id: qam.src,v 12.5 2006/08/24 14:46:23 bostic Exp $ */ PREFIX __qam DBPRIVATE -INCLUDE #ifndef NO_SYSTEM_INCLUDES -INCLUDE #include <sys/types.h> -INCLUDE -INCLUDE #include <ctype.h> -INCLUDE #include <string.h> -INCLUDE #endif -INCLUDE INCLUDE #include "db_int.h" INCLUDE #include "dbinc/crypto.h" INCLUDE #include "dbinc/db_page.h" @@ -31,7 +24,7 @@ INCLUDE * incfirst * Used when we increment first_recno. */ -BEGIN incfirst 84 +BEGIN incfirst 42 84 DB fileid int32_t ld ARG recno db_recno_t lu ARG meta_pgno db_pgno_t lu @@ -41,7 +34,7 @@ END * mvptr * Used when we change one or both of cur_recno and first_recno. */ -BEGIN mvptr 85 +BEGIN mvptr 42 85 ARG opcode u_int32_t lu DB fileid int32_t ld ARG old_first db_recno_t lu @@ -58,7 +51,7 @@ END * Used when we delete a record. * recno is the record that is being deleted. */ -BEGIN del 79 +BEGIN del 42 79 DB fileid int32_t ld POINTER lsn DB_LSN * lu ARG pgno db_pgno_t lu @@ -72,7 +65,7 @@ END * recno is the record being added. * data is the record itself. */ -BEGIN add 80 +BEGIN add 42 80 DB fileid int32_t ld POINTER lsn DB_LSN * lu ARG pgno db_pgno_t lu @@ -88,7 +81,7 @@ END * Used when we delete a record in extent based queue. * recno is the record that is being deleted. */ -BEGIN delext 83 +BEGIN delext 42 83 DB fileid int32_t ld POINTER lsn DB_LSN * lu ARG pgno db_pgno_t lu diff --git a/db/qam/qam_auto.c b/db/qam/qam_auto.c index fe3dcf6fd..acca78332 100644 --- a/db/qam/qam_auto.c +++ b/db/qam/qam_auto.c @@ -2,13 +2,6 @@ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <string.h> -#endif - #include "db_int.h" #include "dbinc/crypto.h" #include "dbinc/db_page.h" @@ -23,9 +16,9 @@ * PUBLIC: u_int32_t, db_recno_t, db_pgno_t)); */ int -__qam_incfirst_log(dbp, txnid, ret_lsnp, flags, recno, meta_pgno) +__qam_incfirst_log(dbp, txnp, ret_lsnp, flags, recno, meta_pgno) DB *dbp; - DB_TXN *txnid; + DB_TXN *txnp; DB_LSN *ret_lsnp; u_int32_t flags; db_recno_t recno; @@ -51,30 +44,31 @@ __qam_incfirst_log(dbp, txnid, ret_lsnp, flags, recno, meta_pgno) if (LF_ISSET(DB_LOG_NOT_DURABLE) || F_ISSET(dbp, DB_AM_NOT_DURABLE)) { + if (txnp == NULL) + return (0); is_durable = 0; } else is_durable = 1; - if (txnid == NULL) { + if (txnp == NULL) { txn_num = 0; lsnp = &null_lsn; null_lsn.file = null_lsn.offset = 0; } else { - if (TAILQ_FIRST(&txnid->kids) != NULL && - (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + if (TAILQ_FIRST(&txnp->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnp)) != 0) return (ret); /* * We need to assign begin_lsn while holding region mutex. * That assignment is done inside the DbEnv->log_put call, * so pass in the appropriate memory location to be filled * in by the log_put code. - */ - DB_SET_BEGIN_LSNP(txnid, &rlsnp); - txn_num = txnid->txnid; - lsnp = &txnid->last_lsn; + */ + DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp); + txn_num = txnp->txnid; } - DB_ASSERT(dbp->log_filename != NULL); + DB_ASSERT(dbenv, dbp->log_filename != NULL); if (dbp->log_filename->id == DB_LOGFILEID_INVALID && (ret = __dbreg_lazy_id(dbp)) != 0) return (ret); @@ -89,7 +83,7 @@ __qam_incfirst_log(dbp, txnid, ret_lsnp, flags, recno, meta_pgno) logrec.size += npad; } - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0) return (ret); @@ -133,12 +127,13 @@ __qam_incfirst_log(dbp, txnid, ret_lsnp, flags, recno, meta_pgno) memcpy(bp, &uinttmp, sizeof(uinttmp)); bp += sizeof(uinttmp); - DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + DB_ASSERT(dbenv, + (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec, - flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) { - txnid->last_lsn = *rlsnp; + flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) { + *lsnp = *rlsnp; if (rlsnp != ret_lsnp) *ret_lsnp = *rlsnp; } @@ -157,20 +152,21 @@ __qam_incfirst_log(dbp, txnid, ret_lsnp, flags, recno, meta_pgno) #else ret = 0; #endif - STAILQ_INSERT_HEAD(&txnid->logs, lr, links); + STAILQ_INSERT_HEAD(&txnp->logs, lr, links); + F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY); LSN_NOT_LOGGED(*ret_lsnp); } #ifdef LOG_DIAGNOSTIC if (ret != 0) (void)__qam_incfirst_print(dbenv, - (DBT *)&logrec, ret_lsnp, NULL, NULL); + (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL); #endif #ifdef DIAGNOSTIC __os_free(dbenv, logrec.data); #else - if (is_durable || txnid == NULL) + if (is_durable || txnp == NULL) __os_free(dbenv, logrec.data); #endif return (ret); @@ -195,13 +191,14 @@ __qam_incfirst_read(dbenv, recbuf, argpp) sizeof(__qam_incfirst_args) + sizeof(DB_TXN), &argp)) != 0) return (ret); bp = recbuf; - argp->txnid = (DB_TXN *)&argp[1]; + argp->txnp = (DB_TXN *)&argp[1]; + memset(argp->txnp, 0, sizeof(DB_TXN)); memcpy(&argp->type, bp, sizeof(argp->type)); bp += sizeof(argp->type); - memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); - bp += sizeof(argp->txnid->txnid); + memcpy(&argp->txnp->txnid, bp, sizeof(argp->txnp->txnid)); + bp += sizeof(argp->txnp->txnid); memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); bp += sizeof(DB_LSN); @@ -228,11 +225,11 @@ __qam_incfirst_read(dbenv, recbuf, argpp) * PUBLIC: db_recno_t, DB_LSN *, db_pgno_t)); */ int -__qam_mvptr_log(dbp, txnid, ret_lsnp, flags, +__qam_mvptr_log(dbp, txnp, ret_lsnp, flags, opcode, old_first, new_first, old_cur, new_cur, metalsn, meta_pgno) DB *dbp; - DB_TXN *txnid; + DB_TXN *txnp; DB_LSN *ret_lsnp; u_int32_t flags; u_int32_t opcode; @@ -263,30 +260,31 @@ __qam_mvptr_log(dbp, txnid, ret_lsnp, flags, if (LF_ISSET(DB_LOG_NOT_DURABLE) || F_ISSET(dbp, DB_AM_NOT_DURABLE)) { + if (txnp == NULL) + return (0); is_durable = 0; } else is_durable = 1; - if (txnid == NULL) { + if (txnp == NULL) { txn_num = 0; lsnp = &null_lsn; null_lsn.file = null_lsn.offset = 0; } else { - if (TAILQ_FIRST(&txnid->kids) != NULL && - (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + if (TAILQ_FIRST(&txnp->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnp)) != 0) return (ret); /* * We need to assign begin_lsn while holding region mutex. * That assignment is done inside the DbEnv->log_put call, * so pass in the appropriate memory location to be filled * in by the log_put code. - */ - DB_SET_BEGIN_LSNP(txnid, &rlsnp); - txn_num = txnid->txnid; - lsnp = &txnid->last_lsn; + */ + DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp); + txn_num = txnp->txnid; } - DB_ASSERT(dbp->log_filename != NULL); + DB_ASSERT(dbenv, dbp->log_filename != NULL); if (dbp->log_filename->id == DB_LOGFILEID_INVALID && (ret = __dbreg_lazy_id(dbp)) != 0) return (ret); @@ -306,7 +304,7 @@ __qam_mvptr_log(dbp, txnid, ret_lsnp, flags, logrec.size += npad; } - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0) return (ret); @@ -362,9 +360,15 @@ __qam_mvptr_log(dbp, txnid, ret_lsnp, flags, memcpy(bp, &uinttmp, sizeof(uinttmp)); bp += sizeof(uinttmp); - if (metalsn != NULL) + if (metalsn != NULL) { + if (txnp != NULL) { + LOG *lp = dbenv->lg_handle->reginfo.primary; + if (LOG_COMPARE(metalsn, &lp->lsn) >= 0 && (ret = + __log_check_page_lsn(dbenv, dbp, metalsn) != 0)) + return (ret); + } memcpy(bp, metalsn, sizeof(*metalsn)); - else + } else memset(bp, 0, sizeof(*metalsn)); bp += sizeof(*metalsn); @@ -372,12 +376,13 @@ __qam_mvptr_log(dbp, txnid, ret_lsnp, flags, memcpy(bp, &uinttmp, sizeof(uinttmp)); bp += sizeof(uinttmp); - DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + DB_ASSERT(dbenv, + (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec, - flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) { - txnid->last_lsn = *rlsnp; + flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) { + *lsnp = *rlsnp; if (rlsnp != ret_lsnp) *ret_lsnp = *rlsnp; } @@ -396,20 +401,21 @@ __qam_mvptr_log(dbp, txnid, ret_lsnp, flags, #else ret = 0; #endif - STAILQ_INSERT_HEAD(&txnid->logs, lr, links); + STAILQ_INSERT_HEAD(&txnp->logs, lr, links); + F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY); LSN_NOT_LOGGED(*ret_lsnp); } #ifdef LOG_DIAGNOSTIC if (ret != 0) (void)__qam_mvptr_print(dbenv, - (DBT *)&logrec, ret_lsnp, NULL, NULL); + (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL); #endif #ifdef DIAGNOSTIC __os_free(dbenv, logrec.data); #else - if (is_durable || txnid == NULL) + if (is_durable || txnp == NULL) __os_free(dbenv, logrec.data); #endif return (ret); @@ -433,13 +439,14 @@ __qam_mvptr_read(dbenv, recbuf, argpp) sizeof(__qam_mvptr_args) + sizeof(DB_TXN), &argp)) != 0) return (ret); bp = recbuf; - argp->txnid = (DB_TXN *)&argp[1]; + argp->txnp = (DB_TXN *)&argp[1]; + memset(argp->txnp, 0, sizeof(DB_TXN)); memcpy(&argp->type, bp, sizeof(argp->type)); bp += sizeof(argp->type); - memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); - bp += sizeof(argp->txnid->txnid); + memcpy(&argp->txnp->txnid, bp, sizeof(argp->txnp->txnid)); + bp += sizeof(argp->txnp->txnid); memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); bp += sizeof(DB_LSN); @@ -484,9 +491,9 @@ __qam_mvptr_read(dbenv, recbuf, argpp) * PUBLIC: u_int32_t, DB_LSN *, db_pgno_t, u_int32_t, db_recno_t)); */ int -__qam_del_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno) +__qam_del_log(dbp, txnp, ret_lsnp, flags, lsn, pgno, indx, recno) DB *dbp; - DB_TXN *txnid; + DB_TXN *txnp; DB_LSN *ret_lsnp; u_int32_t flags; DB_LSN * lsn; @@ -514,30 +521,31 @@ __qam_del_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno) if (LF_ISSET(DB_LOG_NOT_DURABLE) || F_ISSET(dbp, DB_AM_NOT_DURABLE)) { + if (txnp == NULL) + return (0); is_durable = 0; } else is_durable = 1; - if (txnid == NULL) { + if (txnp == NULL) { txn_num = 0; lsnp = &null_lsn; null_lsn.file = null_lsn.offset = 0; } else { - if (TAILQ_FIRST(&txnid->kids) != NULL && - (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + if (TAILQ_FIRST(&txnp->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnp)) != 0) return (ret); /* * We need to assign begin_lsn while holding region mutex. * That assignment is done inside the DbEnv->log_put call, * so pass in the appropriate memory location to be filled * in by the log_put code. - */ - DB_SET_BEGIN_LSNP(txnid, &rlsnp); - txn_num = txnid->txnid; - lsnp = &txnid->last_lsn; + */ + DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp); + txn_num = txnp->txnid; } - DB_ASSERT(dbp->log_filename != NULL); + DB_ASSERT(dbenv, dbp->log_filename != NULL); if (dbp->log_filename->id == DB_LOGFILEID_INVALID && (ret = __dbreg_lazy_id(dbp)) != 0) return (ret); @@ -554,7 +562,7 @@ __qam_del_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno) logrec.size += npad; } - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0) return (ret); @@ -590,9 +598,15 @@ __qam_del_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno) memcpy(bp, &uinttmp, sizeof(uinttmp)); bp += sizeof(uinttmp); - if (lsn != NULL) + if (lsn != NULL) { + if (txnp != NULL) { + LOG *lp = dbenv->lg_handle->reginfo.primary; + if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret = + __log_check_page_lsn(dbenv, dbp, lsn) != 0)) + return (ret); + } memcpy(bp, lsn, sizeof(*lsn)); - else + } else memset(bp, 0, sizeof(*lsn)); bp += sizeof(*lsn); @@ -608,12 +622,13 @@ __qam_del_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno) memcpy(bp, &uinttmp, sizeof(uinttmp)); bp += sizeof(uinttmp); - DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + DB_ASSERT(dbenv, + (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec, - flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) { - txnid->last_lsn = *rlsnp; + flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) { + *lsnp = *rlsnp; if (rlsnp != ret_lsnp) *ret_lsnp = *rlsnp; } @@ -632,20 +647,21 @@ __qam_del_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno) #else ret = 0; #endif - STAILQ_INSERT_HEAD(&txnid->logs, lr, links); + STAILQ_INSERT_HEAD(&txnp->logs, lr, links); + F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY); LSN_NOT_LOGGED(*ret_lsnp); } #ifdef LOG_DIAGNOSTIC if (ret != 0) (void)__qam_del_print(dbenv, - (DBT *)&logrec, ret_lsnp, NULL, NULL); + (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL); #endif #ifdef DIAGNOSTIC __os_free(dbenv, logrec.data); #else - if (is_durable || txnid == NULL) + if (is_durable || txnp == NULL) __os_free(dbenv, logrec.data); #endif return (ret); @@ -669,13 +685,14 @@ __qam_del_read(dbenv, recbuf, argpp) sizeof(__qam_del_args) + sizeof(DB_TXN), &argp)) != 0) return (ret); bp = recbuf; - argp->txnid = (DB_TXN *)&argp[1]; + argp->txnp = (DB_TXN *)&argp[1]; + memset(argp->txnp, 0, sizeof(DB_TXN)); memcpy(&argp->type, bp, sizeof(argp->type)); bp += sizeof(argp->type); - memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); - bp += sizeof(argp->txnid->txnid); + memcpy(&argp->txnp->txnid, bp, sizeof(argp->txnp->txnid)); + bp += sizeof(argp->txnp->txnid); memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); bp += sizeof(DB_LSN); @@ -709,10 +726,10 @@ __qam_del_read(dbenv, recbuf, argpp) * PUBLIC: const DBT *, u_int32_t, const DBT *)); */ int -__qam_add_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data, +__qam_add_log(dbp, txnp, ret_lsnp, flags, lsn, pgno, indx, recno, data, vflag, olddata) DB *dbp; - DB_TXN *txnid; + DB_TXN *txnp; DB_LSN *ret_lsnp; u_int32_t flags; DB_LSN * lsn; @@ -743,30 +760,31 @@ __qam_add_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data, if (LF_ISSET(DB_LOG_NOT_DURABLE) || F_ISSET(dbp, DB_AM_NOT_DURABLE)) { + if (txnp == NULL) + return (0); is_durable = 0; } else is_durable = 1; - if (txnid == NULL) { + if (txnp == NULL) { txn_num = 0; lsnp = &null_lsn; null_lsn.file = null_lsn.offset = 0; } else { - if (TAILQ_FIRST(&txnid->kids) != NULL && - (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + if (TAILQ_FIRST(&txnp->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnp)) != 0) return (ret); /* * We need to assign begin_lsn while holding region mutex. * That assignment is done inside the DbEnv->log_put call, * so pass in the appropriate memory location to be filled * in by the log_put code. - */ - DB_SET_BEGIN_LSNP(txnid, &rlsnp); - txn_num = txnid->txnid; - lsnp = &txnid->last_lsn; + */ + DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp); + txn_num = txnp->txnid; } - DB_ASSERT(dbp->log_filename != NULL); + DB_ASSERT(dbenv, dbp->log_filename != NULL); if (dbp->log_filename->id == DB_LOGFILEID_INVALID && (ret = __dbreg_lazy_id(dbp)) != 0) return (ret); @@ -786,7 +804,7 @@ __qam_add_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data, logrec.size += npad; } - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0) return (ret); @@ -822,9 +840,15 @@ __qam_add_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data, memcpy(bp, &uinttmp, sizeof(uinttmp)); bp += sizeof(uinttmp); - if (lsn != NULL) + if (lsn != NULL) { + if (txnp != NULL) { + LOG *lp = dbenv->lg_handle->reginfo.primary; + if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret = + __log_check_page_lsn(dbenv, dbp, lsn) != 0)) + return (ret); + } memcpy(bp, lsn, sizeof(*lsn)); - else + } else memset(bp, 0, sizeof(*lsn)); bp += sizeof(*lsn); @@ -866,12 +890,13 @@ __qam_add_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data, bp += olddata->size; } - DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + DB_ASSERT(dbenv, + (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec, - flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) { - txnid->last_lsn = *rlsnp; + flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) { + *lsnp = *rlsnp; if (rlsnp != ret_lsnp) *ret_lsnp = *rlsnp; } @@ -890,20 +915,21 @@ __qam_add_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data, #else ret = 0; #endif - STAILQ_INSERT_HEAD(&txnid->logs, lr, links); + STAILQ_INSERT_HEAD(&txnp->logs, lr, links); + F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY); LSN_NOT_LOGGED(*ret_lsnp); } #ifdef LOG_DIAGNOSTIC if (ret != 0) (void)__qam_add_print(dbenv, - (DBT *)&logrec, ret_lsnp, NULL, NULL); + (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL); #endif #ifdef DIAGNOSTIC __os_free(dbenv, logrec.data); #else - if (is_durable || txnid == NULL) + if (is_durable || txnp == NULL) __os_free(dbenv, logrec.data); #endif return (ret); @@ -927,13 +953,14 @@ __qam_add_read(dbenv, recbuf, argpp) sizeof(__qam_add_args) + sizeof(DB_TXN), &argp)) != 0) return (ret); bp = recbuf; - argp->txnid = (DB_TXN *)&argp[1]; + argp->txnp = (DB_TXN *)&argp[1]; + memset(argp->txnp, 0, sizeof(DB_TXN)); memcpy(&argp->type, bp, sizeof(argp->type)); bp += sizeof(argp->type); - memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); - bp += sizeof(argp->txnid->txnid); + memcpy(&argp->txnp->txnid, bp, sizeof(argp->txnp->txnid)); + bp += sizeof(argp->txnp->txnid); memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); bp += sizeof(DB_LSN); @@ -983,9 +1010,9 @@ __qam_add_read(dbenv, recbuf, argpp) * PUBLIC: const DBT *)); */ int -__qam_delext_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data) +__qam_delext_log(dbp, txnp, ret_lsnp, flags, lsn, pgno, indx, recno, data) DB *dbp; - DB_TXN *txnid; + DB_TXN *txnp; DB_LSN *ret_lsnp; u_int32_t flags; DB_LSN * lsn; @@ -1014,30 +1041,31 @@ __qam_delext_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data) if (LF_ISSET(DB_LOG_NOT_DURABLE) || F_ISSET(dbp, DB_AM_NOT_DURABLE)) { + if (txnp == NULL) + return (0); is_durable = 0; } else is_durable = 1; - if (txnid == NULL) { + if (txnp == NULL) { txn_num = 0; lsnp = &null_lsn; null_lsn.file = null_lsn.offset = 0; } else { - if (TAILQ_FIRST(&txnid->kids) != NULL && - (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + if (TAILQ_FIRST(&txnp->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnp)) != 0) return (ret); /* * We need to assign begin_lsn while holding region mutex. * That assignment is done inside the DbEnv->log_put call, * so pass in the appropriate memory location to be filled * in by the log_put code. - */ - DB_SET_BEGIN_LSNP(txnid, &rlsnp); - txn_num = txnid->txnid; - lsnp = &txnid->last_lsn; + */ + DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp); + txn_num = txnp->txnid; } - DB_ASSERT(dbp->log_filename != NULL); + DB_ASSERT(dbenv, dbp->log_filename != NULL); if (dbp->log_filename->id == DB_LOGFILEID_INVALID && (ret = __dbreg_lazy_id(dbp)) != 0) return (ret); @@ -1055,7 +1083,7 @@ __qam_delext_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data) logrec.size += npad; } - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0) return (ret); @@ -1091,9 +1119,15 @@ __qam_delext_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data) memcpy(bp, &uinttmp, sizeof(uinttmp)); bp += sizeof(uinttmp); - if (lsn != NULL) + if (lsn != NULL) { + if (txnp != NULL) { + LOG *lp = dbenv->lg_handle->reginfo.primary; + if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret = + __log_check_page_lsn(dbenv, dbp, lsn) != 0)) + return (ret); + } memcpy(bp, lsn, sizeof(*lsn)); - else + } else memset(bp, 0, sizeof(*lsn)); bp += sizeof(*lsn); @@ -1120,12 +1154,13 @@ __qam_delext_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data) bp += data->size; } - DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + DB_ASSERT(dbenv, + (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); - if (is_durable || txnid == NULL) { + if (is_durable || txnp == NULL) { if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec, - flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) { - txnid->last_lsn = *rlsnp; + flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) { + *lsnp = *rlsnp; if (rlsnp != ret_lsnp) *ret_lsnp = *rlsnp; } @@ -1144,20 +1179,21 @@ __qam_delext_log(dbp, txnid, ret_lsnp, flags, lsn, pgno, indx, recno, data) #else ret = 0; #endif - STAILQ_INSERT_HEAD(&txnid->logs, lr, links); + STAILQ_INSERT_HEAD(&txnp->logs, lr, links); + F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY); LSN_NOT_LOGGED(*ret_lsnp); } #ifdef LOG_DIAGNOSTIC if (ret != 0) (void)__qam_delext_print(dbenv, - (DBT *)&logrec, ret_lsnp, NULL, NULL); + (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL); #endif #ifdef DIAGNOSTIC __os_free(dbenv, logrec.data); #else - if (is_durable || txnid == NULL) + if (is_durable || txnp == NULL) __os_free(dbenv, logrec.data); #endif return (ret); @@ -1181,13 +1217,14 @@ __qam_delext_read(dbenv, recbuf, argpp) sizeof(__qam_delext_args) + sizeof(DB_TXN), &argp)) != 0) return (ret); bp = recbuf; - argp->txnid = (DB_TXN *)&argp[1]; + argp->txnp = (DB_TXN *)&argp[1]; + memset(argp->txnp, 0, sizeof(DB_TXN)); memcpy(&argp->type, bp, sizeof(argp->type)); bp += sizeof(argp->type); - memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); - bp += sizeof(argp->txnid->txnid); + memcpy(&argp->txnp->txnid, bp, sizeof(argp->txnp->txnid)); + bp += sizeof(argp->txnp->txnid); memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); bp += sizeof(DB_LSN); diff --git a/db/qam/qam_autop.c b/db/qam/qam_autop.c index e9c122385..8a1f14f28 100644 --- a/db/qam/qam_autop.c +++ b/db/qam/qam_autop.c @@ -3,13 +3,6 @@ #include "db_config.h" #ifdef HAVE_QUEUE -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <string.h> -#endif - #include "db_int.h" #include "dbinc/crypto.h" #include "dbinc/db_page.h" @@ -34,20 +27,18 @@ __qam_incfirst_print(dbenv, dbtp, lsnp, notused2, notused3) __qam_incfirst_args *argp; int ret; - notused2 = DB_TXN_ABORT; + notused2 = DB_TXN_PRINT; notused3 = NULL; if ((ret = __qam_incfirst_read(dbenv, dbtp->data, &argp)) != 0) return (ret); (void)printf( - "[%lu][%lu]__qam_incfirst%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", - (u_long)lsnp->file, - (u_long)lsnp->offset, + "[%lu][%lu]__qam_incfirst%s: rec: %lu txnp %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, (u_long)lsnp->offset, (argp->type & DB_debug_FLAG) ? "_debug" : "", (u_long)argp->type, - (u_long)argp->txnid->txnid, - (u_long)argp->prev_lsn.file, - (u_long)argp->prev_lsn.offset); + (u_long)argp->txnp->txnid, + (u_long)argp->prev_lsn.file, (u_long)argp->prev_lsn.offset); (void)printf("\tfileid: %ld\n", (long)argp->fileid); (void)printf("\trecno: %lu\n", (u_long)argp->recno); (void)printf("\tmeta_pgno: %lu\n", (u_long)argp->meta_pgno); @@ -71,20 +62,18 @@ __qam_mvptr_print(dbenv, dbtp, lsnp, notused2, notused3) __qam_mvptr_args *argp; int ret; - notused2 = DB_TXN_ABORT; + notused2 = DB_TXN_PRINT; notused3 = NULL; if ((ret = __qam_mvptr_read(dbenv, dbtp->data, &argp)) != 0) return (ret); (void)printf( - "[%lu][%lu]__qam_mvptr%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", - (u_long)lsnp->file, - (u_long)lsnp->offset, + "[%lu][%lu]__qam_mvptr%s: rec: %lu txnp %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, (u_long)lsnp->offset, (argp->type & DB_debug_FLAG) ? "_debug" : "", (u_long)argp->type, - (u_long)argp->txnid->txnid, - (u_long)argp->prev_lsn.file, - (u_long)argp->prev_lsn.offset); + (u_long)argp->txnp->txnid, + (u_long)argp->prev_lsn.file, (u_long)argp->prev_lsn.offset); (void)printf("\topcode: %lu\n", (u_long)argp->opcode); (void)printf("\tfileid: %ld\n", (long)argp->fileid); (void)printf("\told_first: %lu\n", (u_long)argp->old_first); @@ -114,20 +103,18 @@ __qam_del_print(dbenv, dbtp, lsnp, notused2, notused3) __qam_del_args *argp; int ret; - notused2 = DB_TXN_ABORT; + notused2 = DB_TXN_PRINT; notused3 = NULL; if ((ret = __qam_del_read(dbenv, dbtp->data, &argp)) != 0) return (ret); (void)printf( - "[%lu][%lu]__qam_del%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", - (u_long)lsnp->file, - (u_long)lsnp->offset, + "[%lu][%lu]__qam_del%s: rec: %lu txnp %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, (u_long)lsnp->offset, (argp->type & DB_debug_FLAG) ? "_debug" : "", (u_long)argp->type, - (u_long)argp->txnid->txnid, - (u_long)argp->prev_lsn.file, - (u_long)argp->prev_lsn.offset); + (u_long)argp->txnp->txnid, + (u_long)argp->prev_lsn.file, (u_long)argp->prev_lsn.offset); (void)printf("\tfileid: %ld\n", (long)argp->fileid); (void)printf("\tlsn: [%lu][%lu]\n", (u_long)argp->lsn.file, (u_long)argp->lsn.offset); @@ -156,20 +143,18 @@ __qam_add_print(dbenv, dbtp, lsnp, notused2, notused3) int ch; int ret; - notused2 = DB_TXN_ABORT; + notused2 = DB_TXN_PRINT; notused3 = NULL; if ((ret = __qam_add_read(dbenv, dbtp->data, &argp)) != 0) return (ret); (void)printf( - "[%lu][%lu]__qam_add%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", - (u_long)lsnp->file, - (u_long)lsnp->offset, + "[%lu][%lu]__qam_add%s: rec: %lu txnp %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, (u_long)lsnp->offset, (argp->type & DB_debug_FLAG) ? "_debug" : "", (u_long)argp->type, - (u_long)argp->txnid->txnid, - (u_long)argp->prev_lsn.file, - (u_long)argp->prev_lsn.offset); + (u_long)argp->txnp->txnid, + (u_long)argp->prev_lsn.file, (u_long)argp->prev_lsn.offset); (void)printf("\tfileid: %ld\n", (long)argp->fileid); (void)printf("\tlsn: [%lu][%lu]\n", (u_long)argp->lsn.file, (u_long)argp->lsn.offset); @@ -211,20 +196,18 @@ __qam_delext_print(dbenv, dbtp, lsnp, notused2, notused3) int ch; int ret; - notused2 = DB_TXN_ABORT; + notused2 = DB_TXN_PRINT; notused3 = NULL; if ((ret = __qam_delext_read(dbenv, dbtp->data, &argp)) != 0) return (ret); (void)printf( - "[%lu][%lu]__qam_delext%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", - (u_long)lsnp->file, - (u_long)lsnp->offset, + "[%lu][%lu]__qam_delext%s: rec: %lu txnp %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, (u_long)lsnp->offset, (argp->type & DB_debug_FLAG) ? "_debug" : "", (u_long)argp->type, - (u_long)argp->txnid->txnid, - (u_long)argp->prev_lsn.file, - (u_long)argp->prev_lsn.offset); + (u_long)argp->txnp->txnid, + (u_long)argp->prev_lsn.file, (u_long)argp->prev_lsn.offset); (void)printf("\tfileid: %ld\n", (long)argp->fileid); (void)printf("\tlsn: [%lu][%lu]\n", (u_long)argp->lsn.file, (u_long)argp->lsn.offset); diff --git a/db/qam/qam_conv.c b/db/qam/qam_conv.c index c2b7d53a4..85fb47871 100644 --- a/db/qam/qam_conv.c +++ b/db/qam/qam_conv.c @@ -1,18 +1,14 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam_conv.c,v 11.17 2004/01/28 03:36:19 bostic Exp $ + * $Id: qam_conv.c,v 12.4 2006/08/24 14:46:24 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - #include "db_int.h" #include "dbinc/db_page.h" #include "dbinc/db_swap.h" diff --git a/db/qam/qam_files.c b/db/qam/qam_files.c index d3f040603..62ad8ed8a 100644 --- a/db/qam/qam_files.c +++ b/db/qam/qam_files.c @@ -1,25 +1,16 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam_files.c,v 1.88 2004/10/21 14:54:42 bostic Exp $ + * $Id: qam_files.c,v 12.17 2006/08/24 14:46:24 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#include <stdlib.h> - -#include <string.h> -#include <ctype.h> -#endif - #include "db_int.h" #include "dbinc/db_page.h" -#include "dbinc/db_shash.h" #include "dbinc/db_am.h" #include "dbinc/log.h" #include "dbinc/fop.h" @@ -35,13 +26,14 @@ * * Calculate which extent the page is in, open and create if necessary. * - * PUBLIC: int __qam_fprobe - * PUBLIC: __P((DB *, db_pgno_t, void *, qam_probe_mode, u_int32_t)); + * PUBLIC: int __qam_fprobe __P((DB *, db_pgno_t, + * PUBLIC: DB_TXN *, void *, qam_probe_mode, u_int32_t)); */ int -__qam_fprobe(dbp, pgno, addrp, mode, flags) +__qam_fprobe(dbp, pgno, txn, addrp, mode, flags) DB *dbp; db_pgno_t pgno; + DB_TXN *txn; void *addrp; qam_probe_mode mode; u_int32_t flags; @@ -51,8 +43,8 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags) MPFARRAY *array; QUEUE *qp; u_int8_t fid[DB_FILE_ID_LEN]; - u_int32_t extid, maxext, numext, offset, oldext, openflags; - char buf[MAXPATHLEN]; + u_int32_t i, extid, maxext, numext, lflags, offset, oldext, openflags; + char buf[DB_MAXPATHLEN]; int ftype, less, ret, t_ret; dbenv = dbp->dbenv; @@ -61,9 +53,17 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags) if (qp->page_ext == 0) { mpf = dbp->mpf; - return (mode == QAM_PROBE_GET ? - __memp_fget(mpf, &pgno, flags, addrp) : - __memp_fput(mpf, addrp, flags)); + switch (mode) { + case QAM_PROBE_GET: + return (__memp_fget(mpf, &pgno, txn, flags, addrp)); + case QAM_PROBE_PUT: + return (__memp_fput(mpf, addrp, flags)); + case QAM_PROBE_DIRTY: + return (__memp_dirty(mpf, addrp, txn, flags)); + case QAM_PROBE_MPF: + *(DB_MPOOLFILE **)addrp = mpf; + return (0); + } } mpf = NULL; @@ -73,7 +73,7 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags) * The file cannot go away because we must have a record locked * in that file. */ - MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); + MUTEX_LOCK(dbenv, dbp->mutex); extid = QAM_PAGE_EXTENT(dbp, pgno); /* Array1 will always be in use if array2 is in use. */ @@ -87,6 +87,7 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags) goto alloc; } +retry: if (extid < array->low_extent) { less = 1; offset = array->low_extent - extid; @@ -129,16 +130,12 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags) * sizeof(array->mpfarray[0])); offset = 0; } else if (less == 0 && offset == array->n_extent && - mode != QAM_PROBE_MPF && array->mpfarray[0].pinref == 0) { + (mode == QAM_PROBE_GET || mode == QAM_PROBE_PUT) && + array->mpfarray[0].pinref == 0) { /* * If this is at the end of the array and the file at * the beginning has a zero pin count we can close * the bottom extent and put this one at the end. - * TODO: If this process is "slow" then it might be - * appending but miss one or more extents. - * We could check to see if all the extents - * are unpinned and close them in the else - * clause below. */ mpf = array->mpfarray[0].mpf; if (mpf != NULL && (ret = __memp_fclose(mpf, 0)) != 0) @@ -160,18 +157,49 @@ __qam_fprobe(dbp, pgno, addrp, mode, flags) / (qp->page_ext * qp->rec_page); if (offset >= maxext/2) { array = &qp->array2; - DB_ASSERT(array->n_extent == 0); + DB_ASSERT(dbenv, array->n_extent == 0); oldext = 0; array->n_extent = 4; array->low_extent = extid; offset = 0; numext = 0; + } else if (array->mpfarray[0].pinref == 0) { + /* + * Check to see if there are extents marked + * for deletion at the beginning of the cache. + * If so close them so they will go away. + */ + for (i = 0; i < array->n_extent; i++) { + if (array->mpfarray[i].pinref != 0) + break; + mpf = array->mpfarray[i].mpf; + if (mpf == NULL) + continue; + (void)__memp_get_flags(mpf, &lflags); + if (!FLD_ISSET(lflags, DB_MPOOL_UNLINK)) + break; + + array->mpfarray[i].mpf = NULL; + if ((ret = __memp_fclose(mpf, 0)) != 0) + goto err; + } + if (i == 0) + goto increase; + memmove(&array->mpfarray[0], + &array->mpfarray[i], + (array->n_extent - i) * + sizeof(array->mpfarray[0])); + memset(&array->mpfarray[array->n_extent - i], + '\0', i * sizeof(array->mpfarray[0])); + array->low_extent += i; + array->hi_extent += i; + goto retry; } else { /* * Increase the size to at least include * the new one and double it. */ - array->n_extent += offset; +increase: array->n_extent += offset; array->n_extent <<= 2; } alloc: if ((ret = __os_realloc(dbenv, @@ -219,6 +247,7 @@ alloc: if ((ret = __os_realloc(dbenv, (void)__memp_set_pgcookie(mpf, &qp->pgcookie); (void)__memp_get_ftype(dbp->mpf, &ftype); (void)__memp_set_ftype(mpf, ftype); + (void)__memp_set_clear_len(mpf, dbp->pgsize); /* Set up the fileid for this extent. */ __qam_exid(dbp, fid, extid); @@ -255,25 +284,31 @@ alloc: if ((ret = __os_realloc(dbenv, (void)__memp_set_flags(mpf, DB_MPOOL_UNLINK, 0); err: - MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); + MUTEX_UNLOCK(dbenv, dbp->mutex); if (ret == 0) { - if (mode == QAM_PROBE_MPF) { - *(DB_MPOOLFILE **)addrp = mpf; - return (0); - } pgno--; pgno %= qp->page_ext; - if (mode == QAM_PROBE_GET) { - if ((ret = __memp_fget(mpf, &pgno, flags, addrp)) == 0) - return (ret); - } else + switch (mode) { + case QAM_PROBE_GET: + ret = __memp_fget(mpf, &pgno, txn, flags, addrp); + if (ret == 0) + return (0); + break; + case QAM_PROBE_PUT: ret = __memp_fput(mpf, addrp, flags); + break; + case QAM_PROBE_DIRTY: + return (__memp_dirty(mpf, addrp, txn, flags)); + case QAM_PROBE_MPF: + *(DB_MPOOLFILE **)addrp = mpf; + return (0); + } - MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); + MUTEX_LOCK(dbenv, dbp->mutex); /* Recalculate because we dropped the lock. */ offset = extid - array->low_extent; - DB_ASSERT(array->mpfarray[offset].pinref > 0); + DB_ASSERT(dbenv, array->mpfarray[offset].pinref > 0); if (--array->mpfarray[offset].pinref == 0 && (mode == QAM_PROBE_GET || ret == 0)) { /* Check to see if this file will be unlinked. */ @@ -285,7 +320,7 @@ err: ret = t_ret; } } - MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); + MUTEX_UNLOCK(dbenv, dbp->mutex); } return (ret); } @@ -314,7 +349,7 @@ __qam_fclose(dbp, pgnoaddr) dbenv = dbp->dbenv; qp = (QUEUE *)dbp->q_internal; - MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); + MUTEX_LOCK(dbenv, dbp->mutex); extid = QAM_PAGE_EXTENT(dbp, pgnoaddr); array = &qp->array1; @@ -322,7 +357,8 @@ __qam_fclose(dbp, pgnoaddr) array = &qp->array2; offset = extid - array->low_extent; - DB_ASSERT(extid >= array->low_extent && offset < array->n_extent); + DB_ASSERT(dbenv, + extid >= array->low_extent && offset < array->n_extent); /* If other threads are still using this file, leave it. */ if (array->mpfarray[offset].pinref != 0) @@ -333,7 +369,7 @@ __qam_fclose(dbp, pgnoaddr) ret = __memp_fclose(mpf, 0); done: - MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); + MUTEX_UNLOCK(dbenv, dbp->mutex); return (ret); } @@ -356,16 +392,13 @@ __qam_fremove(dbp, pgnoaddr) MPFARRAY *array; QUEUE *qp; u_int32_t extid, offset; -#ifdef CONFIG_TEST - char buf[MAXPATHLEN], *real_name; -#endif int ret; qp = (QUEUE *)dbp->q_internal; dbenv = dbp->dbenv; ret = 0; - MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); + MUTEX_LOCK(dbenv, dbp->mutex); extid = QAM_PAGE_EXTENT(dbp, pgnoaddr); array = &qp->array1; @@ -373,16 +406,14 @@ __qam_fremove(dbp, pgnoaddr) array = &qp->array2; offset = extid - array->low_extent; - DB_ASSERT(extid >= array->low_extent && offset < array->n_extent); + DB_ASSERT(dbenv, + extid >= array->low_extent && offset < array->n_extent); -#ifdef CONFIG_TEST - real_name = NULL; - /* Find the real name of the file. */ - QAM_EXNAME(qp, extid, buf, sizeof(buf)); - if ((ret = __db_appname(dbenv, - DB_APP_DATA, buf, 0, NULL, &real_name)) != 0) + mpf = array->mpfarray[offset].mpf; + /* This extent my already be marked for delete and closed. */ + if (mpf == NULL) goto err; -#endif + /* * The log must be flushed before the file is deleted. We depend on * the log record of the last delete to recreate the file if we crash. @@ -390,7 +421,6 @@ __qam_fremove(dbp, pgnoaddr) if (LOGGING_ON(dbenv) && (ret = __log_flush(dbenv, NULL)) != 0) goto err; - mpf = array->mpfarray[offset].mpf; (void)__memp_set_flags(mpf, DB_MPOOL_UNLINK, 1); /* Someone could be real slow, let them close it down. */ if (array->mpfarray[offset].pinref != 0) @@ -416,12 +446,8 @@ __qam_fremove(dbp, pgnoaddr) array->hi_extent--; } -err: - MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); -#ifdef CONFIG_TEST - if (real_name != NULL) - __os_free(dbenv, real_name); -#endif +err: MUTEX_UNLOCK(dbenv, dbp->mutex); + return (ret); } @@ -491,7 +517,7 @@ __qam_gen_filelist(dbp, filelistp) /* Find out the first and last record numbers in the database. */ i = PGNO_BASE_MD; - if ((ret = __memp_fget(mpf, &i, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &i, NULL, 0, &meta)) != 0) return (ret); current = meta->cur_recno; @@ -536,15 +562,15 @@ again: first += stop % rec_extent; for (i = first; i >= first && i <= stop; i += rec_extent) { - if ((ret = __qam_fprobe(dbp, QAM_RECNO_PAGE(dbp, i), &fp->mpf, - QAM_PROBE_MPF, 0)) != 0) { + if ((ret = __qam_fprobe(dbp, QAM_RECNO_PAGE(dbp, i), NULL, + &fp->mpf, QAM_PROBE_MPF, 0)) != 0) { if (ret == ENOENT) continue; return (ret); } fp->id = QAM_RECNO_EXTENT(dbp, i); fp++; - DB_ASSERT((size_t)(fp - *filelistp) < extent_cnt); + DB_ASSERT(dbenv, (size_t)(fp - *filelistp) < extent_cnt); } if (current < first) { @@ -571,7 +597,7 @@ __qam_extent_names(dbenv, name, namelistp) QUEUE_FILELIST *filelist, *fp; size_t len; int cnt, ret, t_ret; - char buf[MAXPATHLEN], **cp, *freep; + char buf[DB_MAXPATHLEN], **cp, *freep; *namelistp = NULL; filelist = NULL; @@ -579,7 +605,7 @@ __qam_extent_names(dbenv, name, namelistp) return (ret); if ((ret = __db_open(dbp, NULL, name, NULL, DB_QUEUE, DB_RDONLY, 0, PGNO_BASE_MD)) != 0) - return (ret); + goto done; qp = dbp->q_internal; if (qp->page_ext == 0) goto done; @@ -677,7 +703,7 @@ int __qam_nameop(dbp, txn, newname, op) u_int8_t fid[DB_FILE_ID_LEN]; u_int32_t exid; int cnt, i, ret, t_ret; - char buf[MAXPATHLEN], nbuf[MAXPATHLEN], sepsave; + char buf[DB_MAXPATHLEN], nbuf[DB_MAXPATHLEN], sepsave; char *endname, *endpath, *exname, *fullname, **names; char *ndir, *namep, *new, *cp; @@ -769,7 +795,7 @@ int __qam_nameop(dbp, txn, newname, op) continue; /* Make sure we have all numbers. foo.db vs. foo.db.0. */ for (cp = &names[i][len]; *cp != '\0'; cp++) - if (!isdigit(*cp)) + if (!isdigit((int)*cp)) break; if (*cp != '\0') continue; @@ -786,7 +812,8 @@ int __qam_nameop(dbp, txn, newname, op) snprintf(exname, exlen, "%s%s", fullname, names[i] + len); if ((t_ret = __memp_nameop(dbenv, - fid, NULL, exname, NULL)) != 0 && ret == 0) + fid, NULL, exname, NULL, + F_ISSET(dbp, DB_AM_INMEM))) != 0 && ret == 0) ret = t_ret; break; diff --git a/db/qam/qam_method.c b/db/qam/qam_method.c index e3526fa3c..ff5129517 100644 --- a/db/qam/qam_method.c +++ b/db/qam/qam_method.c @@ -1,21 +1,16 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam_method.c,v 11.84 2004/10/14 18:09:32 bostic Exp $ + * $Id: qam_method.c,v 12.8 2006/08/24 14:46:24 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - #include "db_int.h" #include "dbinc/db_page.h" -#include "dbinc/db_shash.h" #include "dbinc/db_am.h" #include "dbinc/lock.h" #include "dbinc/mp.h" @@ -130,7 +125,7 @@ __qam_set_extentsize(dbp, extentsize) DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_extentsize"); if (extentsize < 1) { - __db_err(dbp->dbenv, "Extent size must be at least 1"); + __db_errx(dbp->dbenv, "Extent size must be at least 1"); return (EINVAL); } @@ -163,7 +158,7 @@ __queue_pageinfo(dbp, firstp, lastp, emptyp, prpage, flags) /* Find out the page number of the last page in the database. */ i = PGNO_BASE_MD; - if ((ret = __memp_fget(mpf, &i, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &i, NULL, 0, &meta)) != 0) return (ret); first = QAM_RECNO_PAGE(dbp, meta->first_recno); @@ -222,7 +217,7 @@ __db_prqueue(dbp, flags) /* Dump each page. */ begin: for (; i <= stop; ++i) { - if ((ret = __qam_fget(dbp, &i, 0, &h)) != 0) { + if ((ret = __qam_fget(dbp, &i, NULL, 0, &h)) != 0) { pg_ext = ((QUEUE *)dbp->q_internal)->page_ext; if (pg_ext == 0) { if (ret == DB_PAGE_NOTFOUND && first == last) @@ -302,8 +297,8 @@ __qam_rr(dbp, txn, name, subdb, newname, op) PANIC_CHECK(dbenv); - if (subdb != NULL) { - __db_err(dbenv, + if (subdb != NULL && name != NULL) { + __db_errx(dbenv, "Queue does not support multiple databases per file"); return (EINVAL); } diff --git a/db/qam/qam_open.c b/db/qam/qam_open.c index 595d74dac..75df8e41c 100644 --- a/db/qam/qam_open.c +++ b/db/qam/qam_open.c @@ -1,24 +1,17 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam_open.c,v 11.68 2004/02/27 12:38:31 bostic Exp $ + * $Id: qam_open.c,v 12.11 2006/08/24 14:46:24 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - #include "db_int.h" #include "dbinc/crypto.h" #include "dbinc/db_page.h" -#include "dbinc/db_shash.h" #include "dbinc/db_swap.h" #include "dbinc/db_am.h" #include "dbinc/lock.h" @@ -58,11 +51,17 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags) qmeta = NULL; if (name == NULL && t->page_ext != 0) { - __db_err(dbenv, + __db_errx(dbenv, "Extent size may not be specified for in-memory queue database"); return (EINVAL); } + if (MULTIVERSION(dbp)) { + __db_errx(dbenv, + "Multiversion queue databases are not supported"); + return (EINVAL); + } + /* Initialize the remaining fields/methods of the DB. */ dbp->db_am_remove = __qam_remove; dbp->db_am_rename = __qam_rename; @@ -86,12 +85,12 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags) if ((ret = __db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0) goto err; - if ((ret = __memp_fget(mpf, &base_pgno, 0, &qmeta)) != 0) + if ((ret = __memp_fget(mpf, &base_pgno, dbc->txn, 0, &qmeta)) != 0) goto err; /* If the magic number is incorrect, that's a fatal error. */ if (qmeta->dbmeta.magic != DB_QAMMAGIC) { - __db_err(dbenv, "%s: unexpected file type or format", name); + __db_errx(dbenv, "%s: unexpected file type or format", name); ret = EINVAL; goto err; } @@ -103,7 +102,7 @@ __qam_open(dbp, txn, name, base_pgno, mode, flags) goto err; if (mode == 0) - mode = __db_omode("rwrw--"); + mode = __db_omode("rw-rw----"); t->mode = mode; t->re_pad = qmeta->re_pad; t->re_len = qmeta->re_len; @@ -188,7 +187,7 @@ __qam_metachk(dbp, name, qmeta) switch (vers) { case 1: case 2: - __db_err(dbenv, + __db_errx(dbenv, "%s: queue version %lu requires a version upgrade", name, (u_long)vers); return (DB_OLD_VERSION); @@ -196,7 +195,7 @@ __qam_metachk(dbp, name, qmeta) case 4: break; default: - __db_err(dbenv, + __db_errx(dbenv, "%s: unsupported qam version: %lu", name, (u_long)vers); return (EINVAL); } @@ -233,8 +232,10 @@ __qam_init_meta(dbp, meta) DB *dbp; QMETA *meta; { + DB_ENV *dbenv; QUEUE *t; + dbenv = dbp->dbenv; t = dbp->q_internal; memset(meta, 0, sizeof(QMETA)); @@ -248,8 +249,8 @@ __qam_init_meta(dbp, meta) FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM); if (F_ISSET(dbp, DB_AM_ENCRYPT)) { meta->dbmeta.encrypt_alg = - ((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg; - DB_ASSERT(meta->dbmeta.encrypt_alg != 0); + ((DB_CIPHER *)dbenv->crypto_handle)->alg; + DB_ASSERT(dbenv, meta->dbmeta.encrypt_alg != 0); meta->crypto_magic = meta->dbmeta.magic; } meta->dbmeta.type = P_QAMMETA; @@ -264,7 +265,7 @@ __qam_init_meta(dbp, meta) /* Verify that we can fit at least one record per page. */ if (QAM_RECNO_PER_PAGE(dbp) < 1) { - __db_err(dbp->dbenv, + __db_errx(dbenv, "Record size of %lu too large for page size of %lu", (u_long)t->re_len, (u_long)dbp->pgsize); return (EINVAL); @@ -308,11 +309,12 @@ __qam_new_file(dbp, txn, fhp, name) /* Build meta-data page. */ - if (name == NULL) { + if (F_ISSET(dbp, DB_AM_INMEM)) { pgno = PGNO_BASE_MD; - ret = __memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &meta); + ret = __memp_fget(mpf, &pgno, txn, + DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &meta); } else { - ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf); + ret = __os_calloc(dbenv, 1, dbp->pgsize, &buf); meta = (QMETA *)buf; } if (ret != 0) @@ -321,9 +323,12 @@ __qam_new_file(dbp, txn, fhp, name) if ((ret = __qam_init_meta(dbp, meta)) != 0) goto err; - if (name == NULL) - ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY); - else { + if (F_ISSET(dbp, DB_AM_INMEM)) { + if ((ret = __db_log_page(dbp, + txn, &meta->dbmeta.lsn, pgno, (PAGE *)meta)) != 0) + goto err; + ret = __memp_fput(mpf, meta, 0); + } else { pginfo.db_pagesize = dbp->pgsize; pginfo.flags = F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP)); diff --git a/db/qam/qam_rec.c b/db/qam/qam_rec.c index e92141ddd..88a7bf261 100644 --- a/db/qam/qam_rec.c +++ b/db/qam/qam_rec.c @@ -1,28 +1,42 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam_rec.c,v 11.78 2004/05/11 14:04:51 bostic Exp $ + * $Id: qam_rec.c,v 12.20 2006/09/09 14:28:24 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/db_am.h" #include "dbinc/lock.h" #include "dbinc/log.h" #include "dbinc/mp.h" #include "dbinc/qam.h" +#include "dbinc/txn.h" + +/* + * LSNs in queue data pages are advisory. They do not have to be accurate + * as all operations are idempotent on records. They should not be rolled + * forward during recovery as committed transaction may obscure updates from + * an incomplete transaction that updates the same page. The incomplete + * transaction may be completed during a later hot backup cycle. + */ + +/* Determine if we are restoring prepared transactions from __txn_recover. */ +#define IS_IN_RESTORE(dbenv) \ + (((DB_TXNREGION *) \ + (dbenv)->tx_handle->reginfo.primary)->stat.st_nrestores != 0) + +/* Queue version of REC_DIRTY -- needs to probe the correct file. */ +#define QAM_DIRTY(dbp, pgno, pagep) \ + if ((ret = __qam_dirty((dbp), pgno, pagep, NULL, 0)) != 0) { \ + ret = __db_pgerr((dbp), (pgno), ret); \ + goto out; \ + } /* * __qam_incfirst_recover -- @@ -49,20 +63,23 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info) QUEUE_CURSOR *cp; db_pgno_t metapg; u_int32_t rec_ext; - int exact, modified, ret, t_ret; + int exact, ret, t_ret; + LOCK_INIT(lock); + COMPQUIET(meta, NULL); REC_PRINT(__qam_incfirst_print); - REC_INTRO(__qam_incfirst_read, 1); + REC_INTRO(__qam_incfirst_read, 1, 1); metapg = ((QUEUE *)file_dbp->q_internal)->q_meta; if ((ret = __db_lget(dbc, LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) goto done; - if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapg, NULL, + 0, &meta)) != 0) { if (DB_REDO(op)) { - if ((ret = __memp_fget(mpf, - &metapg, DB_MPOOL_CREATE, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapg, NULL, + DB_MPOOL_CREATE, &meta)) != 0) { (void)__LPUT(dbc, lock); goto out; } @@ -75,8 +92,6 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info) } } - modified = 0; - /* * Only move first_recno backwards so we pick up the aborted delete. * When going forward we need to be careful since @@ -84,21 +99,21 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info) */ if (DB_UNDO(op)) { if (QAM_BEFORE_FIRST(meta, argp->recno)) { + REC_DIRTY(mpf, &meta); meta->first_recno = argp->recno; - modified = 1; } trunc_lsn = ((DB_TXNHEAD *)info)->trunc_lsn; /* if we are truncating, update the LSN */ if (!IS_ZERO_LSN(trunc_lsn) && - log_compare(&LSN(meta), &trunc_lsn) > 0) { + LOG_COMPARE(&LSN(meta), &trunc_lsn) > 0) { + REC_DIRTY(mpf, &meta); LSN(meta) = trunc_lsn; - modified = 1; } } else { - if (log_compare(&LSN(meta), lsnp) < 0) { + if (LOG_COMPARE(&LSN(meta), lsnp) < 0) { + REC_DIRTY(mpf, &meta); LSN(meta) = *lsnp; - modified = 1; } if (meta->page_ext == 0) rec_ext = 0; @@ -110,7 +125,7 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info) while (meta->first_recno != meta->cur_recno && !QAM_BEFORE_FIRST(meta, argp->recno + 1)) { if ((ret = __qam_position(dbc, - &meta->first_recno, QAM_READ, &exact)) != 0) + &meta->first_recno, DB_LOCK_READ, 0, &exact)) != 0) goto err; if (cp->page != NULL && (ret = __qam_fput(file_dbp, cp->pgno, cp->page, 0)) != 0) @@ -123,14 +138,14 @@ __qam_incfirst_recover(dbenv, dbtp, lsnp, op, info) if ((ret = __qam_fremove(file_dbp, cp->pgno)) != 0) goto err; + REC_DIRTY(mpf, &meta); meta->first_recno++; if (meta->first_recno == RECNO_OOB) meta->first_recno++; - modified = 1; } } - ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0); + ret = __memp_fput(mpf, meta, 0); if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) ret = t_ret; if (ret != 0) @@ -169,21 +184,23 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info) DB_LOCK lock; DB_MPOOLFILE *mpf; QMETA *meta; + QUEUE_CURSOR *cp; db_pgno_t metapg; - int cmp_n, cmp_p, modified, ret; + int cmp_n, cmp_p, exact, ret; REC_PRINT(__qam_mvptr_print); - REC_INTRO(__qam_mvptr_read, 1); + REC_INTRO(__qam_mvptr_read, 1, 1); metapg = ((QUEUE *)file_dbp->q_internal)->q_meta; if ((ret = __db_lget(dbc, LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) goto done; - if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapg, NULL, + 0, &meta)) != 0) { if (DB_REDO(op)) { - if ((ret = __memp_fget(mpf, - &metapg, DB_MPOOL_CREATE, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapg, NULL, + DB_MPOOL_CREATE, &meta)) != 0) { (void)__LPUT(dbc, lock); goto out; } @@ -196,43 +213,75 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info) } } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(meta)); - cmp_p = log_compare(&LSN(meta), &argp->metalsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(meta)); + cmp_p = LOG_COMPARE(&LSN(meta), &argp->metalsn); /* * Under normal circumstances, we never undo a movement of one of * the pointers. Just move them along regardless of abort/commit. + * When going forward we need to verify that this is really where + * the pointer belongs. A transaction may roll back and reinsert + * a record that was missing at the time of this action. * * If we're undoing a truncate, we need to reset the pointers to * their state before the truncate. */ if (DB_UNDO(op)) { if ((argp->opcode & QAM_TRUNCATE) && cmp_n <= 0) { + REC_DIRTY(mpf, &meta); meta->first_recno = argp->old_first; meta->cur_recno = argp->old_cur; LSN(meta) = argp->metalsn; - modified = 1; } /* If the page lsn is beyond the truncate point, move it back */ trunc_lsn = ((DB_TXNHEAD *)info)->trunc_lsn; if (!IS_ZERO_LSN(trunc_lsn) && - log_compare(&trunc_lsn, &LSN(meta)) < 0) { + LOG_COMPARE(&trunc_lsn, &LSN(meta)) < 0) { + REC_DIRTY(mpf, &meta); LSN(meta) = argp->metalsn; - modified = 1; } } else if (op == DB_TXN_APPLY || cmp_p == 0) { - if (argp->opcode & QAM_SETFIRST) - meta->first_recno = argp->new_first; + REC_DIRTY(mpf, &meta); + cp = (QUEUE_CURSOR *)dbc->internal; + if ((argp->opcode & QAM_SETFIRST) && + meta->first_recno == argp->old_first) { + if (argp->old_first > argp->new_first) + meta->first_recno = argp->new_first; + else { + if ((ret = __qam_position(dbc, + &meta->first_recno, DB_LOCK_READ, 0, + &exact)) != 0) + goto err; + if (!exact) + meta->first_recno = argp->new_first; + if (cp->page != NULL && + (ret = __qam_fput(file_dbp, + cp->pgno, cp->page, 0)) != 0) + goto err; + } + } - if (argp->opcode & QAM_SETCUR) - meta->cur_recno = argp->new_cur; + if ((argp->opcode & QAM_SETCUR) && + meta->cur_recno == argp->old_cur) { + if (argp->old_cur < argp->new_cur) + meta->cur_recno = argp->new_cur; + else { + if ((ret = __qam_position(dbc, &meta->cur_recno, + DB_LOCK_READ, 0, &exact)) != 0) + goto err; + if (!exact) + meta->cur_recno = argp->new_cur; + if (cp->page != NULL && + (ret = __qam_fput(file_dbp, + cp->pgno, cp->page, 0)) != 0) + goto err; + } + } - modified = 1; meta->dbmeta.lsn = *lsnp; } - if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, meta, 0)) != 0) goto out; if ((ret = __LPUT(dbc, lock)) != 0) @@ -241,6 +290,11 @@ __qam_mvptr_recover(dbenv, dbtp, lsnp, op, info) done: *lsnp = argp->prev_lsn; ret = 0; + if (0) { +err: (void)__memp_fput(mpf, meta, 0); + (void)__LPUT(dbc, lock); + } + out: REC_CLOSE; } @@ -269,24 +323,24 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info) QMETA *meta; QPAGE *pagep; db_pgno_t metapg; - int cmp_n, modified, ret, t_ret; + int cmp_n, ret, t_ret; COMPQUIET(info, NULL); + COMPQUIET(pagep, NULL); REC_PRINT(__qam_del_print); - REC_INTRO(__qam_del_read, 1); + REC_INTRO(__qam_del_read, 1, 1); - if ((ret = __qam_fget(file_dbp, - &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) + if ((ret = __qam_fget(file_dbp, &argp->pgno, NULL, + DB_MPOOL_CREATE, &pagep)) != 0) goto out; - modified = 0; if (pagep->pgno == PGNO_INVALID) { + QAM_DIRTY(file_dbp, argp->pgno, &pagep); pagep->pgno = argp->pgno; pagep->type = P_QAMDATA; - modified = 1; } - cmp_n = log_compare(lsnp, &LSN(pagep)); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); if (DB_UNDO(op)) { /* make sure first is behind us */ @@ -294,7 +348,8 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info) if ((ret = __db_lget(dbc, LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) goto err; - if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapg, NULL, + DB_MPOOL_EDIT, &meta)) != 0) { (void)__LPUT(dbc, lock); goto err; } @@ -303,8 +358,9 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info) (meta->first_recno <= meta->cur_recno || meta->first_recno - argp->recno < argp->recno - meta->cur_recno))) { + REC_DIRTY(mpf, &meta); meta->first_recno = argp->recno; - ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY); + ret = __memp_fput(mpf, meta, 0); } else ret = __memp_fput(mpf, meta, 0); if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) @@ -313,6 +369,7 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info) goto err; /* Need to undo delete - mark the record as present */ + QAM_DIRTY(file_dbp, pagep->pgno, &pagep); qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx); F_SET(qp, QAM_VALID); @@ -323,19 +380,28 @@ __qam_del_recover(dbenv, dbtp, lsnp, op, info) * foul up a concurrent put. Having too late an LSN * is harmless in queue except when we're determining * what we need to roll forward during recovery. [#2588] + * If we are aborting a restored transaction then it + * might get rolled forward later so the LSN needs to + * be correct in that case too. [#12181] */ - if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0) + if (cmp_n <= 0 && + (op == DB_TXN_BACKWARD_ROLL || IS_IN_RESTORE(dbenv))) LSN(pagep) = argp->lsn; - modified = 1; } else if (op == DB_TXN_APPLY || (cmp_n > 0 && DB_REDO(op))) { /* Need to redo delete - clear the valid bit */ + QAM_DIRTY(file_dbp, pagep->pgno, &pagep); qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx); F_CLR(qp, QAM_VALID); - LSN(pagep) = *lsnp; - modified = 1; + /* + * We only move the LSN forward during replication. + * During recovery we could obscure an update from + * a partially completed transaction while processing + * a hot backup. [#13823] + */ + if (op == DB_TXN_APPLY) + LSN(pagep) = *lsnp; } - if ((ret = __qam_fput(file_dbp, - argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __qam_fput(file_dbp, argp->pgno, pagep, 0)) != 0) goto out; done: *lsnp = argp->prev_lsn; @@ -371,34 +437,31 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info) QMETA *meta; QPAGE *pagep; db_pgno_t metapg; - int cmp_n, modified, ret, t_ret; + int cmp_n, ret, t_ret; COMPQUIET(info, NULL); + COMPQUIET(pagep, NULL); REC_PRINT(__qam_delext_print); - REC_INTRO(__qam_delext_read, 1); + REC_INTRO(__qam_delext_read, 1, 1); - if ((ret = __qam_fget(file_dbp, &argp->pgno, 0, &pagep)) != 0) { - if (ret != DB_PAGE_NOTFOUND && ret != ENOENT) - goto out; + if ((ret = __qam_fget(file_dbp, &argp->pgno, NULL, + DB_REDO(op) ? 0 : DB_MPOOL_CREATE, &pagep)) != 0) { /* * If we are redoing a delete and the page is not there * we are done. */ - if (DB_REDO(op)) + if (DB_REDO(op) && (ret == DB_PAGE_NOTFOUND || ret == ENOENT)) goto done; - if ((ret = __qam_fget(file_dbp, - &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; + goto out; } - modified = 0; if (pagep->pgno == PGNO_INVALID) { + QAM_DIRTY(file_dbp, argp->pgno, &pagep); pagep->pgno = argp->pgno; pagep->type = P_QAMDATA; - modified = 1; } - cmp_n = log_compare(lsnp, &LSN(pagep)); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); if (DB_UNDO(op)) { /* make sure first is behind us */ @@ -406,7 +469,8 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info) if ((ret = __db_lget(dbc, LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) goto err; - if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &metapg, NULL, + DB_MPOOL_EDIT, &meta)) != 0) { (void)__LPUT(dbc, lock); goto err; } @@ -416,7 +480,7 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info) meta->first_recno - argp->recno < argp->recno - meta->cur_recno))) { meta->first_recno = argp->recno; - ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY); + ret = __memp_fput(mpf, meta, 0); } else ret = __memp_fput(mpf, meta, 0); if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) @@ -424,6 +488,7 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info) if (ret != 0) goto err; + QAM_DIRTY(file_dbp, pagep->pgno, &pagep); if ((ret = __qam_pitem(dbc, pagep, argp->indx, argp->recno, &argp->data)) != 0) goto err; @@ -436,18 +501,24 @@ __qam_delext_recover(dbenv, dbtp, lsnp, op, info) * is harmless in queue except when we're determining * what we need to roll forward during recovery. [#2588] */ - if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0) + if (cmp_n <= 0 && + (op == DB_TXN_BACKWARD_ROLL || IS_IN_RESTORE(dbenv))) LSN(pagep) = argp->lsn; - modified = 1; } else if (op == DB_TXN_APPLY || (cmp_n > 0 && DB_REDO(op))) { + QAM_DIRTY(file_dbp, pagep->pgno, &pagep); /* Need to redo delete - clear the valid bit */ qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx); F_CLR(qp, QAM_VALID); - LSN(pagep) = *lsnp; - modified = 1; + /* + * We only move the LSN forward during replication. + * During recovery we could obscure an update from + * a partially completed transaction while processing + * a hot backup. [#13823] + */ + if (op == DB_TXN_APPLY) + LSN(pagep) = *lsnp; } - if ((ret = __qam_fput(file_dbp, - argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __qam_fput(file_dbp, argp->pgno, pagep, 0)) != 0) goto out; done: *lsnp = argp->prev_lsn; @@ -482,62 +553,65 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info) QMETA *meta; QPAGE *pagep; db_pgno_t metapg; - int cmp_n, meta_dirty, modified, ret; + int cmp_n, ret; COMPQUIET(info, NULL); + COMPQUIET(pagep, NULL); REC_PRINT(__qam_add_print); - REC_INTRO(__qam_add_read, 1); + REC_INTRO(__qam_add_read, 1, 1); - modified = 0; - if ((ret = __qam_fget(file_dbp, &argp->pgno, 0, &pagep)) != 0) { - if (ret != DB_PAGE_NOTFOUND && ret != ENOENT) - goto out; + if ((ret = __qam_fget(file_dbp, &argp->pgno, NULL, + DB_UNDO(op) ? 0 : DB_MPOOL_CREATE, &pagep)) != 0) { /* * If we are undoing an append and the page is not there * we are done. */ - if (DB_UNDO(op)) + if (DB_UNDO(op) && (ret == DB_PAGE_NOTFOUND || ret == ENOENT)) goto done; - if ((ret = __qam_fget(file_dbp, - &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; + goto out; } if (pagep->pgno == PGNO_INVALID) { + QAM_DIRTY(file_dbp, argp->pgno, &pagep); pagep->pgno = argp->pgno; pagep->type = P_QAMDATA; - modified = 1; } - cmp_n = log_compare(lsnp, &LSN(pagep)); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); if (DB_REDO(op)) { /* Fix meta-data page. */ metapg = ((QUEUE *)file_dbp->q_internal)->q_meta; - if ((ret = __memp_fget(mpf, &metapg, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &metapg, NULL, + 0, &meta)) != 0) goto err; - meta_dirty = 0; if (QAM_BEFORE_FIRST(meta, argp->recno)) { + REC_DIRTY(mpf, &meta); meta->first_recno = argp->recno; - meta_dirty = 1; } if (argp->recno == meta->cur_recno || - QAM_AFTER_CURRENT(meta, argp->recno)) { + QAM_AFTER_CURRENT(meta, argp->recno)) { + REC_DIRTY(mpf, &meta); meta->cur_recno = argp->recno + 1; - meta_dirty = 1; } - if ((ret = __memp_fput(mpf, - meta, meta_dirty? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, meta, 0)) != 0) goto err; /* Now update the actual page if necessary. */ if (op == DB_TXN_APPLY || cmp_n > 0) { + QAM_DIRTY(file_dbp, pagep->pgno, &pagep); /* Need to redo add - put the record on page */ if ((ret = __qam_pitem(dbc, pagep, argp->indx, argp->recno, &argp->data)) != 0) goto err; - LSN(pagep) = *lsnp; - modified = 1; + /* + * We only move the LSN forward during replication. + * During recovery we could obscure an update from + * a partially completed transaction while processing + * a hot backup. [#13823] + */ + if (op == DB_TXN_APPLY) + LSN(pagep) = *lsnp; } } else if (DB_UNDO(op)) { /* @@ -546,6 +620,7 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info) * Otherwise just clear the valid bit */ if (argp->olddata.size != 0) { + QAM_DIRTY(file_dbp, pagep->pgno, &pagep); if ((ret = __qam_pitem(dbc, pagep, argp->indx, argp->recno, &argp->olddata)) != 0) goto err; @@ -555,11 +630,10 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info) file_dbp, pagep, argp->indx); F_CLR(qp, QAM_VALID); } - modified = 1; } else { + QAM_DIRTY(file_dbp, pagep->pgno, &pagep); qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx); qp->flags = 0; - modified = 1; } /* @@ -570,12 +644,13 @@ __qam_add_recover(dbenv, dbtp, lsnp, op, info) * is harmless in queue except when we're determining * what we need to roll forward during recovery. [#2588] */ - if (op == DB_TXN_BACKWARD_ROLL && cmp_n <= 0) + if (cmp_n <= 0 && + (op == DB_TXN_BACKWARD_ROLL || IS_IN_RESTORE(dbenv))) LSN(pagep) = argp->lsn; } if ((ret = __qam_fput(file_dbp, - argp->pgno, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + argp->pgno, pagep, 0)) != 0) goto out; done: *lsnp = argp->prev_lsn; diff --git a/db/qam/qam_stat.c b/db/qam/qam_stat.c index c5264bd01..067555a57 100644 --- a/db/qam/qam_stat.c +++ b/db/qam/qam_stat.c @@ -1,24 +1,16 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam_stat.c,v 11.47 2004/09/22 16:29:47 bostic Exp $ + * $Id: qam_stat.c,v 12.8 2006/08/24 14:46:24 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <string.h> -#endif - #include "db_int.h" #include "dbinc/db_page.h" -#include "dbinc/db_shash.h" #include "dbinc/db_am.h" #include "dbinc/lock.h" #include "dbinc/mp.h" @@ -70,10 +62,10 @@ __qam_stat(dbc, spp, flags) /* Determine the last page of the database. */ if ((ret = __db_lget(dbc, 0, t->q_meta, DB_LOCK_READ, 0, &lock)) != 0) goto err; - if ((ret = __memp_fget(mpf, &t->q_meta, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &t->q_meta, dbc->txn, 0, &meta)) != 0) goto err; - if (flags == DB_FAST_STAT || flags == DB_CACHED_COUNTS) { + if (flags == DB_FAST_STAT) { sp->qs_nkeys = meta->dbmeta.key_count; sp->qs_ndata = meta->dbmeta.record_count; goto meta_only; @@ -102,7 +94,7 @@ begin: if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0) goto err; - ret = __qam_fget(dbp, &pgno, 0, &h); + ret = __qam_fget(dbp, &pgno, dbc->txn, 0, &h); if (ret == ENOENT) { pgno += pg_ext - 1; continue; @@ -153,7 +145,8 @@ begin: 0, t->q_meta, F_ISSET(dbp, DB_AM_RDONLY) ? DB_LOCK_READ : DB_LOCK_WRITE, 0, &lock)) != 0) goto err; - if ((ret = __memp_fget(mpf, &t->q_meta, 0, &meta)) != 0) + if ((ret = __memp_fget(mpf, &t->q_meta, dbc->txn, + F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY, &meta)) != 0) goto err; if (!F_ISSET(dbp, DB_AM_RDONLY)) @@ -174,8 +167,7 @@ meta_only: sp->qs_cur_recno = meta->cur_recno; /* Discard the meta-data page. */ - ret = __memp_fput(mpf, - meta, F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY); + ret = __memp_fput(mpf, meta, 0); if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) ret = t_ret; if (ret != 0) @@ -213,7 +205,7 @@ __qam_stat_print(dbc, flags) dbp = dbc->dbp; dbenv = dbp->dbenv; - if ((ret = __qam_stat(dbc, &sp, 0)) != 0) + if ((ret = __qam_stat(dbc, &sp, LF_ISSET(DB_FAST_STAT))) != 0) return (ret); if (LF_ISSET(DB_STAT_ALL)) { diff --git a/db/qam/qam_stub.c b/db/qam/qam_stub.c index 1c22aaa52..7b02c8ef1 100644 --- a/db/qam/qam_stub.c +++ b/db/qam/qam_stub.c @@ -1,18 +1,14 @@ /*- * 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. * - * $Id: qam_stub.c,v 1.12 2004/06/14 15:23:33 bostic Exp $ + * $Id: qam_stub.c,v 12.5 2006/08/24 14:46:24 bostic Exp $ */ -#include "db_config.h" - #ifndef HAVE_QUEUE -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif +#include "db_config.h" #include "db_int.h" #include "dbinc/db_page.h" @@ -34,7 +30,7 @@ int __db_no_queue_am(dbenv) DB_ENV *dbenv; { - __db_err(dbenv, + __db_errx(dbenv, "library build did not include support for the Queue access method"); return (DB_OPNOTSUP); } diff --git a/db/qam/qam_upgrade.c b/db/qam/qam_upgrade.c index dff82404a..0c5777e25 100644 --- a/db/qam/qam_upgrade.c +++ b/db/qam/qam_upgrade.c @@ -1,20 +1,14 @@ /*- * 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. * - * $Id: qam_upgrade.c,v 11.16 2004/05/10 21:29:43 bostic Exp $ + * $Id: qam_upgrade.c,v 12.4 2006/08/24 14:46:24 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_upgrade.h" #include "dbinc/db_page.h" diff --git a/db/qam/qam_verify.c b/db/qam/qam_verify.c index 571157b8f..b6457ce70 100644 --- a/db/qam/qam_verify.c +++ b/db/qam/qam_verify.c @@ -1,29 +1,20 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1999-2006 + * Oracle Corporation. All rights reserved. * - * $Id: qam_verify.c,v 1.51 2004/10/11 18:47:51 bostic Exp $ + * $Id: qam_verify.c,v 12.9 2006/08/24 14:46:24 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#endif - #include "db_int.h" #include "dbinc/db_page.h" #include "dbinc/db_verify.h" #include "dbinc/db_am.h" -#include "dbinc/db_shash.h" #include "dbinc/mp.h" #include "dbinc/qam.h" -#include <stdlib.h> -#include <string.h> - /* * __qam_vrfy_meta -- * Verify the queue-specific part of a metadata page. @@ -93,6 +84,8 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags) * it when handling extents. It would get set up in open, * if we called open normally, but we don't. */ + vdp->re_pad = meta->re_pad; + qp->re_pad = (int)meta->re_pad; qp->re_len = vdp->re_len = meta->re_len; qp->rec_page = vdp->rec_page = meta->rec_page; qp->page_ext = vdp->page_ext = meta->page_ext; @@ -165,7 +158,7 @@ __qam_vrfy_meta(dbp, vdp, meta, pgno, flags) } } if (nextents > 0) - __db_err(dbenv, + __db_errx(dbenv, "Warning: %d extra extent files found", nextents); vdp->nextents = nextents; vdp->extents = extents; @@ -344,7 +337,7 @@ begin: for (; i <= stop; i++) { */ if (LF_ISSET(DB_SALVAGE) && (__db_salvage_isdone(vdp, i) != 0)) continue; - if ((t_ret = __qam_fget(dbp, &i, 0, &h)) != 0) { + if ((t_ret = __qam_fget(dbp, &i, NULL, 0, &h)) != 0) { if (t_ret == ENOENT || t_ret == DB_PAGE_NOTFOUND) { i += (pg_ext - ((i - 1) % pg_ext)) - 1; continue; |