summary refs log tree commit diff
path: root/db2/log
diff options
context:
space:
mode:
Diffstat (limited to 'db2/log')
-rw-r--r--db2/log/log.c67
-rw-r--r--db2/log/log.src9
-rw-r--r--db2/log/log_archive.c4
-rw-r--r--db2/log/log_auto.c140
-rw-r--r--db2/log/log_get.c26
-rw-r--r--db2/log/log_put.c13
-rw-r--r--db2/log/log_rec.c102
-rw-r--r--db2/log/log_register.c55
8 files changed, 139 insertions, 277 deletions
diff --git a/db2/log/log.c b/db2/log/log.c
index a9bf7a95ab..8013d42aef 100644
--- a/db2/log/log.c
+++ b/db2/log/log.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log.c	10.34 (Sleepycat) 11/28/97";
+static const char sccsid[] = "@(#)log.c	10.39 (Sleepycat) 1/17/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -203,28 +203,21 @@ __log_recover(dblp)
 	 * Find a log file.  If none exist, we simply return, leaving
 	 * everything initialized to a new log.
 	 */
-	if ((ret = __log_find(dblp, &cnt)) != 0)
+	if ((ret = __log_find(dblp, 0, &cnt)) != 0)
 		return (ret);
 	if (cnt == 0)
 		return (0);
 
-	/* We have a log file name, find the last one. */
-	while (cnt < MAXLFNAME)
-		if (__log_valid(dblp, lp, ++cnt) != 0) {
-			--cnt;
-			break;
-		}
-
 	/*
 	 * We have the last useful log file and we've loaded any persistent
 	 * information.  Pretend that the log is larger than it can possibly
-	 * be, and read this file, looking for a checkpoint and its end.
+	 * be, and read the last file, looking for the last checkpoint and
+	 * the log's end.
 	 */
-	dblp->c_lsn.file = cnt;
-	dblp->c_lsn.offset = 0;
-	lsn = dblp->c_lsn;
 	lp->lsn.file = cnt + 1;
 	lp->lsn.offset = 0;
+	lsn.file = cnt;
+	lsn.offset = 0;
 
 	/* Set the cursor.  Shouldn't fail, leave error messages on. */
 	memset(&dbt, 0, sizeof(dbt));
@@ -264,9 +257,8 @@ __log_recover(dblp)
 	 * one in the last log file.  Start searching.
 	 */
 	while (!found_checkpoint && cnt > 1) {
-		dblp->c_lsn.file = --cnt;
-		dblp->c_lsn.offset = 0;
-		lsn = dblp->c_lsn;
+		lsn.file = --cnt;
+		lsn.offset = 0;
 
 		/* Set the cursor.  Shouldn't fail, leave error messages on. */
 		if ((ret = __log_get(dblp, &lsn, &dbt, DB_SET, 0)) != 0)
@@ -288,36 +280,35 @@ __log_recover(dblp)
 	}
 
 	/* If we never find a checkpoint, that's okay, just 0 it out. */
-	if (!found_checkpoint) {
-		lp->c_lsn.file = 1;
-		lp->c_lsn.offset = 0;
-	}
+	if (!found_checkpoint)
+		ZERO_LSN(lp->c_lsn);
 
 	__db_err(dblp->dbenv,
 	    "Recovering the log: last valid LSN: file: %lu offset %lu",
 	    (u_long)lp->lsn.file, (u_long)lp->lsn.offset);
 
-	/* Reset the cursor.  */
-	ZERO_LSN(dblp->c_lsn);
-
 	return (0);
 }
 
 /*
  * __log_find --
- *	Try to find a log file.
+ *	Try to find a log file.  If find_first is set, valp will contain
+ * the number of the first log file, else it will contain the number of
+ * the last log file.
  *
- * PUBLIC: int __log_find __P((DB_LOG *, int *));
+ * PUBLIC: int __log_find __P((DB_LOG *, int, int *));
  */
 int
-__log_find(dblp, valp)
+__log_find(dblp, find_first, valp)
 	DB_LOG *dblp;
