2323 *
2424 *
2525 * IDENTIFICATION
26- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.33 2007/09/08 20:31:15 tgl Exp $
26+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.34 2007/09/21 17:36:53 tgl Exp $
2727 *
2828 *-------------------------------------------------------------------------
2929 */
@@ -60,11 +60,13 @@ static ProcArrayStruct *procArray;
6060
6161/* counters for XidCache measurement */
6262static long xc_by_recent_xmin = 0 ;
63+ static long xc_by_my_xact = 0 ;
6364static long xc_by_main_xid = 0 ;
6465static long xc_by_child_xid = 0 ;
6566static long xc_slow_answer = 0 ;
6667
6768#define xc_by_recent_xmin_inc ()(xc_by_recent_xmin++)
69+ #define xc_by_my_xact_inc ()(xc_by_my_xact++)
6870#define xc_by_main_xid_inc ()(xc_by_main_xid++)
6971#define xc_by_child_xid_inc ()(xc_by_child_xid++)
7072#define xc_slow_answer_inc ()(xc_slow_answer++)
@@ -73,6 +75,7 @@ static void DisplayXidCache(void);
7375#else /* !XIDCACHE_DEBUG */
7476
7577#define xc_by_recent_xmin_inc ()((void) 0)
78+ #define xc_by_my_xact_inc ()((void) 0)
7679#define xc_by_main_xid_inc ()((void) 0)
7780#define xc_by_child_xid_inc ()((void) 0)
7881#define xc_slow_answer_inc ()((void) 0)
@@ -320,14 +323,12 @@ ProcArrayClearTransaction(PGPROC *proc)
320323bool
321324TransactionIdIsInProgress (TransactionId xid )
322325{
323- bool result = false;
326+ static TransactionId * xids = NULL ;
327+ int nxids = 0 ;
324328ProcArrayStruct * arrayP = procArray ;
329+ TransactionId topxid ;
325330int i ,
326331j ;
327- int nxids = 0 ;
328- TransactionId * xids ;
329- TransactionId topxid ;
330- bool locked ;
331332
332333/*
333334 * Don't bother checking a transaction older than RecentXmin; it could not
@@ -341,18 +342,43 @@ TransactionIdIsInProgress(TransactionId xid)
341342return false;
342343}
343344
344- /* Get workspace to remember main XIDs in */
345- xids = (TransactionId * )palloc (sizeof (TransactionId )* arrayP -> maxProcs );
345+ /*
346+ * Also, we can handle our own transaction (and subtransactions) without
347+ * any access to shared memory.
348+ */
349+ if (TransactionIdIsCurrentTransactionId (xid ))
350+ {
351+ xc_by_my_xact_inc ();
352+ return true;
353+ }
354+
355+ /*
356+ * If not first time through, get workspace to remember main XIDs in.
357+ * We malloc it permanently to avoid repeated palloc/pfree overhead.
358+ */
359+ if (xids == NULL )
360+ {
361+ xids = (TransactionId * )
362+ malloc (arrayP -> maxProcs * sizeof (TransactionId ));
363+ if (xids == NULL )
364+ ereport (ERROR ,
365+ (errcode (ERRCODE_OUT_OF_MEMORY ),
366+ errmsg ("out of memory" )));
367+ }
346368
347369LWLockAcquire (ProcArrayLock ,LW_SHARED );
348- locked = true;
349370
350371for (i = 0 ;i < arrayP -> numProcs ;i ++ )
351372{
352373volatile PGPROC * proc = arrayP -> procs [i ];
374+ TransactionId pxid ;
375+
376+ /* Ignore my own proc --- dealt with it above */
377+ if (proc == MyProc )
378+ continue ;
353379
354380/* Fetch xid just once - see GetNewTransactionId */
355- TransactionId pxid = proc -> xid ;
381+ pxid = proc -> xid ;
356382
357383if (!TransactionIdIsValid (pxid ))
358384continue ;
@@ -362,9 +388,9 @@ TransactionIdIsInProgress(TransactionId xid)
362388 */
363389if (TransactionIdEquals (pxid ,xid ))
364390{
391+ LWLockRelease (ProcArrayLock );
365392xc_by_main_xid_inc ();
366- result = true;
367- gotoresult_known ;
393+ return true;
368394}
369395
370396/*
@@ -384,9 +410,9 @@ TransactionIdIsInProgress(TransactionId xid)
384410
385411if (TransactionIdEquals (cxid ,xid ))
386412{
413+ LWLockRelease (ProcArrayLock );
387414xc_by_child_xid_inc ();
388- result = true;
389- gotoresult_known ;
415+ return true;
390416}
391417}
392418
@@ -402,14 +428,13 @@ TransactionIdIsInProgress(TransactionId xid)
402428}
403429
404430LWLockRelease (ProcArrayLock );
405- locked = false;
406431
407432/*
408433 * If none of the relevant caches overflowed, we know the Xid is not
409434 * running without looking at pg_subtrans.
410435 */
411436if (nxids == 0 )
412- goto result_known ;
437+ return false ;
413438
414439/*
415440 * Step 3: have to check pg_subtrans.
@@ -422,7 +447,7 @@ TransactionIdIsInProgress(TransactionId xid)
422447xc_slow_answer_inc ();
423448
424449if (TransactionIdDidAbort (xid ))
425- goto result_known ;
450+ return false ;
426451
427452/*
428453 * It isn't aborted, so check whether the transaction tree it belongs to
@@ -436,20 +461,11 @@ TransactionIdIsInProgress(TransactionId xid)
436461for (i = 0 ;i < nxids ;i ++ )
437462{
438463if (TransactionIdEquals (xids [i ],topxid ))
439- {
440- result = true;
441- break ;
442- }
464+ return true;
443465}
444466}
445467
446- result_known :
447- if (locked )
448- LWLockRelease (ProcArrayLock );
449-
450- pfree (xids );
451-
452- return result ;
468+ return false;
453469}
454470
455471/*
@@ -1284,8 +1300,9 @@ static void
12841300DisplayXidCache (void )
12851301{
12861302fprintf (stderr ,
1287- "XidCache: xmin: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n" ,
1303+ "XidCache: xmin: %ld,myxact: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n" ,
12881304xc_by_recent_xmin ,
1305+ xc_by_my_xact ,
12891306xc_by_main_xid ,
12901307xc_by_child_xid ,
12911308xc_slow_answer );