Thread

  1. [PATCH 3/6] Move conversion of a "historic" to MVCC snapshot to a separate function.

    Antonin Houska <ah@cybertec.at> — 2025-12-13T18:27:18Z

    The conversion is now handled by SnapBuildMVCCFromHistoric(). REPACK
    CONCURRENTLY will also need it.
    ---
     src/backend/replication/logical/snapbuild.c | 57 +++++++++++++++++----
     src/backend/utils/time/snapmgr.c            |  3 +-
     src/include/replication/snapbuild.h         |  1 +
     src/include/utils/snapmgr.h                 |  1 +
     4 files changed, 50 insertions(+), 12 deletions(-)
    
    diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
    index d6ab1e017eb..a3730804428 100644
    --- a/src/backend/replication/logical/snapbuild.c
    +++ b/src/backend/replication/logical/snapbuild.c
    @@ -440,10 +440,7 @@ Snapshot
     SnapBuildInitialSnapshot(SnapBuild *builder)
     {
     	Snapshot	snap;
    -	TransactionId xid;
     	TransactionId safeXid;
    -	TransactionId *newxip;
    -	int			newxcnt = 0;
     
     	Assert(XactIsoLevel == XACT_REPEATABLE_READ);
     	Assert(builder->building_full_snapshot);
    @@ -485,7 +482,33 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
     
     	MyProc->xmin = snap->xmin;
     
    -	/* allocate in transaction context */
    +	/* Convert the historic snapshot to MVCC snapshot. */
    +	return SnapBuildMVCCFromHistoric(snap, true);
    +}
    +
    +/*
    + * Turn a historic MVCC snapshot into an ordinary MVCC snapshot.
    + *
    + * Unlike a regular (non-historic) MVCC snapshot, the 'xip' array of this
    + * snapshot contains not only running main transactions, but also their
    + * subtransactions. On the other hand, 'subxip' will usually be empty. This
    + * difference does not affect the result of XidInMVCCSnapshot() because it
    + * searches both in 'xip' and 'subxip'.
    + *
    + * Pass true for 'in_place' if you don't care about modifying the source
    + * snapshot. If you need a new instance, and one that was allocated as a
    + * single chunk of memory, pass false.
    + */
    +Snapshot
    +SnapBuildMVCCFromHistoric(Snapshot snapshot, bool in_place)
    +{
    +	TransactionId xid;
    +	TransactionId *oldxip = snapshot->xip;
    +	uint32		oldxcnt = snapshot->xcnt;
    +	TransactionId *newxip;
    +	int			newxcnt = 0;
    +	Snapshot	result;
    +
     	newxip = palloc_array(TransactionId, GetMaxSnapshotXidCount());
     
     	/*
    @@ -494,7 +517,7 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
     	 * classical snapshot by marking all non-committed transactions as
     	 * in-progress. This can be expensive.
     	 */
    -	for (xid = snap->xmin; NormalTransactionIdPrecedes(xid, snap->xmax);)
    +	for (xid = snapshot->xmin; NormalTransactionIdPrecedes(xid, snapshot->xmax);)
     	{
     		void	   *test;
     
    @@ -502,7 +525,7 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
     		 * Check whether transaction committed using the decoding snapshot
     		 * meaning of ->xip.
     		 */
    -		test = bsearch(&xid, snap->xip, snap->xcnt,
    +		test = bsearch(&xid, snapshot->xip, snapshot->xcnt,
     					   sizeof(TransactionId), xidComparator);
     
     		if (test == NULL)
    @@ -519,11 +542,25 @@ SnapBuildInitialSnapshot(SnapBuild *builder)
     	}
     
     	/* adjust remaining snapshot fields as needed */
    -	snap->snapshot_type = SNAPSHOT_MVCC;
    -	snap->xcnt = newxcnt;
    -	snap->xip = newxip;
    +	snapshot->xcnt = newxcnt;
    +	snapshot->xip = newxip;
    +
    +	if (in_place)
    +		result = snapshot;
    +	else
    +	{
    +		result = CopySnapshot(snapshot);
    +
    +		/* Restore the original values so the source is intact. */
    +		snapshot->xip = oldxip;
    +		snapshot->xcnt = oldxcnt;
    +
    +		/* newxip has been copied */
    +		pfree(newxip);
    +	}
    +	result->snapshot_type = SNAPSHOT_MVCC;
     
    -	return snap;
    +	return result;
     }
     
     /*
    diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
    index 40a2e90e071..4cf32ffe833 100644
    --- a/src/backend/utils/time/snapmgr.c
    +++ b/src/backend/utils/time/snapmgr.c
    @@ -213,7 +213,6 @@ typedef struct ExportedSnapshot
     static List *exportedSnapshots = NIL;
     
     /* Prototypes for local functions */
    -static Snapshot CopySnapshot(Snapshot snapshot);
     static void UnregisterSnapshotNoOwner(Snapshot snapshot);
     static void FreeSnapshot(Snapshot snapshot);
     static void SnapshotResetXmin(void);
    @@ -604,7 +603,7 @@ SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid,
      * The copy is palloc'd in TopTransactionContext and has initial refcounts set
      * to 0.  The returned snapshot has the copied flag set.
      */
    -static Snapshot
    +Snapshot
     CopySnapshot(Snapshot snapshot)
     {
     	Snapshot	newsnap;
    diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h
    index 44031dcf6e3..6d4d2d1814c 100644
    --- a/src/include/replication/snapbuild.h
    +++ b/src/include/replication/snapbuild.h
    @@ -73,6 +73,7 @@ extern void FreeSnapshotBuilder(SnapBuild *builder);
     extern void SnapBuildSnapDecRefcount(Snapshot snap);
     
     extern Snapshot SnapBuildInitialSnapshot(SnapBuild *builder);
    +extern Snapshot SnapBuildMVCCFromHistoric(Snapshot snapshot, bool in_place);
     extern const char *SnapBuildExportSnapshot(SnapBuild *builder);
     extern void SnapBuildClearExportedSnapshot(void);
     extern void SnapBuildResetExportedSnapshotState(void);
    diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h
    index 604c1f90216..f65f83c85cd 100644
    --- a/src/include/utils/snapmgr.h
    +++ b/src/include/utils/snapmgr.h
    @@ -63,6 +63,7 @@ extern Snapshot GetTransactionSnapshot(void);
     extern Snapshot GetLatestSnapshot(void);
     extern void SnapshotSetCommandId(CommandId curcid);
     
    +extern Snapshot CopySnapshot(Snapshot snapshot);
     extern Snapshot GetCatalogSnapshot(Oid relid);
     extern Snapshot GetNonHistoricCatalogSnapshot(Oid relid);
     extern void InvalidateCatalogSnapshot(void);
    -- 
    2.47.3
    
    
    --=-=-=
    Content-Type: text/plain
    Content-Disposition: attachment;
     filename=v28-0004-Add-CONCURRENTLY-option-to-REPACK-command.patch