aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc/procarray.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/ipc/procarray.c')
-rw-r--r--src/backend/storage/ipc/procarray.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 8acd2014a0d..30f66c089c6 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -23,7 +23,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.48 2009/03/31 05:18:33 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.49 2009/04/04 17:40:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1022,25 +1022,42 @@ IsBackendPid(int pid)
/*
* GetCurrentVirtualXIDs -- returns an array of currently active VXIDs.
*
- * The array is palloc'd and is terminated with an invalid VXID.
+ * The array is palloc'd. The number of valid entries is returned into *nvxids.
*
- * If limitXmin is not InvalidTransactionId, we skip any backends
- * with xmin >= limitXmin. If allDbs is false, we skip backends attached
- * to other databases. If excludeVacuum isn't zero, we skip processes for
- * which (excludeVacuum & vacuumFlags) is not zero. Also, our own process
- * is always skipped.
+ * The arguments allow filtering the set of VXIDs returned. Our own process
+ * is always skipped. In addition:
+ * If limitXmin is not InvalidTransactionId, skip processes with
+ * xmin > limitXmin.
+ * If excludeXmin0 is true, skip processes with xmin = 0.
+ * If allDbs is false, skip processes attached to other databases.
+ * If excludeVacuum isn't zero, skip processes for which
+ * (vacuumFlags & excludeVacuum) is not zero.
+ *
+ * Note: the purpose of the limitXmin and excludeXmin0 parameters is to
+ * allow skipping backends whose oldest live snapshot is no older than
+ * some snapshot we have. Since we examine the procarray with only shared
+ * lock, there are race conditions: a backend could set its xmin just after
+ * we look. Indeed, on multiprocessors with weak memory ordering, the
+ * other backend could have set its xmin *before* we look. We know however
+ * that such a backend must have held shared ProcArrayLock overlapping our
+ * own hold of ProcArrayLock, else we would see its xmin update. Therefore,
+ * any snapshot the other backend is taking concurrently with our scan cannot
+ * consider any transactions as still running that we think are committed
+ * (since backends must hold ProcArrayLock exclusive to commit).
*/
VirtualTransactionId *
-GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs, int excludeVacuum)
+GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
+ bool allDbs, int excludeVacuum,
+ int *nvxids)
{
VirtualTransactionId *vxids;
ProcArrayStruct *arrayP = procArray;
int count = 0;
int index;
- /* allocate result space with room for a terminator */
+ /* allocate what's certainly enough result space */
vxids = (VirtualTransactionId *)
- palloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
+ palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
LWLockAcquire(ProcArrayLock, LW_SHARED);
@@ -1056,15 +1073,18 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs, int excludeVacuum)
if (allDbs || proc->databaseId == MyDatabaseId)
{
- /* Fetch xmin just once - might change on us? */
+ /* Fetch xmin just once - might change on us */
TransactionId pxmin = proc->xmin;
+ if (excludeXmin0 && !TransactionIdIsValid(pxmin))
+ continue;
+
/*
- * Note that InvalidTransactionId precedes all other XIDs, so a
- * proc that hasn't set xmin yet will always be included.
+ * InvalidTransactionId precedes all other XIDs, so a proc that
+ * hasn't set xmin yet will not be rejected by this test.
*/
if (!TransactionIdIsValid(limitXmin) ||
- TransactionIdPrecedes(pxmin, limitXmin))
+ TransactionIdPrecedesOrEquals(pxmin, limitXmin))
{
VirtualTransactionId vxid;
@@ -1077,10 +1097,7 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs, int excludeVacuum)
LWLockRelease(ProcArrayLock);
- /* add the terminator */
- vxids[count].backendId = InvalidBackendId;
- vxids[count].localTransactionId = InvalidLocalTransactionId;
-
+ *nvxids = count;
return vxids;
}