about 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.c203
-rw-r--r--db2/log/log.src35
-rw-r--r--db2/log/log_archive.c35
-rw-r--r--db2/log/log_auto.c35
-rw-r--r--db2/log/log_compare.c4
-rw-r--r--db2/log/log_findckp.c24
-rw-r--r--db2/log/log_get.c29
-rw-r--r--db2/log/log_put.c42
-rw-r--r--db2/log/log_rec.c10
-rw-r--r--db2/log/log_register.c29
10 files changed, 203 insertions, 243 deletions
diff --git a/db2/log/log.c b/db2/log/log.c
index 8013d42aef..d642c9f9ef 100644
--- a/db2/log/log.c
+++ b/db2/log/log.c
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log.c	10.39 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log.c	10.54 (Sleepycat) 5/31/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -23,7 +21,6 @@ static const char sccsid[] = "@(#)log.c	10.39 (Sleepycat) 1/17/98";
 
 #include "db_int.h"
 #include "shqueue.h"
-#include "db_shash.h"
 #include "log.h"
 #include "db_dispatch.h"
 #include "txn_auto.h"
@@ -38,15 +35,14 @@ static int __log_recover __P((DB_LOG *));
 int
 log_open(path, flags, mode, dbenv, lpp)
 	const char *path;
-	int flags;
+	u_int32_t flags;
 	int mode;
 	DB_ENV *dbenv;
 	DB_LOG **lpp;
 {
 	DB_LOG *dblp;
 	LOG *lp;
-	size_t len;
-	int fd, newregion, ret, retry_cnt;
+	int ret;
 
 	/* Validate arguments. */
 #ifdef HAVE_SPINLOCKS
@@ -57,22 +53,13 @@ log_open(path, flags, mode, dbenv, lpp)
 	if ((ret = __db_fchk(dbenv, "log_open", flags, OKFLAGS)) != 0)
 		return (ret);
 
-	/*
-	 * We store 4-byte offsets into the file, so the maximum file
-	 * size can't be larger than that.
-	 */
-	if (dbenv != NULL && dbenv->lg_max > UINT32_T_MAX) {
-		__db_err(dbenv, "log_open: maximum file size too large");
-		return (EINVAL);
-	}
-
 	/* Create and initialize the DB_LOG structure. */
 	if ((dblp = (DB_LOG *)__db_calloc(1, sizeof(DB_LOG))) == NULL)
 		return (ENOMEM);
 
 	if (path != NULL && (dblp->dir = __db_strdup(path)) == NULL) {
-		__db_free(dblp);
-		return (ENOMEM);
+		ret = ENOMEM;
+		goto err;
 	}
 
 	dblp->dbenv = dbenv;
@@ -85,102 +72,87 @@ log_open(path, flags, mode, dbenv, lpp)
 	 * file names there.  Make it fairly large so that we don't have to
 	 * grow it.
 	 */
-	len = 30 * 1024;
+#define	DEF_LOG_SIZE	(30 * 1024)
 
 	/* Map in the region. */
-	retry_cnt = newregion = 0;
-retry:	if (LF_ISSET(DB_CREATE)) {
-		ret = __db_rcreate(dbenv, DB_APP_LOG, path,
-		    DB_DEFAULT_LOG_FILE, mode, len, 0, &fd, &dblp->maddr);
-		if (ret == 0) {
-			/* Put the LOG structure first in the region. */
-			lp = dblp->maddr;
-
-			/* Initialize the rest of the region as free space. */
-			dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);
-			__db_shalloc_init(dblp->addr, len - sizeof(LOG));
-
-			/* Initialize the LOG structure. */
-			lp->persist.lg_max = dbenv == NULL ? 0 : dbenv->lg_max;
-			if (lp->persist.lg_max == 0)
-				lp->persist.lg_max = DEFAULT_MAX;
-			lp->persist.magic = DB_LOGMAGIC;
-			lp->persist.version = DB_LOGVERSION;
-			lp->persist.mode = mode;
-			SH_TAILQ_INIT(&lp->fq);
-
-			/* Initialize LOG LSNs. */
-			lp->lsn.file = 1;
-			lp->lsn.offset = 0;
-
-			newregion = 1;
-		} else if (ret != EEXIST)
+	dblp->reginfo.dbenv = dbenv;
+	dblp->reginfo.appname = DB_APP_LOG;
+	if (path == NULL)
+		dblp->reginfo.path = NULL;
+	else
+		if ((dblp->reginfo.path = __db_strdup(path)) == NULL)
 			goto err;
-	}
-
-	/* If we didn't or couldn't create the region, try and join it. */
-	if (!newregion &&
-	    (ret = __db_ropen(dbenv, DB_APP_LOG,
-	    path, DB_DEFAULT_LOG_FILE, 0, &fd, &dblp->maddr)) != 0) {
-		/*
-		 * If we fail because the file isn't available, wait a
-		 * second and try again.
-		 */
-		if (ret == EAGAIN && ++retry_cnt < 3) {
-			(void)__db_sleep(1, 0);
-			goto retry;
-		}
+	dblp->reginfo.file = DB_DEFAULT_LOG_FILE;
+	dblp->reginfo.mode = mode;
+	dblp->reginfo.size = DEF_LOG_SIZE;
+	dblp->reginfo.dbflags = flags;
+	dblp->reginfo.flags = REGION_SIZEDEF;
+	if ((ret = __db_rattach(&dblp->reginfo)) != 0)
 		goto err;
-	}
 
