LCOV - differential code coverage report
Current view: top level - src/backend/access/transam - subtrans.c (source / functions) Coverage Total Hit UNC UBC GIC GNC CBC DUB DCB
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 92.7 % 109 101 3 5 1 9 91 18
Current Date: 2026-05-05 10:23:31 +0900 Functions: 93.3 % 15 14 1 7 7 3
Baseline: lcov-20260505-025707-baseline Branches: 69.2 % 52 36 16 36 1 1
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 4 4 4
(30,360] days: 62.5 % 8 5 3 5
(360..) days: 94.8 % 97 92 5 1 91
Function coverage date bins:
(7,30] days: 100.0 % 2 2 2
(30,360] days: 0.0 % 1 0 1
(360..) days: 100.0 % 12 12 5 7
Branch coverage date bins:
(360..) days: 69.2 % 52 36 16 36

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * subtrans.c
                                  4                 :                :  *      PostgreSQL subtransaction-log manager
                                  5                 :                :  *
                                  6                 :                :  * The pg_subtrans manager is a pg_xact-like manager that stores the parent
                                  7                 :                :  * transaction Id for each transaction.  It is a fundamental part of the
                                  8                 :                :  * nested transactions implementation.  A main transaction has a parent
                                  9                 :                :  * of InvalidTransactionId, and each subtransaction has its immediate parent.
                                 10                 :                :  * The tree can easily be walked from child to parent, but not in the
                                 11                 :                :  * opposite direction.
                                 12                 :                :  *
                                 13                 :                :  * This code is based on xact.c, but the robustness requirements
                                 14                 :                :  * are completely different from pg_xact, because we only need to remember
                                 15                 :                :  * pg_subtrans information for currently-open transactions.  Thus, there is
                                 16                 :                :  * no need to preserve data over a crash and restart.
                                 17                 :                :  *
                                 18                 :                :  * There are no XLOG interactions since we do not care about preserving
                                 19                 :                :  * data across crashes.  During database startup, we simply force the
                                 20                 :                :  * currently-active page of SUBTRANS to zeroes.
                                 21                 :                :  *
                                 22                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                 23                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 24                 :                :  *
                                 25                 :                :  * src/backend/access/transam/subtrans.c
                                 26                 :                :  *
                                 27                 :                :  *-------------------------------------------------------------------------
                                 28                 :                :  */
                                 29                 :                : #include "postgres.h"
                                 30                 :                : 
                                 31                 :                : #include "access/slru.h"
                                 32                 :                : #include "access/subtrans.h"
                                 33                 :                : #include "access/transam.h"
                                 34                 :                : #include "miscadmin.h"
                                 35                 :                : #include "pg_trace.h"
                                 36                 :                : #include "storage/subsystems.h"
                                 37                 :                : #include "utils/guc_hooks.h"
                                 38                 :                : #include "utils/snapmgr.h"
                                 39                 :                : 
                                 40                 :                : 
                                 41                 :                : /*
                                 42                 :                :  * Defines for SubTrans page sizes.  A page is the same BLCKSZ as is used
                                 43                 :                :  * everywhere else in Postgres.
                                 44                 :                :  *
                                 45                 :                :  * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF,
                                 46                 :                :  * SubTrans page numbering also wraps around at
                                 47                 :                :  * 0xFFFFFFFF/SUBTRANS_XACTS_PER_PAGE, and segment numbering at
                                 48                 :                :  * 0xFFFFFFFF/SUBTRANS_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT.  We need take no
                                 49                 :                :  * explicit notice of that fact in this module, except when comparing segment
                                 50                 :                :  * and page numbers in TruncateSUBTRANS (see SubTransPagePrecedes) and zeroing
                                 51                 :                :  * them in StartupSUBTRANS.
                                 52                 :                :  */
                                 53                 :                : 
                                 54                 :                : /* We need four bytes per xact */
                                 55                 :                : #define SUBTRANS_XACTS_PER_PAGE (BLCKSZ / sizeof(TransactionId))
                                 56                 :                : 
                                 57                 :                : /*
                                 58                 :                :  * Although we return an int64 the actual value can't currently exceed
                                 59                 :                :  * 0xFFFFFFFF/SUBTRANS_XACTS_PER_PAGE.
                                 60                 :                :  */
                                 61                 :                : static inline int64
  888 akorotkov@postgresql       62                 :CBC       15657 : TransactionIdToPage(TransactionId xid)
                                 63                 :                : {
                                 64                 :          15657 :     return xid / (int64) SUBTRANS_XACTS_PER_PAGE;
                                 65                 :                : }
                                 66                 :                : 
                                 67                 :                : #define TransactionIdToEntry(xid) ((xid) % (TransactionId) SUBTRANS_XACTS_PER_PAGE)
                                 68                 :                : 
                                 69                 :                : 
                                 70                 :                : static void SUBTRANSShmemRequest(void *arg);
                                 71                 :                : static void SUBTRANSShmemInit(void *arg);
                                 72                 :                : static bool SubTransPagePrecedes(int64 page1, int64 page2);
                                 73                 :                : static int  subtrans_errdetail_for_io_error(const void *opaque_data);
                                 74                 :                : 
                                 75                 :                : const ShmemCallbacks SUBTRANSShmemCallbacks = {
                                 76                 :                :     .request_fn = SUBTRANSShmemRequest,
                                 77                 :                :     .init_fn = SUBTRANSShmemInit,
                                 78                 :                : };
                                 79                 :                : 
                                 80                 :                : /*
                                 81                 :                :  * Link to shared-memory data structures for SUBTRANS control
                                 82                 :                :  */
                                 83                 :                : static SlruDesc SubTransSlruDesc;
                                 84                 :                : 
                                 85                 :                : #define SubTransCtl  (&SubTransSlruDesc)
                                 86                 :                : 
                                 87                 :                : 
                                 88                 :                : /*
                                 89                 :                :  * Record the parent of a subtransaction in the subtrans log.
                                 90                 :                :  */
                                 91                 :                : void
 3295 simon@2ndQuadrant.co       92                 :           8382 : SubTransSetParent(TransactionId xid, TransactionId parent)
                                 93                 :                : {
  888 akorotkov@postgresql       94                 :           8382 :     int64       pageno = TransactionIdToPage(xid);
 7978 tgl@sss.pgh.pa.us          95                 :           8382 :     int         entryno = TransactionIdToEntry(xid);
                                 96                 :                :     int         slotno;
                                 97                 :                :     LWLock     *lock;
                                 98                 :                :     TransactionId *ptr;
                                 99                 :                : 
 5981 simon@2ndQuadrant.co      100         [ -  + ]:           8382 :     Assert(TransactionIdIsValid(parent));
 3295                           101         [ -  + ]:           8382 :     Assert(TransactionIdFollows(xid, parent));
                                102                 :                : 
  797 alvherre@alvh.no-ip.      103                 :           8382 :     lock = SimpleLruGetBankLock(SubTransCtl, pageno);
                                104                 :           8382 :     LWLockAcquire(lock, LW_EXCLUSIVE);
                                105                 :                : 
   53 heikki.linnakangas@i      106                 :GNC        8382 :     slotno = SimpleLruReadPage(SubTransCtl, pageno, true, &xid);
 7925 tgl@sss.pgh.pa.us         107                 :CBC        8382 :     ptr = (TransactionId *) SubTransCtl->shared->page_buffer[slotno];
 7978                           108                 :           8382 :     ptr += entryno;
                                109                 :                : 
                                110                 :                :     /*
                                111                 :                :      * It's possible we'll try to set the parent xid multiple times but we
                                112                 :                :      * shouldn't ever be changing the xid from one valid xid to another valid
                                113                 :                :      * xid, which would corrupt the data structure.
                                114                 :                :      */
 3295 simon@2ndQuadrant.co      115         [ +  + ]:           8382 :     if (*ptr != parent)
                                116                 :                :     {
                                117         [ -  + ]:           7795 :         Assert(*ptr == InvalidTransactionId);
                                118                 :           7795 :         *ptr = parent;
                                119                 :           7795 :         SubTransCtl->shared->page_dirty[slotno] = true;
                                120                 :                :     }
                                121                 :                : 
  797 alvherre@alvh.no-ip.      122                 :           8382 :     LWLockRelease(lock);
 7978 tgl@sss.pgh.pa.us         123                 :           8382 : }
                                124                 :                : 
                                125                 :                : /*
                                126                 :                :  * Interrogate the parent of a transaction in the subtrans log.
                                127                 :                :  */
                                128                 :                : TransactionId
                                129                 :           3090 : SubTransGetParent(TransactionId xid)
                                130                 :                : {
  888 akorotkov@postgresql      131                 :           3090 :     int64       pageno = TransactionIdToPage(xid);
 7978 tgl@sss.pgh.pa.us         132                 :           3090 :     int         entryno = TransactionIdToEntry(xid);
                                133                 :                :     int         slotno;
                                134                 :                :     TransactionId *ptr;
                                135                 :                :     TransactionId parent;
                                136                 :                : 
                                137                 :                :     /* Can't ask about stuff that might not be around anymore */
 7901                           138         [ -  + ]:           3090 :     Assert(TransactionIdFollowsOrEquals(xid, TransactionXmin));
                                139                 :                : 
                                140                 :                :     /* Bootstrap and frozen XIDs have no parent */
 7978                           141         [ -  + ]:           3090 :     if (!TransactionIdIsNormal(xid))
 7978 tgl@sss.pgh.pa.us         142                 :UBC           0 :         return InvalidTransactionId;
                                143                 :                : 
                                144                 :                :     /* lock is acquired by SimpleLruReadPage_ReadOnly */
                                145                 :                : 
   53 heikki.linnakangas@i      146                 :GNC        3090 :     slotno = SimpleLruReadPage_ReadOnly(SubTransCtl, pageno, &xid);
 7925 tgl@sss.pgh.pa.us         147                 :CBC        3090 :     ptr = (TransactionId *) SubTransCtl->shared->page_buffer[slotno];
 7978                           148                 :           3090 :     ptr += entryno;
                                149                 :                : 
                                150                 :           3090 :     parent = *ptr;
                                151                 :                : 
  797 alvherre@alvh.no-ip.      152                 :           3090 :     LWLockRelease(SimpleLruGetBankLock(SubTransCtl, pageno));
                                153                 :                : 
 7978 tgl@sss.pgh.pa.us         154                 :           3090 :     return parent;
                                155                 :                : }
                                156                 :                : 
                                157                 :                : /*
                                158                 :                :  * SubTransGetTopmostTransaction
                                159                 :                :  *
                                160                 :                :  * Returns the topmost transaction of the given transaction id.
                                161                 :                :  *
                                162                 :                :  * Because we cannot look back further than TransactionXmin, it is possible
                                163                 :                :  * that this function will lie and return an intermediate subtransaction ID
                                164                 :                :  * instead of the true topmost parent ID.  This is OK, because in practice
                                165                 :                :  * we only care about detecting whether the topmost parent is still running
                                166                 :                :  * or is part of a current snapshot's list of still-running transactions.
                                167                 :                :  * Therefore, any XID before TransactionXmin is as good as any other.
                                168                 :                :  */
                                169                 :                : TransactionId
                                170                 :           1084 : SubTransGetTopmostTransaction(TransactionId xid)
                                171                 :                : {
                                172                 :           1084 :     TransactionId parentXid = xid,
 7919 bruce@momjian.us          173                 :           1084 :                 previousXid = xid;
                                174                 :                : 
                                175                 :                :     /* Can't ask about stuff that might not be around anymore */
 7901 tgl@sss.pgh.pa.us         176         [ -  + ]:           1084 :     Assert(TransactionIdFollowsOrEquals(xid, TransactionXmin));
                                177                 :                : 
 7978                           178         [ +  + ]:           4174 :     while (TransactionIdIsValid(parentXid))
                                179                 :                :     {
                                180                 :           3090 :         previousXid = parentXid;
 7901                           181         [ -  + ]:           3090 :         if (TransactionIdPrecedes(parentXid, TransactionXmin))
 7926 tgl@sss.pgh.pa.us         182                 :UBC           0 :             break;
 7978 tgl@sss.pgh.pa.us         183                 :CBC        3090 :         parentXid = SubTransGetParent(parentXid);
                                184                 :                : 
                                185                 :                :         /*
                                186                 :                :          * By convention the parent xid gets allocated first, so should always
                                187                 :                :          * precede the child xid. Anything else points to a corrupted data
                                188                 :                :          * structure that could lead to an infinite loop, so exit.
                                189                 :                :          */
 3295 simon@2ndQuadrant.co      190         [ -  + ]:           3090 :         if (!TransactionIdPrecedes(parentXid, previousXid))
 3295 simon@2ndQuadrant.co      191         [ #  # ]:UBC           0 :             elog(ERROR, "pg_subtrans contains invalid entry: xid %u points to parent xid %u",
                                192                 :                :                  previousXid, parentXid);
                                193                 :                :     }
                                194                 :                : 
 7978 tgl@sss.pgh.pa.us         195         [ -  + ]:CBC        1084 :     Assert(TransactionIdIsValid(previousXid));
                                196                 :                : 
                                197                 :           1084 :     return previousXid;
                                198                 :                : }
                                199                 :                : 
                                200                 :                : /*
                                201                 :                :  * Number of shared SUBTRANS buffers.
                                202                 :                :  *
                                203                 :                :  * If asked to autotune, use 2MB for every 1GB of shared buffers, up to 8MB.
                                204                 :                :  * Otherwise just cap the configured amount to be between 16 and the maximum
                                205                 :                :  * allowed.
                                206                 :                :  */
                                207                 :                : static int
  797 alvherre@alvh.no-ip.      208                 :           2476 : SUBTRANSShmemBuffers(void)
                                209                 :                : {
                                210                 :                :     /* auto-tune based on shared buffers */
                                211         [ +  + ]:           2476 :     if (subtransaction_buffers == 0)
                                212                 :           1232 :         return SimpleLruAutotuneBuffers(512, 1024);
                                213                 :                : 
                                214         [ +  - ]:           1244 :     return Min(Max(16, subtransaction_buffers), SLRU_MAX_ALLOWED_BUFFERS);
                                215                 :                : }
                                216                 :                : 
                                217                 :                : 
                                218                 :                : 
                                219                 :                : /*
                                220                 :                :  * Register shared memory for SUBTRANS
                                221                 :                :  */
                                222                 :                : static void
   29 heikki.linnakangas@i      223                 :GNC        1244 : SUBTRANSShmemRequest(void *arg)
                                224                 :                : {
                                225                 :                :     /* If auto-tuning is requested, now is the time to do it */
  797 alvherre@alvh.no-ip.      226         [ +  + ]:CBC        1244 :     if (subtransaction_buffers == 0)
                                227                 :                :     {
                                228                 :                :         char        buf[32];
                                229                 :                : 
                                230                 :           1232 :         snprintf(buf, sizeof(buf), "%d", SUBTRANSShmemBuffers());
                                231                 :           1232 :         SetConfigOption("subtransaction_buffers", buf, PGC_POSTMASTER,
                                232                 :                :                         PGC_S_DYNAMIC_DEFAULT);
                                233                 :                : 
                                234                 :                :         /*
                                235                 :                :          * We prefer to report this value's source as PGC_S_DYNAMIC_DEFAULT.
                                236                 :                :          * However, if the DBA explicitly set subtransaction_buffers = 0 in
                                237                 :                :          * the config file, then PGC_S_DYNAMIC_DEFAULT will fail to override
                                238                 :                :          * that and we must force the matter with PGC_S_OVERRIDE.
                                239                 :                :          */
                                240         [ -  + ]:           1232 :         if (subtransaction_buffers == 0)    /* failed to apply it? */
  797 alvherre@alvh.no-ip.      241                 :UBC           0 :             SetConfigOption("subtransaction_buffers", buf, PGC_POSTMASTER,
                                242                 :                :                             PGC_S_OVERRIDE);
                                243                 :                :     }
  797 alvherre@alvh.no-ip.      244         [ -  + ]:CBC        1244 :     Assert(subtransaction_buffers != 0);
                                245                 :                : 
   29 heikki.linnakangas@i      246                 :GNC        1244 :     SimpleLruRequest(.desc = &SubTransSlruDesc,
                                247                 :                :                      .name = "subtransaction",
                                248                 :                :                      .Dir = "pg_subtrans",
                                249                 :                :                      .long_segment_names = false,
                                250                 :                : 
                                251                 :                :                      .nslots = SUBTRANSShmemBuffers(),
                                252                 :                : 
                                253                 :                :                      .sync_handler = SYNC_HANDLER_NONE,
                                254                 :                :                      .PagePrecedes = SubTransPagePrecedes,
                                255                 :                :                      .errdetail_for_io_error = subtrans_errdetail_for_io_error,
                                256                 :                : 
                                257                 :                :                      .buffer_tranche_id = LWTRANCHE_SUBTRANS_BUFFER,
                                258                 :                :                      .bank_tranche_id = LWTRANCHE_SUBTRANS_SLRU,
                                259                 :                :         );
                                260                 :           1244 : }
                                261                 :                : 
                                262                 :                : static void
                                263                 :           1241 : SUBTRANSShmemInit(void *arg)
                                264                 :                : {
 1935 noah@leadboat.com         265                 :CBC        1241 :     SlruPagePrecedesUnitTests(SubTransCtl, SUBTRANS_XACTS_PER_PAGE);
 7978 tgl@sss.pgh.pa.us         266                 :           1241 : }
                                267                 :                : 
                                268                 :                : /*
                                269                 :                :  * GUC check_hook for subtransaction_buffers
                                270                 :                :  */
                                271                 :                : bool
  797 alvherre@alvh.no-ip.      272                 :           2542 : check_subtrans_buffers(int *newval, void **extra, GucSource source)
                                273                 :                : {
                                274                 :           2542 :     return check_slru_buffers("subtransaction_buffers", newval);
                                275                 :                : }
                                276                 :                : 
                                277                 :                : /*
                                278                 :                :  * This func must be called ONCE on system install.  It creates
                                279                 :                :  * the initial SUBTRANS segment.  (The SUBTRANS directory is assumed to
                                280                 :                :  * have been created by the initdb shell script, and SUBTRANSShmemInit
                                281                 :                :  * must have been called already.)
                                282                 :                :  *
                                283                 :                :  * Note: it's not really necessary to create the initial segment now,
                                284                 :                :  * since slru.c would create it on first write anyway.  But we may as well
                                285                 :                :  * do it to be sure the directory is set up correctly.
                                286                 :                :  */
                                287                 :                : void
 7978 tgl@sss.pgh.pa.us         288                 :             57 : BootStrapSUBTRANS(void)
                                289                 :                : {
                                290                 :                :     /* Zero the initial page and flush it to disk */
  302 alvherre@kurilemu.de      291                 :GNC          57 :     SimpleLruZeroAndWritePage(SubTransCtl, 0);
 7978 tgl@sss.pgh.pa.us         292                 :GIC          57 : }
                                293                 :                : 
                                294                 :                : /*
                                295                 :                :  * This must be called ONCE during postmaster or standalone-backend startup,
                                296                 :                :  * after StartupXLOG has initialized TransamVariables->nextXid.
                                297                 :                :  *
                                298                 :                :  * oldestActiveXID is the oldest XID of any prepared transaction, or nextXid
                                299                 :                :  * if there are none.
                                300                 :                :  */
                                301                 :                : void
 7627 tgl@sss.pgh.pa.us         302                 :CBC        1075 : StartupSUBTRANS(TransactionId oldestActiveXID)
                                303                 :                : {
                                304                 :                :     FullTransactionId nextXid;
                                305                 :                :     int64       startPage;
                                306                 :                :     int64       endPage;
  791 alvherre@alvh.no-ip.      307                 :           1075 :     LWLock     *prevlock = NULL;
                                308                 :                :     LWLock     *lock;
                                309                 :                : 
                                310                 :                :     /*
                                311                 :                :      * Since we don't expect pg_subtrans to be valid across crashes, we
                                312                 :                :      * initialize the currently-active page(s) to zeroes during startup.
                                313                 :                :      * Whenever we advance into a new page, ExtendSUBTRANS will likewise zero
                                314                 :                :      * the new page without regard to whatever was previously on disk.
                                315                 :                :      */
 7627 tgl@sss.pgh.pa.us         316                 :           1075 :     startPage = TransactionIdToPage(oldestActiveXID);
  879 heikki.linnakangas@i      317                 :           1075 :     nextXid = TransamVariables->nextXid;
 2093 andres@anarazel.de        318                 :           1075 :     endPage = TransactionIdToPage(XidFromFullTransactionId(nextXid));
                                319                 :                : 
                                320                 :                :     for (;;)
                                321                 :                :     {
  797 alvherre@alvh.no-ip.      322                 :           1077 :         lock = SimpleLruGetBankLock(SubTransCtl, startPage);
                                323         [ +  - ]:           1077 :         if (prevlock != lock)
                                324                 :                :         {
  791                           325         [ +  + ]:           1077 :             if (prevlock)
                                326                 :              2 :                 LWLockRelease(prevlock);
  797                           327                 :           1077 :             LWLockAcquire(lock, LW_EXCLUSIVE);
                                328                 :           1077 :             prevlock = lock;
                                329                 :                :         }
                                330                 :                : 
  302 alvherre@kurilemu.de      331                 :GNC        1077 :         (void) SimpleLruZeroPage(SubTransCtl, startPage);
  791 alvherre@alvh.no-ip.      332         [ +  + ]:CBC        1077 :         if (startPage == endPage)
                                333                 :           1075 :             break;
                                334                 :                : 
 7627 tgl@sss.pgh.pa.us         335                 :              2 :         startPage++;
                                336                 :                :         /* must account for wraparound */
 3728 simon@2ndQuadrant.co      337         [ -  + ]:              2 :         if (startPage > TransactionIdToPage(MaxTransactionId))
 3617 rhaas@postgresql.org      338                 :UBC           0 :             startPage = 0;
                                339                 :                :     }
                                340                 :                : 
  797 alvherre@alvh.no-ip.      341                 :CBC        1075 :     LWLockRelease(lock);
 7978 tgl@sss.pgh.pa.us         342                 :           1075 : }
                                343                 :                : 
                                344                 :                : /*
                                345                 :                :  * Perform a checkpoint --- either during shutdown, or on-the-fly
                                346                 :                :  */
                                347                 :                : void
                                348                 :           1944 : CheckPointSUBTRANS(void)
                                349                 :                : {
                                350                 :                :     /*
                                351                 :                :      * Write dirty SUBTRANS pages to disk
                                352                 :                :      *
                                353                 :                :      * This is not actually necessary from a correctness point of view. We do
                                354                 :                :      * it merely to improve the odds that writing of dirty pages is done by
                                355                 :                :      * the checkpoint process and not by backends.
                                356                 :                :      */
                                357                 :                :     TRACE_POSTGRESQL_SUBTRANS_CHECKPOINT_START(true);
 2048 tmunro@postgresql.or      358                 :           1944 :     SimpleLruWriteAll(SubTransCtl, true);
                                359                 :                :     TRACE_POSTGRESQL_SUBTRANS_CHECKPOINT_DONE(true);
 7978 tgl@sss.pgh.pa.us         360                 :           1944 : }
                                361                 :                : 
                                362                 :                : 
                                363                 :                : /*
                                364                 :                :  * Make sure that SUBTRANS has room for a newly-allocated XID.
                                365                 :                :  *
                                366                 :                :  * NB: this is called while holding XidGenLock.  We want it to be very fast
                                367                 :                :  * most of the time; even when it's not so fast, no actual I/O need happen
                                368                 :                :  * unless we're forced to write out a dirty subtrans page to make room
                                369                 :                :  * in shared memory.
                                370                 :                :  */
                                371                 :                : void
                                372                 :         196632 : ExtendSUBTRANS(TransactionId newestXact)
                                373                 :                : {
                                374                 :                :     int64       pageno;
                                375                 :                :     LWLock     *lock;
                                376                 :                : 
                                377                 :                :     /*
                                378                 :                :      * No work except at first XID of a page.  But beware: just after
                                379                 :                :      * wraparound, the first XID of page zero is FirstNormalTransactionId.
                                380                 :                :      */
                                381   [ +  +  +  + ]:         196632 :     if (TransactionIdToEntry(newestXact) != 0 &&
                                382                 :                :         !TransactionIdEquals(newestXact, FirstNormalTransactionId))
                                383                 :         196513 :         return;
                                384                 :                : 
                                385                 :            119 :     pageno = TransactionIdToPage(newestXact);
                                386                 :                : 
  797 alvherre@alvh.no-ip.      387                 :            119 :     lock = SimpleLruGetBankLock(SubTransCtl, pageno);
                                388                 :            119 :     LWLockAcquire(lock, LW_EXCLUSIVE);
                                389                 :                : 
                                390                 :                :     /* Zero the page */
  302 alvherre@kurilemu.de      391                 :GNC         119 :     SimpleLruZeroPage(SubTransCtl, pageno);
                                392                 :                : 
  797 alvherre@alvh.no-ip.      393                 :CBC         119 :     LWLockRelease(lock);
                                394                 :                : }
                                395                 :                : 
                                396                 :                : 
                                397                 :                : /*
                                398                 :                :  * Remove all SUBTRANS segments before the one holding the passed transaction ID
                                399                 :                :  *
                                400                 :                :  * oldestXact is the oldest TransactionXmin of any running transaction.  This
                                401                 :                :  * is called only during checkpoint.
                                402                 :                :  */
                                403                 :                : void
 7978 tgl@sss.pgh.pa.us         404                 :           1914 : TruncateSUBTRANS(TransactionId oldestXact)
                                405                 :                : {
                                406                 :                :     int64       cutoffPage;
                                407                 :                : 
                                408                 :                :     /*
                                409                 :                :      * The cutoff point is the start of the segment containing oldestXact. We
                                410                 :                :      * pass the *page* containing oldestXact to SimpleLruTruncate.  We step
                                411                 :                :      * back one transaction to avoid passing a cutoff page that hasn't been
                                412                 :                :      * created yet in the rare case that oldestXact would be the first item on
                                413                 :                :      * a page and oldestXact == next XID.  In that case, if we didn't subtract
                                414                 :                :      * one, we'd trigger SimpleLruTruncate's wraparound detection.
                                415                 :                :      */
 3939 heikki.linnakangas@i      416         [ +  + ]:           2091 :     TransactionIdRetreat(oldestXact);
 7978 tgl@sss.pgh.pa.us         417                 :           1914 :     cutoffPage = TransactionIdToPage(oldestXact);
                                418                 :                : 
                                419                 :           1914 :     SimpleLruTruncate(SubTransCtl, cutoffPage);
                                420                 :           1914 : }
                                421                 :                : 
                                422                 :                : 
                                423                 :                : /*
                                424                 :                :  * Decide whether a SUBTRANS page number is "older" for truncation purposes.
                                425                 :                :  * Analogous to CLOGPagePrecedes().
                                426                 :                :  */
                                427                 :                : static bool
  888 akorotkov@postgresql      428                 :          54674 : SubTransPagePrecedes(int64 page1, int64 page2)
                                429                 :                : {
                                430                 :                :     TransactionId xid1;
                                431                 :                :     TransactionId xid2;
                                432                 :                : 
 7978 tgl@sss.pgh.pa.us         433                 :          54674 :     xid1 = ((TransactionId) page1) * SUBTRANS_XACTS_PER_PAGE;
 1935 noah@leadboat.com         434                 :          54674 :     xid1 += FirstNormalTransactionId + 1;
 7978 tgl@sss.pgh.pa.us         435                 :          54674 :     xid2 = ((TransactionId) page2) * SUBTRANS_XACTS_PER_PAGE;
 1935 noah@leadboat.com         436                 :          54674 :     xid2 += FirstNormalTransactionId + 1;
                                437                 :                : 
                                438   [ +  +  +  + ]:          87392 :     return (TransactionIdPrecedes(xid1, xid2) &&
                                439                 :          32718 :             TransactionIdPrecedes(xid1, xid2 + SUBTRANS_XACTS_PER_PAGE - 1));
                                440                 :                : }
                                441                 :                : 
                                442                 :                : static int
   53 heikki.linnakangas@i      443                 :UNC           0 : subtrans_errdetail_for_io_error(const void *opaque_data)
                                444                 :                : {
                                445                 :              0 :     TransactionId xid = *(const TransactionId *) opaque_data;
                                446                 :                : 
                                447                 :              0 :     return errdetail("Could not access subtransaction status of transaction %u.", xid);
                                448                 :                : }
        

Generated by: LCOV version 2.5.0-beta