diff options
author | jbj <devnull@localhost> | 2004-10-16 01:31:54 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2004-10-16 01:31:54 +0000 |
commit | d03f220fde879509cab2ac1c73b71b7efb52b737 (patch) | |
tree | 1e34bfadac0a6618d0e9a7933bad90063a785acf /db/dbreg | |
parent | 2dc699bfe049b9319ea3719f604d25940ff52004 (diff) | |
download | librpm-tizen-d03f220fde879509cab2ac1c73b71b7efb52b737.tar.gz librpm-tizen-d03f220fde879509cab2ac1c73b71b7efb52b737.tar.bz2 librpm-tizen-d03f220fde879509cab2ac1c73b71b7efb52b737.zip |
... and in with the New ...
CVS patchset: 7471
CVS date: 2004/10/16 01:31:54
Diffstat (limited to 'db/dbreg')
-rw-r--r-- | db/dbreg/dbreg.c | 181 | ||||
-rw-r--r-- | db/dbreg/dbreg.src | 6 | ||||
-rw-r--r-- | db/dbreg/dbreg_auto.c | 223 | ||||
-rw-r--r-- | db/dbreg/dbreg_autop.c | 89 | ||||
-rw-r--r-- | db/dbreg/dbreg_rec.c | 196 | ||||
-rw-r--r-- | db/dbreg/dbreg_stat.c | 97 | ||||
-rw-r--r-- | db/dbreg/dbreg_util.c | 237 |
7 files changed, 534 insertions, 495 deletions
diff --git a/db/dbreg/dbreg.c b/db/dbreg/dbreg.c index 4101e5e5a..76edd520c 100644 --- a/db/dbreg/dbreg.c +++ b/db/dbreg/dbreg.c @@ -1,14 +1,13 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2003 + * Copyright (c) 1996-2004 * Sleepycat Software. All rights reserved. + * + * $Id: dbreg.c,v 11.89 2004/09/22 03:43:09 bostic Exp $ */ -#include "db_config.h" -#ifndef lint -static const char revid[] = "$Id: dbreg.c,v 11.81 2003/10/27 15:54:31 sue Exp $"; -#endif /* not lint */ +#include "db_config.h" #ifndef NO_SYSTEM_INCLUDES #include <sys/types.h> @@ -22,6 +21,10 @@ static const char revid[] = "$Id: dbreg.c,v 11.81 2003/10/27 15:54:31 sue Exp $" #include "dbinc/txn.h" #include "dbinc/db_am.h" +static int __dbreg_push_id __P((DB_ENV *, int32_t)); +static int __dbreg_pop_id __P((DB_ENV *, int32_t *)); +static int __dbreg_pluck_id __P((DB_ENV *, int32_t)); + /* * The dbreg subsystem, as its name implies, registers database handles so * that we can associate log messages with them without logging a filename @@ -98,33 +101,33 @@ __dbreg_setup(dbp, name, create_txnid) DB_ENV *dbenv; DB_LOG *dblp; FNAME *fnp; + REGINFO *infop; int ret; size_t len; void *namep; dbenv = dbp->dbenv; dblp = dbenv->lg_handle; + infop = &dblp->reginfo; fnp = NULL; namep = NULL; /* Allocate an FNAME and, if necessary, a buffer for the name itself. */ - R_LOCK(dbenv, &dblp->reginfo); - if ((ret = - __db_shalloc(dblp->reginfo.addr, sizeof(FNAME), 0, &fnp)) != 0) + R_LOCK(dbenv, infop); + if ((ret = __db_shalloc(infop, sizeof(FNAME), 0, &fnp)) != 0) goto err; memset(fnp, 0, sizeof(FNAME)); if (name != NULL) { len = strlen(name) + 1; - if ((ret = - __db_shalloc(dblp->reginfo.addr, len, 0, &namep)) != 0) + if ((ret = __db_shalloc(infop, len, 0, &namep)) != 0) goto err; - fnp->name_off = R_OFFSET(&dblp->reginfo, namep); + fnp->name_off = R_OFFSET(dbenv, infop, namep); memcpy(namep, name, len); } else fnp->name_off = INVALID_ROFF; - R_UNLOCK(dbenv, &dblp->reginfo); + R_UNLOCK(dbenv, infop); /* * Fill in all the remaining info that we'll need later to register @@ -140,7 +143,7 @@ __dbreg_setup(dbp, name, create_txnid) return (0); -err: R_UNLOCK(dbenv, &dblp->reginfo); +err: R_UNLOCK(dbenv, infop); if (ret == ENOMEM) __db_err(dbenv, "Logging region out of memory; you may need to increase its size"); @@ -160,10 +163,12 @@ __dbreg_teardown(dbp) { DB_ENV *dbenv; DB_LOG *dblp; + REGINFO *infop; FNAME *fnp; dbenv = dbp->dbenv; dblp = dbenv->lg_handle; + infop = &dblp->reginfo; fnp = dbp->log_filename; /* @@ -175,12 +180,11 @@ __dbreg_teardown(dbp) DB_ASSERT(fnp->id == DB_LOGFILEID_INVALID); - R_LOCK(dbenv, &dblp->reginfo); + R_LOCK(dbenv, infop); if (fnp->name_off != INVALID_ROFF) - __db_shalloc_free(dblp->reginfo.addr, - R_ADDR(&dblp->reginfo, fnp->name_off)); - __db_shalloc_free(dblp->reginfo.addr, fnp); - R_UNLOCK(dbenv, &dblp->reginfo); + __db_shalloc_free(infop, R_ADDR(dbenv, infop, fnp->name_off)); + __db_shalloc_free(infop, fnp); + R_UNLOCK(dbenv, infop); dbp->log_filename = NULL; @@ -279,7 +283,7 @@ __dbreg_get_id(dbp, txn, idp) 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.data = R_ADDR(dbenv, &dblp->reginfo, fnp->name_off); r_name.size = (u_int32_t)strlen((char *)r_name.data) + 1; } fid_dbt.data = dbp->fileid; @@ -291,7 +295,7 @@ __dbreg_get_id(dbp, txn, idp) 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 + * log it again (as might happen if this is a replication client * that later upgrades to a master). */ fnp->create_txnid = TXN_INVALID; @@ -310,7 +314,7 @@ err: if (ret != 0 && id != DB_LOGFILEID_INVALID) { (void)__dbreg_revoke_id(dbp, 1, id); id = DB_LOGFILEID_INVALID; - } + } *idp = id; return (ret); } @@ -390,8 +394,13 @@ cont: if ((ret = __dbreg_pluck_id(dbenv, id)) != 0) fnp->is_durable = !F_ISSET(dbp, DB_AM_NOT_DURABLE); SH_TAILQ_INSERT_HEAD(&lp->fq, fnp, q, __fname); + /* + * If we get an error adding the dbentry, revoke the id. + * We void the return value since we want to retain and + * return the original error in ret anyway. + */ if ((ret = __dbreg_add_dbentry(dbenv, dblp, dbp, id)) != 0) - goto err; + (void)__dbreg_revoke_id(dbp, 1, id); err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex); @@ -466,12 +475,13 @@ __dbreg_revoke_id(dbp, have_lock, force_id) * Take a dbreg id away from a dbp that we're closing, and log * the unregistry. * - * PUBLIC: int __dbreg_close_id __P((DB *, DB_TXN *)); + * PUBLIC: int __dbreg_close_id __P((DB *, DB_TXN *, u_int32_t)); */ int -__dbreg_close_id(dbp, txn) +__dbreg_close_id(dbp, txn, op) DB *dbp; DB_TXN *txn; + u_int32_t op; { DBT fid_dbt, r_name, *dbtp; DB_ENV *dbenv; @@ -496,7 +506,7 @@ __dbreg_close_id(dbp, txn) dbtp = NULL; else { memset(&r_name, 0, sizeof(r_name)); - r_name.data = R_ADDR(&dblp->reginfo, fnp->name_off); + r_name.data = R_ADDR(dbenv, &dblp->reginfo, fnp->name_off); r_name.size = (u_int32_t)strlen((char *)r_name.data) + 1; dbtp = &r_name; @@ -506,7 +516,7 @@ __dbreg_close_id(dbp, txn) 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, - DBREG_CLOSE, dbtp, &fid_dbt, fnp->id, + op, dbtp, &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno, TXN_INVALID)) != 0) goto err; @@ -515,3 +525,122 @@ __dbreg_close_id(dbp, txn) err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex); return (ret); } + +/* + * __dbreg_push_id and __dbreg_pop_id -- + * Dbreg ids from closed files are kept on a stack in shared memory + * for recycling. (We want to reuse them as much as possible because each + * 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. + */ +static int +__dbreg_push_id(dbenv, id) + DB_ENV *dbenv; + int32_t id; +{ + DB_LOG *dblp; + LOG *lp; + REGINFO *infop; + int32_t *stack, *newstack; + int ret; + + dblp = dbenv->lg_handle; + infop = &dblp->reginfo; + lp = infop->primary; + + if (lp->free_fid_stack == INVALID_ROFF) { + stack = NULL; + DB_ASSERT(lp->free_fids_alloced == 0); + } else + stack = R_ADDR(dbenv, infop, lp->free_fid_stack); + + /* Check if we have room on the stack. */ + if (lp->free_fids_alloced <= lp->free_fids + 1) { + R_LOCK(dbenv, infop); + if ((ret = __db_shalloc(infop, + (lp->free_fids_alloced + 20) * sizeof(u_int32_t), 0, + &newstack)) != 0) { + R_UNLOCK(dbenv, infop); + return (ret); + } + + if (stack != NULL) { + memcpy(newstack, stack, + lp->free_fids_alloced * sizeof(u_int32_t)); + __db_shalloc_free(infop, stack); + } + stack = newstack; + lp->free_fid_stack = R_OFFSET(dbenv, infop, stack); + lp->free_fids_alloced += 20; + R_UNLOCK(dbenv, infop); + } + + stack[lp->free_fids++] = id; + return (0); +} + +static int +__dbreg_pop_id(dbenv, id) + DB_ENV *dbenv; + int32_t *id; +{ + DB_LOG *dblp; + LOG *lp; + int32_t *stack; + + dblp = dbenv->lg_handle; + lp = dblp->reginfo.primary; + + /* Do we have anything to pop? */ + if (lp->free_fid_stack != INVALID_ROFF && lp->free_fids > 0) { + stack = R_ADDR(dbenv, &dblp->reginfo, lp->free_fid_stack); + *id = stack[--lp->free_fids]; + } else + *id = DB_LOGFILEID_INVALID; + + return (0); +} + +/* + * __dbreg_pluck_id -- + * Remove a particular dbreg id from the stack of free ids. This is + * used when we open a file, as in recovery, with a specific ID that might + * 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. + */ +static int +__dbreg_pluck_id(dbenv, id) + DB_ENV *dbenv; + int32_t id; +{ + DB_LOG *dblp; + LOG *lp; + int32_t *stack; + u_int i; + + dblp = dbenv->lg_handle; + lp = dblp->reginfo.primary; + + /* Do we have anything to look at? */ + if (lp->free_fid_stack != INVALID_ROFF) { + stack = R_ADDR(dbenv, &dblp->reginfo, lp->free_fid_stack); + for (i = 0; i < lp->free_fids; i++) + if (id == stack[i]) { + /* + * Found it. Overwrite it with the top + * id (which may harmlessly be itself), + * and shorten the stack by one. + */ + stack[i] = stack[lp->free_fids - 1]; + lp->free_fids--; + return (0); + } + } + + return (0); +} diff --git a/db/dbreg/dbreg.src b/db/dbreg/dbreg.src index c2205958b..ff3fc2923 100644 --- a/db/dbreg/dbreg.src +++ b/db/dbreg/dbreg.src @@ -1,17 +1,15 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2003 + * Copyright (c) 1996-2004 * Sleepycat Software. All rights reserved. * - * $Id: dbreg.src,v 10.24 2003/04/24 14:19:17 bostic Exp $ + * $Id: dbreg.src,v 10.26 2004/06/17 17:35:17 bostic Exp $ */ PREFIX __dbreg DBPRIVATE -INCLUDE #include "db_config.h" -INCLUDE INCLUDE #ifndef NO_SYSTEM_INCLUDES INCLUDE #include <sys/types.h> INCLUDE diff --git a/db/dbreg/dbreg_auto.c b/db/dbreg/dbreg_auto.c index 857559c66..a9cc5f704 100644 --- a/db/dbreg/dbreg_auto.c +++ b/db/dbreg/dbreg_auto.c @@ -1,4 +1,5 @@ /* Do not edit: automatically built by gen_rec.awk. */ + #include "db_config.h" #ifndef NO_SYSTEM_INCLUDES @@ -39,31 +40,42 @@ __dbreg_register_log(dbenv, txnid, ret_lsnp, flags, { DBT logrec; DB_TXNLOGREC *lr; - DB_LSN *lsnp, null_lsn; + DB_LSN *lsnp, null_lsn, *rlsnp; u_int32_t zero, uinttmp, rectype, txn_num; u_int npad; u_int8_t *bp; int is_durable, ret; + COMPQUIET(lr, NULL); + rectype = DB___dbreg_register; npad = 0; + rlsnp = ret_lsnp; - is_durable = 1; - if (LF_ISSET(DB_LOG_NOT_DURABLE) || - F_ISSET(dbenv, DB_ENV_TXN_NOT_DURABLE)) { + ret = 0; + + if (LF_ISSET(DB_LOG_NOT_DURABLE)) { if (txnid == NULL) return (0); is_durable = 0; - } + } else + is_durable = 1; + if (txnid == NULL) { txn_num = 0; - null_lsn.file = 0; - null_lsn.offset = 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) 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; } @@ -82,27 +94,23 @@ __dbreg_register_log(dbenv, txnid, ret_lsnp, flags, logrec.size += npad; } - if (!is_durable && txnid != NULL) { + if (is_durable || txnid == NULL) { + if ((ret = + __os_malloc(dbenv, logrec.size, &logrec.data)) != 0) + return (ret); + } else { if ((ret = __os_malloc(dbenv, logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0) return (ret); #ifdef DIAGNOSTIC - goto do_malloc; -#else - logrec.data = &lr->data; -#endif - } else { -#ifdef DIAGNOSTIC -do_malloc: -#endif if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0) { -#ifdef DIAGNOSTIC - if (!is_durable && txnid != NULL) - (void)__os_free(dbenv, lr); -#endif + __os_free(dbenv, lr); return (ret); } +#else + logrec.data = lr->data; +#endif } if (npad > 0) memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad); @@ -162,139 +170,47 @@ do_malloc: DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + if (is_durable || txnid == NULL) { + if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec, + flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) { + txnid->last_lsn = *rlsnp; + if (rlsnp != ret_lsnp) + *ret_lsnp = *rlsnp; + } + } else { #ifdef DIAGNOSTIC - if (!is_durable && txnid != NULL) { - /* - * We set the debug bit if we are going - * to log non-durable transactions so - * they will be ignored by recovery. + /* + * Set the debug bit if we are going to log non-durable + * transactions so they will be ignored by recovery. */ memcpy(lr->data, logrec.data, logrec.size); rectype |= DB_debug_FLAG; memcpy(logrec.data, &rectype, sizeof(rectype)); - } -#endif - if (!is_durable && txnid != NULL) { + ret = __log_put(dbenv, + rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY); +#else ret = 0; - STAILQ_INSERT_HEAD(&txnid->logs, lr, links); -#ifdef DIAGNOSTIC - goto do_put; #endif - } else{ -#ifdef DIAGNOSTIC -do_put: -#endif - ret = __log_put(dbenv, - ret_lsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY); - if (ret == 0 && txnid != NULL) - txnid->last_lsn = *ret_lsnp; + STAILQ_INSERT_HEAD(&txnid->logs, lr, links); + LSN_NOT_LOGGED(*ret_lsnp); } - if (!is_durable) - LSN_NOT_LOGGED(*ret_lsnp); #ifdef LOG_DIAGNOSTIC if (ret != 0) (void)__dbreg_register_print(dbenv, (DBT *)&logrec, ret_lsnp, NULL, NULL); #endif -#ifndef DIAGNOSTIC + +#ifdef DIAGNOSTIC + __os_free(dbenv, logrec.data); +#else if (is_durable || txnid == NULL) -#endif __os_free(dbenv, logrec.data); - +#endif return (ret); } -#ifdef HAVE_REPLICATION -/* - * PUBLIC: int __dbreg_register_getpgnos __P((DB_ENV *, DBT *, - * PUBLIC: DB_LSN *, db_recops, void *)); - */ -int -__dbreg_register_getpgnos(dbenv, rec, lsnp, notused1, summary) - DB_ENV *dbenv; - DBT *rec; - DB_LSN *lsnp; - db_recops notused1; - void *summary; -{ - TXN_RECS *t; - int ret; - COMPQUIET(rec, NULL); - COMPQUIET(notused1, DB_TXN_ABORT); - - t = (TXN_RECS *)summary; - - if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0) - return (ret); - - t->array[t->npages].flags = LSN_PAGE_NOLOCK; - t->array[t->npages].lsn = *lsnp; - t->array[t->npages].fid = DB_LOGFILEID_INVALID; - memset(&t->array[t->npages].pgdesc, 0, - sizeof(t->array[t->npages].pgdesc)); - - t->npages++; - - return (0); -} -#endif /* HAVE_REPLICATION */ - -/* - * PUBLIC: int __dbreg_register_print __P((DB_ENV *, DBT *, DB_LSN *, - * PUBLIC: db_recops, void *)); - */ -int -__dbreg_register_print(dbenv, dbtp, lsnp, notused2, notused3) - DB_ENV *dbenv; - DBT *dbtp; - DB_LSN *lsnp; - db_recops notused2; - void *notused3; -{ - __dbreg_register_args *argp; - u_int32_t i; - int ch; - int ret; - - notused2 = DB_TXN_ABORT; - 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, - (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); - (void)printf("\topcode: %lu\n", (u_long)argp->opcode); - (void)printf("\tname: "); - for (i = 0; i < argp->name.size; i++) { - ch = ((u_int8_t *)argp->name.data)[i]; - printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); - } - (void)printf("\n"); - (void)printf("\tuid: "); - for (i = 0; i < argp->uid.size; i++) { - ch = ((u_int8_t *)argp->uid.data)[i]; - printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); - } - (void)printf("\n"); - (void)printf("\tfileid: %ld\n", (long)argp->fileid); - (void)printf("\tftype: 0x%lx\n", (u_long)argp->ftype); - (void)printf("\tmeta_pgno: %lu\n", (u_long)argp->meta_pgno); - (void)printf("\tid: 0x%lx\n", (u_long)argp->id); - (void)printf("\n"); - __os_free(dbenv, argp); - - return (0); -} - /* * PUBLIC: int __dbreg_register_read __P((DB_ENV *, void *, * PUBLIC: __dbreg_register_args **)); @@ -313,9 +229,9 @@ __dbreg_register_read(dbenv, recbuf, argpp) if ((ret = __os_malloc(dbenv, sizeof(__dbreg_register_args) + sizeof(DB_TXN), &argp)) != 0) return (ret); + bp = recbuf; argp->txnid = (DB_TXN *)&argp[1]; - bp = recbuf; memcpy(&argp->type, bp, sizeof(argp->type)); bp += sizeof(argp->type); @@ -362,45 +278,6 @@ __dbreg_register_read(dbenv, recbuf, argpp) } /* - * PUBLIC: int __dbreg_init_print __P((DB_ENV *, int (***)(DB_ENV *, - * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *)); - */ -int -__dbreg_init_print(dbenv, dtabp, dtabsizep) - DB_ENV *dbenv; - int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); - size_t *dtabsizep; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, - __dbreg_register_print, DB___dbreg_register)) != 0) - return (ret); - return (0); -} - -#ifdef HAVE_REPLICATION -/* - * PUBLIC: int __dbreg_init_getpgnos __P((DB_ENV *, - * PUBLIC: int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), - * PUBLIC: size_t *)); - */ -int -__dbreg_init_getpgnos(dbenv, dtabp, dtabsizep) - DB_ENV *dbenv; - int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); - size_t *dtabsizep; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, - __dbreg_register_getpgnos, DB___dbreg_register)) != 0) - return (ret); - return (0); -} -#endif /* HAVE_REPLICATION */ - -/* * PUBLIC: int __dbreg_init_recover __P((DB_ENV *, int (***)(DB_ENV *, * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *)); */ diff --git a/db/dbreg/dbreg_autop.c b/db/dbreg/dbreg_autop.c new file mode 100644 index 000000000..3889b357d --- /dev/null +++ b/db/dbreg/dbreg_autop.c @@ -0,0 +1,89 @@ +/* Do not edit: automatically built by gen_rec.awk. */ + +#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" +#include "dbinc/db_dispatch.h" +#include "dbinc/db_am.h" +#include "dbinc/log.h" +#include "dbinc/txn.h" + +/* + * PUBLIC: int __dbreg_register_print __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__dbreg_register_print(dbenv, dbtp, lsnp, notused2, notused3) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *notused3; +{ + __dbreg_register_args *argp; + u_int32_t i; + int ch; + int ret; + + notused2 = DB_TXN_ABORT; + 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, + (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); + (void)printf("\topcode: %lu\n", (u_long)argp->opcode); + (void)printf("\tname: "); + for (i = 0; i < argp->name.size; i++) { + ch = ((u_int8_t *)argp->name.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tuid: "); + for (i = 0; i < argp->uid.size; i++) { + ch = ((u_int8_t *)argp->uid.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tfileid: %ld\n", (long)argp->fileid); + (void)printf("\tftype: 0x%lx\n", (u_long)argp->ftype); + (void)printf("\tmeta_pgno: %lu\n", (u_long)argp->meta_pgno); + (void)printf("\tid: 0x%lx\n", (u_long)argp->id); + (void)printf("\n"); + __os_free(dbenv, argp); + return (0); +} + +/* + * PUBLIC: int __dbreg_init_print __P((DB_ENV *, int (***)(DB_ENV *, + * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *)); + */ +int +__dbreg_init_print(dbenv, dtabp, dtabsizep) + DB_ENV *dbenv; + int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t *dtabsizep; +{ + int ret; + + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __dbreg_register_print, DB___dbreg_register)) != 0) + return (ret); + return (0); +} diff --git a/db/dbreg/dbreg_rec.c b/db/dbreg/dbreg_rec.c index 3c81e29d7..07b175a1f 100644 --- a/db/dbreg/dbreg_rec.c +++ b/db/dbreg/dbreg_rec.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2003 + * Copyright (c) 1996-2004 * Sleepycat Software. All rights reserved. */ /* @@ -31,14 +31,12 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * 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 $ */ #include "db_config.h" -#ifndef lint -static const char revid[] = "$Id: dbreg_rec.c,v 11.120 2003/10/27 15:54:31 sue Exp $"; -#endif /* not lint */ - #ifndef NO_SYSTEM_INCLUDES #include <sys/types.h> @@ -52,7 +50,6 @@ static const char revid[] = "$Id: dbreg_rec.c,v 11.120 2003/10/27 15:54:31 sue E #include "dbinc/log.h" #include "dbinc/mp.h" #include "dbinc/txn.h" -#include "dbinc/qam.h" static int __dbreg_open_file __P((DB_ENV *, DB_TXN *, __dbreg_register_args *, void *)); @@ -74,6 +71,7 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info) DB *dbp; __dbreg_register_args *argp; int do_close, do_open, do_rem, ret, t_ret; + u_int32_t status; dblp = dbenv->lg_handle; dbp = NULL; @@ -93,7 +91,6 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info) else do_close = 1; break; - case DBREG_CLOSE: if (DB_UNDO(op)) do_open = 1; @@ -114,12 +111,15 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info) else do_close = 1; break; - case DBREG_CHKPNT: if (DB_UNDO(op) || op == DB_TXN_OPENFILES || op == DB_TXN_POPENFILES) do_open = 1; break; + default: + DB_ASSERT(0); + ret = EINVAL; + break; } if (do_open) { @@ -138,6 +138,8 @@ __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); + if (ret == DB_PAGE_NOTFOUND && argp->meta_pgno != PGNO_BASE_MD) + ret = ENOENT; if (ret == ENOENT || ret == EINVAL) { /* * If this is an OPEN while rolling forward, it's @@ -152,6 +154,9 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info) dblp->dbentry[argp->fileid].deleted = 0; ret = __dbreg_open_file(dbenv, NULL, argp, info); + if (ret == DB_PAGE_NOTFOUND && + argp->meta_pgno != PGNO_BASE_MD) + ret = ENOENT; } /* * We treat ENOENT as OK since it's possible that @@ -190,11 +195,15 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info) * recovery, it's possible that we failed after * the log record, but before we actually entered * a handle here. + * 3. If we aborted an open, then we wrote a non-txnal + * RCLOSE into the log. During the forward pass, the + * file won't be open, and that's OK. */ dbe = &dblp->dbentry[argp->fileid]; if (dbe->dbp == NULL && !dbe->deleted) { /* No valid entry here. */ - if (DB_REDO(op) || + if ((DB_REDO(op) && + argp->opcode != DBREG_RCLOSE) || argp->opcode == DBREG_CHKPNT) { __db_err(dbenv, "Improper file close at %lu/%lu", @@ -208,64 +217,70 @@ __dbreg_register_recover(dbenv, dbtp, lsnp, op, info) /* We have either an open entry or a deleted entry. */ if ((dbp = dbe->dbp) != NULL) { - MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); - (void)__dbreg_revoke_id(dbp, 0, - DB_LOGFILEID_INVALID); - /* * If we're a replication client, it's * possible to get here with a dbp that * the user opened, but which we later * assigned a fileid to. Be sure that * we only close dbps that we opened in - * the recovery code; they should have - * DB_AM_RECOVER set. - * - * The only exception is if we're aborting - * in a normal environment; then we might - * get here with a non-AM_RECOVER database. + * the recovery code or that were opened + * inside a currently aborting transaction. */ - if (F_ISSET(dbp, DB_AM_RECOVER) || - op == DB_TXN_ABORT) - do_rem = 1; + do_rem = F_ISSET(dbp, DB_AM_RECOVER) || + op == DB_TXN_ABORT; + MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); + if (op == DB_TXN_ABORT) + (void)__dbreg_close_id(dbp, + NULL, DBREG_RCLOSE); + else + (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); } } else MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); - if (do_rem) { - /* - * During recovery, all files are closed. On an abort, - * we only close the file if we opened it during the - * abort (DB_AM_RECOVER set), otherwise we simply do - * a __db_refresh. For the close case, if remove or - * rename has closed the file, don't request a sync, - * because the NULL mpf would be a problem. - */ - if (dbp != NULL) { - /* - * If we are undoing a create we'd better - * discard any buffers from the memory pool. - * We identify creates because the argp->id - * field contains the transaction containing - * the file create; if that id is invalid, we - * are not creating. - */ - if (argp->id != TXN_INVALID) + /* + * During recovery, all files are closed. On an abort, we only + * close the file if we opened it during the abort + * (DB_AM_RECOVER set), otherwise we simply do a __db_refresh. + * For the close case, if remove or rename has closed the file, + * don't request a sync, because a NULL mpf would be a problem. + * + * If we are undoing a create we'd better discard any buffers + * from the memory pool. We identify creates because the + * argp->id field contains the transaction containing the file + * create; if that id is invalid, we are not creating. + * + * On the backward pass, we need to "undo" opens even if the + * transaction in which they appeared committed, because we have + * already undone the corresponding close. In that case, the + * id will be valid, but we do not want to discard buffers. + */ + if (do_rem && dbp != NULL) { + if (argp->id != TXN_INVALID) { + if ((ret = __db_txnlist_find(dbenv, + info, argp->txnid->txnid, &status)) + != DB_NOTFOUND && ret != 0) + goto out; + if (ret == DB_NOTFOUND || status != TXN_COMMIT) F_SET(dbp, DB_AM_DISCARD); - if (op == DB_TXN_ABORT && - !F_ISSET(dbp, DB_AM_RECOVER)) - t_ret = __db_refresh(dbp, - NULL, DB_NOSYNC, NULL); - else { - if (op == DB_TXN_APPLY) - __db_sync(dbp); - t_ret = - __db_close(dbp, NULL, DB_NOSYNC); - } - if (t_ret != 0 && ret == 0) + ret = 0; + } + + if (op == DB_TXN_ABORT && + !F_ISSET(dbp, DB_AM_RECOVER)) { + if ((t_ret = __db_refresh(dbp, + NULL, DB_NOSYNC, NULL)) != 0 && ret == 0) + ret = t_ret; + } else { + if (op == DB_TXN_APPLY && + (t_ret = __db_sync(dbp)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __db_close( + dbp, NULL, DB_NOSYNC)) != 0 && ret == 0) ret = t_ret; } } @@ -291,49 +306,51 @@ __dbreg_open_file(dbenv, txn, argp, info) void *info; { DB_ENTRY *dbe; - DB_LOG *lp; + DB_LOG *dblp; DB *dbp; - u_int32_t id; + u_int32_t id, status; + int ret; - lp = (DB_LOG *)dbenv->lg_handle; - /* - * We never re-open temporary files. Temp files are only - * useful during aborts in which case the dbp was entered - * when the file was registered. During recovery, we treat - * temp files as properly deleted files, allowing the open to - * fail and not reporting any errors when recovery fails to - * get a valid dbp from __dbreg_id_to_db. - */ - if (argp->name.size == 0) { - (void)__dbreg_add_dbentry(dbenv, lp, NULL, argp->fileid); - return (ENOENT); - } + dblp = (DB_LOG *)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, lp->mutexp); - if (argp->fileid < lp->dbentry_cnt) - dbe = &lp->dbentry[argp->fileid]; + MUTEX_THREAD_LOCK(dbenv, dblp->mutexp); + if (argp->fileid < dblp->dbentry_cnt) + dbe = &dblp->dbentry[argp->fileid]; else dbe = NULL; if (dbe != NULL) { if (dbe->deleted) { - MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp); + MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); return (ENOENT); } + + /* + * At the end of OPENFILES, we may have a file open. 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 + * three ways we can detect this. 1) the meta-pgno in the + * current file does not match that of the open file, 2) the + * file uid of the current file does not match that of the + * previously opened file, 3) the current file is unnamed, in + * which case it should never be opened during recovery. + */ if ((dbp = dbe->dbp) != NULL) { if (dbp->meta_pgno != argp->meta_pgno || - memcmp(dbp->fileid, - argp->uid.data, DB_FILE_ID_LEN) != 0) { - MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp); + argp->name.size == 0 || + memcmp(dbp->fileid, argp->uid.data, + DB_FILE_ID_LEN) != 0) { + MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); (void)__dbreg_revoke_id(dbp, 0, DB_LOGFILEID_INVALID); if (F_ISSET(dbp, DB_AM_RECOVER)) - __db_close(dbp, NULL, DB_NOSYNC); + (void)__db_close(dbp, NULL, DB_NOSYNC); goto reopen; } @@ -343,7 +360,7 @@ __dbreg_open_file(dbenv, txn, argp, info) * here had better be the same dbp. */ DB_ASSERT(dbe->dbp == dbp); - MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp); + MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); /* * This is a successful open. We need to record that @@ -351,27 +368,40 @@ __dbreg_open_file(dbenv, txn, argp, info) * subtransaction that created the file system object. */ if (argp->id != TXN_INVALID && - __db_txnlist_update(dbenv, info, - argp->id, TXN_EXPECTED, NULL) == TXN_NOTFOUND) - (void)__db_txnlist_add(dbenv, - info, argp->id, TXN_EXPECTED, NULL); + (ret = __db_txnlist_update(dbenv, info, + argp->id, TXN_EXPECTED, NULL, &status, 1)) != 0) + return (ret); return (0); } } - MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp); + MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); + +reopen: + /* + * We never re-open temporary files. Temp files are only useful during + * aborts in which case the dbp was entered when the file was + * registered. During recovery, we treat temp files as properly deleted + * files, allowing the open to fail and not reporting any errors when + * recovery fails to get a valid dbp from __dbreg_id_to_db. + */ + if (argp->name.size == 0) { + (void)__dbreg_add_dbentry(dbenv, dblp, NULL, argp->fileid); + return (ENOENT); + } /* * We are about to pass a recovery txn pointer into the main library. * We need to make sure that any accessed fields are set appropriately. */ -reopen: if (txn != NULL) { + if (txn != NULL) { id = txn->txnid; memset(txn, 0, sizeof(DB_TXN)); txn->txnid = id; txn->mgrp = dbenv->tx_handle; } - return (__dbreg_do_open(dbenv, txn, lp, argp->uid.data, argp->name.data, + return (__dbreg_do_open(dbenv, + txn, dblp, argp->uid.data, argp->name.data, argp->ftype, argp->fileid, argp->meta_pgno, info, argp->id)); } diff --git a/db/dbreg/dbreg_stat.c b/db/dbreg/dbreg_stat.c new file mode 100644 index 000000000..d033d7ea1 --- /dev/null +++ b/db/dbreg/dbreg_stat.c @@ -0,0 +1,97 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997-2004 + * Sleepycat Software. All rights reserved. + * + * $Id: dbreg_stat.c,v 11.47 2004/09/22 03:43:09 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/log.h" +#include "dbinc/txn.h" + +#ifdef HAVE_STATISTICS +/* + * __dbreg_print_fname -- + * Display the contents of an FNAME structure. + * + * PUBLIC: void __dbreg_print_fname __P((DB_ENV *, FNAME *)); + */ +void +__dbreg_print_fname(dbenv, fnp) + DB_ENV *dbenv; + FNAME *fnp; +{ + __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); +} + +/* + * __dbreg_print_dblist -- + * Display the DB_ENV's list of files. + * + * PUBLIC: void __dbreg_print_dblist __P((DB_ENV *, u_int32_t)); + */ +void +__dbreg_print_dblist(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + DB *dbp; + DB_LOG *dblp; + FNAME *fnp; + LOG *lp; + int del, first; + char *name; + + dblp = dbenv->lg_handle; + lp = dblp->reginfo.primary; + + __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); + + 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)) { + if (first) { + first = 0; + __db_msg(dbenv, + "ID\tName\tType\tPgno\tTxnid\tDBP-info"); + } + if (fnp->name_off == INVALID_ROFF) + name = ""; + else + name = R_ADDR(dbenv, &dblp->reginfo, fnp->name_off); + + dbp = fnp->id >= dblp->dbentry_cnt ? NULL : + dblp->dbentry[fnp->id].dbp; + del = fnp->id >= dblp->dbentry_cnt ? 0 : + dblp->dbentry[fnp->id].deleted; + __db_msg(dbenv, "%ld\t%s\t%s\t%lu\t%lx\t%s %d %lx %lx", + (long)fnp->id, name, + __db_dbtype_to_string(fnp->s_type), + (u_long)fnp->meta_pgno, (u_long)fnp->create_txnid, + dbp == NULL ? "No DBP" : "DBP", del, P_TO_ULONG(dbp), + (u_long)(dbp == NULL ? 0 : dbp->flags)); + } + MUTEX_UNLOCK(dbenv, &lp->fq_mutex); +} +#endif diff --git a/db/dbreg/dbreg_util.c b/db/dbreg/dbreg_util.c index 6e21c35f3..c0d36ef17 100644 --- a/db/dbreg/dbreg_util.c +++ b/db/dbreg/dbreg_util.c @@ -1,16 +1,14 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997-2003 + * Copyright (c) 1997-2004 * Sleepycat Software. All rights reserved. + * + * $Id: dbreg_util.c,v 11.49 2004/09/22 03:43:09 bostic Exp $ */ #include "db_config.h" -#ifndef lint -static const char revid[] = "$Id: dbreg_util.c,v 11.39 2003/11/10 17:42:34 sue Exp $"; -#endif /* not lint */ - #ifndef NO_SYSTEM_INCLUDES #include <sys/types.h> #include <string.h> @@ -51,7 +49,7 @@ __dbreg_add_dbentry(dbenv, dblp, dbp, ndx) */ if (dblp->dbentry_cnt <= ndx) { if ((ret = __os_realloc(dbenv, - (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY), + (size_t)(ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY), &dblp->dbentry)) != 0) goto err; @@ -91,13 +89,13 @@ __dbreg_rem_dbentry(dblp, ndx) } /* - * __dbreg_open_files -- - * Put a DBREG_CHKPNT log record for each open database. + * __dbreg_log_files -- + * Put a DBREG_CHKPNT/CLOSE log record for each open database. * - * PUBLIC: int __dbreg_open_files __P((DB_ENV *)); + * PUBLIC: int __dbreg_log_files __P((DB_ENV *)); */ int -__dbreg_open_files(dbenv) +__dbreg_log_files(dbenv) DB_ENV *dbenv; { DB_LOG *dblp; @@ -121,7 +119,7 @@ __dbreg_open_files(dbenv) dbtp = NULL; else { memset(&t, 0, sizeof(t)); - t.data = R_ADDR(&dblp->reginfo, fnp->name_off); + t.data = R_ADDR(dbenv, &dblp->reginfo, fnp->name_off); t.size = (u_int32_t)strlen(t.data) + 1; dbtp = &t; } @@ -185,9 +183,9 @@ __dbreg_close_files(dbenv) * so that we don't end up leaving around FNAME entries * for dbps that shouldn't have them. */ - if ((dbp = dblp->dbentry[i].dbp) != NULL) { + if ((dbp = dblp->dbentry[i].dbp) != NULL) { /* - * It's unsafe to call DB->close or revoke_id + * It's unsafe to call DB->close or revoke_id * while holding the thread lock, because * we'll call __dbreg_rem_dbentry and grab it again. * @@ -302,7 +300,7 @@ __dbreg_id_to_db_int(dbenv, txn, dbpp, ndx, inc, tryopen) * assumption, because 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); + name = R_ADDR(dbenv, &dblp->reginfo, fname->name_off); /* * At this point, we are not holding the thread lock, so exit @@ -346,9 +344,9 @@ err: MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp); * PUBLIC: int __dbreg_id_to_fname __P((DB_LOG *, int32_t, int, FNAME **)); */ int -__dbreg_id_to_fname(dblp, lid, have_lock, fnamep) +__dbreg_id_to_fname(dblp, id, have_lock, fnamep) DB_LOG *dblp; - int32_t lid; + int32_t id; int have_lock; FNAME **fnamep; { @@ -366,7 +364,7 @@ __dbreg_id_to_fname(dblp, lid, have_lock, fnamep) MUTEX_LOCK(dbenv, &lp->fq_mutex); for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname); fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { - if (fnp->id == lid) { + if (fnp->id == id) { *fnamep = fnp; ret = 0; break; @@ -433,12 +431,12 @@ __dbreg_get_name(dbenv, fid, namep) char **namep; { DB_LOG *dblp; - FNAME *fname; + FNAME *fnp; dblp = dbenv->lg_handle; - if (dblp != NULL && __dbreg_fid_to_fname(dblp, fid, 0, &fname) == 0) { - *namep = R_ADDR(&dblp->reginfo, fname->name_off); + if (dblp != NULL && __dbreg_fid_to_fname(dblp, fid, 0, &fnp) == 0) { + *namep = R_ADDR(dbenv, &dblp->reginfo, fnp->name_off); return (0); } @@ -467,8 +465,8 @@ __dbreg_do_open(dbenv, u_int32_t id; { DB *dbp; + u_int32_t cstat, ret_stat; int ret; - u_int32_t cstat; if ((ret = db_create(&dbp, lp->dbenv, 0)) != 0) return (ret); @@ -516,26 +514,21 @@ __dbreg_do_open(dbenv, * know how to handle the subtransaction that created * the file system object. */ - if (id != TXN_INVALID) { - if ((ret = __db_txnlist_update(dbenv, - info, id, cstat, NULL)) == TXN_NOTFOUND) - ret = __db_txnlist_add(dbenv, - info, id, cstat, NULL); - else if (ret > 0) - ret = 0; - } + if (id != TXN_INVALID) + ret = __db_txnlist_update(dbenv, + info, id, cstat, NULL, &ret_stat, 1); + err: if (cstat == TXN_IGNORE) goto not_right; return (ret); } else if (ret == ENOENT) { /* Record that the open failed in the txnlist. */ - if (id != TXN_INVALID && (ret = __db_txnlist_update(dbenv, - info, id, TXN_UNEXPECTED, NULL)) == TXN_NOTFOUND) - ret = __db_txnlist_add(dbenv, - info, id, TXN_UNEXPECTED, NULL); + if (id != TXN_INVALID) + ret = __db_txnlist_update(dbenv, info, + id, TXN_UNEXPECTED, NULL, &ret_stat, 1); } not_right: - (void)__db_close(dbp, NULL, 0); + (void)__db_close(dbp, NULL, DB_NOSYNC); /* Add this file as deleted. */ (void)__dbreg_add_dbentry(dbenv, lp, NULL, ndx); return (ret); @@ -625,7 +618,7 @@ __dbreg_lazy_id(dbp) * modification call finding a valid ID in the dbp before the * dbreg_register and commit records are in the log. * If there was an error, then we call __dbreg_revoke_id to - * remove the entry from the lists. + * remove the entry from the lists. */ fnp->id = id; err: @@ -634,177 +627,3 @@ err: MUTEX_UNLOCK(dbenv, &lp->fq_mutex); return (ret); } - -/* - * __dbreg_push_id and __dbreg_pop_id -- - * Dbreg ids from closed files are kept on a stack in shared memory - * for recycling. (We want to reuse them as much as possible because each - * 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. - * - * PUBLIC: int __dbreg_push_id __P((DB_ENV *, int32_t)); - * PUBLIC: int __dbreg_pop_id __P((DB_ENV *, int32_t *)); - */ -int -__dbreg_push_id(dbenv, id) - DB_ENV *dbenv; - int32_t id; -{ - DB_LOG *dblp; - LOG *lp; - int32_t *stack, *newstack; - int ret; - - dblp = dbenv->lg_handle; - lp = dblp->reginfo.primary; - - if (lp->free_fid_stack != INVALID_ROFF) - stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack); - else - stack = NULL; - - /* Check if we have room on the stack. */ - if (lp->free_fids_alloced <= lp->free_fids + 1) { - R_LOCK(dbenv, &dblp->reginfo); - if ((ret = __db_shalloc(dblp->reginfo.addr, - (lp->free_fids_alloced + 20) * sizeof(u_int32_t), 0, - &newstack)) != 0) { - R_UNLOCK(dbenv, &dblp->reginfo); - return (ret); - } - - memcpy(newstack, stack, - lp->free_fids_alloced * sizeof(u_int32_t)); - lp->free_fid_stack = R_OFFSET(&dblp->reginfo, newstack); - lp->free_fids_alloced += 20; - - if (stack != NULL) - __db_shalloc_free(dblp->reginfo.addr, stack); - - stack = newstack; - R_UNLOCK(dbenv, &dblp->reginfo); - } - - DB_ASSERT(stack != NULL); - stack[lp->free_fids++] = id; - return (0); -} - -int -__dbreg_pop_id(dbenv, id) - DB_ENV *dbenv; - int32_t *id; -{ - DB_LOG *dblp; - LOG *lp; - int32_t *stack; - - dblp = dbenv->lg_handle; - lp = dblp->reginfo.primary; - - /* Do we have anything to pop? */ - if (lp->free_fid_stack != INVALID_ROFF && lp->free_fids > 0) { - stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack); - *id = stack[--lp->free_fids]; - } else - *id = DB_LOGFILEID_INVALID; - - return (0); -} - -/* - * __dbreg_pluck_id -- - * Remove a particular dbreg id from the stack of free ids. This is - * used when we open a file, as in recovery, with a specific ID that might - * 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. - * - * PUBLIC: int __dbreg_pluck_id __P((DB_ENV *, int32_t)); - */ -int -__dbreg_pluck_id(dbenv, id) - DB_ENV *dbenv; - int32_t id; -{ - DB_LOG *dblp; - LOG *lp; - int32_t *stack; - int i; - - dblp = dbenv->lg_handle; - lp = dblp->reginfo.primary; - - /* Do we have anything to look at? */ - if (lp->free_fid_stack != INVALID_ROFF) { - stack = R_ADDR(&dblp->reginfo, lp->free_fid_stack); - for (i = 0; i < lp->free_fids; i++) - if (id == stack[i]) { - /* - * Found it. Overwrite it with the top - * id (which may harmlessly be itself), - * and shorten the stack by one. - */ - stack[i] = stack[lp->free_fids - 1]; - lp->free_fids--; - return (0); - } - } - - return (0); -} - -#ifdef DEBUG -/* - * __dbreg_print_dblist -- - * Display the list of files. - * - * PUBLIC: void __dbreg_print_dblist __P((DB_ENV *)); - */ -void -__dbreg_print_dblist(dbenv) - DB_ENV *dbenv; -{ - DB *dbp; - DB_LOG *dblp; - FNAME *fnp; - LOG *lp; - int del, first; - char *name; - - dblp = dbenv->lg_handle; - lp = dblp->reginfo.primary; - - 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)) { - if (first) { - first = 0; - __db_err(dbenv, - "ID\t\t\tName\tType\tPgno\tTxnid\tDBP-info"); - } - if (fnp->name_off == INVALID_ROFF) - name = ""; - else - name = R_ADDR(&dblp->reginfo, fnp->name_off); - - dbp = fnp->id >= dblp->dbentry_cnt ? NULL : - dblp->dbentry[fnp->id].dbp; - del = fnp->id >= dblp->dbentry_cnt ? 0 : - dblp->dbentry[fnp->id].deleted; - __db_err(dbenv, "%ld\t%s\t\t\t%s\t%lu\t%lx\t%s %d %lx %lx", - (long)fnp->id, name, - __db_dbtype_to_string(fnp->s_type), - (u_long)fnp->meta_pgno, (u_long)fnp->create_txnid, - dbp == NULL ? "No DBP" : "DBP", del, P_TO_ULONG(dbp), - (u_long)(dbp == NULL ? 0 : dbp->flags)); - } - - MUTEX_UNLOCK(dbenv, &lp->fq_mutex); -} -#endif |