-	/* Set up the common information. */
-	dblp->lp = dblp->maddr;
-	dblp->addr = (u_int8_t *)dblp->maddr + sizeof(LOG);
-	dblp->fd = fd;
+	/*
+	 * The LOG structure is first in the region, the rest of the region
+	 * is free space.
+	 */
+	dblp->lp = dblp->reginfo.addr;
+	dblp->addr = (u_int8_t *)dblp->lp + sizeof(LOG);
+
+	/* Initialize a created region. */
+	if (F_ISSET(&dblp->reginfo, REGION_CREATED)) {
+		__db_shalloc_init(dblp->addr, DEF_LOG_SIZE - sizeof(LOG));
+
+		/* Initialize the LOG structure. */
+		lp = dblp->lp;
+		lp->persist.lg_max = dbenv == NULL ? 0 : dbenv->lg_max;
+		if (lp->persist.lg_max == 0)
+			lp->persist.lg_max = DEFAULT_MAX;
+		lp->persist.magic = DB_LOGMAGIC;
+		lp->persist.version = DB_LOGVERSION;
+		lp->persist.mode = mode;
+		SH_TAILQ_INIT(&lp->fq);
+
+		/* Initialize LOG LSNs. */
+		lp->lsn.file = 1;
+		lp->lsn.offset = 0;
+	}
 
-	/* Initialize thread information. */
+	/* Initialize thread information, mutex. */
 	if (LF_ISSET(DB_THREAD)) {
 		F_SET(dblp, DB_AM_THREAD);
-
-		if (!newregion)
-			LOCK_LOGREGION(dblp);
 		if ((ret = __db_shalloc(dblp->addr,
-		    sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) == 0)
-			(void)__db_mutex_init(dblp->mutexp, -1);
-		if (!newregion)
-			UNLOCK_LOGREGION(dblp);
-		if (ret != 0) {
-			(void)log_close(dblp);
-			if (newregion)
-				(void)log_unlink(path, 1, dbenv);
-			return (ret);
-		}
+		    sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) != 0)
+			goto err;
+		(void)__db_mutex_init(dblp->mutexp, -1);
 	}
 
 	/*
-	 * If doing recovery, try and recover any previous log files
-	 * before releasing the lock.
+	 * If doing recovery, try and recover any previous log files before
+	 * releasing the lock.
 	 */
-	if (newregion) {
-		ret = __log_recover(dblp);
-		UNLOCK_LOGREGION(dblp);
+	if (F_ISSET(&dblp->reginfo, REGION_CREATED) &&
+	    (ret = __log_recover(dblp)) != 0)
+		goto err;
 
-		if (ret != 0) {
-			(void)log_close(dblp);
-			(void)log_unlink(path, 1, dbenv);
-			return (ret);
-		}
-	}
+	UNLOCK_LOGREGION(dblp);
 	*lpp = dblp;
 	return (0);
 
-err:	/*
-	 * We never get here with an allocated thread-mutex, so we do
-	 * not have to worry about freeing it.
-	 */
-	FREE(dblp, sizeof(DB_LOG));
-	return (ret);
+err:	if (dblp->reginfo.addr != NULL) {
+		if (dblp->mutexp != NULL)
+			__db_shalloc_free(dblp->addr, dblp->mutexp);
+
+		UNLOCK_LOGREGION(dblp);
+		(void)__db_rdetach(&dblp->reginfo);
+		if (F_ISSET(&dblp->reginfo, REGION_CREATED))
+			(void)log_unlink(path, 1, dbenv);
+	}
 
