diff options
Diffstat (limited to 'src/backend/commands/dbcommands.c')
-rw-r--r-- | src/backend/commands/dbcommands.c | 45 |
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); } |