LCOV - differential code coverage report
Current view: top level - src/bin/pg_upgrade - multixact_rewrite.c (source / functions) Coverage Total Hit UNC
Current: 7a15cff1f11193467898da1c1fabf06fd2caee04 vs 84a3778c79c2d28b4dc281d03ef2ab019b16483b Lines: 0.0 % 52 0 52
Current Date: 2025-12-15 18:36:29 -0500 Functions: 0.0 % 3 0 3
Baseline: lcov-20251216-010103-baseline Branches: 0.0 % 18 0 18
Baseline Date: 2025-12-15 13:30:48 -0800 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(1,7] days: 0.0 % 52 0 52
Function coverage date bins:
(1,7] days: 0.0 % 3 0 3
Branch coverage date bins:
(1,7] days: 0.0 % 18 0 18

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * multixact_rewrite.c
                                  3                 :                :  *
                                  4                 :                :  * Functions to convert multixact SLRUs from the pre-v19 format to the current
                                  5                 :                :  * format with 64-bit MultiXactOffsets.
                                  6                 :                :  *
                                  7                 :                :  * Copyright (c) 2025, PostgreSQL Global Development Group
                                  8                 :                :  * src/bin/pg_upgrade/multixact_rewrite.c
                                  9                 :                :  */
                                 10                 :                : 
                                 11                 :                : #include "postgres_fe.h"
                                 12                 :                : 
                                 13                 :                : #include "access/multixact_internal.h"
                                 14                 :                : #include "multixact_read_v18.h"
                                 15                 :                : #include "pg_upgrade.h"
                                 16                 :                : 
                                 17                 :                : static void RecordMultiXactOffset(SlruSegState *offsets_writer, MultiXactId multi,
                                 18                 :                :                                   MultiXactOffset offset);
                                 19                 :                : static void RecordMultiXactMembers(SlruSegState *members_writer,
                                 20                 :                :                                    MultiXactOffset offset,
                                 21                 :                :                                    int nmembers, MultiXactMember *members);
                                 22                 :                : 
                                 23                 :                : /*
                                 24                 :                :  * Convert pg_multixact/offset and /members from the old pre-v19 format with
                                 25                 :                :  * 32-bit offsets to the current format.
                                 26                 :                :  *
                                 27                 :                :  * Multixids in the range [from_multi, to_multi) are read from the old
                                 28                 :                :  * cluster, and written in the new format.  An important edge case is that if
                                 29                 :                :  * from_multi == to_multi, this initializes the new pg_multixact files in the
                                 30                 :                :  * new format without trying to open any old files.  (We rely on that when
                                 31                 :                :  * upgrading from PostgreSQL version 9.2 or below.)
                                 32                 :                :  *
                                 33                 :                :  * Returns the new nextOffset value; the caller should set it in the new
                                 34                 :                :  * control file.  The new members always start from offset 1, regardless of
                                 35                 :                :  * the offset range used in the old cluster.
                                 36                 :                :  */
                                 37                 :                : MultiXactOffset
    7 heikki.linnakangas@i       38                 :UNC           0 : rewrite_multixacts(MultiXactId from_multi, MultiXactId to_multi)
                                 39                 :                : {
                                 40                 :                :     MultiXactOffset next_offset;
                                 41                 :                :     SlruSegState *offsets_writer;
                                 42                 :                :     SlruSegState *members_writer;
                                 43                 :              0 :     char        dir[MAXPGPATH] = {0};
                                 44                 :              0 :     bool        prev_multixid_valid = false;
                                 45                 :                : 
                                 46                 :                :     /*
                                 47                 :                :      * The range of valid multi XIDs is unchanged by the conversion (they are
                                 48                 :                :      * referenced from the heap tables), but the members SLRU is rewritten to
                                 49                 :                :      * start from offset 1.
                                 50                 :                :      */
                                 51                 :              0 :     next_offset = 1;
                                 52                 :                : 
                                 53                 :                :     /* Prepare to write the new SLRU files */
                                 54                 :              0 :     pg_sprintf(dir, "%s/pg_multixact/offsets", new_cluster.pgdata);
                                 55                 :              0 :     offsets_writer = AllocSlruWrite(dir, false);
                                 56                 :              0 :     SlruWriteSwitchPage(offsets_writer, MultiXactIdToOffsetPage(from_multi));
                                 57                 :                : 
                                 58                 :              0 :     pg_sprintf(dir, "%s/pg_multixact/members", new_cluster.pgdata);
                                 59                 :              0 :     members_writer = AllocSlruWrite(dir, true /* use long segment names */ );
                                 60                 :              0 :     SlruWriteSwitchPage(members_writer, MXOffsetToMemberPage(next_offset));
                                 61                 :                : 
                                 62                 :                :     /*
                                 63                 :                :      * Convert old multixids, if needed, by reading them one-by-one from the
                                 64                 :                :      * old cluster.
                                 65                 :                :      */
                                 66         [ #  # ]:              0 :     if (to_multi != from_multi)
                                 67                 :                :     {
                                 68                 :                :         OldMultiXactReader *old_reader;
                                 69                 :                : 
                                 70                 :              0 :         old_reader = AllocOldMultiXactRead(old_cluster.pgdata,
                                 71                 :                :                                            old_cluster.controldata.chkpnt_nxtmulti,
                                 72                 :              0 :                                            old_cluster.controldata.chkpnt_nxtmxoff);
                                 73                 :                : 
                                 74         [ #  # ]:              0 :         for (MultiXactId multi = from_multi; multi != to_multi;)
                                 75                 :                :         {
                                 76                 :                :             MultiXactMember member;
                                 77                 :                :             bool        multixid_valid;
                                 78                 :                : 
                                 79                 :                :             /*
                                 80                 :                :              * Read this multixid's members.
                                 81                 :                :              *
                                 82                 :                :              * Locking-only XIDs that may be part of multi-xids don't matter
                                 83                 :                :              * after upgrade, as there can be no transactions running across
                                 84                 :                :              * upgrade.  So as a small optimization, we only read one member
                                 85                 :                :              * from each multixid: the one updating one, or if there was no
                                 86                 :                :              * update, arbitrarily the first locking xid.
                                 87                 :                :              */
                                 88                 :              0 :             multixid_valid = GetOldMultiXactIdSingleMember(old_reader, multi, &member);
                                 89                 :                : 
                                 90                 :                :             /*
                                 91                 :                :              * Write the new offset to pg_multixact/offsets.
                                 92                 :                :              *
                                 93                 :                :              * Even if this multixid is invalid, we still need to write its
                                 94                 :                :              * offset if the *previous* multixid was valid.  That's because
                                 95                 :                :              * when reading a multixid, the number of members is calculated
                                 96                 :                :              * from the difference between the two offsets.
                                 97                 :                :              */
                                 98         [ #  # ]:              0 :             RecordMultiXactOffset(offsets_writer, multi,
                                 99         [ #  # ]:              0 :                                   (multixid_valid || prev_multixid_valid) ? next_offset : 0);
                                100                 :                : 
                                101                 :                :             /* Write the members */
                                102         [ #  # ]:              0 :             if (multixid_valid)
                                103                 :                :             {
                                104                 :              0 :                 RecordMultiXactMembers(members_writer, next_offset, 1, &member);
                                105                 :              0 :                 next_offset += 1;
                                106                 :                :             }
                                107                 :                : 
                                108                 :                :             /* Advance to next multixid, handling wraparound */
                                109                 :              0 :             multi++;
                                110         [ #  # ]:              0 :             if (multi < FirstMultiXactId)
                                111                 :              0 :                 multi = FirstMultiXactId;
                                112                 :              0 :             prev_multixid_valid = multixid_valid;
                                113                 :                :         }
                                114                 :                : 
                                115                 :              0 :         FreeOldMultiXactReader(old_reader);
                                116                 :                :     }
                                117                 :                : 
                                118                 :                :     /* Write the final 'next' offset to the last SLRU page */
                                119         [ #  # ]:              0 :     RecordMultiXactOffset(offsets_writer, to_multi,
                                120                 :                :                           prev_multixid_valid ? next_offset : 0);
                                121                 :                : 
                                122                 :                :     /* Flush the last SLRU pages */
                                123                 :              0 :     FreeSlruWrite(offsets_writer);
                                124                 :              0 :     FreeSlruWrite(members_writer);
                                125                 :                : 
                                126                 :              0 :     return next_offset;
                                127                 :                : }
                                128                 :                : 
                                129                 :                : 
                                130                 :                : /*
                                131                 :                :  * Write one offset to the offset SLRU
                                132                 :                :  */
                                133                 :                : static void
                                134                 :              0 : RecordMultiXactOffset(SlruSegState *offsets_writer, MultiXactId multi,
                                135                 :                :                       MultiXactOffset offset)
                                136                 :                : {
                                137                 :                :     int64       pageno;
                                138                 :                :     int         entryno;
                                139                 :                :     char       *buf;
                                140                 :                :     MultiXactOffset *offptr;
                                141                 :                : 
                                142                 :              0 :     pageno = MultiXactIdToOffsetPage(multi);
                                143                 :              0 :     entryno = MultiXactIdToOffsetEntry(multi);
                                144                 :                : 
                                145                 :              0 :     buf = SlruWriteSwitchPage(offsets_writer, pageno);
                                146                 :              0 :     offptr = (MultiXactOffset *) buf;
                                147                 :              0 :     offptr[entryno] = offset;
                                148                 :              0 : }
                                149                 :                : 
                                150                 :                : /*
                                151                 :                :  * Write the members for one multixid in the members SLRU
                                152                 :                :  *
                                153                 :                :  * (Currently, this is only ever called with nmembers == 1)
                                154                 :                :  */
                                155                 :                : static void
                                156                 :              0 : RecordMultiXactMembers(SlruSegState *members_writer,
                                157                 :                :                        MultiXactOffset offset,
                                158                 :                :                        int nmembers, MultiXactMember *members)
                                159                 :                : {
                                160         [ #  # ]:              0 :     for (int i = 0; i < nmembers; i++, offset++)
                                161                 :                :     {
                                162                 :                :         int64       pageno;
                                163                 :                :         char       *buf;
                                164                 :                :         TransactionId *memberptr;
                                165                 :                :         uint32     *flagsptr;
                                166                 :                :         uint32      flagsval;
                                167                 :                :         int         bshift;
                                168                 :                :         int         flagsoff;
                                169                 :                :         int         memberoff;
                                170                 :                : 
                                171         [ #  # ]:              0 :         Assert(members[i].status <= MultiXactStatusUpdate);
                                172                 :                : 
                                173                 :              0 :         pageno = MXOffsetToMemberPage(offset);
                                174                 :              0 :         memberoff = MXOffsetToMemberOffset(offset);
                                175                 :              0 :         flagsoff = MXOffsetToFlagsOffset(offset);
                                176                 :              0 :         bshift = MXOffsetToFlagsBitShift(offset);
                                177                 :                : 
                                178                 :              0 :         buf = SlruWriteSwitchPage(members_writer, pageno);
                                179                 :                : 
                                180                 :              0 :         memberptr = (TransactionId *) (buf + memberoff);
                                181                 :                : 
                                182                 :              0 :         *memberptr = members[i].xid;
                                183                 :                : 
                                184                 :              0 :         flagsptr = (uint32 *) (buf + flagsoff);
                                185                 :                : 
                                186                 :              0 :         flagsval = *flagsptr;
                                187                 :              0 :         flagsval &= ~(((1 << MXACT_MEMBER_BITS_PER_XACT) - 1) << bshift);
                                188                 :              0 :         flagsval |= (members[i].status << bshift);
                                189                 :              0 :         *flagsptr = flagsval;
                                190                 :                :     }
                                191                 :              0 : }
        

Generated by: LCOV version 2.4-beta