diff options
author | Michael P | 2011-03-02 00:46:21 +0000 |
---|---|---|
committer | Pavan Deolasee | 2011-05-19 17:49:39 +0000 |
commit | 9bf28d03c9ca4f8a791b5e455f77b39d092dfa6c (patch) | |
tree | 9cd60b1ffc75eb822a85994e707ec0ac107e6dbe /src | |
parent | 20e88ee4c8cd85092891ed5b3bec36820018323f (diff) |
Fix for bug 3134395, 3086422, 3136230: 2PC locks
When a PREPARE was being made on Coordinator for a transaction not
using DDL, 2PC file was bypassed so as to make a fake COMMIT on Coordinator.
The problem was that locks hold at PREPARE state were not released at COMMIT
PREPARED on Coordinator because lock information was obtained from 2PC,
which indeed did not exist on Coordinator for non-DDL transactions.
With this fix, instead of a fake PREPARE, XC does a Commit on Coordinator
without contacting GTM, this permits to release correctly all the locks
held by transaction.
PrepareTransaction is simplified in xact.c, but CommitTransaction
needs an additional parameter to decide if GTM is called at COMMIT
or not.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/twophase.c | 40 | ||||
-rw-r--r-- | src/backend/access/transam/xact.c | 184 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 25 | ||||
-rw-r--r-- | src/include/access/twophase.h | 6 | ||||
-rw-r--r-- | src/include/access/xact.h | 6 |
5 files changed, 112 insertions, 149 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 43c8732245..749375e3fd 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -861,13 +861,8 @@ StartPrepare(GlobalTransaction gxact) * * Calculates CRC and writes state file to WAL and in pg_twophase directory. */ -#ifdef PGXC -void -EndPrepare(GlobalTransaction gxact, bool write_2pc_file) -#else void EndPrepare(GlobalTransaction gxact) -#endif { TransactionId xid = gxact->proc.xid; TwoPhaseFileHeader *hdr; @@ -904,11 +899,6 @@ EndPrepare(GlobalTransaction gxact) * PANIC anyway. */ -#ifdef PGXC - /* Write 2PC state file on Coordinator side if a DDL is involved in transaction */ - if (write_2pc_file) - { -#endif TwoPhaseFilePath(path, xid); fd = BasicOpenFile(path, @@ -981,9 +971,6 @@ EndPrepare(GlobalTransaction gxact) * We save the PREPARE record's location in the gxact for later use by * CheckPointTwoPhase. */ -#ifdef PGXC - } -#endif START_CRIT_SECTION(); @@ -995,15 +982,6 @@ EndPrepare(GlobalTransaction gxact) /* If we crash now, we have prepared: WAL replay will fix things */ -#ifdef PGXC - /* - * Just write 2PC state file on Datanodes - * or on Coordinators if DDL queries are involved. - */ - if (write_2pc_file) - { -#endif - /* write correct CRC and close file */ if ((write(fd, &statefile_crc, sizeof(pg_crc32))) != sizeof(pg_crc32)) { @@ -1018,10 +996,6 @@ EndPrepare(GlobalTransaction gxact) (errcode_for_file_access(), errmsg("could not close two-phase state file: %m"))); -#ifdef PGXC - } -#endif - /* * Mark the prepared transaction as valid. As soon as xact.c marks MyProc * as not running our XID (which it will do immediately after this @@ -1872,17 +1846,3 @@ RecordTransactionAbortPrepared(TransactionId xid, END_CRIT_SECTION(); } - - -#ifdef PGXC -/* - * Remove a gxact on a Coordinator, - * this is used to be able to prepare a commit transaction on another coordinator than the one - * who prepared the transaction, for a transaction that does not include DDLs - */ -void -RemoveGXactCoord(GlobalTransaction gxact) -{ - RemoveGXact(gxact); -} -#endif diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index ea1215d45c..e033d4f4f8 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -112,14 +112,13 @@ typedef enum TBlockState TBLOCK_BEGIN, /* starting transaction block */ TBLOCK_INPROGRESS, /* live transaction */ TBLOCK_END, /* COMMIT received */ +#ifdef PGXC + TBLOCK_END_NOT_GTM, /* COMMIT received but do not commit on GTM */ +#endif TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */ TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */ TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */ TBLOCK_PREPARE, /* live xact, PREPARE received */ -#ifdef PGXC - TBLOCK_PREPARE_NO_2PC_FILE, /* PREPARE receive but skip 2PC file creation - * and Commit gxact */ -#endif /* subtransaction states */ TBLOCK_SUBBEGIN, /* starting a subtransaction */ TBLOCK_SUBINPROGRESS, /* live subtransaction */ @@ -287,7 +286,7 @@ static void CallSubXactCallbacks(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid); static void CleanupTransaction(void); -static void CommitTransaction(void); +static void CommitTransaction(bool contact_gtm); static TransactionId RecordTransactionAbort(bool isSubXact); static void StartTransaction(void); @@ -312,7 +311,7 @@ static const char *TransStateAsString(TransState state); #ifdef PGXC /* PGXC_COORD */ static GlobalTransactionId GetGlobalTransactionId(TransactionState s); -static void PrepareTransaction(bool write_2pc_file, bool is_implicit); +static void PrepareTransaction(bool is_implicit); /* ---------------------------------------------------------------- * PG-XC Functions @@ -1744,7 +1743,7 @@ StartTransaction(void) * NB: if you change this routine, better look at PrepareTransaction too! */ static void -CommitTransaction(void) +CommitTransaction(bool contact_gtm) { TransactionState s = CurrentTransactionState; TransactionId latestXid; @@ -1754,7 +1753,7 @@ CommitTransaction(void) char implicitgid[256]; TransactionId xid = GetCurrentTransactionId(); - if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && contact_gtm) PreparePGXCNodes = PGXCNodeIsImplicit2PC(&PrepareLocalCoord); if (PrepareLocalCoord || PreparePGXCNodes) @@ -1768,7 +1767,7 @@ CommitTransaction(void) * If current transaction has a DDL, and involves more than 1 Coordinator, * PREPARE first on local Coordinator. */ - PrepareTransaction(true, true); + PrepareTransaction(true); } else { @@ -1865,7 +1864,7 @@ CommitTransaction(void) * * This is called only if it is not necessary to prepare the nodes. */ - if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes) + if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes && contact_gtm) PGXCNodeCommit(); #endif @@ -1892,12 +1891,12 @@ CommitTransaction(void) * * Also do not commit a transaction that has already been prepared on Datanodes */ - if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes) + if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !PreparePGXCNodes && contact_gtm) { CommitTranGTM(s->globalTransactionId); latestXid = s->globalTransactionId; } - else if (IS_PGXC_DATANODE || IsConnFromCoord()) + else if ((IS_PGXC_DATANODE || IsConnFromCoord()) && contact_gtm) { /* If we are autovacuum, commit on GTM */ if ((IsAutoVacuumWorkerProcess() || GetForceXidFromGTM()) @@ -2086,7 +2085,7 @@ CommitTransaction(void) * this is made by CommitTransaction when transaction has been committed on Nodes. */ static void -PrepareTransaction(bool write_2pc_file, bool is_implicit) +PrepareTransaction(bool is_implicit) #else static void PrepareTransaction(void) @@ -2221,7 +2220,7 @@ PrepareTransaction(void) * updates, because the transaction manager might get confused if we lose * a global transaction. */ - EndPrepare(gxact, write_2pc_file); + EndPrepare(gxact); /* * Now we clean up backend-internal state and release internal resources. @@ -2272,17 +2271,6 @@ PrepareTransaction(void) #ifdef PGXC /* - * We want to be able to commit a prepared transaction from another coordinator, - * so clean up the gxact in shared memory also. - */ - if (!write_2pc_file) - { - RemoveGXactCoord(gxact); - } -#endif - -#ifdef PGXC - /* * In case of an implicit 2PC, ressources are released by CommitTransaction() */ if (!is_implicit) @@ -2661,6 +2649,9 @@ StartTransactionCommand(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -2669,9 +2660,6 @@ StartTransactionCommand(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(ERROR, "StartTransactionCommand: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -2710,7 +2698,11 @@ CommitTransactionCommand(void) * transaction commit, and return to the idle state. */ case TBLOCK_STARTED: +#ifdef PGXC + CommitTransaction(true); +#else CommitTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; break; @@ -2739,10 +2731,20 @@ CommitTransactionCommand(void) * idle state. */ case TBLOCK_END: +#ifdef PGXC + CommitTransaction(true); +#else CommitTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; break; +#ifdef PGXC + case TBLOCK_END_NOT_GTM: + CommitTransaction(false); + s->blockState = TBLOCK_DEFAULT; + break; +#endif /* * Here we are in the middle of a transaction block but one of the * commands caused an abort so we do nothing but remain in the @@ -2778,20 +2780,13 @@ CommitTransactionCommand(void) * return to the idle state. */ case TBLOCK_PREPARE: - PrepareTransaction(true, false); - s->blockState = TBLOCK_DEFAULT; - break; - #ifdef PGXC - /* - * We are complieting a PREPARE TRANSACTION for a pgxc transaction - * that involved DDLs on a Coordinator. - */ - case TBLOCK_PREPARE_NO_2PC_FILE: - PrepareTransaction(false, false); + PrepareTransaction(false); +#else + PrepareTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; break; -#endif /* * We were just issued a SAVEPOINT inside a transaction block. @@ -2820,23 +2815,21 @@ CommitTransactionCommand(void) if (s->blockState == TBLOCK_END) { Assert(s->parent == NULL); +#ifdef PGXC + CommitTransaction(true); +#else CommitTransaction(); +#endif s->blockState = TBLOCK_DEFAULT; } else if (s->blockState == TBLOCK_PREPARE) { Assert(s->parent == NULL); - PrepareTransaction(true, false); - s->blockState = TBLOCK_DEFAULT; - } #ifdef PGXC - else if (s->blockState == TBLOCK_PREPARE_NO_2PC_FILE) - { - Assert(s->parent == NULL); - PrepareTransaction(false, false); + PrepareTransaction(false); +#endif s->blockState = TBLOCK_DEFAULT; } -#endif else { Assert(s->blockState == TBLOCK_INPROGRESS || @@ -2994,6 +2987,9 @@ AbortCurrentTransaction(void) * the transaction). */ case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; @@ -3034,9 +3030,6 @@ AbortCurrentTransaction(void) * the transaction). */ case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; @@ -3380,6 +3373,9 @@ BeginTransactionBlock(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3388,9 +3384,6 @@ BeginTransactionBlock(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "BeginTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3409,19 +3402,18 @@ BeginTransactionBlock(void) * We do it this way because it's not convenient to change memory context, * resource owner, etc while executing inside a Portal. */ -#ifdef PGXC -bool -PrepareTransactionBlock(char *gid, bool write_2pc_file) -#else bool PrepareTransactionBlock(char *gid) -#endif { TransactionState s; bool result; /* Set up to commit the current transaction */ +#ifdef PGXC + result = EndTransactionBlock(true); +#else result = EndTransactionBlock(); +#endif /* If successful, change outer tblock state to PREPARE */ if (result) @@ -3436,16 +3428,6 @@ PrepareTransactionBlock(char *gid) /* Save GID where PrepareTransaction can find it again */ prepareGID = MemoryContextStrdup(TopTransactionContext, gid); -#ifdef PGXC - /* - * For a Postgres-XC Coordinator, prepare is done for a transaction - * if and only if a DDL was involved in the transaction. - * If not, it is enough to prepare it on Datanodes involved only. - */ - if (!write_2pc_file) - s->blockState = TBLOCK_PREPARE_NO_2PC_FILE; - else -#endif s->blockState = TBLOCK_PREPARE; } else @@ -3476,7 +3458,11 @@ PrepareTransactionBlock(char *gid) * resource owner, etc while executing inside a Portal. */ bool +#ifdef PGXC +EndTransactionBlock(bool contact_gtm) +#else EndTransactionBlock(void) +#endif { TransactionState s = CurrentTransactionState; bool result = false; @@ -3488,6 +3474,11 @@ EndTransactionBlock(void) * to COMMIT. */ case TBLOCK_INPROGRESS: +#ifdef PGXC + if (!contact_gtm) + s->blockState = TBLOCK_END_NOT_GTM; + else +#endif s->blockState = TBLOCK_END; result = true; break; @@ -3566,6 +3557,9 @@ EndTransactionBlock(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3574,9 +3568,6 @@ EndTransactionBlock(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3661,6 +3652,9 @@ UserAbortTransactionBlock(void) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3669,9 +3663,6 @@ UserAbortTransactionBlock(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "UserAbortTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3709,6 +3700,9 @@ DefineSavepoint(char *name) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT: case TBLOCK_SUBABORT: @@ -3719,9 +3713,6 @@ DefineSavepoint(char *name) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "DefineSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3768,6 +3759,9 @@ ReleaseSavepoint(List *options) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT: case TBLOCK_SUBABORT: @@ -3778,9 +3772,6 @@ ReleaseSavepoint(List *options) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "ReleaseSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3871,6 +3862,9 @@ RollbackToSavepoint(List *options) case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: @@ -3879,9 +3873,6 @@ RollbackToSavepoint(List *options) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "RollbackToSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -3964,10 +3955,10 @@ BeginInternalSubTransaction(char *name) case TBLOCK_STARTED: case TBLOCK_INPROGRESS: case TBLOCK_END: - case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif + case TBLOCK_PREPARE: case TBLOCK_SUBINPROGRESS: /* Normal subtransaction start */ PushTransaction(); @@ -3980,7 +3971,6 @@ BeginInternalSubTransaction(char *name) if (name) s->name = MemoryContextStrdup(TopTransactionContext, name); break; - /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_BEGIN: @@ -4051,6 +4041,9 @@ RollbackAndReleaseCurrentSubTransaction(void) case TBLOCK_SUBBEGIN: case TBLOCK_INPROGRESS: case TBLOCK_END: +#ifdef PGXC + case TBLOCK_END_NOT_GTM: +#endif case TBLOCK_SUBEND: case TBLOCK_ABORT: case TBLOCK_ABORT_END: @@ -4060,9 +4053,6 @@ RollbackAndReleaseCurrentSubTransaction(void) case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: -#ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: -#endif elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s", BlockStateAsString(s->blockState)); break; @@ -4109,11 +4099,11 @@ AbortOutOfAnyTransaction(void) case TBLOCK_BEGIN: case TBLOCK_INPROGRESS: case TBLOCK_END: - case TBLOCK_ABORT_PENDING: - case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif + case TBLOCK_ABORT_PENDING: + case TBLOCK_PREPARE: /* In a transaction, so clean up */ AbortTransaction(); CleanupTransaction(); @@ -4203,11 +4193,11 @@ TransactionBlockStatusCode(void) case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: case TBLOCK_END: - case TBLOCK_SUBEND: - case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif + case TBLOCK_SUBEND: + case TBLOCK_PREPARE: return 'T'; /* in transaction */ case TBLOCK_ABORT: case TBLOCK_SUBABORT: @@ -4703,10 +4693,10 @@ BlockStateAsString(TBlockState blockState) return "ABORT END"; case TBLOCK_ABORT_PENDING: return "ABORT PEND"; + case TBLOCK_PREPARE: #ifdef PGXC - case TBLOCK_PREPARE_NO_2PC_FILE: + case TBLOCK_END_NOT_GTM: #endif - case TBLOCK_PREPARE: return "PREPARE"; case TBLOCK_SUBBEGIN: return "SUB BEGIN"; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 9dcc634606..1be891e0c6 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -316,7 +316,11 @@ ProcessUtility(Node *parsetree, break; case TRANS_STMT_COMMIT: +#ifdef PGXC + if (!EndTransactionBlock(true)) +#else if (!EndTransactionBlock()) +#endif { /* report unsuccessful commit in completionTag */ if (completionTag) @@ -342,16 +346,31 @@ ProcessUtility(Node *parsetree, if (IsConnFromCoord()) operation_local = true; - if (!PrepareTransactionBlock(stmt->gid, operation_local)) + if (operation_local) { -#else +#endif if (!PrepareTransactionBlock(stmt->gid)) { -#endif /* report unsuccessful commit in completionTag */ if (completionTag) strcpy(completionTag, "ROLLBACK"); } +#ifdef PGXC + } + else + { + /* + * In this case commit locally to erase the transaction traces + * but do not contact GTM + */ + if (!EndTransactionBlock(false)) + { + /* report unsuccessful commit in completionTag */ + if (completionTag) + strcpy(completionTag, "ROLLBACK"); + } + } +#endif break; case TRANS_STMT_COMMIT_PREPARED: diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h index 58bc7e4d43..8261ee7620 100644 --- a/src/include/access/twophase.h +++ b/src/include/access/twophase.h @@ -36,13 +36,7 @@ extern GlobalTransaction MarkAsPreparing(TransactionId xid, const char *gid, TimestampTz prepared_at, Oid owner, Oid databaseid); -#ifdef PGXC -extern void RemoveGXactCoord(GlobalTransaction gxact); -extern void EndPrepare(GlobalTransaction gxact, bool write_2pc_file); -#else extern void EndPrepare(GlobalTransaction gxact); -#endif - extern void StartPrepare(GlobalTransaction gxact); extern TransactionId PrescanPreparedTransactions(void); diff --git a/src/include/access/xact.h b/src/include/access/xact.h index d211329bd3..6ff489ff7d 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -172,12 +172,12 @@ extern void AbortCurrentTransactionOnce(void); #endif extern void AbortCurrentTransaction(void); extern void BeginTransactionBlock(void); -extern bool EndTransactionBlock(void); #ifdef PGXC -extern bool PrepareTransactionBlock(char *gid, bool write_2pc_file); +extern bool EndTransactionBlock(bool contact_gtm); #else -extern bool PrepareTransactionBlock(char *gid); +extern bool EndTransactionBlock(void); #endif +extern bool PrepareTransactionBlock(char *gid); extern void UserAbortTransactionBlock(void); extern void ReleaseSavepoint(List *options); extern void DefineSavepoint(char *name); |