-	int *valp;
+	int find_first, *valp;
 {
 	int cnt, fcnt, logval, ret;
 	const char *dir;
 	char **names, *p, *q;
 
+	*valp = 0;
+
 	/* Find the directory name. */
 	if ((ret = __log_name(dblp, 1, &p)) != 0)
 		return (ret);
@@ -340,21 +331,29 @@ __log_find(dblp, valp)
 	 * Search for a valid log file name, return a value of 0 on
 	 * failure.
 	 */
-	*valp = 0;
 	for (cnt = fcnt, logval = 0; --cnt >= 0;)
 		if (strncmp(names[cnt], "log.", sizeof("log.") - 1) == 0) {
 			logval = atoi(names[cnt] + 4);
 			if (logval != 0 &&
-			    __log_valid(dblp, dblp->lp, logval) == 0) {
-				*valp = logval;
+			    __log_valid(dblp, dblp->lp, logval) == 0)
 				break;
-			}
 		}
 
 	/* Discard the list. */
 	__db_dirfree(names, fcnt);
 
-	return (ret);
+	/* We have a valid log file, find either the first or last one. */
+	if (find_first) {
+		for (; logval > 0; --logval)
+			if (__log_valid(dblp, dblp->lp, logval - 1) != 0)
+				break;
+	} else
+		for (; logval < MAXLFNAME; ++logval)
+			if (__log_valid(dblp, dblp->lp, logval + 1) != 0)
+				break;
+	*valp = logval;
+
+	return (0);
 }
 
 /*
@@ -508,6 +507,10 @@ log_stat(dblp, gspp, db_malloc)
 
 	(*gspp)->st_region_nowait = lp->rlayout.lock.mutex_set_nowait;
 	(*gspp)->st_region_wait = lp->rlayout.lock.mutex_set_wait;
+
+	(*gspp)->st_cur_file = lp->lsn.file;
+	(*gspp)->st_cur_offset = lp->lsn.offset;
+
 	UNLOCK_LOGREGION(dblp);
 
 	return (0);
diff --git a/db2/log/log.src b/db2/log/log.src
index 9f4829179b..f3d9f32b2d 100644
--- a/db2/log/log.src
+++ b/db2/log/log.src
@@ -4,7 +4,7 @@
  * Copyright (c) 1996, 1997
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)log.src	10.3 (Sleepycat) 8/20/97
+ *	@(#)log.src	10.4 (Sleepycat) 1/17/98
  *
  * This is the source file used to create the logging functions for the
  * log package.  Each access method (or set of routines wishing to register
@@ -40,14 +40,11 @@
  */
 PREFIX	log
 
-/* Used for registering new name/id translations. */
+/* Used for registering name/id translations at open or close. */
 BEGIN	register
+ARG	opcode		u_int32_t	lu
 DBT	name		DBT		s
 DBT	uid		DBT		s
 ARG	id		u_int32_t	lu
 ARG	ftype		DBTYPE		lx
 END
-
-BEGIN	unregister
-ARG	id		u_int32_t	lu
-END
diff --git a/db2/log/log_archive.c b/db2/log/log_archive.c
index 0248e2815c..91ae5abe0b 100644
--- a/db2/log/log_archive.c
+++ b/db2/log/log_archive.c
@@ -8,7 +8,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_archive.c	10.29 (Sleepycat) 11/12/97";
+static const char sccsid[] = "@(#)log_archive.c	10.30 (Sleepycat) 1/8/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -49,7 +49,7 @@ log_archive(dblp, listp, flags, db_malloc)
 	int array_size, n, ret;
 	char **array, **arrayp, *name, *p, *pref, buf[MAXPATHLEN];
 
-	fnum = 0;				/* XXX: Shut the compiler up. */
+	COMPQUIET(fnum, 0);
 
 #define	OKFLAGS	(DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG)
 	if (flags != 0) {
diff --git a/db2/log/log_auto.c b/db2/log/log_auto.c
index 61626b090e..2fe17834c3 100644
--- a/db2/log/log_auto.c
+++ b/db2/log/log_auto.c
@@ -20,16 +20,18 @@
 /*
  * PUBLIC: int __log_register_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
- * PUBLIC:     DBT *, DBT *, u_int32_t, DBTYPE));
+ * PUBLIC:     u_int32_t, const DBT *, const DBT *, u_int32_t,
+ * PUBLIC:     DBTYPE));
  */
 int __log_register_log(logp, txnid, ret_lsnp, flags,
-	name, uid, id, ftype)
+	opcode, name, uid, id, ftype)
 	DB_LOG *logp;
 	DB_TXN *txnid;
 	DB_LSN *ret_lsnp;
 	u_int32_t flags;
