diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 2251b02..e196a55 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -114,6 +114,7 @@ int max_prepared_xacts = 0; typedef struct GlobalTransactionData { GlobalTransaction next; /* list link for free list */ + int prepXactId /* array offset within prepXacts */ int pgprocno; /* ID of associated dummy PGPROC */ BackendId dummyBackendId; /* similar to backend id for backends */ TimestampTz prepared_at; /* time of preparation */ @@ -407,7 +408,8 @@ MarkAsPreparing(TransactionId xid, const char *gid, /* And insert it into the active array */ Assert(TwoPhaseState->numPrepXacts < max_prepared_xacts); - TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts++] = gxact; + TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts] = gxact; + gxact->prepXactId = TwoPhaseState->numPrepXacts++; /* * Remember that we have this GlobalTransaction entry locked for us. If we @@ -551,31 +553,25 @@ LockGXact(const char *gid, Oid user) static void RemoveGXact(GlobalTransaction gxact) { - int i; - - LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE); + int i = gxact->prepXactId; + GlobalTransaction last_gxact; - for (i = 0; i < TwoPhaseState->numPrepXacts; i++) - { - if (gxact == TwoPhaseState->prepXacts[i]) - { - /* remove from the active array */ - TwoPhaseState->numPrepXacts--; - TwoPhaseState->prepXacts[i] = TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts]; + Assert(gxact->prepXactId >= 0); - /* and put it back in the freelist */ - gxact->next = TwoPhaseState->freeGXacts; - TwoPhaseState->freeGXacts = gxact; + LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE); - LWLockRelease(TwoPhaseStateLock); + /* remove from the active array */ + TwoPhaseState->numPrepXacts--; + last_gxact = TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts]; + TwoPhaseState->prepXacts[i] = last_gxact; + last_gxact->prepXactId = i; + gxact->prepXactId = -1; - return; - } - } + /* and put it back in the freelist */ + gxact->next = TwoPhaseState->freeGXacts; + TwoPhaseState->freeGXacts = gxact; LWLockRelease(TwoPhaseStateLock); - - elog(ERROR, "failed to find %p in GlobalTransaction array", gxact); } /*