From: Simon Riggs Date: Thu, 1 Oct 2009 16:39:28 +0000 (+0100) Subject: TransactionIdIsInProgress() must check KnownAssignedXids. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=88b50b6656bb82414ed97a1666bd47b4366781a8;p=users%2Fsimon%2Fpostgres.git TransactionIdIsInProgress() must check KnownAssignedXids. --- diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index cc552d81b5..4cb0bc9a2c 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -137,6 +137,7 @@ static void KnownAssignedXidsAdd(TransactionId xid, int nsubxids, TransactionId *subxid); static void KnownAssignedXidsRemove(TransactionId xid, bool report_error); static void KnownAssignedXidsRemoveMany(TransactionId xid); +static bool KnownAssignedXidsFind(TransactionId xid); static void KnownAssignedXidsDisplay(int trace_level); /* @@ -608,6 +609,7 @@ TransactionIdIsInProgress(TransactionId xid) TransactionId topxid; int i, j; + bool found; /* * Don't bother checking a transaction older than RecentXmin; it could not @@ -729,6 +731,22 @@ TransactionIdIsInProgress(TransactionId xid) xids[nxids++] = pxid; } + /* + * Check if the transaction id known assigned or whether it is + * completed. + */ + if (RecoveryInProgress()) + { + found = FindKnownAssignedTransactionId(xid); + + if (found) + { + LWLockRelease(ProcArrayLock); + xc_by_main_xid_inc(); /* we don't know whether its child or main */ + return true; + } + } + LWLockRelease(ProcArrayLock); /* @@ -760,17 +778,33 @@ TransactionIdIsInProgress(TransactionId xid) * held ProcArrayLock). */ topxid = SubTransGetTopmostTransaction(xid); - Assert(TransactionIdIsValid(topxid)); - if (!TransactionIdEquals(topxid, xid)) + if (!RecoveryInProgress()) { - for (i = 0; i < nxids; i++) + Assert(TransactionIdIsValid(topxid)); + if (!TransactionIdEquals(topxid, xid)) { - if (TransactionIdEquals(xids[i], topxid)) - return true; + for (i = 0; i < nxids; i++) + { + if (TransactionIdEquals(xids[i], topxid)) + return true; + } } + + return false; } + else + { + /* + * We weren't sure which xids were top-level or not, so + * we don't have space to record them in the work area. + * So we must re-acquire lock and re-check KnownAssignedXids. + */ + LWLockAcquire(ProcArrayLock, LW_SHARED); + found = FindKnownAssignedTransactionId(xid); + LWLockRelease(ProcArrayLock); - return false; + return found; + } } /* @@ -2303,6 +2337,12 @@ ExpireOldKnownAssignedTransactionIds(TransactionId xid) LWLockRelease(ProcArrayLock); } +bool +FindKnownAssignedTransactionId(TransactionId xid) +{ + return KnownAssignedXidsFind(xid); +} + /* * Get an array of KnownAssignedXids, not necessarily in sorted order. * @@ -2492,6 +2532,16 @@ KnownAssignedXidsRemoveMany(TransactionId xid) } } +static bool +KnownAssignedXidsFind(TransactionId xid) +{ + bool found; + + (void) hash_search(KnownAssignedXidsHash, &xid, HASH_FIND, &found); + + return found; +} + /* * xidComparator * qsort comparison function for XIDs diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h index 36d5d52ae7..302090398e 100644 --- a/src/include/storage/procarray.h +++ b/src/include/storage/procarray.h @@ -37,6 +37,7 @@ extern void ExpireOldKnownAssignedTransactionIds(TransactionId xid); extern int GetKnownAssignedTransactions(TransactionId *xarray, TransactionId *xmin, TransactionId xmax, bool *overflow); +extern bool FindKnownAssignedTransactionId(TransactionId xid); extern bool IsRunningXactDataValid(void); extern void GetRunningTransactionData(void);