-	DBT *name;
-	DBT *uid;
+	u_int32_t opcode;
+	const DBT *name;
+	const DBT *uid;
 	u_int32_t id;
 	DBTYPE ftype;
 {
@@ -49,6 +51,7 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
 	} else
 		lsnp = &txnid->last_lsn;
 	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+	    + sizeof(opcode)
 	    + sizeof(u_int32_t) + (name == NULL ? 0 : name->size)
 	    + sizeof(u_int32_t) + (uid == NULL ? 0 : uid->size)
 	    + sizeof(id)
@@ -63,6 +66,8 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
 	bp += sizeof(txn_num);
 	memcpy(bp, lsnp, sizeof(DB_LSN));
 	bp += sizeof(DB_LSN);
+	memcpy(bp, &opcode, sizeof(opcode));
+	bp += sizeof(opcode);
 	if (name == NULL) {
 		zero = 0;
 		memcpy(bp, &zero, sizeof(u_int32_t));
@@ -129,6 +134,7 @@ __log_register_print(notused1, dbtp, lsnp, notused3, notused4)
 	    (u_long)argp->txnid->txnid,
 	    (u_long)argp->prev_lsn.file,
 	    (u_long)argp->prev_lsn.offset);
+	printf("\topcode: %lu\n", (u_long)argp->opcode);
 	printf("\tname: ");
 	for (i = 0; i < argp->name.size; i++) {
 		c = ((char *)argp->name.data)[i];
@@ -177,6 +183,8 @@ __log_register_read(recbuf, argpp)
 	bp += sizeof(argp->txnid->txnid);
 	memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
 	bp += sizeof(DB_LSN);
+	memcpy(&argp->opcode, bp, sizeof(argp->opcode));
+	bp += sizeof(argp->opcode);
 	memcpy(&argp->name.size, bp, sizeof(u_int32_t));
 	bp += sizeof(u_int32_t);
 	argp->name.data = bp;
@@ -194,124 +202,6 @@ __log_register_read(recbuf, argpp)
 }
 
 /*
- * PUBLIC: int __log_unregister_log
- * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
- * PUBLIC:     u_int32_t));
- */
-int __log_unregister_log(logp, txnid, ret_lsnp, flags,
-	id)
-	DB_LOG *logp;
-	DB_TXN *txnid;
-	DB_LSN *ret_lsnp;
-	u_int32_t flags;
-	u_int32_t id;
-{
-	DBT logrec;
-	DB_LSN *lsnp, null_lsn;
-	u_int32_t rectype, txn_num;
-	int ret;
-	u_int8_t *bp;
-
-	rectype = DB_log_unregister;
-	txn_num = txnid == NULL ? 0 : txnid->txnid;
-	if (txnid == NULL) {
-		null_lsn.file = 0;
-		null_lsn.offset = 0;
-		lsnp = &null_lsn;
-	} else
-		lsnp = &txnid->last_lsn;
-	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
-	    + sizeof(id);
-	if ((logrec.data = (void *)__db_malloc(logrec.size)) == NULL)
-		return (ENOMEM);
-
-	bp = logrec.data;
-	memcpy(bp, &rectype, sizeof(rectype));
-	bp += sizeof(rectype);
-	memcpy(bp, &txn_num, sizeof(txn_num));
-	bp += sizeof(txn_num);
-	memcpy(bp, lsnp, sizeof(DB_LSN));
-	bp += sizeof(DB_LSN);
-	memcpy(bp, &id, sizeof(id));
-	bp += sizeof(id);
-#ifdef DEBUG
-	if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
-		fprintf(stderr, "Error in log record length");
-#endif
-	ret = __log_put(logp, ret_lsnp, (DBT *)&logrec, flags);
-	if (txnid != NULL)
-		txnid->last_lsn = *ret_lsnp;
-	__db_free(logrec.data);
-	return (ret);
-}
-
-/*
- * PUBLIC: int __log_unregister_print
- * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
- */
-int
-__log_unregister_print(notused1, dbtp, lsnp, notused3, notused4)
-	DB_LOG *notused1;
-	DBT *dbtp;
-	DB_LSN *lsnp;
-	int notused3;
-	void *notused4;
-{
-	__log_unregister_args *argp;
-	u_int32_t i;
-	int c, ret;
-
-	i = 0;
-	c = 0;
-	notused1 = NULL;
-	notused3 = 0;
-	notused4 = NULL;
-
-	if ((ret = __log_unregister_read(dbtp->data, &argp)) != 0)
-		return (ret);
-	printf("[%lu][%lu]log_unregister: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
-	    (u_long)lsnp->file,
-	    (u_long)lsnp->offset,
-	    (u_long)argp->type,
-	    (u_long)argp->txnid->txnid,
-	    (u_long)argp->prev_lsn.file,
-	    (u_long)argp->prev_lsn.offset);
-	printf("\tid: %lu\n", (u_long)argp->id);
-	printf("\n");
-	__db_free(argp);
-	return (0);
-}
-
-/*
- * PUBLIC: int __log_unregister_read __P((void *, __log_unregister_args **));
- */
-int
-__log_unregister_read(recbuf, argpp)
-	void *recbuf;
-	__log_unregister_args **argpp;
-{
-	__log_unregister_args *argp;
-	u_int8_t *bp;
-
-	argp = (__log_unregister_args *)__db_malloc(sizeof(__log_unregister_args) +
-	    sizeof(DB_TXN));
-	if (argp == NULL)
-		return (ENOMEM);
-	argp->txnid = (DB_TXN *)&argp[1];
-	bp = recbuf;
-	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->prev_lsn, bp, sizeof(DB_LSN));
-	bp += sizeof(DB_LSN);
-	memcpy(&argp->id, bp, sizeof(argp->id));
-	bp += sizeof(argp->id);
-	*argpp = argp;
-	return (0);
-}
-
-/*
  * PUBLIC: int __log_init_print __P((DB_ENV *));
  */
 int
