*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.33 2007/09/08 20:31:15 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.34 2007/09/21 17:36:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* counters for XidCache measurement */
static long xc_by_recent_xmin = 0;
+static long xc_by_my_xact = 0;
static long xc_by_main_xid = 0;
static long xc_by_child_xid = 0;
static long xc_slow_answer = 0;
#define xc_by_recent_xmin_inc() (xc_by_recent_xmin++)
+#define xc_by_my_xact_inc() (xc_by_my_xact++)
#define xc_by_main_xid_inc() (xc_by_main_xid++)
#define xc_by_child_xid_inc() (xc_by_child_xid++)
#define xc_slow_answer_inc() (xc_slow_answer++)
#else /* !XIDCACHE_DEBUG */
#define xc_by_recent_xmin_inc() ((void) 0)
+#define xc_by_my_xact_inc() ((void) 0)
#define xc_by_main_xid_inc() ((void) 0)
#define xc_by_child_xid_inc() ((void) 0)
#define xc_slow_answer_inc() ((void) 0)
bool
TransactionIdIsInProgress(TransactionId xid)
{
- bool result = false;
+ static TransactionId *xids = NULL;
+ int nxids = 0;
ProcArrayStruct *arrayP = procArray;
+ TransactionId topxid;
int i,
j;
- int nxids = 0;
- TransactionId *xids;
- TransactionId topxid;
- bool locked;
/*
* Don't bother checking a transaction older than RecentXmin; it could not
return false;
}
- /* Get workspace to remember main XIDs in */
- xids = (TransactionId *) palloc(sizeof(TransactionId) * arrayP->maxProcs);
+ /*
+ * Also, we can handle our own transaction (and subtransactions) without
+ * any access to shared memory.
+ */
+ if (TransactionIdIsCurrentTransactionId(xid))
+ {
+ xc_by_my_xact_inc();
+ return true;
+ }
+
+ /*
+ * If not first time through, get workspace to remember main XIDs in.
+ * We malloc it permanently to avoid repeated palloc/pfree overhead.
+ */
+ if (xids == NULL)
+ {
+ xids = (TransactionId *)
+ malloc(arrayP->maxProcs * sizeof(TransactionId));
+ if (xids == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+ }
LWLockAcquire(ProcArrayLock, LW_SHARED);
- locked = true;
for (i = 0; i < arrayP->numProcs; i++)
{
volatile PGPROC *proc = arrayP->procs[i];
+ TransactionId pxid;
+
+ /* Ignore my own proc --- dealt with it above */
+ if (proc == MyProc)
+ continue;
/* Fetch xid just once - see GetNewTransactionId */
- TransactionId pxid = proc->xid;
+ pxid = proc->xid;
if (!TransactionIdIsValid(pxid))
continue;
*/
if (TransactionIdEquals(pxid, xid))
{
+ LWLockRelease(ProcArrayLock);
xc_by_main_xid_inc();
- result = true;
- goto result_known;
+ return true;
}
/*
if (TransactionIdEquals(cxid, xid))
{
+ LWLockRelease(ProcArrayLock);
xc_by_child_xid_inc();
- result = true;
- goto result_known;
+ return true;
}
}
}
LWLockRelease(ProcArrayLock);
- locked = false;
/*
* If none of the relevant caches overflowed, we know the Xid is not
* running without looking at pg_subtrans.
*/
if (nxids == 0)
- goto result_known;
+ return false;
/*
* Step 3: have to check pg_subtrans.
xc_slow_answer_inc();
if (TransactionIdDidAbort(xid))
- goto result_known;
+ return false;
/*
* It isn't aborted, so check whether the transaction tree it belongs to
for (i = 0; i < nxids; i++)
{
if (TransactionIdEquals(xids[i], topxid))
- {
- result = true;
- break;
- }
+ return true;
}
}
-result_known:
- if (locked)
- LWLockRelease(ProcArrayLock);
-
- pfree(xids);
-
- return result;
+ return false;
}
/*
DisplayXidCache(void)
{
fprintf(stderr,
- "XidCache: xmin: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
+ "XidCache: xmin: %ld, myxact: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
xc_by_recent_xmin,
+ xc_by_my_xact,
xc_by_main_xid,
xc_by_child_xid,
xc_slow_answer);