+	if (dblp->reginfo.path != NULL)
+		FREES(dblp->reginfo.path);
+	if (dblp->dir != NULL)
+		FREES(dblp->dir);
+	FREE(dblp, sizeof(*dblp));
+	return (ret);
 }
 
 /*
@@ -234,7 +206,7 @@ __log_recover(dblp)
 			continue;
 		memcpy(&chk, dbt.data, sizeof(u_int32_t));
 		if (chk == DB_txn_ckp) {
-			lp->c_lsn = lsn;
+			lp->chkpt_lsn = lsn;
 			found_checkpoint = 1;
 		}
 	}
@@ -273,7 +245,7 @@ __log_recover(dblp)
 				continue;
 			memcpy(&chk, dbt.data, sizeof(u_int32_t));
 			if (chk == DB_txn_ckp) {
-				lp->c_lsn = lsn;
+				lp->chkpt_lsn = lsn;
 				found_checkpoint = 1;
 			}
 		}
@@ -281,7 +253,7 @@ __log_recover(dblp)
 
 	/* If we never find a checkpoint, that's okay, just 0 it out. */
 	if (!found_checkpoint)
-		ZERO_LSN(lp->c_lsn);
+		ZERO_LSN(lp->chkpt_lsn);
 
 	__db_err(dblp->dbenv,
 	    "Recovering the log: last valid LSN: file: %lu offset %lu",
@@ -380,7 +352,7 @@ __log_valid(dblp, lp, cnt)
 	if ((ret = __db_open(p,
 	    DB_RDONLY | DB_SEQUENTIAL,
 	    DB_RDONLY | DB_SEQUENTIAL, 0, &fd)) != 0 ||
-	    (ret = __db_seek(fd, 0, 0, sizeof(HDR), SEEK_SET)) != 0 ||
+	    (ret = __db_seek(fd, 0, 0, sizeof(HDR), 0, SEEK_SET)) != 0 ||
 	    (ret = __db_read(fd, &persist, sizeof(LOGP), &nw)) != 0 ||
 	    nw != sizeof(LOGP)) {
 		if (ret == 0)
@@ -429,8 +401,6 @@ log_close(dblp)
 {
 	int ret, t_ret;
 
-	ret = 0;
-
 	/* Discard the per-thread pointer. */
 	if (dblp->mutexp != NULL) {
 		LOCK_LOGREGION(dblp);
@@ -439,9 +409,7 @@ log_close(dblp)
 	}
 
 	/* Close the region. */
-	if ((t_ret =
-	    __db_rclose(dblp->dbenv, dblp->fd, dblp->maddr)) != 0 && ret == 0)
-		ret = t_ret;
+	ret = __db_rdetach(&dblp->reginfo);
 
 	/* Close open files, release allocated memory. */
 	if (dblp->lfd != -1 && (t_ret = __db_close(dblp->lfd)) != 0 && ret == 0)
@@ -456,8 +424,9 @@ log_close(dblp)
 	if (dblp->dir != NULL)
 		FREES(dblp->dir);
 
-	/* Free the structure. */
-	FREE(dblp, sizeof(DB_LOG));
+	if (dblp->reginfo.path != NULL)
+		FREES(dblp->reginfo.path);
+	FREE(dblp, sizeof(*dblp));
 
 	return (ret);
 }
@@ -472,8 +441,19 @@ log_unlink(path, force, dbenv)
 	int force;
 	DB_ENV *dbenv;
 {
-	return (__db_runlink(dbenv,
-	    DB_APP_LOG, path, DB_DEFAULT_LOG_FILE, force));
+	REGINFO reginfo;
+	int ret;
+
+	memset(&reginfo, 0, sizeof(reginfo));
+	reginfo.dbenv = dbenv;
+	reginfo.appname = DB_APP_LOG;
+	if (path != NULL && (reginfo.path = __db_strdup(path)) == NULL)
+		return (ENOMEM);
+	reginfo.file = DB_DEFAULT_LOG_FILE;
+	ret = __db_runlink(&reginfo, force);
+	if (reginfo.path != NULL)
+		FREES(reginfo.path);
+	return (ret);
 }
 
 /*
@@ -511,6 +491,9 @@ log_stat(dblp, gspp, db_malloc)
 	(*gspp)->st_cur_file = lp->lsn.file;
 	(*gspp)->st_cur_offset = lp->lsn.offset;
 
+	(*gspp)->st_refcnt = lp->rlayout.refcnt;
+	(*gspp)->st_regsize = lp->rlayout.size;
+
 	UNLOCK_LOGREGION(dblp);
 
 	return (0);
diff --git a/db2/log/log.src b/db2/log/log.src
index f3d9f32b2d..12883bd1e3 100644
--- a/db2/log/log.src
+++ b/db2/log/log.src
@@ -1,43 +1,12 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  *
- *	@(#)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
- * record types with the transaction system) should have a file like this.
- * Each type of log record and its parameters is defined.  The basic
- * format of a record definition is:
- *
- * BEGIN	<RECORD_TYPE>
- * ARG|STRING|POINTER	<variable name>	<variable type> <printf format>
- * ...
- * END
- * ARG the argument is a simple parameter of the type *	specified.
- * DBT the argument is a DBT (db.h) containing a length and pointer.
- * PTR the argument is a pointer to the data type specified; the entire
- *     type should be logged.
- *
- * There are a set of shell scripts of the form xxx.sh that generate c
- * code and or h files to process these.  (This is probably better done
- * in a single PERL script, but for now, this works.)
- *
- * The DB recovery system requires the following three fields appear in
- * every record, and will assign them to the per-record-type structures
- * as well as making them the first parameters to the appropriate logging
- * call.
- * rectype:	record-type, identifies the structure and log/read call
- * txnid:	transaction id, a DBT in this implementation
- * prev:	the last LSN for this transaction
+ *	@(#)log.src	10.5 (Sleepycat) 4/10/98
  */
 
-/*
- * Use the argument of PREFIX as the prefix for all record types,
- * routines, id numbers, etc.
- */
 PREFIX	log
 
 /* Used for registering name/id translations at open or close. */
diff --git a/db2/log/log_archive.c b/db2/log/log_archive.c
index 91ae5abe0b..7db0cc3e36 100644
--- a/db2/log/log_archive.c
+++ b/db2/log/log_archive.c
@@ -1,14 +1,14 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1997
+ * Copyright (c) 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_archive.c	10.30 (Sleepycat) 1/8/98";
+static const char sccsid[] = "@(#)log_archive.c	10.37 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -24,8 +24,8 @@ static const char sccsid[] = "@(#)log_archive.c	10.30 (Sleepycat) 1/8/98";
 #include "db_dispatch.h"
 #include "shqueue.h"
 #include "log.h"
-#include "clib_ext.h"
 #include "common_ext.h"
+#include "clib_ext.h"			/* XXX: needed for getcwd. */
 
 static int __absname __P((char *, char *, char **));
 static int __build_data __P((DB_LOG *, char *, char ***, void *(*)(size_t)));
@@ -40,7 +40,7 @@ int
 log_archive(dblp, listp, flags, db_malloc)
 	DB_LOG *dblp;
 	char ***listp;
-	int flags;
+	u_int32_t flags;
 	void *(*db_malloc) __P((size_t));
 {
 	DBT rec;
@@ -89,6 +89,11 @@ log_archive(dblp, listp, flags, db_malloc)
 		break;
 	case 0:
 		if ((ret = __log_findckp(dblp, &stable_lsn)) != 0) {
+			/*
+			 * A return of DB_NOTFOUND means that we didn't find
+			 * any records in the log (so we are not going to be
+			 * deleting any log files).
+			 */
 			if (ret != DB_NOTFOUND)
 				return (ret);
 			*listp = NULL;
@@ -269,7 +274,7 @@ lg_free:		if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL)
 
 		/* Get the real name. */
 		if ((ret = __db_appname(dblp->dbenv,
-		    DB_APP_DATA, NULL, array[last], NULL, &real_name)) != 0)
+		    DB_APP_DATA, NULL, array[last], 0, NULL, &real_name)) != 0)
 			goto err2;
 
 		/* If the file doesn't exist, ignore it. */
@@ -335,21 +340,25 @@ __absname(pref, name, newnamep)
 	char *pref, *name, **newnamep;
 {
 	size_t l_pref, l_name;
+	int isabspath;
 	char *newname;
 
-	l_pref = strlen(pref);
 	l_name = strlen(name);
+	isabspath = __db_abspath(name);
+	l_pref = isabspath ? 0 : strlen(pref);
 
 	/* Malloc space for concatenating the two. */
-	if ((newname = (char *)__db_malloc(l_pref + l_name + 2)) == NULL)
+	if ((*newnamep =
+	    newname = (char *)__db_malloc(l_pref + l_name + 2)) == NULL)
 		return (ENOMEM);
 
-	/* Build the name. */
-	memcpy(newname, pref, l_pref);
-	if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL)
-		newname[l_pref++] = PATH_SEPARATOR[0];
+	/* Build the name.  If `name' is an absolute path, ignore any prefix. */
+	if (!isabspath) {
+		memcpy(newname, pref, l_pref);
+		if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL)
+			newname[l_pref++] = PATH_SEPARATOR[0];
+	}
 	memcpy(newname + l_pref, name, l_name + 1);