@@ -323,9 +213,6 @@ __log_init_print(dbenv)
 	if ((ret = __db_add_recovery(dbenv,
 	    __log_register_print, DB_log_register)) != 0)
 		return (ret);
-	if ((ret = __db_add_recovery(dbenv,
-	    __log_unregister_print, DB_log_unregister)) != 0)
-		return (ret);
 	return (0);
 }
 
@@ -341,9 +228,6 @@ __log_init_recover(dbenv)
 	if ((ret = __db_add_recovery(dbenv,
 	    __log_register_recover, DB_log_register)) != 0)
 		return (ret);
-	if ((ret = __db_add_recovery(dbenv,
-	    __log_unregister_recover, DB_log_unregister)) != 0)
-		return (ret);
 	return (0);
 }
 
diff --git a/db2/log/log_get.c b/db2/log/log_get.c
index 2d1512c6b9..ab6f6247cb 100644
--- a/db2/log/log_get.c
+++ b/db2/log/log_get.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_get.c	10.22 (Sleepycat) 11/22/97";
+static const char sccsid[] = "@(#)log_get.c	10.24 (Sleepycat) 1/17/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -122,7 +122,7 @@ __log_get(dblp, alsn, dbt, flags, silent)
 	nlsn = dblp->c_lsn;
 	switch (flags) {
 	case DB_CHECKPOINT:
-		nlsn = dblp->lp->c_lsn;
+		nlsn = lp->c_lsn;
 		if (IS_ZERO_LSN(nlsn)) {
 			__db_err(dblp->dbenv,
 	"log_get: unable to find checkpoint record: no checkpoint set.");
@@ -138,26 +138,18 @@ __log_get(dblp, alsn, dbt, flags, silent)
 		}
 		/* FALLTHROUGH */
 	case DB_FIRST:				/* Find the first log record. */
-		/*
-		 * Find any log file.  Note, we may have only entered records
-		 * in the buffer, and not yet written a log file.
-		 */
-		if ((ret = __log_find(dblp, &cnt)) != 0) {
-			__db_err(dblp->dbenv,
-	"log_get: unable to find the first record: no log files found.");
+		/* Find the first log file. */
+		if ((ret = __log_find(dblp, 1, &cnt)) != 0)
 			goto err2;
-		}
 
-		/* If there's anything in the buffer, it belongs to file 1. */
+		/*
+		 * We may have only entered records in the buffer, and not
+		 * yet written a log file.  If no log files were found and
+		 * there's anything in the buffer, it belongs to file 1.
+		 */
 		if (cnt == 0)
 			cnt = 1;
 
-		/* Now go backwards to find the smallest one. */
-		for (; cnt > 1; --cnt)
-			if (__log_valid(dblp, NULL, cnt) != 0) {
-				++cnt;
-				break;
-			}
 		nlsn.file = cnt;
 		nlsn.offset = 0;
 		break;
diff --git a/db2/log/log_put.c b/db2/log/log_put.c
index 42fec88a7d..65a3990799 100644
--- a/db2/log/log_put.c
+++ b/db2/log/log_put.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_put.c	10.22 (Sleepycat) 11/12/97";
+static const char sccsid[] = "@(#)log_put.c	10.24 (Sleepycat) 1/17/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -82,8 +82,7 @@ __log_put(dblp, lsn, dbt, flags)
 	const DBT *dbt;
 	int flags;
 {
-	DBT t;
-	DBT fid_dbt;
+	DBT fid_dbt, t;
 	DB_LSN r_unused;
 	FNAME *fnp;
 	LOG *lp;
@@ -156,13 +155,15 @@ __log_put(dblp, lsn, dbt, flags)
 
 		for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
 		    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
+			memset(&t, 0, sizeof(t));
 			t.data = R_ADDR(dblp, fnp->name_off);
 			t.size = strlen(t.data) + 1;
 			memset(&fid_dbt, 0, sizeof(fid_dbt));
 			fid_dbt.data = R_ADDR(dblp, fnp->fileid_off);
 			fid_dbt.size = DB_FILE_ID_LEN;
-			if ((ret = __log_register_log(dblp, NULL, &r_unused,
-			    0, &t, &fid_dbt, fnp->id, fnp->s_type)) != 0)
+			if ((ret = __log_register_log(dblp, NULL, &r_unused, 0,
+			    LOG_CHECKPOINT, &t, &fid_dbt, fnp->id, fnp->s_type))
+			    != 0)
 				return (ret);
 		}
 	}
