diff options
| author | Pavan Deolasee | 2011-04-26 14:24:09 +0000 |
|---|---|---|
| committer | Pavan Deolasee | 2011-06-17 08:56:13 +0000 |
| commit | 9db03183fe491e60dda1a6a5b36b44c55149e077 (patch) | |
| tree | 33569db52096ccf5be0300f7b494afb5ec6c9995 /src | |
| parent | 3cbf503a660e19f5c48c57d3ecd4a746a468cd68 (diff) | |
Rearrange the 2PC commit code so that we can commit the local
transaction after releasing the barrier lock.
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/pgxc/pool/execRemote.c | 30 | ||||
| -rw-r--r-- | src/backend/tcop/utility.c | 45 | ||||
| -rw-r--r-- | src/include/pgxc/execRemote.h | 4 |
3 files changed, 46 insertions, 33 deletions
diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index 5ee876d54d..441a6254f5 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -2035,7 +2035,7 @@ finish: * This avoid to have any additional interaction with GTM when making a 2PC transaction. */ void -PGXCNodeCommitPrepared(char *gid, bool isTopLevel) +PGXCNodeCommitPrepared(char *gid) { int res = 0; int res_gtm = 0; @@ -2136,17 +2136,11 @@ finish: * If remote connection is a Coordinator type, the commit prepared has to be done locally * if and only if the Coordinator number was in the node list received from GTM. */ - if (operation_local || IsConnFromCoord()) - { - PreventTransactionChain(isTopLevel, "COMMIT PREPARED"); + if (operation_local) FinishPreparedTransaction(gid, true); - } - /* - * Release the barrier lock now so that pending barriers can get moving - */ LWLockRelease(BarrierLock); - return; + return; } /* @@ -2191,9 +2185,11 @@ finish: /* * Rollback prepared transaction on Datanodes involved in the current transaction + * + * Return whether or not a local operation required. */ -void -PGXCNodeRollbackPrepared(char *gid, bool isTopLevel) +bool +PGXCNodeRollbackPrepared(char *gid) { int res = 0; int res_gtm = 0; @@ -2273,17 +2269,7 @@ finish: (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Could not rollback prepared transaction on Datanodes"))); - /* - * Local coordinator rollbacks if involved in PREPARE - * If remote connection is a Coordinator type, the commit prepared has to be done locally also. - * This works for both Datanodes and Coordinators. - */ - if (operation_local || IsConnFromCoord()) - { - PreventTransactionChain(isTopLevel, "ROLLBACK PREPARED"); - FinishPreparedTransaction(gid, false); - } - return; + return operation_local; } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index bc6c6302a8..d12e81b7e1 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -59,6 +59,7 @@ #ifdef PGXC #include "pgxc/barrier.h" +#include "pgxc/execRemote.h" #include "pgxc/locator.h" #include "pgxc/pgxc.h" #include "pgxc/planner.h" @@ -479,32 +480,58 @@ standard_ProcessUtility(Node *parsetree, break; case TRANS_STMT_COMMIT_PREPARED: + PreventTransactionChain(isTopLevel, "COMMIT PREPARED"); + PreventCommandDuringRecovery("COMMIT PREPARED"); #ifdef PGXC /* * If a COMMIT PREPARED message is received from another Coordinator, * Don't send it down to Datanodes. + * + * XXX We call FinishPreparedTransaction inside + * PGXCNodeCommitPrepared if we are doing a local + * operation. This is convinient because we want to + * hold on to the BarrierLock until local transaction + * is committed too. + * */ if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) - PGXCNodeCommitPrepared(stmt->gid, isTopLevel); -#else - PreventTransactionChain(isTopLevel, "COMMIT PREPARED"); - PreventCommandDuringRecovery("COMMIT PREPARED"); + PGXCNodeCommitPrepared(stmt->gid); + else if (IsConnFromCoord()) + { + /* + * A local Coordinator always commits if involved in Prepare. + * 2PC file is created and flushed if a DDL has been involved in the transaction. + * If remote connection is a Coordinator type, the commit prepared has to be done locally + * if and only if the Coordinator number was in the node list received from GTM. + */ +#endif FinishPreparedTransaction(stmt->gid, true); +#ifdef PGXC + } #endif break; case TRANS_STMT_ROLLBACK_PREPARED: + PreventTransactionChain(isTopLevel, "ROLLBACK PREPARED"); + PreventCommandDuringRecovery("ROLLBACK PREPARED"); #ifdef PGXC /* * If a ROLLBACK PREPARED message is received from another Coordinator, * Don't send it down to Datanodes. */ if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) - PGXCNodeRollbackPrepared(stmt->gid, isTopLevel); -#else - PreventTransactionChain(isTopLevel, "ROLLBACK PREPARED"); - PreventCommandDuringRecovery("ROLLBACK PREPARED"); - FinishPreparedTransaction(gid, false); + operation_local = PGXCNodeRollbackPrepared(stmt->gid); + /* + * Local coordinator rollbacks if involved in PREPARE + * If remote connection is a Coordinator type, the commit prepared has to be done locally also. + * This works for both Datanodes and Coordinators. + */ + if (operation_local || IsConnFromCoord()) + { +#endif + FinishPreparedTransaction(stmt->gid, false); +#ifdef PGXC + } #endif break; diff --git a/src/include/pgxc/execRemote.h b/src/include/pgxc/execRemote.h index 97656324db..983a1267ec 100644 --- a/src/include/pgxc/execRemote.h +++ b/src/include/pgxc/execRemote.h @@ -128,8 +128,8 @@ extern void PGXCNodeSetBeginQuery(char *query_string); extern void PGXCNodeCommit(bool bReleaseHandles); extern int PGXCNodeRollback(void); extern bool PGXCNodePrepare(char *gid); -extern void PGXCNodeRollbackPrepared(char *gid, bool isTopLevel); -extern void PGXCNodeCommitPrepared(char *gid, bool isTopLevel); +extern bool PGXCNodeRollbackPrepared(char *gid); +extern void PGXCNodeCommitPrepared(char *gid); extern bool PGXCNodeIsImplicit2PC(bool *prepare_local_coord); extern int PGXCNodeImplicitPrepare(GlobalTransactionId prepare_xid, char *gid); extern void PGXCNodeImplicitCommitPrepared(GlobalTransactionId prepare_xid, |