-	*newnamep = newname;
 
 	return (0);
 }
@@ -409,5 +418,5 @@ static int
 __cmpfunc(p1, p2)
 	const void *p1, *p2;
 {
-	return (strcmp(*((char **)p1), *((char **)p2)));
+	return (strcmp(*((char * const *)p1), *((char * const *)p2)));
 }
diff --git a/db2/log/log_auto.c b/db2/log/log_auto.c
index 2fe17834c3..b17b1ffb2f 100644
--- a/db2/log/log_auto.c
+++ b/db2/log/log_auto.c
@@ -15,8 +15,6 @@
 #include "db_dispatch.h"
 #include "log.h"
 #include "db_am.h"
-#include "common_ext.h"
-
 /*
  * PUBLIC: int __log_register_log
  * PUBLIC:     __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t,
@@ -92,7 +90,7 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
 	bp += sizeof(id);
 	memcpy(bp, &ftype, sizeof(ftype));
 	bp += sizeof(ftype);
-#ifdef DEBUG
+#ifdef DIAGNOSTIC
 	if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size)
 		fprintf(stderr, "Error in log record length");
 #endif
@@ -108,22 +106,23 @@ int __log_register_log(logp, txnid, ret_lsnp, flags,
  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
  */
 int
-__log_register_print(notused1, dbtp, lsnp, notused3, notused4)
+__log_register_print(notused1, dbtp, lsnp, notused2, notused3)
 	DB_LOG *notused1;
 	DBT *dbtp;
 	DB_LSN *lsnp;
