2323 *
2424 *
2525 * IDENTIFICATION
26- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.34 2007/09/21 17:36:53 tgl Exp $
26+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.35 2007/09/23 18:50:38 tgl Exp $
2727 *
2828 *-------------------------------------------------------------------------
2929 */
@@ -61,23 +61,29 @@ static ProcArrayStruct *procArray;
6161/* counters for XidCache measurement */
6262static long xc_by_recent_xmin = 0 ;
6363static long xc_by_my_xact = 0 ;
64+ static long xc_by_latest_xid = 0 ;
6465static long xc_by_main_xid = 0 ;
6566static long xc_by_child_xid = 0 ;
67+ static long xc_no_overflow = 0 ;
6668static long xc_slow_answer = 0 ;
6769
6870#define xc_by_recent_xmin_inc ()(xc_by_recent_xmin++)
6971#define xc_by_my_xact_inc ()(xc_by_my_xact++)
72+ #define xc_by_latest_xid_inc ()(xc_by_latest_xid++)
7073#define xc_by_main_xid_inc ()(xc_by_main_xid++)
7174#define xc_by_child_xid_inc ()(xc_by_child_xid++)
75+ #define xc_no_overflow_inc ()(xc_no_overflow++)
7276#define xc_slow_answer_inc ()(xc_slow_answer++)
7377
7478static void DisplayXidCache (void );
7579#else /* !XIDCACHE_DEBUG */
7680
7781#define xc_by_recent_xmin_inc ()((void) 0)
7882#define xc_by_my_xact_inc ()((void) 0)
83+ #define xc_by_latest_xid_inc ()((void) 0)
7984#define xc_by_main_xid_inc ()((void) 0)
8085#define xc_by_child_xid_inc ()((void) 0)
86+ #define xc_no_overflow_inc ()((void) 0)
8187#define xc_slow_answer_inc ()((void) 0)
8288#endif /* XIDCACHE_DEBUG */
8389
@@ -302,7 +308,8 @@ ProcArrayClearTransaction(PGPROC *proc)
302308/*
303309 * TransactionIdIsInProgress -- is given transaction running in some backend
304310 *
305- * There are three possibilities for finding a running transaction:
311+ * Aside from some shortcuts such as checking RecentXmin and our own Xid,
312+ * there are three possibilities for finding a running transaction:
306313 *
307314 * 1. the given Xid is a main transaction Id. We will find this out cheaply
308315 * by looking at the PGPROC struct for each backend.
@@ -368,6 +375,18 @@ TransactionIdIsInProgress(TransactionId xid)
368375
369376LWLockAcquire (ProcArrayLock ,LW_SHARED );
370377
378+ /*
379+ * Now that we have the lock, we can check latestCompletedXid; if the
380+ * target Xid is after that, it's surely still running.
381+ */
382+ if (TransactionIdPrecedes (ShmemVariableCache -> latestCompletedXid ,xid ))
383+ {
384+ LWLockRelease (ProcArrayLock );
385+ xc_by_latest_xid_inc ();
386+ return true;
387+ }
388+
389+ /* No shortcuts, gotta grovel through the array */
371390for (i = 0 ;i < arrayP -> numProcs ;i ++ )
372391{
373392volatile PGPROC * proc = arrayP -> procs [i ];
@@ -434,7 +453,10 @@ TransactionIdIsInProgress(TransactionId xid)
434453 * running without looking at pg_subtrans.
435454 */
436455if (nxids == 0 )
456+ {
457+ xc_no_overflow_inc ();
437458return false;
459+ }
438460
439461/*
440462 * Step 3: have to check pg_subtrans.
@@ -451,8 +473,8 @@ TransactionIdIsInProgress(TransactionId xid)
451473
452474/*
453475 * It isn't aborted, so check whether the transaction tree it belongs to
454- * is still running (or, more precisely, whether it was running when this
455- *routine started -- note that wealready released ProcArrayLock).
476+ * is still running (or, more precisely, whether it was running when
477+ * weheld ProcArrayLock).
456478 */
457479topxid = SubTransGetTopmostTransaction (xid );
458480Assert (TransactionIdIsValid (topxid ));
@@ -1300,11 +1322,13 @@ static void
13001322DisplayXidCache (void )
13011323{
13021324fprintf (stderr ,
1303- "XidCache: xmin: %ld, myxact: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n" ,
1325+ "XidCache: xmin: %ld, myxact: %ld,latest: %ld, mainxid: %ld, childxid: %ld, nooflo : %ld, slow: %ld\n" ,
13041326xc_by_recent_xmin ,
13051327xc_by_my_xact ,
1328+ xc_by_latest_xid ,
13061329xc_by_main_xid ,
13071330xc_by_child_xid ,
1331+ xc_no_overflow ,
13081332xc_slow_answer );
13091333}
13101334