23
23
*
24
24
*
25
25
* 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 $
27
27
*
28
28
*-------------------------------------------------------------------------
29
29
*/
@@ -60,11 +60,13 @@ static ProcArrayStruct *procArray;
60
60
61
61
/* counters for XidCache measurement */
62
62
static long xc_by_recent_xmin = 0 ;
63
+ static long xc_by_my_xact = 0 ;
63
64
static long xc_by_main_xid = 0 ;
64
65
static long xc_by_child_xid = 0 ;
65
66
static long xc_slow_answer = 0 ;
66
67
67
68
#define xc_by_recent_xmin_inc () (xc_by_recent_xmin++)
69
+ #define xc_by_my_xact_inc () (xc_by_my_xact++)
68
70
#define xc_by_main_xid_inc () (xc_by_main_xid++)
69
71
#define xc_by_child_xid_inc () (xc_by_child_xid++)
70
72
#define xc_slow_answer_inc () (xc_slow_answer++)
@@ -73,6 +75,7 @@ static void DisplayXidCache(void);
73
75
#else /* !XIDCACHE_DEBUG */
74
76
75
77
#define xc_by_recent_xmin_inc () ((void) 0)
78
+ #define xc_by_my_xact_inc () ((void) 0)
76
79
#define xc_by_main_xid_inc () ((void) 0)
77
80
#define xc_by_child_xid_inc () ((void) 0)
78
81
#define xc_slow_answer_inc () ((void) 0)
@@ -320,14 +323,12 @@ ProcArrayClearTransaction(PGPROC *proc)
320
323
bool
321
324
TransactionIdIsInProgress (TransactionId xid )
322
325
{
323
- bool result = false;
326
+ static TransactionId * xids = NULL ;
327
+ int nxids = 0 ;
324
328
ProcArrayStruct * arrayP = procArray ;
329
+ TransactionId topxid ;
325
330
int i ,
326
331
j ;
327
- int nxids = 0 ;
328
- TransactionId * xids ;
329
- TransactionId topxid ;
330
- bool locked ;
331
332
332
333
/*
333
334
* Don't bother checking a transaction older than RecentXmin; it could not
@@ -341,18 +342,43 @@ TransactionIdIsInProgress(TransactionId xid)
341
342
return false;
342
343
}
343
344
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
+ }
346
368
347
369
LWLockAcquire (ProcArrayLock , LW_SHARED );
348
- locked = true;
349
370
350
371
for (i = 0 ; i < arrayP -> numProcs ; i ++ )
351
372
{
352
373
volatile PGPROC * proc = arrayP -> procs [i ];
374
+ TransactionId pxid ;
375
+
376
+ /* Ignore my own proc --- dealt with it above */
377
+ if (proc == MyProc )
378
+ continue ;
353
379
354
380
/* Fetch xid just once - see GetNewTransactionId */
355
- TransactionId pxid = proc -> xid ;
381
+ pxid = proc -> xid ;
356
382
357
383
if (!TransactionIdIsValid (pxid ))
358
384
continue ;
@@ -362,9 +388,9 @@ TransactionIdIsInProgress(TransactionId xid)
362
388
*/
363
389
if (TransactionIdEquals (pxid , xid ))
364
390
{
391
+ LWLockRelease (ProcArrayLock );
365
392
xc_by_main_xid_inc ();
366
- result = true;
367
- goto result_known ;
393
+ return true;
368
394
}
369
395
370
396
/*
@@ -384,9 +410,9 @@ TransactionIdIsInProgress(TransactionId xid)
384
410
385
411
if (TransactionIdEquals (cxid , xid ))
386
412
{
413
+ LWLockRelease (ProcArrayLock );
387
414
xc_by_child_xid_inc ();
388
- result = true;
389
- goto result_known ;
415
+ return true;
390
416
}
391
417
}
392
418
@@ -402,14 +428,13 @@ TransactionIdIsInProgress(TransactionId xid)
402
428
}
403
429
404
430
LWLockRelease (ProcArrayLock );
405
- locked = false;
406
431
407
432
/*
408
433
* If none of the relevant caches overflowed, we know the Xid is not
409
434
* running without looking at pg_subtrans.
410
435
*/
411
436
if (nxids == 0 )
412
- goto result_known ;
437
+ return false ;
413
438
414
439
/*
415
440
* Step 3: have to check pg_subtrans.
@@ -422,7 +447,7 @@ TransactionIdIsInProgress(TransactionId xid)
422
447
xc_slow_answer_inc ();
423
448
424
449
if (TransactionIdDidAbort (xid ))
425
- goto result_known ;
450
+ return false ;
426
451
427
452
/*
428
453
* It isn't aborted, so check whether the transaction tree it belongs to
@@ -436,20 +461,11 @@ TransactionIdIsInProgress(TransactionId xid)
436
461
for (i = 0 ; i < nxids ; i ++ )
437
462
{
438
463
if (TransactionIdEquals (xids [i ], topxid ))
439
- {
440
- result = true;
441
- break ;
442
- }
464
+ return true;
443
465
}
444
466
}
445
467
446
- result_known :
447
- if (locked )
448
- LWLockRelease (ProcArrayLock );
449
-
450
- pfree (xids );
451
-
452
- return result ;
468
+ return false;
453
469
}
454
470
455
471
/*
@@ -1284,8 +1300,9 @@ static void
1284
1300
DisplayXidCache (void )
1285
1301
{
1286
1302
fprintf (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" ,
1288
1304
xc_by_recent_xmin ,
1305
+ xc_by_my_xact ,
1289
1306
xc_by_main_xid ,
1290
1307
xc_by_child_xid ,
1291
1308
xc_slow_answer );
0 commit comments