@@ -280,7 +281,7 @@ __log_flush(dblp, lsn)
 
 	/*
 	 * If the LSN is less than the last-sync'd LSN, we're done.  Note,
-	 * the last-sync LSN saved in s_lsn is the LSN of the first byte 
+	 * the last-sync LSN saved in s_lsn is the LSN of the first byte
 	 * we absolutely know has been written to disk, so the test is <=.
 	 */
 	if (lsn->file < lp->s_lsn.file ||
diff --git a/db2/log/log_rec.c b/db2/log/log_rec.c
index 92b8203990..69334f8bc8 100644
--- a/db2/log/log_rec.c
+++ b/db2/log/log_rec.c
@@ -40,7 +40,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_rec.c	10.14 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)log_rec.c	10.16 (Sleepycat) 1/17/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -80,73 +80,53 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
 #ifdef DEBUG_RECOVER
 	__log_register_print(logp, dbtp, lsnp, redo, info);
 #endif
-	info = info;				/* XXX: Shut the compiler up. */
-	lsnp = lsnp;
+	COMPQUIET(info, NULL);
+	COMPQUIET(lsnp, NULL);
 
 	F_SET(logp, DB_AM_RECOVER);
 
 	if ((ret = __log_register_read(dbtp->data, &argp)) != 0)
 		goto out;
 
