aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/dbcommands.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/dbcommands.c')
-rw-r--r--src/backend/commands/dbcommands.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index fdd5e32b37b..13bb4f92c22 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.187.2.2 2007/04/12 15:04:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.187.2.3 2008/04/17 00:00:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,6 +39,7 @@
#include "miscadmin.h"
#include "postmaster/bgwriter.h"
#include "storage/freespace.h"
+#include "storage/ipc.h"
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "utils/acl.h"
@@ -50,7 +51,14 @@
#include "utils/syscache.h"
+typedef struct
+{
+ Oid src_dboid; /* source (template) DB */
+ Oid dest_dboid; /* DB we are trying to create */
+} createdb_failure_params;
+
/* non-export function prototypes */
+static void createdb_failure_callback(int code, Datum arg);
static bool get_db_info(const char *name, LOCKMODE lockmode,
Oid *dbIdP, Oid *ownerIdP,
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
@@ -95,6 +103,7 @@ createdb(const CreatedbStmt *stmt)
const char *dbtemplate = NULL;
int encoding = -1;
int dbconnlimit = -1;
+ createdb_failure_params fparms;
/* don't call this in a transaction block */
PreventTransactionChain((void *) stmt, "CREATE DATABASE");
@@ -406,12 +415,15 @@ createdb(const CreatedbStmt *stmt)
/*
* Once we start copying subdirectories, we need to be able to clean 'em
- * up if we fail. Establish a TRY block to make sure this happens. (This
+ * up if we fail. Use an ENSURE block to make sure this happens. (This
* is not a 100% solution, because of the possibility of failure during
* transaction commit after we leave this routine, but it should handle
* most scenarios.)
*/
- PG_TRY();
+ fparms.src_dboid = src_dboid;
+ fparms.dest_dboid = dboid;
+ PG_ENSURE_ERROR_CLEANUP(createdb_failure_callback,
+ PointerGetDatum(&fparms));
{
/*
* Iterate through all tablespaces of the template database, and copy
@@ -518,18 +530,25 @@ createdb(const CreatedbStmt *stmt)
*/
database_file_update_needed();
}
- PG_CATCH();
- {
- /* Release lock on source database before doing recursive remove */
- UnlockSharedObject(DatabaseRelationId, src_dboid, 0,
- ShareLock);
+ PG_END_ENSURE_ERROR_CLEANUP(createdb_failure_callback,
+ PointerGetDatum(&fparms));
+}
+
+/* Error cleanup callback for createdb */
+static void
+createdb_failure_callback(int code, Datum arg)
+{
+ createdb_failure_params *fparms = (createdb_failure_params *) DatumGetPointer(arg);
- /* Throw away any successfully copied subdirectories */
- remove_dbtablespaces(dboid);
+ /*
+ * Release lock on source database before doing recursive remove.
+ * This is not essential but it seems desirable to release the lock
+ * as soon as possible.
+ */
+ UnlockSharedObject(DatabaseRelationId, fparms->src_dboid, 0, ShareLock);
- PG_RE_THROW();
- }
- PG_END_TRY();
+ /* Throw away any successfully copied subdirectories */
+ remove_dbtablespaces(fparms->dest_dboid);
}