LCOV - differential code coverage report
Current view: top level - src/backend/access/transam - transam.c (source / functions) Coverage Total Hit LBC UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 80.7 % 83 67 16 67
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 12 12 12
Baseline: 16@8cea358b128 Branches: 67.9 % 56 38 1 17 38
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 80.7 % 83 67 16 67
Function coverage date bins:
(240..) days: 100.0 % 12 12 12
Branch coverage date bins:
(240..) days: 67.9 % 56 38 1 17 38

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * transam.c
                                  4                 :                :  *    postgres transaction (commit) log interface routines
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/access/transam/transam.c
                                 12                 :                :  *
                                 13                 :                :  * NOTES
                                 14                 :                :  *    This file contains the high level access-method interface to the
                                 15                 :                :  *    transaction system.
                                 16                 :                :  *
                                 17                 :                :  *-------------------------------------------------------------------------
                                 18                 :                :  */
                                 19                 :                : 
                                 20                 :                : #include "postgres.h"
                                 21                 :                : 
                                 22                 :                : #include "access/clog.h"
                                 23                 :                : #include "access/subtrans.h"
                                 24                 :                : #include "access/transam.h"
                                 25                 :                : #include "utils/snapmgr.h"
                                 26                 :                : 
                                 27                 :                : /*
                                 28                 :                :  * Single-item cache for results of TransactionLogFetch.  It's worth having
                                 29                 :                :  * such a cache because we frequently find ourselves repeatedly checking the
                                 30                 :                :  * same XID, for example when scanning a table just after a bulk insert,
                                 31                 :                :  * update, or delete.
                                 32                 :                :  */
                                 33                 :                : static TransactionId cachedFetchXid = InvalidTransactionId;
                                 34                 :                : static XidStatus cachedFetchXidStatus;
                                 35                 :                : static XLogRecPtr cachedCommitLSN;
                                 36                 :                : 
                                 37                 :                : /* Local functions */
                                 38                 :                : static XidStatus TransactionLogFetch(TransactionId transactionId);
                                 39                 :                : 
                                 40                 :                : 
                                 41                 :                : /* ----------------------------------------------------------------
                                 42                 :                :  *      Postgres log access method interface
                                 43                 :                :  *
                                 44                 :                :  *      TransactionLogFetch
                                 45                 :                :  * ----------------------------------------------------------------
                                 46                 :                :  */
                                 47                 :                : 
                                 48                 :                : /*
                                 49                 :                :  * TransactionLogFetch --- fetch commit status of specified transaction id
                                 50                 :                :  */
                                 51                 :                : static XidStatus
 7227 tgl@sss.pgh.pa.us          52                 :CBC     9828403 : TransactionLogFetch(TransactionId transactionId)
                                 53                 :                : {
                                 54                 :                :     XidStatus   xidstatus;
                                 55                 :                :     XLogRecPtr  xidlsn;
                                 56                 :                : 
                                 57                 :                :     /*
                                 58                 :                :      * Before going to the commit log manager, check our single item cache to
                                 59                 :                :      * see if we didn't just check the transaction status a moment ago.
                                 60                 :                :      */
                                 61         [ +  + ]:        9828403 :     if (TransactionIdEquals(transactionId, cachedFetchXid))
                                 62                 :        8677434 :         return cachedFetchXidStatus;
                                 63                 :                : 
                                 64                 :                :     /*
                                 65                 :                :      * Also, check to see if the transaction ID is a permanent one.
                                 66                 :                :      */
 8207 bruce@momjian.us           67         [ +  + ]:        1150969 :     if (!TransactionIdIsNormal(transactionId))
                                 68                 :                :     {
 8268 tgl@sss.pgh.pa.us          69         [ +  + ]:         511059 :         if (TransactionIdEquals(transactionId, BootstrapTransactionId))
 7227                            70                 :         507149 :             return TRANSACTION_STATUS_COMMITTED;
 8268                            71         [ +  + ]:           3910 :         if (TransactionIdEquals(transactionId, FrozenTransactionId))
 7227                            72                 :           3906 :             return TRANSACTION_STATUS_COMMITTED;
                                 73                 :              4 :         return TRANSACTION_STATUS_ABORTED;
                                 74                 :                :     }
                                 75                 :                : 
                                 76                 :                :     /*
                                 77                 :                :      * Get the transaction status.
                                 78                 :                :      */
 6101                            79                 :         639910 :     xidstatus = TransactionIdGetStatus(transactionId, &xidlsn);
                                 80                 :                : 
                                 81                 :                :     /*
                                 82                 :                :      * Cache it, but DO NOT cache status for unfinished or sub-committed
                                 83                 :                :      * transactions!  We only cache status that is guaranteed not to change.
                                 84                 :                :      */
 7227                            85   [ +  +  +  - ]:         639910 :     if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
                                 86                 :                :         xidstatus != TRANSACTION_STATUS_SUB_COMMITTED)
                                 87                 :                :     {
 6101                            88                 :         590462 :         cachedFetchXid = transactionId;
 7227                            89                 :         590462 :         cachedFetchXidStatus = xidstatus;
 6101                            90                 :         590462 :         cachedCommitLSN = xidlsn;
                                 91                 :                :     }
                                 92                 :                : 
 7227                            93                 :         639910 :     return xidstatus;
                                 94                 :                : }
                                 95                 :                : 
                                 96                 :                : /* ----------------------------------------------------------------
                                 97                 :                :  *                      Interface functions
                                 98                 :                :  *
                                 99                 :                :  *      TransactionIdDidCommit
                                100                 :                :  *      TransactionIdDidAbort
                                101                 :                :  *      ========
                                102                 :                :  *         these functions test the transaction status of
                                103                 :                :  *         a specified transaction id.
                                104                 :                :  *
                                105                 :                :  *      TransactionIdCommitTree
                                106                 :                :  *      TransactionIdAsyncCommitTree
                                107                 :                :  *      TransactionIdAbortTree
                                108                 :                :  *      ========
                                109                 :                :  *         these functions set the transaction status of the specified
                                110                 :                :  *         transaction tree.
                                111                 :                :  *
                                112                 :                :  * See also TransactionIdIsInProgress, which once was in this module
                                113                 :                :  * but now lives in procarray.c, as well as comments at the top of
                                114                 :                :  * heapam_visibility.c that explain how everything fits together.
                                115                 :                :  * ----------------------------------------------------------------
                                116                 :                :  */
                                117                 :                : 
                                118                 :                : /*
                                119                 :                :  * TransactionIdDidCommit
                                120                 :                :  *      True iff transaction associated with the identifier did commit.
                                121                 :                :  *
                                122                 :                :  * Note:
                                123                 :                :  *      Assumes transaction identifier is valid and exists in clog.
                                124                 :                :  */
                                125                 :                : bool                            /* true if given transaction committed */