-	ret = __log_open_file(logp,
-	    argp->uid.data, argp->name.data, argp->ftype, argp->id);
-	if (ret == ENOENT) {
-		if (redo == TXN_OPENFILES)
-			__db_err(logp->dbenv,
-			    "warning: file %s not found", argp->name.data);
-		ret = 0;
-	}
-
-out:	F_CLR(logp, DB_AM_RECOVER);
-	if (argp != NULL)
-		__db_free(argp);
-	return (ret);
-}
-
-/*
- * PUBLIC: int __log_unregister_recover
- * PUBLIC:     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
- */
-int
-__log_unregister_recover(logp, dbtp, lsnp, redo, info)
-	DB_LOG *logp;
-	DBT *dbtp;
-	DB_LSN *lsnp;
-	int redo;
-	void *info;
-{
-	__log_unregister_args *argp;
-	int ret;
-
-#ifdef DEBUG_RECOVER
-	__log_unregister_print(logp, dbtp, lsnp, redo, info);
-#endif
-	info = info;				/* XXX: Shut the compiler up. */
-	lsnp = lsnp;
-
-	if (redo == TXN_OPENFILES ||
-	    redo == TXN_BACKWARD_ROLL || redo == TXN_UNDO)
-		return (0);
-
-	F_SET(logp, DB_AM_RECOVER);
-	if ((ret = __log_unregister_read(dbtp->data, &argp)) != 0)
-		goto out;
-
-	/*
-	 * If the file is deleted, then we can just ignore this close.
-	 * Otherwise, we'd better have a valid dbp that we should either
-	 * close or whose reference count should be decremented.
-	 */
-	LOCK_LOGTHREAD(logp);
-	if (logp->dbentry[argp->id].dbp == NULL) {
-		if (!logp->dbentry[argp->id].deleted)
-			ret = EINVAL;
-	} else if (--logp->dbentry[argp->id].refcount == 0) {
-		ret = logp->dbentry[argp->id].dbp->close(
-		    logp->dbentry[argp->id].dbp, 0);
-		logp->dbentry[argp->id].dbp = NULL;
+	if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) ||
+	    (argp->opcode == LOG_OPEN &&
+	    (redo == TXN_REDO || redo == TXN_OPENFILES || 
+	     redo == TXN_FORWARD_ROLL)) ||
+	    (argp->opcode == LOG_CLOSE &&
+	    (redo == TXN_UNDO || redo == TXN_BACKWARD_ROLL))) {
+		/*
+		 * If we are redoing an open or undoing a close, then we need
+		 * to open a file.
+		 */
+		ret = __log_open_file(logp,
+		    argp->uid.data, argp->name.data, argp->ftype, argp->id);
+		if (ret == ENOENT) {
+			if (redo == TXN_OPENFILES)
+				__db_err(logp->dbenv,
+				    "warning: file %s not found",
+				    argp->name.data);
+			ret = 0;
+		}
+	} else if (argp->opcode != LOG_CHECKPOINT) {
+		/*
+		 * If we are redoing a close or undoing an open, then we need
+		 * to close the file.
+		 *
+		 * If the file is deleted, then we can just ignore this close.
+		 * Otherwise, we'd better have a valid dbp that we should either
+		 * close or whose reference count should be decremented.
+		 */
+		LOCK_LOGTHREAD(logp);
+		if (logp->dbentry[argp->id].dbp == NULL) {
+			if (!logp->dbentry[argp->id].deleted)
+				ret = EINVAL;
+		} else if (--logp->dbentry[argp->id].refcount == 0) {
+			ret = logp->dbentry[argp->id].dbp->close(
+			    logp->dbentry[argp->id].dbp, 0);
+			logp->dbentry[argp->id].dbp = NULL;
+		}
+		UNLOCK_LOGTHREAD(logp);
 	}
-	UNLOCK_LOGTHREAD(logp);
 
 out:	F_CLR(logp, DB_AM_RECOVER);
 	if (argp != NULL)
diff --git a/db2/log/log_register.c b/db2/log/log_register.c
index 2dab361616..9907d6e25a 100644
--- a/db2/log/log_register.c
+++ b/db2/log/log_register.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_register.c	10.12 (Sleepycat) 9/29/97";
+static const char sccsid[] = "@(#)log_register.c	10.14 (Sleepycat) 1/19/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -35,8 +35,7 @@ log_register(dblp, dbp, name, type, idp)
 	DBTYPE type;
 	u_int32_t *idp;
 {
-	DBT r_name;
-	DBT fid_dbt;
+	DBT fid_dbt, r_name;
 	DB_LSN r_unused;
 	FNAME *fnp;
 	size_t len;
@@ -75,10 +74,7 @@ log_register(dblp, dbp, name, type, idp)
 		    R_ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
 			++fnp->ref;
 			fid = fnp->id;
-			if (!F_ISSET(dblp, DB_AM_RECOVER) &&
-			    (ret = __log_add_logid(dblp, dbp, fid) != 0))
-				goto err;
-			goto ret1;
+			goto found;
 		}
 	}
 
