|
13 | 13 | *
|
14 | 14 | *
|
15 | 15 | * IDENTIFICATION
|
16 |
| - * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.205 2008/03/26 21:10:37 alvherre Exp $ |
| 16 | + * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.206 2008/04/16 23:59:40 tgl Exp $ |
17 | 17 | *
|
18 | 18 | *-------------------------------------------------------------------------
|
19 | 19 | */
|
|
41 | 41 | #include "pgstat.h"
|
42 | 42 | #include "postmaster/bgwriter.h"
|
43 | 43 | #include "storage/freespace.h"
|
| 44 | +#include "storage/ipc.h" |
44 | 45 | #include "storage/procarray.h"
|
45 | 46 | #include "storage/smgr.h"
|
46 | 47 | #include "utils/acl.h"
|
|
53 | 54 | #include "utils/tqual.h"
|
54 | 55 |
|
55 | 56 |
|
| 57 | +typedef struct |
| 58 | +{ |
| 59 | + Oid src_dboid; /* source (template) DB */ |
| 60 | + Oid dest_dboid; /* DB we are trying to create */ |
| 61 | +} createdb_failure_params; |
| 62 | + |
56 | 63 | /* non-export function prototypes */
|
| 64 | +static void createdb_failure_callback(int code, Datum arg); |
57 | 65 | static bool get_db_info(const char *name, LOCKMODE lockmode,
|
58 | 66 | Oid *dbIdP, Oid *ownerIdP,
|
59 | 67 | int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
|
@@ -99,6 +107,7 @@ createdb(const CreatedbStmt *stmt)
|
99 | 107 | int encoding = -1;
|
100 | 108 | int dbconnlimit = -1;
|
101 | 109 | int ctype_encoding;
|
| 110 | + createdb_failure_params fparms; |
102 | 111 |
|
103 | 112 | /* Extract options from the statement node tree */
|
104 | 113 | foreach(option, stmt->options)
|
@@ -449,12 +458,15 @@ createdb(const CreatedbStmt *stmt)
|
449 | 458 |
|
450 | 459 | /*
|
451 | 460 | * Once we start copying subdirectories, we need to be able to clean 'em
|
452 |
| - * up if we fail. Establish a TRY block to make sure this happens. (This |
| 461 | + * up if we fail. Use an ENSURE block to make sure this happens. (This |
453 | 462 | * is not a 100% solution, because of the possibility of failure during
|
454 | 463 | * transaction commit after we leave this routine, but it should handle
|
455 | 464 | * most scenarios.)
|
456 | 465 | */
|
457 |
| - PG_TRY(); |
| 466 | + fparms.src_dboid = src_dboid; |
| 467 | + fparms.dest_dboid = dboid; |
| 468 | + PG_ENSURE_ERROR_CLEANUP(createdb_failure_callback, |
| 469 | + PointerGetDatum(&fparms)); |
458 | 470 | {
|
459 | 471 | /*
|
460 | 472 | * Iterate through all tablespaces of the template database, and copy
|
@@ -565,18 +577,25 @@ createdb(const CreatedbStmt *stmt)
|
565 | 577 | */
|
566 | 578 | database_file_update_needed();
|
567 | 579 | }
|
568 |
| - PG_CATCH(); |
569 |
| - { |
570 |
| - /* Release lock on source database before doing recursive remove */ |
571 |
| - UnlockSharedObject(DatabaseRelationId, src_dboid, 0, |
572 |
| - ShareLock); |
| 580 | + PG_END_ENSURE_ERROR_CLEANUP(createdb_failure_callback, |
| 581 | + PointerGetDatum(&fparms)); |
| 582 | +} |
| 583 | + |
| 584 | +/* Error cleanup callback for createdb */ |
| 585 | +static void |
| 586 | +createdb_failure_callback(int code, Datum arg) |
| 587 | +{ |
| 588 | + createdb_failure_params *fparms = (createdb_failure_params *) DatumGetPointer(arg); |
573 | 589 |
|
574 |
| - /* Throw away any successfully copied subdirectories */ |
575 |
| - remove_dbtablespaces(dboid); |
| 590 | + /* |
| 591 | + * Release lock on source database before doing recursive remove. |
| 592 | + * This is not essential but it seems desirable to release the lock |
| 593 | + * as soon as possible. |
| 594 | + */ |
| 595 | + UnlockSharedObject(DatabaseRelationId, fparms->src_dboid, 0, ShareLock); |
576 | 596 |
|
577 |
| - PG_RE_THROW(); |
578 |
| - } |
579 |
| - PG_END_TRY(); |
| 597 | + /* Throw away any successfully copied subdirectories */ |
| 598 | + remove_dbtablespaces(fparms->dest_dboid); |
580 | 599 | }
|
581 | 600 |
|
582 | 601 |
|
|
0 commit comments