10141 scrappy@hub.org           126                 :        9806355 : TransactionIdDidCommit(TransactionId transactionId)
                                127                 :                : {
                                128                 :                :     XidStatus   xidstatus;
                                129                 :                : 
 7227 tgl@sss.pgh.pa.us         130                 :        9806355 :     xidstatus = TransactionLogFetch(transactionId);
                                131                 :                : 
                                132                 :                :     /*
                                133                 :                :      * If it's marked committed, it's committed.
                                134                 :                :      */
                                135         [ +  + ]:        9806355 :     if (xidstatus == TRANSACTION_STATUS_COMMITTED)
                                136                 :        9690141 :         return true;
                                137                 :                : 
                                138                 :                :     /*
                                139                 :                :      * If it's marked subcommitted, we have to check the parent recursively.
                                140                 :                :      * However, if it's older than TransactionXmin, we can't look at
                                141                 :                :      * pg_subtrans; instead assume that the parent crashed without cleaning up
                                142                 :                :      * its children.
                                143                 :                :      *
                                144                 :                :      * Originally we Assert'ed that the result of SubTransGetParent was not
                                145                 :                :      * zero. However with the introduction of prepared transactions, there can
                                146                 :                :      * be a window just after database startup where we do not have complete
                                147                 :                :      * knowledge in pg_subtrans of the transactions after TransactionXmin.
                                148                 :                :      * StartupSUBTRANS() has ensured that any missing information will be
                                149                 :                :      * zeroed.  Since this case should not happen under normal conditions, it
                                150                 :                :      * seems reasonable to emit a WARNING for it.
                                151                 :                :      */
                                152         [ -  + ]:         116214 :     if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
                                153                 :                :     {
                                154                 :                :         TransactionId parentXid;
                                155                 :                : 
 7150 tgl@sss.pgh.pa.us         156         [ #  # ]:UBC           0 :         if (TransactionIdPrecedes(transactionId, TransactionXmin))
 7175                           157                 :              0 :             return false;
 7227                           158                 :              0 :         parentXid = SubTransGetParent(transactionId);
 6876                           159         [ #  # ]:              0 :         if (!TransactionIdIsValid(parentXid))
                                160                 :                :         {
                                161         [ #  # ]:              0 :             elog(WARNING, "no pg_subtrans entry for subcommitted XID %u",
                                162                 :                :                  transactionId);
                                163                 :              0 :             return false;
                                164                 :                :         }
 7227                           165                 :              0 :         return TransactionIdDidCommit(parentXid);
                                166                 :                :     }
                                167                 :                : 
                                168                 :                :     /*
                                169                 :                :      * It's not committed.
                                170                 :                :      */
 7227 tgl@sss.pgh.pa.us         171                 :CBC      116214 :     return false;
                                172                 :                : }
                                173                 :                : 
                                174                 :                : /*
                                175                 :                :  * TransactionIdDidAbort
                                176                 :                :  *      True iff transaction associated with the identifier did abort.
                                177                 :                :  *
                                178                 :                :  * Note:
                                179                 :                :  *      Assumes transaction identifier is valid and exists in clog.
                                180                 :                :  *
                                181                 :                :  *      Returns true only for explicitly aborted transactions, as transactions
                                182                 :                :  *      implicitly aborted due to a crash will commonly still appear to be
                                183                 :                :  *      in-progress in the clog.  Most of the time TransactionIdDidCommit(),
                                184                 :                :  *      with a preceding TransactionIdIsInProgress() check, should be used
                                185                 :                :  *      instead of TransactionIdDidAbort().
                                186                 :                :  */
                                187                 :                : bool                            /* true if given transaction aborted */
10141 scrappy@hub.org           188                 :          22048 : TransactionIdDidAbort(TransactionId transactionId)
                                189                 :                : {
                                190                 :                :     XidStatus   xidstatus;
                                191                 :                : 
 7227 tgl@sss.pgh.pa.us         192                 :          22048 :     xidstatus = TransactionLogFetch(transactionId);
                                193                 :                : 
                                194                 :                :     /*
                                195                 :                :      * If it's marked aborted, it's aborted.
                                196                 :                :      */
                                197         [ +  + ]:          22048 :     if (xidstatus == TRANSACTION_STATUS_ABORTED)
                                198                 :             18 :         return true;
                                199                 :                : 
                                200                 :                :     /*
                                201                 :                :      * If it's marked subcommitted, we have to check the parent recursively.
                                202                 :                :      * However, if it's older than TransactionXmin, we can't look at
                                203                 :                :      * pg_subtrans; instead assume that the parent crashed without cleaning up
                                204                 :                :      * its children.
                                205                 :                :      */
                                206         [ -  + ]:          22030 :     if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
                                207                 :                :     {
                                208                 :                :         TransactionId parentXid;
                                209                 :                : 
 7150 tgl@sss.pgh.pa.us         210         [ #  # ]:UBC           0 :         if (TransactionIdPrecedes(transactionId, TransactionXmin))
 7175                           211                 :              0 :             return true;
                                212                 :              0 :         parentXid = SubTransGetParent(transactionId);
 6876                           213         [ #  # ]:              0 :         if (!TransactionIdIsValid(parentXid))
                                214                 :                :         {
                                215                 :                :             /* see notes in TransactionIdDidCommit */
                                216         [ #  # ]:              0 :             elog(WARNING, "no pg_subtrans entry for subcommitted XID %u",
                                217                 :                :                  transactionId);
                                218                 :              0 :             return true;
                                219                 :                :         }
 7175                           220                 :              0 :         return TransactionIdDidAbort(parentXid);
                                221                 :                :     }
                                222                 :                : 
                                223                 :                :     /*
                                224                 :                :      * It's not aborted.
                                225                 :                :      */
 7227 tgl@sss.pgh.pa.us         226                 :CBC       22030 :     return false;
                                227                 :                : }
                                228                 :                : 
                                229                 :                : /*
                                230                 :                :  * TransactionIdCommitTree
                                231                 :                :  *      Marks the given transaction and children as committed
                                232                 :                :  *
                                233                 :                :  * "xid" is a toplevel transaction commit, and the xids array contains its
                                234                 :                :  * committed subtransactions.
                                235                 :                :  *
                                236                 :                :  * This commit operation is not guaranteed to be atomic, but if not, subxids
                                237                 :                :  * are correctly marked subcommit first.
                                238                 :                :  */
                                239                 :                : void
 5655 alvherre@alvh.no-ip.      240                 :         105648 : TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids)
                                241                 :                : {
                                242                 :         105648 :     TransactionIdSetTreeStatus(xid, nxids, xids,
                                243                 :                :                                TRANSACTION_STATUS_COMMITTED,
                                244                 :                :                                InvalidXLogRecPtr);
 7227 tgl@sss.pgh.pa.us         245                 :         105648 : }
                                246                 :                : 
                                247                 :                : /*
                                248                 :                :  * TransactionIdAsyncCommitTree
                                249                 :                :  *      Same as above, but for async commits.  The commit record LSN is needed.
                                250                 :                :  */
                                251                 :                : void
 5655 alvherre@alvh.no-ip.      252                 :          24053 : TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids,
                                253                 :                :                              XLogRecPtr lsn)
                                254                 :                : {
                                255                 :          24053 :     TransactionIdSetTreeStatus(xid, nxids, xids,
                                256                 :                :                                TRANSACTION_STATUS_COMMITTED, lsn);
 6101 tgl@sss.pgh.pa.us         257                 :          24053 : }
                                258                 :                : 
                                259                 :                : /*
                                260                 :                :  * TransactionIdAbortTree
                                261                 :                :  *      Marks the given transaction and children as aborted.
                                262                 :                :  *
                                263                 :                :  * "xid" is a toplevel transaction commit, and the xids array contains its
                                264                 :                :  * committed subtransactions.
                                265                 :                :  *
                                266                 :                :  * We don't need to worry about the non-atomic behavior, since any onlookers
                                267                 :                :  * will consider all the xacts as not-yet-committed anyway.
                                268                 :                :  */
                                269                 :                : void
 5655 alvherre@alvh.no-ip.      270                 :           7033 : TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids)
                                271                 :                : {
                                272                 :           7033 :     TransactionIdSetTreeStatus(xid, nxids, xids,
                                273                 :                :                                TRANSACTION_STATUS_ABORTED, InvalidXLogRecPtr);
 7227 tgl@sss.pgh.pa.us         274                 :           7033 : }
                                275                 :                : 
                                276                 :                : /*
                                277                 :                :  * TransactionIdPrecedes --- is id1 logically < id2?
                                278                 :                :  */
                                279                 :                : bool
 8267                           280                 :      130618814 : TransactionIdPrecedes(TransactionId id1, TransactionId id2)
                                281                 :                : {
                                282                 :                :     /*
                                283                 :                :      * If either ID is a permanent XID then we can just do unsigned
                                284                 :                :      * comparison.  If both are normal, do a modulo-2^32 comparison.
                                285                 :                :      */
                                286                 :                :     int32       diff;
                                287                 :                : 
                                288   [ +  +  +  + ]:      130618814 :     if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
                                289                 :       44012519 :         return (id1 < id2);
                                290                 :                : 
                                291                 :       86606295 :     diff = (int32) (id1 - id2);
                                292                 :       86606295 :     return (diff < 0);
                                293                 :                : }
                                294                 :                : 
                                295                 :                : /*
                                296                 :                :  * TransactionIdPrecedesOrEquals --- is id1 logically <= id2?
                                297                 :                :  */
                                298                 :                : bool
                                299                 :        8971524 : TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
                                300                 :                : {
                                301                 :                :     int32       diff;
                                302                 :                : 
                                303   [ +  -  +  + ]:        8971524 :     if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
                                304                 :           1011 :         return (id1 <= id2);
                                305                 :                : 
                                306                 :        8970513 :     diff = (int32) (id1 - id2);
                                307                 :        8970513 :     return (diff <= 0);
                                308                 :                : }
                                309                 :                : 
                                310                 :                : /*
                                311                 :                :  * TransactionIdFollows --- is id1 logically > id2?
                                312                 :                :  */
                                313                 :                : bool
                                314                 :       29171416 : TransactionIdFollows(TransactionId id1, TransactionId id2)
                                315                 :                : {
                                316                 :                :     int32       diff;
                                317                 :                : 
                                318   [ +  +  +  + ]:       29171416 :     if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
                                319                 :       16313140 :         return (id1 > id2);
                                320                 :                : 
                                321                 :       12858276 :     diff = (int32) (id1 - id2);
                                322                 :       12858276 :     return (diff > 0);
                                323                 :                : }
                                324                 :                : 
                                325                 :                : /*
                                326                 :                :  * TransactionIdFollowsOrEquals --- is id1 logically >= id2?
                                327                 :                :  */
                                328                 :                : bool
                                329                 :       62604862 : TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
                                330                 :                : {
                                331                 :                :     int32       diff;
                                332                 :                : 
                                333   [ +  +  -  + ]:       62604862 :     if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
                                334                 :          53072 :         return (id1 >= id2);
                                335                 :                : 
                                336                 :       62551790 :     diff = (int32) (id1 - id2);
                                337                 :       62551790 :     return (diff >= 0);
                                338                 :                : }
                                339                 :                : 
                                340                 :                : 
                                341                 :                : /*
                                342                 :                :  * TransactionIdLatest --- get latest XID among a main xact and its children
                                343                 :                :  */
                                344                 :                : TransactionId
 6063                           345                 :         166180 : TransactionIdLatest(TransactionId mainxid,
                                346                 :                :                     int nxids, const TransactionId *xids)
                                347                 :                : {
                                348                 :                :     TransactionId result;
                                349                 :                : 
                                350                 :                :     /*
                                351                 :                :      * In practice it is highly likely that the xids[] array is sorted, and so
                                352                 :                :      * we could save some cycles by just taking the last child XID, but this
                                353                 :                :      * probably isn't so performance-critical that it's worth depending on
                                354                 :                :      * that assumption.  But just to show we're not totally stupid, scan the
                                355                 :                :      * array back-to-front to avoid useless assignments.
                                356                 :                :      */
                                357                 :         166180 :     result = mainxid;
                                358         [ +  + ]:         174746 :     while (--nxids >= 0)
                                359                 :                :     {
                                360         [ +  + ]:           8566 :         if (TransactionIdPrecedes(result, xids[nxids]))
                                361                 :            743 :             result = xids[nxids];
                                362                 :                :     }
                                363                 :         166180 :     return result;
                                364                 :                : }
                                365                 :                : 
                                366                 :                : 
                                367                 :                : /*
                                368                 :                :  * TransactionIdGetCommitLSN
                                369                 :                :  *
                                370                 :                :  * This function returns an LSN that is late enough to be able
                                371                 :                :  * to guarantee that if we flush up to the LSN returned then we
                                372                 :                :  * will have flushed the transaction's commit record to disk.
                                373                 :                :  *
                                374                 :                :  * The result is not necessarily the exact LSN of the transaction's
                                375                 :                :  * commit record!  For example, for long-past transactions (those whose
                                376                 :                :  * clog pages already migrated to disk), we'll return InvalidXLogRecPtr.
                                377                 :                :  * Also, because we group transactions on the same clog page to conserve
                                378                 :                :  * storage, we might return the LSN of a later transaction that falls into
                                379                 :                :  * the same group.
                                380                 :                :  */
                                381                 :                : XLogRecPtr
 6101                           382                 :        8921133 : TransactionIdGetCommitLSN(TransactionId xid)
                                383                 :                : {
                                384                 :                :     XLogRecPtr  result;
                                385                 :                : 
                                386                 :                :     /*
                                387                 :                :      * Currently, all uses of this function are for xids that were just
                                388                 :                :      * reported to be committed by TransactionLogFetch, so we expect that
                                389                 :                :      * checking TransactionLogFetch's cache will usually succeed and avoid an
                                390                 :                :      * extra trip to shared memory.
                                391                 :                :      */
                                392         [ +  + ]:        8921133 :     if (TransactionIdEquals(xid, cachedFetchXid))
                                393                 :        8430591 :         return cachedCommitLSN;
                                394                 :                : 
                                395                 :                :     /* Special XIDs are always known committed */
                                396         [ +  - ]:         490542 :     if (!TransactionIdIsNormal(xid))
                                397                 :         490542 :         return InvalidXLogRecPtr;
                                398                 :                : 
                                399                 :                :     /*
                                400                 :                :      * Get the transaction status.
                                401                 :                :      */
 6101 tgl@sss.pgh.pa.us         402                 :UBC           0 :     (void) TransactionIdGetStatus(xid, &result);
                                403                 :                : 
                                404                 :              0 :     return result;
                                405                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622