-	int notused3;
-	void *notused4;
+	int notused2;
+	void *notused3;
 {
 	__log_register_args *argp;
 	u_int32_t i;
-	int c, ret;
+	u_int ch;
+	int ret;
 
 	i = 0;
-	c = 0;
+	ch = 0;
 	notused1 = NULL;
-	notused3 = 0;
-	notused4 = NULL;
+	notused2 = 0;
+	notused3 = NULL;
 
 	if ((ret = __log_register_read(dbtp->data, &argp)) != 0)
 		return (ret);
@@ -137,20 +136,20 @@ __log_register_print(notused1, dbtp, lsnp, notused3, notused4)
 	printf("\topcode: %lu\n", (u_long)argp->opcode);
 	printf("\tname: ");
 	for (i = 0; i < argp->name.size; i++) {
-		c = ((char *)argp->name.data)[i];
-		if (isprint(c) || c == 0xa)
-			putchar(c);
+		ch = ((u_int8_t *)argp->name.data)[i];
+		if (isprint(ch) || ch == 0xa)
+			putchar(ch);
 		else
-			printf("%#x ", c);
+			printf("%#x ", ch);
 	}
 	printf("\n");
 	printf("\tuid: ");
 	for (i = 0; i < argp->uid.size; i++) {
-		c = ((char *)argp->uid.data)[i];
-		if (isprint(c) || c == 0xa)
-			putchar(c);
+		ch = ((u_int8_t *)argp->uid.data)[i];
+		if (isprint(ch) || ch == 0xa)
+			putchar(ch);
 		else
-			printf("%#x ", c);
+			printf("%#x ", ch);
 	}
 	printf("\n");
 	printf("\tid: %lu\n", (u_long)argp->id);
diff --git a/db2/log/log_compare.c b/db2/log/log_compare.c
index 601b25c626..320b34af4d 100644
--- a/db2/log/log_compare.c
+++ b/db2/log/log_compare.c
@@ -1,13 +1,13 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_compare.c	10.2 (Sleepycat) 6/21/97";
+static const char sccsid[] = "@(#)log_compare.c	10.3 (Sleepycat) 4/10/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
diff --git a/db2/log/log_findckp.c b/db2/log/log_findckp.c
index 115a00e8aa..82bd5890e6 100644
--- a/db2/log/log_findckp.c
+++ b/db2/log/log_findckp.c
@@ -1,21 +1,20 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_findckp.c	10.12 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)log_findckp.c	10.15 (Sleepycat) 4/26/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -44,10 +43,10 @@ static const char sccsid[] = "@(#)log_findckp.c	10.12 (Sleepycat) 10/25/97";
  * We find one at 500.  This means that we can truncate the log before
  * 500 or run recovery beginning at 500.
  *
- * Returns 0 if we find a checkpoint.
+ * Returns 0 if we find a suitable checkpoint or we retrieved the
+ * first record in the log from which to start.
+ * Returns DB_NOTFOUND if there are no log records.
  * Returns errno on error.
- * Returns DB_NOTFOUND if we could not find a suitable start point and
- * we should start from the beginning.
  *
  * PUBLIC: int __log_findckp __P((DB_LOG *, DB_LSN *));
  */
