about summary refs log tree commit diff
path: root/db2/mp/mp_bh.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/mp/mp_bh.c')
-rw-r--r--db2/mp/mp_bh.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/db2/mp/mp_bh.c b/db2/mp/mp_bh.c
index e1b68ce450..3d0d053b5f 100644
--- a/db2/mp/mp_bh.c
+++ b/db2/mp/mp_bh.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)mp_bh.c	10.12 (Sleepycat) 8/20/97";
+static const char sccsid[] = "@(#)mp_bh.c	10.15 (Sleepycat) 8/29/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -24,6 +24,8 @@ static const char sccsid[] = "@(#)mp_bh.c	10.12 (Sleepycat) 8/20/97";
 #include "mp.h"
 #include "common_ext.h"
 
+static int __memp_upgrade __P((DB_MPOOL *, DB_MPOOLFILE *, MPOOLFILE *));
+
 /*
  * __memp_bhwrite --
  *	Write the page associated with a given bucket header.
@@ -48,14 +50,20 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
 		*wrotep = 0;
 
 	/*
-	 * Walk the process' DB_MPOOLFILE list and try and find a file
-	 * descriptor for this file.
+	 * Walk the process' DB_MPOOLFILE list and find a file descriptor for
+	 * the file.  We also check that the descriptor is open for writing.
+	 * If we find a descriptor on the file that's not open for writing, we
+	 * try and upgrade it to make it writeable.
 	 */
 	LOCKHANDLE(dbmp, &dbmp->mutex);
 	for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
 	    dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q))
-		if (dbmfp->mfp == mfp)
+		if (dbmfp->mfp == mfp) {
+			if (F_ISSET(dbmfp, MP_READONLY) &&
+			    __memp_upgrade(dbmp, dbmfp, mfp))
+				return (0);
 			break;
+		}
 	UNLOCKHANDLE(dbmp, &dbmp->mutex);
 	if (dbmfp != NULL)
 		goto found;
@@ -80,6 +88,10 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep)
 	/*
 	 * Try and open the file; ignore any error, assume it's a permissions
 	 * problem.
+	 *
+	 * XXX
+	 * There's no negative cache here, so we may repeatedly try and open
+	 * files that we have previously tried (and failed) to open.
 	 */
 	dbt.size = mfp->pgcookie_len;
 	dbt.data = ADDR(dbmp, mfp->pgcookie_off);
@@ -435,3 +447,42 @@ __memp_bhfree(dbmp, mfp, bhp, free_mem)
 	if (free_mem)
 		__db_shalloc_free(dbmp->addr, bhp);
 }
+
+/*
+ * __memp_upgrade --
+ *	Upgrade a file descriptor from readonly to readwrite.
+ */
+static int
+__memp_upgrade(dbmp, dbmfp, mfp)
+	DB_MPOOL *dbmp;
+	DB_MPOOLFILE *dbmfp;
+	MPOOLFILE *mfp;
+{
+	int fd;
+
+	/*
+	 * !!!
+	 * We expect the handle to already be locked.
+	 */
+
+	/* Check to see if we've already upgraded. */
+	if (F_ISSET(dbmfp, MP_UPGRADE))
+		return (0);
+
+	/* Check to see if we've already failed. */
+	if (F_ISSET(dbmfp, MP_UPGRADE_FAIL))
+		return (1);
+
+	/* Try the open. */
+	if (__db_fdopen(ADDR(dbmp, mfp->path_off), 0, 0, 0, &fd) != 0) {
+		F_SET(dbmfp, MP_UPGRADE_FAIL);
+		return (1);
+	}
+
+	/* Swap the descriptors and set the upgrade flag. */
+	(void)close(dbmfp->fd);
+	dbmfp->fd = fd;
+	F_SET(dbmfp, MP_UPGRADE);
+
+	return (0);
+}