@@ -107,7 +103,7 @@ log_register(dblp, dbp, name, type, idp)
 	SH_TAILQ_INSERT_HEAD(&dblp->lp->fq, fnp, q, __fname);
 	inserted = 1;
 
-	/* Log the registry. */
+found:	/* Log the registry. */
 	if (!F_ISSET(dblp, DB_AM_RECOVER)) {
 		r_name.data = (void *)name;		/* XXX: Yuck! */
 		r_name.size = strlen(name) + 1;
@@ -115,7 +111,7 @@ log_register(dblp, dbp, name, type, idp)
 		fid_dbt.data = dbp->lock.fileid;
 		fid_dbt.size = DB_FILE_ID_LEN;
 		if ((ret = __log_register_log(dblp, NULL, &r_unused,
-		    0, &r_name, &fid_dbt, fid, type)) != 0)
+		    0, LOG_OPEN, &r_name, &fid_dbt, fid, type)) != 0)
 			goto err;
 		if ((ret = __log_add_logid(dblp, dbp, fid)) != 0)
 			goto err;
@@ -136,7 +132,7 @@ err:		/*
 			__db_shalloc_free(dblp->addr, fnp);
 	}
 
-ret1:	UNLOCK_LOGREGION(dblp);
+	UNLOCK_LOGREGION(dblp);
 
 	if (fullname != NULL)
 		FREES(fullname);
@@ -155,6 +151,7 @@ log_unregister(dblp, fid)
 	DB_LOG *dblp;
 	u_int32_t fid;
 {
+	DBT fid_dbt, r_name;
 	DB_LSN r_unused;
 	FNAME *fnp;
 	int ret;
@@ -162,11 +159,6 @@ log_unregister(dblp, fid)
 	ret = 0;
 	LOCK_LOGREGION(dblp);
 
-	/* Unlog the registry. */
-	if (!F_ISSET(dblp, DB_AM_RECOVER) &&
-	    (ret = __log_unregister_log(dblp, NULL, &r_unused, 0, fid)) != 0)
-		return (ret);
-
 	/* Find the entry in the log. */
 	for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
 	    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname))
@@ -178,17 +170,31 @@ log_unregister(dblp, fid)
 		goto ret1;
 	}
 
-	/* If more than 1 reference, decrement the reference and return. */
-	if (fnp->ref > 1) {
-		--fnp->ref;
-		goto ret1;
+	/* Unlog the registry. */
+	if (!F_ISSET(dblp, DB_AM_RECOVER)) {
+		memset(&r_name, 0, sizeof(r_name));
+		r_name.data = R_ADDR(dblp, fnp->name_off);
+		r_name.size = strlen(r_name.data) + 1;
+		memset(&fid_dbt, 0, sizeof(fid_dbt));
+		fid_dbt.data =  R_ADDR(dblp, fnp->fileid_off);
+		fid_dbt.size = DB_FILE_ID_LEN;
+		if ((ret = __log_register_log(dblp, NULL, &r_unused,
+		    0, LOG_CLOSE, &r_name, &fid_dbt, fid, fnp->s_type)) != 0)
+			goto ret1;
 	}
 
-	/* Free the unique file information, name and structure. */
-	__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->fileid_off));
-	__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off));
-	SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
-	__db_shalloc_free(dblp->addr, fnp);
+	/*
+	 * If more than 1 reference, just decrement the reference and return.
+	 * Otherwise, free the unique file information, name and structure.
+	 */
+	if (fnp->ref > 1)
+		--fnp->ref;
+	else {
+		__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->fileid_off));
+		__db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off));
+		SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
+		__db_shalloc_free(dblp->addr, fnp);
+	}
 
 	/*
 	 * Remove from the process local table.  If this operation is taking
@@ -199,6 +205,5 @@ log_unregister(dblp, fid)
 		__log_rem_logid(dblp, fid);
 
 ret1:	UNLOCK_LOGREGION(dblp);
-
 	return (ret);
 }