@@ -70,9 +69,12 @@ __log_findckp(lp, lsnp)
 	memset(&data, 0, sizeof(data));
 	if (F_ISSET(lp, DB_AM_THREAD))
 		F_SET(&data, DB_DBT_MALLOC);
-	if ((ret = log_get(lp, &last_ckp, &data, DB_CHECKPOINT)) != 0)
-		return (ret == ENOENT ? DB_NOTFOUND : ret);
 	ZERO_LSN(ckp_lsn);
+	if ((ret = log_get(lp, &last_ckp, &data, DB_CHECKPOINT)) != 0)
+		if (ret == ENOENT)
+			goto get_first;
+		else
+			return (ret);
 
 	next_lsn = last_ckp;
 	do {
@@ -115,16 +117,12 @@ __log_findckp(lp, lsnp)
 	 * beginning of the log.
 	 */
 	if (log_compare(&last_ckp, &ckp_lsn) > 0) {
-		if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0)
+get_first:	if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0)
 			return (ret);
 		if (F_ISSET(lp, DB_AM_THREAD))
 			__db_free(data.data);
 	}
 	*lsnp = last_ckp;
 
-	if (verbose)
-		__db_err(lp->dbenv, "Rolling forward from [%lu][%lu]",
-			(u_long)last_ckp.file, (u_long)last_ckp.offset);
-
 	return (IS_ZERO_LSN(last_ckp) ? DB_NOTFOUND : 0);
 }
diff --git a/db2/log/log_get.c b/db2/log/log_get.c
index ab6f6247cb..9a055de0a6 100644
--- a/db2/log/log_get.c
+++ b/db2/log/log_get.c
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_get.c	10.24 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log_get.c	10.32 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #endif
@@ -36,9 +34,8 @@ log_get(dblp, alsn, dbt, flags)
 	DB_LOG *dblp;
 	DB_LSN *alsn;
 	DBT *dbt;
-	int flags;
+	u_int32_t flags;
 {
-	LOG *lp;
 	int ret;
 
 	/* Validate arguments. */
@@ -66,8 +63,6 @@ log_get(dblp, alsn, dbt, flags)
 			return (__db_ferr(dblp->dbenv, "threaded data", 1));
 	}
 
-	lp = dblp->lp;
-
 	LOCK_LOGREGION(dblp);
 
 	/*
@@ -97,14 +92,15 @@ log_get(dblp, alsn, dbt, flags)
  * __log_get --
  *	Get a log record; internal version.
  *
- * PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, int, int));
+ * PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
  */
 int
 __log_get(dblp, alsn, dbt, flags, silent)
 	DB_LOG *dblp;
 	DB_LSN *alsn;
 	DBT *dbt;
