summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPavan Deolasee2011-04-26 14:24:09 +0000
committerPavan Deolasee2011-06-17 08:56:13 +0000
commit9db03183fe491e60dda1a6a5b36b44c55149e077 (patch)
tree33569db52096ccf5be0300f7b494afb5ec6c9995 /src
parent3cbf503a660e19f5c48c57d3ecd4a746a468cd68 (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.c30
-rw-r--r--src/backend/tcop/utility.c45
-rw-r--r--src/include/pgxc/execRemote.h4
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,