summaryrefslogtreecommitdiff
path: root/db/dbreg
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2007-07-16 16:48:14 +0300
committerPanu Matilainen <pmatilai@redhat.com>2007-07-16 16:48:14 +0300
commit2cfd3012bfcb5c5c61bbaf662ef084e0ab789d79 (patch)
treee12ee52087506ac8c7a5eee83b17497d98df2d40 /db/dbreg
parentb754fe19fd387ca5fe8e7c00ddaa25c898fa192f (diff)
downloadlibrpm-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/dbreg')
-rw-r--r--db/dbreg/dbreg.c296
-rw-r--r--db/dbreg/dbreg.src15
-rw-r--r--db/dbreg/dbreg_auto.c53
-rw-r--r--db/dbreg/dbreg_autop.c19
-rw-r--r--db/dbreg/dbreg_rec.c87
-rw-r--r--db/dbreg/dbreg_stat.c58
-rw-r--r--db/dbreg/dbreg_util.c212
7 files changed, 477 insertions, 263 deletions
diff --git a/db/dbreg/dbreg.c b/db/dbreg/dbreg.c
index 930c8bb7a..edc4599be 100644
--- a/db/dbreg/dbreg.c
+++ b/db/dbreg/dbreg.c
@@ -1,27 +1,21 @@
/*-
* 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: dbreg.c,v 11.90 2004/10/15 16:59:39 bostic Exp $
+ * $Id: dbreg.c,v 12.20 2006/08/24 14:45:31 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/log.h"
#include "dbinc/txn.h"
#include "dbinc/db_am.h"
-static int __dbreg_push_id __P((DB_ENV *, int32_t));
+static int __dbreg_push_id __P((DB_ENV *, DB *, int32_t));
static int __dbreg_pop_id __P((DB_ENV *, int32_t *));
static int __dbreg_pluck_id __P((DB_ENV *, int32_t));
@@ -60,9 +54,9 @@ static int __dbreg_pluck_id __P((DB_ENV *, int32_t));
* region list so they can get logged on checkpoints.
*
* An FNAME that may/does have a valid id must be accessed under
- * protection of the fq_mutex, with the following exception:
+ * protection of the mtx_filelist, with the following exception:
*
- * We don't want to have to grab the fq_mutex on every log
+ * We don't want to have to grab the mtx_filelist on every log
* record, and it should be safe not to do so when we're just
* looking at the id, because once allocated, the id should
* not change under a handle until the handle is closed.
@@ -114,7 +108,7 @@ __dbreg_setup(dbp, name, create_txnid)
namep = NULL;
/* Allocate an FNAME and, if necessary, a buffer for the name itself. */
- R_LOCK(dbenv, infop);
+ LOG_SYSTEM_LOCK(dbenv);
if ((ret = __db_shalloc(infop, sizeof(FNAME), 0, &fnp)) != 0)
goto err;
memset(fnp, 0, sizeof(FNAME));
@@ -127,13 +121,13 @@ __dbreg_setup(dbp, name, create_txnid)
} else
fnp->name_off = INVALID_ROFF;
- R_UNLOCK(dbenv, infop);
+ LOG_SYSTEM_UNLOCK(dbenv);
/*
* Fill in all the remaining info that we'll need later to register
* the file, if we use it for logging.
*/
- fnp->id = DB_LOGFILEID_INVALID;
+ fnp->id = fnp->old_id = DB_LOGFILEID_INVALID;
fnp->s_type = dbp->type;
memcpy(fnp->ufid, dbp->fileid, DB_FILE_ID_LEN);
fnp->meta_pgno = dbp->meta_pgno;
@@ -143,9 +137,9 @@ __dbreg_setup(dbp, name, create_txnid)
return (0);
-err: R_UNLOCK(dbenv, infop);
+err: LOG_SYSTEM_UNLOCK(dbenv);
if (ret == ENOMEM)
- __db_err(dbenv,
+ __db_errx(dbenv,
"Logging region out of memory; you may need to increase its size");
return (ret);
@@ -175,16 +169,16 @@ __dbreg_teardown(dbp)
* We may not have an FNAME if we were never opened. This is not an
* error.
*/
- if (fnp == NULL)
+ if (fnp == NULL || F_ISSET(fnp, DB_FNAME_NOTLOGGED))
return (0);
- DB_ASSERT(fnp->id == DB_LOGFILEID_INVALID);
+ DB_ASSERT(dbenv, fnp->id == DB_LOGFILEID_INVALID);
- R_LOCK(dbenv, infop);
+ LOG_SYSTEM_LOCK(dbenv);
if (fnp->name_off != INVALID_ROFF)
__db_shalloc_free(infop, R_ADDR(infop, fnp->name_off));
__db_shalloc_free(infop, fnp);
- R_UNLOCK(dbenv, infop);
+ LOG_SYSTEM_UNLOCK(dbenv);
dbp->log_filename = NULL;
@@ -216,22 +210,22 @@ __dbreg_new_id(dbp, txn)
lp = dblp->reginfo.primary;
fnp = dbp->log_filename;
- /* The fq_mutex protects the FNAME list and id management. */
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
+ /* The mtx_filelist protects the FNAME list and id management. */
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
if (fnp->id != DB_LOGFILEID_INVALID) {
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (0);
}
if ((ret = __dbreg_get_id(dbp, txn, &id)) == 0)
fnp->id = id;
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (ret);
}
/*
* __dbreg_get_id --
* Assign an unused dbreg id to this database handle.
- * Assume the caller holds the fq_mutex locked. Assume the
+ * Assume the caller holds the mtx_filelist locked. Assume the
* caller will set the fnp->id field with the id we return.
*
* PUBLIC: int __dbreg_get_id __P((DB *, DB_TXN *, int32_t *));
@@ -242,10 +236,8 @@ __dbreg_get_id(dbp, txn, idp)
DB_TXN *txn;
int32_t *idp;
{
- DBT fid_dbt, r_name;
DB_ENV *dbenv;
DB_LOG *dblp;
- DB_LSN unused;
FNAME *fnp;
LOG *lp;
int32_t id;
@@ -269,7 +261,9 @@ __dbreg_get_id(dbp, txn, idp)
if (id == DB_LOGFILEID_INVALID)
id = lp->fid_max++;
- fnp->is_durable = !F_ISSET(dbp, DB_AM_NOT_DURABLE);
+ /* If the file is durable (i.e., not, not-durable), mark it as such. */
+ if (!F_ISSET(dbp, DB_AM_NOT_DURABLE))
+ F_SET(fnp, DB_FNAME_DURABLE);
/* Hook the FNAME into the list of open files. */
SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
@@ -278,21 +272,11 @@ __dbreg_get_id(dbp, txn, idp)
* Log the registry. We should only request a new ID in situations
* where logging is reasonable.
*/
- DB_ASSERT(!F_ISSET(dbp, DB_AM_RECOVER));
+ DB_ASSERT(dbenv, !F_ISSET(dbp, DB_AM_RECOVER));
- memset(&fid_dbt, 0, sizeof(fid_dbt));
- memset(&r_name, 0, sizeof(r_name));
- if (fnp->name_off != INVALID_ROFF) {
- r_name.data = R_ADDR(&dblp->reginfo, fnp->name_off);
- r_name.size = (u_int32_t)strlen((char *)r_name.data) + 1;
- }
- fid_dbt.data = dbp->fileid;
- fid_dbt.size = DB_FILE_ID_LEN;
- if ((ret = __dbreg_register_log(dbenv, txn, &unused,
- F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0,
- DBREG_OPEN, r_name.size == 0 ? NULL : &r_name, &fid_dbt, id,
- fnp->s_type, fnp->meta_pgno, fnp->create_txnid)) != 0)
+ if ((ret = __dbreg_log_id(dbp, txn, id, 0)) != 0)
goto err;
+
/*
* Once we log the create_txnid, we need to make sure we never
* log it again (as might happen if this is a replication client
@@ -300,8 +284,8 @@ __dbreg_get_id(dbp, txn, idp)
*/
fnp->create_txnid = TXN_INVALID;
- DB_ASSERT(dbp->type == fnp->s_type);
- DB_ASSERT(dbp->meta_pgno == fnp->meta_pgno);
+ DB_ASSERT(dbenv, dbp->type == fnp->s_type);
+ DB_ASSERT(dbenv, dbp->meta_pgno == fnp->meta_pgno);
if ((ret = __dbreg_add_dbentry(dbenv, dblp, dbp, id)) != 0)
goto err;
@@ -345,11 +329,11 @@ __dbreg_assign_id(dbp, id)
close_dbp = NULL;
close_fnp = NULL;
- /* The fq_mutex protects the FNAME list and id management. */
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
+ /* The mtx_filelist protects the FNAME list and id management. */
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
/* We should only call this on DB handles that have no ID. */
- DB_ASSERT(fnp->id == DB_LOGFILEID_INVALID);
+ DB_ASSERT(dbenv, fnp->id == DB_LOGFILEID_INVALID);
/*
* Make sure there isn't already a file open with this ID. There can
@@ -358,8 +342,8 @@ __dbreg_assign_id(dbp, id)
*/
if (__dbreg_id_to_fname(dblp, id, 1, &close_fnp) == 0) {
/*
- * We want to save off any dbp we have open with this id.
- * We can't safely close it now, because we hold the fq_mutex,
+ * We want to save off any dbp we have open with this id. We
+ * can't safely close it now, because we hold the mtx_filelist,
* but we should be able to rely on it being open in this
* process, and we're running recovery, so no other thread
* should muck with it if we just put off closing it until
@@ -391,7 +375,9 @@ cont: if ((ret = __dbreg_pluck_id(dbenv, id)) != 0)
/* Now go ahead and assign the id to our dbp. */
fnp->id = id;
- fnp->is_durable = !F_ISSET(dbp, DB_AM_NOT_DURABLE);
+ /* If the file is durable (i.e., not, not-durable), mark it as such. */
+ if (!F_ISSET(dbp, DB_AM_NOT_DURABLE))
+ F_SET(fnp, DB_FNAME_DURABLE);
SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname);
/*
@@ -402,7 +388,7 @@ cont: if ((ret = __dbreg_pluck_id(dbenv, id)) != 0)
if ((ret = __dbreg_add_dbentry(dbenv, dblp, dbp, id)) != 0)
(void)__dbreg_revoke_id(dbp, 1, id);
-err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+err: MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
/* There's nothing useful that our caller can do if this close fails. */
if (close_dbp != NULL)
@@ -435,6 +421,7 @@ __dbreg_revoke_id(dbp, have_lock, force_id)
dblp = dbenv->lg_handle;
lp = dblp->reginfo.primary;
fnp = dbp->log_filename;
+ ret = 0;
/* If we lack an ID, this is a null-op. */
if (fnp == NULL)
@@ -447,26 +434,38 @@ __dbreg_revoke_id(dbp, have_lock, force_id)
*/
if (force_id != DB_LOGFILEID_INVALID)
id = force_id;
- else if (fnp->id == DB_LOGFILEID_INVALID)
- return (0);
- else
+ else if (fnp->id == DB_LOGFILEID_INVALID) {
+ if (fnp->old_id == DB_LOGFILEID_INVALID)
+ return (0);
+ id = fnp->old_id;
+ } else
id = fnp->id;
if (!have_lock)
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
fnp->id = DB_LOGFILEID_INVALID;
+ fnp->old_id = DB_LOGFILEID_INVALID;
/* Remove the FNAME from the list of open files. */
SH_TAILQ_REMOVE(&lp->fq, fnp, q, __fname);
- /* Remove this id from the dbentry table. */
- __dbreg_rem_dbentry(dblp, id);
-
- /* Push this id onto the free list. */
- ret = __dbreg_push_id(dbenv, id);
+ /*
+ * Remove this id from the dbentry table and push it onto the
+ * free list.
+ */
+ if ((ret = __dbreg_rem_dbentry(dblp, id)) == 0) {
+ /*
+ * If we are not in recovery but the file was opened
+ * for a recovery operation, then this process aborted
+ * a transaction for another process and the id may
+ * still be in use, so don't reuse this id.
+ */
+ if (!F_ISSET(dbp, DB_AM_RECOVER) || IS_RECOVERING(dbenv))
+ ret = __dbreg_push_id(dbenv, dbp, id);
+ }
if (!have_lock)
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (ret);
}
@@ -483,10 +482,8 @@ __dbreg_close_id(dbp, txn, op)
DB_TXN *txn;
u_int32_t op;
{
- DBT fid_dbt, r_name, *dbtp;
DB_ENV *dbenv;
DB_LOG *dblp;
- DB_LSN r_unused;
FNAME *fnp;
LOG *lp;
int ret;
@@ -497,10 +494,48 @@ __dbreg_close_id(dbp, txn, op)
fnp = dbp->log_filename;
/* If we lack an ID, this is a null-op. */
- if (fnp == NULL || fnp->id == DB_LOGFILEID_INVALID)
+ if (fnp == NULL)
return (0);
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
+ if (fnp->id == DB_LOGFILEID_INVALID)
+ return (__dbreg_revoke_id(dbp, 0, DB_LOGFILEID_INVALID));
+
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
+
+ if ((ret = __dbreg_log_close(dbenv, fnp, txn, op)) != 0)
+ goto err;
+ ret = __dbreg_revoke_id(dbp, 1, DB_LOGFILEID_INVALID);
+
+err: MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
+ return (ret);
+}
+
+/*
+ * __dbreg_log_close --
+ *
+ * Log a close of a database. Called when closing a file or when a
+ * replication client is becoming a master. That closes all the
+ * files it previously had open.
+ *
+ * Assumes caller holds the lp->mutex_filelist lock already.
+ *
+ * PUBLIC: int __dbreg_log_close __P((DB_ENV *, FNAME *,
+ * PUBLIC: DB_TXN *, u_int32_t));
+ */
+int
+__dbreg_log_close(dbenv, fnp, txn, op)
+ DB_ENV *dbenv;
+ FNAME *fnp;
+ DB_TXN *txn;
+ u_int32_t op;
+{
+ DB_LOG *dblp;
+ DBT fid_dbt, r_name, *dbtp;
+ DB_LSN r_unused;
+ int ret;
+
+ dblp = dbenv->lg_handle;
+ ret = 0;
if (fnp->name_off == INVALID_ROFF)
dbtp = NULL;
@@ -515,14 +550,22 @@ __dbreg_close_id(dbp, txn, op)
fid_dbt.data = fnp->ufid;
fid_dbt.size = DB_FILE_ID_LEN;
if ((ret = __dbreg_register_log(dbenv, txn, &r_unused,
- F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0,
+ F_ISSET(fnp, DB_FNAME_DURABLE) ? 0 : DB_LOG_NOT_DURABLE,
op, dbtp, &fid_dbt, fnp->id,
- fnp->s_type, fnp->meta_pgno, TXN_INVALID)) != 0)
- goto err;
-
- ret = __dbreg_revoke_id(dbp, 1, DB_LOGFILEID_INVALID);
-
-err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ fnp->s_type, fnp->meta_pgno, TXN_INVALID)) != 0) {
+ /*
+ * We are trying to close, but the log write failed.
+ * Unfortunately, close needs to plow forward, because
+ * the application can't do anything with the handle.
+ * Make the entry in the shared memory region so that
+ * when we close the environment, we know that this
+ * happened. Also, make sure we remove this from the
+ * per-process table, so that we don't try to close it
+ * later.
+ */
+ F_SET(fnp, DB_FNAME_NOTLOGGED);
+ (void)__dbreg_rem_dbentry(dblp, fnp->id);
+ }
return (ret);
}
@@ -533,15 +576,17 @@ err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
* process keeps open files in an array by ID.) Push them to the stack and
* pop them from it, managing memory as appropriate.
*
- * The stack is protected by the fq_mutex, and in both functions we assume
- * that this is already locked.
+ * The stack is protected by the mtx_filelist, and both functions assume it
+ * is already locked.
*/
static int
-__dbreg_push_id(dbenv, id)
+__dbreg_push_id(dbenv, dbp, id)
DB_ENV *dbenv;
+ DB *dbp;
int32_t id;
{
DB_LOG *dblp;
+ DB_REP *db_rep;
LOG *lp;
REGINFO *infop;
int32_t *stack, *newstack;
@@ -550,34 +595,37 @@ __dbreg_push_id(dbenv, id)
dblp = dbenv->lg_handle;
infop = &dblp->reginfo;
lp = infop->primary;
+ db_rep = dbenv->rep_handle;
- if (lp->free_fid_stack == INVALID_ROFF) {
- stack = NULL;
- DB_ASSERT(lp->free_fids_alloced == 0);
- } else
- stack = R_ADDR(infop, lp->free_fid_stack);
-
+ /*
+ * If our fid generation in replication has changed, this fid should
+ * not be pushed back onto the stack.
+ */
+ if (REP_ON(dbenv) && ((REP *)db_rep->region)->gen != dbp->fid_gen)
+ return (0);
/* Check if we have room on the stack. */
- if (lp->free_fids_alloced <= lp->free_fids + 1) {
- R_LOCK(dbenv, infop);
+ if (lp->free_fid_stack == INVALID_ROFF ||
+ lp->free_fids_alloced <= lp->free_fids + 1) {
+ LOG_SYSTEM_LOCK(dbenv);
if ((ret = __db_shalloc(infop,
(lp->free_fids_alloced + 20) * sizeof(u_int32_t), 0,
&newstack)) != 0) {
- R_UNLOCK(dbenv, infop);
+ LOG_SYSTEM_UNLOCK(dbenv);
return (ret);
}
- if (stack != NULL) {
+ if (lp->free_fid_stack != INVALID_ROFF) {
+ stack = R_ADDR(infop, lp->free_fid_stack);
memcpy(newstack, stack,
lp->free_fids_alloced * sizeof(u_int32_t));
__db_shalloc_free(infop, stack);
}
- stack = newstack;
- lp->free_fid_stack = R_OFFSET(infop, stack);
+ lp->free_fid_stack = R_OFFSET(infop, newstack);
lp->free_fids_alloced += 20;
- R_UNLOCK(dbenv, infop);
+ LOG_SYSTEM_UNLOCK(dbenv);
}
+ stack = R_ADDR(infop, lp->free_fid_stack);
stack[lp->free_fids++] = id;
return (0);
}
@@ -611,7 +659,7 @@ __dbreg_pop_id(dbenv, id)
* be on the stack.
*
* Returns success whether or not the particular id was found, and like
- * push and pop, assumes that the fq_mutex is locked.
+ * push and pop, assumes that the mtx_filelist is locked.
*/
static int
__dbreg_pluck_id(dbenv, id)
@@ -644,3 +692,73 @@ __dbreg_pluck_id(dbenv, id)
return (0);
}
+
+/*
+ * __dbreg_log_id --
+ * Used for in-memory named files. They are created in mpool and
+ * are given id's early in the open process so that we can read and
+ * create pages in the mpool for the files. However, at the time that
+ * the mpf is created, the file may not be fully created and/or its
+ * meta-data may not be fully known, so we can't do a full dbregister.
+ * This is a routine exported that will log a complete dbregister
+ * record that will allow for both recovery and replication.
+ *
+ * PUBLIC: int __dbreg_log_id __P((DB *, DB_TXN *, int32_t, int));
+ */
+int
+__dbreg_log_id(dbp, txn, id, needlock)
+ DB *dbp;
+ DB_TXN *txn;
+ int32_t id;
+ int needlock;
+{
+ DBT fid_dbt, r_name;
+ DB_ENV *dbenv;
+ DB_LOG *dblp;
+ DB_LSN unused;
+ FNAME *fnp;
+ LOG *lp;
+ u_int32_t op;
+ int ret;
+
+ dbenv = dbp->dbenv;
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+ fnp = dbp->log_filename;
+
+ /* Verify that the fnp has been initialized. */
+ if (fnp->s_type == DB_UNKNOWN) {
+ memcpy(fnp->ufid, dbp->fileid, DB_FILE_ID_LEN);
+ fnp->s_type = dbp->type;
+ }
+
+ /*
+ * Log the registry. We should only request a new ID in situations
+ * where logging is reasonable.
+ */
+ memset(&fid_dbt, 0, sizeof(fid_dbt));
+ memset(&r_name, 0, sizeof(r_name));
+
+ if (needlock)
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
+
+ if (fnp->name_off != INVALID_ROFF) {
+ r_name.data = R_ADDR(&dblp->reginfo, fnp->name_off);
+ r_name.size = (u_int32_t)strlen((char *)r_name.data) + 1;
+ }
+
+ fid_dbt.data = dbp->fileid;
+ fid_dbt.size = DB_FILE_ID_LEN;
+
+ op = !F_ISSET(dbp, DB_AM_OPEN_CALLED) ? DBREG_PREOPEN :
+ (F_ISSET(dbp, DB_AM_INMEM) ? DBREG_REOPEN : DBREG_OPEN);
+ ret = __dbreg_register_log(dbenv, txn, &unused,
+ F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0,
+ op, r_name.size == 0 ? NULL : &r_name, &fid_dbt, id,
+ fnp->s_type, fnp->meta_pgno, fnp->create_txnid);
+
+ if (needlock)
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
+
+ return (ret);
+}
diff --git a/db/dbreg/dbreg.src b/db/dbreg/dbreg.src
index ff3fc2923..6f229e287 100644
--- a/db/dbreg/dbreg.src
+++ b/db/dbreg/dbreg.src
@@ -1,22 +1,15 @@
/*-
* 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: dbreg.src,v 10.26 2004/06/17 17:35:17 bostic Exp $
+ * $Id: dbreg.src,v 12.5 2006/08/24 14:45:31 bostic Exp $
*/
PREFIX __dbreg
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"
@@ -35,7 +28,7 @@ INCLUDE
* ftype: database type
* id: transaction id of the subtransaction that created the fs object
*/
-BEGIN register 2
+BEGIN register 42 2
ARG opcode u_int32_t lu
DBT name DBT s
DBT uid DBT s
diff --git a/db/dbreg/dbreg_auto.c b/db/dbreg/dbreg_auto.c
index a9cc5f704..519786c14 100644
--- a/db/dbreg/dbreg_auto.c
+++ b/db/dbreg/dbreg_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,11 +16,11 @@
* PUBLIC: int32_t, DBTYPE, db_pgno_t, u_int32_t));
*/
int
-__dbreg_register_log(dbenv, txnid, ret_lsnp, flags,
+__dbreg_register_log(dbenv, txnp, ret_lsnp, flags,
opcode, name, uid, fileid, ftype, meta_pgno,
id)
DB_ENV *dbenv;
- DB_TXN *txnid;
+ DB_TXN *txnp;
DB_LSN *ret_lsnp;
u_int32_t flags;
u_int32_t opcode;
@@ -55,29 +48,30 @@ __dbreg_register_log(dbenv, txnid, ret_lsnp, flags,
ret = 0;
if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
- if (txnid == NULL)
+ if (txnp == NULL)
+ return (0);
+ 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;
}
logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
@@ -94,7 +88,7 @@ __dbreg_register_log(dbenv, 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);
@@ -168,12 +162,13 @@ __dbreg_register_log(dbenv, 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;
}
@@ -192,20 +187,21 @@ __dbreg_register_log(dbenv, 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)__dbreg_register_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);
@@ -230,13 +226,14 @@ __dbreg_register_read(dbenv, recbuf, argpp)
sizeof(__dbreg_register_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/dbreg/dbreg_autop.c b/db/dbreg/dbreg_autop.c
index 3889b357d..b2e12e2d4 100644
--- a/db/dbreg/dbreg_autop.c
+++ b/db/dbreg/dbreg_autop.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"
@@ -34,20 +27,18 @@ __dbreg_register_print(dbenv, dbtp, lsnp, notused2, notused3)
int ch;
int ret;
- notused2 = DB_TXN_ABORT;
+ notused2 = DB_TXN_PRINT;
notused3 = NULL;
if ((ret = __dbreg_register_read(dbenv, dbtp->data, &argp)) != 0)
return (ret);
(void)printf(
- "[%lu][%lu]__dbreg_register%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
- (u_long)lsnp->file,
- (u_long)lsnp->offset,
+ "[%lu][%lu]__dbreg_register%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("\tname: ");
for (i = 0; i < argp->name.size; i++) {
diff --git a/db/dbreg/dbreg_rec.c b/db/dbreg/dbreg_rec.c
index 07b175a1f..180239842 100644
--- a/db/dbreg/dbreg_rec.c
+++ b/db/dbreg/dbreg_rec.c
@@ -1,8 +1,8 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996-2004
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1996-2006
+ * Oracle Corporation. All rights reserved.
*/
/*
* Copyright (c) 1995, 1996
@@ -32,23 +32,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: dbreg_rec.c,v 11.133 2004/09/24 00:43:18 bostic Exp $
+ * $Id: dbreg_rec.c,v 12.17 2006/09/07 20:05:28 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/log.h"
-#include "dbinc/mp.h"
#include "dbinc/txn.h"
static int __dbreg_open_file __P((DB_ENV *,
@@ -84,11 +76,19 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
goto out;
switch (argp->opcode) {
+ case DBREG_REOPEN:
+ case DBREG_PREOPEN:
case DBREG_OPEN:
+ /*
+ * In general, we redo the open on REDO and abort on UNDO.
+ * However, a reopen is a second instance of an open of
+ * in-memory files and we don't want to close them yet
+ * on abort, so just skip that here.
+ */
if ((DB_REDO(op) ||
op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES))
do_open = 1;
- else
+ else if (argp->opcode != DBREG_REOPEN)
do_close = 1;
break;
case DBREG_CLOSE:
@@ -117,9 +117,8 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
do_open = 1;
break;
default:
- DB_ASSERT(0);
- ret = EINVAL;
- break;
+ ret = __db_unknown_path(dbenv, "__dbreg_register_recover");
+ goto out;
}
if (do_open) {
@@ -137,7 +136,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
*/
ret = __dbreg_open_file(dbenv,
op == DB_TXN_ABORT || op == DB_TXN_POPENFILES ?
- argp->txnid : NULL, argp, info);
+ argp->txnp : NULL, argp, info);
if (ret == DB_PAGE_NOTFOUND && argp->meta_pgno != PGNO_BASE_MD)
ret = ENOENT;
if (ret == ENOENT || ret == EINVAL) {
@@ -149,7 +148,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
* for that case and possibly retry.
*/
if (op == DB_TXN_FORWARD_ROLL &&
- argp->txnid != 0 &&
+ argp->txnp != 0 &&
dblp->dbentry[argp->fileid].deleted) {
dblp->dbentry[argp->fileid].deleted = 0;
ret =
@@ -172,7 +171,9 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
if (do_close) {
/*
* If we are undoing an open, or redoing a close,
- * then we need to close the file.
+ * then we need to close the file. If we are simply
+ * revoking then we just need to grab the DBP and revoke
+ * the log id.
*
* If the file is deleted, then we can just ignore this close.
* Otherwise, we should usually have a valid dbp we should
@@ -181,7 +182,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
* fact, not have the file open, and that's OK.
*/
do_rem = 0;
- MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
if (argp->fileid < dblp->dbentry_cnt) {
/*
* Typically, closes should match an open which means
@@ -205,13 +206,12 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
if ((DB_REDO(op) &&
argp->opcode != DBREG_RCLOSE) ||
argp->opcode == DBREG_CHKPNT) {
- __db_err(dbenv,
- "Improper file close at %lu/%lu",
+ __db_errx(dbenv,
+ "Warning: Improper file close at %lu/%lu",
(u_long)lsnp->file,
(u_long)lsnp->offset);
- ret = EINVAL;
}
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
goto done;
}
@@ -228,7 +228,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
*/
do_rem = F_ISSET(dbp, DB_AM_RECOVER) ||
op == DB_TXN_ABORT;
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
if (op == DB_TXN_ABORT)
(void)__dbreg_close_id(dbp,
NULL, DBREG_RCLOSE);
@@ -236,11 +236,13 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
(void)__dbreg_revoke_id(dbp, 0,
DB_LOGFILEID_INVALID);
} else if (dbe->deleted) {
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
- __dbreg_rem_dbentry(dblp, argp->fileid);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
+ if ((ret = __dbreg_rem_dbentry(
+ dblp, argp->fileid)) != 0)
+ goto out;
}
} else
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
/*
* During recovery, all files are closed. On an abort, we only
@@ -262,7 +264,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
if (do_rem && dbp != NULL) {
if (argp->id != TXN_INVALID) {
if ((ret = __db_txnlist_find(dbenv,
- info, argp->txnid->txnid, &status))
+ info, argp->txnp->txnid, &status))
!= DB_NOTFOUND && ret != 0)
goto out;
if (ret == DB_NOTFOUND || status != TXN_COMMIT)
@@ -273,7 +275,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info)
if (op == DB_TXN_ABORT &&
!F_ISSET(dbp, DB_AM_RECOVER)) {
if ((t_ret = __db_refresh(dbp,
- NULL, DB_NOSYNC, NULL)) != 0 && ret == 0)
+ NULL, DB_NOSYNC, NULL, 0)) != 0 && ret == 0)
ret = t_ret;
} else {
if (op == DB_TXN_APPLY &&
@@ -311,27 +313,29 @@ __dbreg_open_file(dbenv, txn, argp, info)
u_int32_t id, status;
int ret;
- dblp = (DB_LOG *)dbenv->lg_handle;
+ dblp = dbenv->lg_handle;
/*
* When we're opening, we have to check that the name we are opening
* is what we expect. If it's not, then we close the old file and
* open the new one.
*/
- MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
- if (argp->fileid < dblp->dbentry_cnt)
+ MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
+ if (argp->fileid != DB_LOGFILEID_INVALID &&
+ argp->fileid < dblp->dbentry_cnt)
dbe = &dblp->dbentry[argp->fileid];
else
dbe = NULL;
if (dbe != NULL) {
if (dbe->deleted) {
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
return (ENOENT);
}
/*
- * At the end of OPENFILES, we may have a file open. The
+ * At the end of OPENFILES, we may have a file open. If this
+ * is a reopen, then we will always close and reopen. If the
* open was part of a committed transaction, so it doesn't
* get undone. However, if the fileid was previously used,
* we'll see a close that may need to get undone. There are
@@ -342,11 +346,12 @@ __dbreg_open_file(dbenv, txn, argp, info)
* which case it should never be opened during recovery.
*/
if ((dbp = dbe->dbp) != NULL) {
- if (dbp->meta_pgno != argp->meta_pgno ||
+ if (argp->opcode == DBREG_REOPEN ||
+ dbp->meta_pgno != argp->meta_pgno ||
argp->name.size == 0 ||
memcmp(dbp->fileid, argp->uid.data,
DB_FILE_ID_LEN) != 0) {
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
(void)__dbreg_revoke_id(dbp, 0,
DB_LOGFILEID_INVALID);
if (F_ISSET(dbp, DB_AM_RECOVER))
@@ -359,8 +364,8 @@ __dbreg_open_file(dbenv, txn, argp, info)
* dbp from an openfiles pass, in which case, what's
* here had better be the same dbp.
*/
- DB_ASSERT(dbe->dbp == dbp);
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ DB_ASSERT(dbenv, dbe->dbp == dbp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
/*
* This is a successful open. We need to record that
@@ -375,7 +380,7 @@ __dbreg_open_file(dbenv, txn, argp, info)
}
}
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
reopen:
/*
@@ -402,6 +407,6 @@ reopen:
}
return (__dbreg_do_open(dbenv,
- txn, dblp, argp->uid.data, argp->name.data,
- argp->ftype, argp->fileid, argp->meta_pgno, info, argp->id));
+ txn, dblp, argp->uid.data, argp->name.data, argp->ftype,
+ argp->fileid, argp->meta_pgno, info, argp->id, argp->opcode));
}
diff --git a/db/dbreg/dbreg_stat.c b/db/dbreg/dbreg_stat.c
index dd53b77c3..c19adc688 100644
--- a/db/dbreg/dbreg_stat.c
+++ b/db/dbreg/dbreg_stat.c
@@ -1,19 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997-2004
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2006
+ * Oracle Corporation. All rights reserved.
*
- * $Id: dbreg_stat.c,v 11.48 2004/10/15 16:59:41 bostic Exp $
+ * $Id: dbreg_stat.c,v 12.9 2006/08/24 14:45:32 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_am.h"
@@ -21,6 +16,28 @@
#include "dbinc/txn.h"
#ifdef HAVE_STATISTICS
+static int __dbreg_print_dblist __P((DB_ENV *, u_int32_t));
+
+/*
+ * __dbreg_stat_print --
+ * Print the dbreg statistics.
+ *
+ * PUBLIC: int __dbreg_stat_print __P((DB_ENV *, u_int32_t));
+ */
+int
+__dbreg_stat_print(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+{
+ int ret;
+
+ if (LF_ISSET(DB_STAT_ALL) &&
+ (ret = __dbreg_print_dblist(dbenv, flags)) != 0)
+ return (ret);
+
+ return (0);
+}
+
/*
* __dbreg_print_fname --
* Display the contents of an FNAME structure.
@@ -32,22 +49,26 @@ __dbreg_print_fname(dbenv, fnp)
DB_ENV *dbenv;
FNAME *fnp;
{
+ static const FN fn[] = {
+ { DB_FNAME_DURABLE, "DB_FNAME_DURABLE" },
+ { DB_FNAME_NOTLOGGED, "DB_FNAME_NOTLOGGED" },
+ { 0, NULL }
+ };
+
__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
__db_msg(dbenv, "DB handle FNAME contents:");
STAT_LONG("log ID", fnp->id);
STAT_ULONG("Meta pgno", fnp->meta_pgno);
__db_print_fileid(dbenv, fnp->ufid, "\tFile ID");
STAT_ULONG("create txn", fnp->create_txnid);
- STAT_LONG("durable", fnp->is_durable);
+ __db_prflags(dbenv, NULL, fnp->flags, fn, NULL, "\tFlags");
}
/*
* __dbreg_print_dblist --
* Display the DB_ENV's list of files.
- *
- * PUBLIC: void __dbreg_print_dblist __P((DB_ENV *, u_int32_t));
*/
-void
+static int
__dbreg_print_dblist(dbenv, flags)
DB_ENV *dbenv;
u_int32_t flags;
@@ -64,13 +85,14 @@ __dbreg_print_dblist(dbenv, flags)
__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
__db_msg(dbenv, "LOG FNAME list:");
- __db_print_mutex(dbenv, NULL, &lp->fq_mutex, "File name mutex", flags);
+ __mutex_print_debug_single(
+ dbenv, "File name mutex", lp->mtx_filelist, flags);
STAT_LONG("Fid max", lp->fid_max);
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
- for (first = 1, fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
+ first = 1;
+ SH_TAILQ_FOREACH(fnp, &lp->fq, q, __fname) {
if (first) {
first = 0;
__db_msg(dbenv,
@@ -92,6 +114,8 @@ __dbreg_print_dblist(dbenv, flags)
dbp == NULL ? "No DBP" : "DBP", del, P_TO_ULONG(dbp),
(u_long)(dbp == NULL ? 0 : dbp->flags));
}
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
+
+ return (0);
}
#endif
diff --git a/db/dbreg/dbreg_util.c b/db/dbreg/dbreg_util.c
index 6f1cc9297..5037810c1 100644
--- a/db/dbreg/dbreg_util.c
+++ b/db/dbreg/dbreg_util.c
@@ -1,23 +1,20 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1997-2004
- * Sleepycat Software. All rights reserved.
+ * Copyright (c) 1997-2006
+ * Oracle Corporation. All rights reserved.
*
- * $Id: dbreg_util.c,v 11.50 2004/10/15 16:59:41 bostic Exp $
+ * $Id: dbreg_util.c,v 12.20 2006/09/09 14:28:22 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_am.h"
+#include "dbinc/fop.h"
#include "dbinc/log.h"
+#include "dbinc/mp.h"
#include "dbinc/txn.h"
static int __dbreg_check_master __P((DB_ENV *, u_int8_t *, char *));
@@ -40,7 +37,7 @@ __dbreg_add_dbentry(dbenv, dblp, dbp, ndx)
ret = 0;
- MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
/*
* Check if we need to grow the table. Note, ndx is 0-based (the
@@ -61,11 +58,11 @@ __dbreg_add_dbentry(dbenv, dblp, dbp, ndx)
dblp->dbentry_cnt = i;
}
- DB_ASSERT(dblp->dbentry[ndx].dbp == NULL);
+ DB_ASSERT(dbenv, dblp->dbentry[ndx].dbp == NULL);
dblp->dbentry[ndx].deleted = dbp == NULL;
dblp->dbentry[ndx].dbp = dbp;
-err: MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+err: MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
return (ret);
}
@@ -73,19 +70,21 @@ err: MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
* __dbreg_rem_dbentry
* Remove an entry from the DB entry table.
*
- * PUBLIC: void __dbreg_rem_dbentry __P((DB_LOG *, int32_t));
+ * PUBLIC: int __dbreg_rem_dbentry __P((DB_LOG *, int32_t));
*/
-void
+int
__dbreg_rem_dbentry(dblp, ndx)
DB_LOG *dblp;
int32_t ndx;
{
- MUTEX_THREAD_LOCK(dblp->dbenv, dblp->mutexp);
+ MUTEX_LOCK(dblp->dbenv, dblp->mtx_dbreg);
if (dblp->dbentry_cnt > ndx) {
dblp->dbentry[ndx].dbp = NULL;
dblp->dbentry[ndx].deleted = 0;
}
- MUTEX_THREAD_UNLOCK(dblp->dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dblp->dbenv, dblp->mtx_dbreg);
+
+ return (0);
}
/*
@@ -110,11 +109,12 @@ __dbreg_log_files(dbenv)
ret = 0;
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
-
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
+ SH_TAILQ_FOREACH(fnp, &lp->fq, q, __fname) {
+ /* This id was revoked by a switch in replication master. */
+ if (fnp->id == DB_LOGFILEID_INVALID)
+ continue;
if (fnp->name_off == INVALID_ROFF)
dbtp = NULL;
else {
@@ -136,14 +136,14 @@ __dbreg_log_files(dbenv)
*/
if ((ret = __dbreg_register_log(dbenv,
NULL, &r_unused,
- fnp->is_durable ? 0 : DB_LOG_NOT_DURABLE,
+ F_ISSET(fnp, DB_FNAME_DURABLE) ? 0 : DB_LOG_NOT_DURABLE,
F_ISSET(dblp, DBLOG_RECOVER) ? DBREG_RCLOSE : DBREG_CHKPNT,
dbtp, &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno,
TXN_INVALID)) != 0)
break;
}
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (ret);
}
@@ -173,7 +173,8 @@ __dbreg_close_files(dbenv)
dblp = dbenv->lg_handle;
ret = 0;
- MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+
+ MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
for (i = 0; i < dblp->dbentry_cnt; i++) {
/*
* We only want to close dbps that recovery opened. Any
@@ -182,6 +183,12 @@ __dbreg_close_files(dbenv)
* Before doing so, we need to revoke their log fileids
* so that we don't end up leaving around FNAME entries
* for dbps that shouldn't have them.
+ *
+ * Any FNAME entries that were marked NOTLOGGED had the
+ * log write fail while they were being closed. Since it's
+ * too late to be logging now we flag that as a failure
+ * so recovery will be run. This will get returned by
+ * __dbreg_revoke_id.
*/
if ((dbp = dblp->dbentry[i].dbp) != NULL) {
/*
@@ -195,7 +202,7 @@ __dbreg_close_files(dbenv)
* we're in this loop anyway--we're in the process of
* making all outstanding dbps invalid.
*/
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
if (F_ISSET(dbp, DB_AM_RECOVER))
t_ret = __db_close(dbp,
NULL, dbp->mpf == NULL ? DB_NOSYNC : 0);
@@ -204,13 +211,52 @@ __dbreg_close_files(dbenv)
dbp, 0, DB_LOGFILEID_INVALID);
if (ret == 0)
ret = t_ret;
- MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
}
dblp->dbentry[i].deleted = 0;
dblp->dbentry[i].dbp = NULL;
}
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
+ return (ret);
+}
+
+/*
+ * __dbreg_invalidate_files --
+ * Invalidate files when we change replication roles. Save the
+ * id so that another process will be able to clean up the information
+ * when it notices.
+ *
+ * PUBLIC: int __dbreg_invalidate_files __P((DB_ENV *));
+ */
+int
+__dbreg_invalidate_files(dbenv)
+ DB_ENV *dbenv;
+{
+ DB_LOG *dblp;
+ FNAME *fnp;
+ LOG *lp;
+ int ret;
+
+ /* If we haven't initialized logging, we have nothing to do. */
+ if (!LOGGING_ON(dbenv))
+ return (0);
+
+ dblp = dbenv->lg_handle;
+ lp = dblp->reginfo.primary;
+
+ ret = 0;
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
+ SH_TAILQ_FOREACH(fnp, &lp->fq, q, __fname) {
+ if (fnp->id != DB_LOGFILEID_INVALID) {
+ if ((ret = __dbreg_log_close(dbenv,
+ fnp, NULL, DBREG_RCLOSE)) != 0)
+ goto err;
+ fnp->old_id = fnp->id;
+ fnp->id = DB_LOGFILEID_INVALID;
+ }
+ }
+err: MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (ret);
}
@@ -261,7 +307,7 @@ __dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen)
dblp = dbenv->lg_handle;
COMPQUIET(inc, 0);
- MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);
+ MUTEX_LOCK(dbenv, dblp->mtx_dbreg);
/*
* Under XA, a process different than the one issuing DB operations
@@ -277,12 +323,12 @@ __dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen)
}
/*
- * __dbreg_id_to_fname acquires the region's fq_mutex,
- * which we can't safely acquire while we hold the thread lock.
- * We no longer need it anyway--the dbentry table didn't
- * have what we needed.
+ * __dbreg_id_to_fname acquires the mtx_filelist mutex, which
+ * we can't safely acquire while we hold the thread lock. We
+ * no longer need it anyway--the dbentry table didn't have what
+ * we needed.
*/
- MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+ MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
if (__dbreg_id_to_fname(dblp, ndx, 0, &fname) != 0)
/*
@@ -294,11 +340,11 @@ __dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen)
return (ENOENT);
/*
- * Note that we're relying on fname not to change, even
- * though we released the mutex that protects it (fq_mutex)
- * inside __dbreg_id_to_fname. This should be a safe
- * assumption, because the other process that has the file
- * open shouldn't be closing it while we're trying to abort.
+ * Note that we're relying on fname not to change, even though
+ * we released the mutex that protects it (mtx_filelist) inside
+ * __dbreg_id_to_fname. This should be a safe assumption, the
+ * other process that has the file open shouldn't be closing it
+ * while we're trying to abort.
*/
name = R_ADDR(&dblp->reginfo, fname->name_off);
@@ -313,7 +359,7 @@ __dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen)
*/
if ((ret = __dbreg_do_open(dbenv, txn, dblp,
fname->ufid, name, fname->s_type,
- ndx, fname->meta_pgno, NULL, 0)) != 0)
+ ndx, fname->meta_pgno, NULL, 0, DBREG_OPEN)) != 0)
return (ret);
*dbpp = dblp->dbentry[ndx].dbp;
@@ -331,8 +377,20 @@ __dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen)
/* It's an error if we don't have a corresponding writeable DB. */
if ((*dbpp = dblp->dbentry[ndx].dbp) == NULL)
ret = ENOENT;
+ else
+ /*
+ * If we are in recovery, then set that the file has
+ * been written. It is possible to run recovery,
+ * find all the pages in their post update state
+ * in the OS buffer pool, put a checkpoint in the log
+ * and then crash the system without forcing the pages
+ * to disk. If this is an in-memory file, we may not have
+ * an mpf yet.
+ */
+ if ((*dbpp)->mpf != NULL && (*dbpp)->mpf->mfp != NULL)
+ (*dbpp)->mpf->mfp->file_written = 1;
-err: MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);
+err: MUTEX_UNLOCK(dbenv, dblp->mtx_dbreg);
return (ret);
}
@@ -361,17 +419,15 @@ __dbreg_id_to_fname(dblp, id, have_lock, fnamep)
ret = -1;
if (!have_lock)
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
+ SH_TAILQ_FOREACH(fnp, &lp->fq, q, __fname)
if (fnp->id == id) {
*fnamep = fnp;
ret = 0;
break;
}
- }
if (!have_lock)
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (ret);
}
@@ -400,17 +456,15 @@ __dbreg_fid_to_fname(dblp, fid, have_lock, fnamep)
ret = -1;
if (!have_lock)
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
- for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
- fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
+ SH_TAILQ_FOREACH(fnp, &lp->fq, q, __fname)
if (memcmp(fnp->ufid, fid, DB_FILE_ID_LEN) == 0) {
*fnamep = fnp;
ret = 0;
break;
}
- }
if (!have_lock)
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (ret);
}
@@ -448,11 +502,12 @@ __dbreg_get_name(dbenv, fid, namep)
* Open files referenced in the log. This is the part of the open that
* is not protected by the thread mutex.
* PUBLIC: int __dbreg_do_open __P((DB_ENV *, DB_TXN *, DB_LOG *, u_int8_t *,
- * PUBLIC: char *, DBTYPE, int32_t, db_pgno_t, void *, u_int32_t));
+ * PUBLIC: char *, DBTYPE, int32_t, db_pgno_t, void *, u_int32_t,
+ * PUBLIC: u_int32_t));
*/
int
__dbreg_do_open(dbenv,
- txn, lp, uid, name, ftype, ndx, meta_pgno, info, id)
+ txn, lp, uid, name, ftype, ndx, meta_pgno, info, id, opcode)
DB_ENV *dbenv;
DB_TXN *txn;
DB_LOG *lp;
@@ -462,12 +517,16 @@ __dbreg_do_open(dbenv,
int32_t ndx;
db_pgno_t meta_pgno;
void *info;
- u_int32_t id;
+ u_int32_t id, opcode;
{
DB *dbp;
u_int32_t cstat, ret_stat;
int ret;
+ char *dname, *fname;
+ cstat = TXN_EXPECTED;
+ fname = name;
+ dname = NULL;
if ((ret = db_create(&dbp, lp->dbenv, 0)) != 0)
return (ret);
@@ -490,9 +549,24 @@ __dbreg_do_open(dbenv,
memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
dbp->meta_pgno = meta_pgno;
}
- if ((ret = __db_open(dbp, txn, name, NULL,
- ftype, DB_ODDFILESIZE, __db_omode("rw----"), meta_pgno)) == 0) {
+ if (opcode == DBREG_PREOPEN) {
+ dbp->type = ftype;
+ if ((ret = __dbreg_setup(dbp, name, id)) != 0)
+ goto err;
+ MAKE_INMEM(dbp);
+ goto skip_open;
+ }
+
+ if (opcode == DBREG_REOPEN) {
+ MAKE_INMEM(dbp);
+ fname = NULL;
+ dname = name;
+ }
+ if ((ret = __db_open(dbp, txn, fname, dname, ftype,
+ DB_DURABLE_UNKNOWN | DB_ODDFILESIZE,
+ __db_omode(OWNER_RW), meta_pgno)) == 0) {
+skip_open:
/*
* Verify that we are opening the same file that we were
* referring to when we wrote this log record.
@@ -500,7 +574,7 @@ __dbreg_do_open(dbenv,
if ((meta_pgno != PGNO_BASE_MD &&
__dbreg_check_master(dbenv, uid, name) != 0) ||
memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
- cstat = TXN_IGNORE;
+ cstat = TXN_UNEXPECTED;
else
cstat = TXN_EXPECTED;
@@ -518,7 +592,7 @@ __dbreg_do_open(dbenv,
ret = __db_txnlist_update(dbenv,
info, id, cstat, NULL, &ret_stat, 1);
-err: if (cstat == TXN_IGNORE)
+err: if (cstat == TXN_UNEXPECTED)
goto not_right;
return (ret);
} else if (ret == ENOENT) {
@@ -547,8 +621,8 @@ __dbreg_check_master(dbenv, uid, name)
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
return (ret);
F_SET(dbp, DB_AM_RECOVER);
- ret = __db_open(dbp,
- NULL, name, NULL, DB_BTREE, 0, __db_omode("rw----"), PGNO_BASE_MD);
+ ret = __db_open(dbp, NULL,
+ name, NULL, DB_BTREE, 0, __db_omode(OWNER_RW), PGNO_BASE_MD);
if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
ret = EINVAL;
@@ -569,6 +643,10 @@ __dbreg_check_master(dbenv, uid, name)
* at this point we have no way of knowing whether the log record that incited
* us to call this will be part of a committed transaction.
*
+ * We first revoke any old id this handle may have had. That can happen
+ * if a master becomes a client and then becomes a master again and
+ * there are other processes with valid open handles to this env.
+ *
* PUBLIC: int __dbreg_lazy_id __P((DB *));
*/
int
@@ -585,20 +663,28 @@ __dbreg_lazy_id(dbp)
dbenv = dbp->dbenv;
- DB_ASSERT(IS_REP_MASTER(dbenv));
+ DB_ASSERT(dbenv, IS_REP_MASTER(dbenv));
dbenv = dbp->dbenv;
dblp = dbenv->lg_handle;
lp = dblp->reginfo.primary;
fnp = dbp->log_filename;
- /* The fq_mutex protects the FNAME list and id management. */
- MUTEX_LOCK(dbenv, &lp->fq_mutex);
+ /* The mtx_filelist protects the FNAME list and id management. */
+ MUTEX_LOCK(dbenv, lp->mtx_filelist);
if (fnp->id != DB_LOGFILEID_INVALID) {
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (0);
}
id = DB_LOGFILEID_INVALID;
+ /*
+ * When we became master we moved the fnp->id to old_id in
+ * every FNAME structure that was open. If our id was changed,
+ * we need to revoke and give back that id.
+ */
+ if (fnp->old_id != DB_LOGFILEID_INVALID &&
+ (ret = __dbreg_revoke_id(dbp, 1, DB_LOGFILEID_INVALID)) != 0)
+ goto err;
if ((ret = __txn_begin(dbenv, NULL, &txn, 0)) != 0)
goto err;
@@ -612,7 +698,7 @@ __dbreg_lazy_id(dbp)
/*
* All DB related logging routines check the id value *without*
- * holding the fq_mutex to know whether we need to call
+ * holding the mtx_filelist to know whether we need to call
* dbreg_lazy_id to begin with. We must set the ID after a
* *successful* commit so that there is no possibility of a second
* modification call finding a valid ID in the dbp before the
@@ -624,6 +710,6 @@ __dbreg_lazy_id(dbp)
err:
if (ret != 0 && id != DB_LOGFILEID_INVALID)
(void)__dbreg_revoke_id(dbp, 1, id);
- MUTEX_UNLOCK(dbenv, &lp->fq_mutex);
+ MUTEX_UNLOCK(dbenv, lp->mtx_filelist);
return (ret);
}