-	int flags, silent;
+	u_int32_t flags;
+	int silent;
 {
 	DB_LSN nlsn;
 	HDR hdr;
@@ -122,7 +118,7 @@ __log_get(dblp, alsn, dbt, flags, silent)
 	nlsn = dblp->c_lsn;
 	switch (flags) {
 	case DB_CHECKPOINT:
-		nlsn = lp->c_lsn;
+		nlsn = lp->chkpt_lsn;
 		if (IS_ZERO_LSN(nlsn)) {
 			__db_err(dblp->dbenv,
 	"log_get: unable to find checkpoint record: no checkpoint set.");
@@ -219,7 +215,8 @@ retry:
 	}
 
 	/* Seek to the header offset and read the header. */
-	if ((ret = __db_seek(dblp->c_fd, 0, 0, nlsn.offset, SEEK_SET)) != 0) {
+	if ((ret =
+	    __db_seek(dblp->c_fd, 0, 0, nlsn.offset, 0, SEEK_SET)) != 0) {
 		fail = "seek";
 		goto err1;
 	}
@@ -272,7 +269,13 @@ retry:
 		goto cksum;
 	}
 
-	/* Allocate temporary memory to hold the record. */
+	/*
+	 * Allocate temporary memory to hold the record.
+	 *
+	 * XXX
+	 * We're calling malloc(3) with a region locked.  This isn't
+	 * a good idea.
+	 */
 	if ((tbuf = (char *)__db_malloc(len)) == NULL) {
 		ret = ENOMEM;
 		goto err1;
diff --git a/db2/log/log_put.c b/db2/log/log_put.c
index 65a3990799..d00e7dde21 100644
--- a/db2/log/log_put.c
+++ b/db2/log/log_put.c
@@ -1,21 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_put.c	10.24 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log_put.c	10.35 (Sleepycat) 5/6/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
@@ -43,18 +41,19 @@ log_put(dblp, lsn, dbt, flags)
 	DB_LOG *dblp;
 	DB_LSN *lsn;
 	const DBT *dbt;
-	int flags;
+	u_int32_t flags;
 {
 	int ret;
 
 	/* Validate arguments. */
-#define	OKFLAGS	(DB_CHECKPOINT | DB_FLUSH)
+#define	OKFLAGS	(DB_CHECKPOINT | DB_FLUSH | DB_CURLSN)
 	if (flags != 0) {
 		if ((ret =
 		    __db_fchk(dblp->dbenv, "log_put", flags, OKFLAGS)) != 0)
 			return (ret);
 		switch (flags) {
 		case DB_CHECKPOINT:
+		case DB_CURLSN:
 		case DB_FLUSH:
 		case 0:
 			break;
@@ -73,14 +72,14 @@ log_put(dblp, lsn, dbt, flags)
  * __log_put --
  *	Write a log record; internal version.
  *
- * PUBLIC: int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, int));
+ * PUBLIC: int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
  */
 int
 __log_put(dblp, lsn, dbt, flags)
 	DB_LOG *dblp;
 	DB_LSN *lsn;
 	const DBT *dbt;
-	int flags;
+	u_int32_t flags;
 {
 	DBT fid_dbt, t;
 	DB_LSN r_unused;
@@ -91,6 +90,17 @@ __log_put(dblp, lsn, dbt, flags)
 
 	lp = dblp->lp;
 
+	/*
+	 * If the application just wants to know where we are, fill in
+	 * the information.  Currently used by the transaction manager
+	 * to avoid writing TXN_begin records.
+	 */
+	if (LF_ISSET(DB_CURLSN)) {
+		lsn->file = lp->lsn.file;
+		lsn->offset = lp->lsn.offset;
+		return (0);
+	}
+
 	/* If this information won't fit in the file, swap files. */
 	if (lp->lsn.offset + sizeof(HDR) + dbt->size > lp->persist.lg_max) {
 		if (sizeof(HDR) +
@@ -151,7 +161,7 @@ __log_put(dblp, lsn, dbt, flags)
 	 *	Append the set of file name information into the log.
 	 */
 	if (flags == DB_CHECKPOINT) {
-		lp->c_lsn = *lsn;
+		lp->chkpt_lsn = *lsn;
 
 		for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname);
 		    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
@@ -159,7 +169,7 @@ __log_put(dblp, lsn, dbt, flags)
 			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.data = fnp->ufid;
 			fid_dbt.size = DB_FILE_ID_LEN;
 			if ((ret = __log_register_log(dblp, NULL, &r_unused, 0,
 			    LOG_CHECKPOINT, &t, &fid_dbt, fnp->id, fnp->s_type))
@@ -324,7 +334,11 @@ __log_flush(dblp, lsn)
 	 */
 	lp->s_lsn = lp->f_lsn;
 	if (!current)
-		--lp->s_lsn.offset;
+		if (lp->s_lsn.offset == 0) {
+			--lp->s_lsn.file;
+			lp->s_lsn.offset = lp->persist.lg_max;
+		} else
+			--lp->s_lsn.offset;
 
 	return (0);
 }
@@ -416,7 +430,7 @@ __log_write(dblp, addr, len)
 	 * Seek to the offset in the file (someone may have written it
 	 * since we last did).
 	 */
-	if ((ret = __db_seek(dblp->lfd, 0, 0, lp->w_off, SEEK_SET)) != 0)
+	if ((ret = __db_seek(dblp->lfd, 0, 0, lp->w_off, 0, SEEK_SET)) != 0)
 		return (ret);
 	if ((ret = __db_write(dblp->lfd, addr, len, &nw)) != 0)
 		return (ret);
@@ -461,7 +475,7 @@ log_file(dblp, lsn, namep, len)
 		return (ret);
 
 	/* Check to make sure there's enough room and copy the name. */
-	if (len < strlen(p)) {
+	if (len < strlen(p) + 1) {
 		*namep = '\0';
 		return (ENOMEM);
 	}
@@ -518,5 +532,5 @@ __log_name(dblp, filenumber, namep)
 
 	(void)snprintf(name, sizeof(name), LFNAME, filenumber);
 	return (__db_appname(dblp->dbenv,
-	    DB_APP_LOG, dblp->dir, name, NULL, namep));
+	    DB_APP_LOG, dblp->dir, name, 0, NULL, namep));
 }
diff --git a/db2/log/log_rec.c b/db2/log/log_rec.c
index 69334f8bc8..5deac46298 100644
--- a/db2/log/log_rec.c
+++ b/db2/log/log_rec.c
@@ -1,7 +1,7 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 /*
@@ -40,16 +40,13 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_rec.c	10.16 (Sleepycat) 1/17/98";
+static const char sccsid[] = "@(#)log_rec.c	10.20 (Sleepycat) 4/28/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -90,7 +87,7 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
 
 	if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) ||
 	    (argp->opcode == LOG_OPEN &&
-	    (redo == TXN_REDO || redo == TXN_OPENFILES || 
+	    (redo == TXN_REDO || redo == TXN_OPENFILES ||
 	     redo == TXN_FORWARD_ROLL)) ||
 	    (argp->opcode == LOG_CLOSE &&
 	    (redo == TXN_UNDO || redo == TXN_BACKWARD_ROLL))) {
@@ -121,6 +118,7 @@ __log_register_recover(logp, dbtp, lsnp, redo, info)
 			if (!logp->dbentry[argp->id].deleted)
 				ret = EINVAL;
 		} else if (--logp->dbentry[argp->id].refcount == 0) {
+			F_SET(logp->dbentry[argp->id].dbp, DB_AM_RECOVER);
 			ret = logp->dbentry[argp->id].dbp->close(
 			    logp->dbentry[argp->id].dbp, 0);
 			logp->dbentry[argp->id].dbp = NULL;
diff --git a/db2/log/log_register.c b/db2/log/log_register.c
index 9907d6e25a..a6fc4c1b3b 100644
--- a/db2/log/log_register.c
+++ b/db2/log/log_register.c
@@ -1,20 +1,19 @@
 /*-
  * See the file LICENSE for redistribution information.
  *
- * Copyright (c) 1996, 1997
+ * Copyright (c) 1996, 1997, 1998
  *	Sleepycat Software.  All rights reserved.
  */
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)log_register.c	10.14 (Sleepycat) 1/19/98";
+static const char sccsid[] = "@(#)log_register.c	10.18 (Sleepycat) 5/3/98";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
 #include <sys/types.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 #endif
 
@@ -42,12 +41,12 @@ log_register(dblp, dbp, name, type, idp)
 	u_int32_t fid;
 	int inserted, ret;
 	char *fullname;
-	void *fidp, *namep;
+	void *namep;
 
 	fid = 0;
 	inserted = 0;
 	fullname = NULL;
-	fnp = fidp = namep = NULL;
+	fnp = namep = NULL;
 
 	/* Check the arguments. */
 	if (type != DB_BTREE && type != DB_HASH && type != DB_RECNO) {
@@ -57,7 +56,7 @@ log_register(dblp, dbp, name, type, idp)
 
 	/* Get the log file id. */
 	if ((ret = __db_appname(dblp->dbenv,
-	    DB_APP_DATA, NULL, name, NULL, &fullname)) != 0)
+	    DB_APP_DATA, NULL, name, 0, NULL, &fullname)) != 0)
 		return (ret);
 
 	LOCK_LOGREGION(dblp);
@@ -70,8 +69,7 @@ log_register(dblp, dbp, name, type, idp)
 	    fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
 		if (fid <= fnp->id)
 			fid = fnp->id + 1;
-		if (!memcmp(dbp->lock.fileid,
-		    R_ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) {
+		if (!memcmp(dbp->lock.fileid, fnp->ufid, DB_FILE_ID_LEN)) {
 			++fnp->ref;
 			fid = fnp->id;
 			goto found;
@@ -84,15 +82,7 @@ log_register(dblp, dbp, name, type, idp)
 	fnp->ref = 1;
 	fnp->id = fid;
 	fnp->s_type = type;
-
-	if ((ret = __db_shalloc(dblp->addr, DB_FILE_ID_LEN, 0, &fidp)) != 0)
-		goto err;
-	/*
-	 * XXX Now that uids are fixed size, we can put them in the fnp
-	 * structure.
-	 */
-	fnp->fileid_off = R_OFFSET(dblp, fidp);
-	memcpy(fidp, dbp->lock.fileid, DB_FILE_ID_LEN);
+	memcpy(fnp->ufid, dbp->lock.fileid, DB_FILE_ID_LEN);
 
 	len = strlen(name) + 1;
 	if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0)
@@ -126,8 +116,6 @@ err:		/*
 			SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname);
 		if (namep != NULL)
 			__db_shalloc_free(dblp->addr, namep);
-		if (fidp != NULL)
-			__db_shalloc_free(dblp->addr, fidp);
 		if (fnp != NULL)
 			__db_shalloc_free(dblp->addr, fnp);
 	}
@@ -176,7 +164,7 @@ log_unregister(dblp, fid)
 		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.data = fnp->ufid;
 		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)
@@ -190,7 +178,6 @@ log_unregister(dblp, fid)
 	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);