Move SnapBuild and SnapBuildOnDisk structs to snapshot_internal.h.
authorMasahiko Sawada <[email protected]>
Tue, 15 Oct 2024 00:19:33 +0000 (17:19 -0700)
committerMasahiko Sawada <[email protected]>
Tue, 15 Oct 2024 00:19:33 +0000 (17:19 -0700)
This commit moves the definitions of the SnapBuild and SnapBuildOnDisk
structs, related to logical snapshots, to the snapshot_internal.h
file. This change allows external tools, such as
pg_logicalinspect (with an upcoming patch), to access and utilize the
contents of logical snapshots.

Author: Bertrand Drouvot
Reviewed-by: Amit Kapila, Shveta Malik, Peter Smith
Discussion: https://postgr.es/m/ZscuZ92uGh3wm4tW%40ip-10-97-1-34.eu-west-3.compute.internal

src/backend/replication/logical/snapbuild.c
src/include/replication/snapbuild.h
src/include/replication/snapbuild_internal.h [new file with mode: 0644]

index 0450f94ba8a9384b0868e01802c434c9c9eda446..b9df8c0a0245b7ce00fbc5e616957fdce7b391df 100644 (file)
 #include "replication/logical.h"
 #include "replication/reorderbuffer.h"
 #include "replication/snapbuild.h"
+#include "replication/snapbuild_internal.h"
 #include "storage/fd.h"
 #include "storage/lmgr.h"
 #include "storage/proc.h"
 #include "utils/memutils.h"
 #include "utils/snapmgr.h"
 #include "utils/snapshot.h"
-
-/*
- * This struct contains the current state of the snapshot building
- * machinery. Besides a forward declaration in the header, it is not exposed
- * to the public, so we can easily change its contents.
- */
-struct SnapBuild
-{
-       /* how far are we along building our first full snapshot */
-       SnapBuildState state;
-
-       /* private memory context used to allocate memory for this module. */
-       MemoryContext context;
-
-       /* all transactions < than this have committed/aborted */
-       TransactionId xmin;
-
-       /* all transactions >= than this are uncommitted */
-       TransactionId xmax;
-
-       /*
-        * Don't replay commits from an LSN < this LSN. This can be set externally
-        * but it will also be advanced (never retreat) from within snapbuild.c.
-        */
-       XLogRecPtr      start_decoding_at;
-
-       /*
-        * LSN at which two-phase decoding was enabled or LSN at which we found a
-        * consistent point at the time of slot creation.
-        *
-        * The prepared transactions, that were skipped because previously
-        * two-phase was not enabled or are not covered by initial snapshot, need
-        * to be sent later along with commit prepared and they must be before
-        * this point.
-        */
-       XLogRecPtr      two_phase_at;
-
-       /*
-        * Don't start decoding WAL until the "xl_running_xacts" information
-        * indicates there are no running xids with an xid smaller than this.
-        */
-       TransactionId initial_xmin_horizon;
-
-       /* Indicates if we are building full snapshot or just catalog one. */
-       bool            building_full_snapshot;
-
-       /*
-        * Indicates if we are using the snapshot builder for the creation of a
-        * logical replication slot. If it's true, the start point for decoding
-        * changes is not determined yet. So we skip snapshot restores to properly
-        * find the start point. See SnapBuildFindSnapshot() for details.
-        */
-       bool            in_slot_creation;
-
-       /*
-        * Snapshot that's valid to see the catalog state seen at this moment.
-        */
-       Snapshot        snapshot;
-
-       /*
-        * LSN of the last location we are sure a snapshot has been serialized to.
-        */
-       XLogRecPtr      last_serialized_snapshot;
-
-       /*
-        * The reorderbuffer we need to update with usable snapshots et al.
-        */
-       ReorderBuffer *reorder;
-
-       /*
-        * TransactionId at which the next phase of initial snapshot building will
-        * happen. InvalidTransactionId if not known (i.e. SNAPBUILD_START), or
-        * when no next phase necessary (SNAPBUILD_CONSISTENT).
-        */
-       TransactionId next_phase_at;
-
-       /*
-        * Array of transactions which could have catalog changes that committed
-        * between xmin and xmax.
-        */
-       struct
-       {
-               /* number of committed transactions */
-               size_t          xcnt;
-
-               /* available space for committed transactions */
-               size_t          xcnt_space;
-
-               /*
-                * Until we reach a CONSISTENT state, we record commits of all
-                * transactions, not just the catalog changing ones. Record when that
-                * changes so we know we cannot export a snapshot safely anymore.
-                */
-               bool            includes_all_transactions;
-
-               /*
-                * Array of committed transactions that have modified the catalog.
-                *
-                * As this array is frequently modified we do *not* keep it in
-                * xidComparator order. Instead we sort the array when building &
-                * distributing a snapshot.
-                *
-                * TODO: It's unclear whether that reasoning has much merit. Every
-                * time we add something here after becoming consistent will also
-                * require distributing a snapshot. Storing them sorted would
-                * potentially also make it easier to purge (but more complicated wrt
-                * wraparound?). Should be improved if sorting while building the
-                * snapshot shows up in profiles.
-                */
-               TransactionId *xip;
-       }                       committed;
-
-       /*
-        * Array of transactions and subtransactions that had modified catalogs
-        * and were running when the snapshot was serialized.
-        *
-        * We normally rely on some WAL record types such as HEAP2_NEW_CID to know
-        * if the transaction has changed the catalog. But it could happen that
-        * the logical decoding decodes only the commit record of the transaction
-        * after restoring the previously serialized snapshot in which case we
-        * will miss adding the xid to the snapshot and end up looking at the
-        * catalogs with the wrong snapshot.
-        *
-        * Now to avoid the above problem, we serialize the transactions that had
-        * modified the catalogs and are still running at the time of snapshot
-        * serialization. We fill this array while restoring the snapshot and then
-        * refer it while decoding commit to ensure if the xact has modified the
-        * catalog. We discard this array when all the xids in the list become old
-        * enough to matter. See SnapBuildPurgeOlderTxn for details.
-        */
-       struct
-       {
-               /* number of transactions */
-               size_t          xcnt;
-
-               /* This array must be sorted in xidComparator order */
-               TransactionId *xip;
-       }                       catchange;
-};
-
 /*
  * Starting a transaction -- which we need to do while exporting a snapshot --
  * removes knowledge about the previously used resowner, so we save it here.
@@ -1557,40 +1418,6 @@ SnapBuildWaitSnapshot(xl_running_xacts *running, TransactionId cutoff)
        }
 }
 
-/* -----------------------------------
- * Snapshot serialization support
- * -----------------------------------
- */
-
-/*
- * We store current state of struct SnapBuild on disk in the following manner:
- *
- * struct SnapBuildOnDisk;
- * TransactionId * committed.xcnt; (*not xcnt_space*)
- * TransactionId * catchange.xcnt;
- *
- */
-typedef struct SnapBuildOnDisk
-{
-       /* first part of this struct needs to be version independent */
-
-       /* data not covered by checksum */
-       uint32          magic;
-       pg_crc32c       checksum;
-
-       /* data covered by checksum */
-
-       /* version, in case we want to support pg_upgrade */
-       uint32          version;
-       /* how large is the on disk data, excluding the constant sized part */
-       uint32          length;
-
-       /* version dependent part */
-       SnapBuild       builder;
-
-       /* variable amount of TransactionIds follows */
-} SnapBuildOnDisk;
-
 #define SnapBuildOnDiskConstantSize \
        offsetof(SnapBuildOnDisk, builder)
 #define SnapBuildOnDiskNotChecksummedSize \
index caa5113ff81a8da3827c7e1c272079d533763969..dbb4bc2f4b2e4ef580c66d4c3fdd7e4d4a1eca85 100644 (file)
@@ -46,7 +46,7 @@ typedef enum
        SNAPBUILD_CONSISTENT = 2,
 } SnapBuildState;
 
-/* forward declare so we don't have to expose the struct to the public */
+/* forward declare so we don't have to include snapbuild_internal.h */
 struct SnapBuild;
 typedef struct SnapBuild SnapBuild;
 
diff --git a/src/include/replication/snapbuild_internal.h b/src/include/replication/snapbuild_internal.h
new file mode 100644 (file)
index 0000000..5df2ae4
--- /dev/null
@@ -0,0 +1,196 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapbuild_internal.h
+ *    This file contains declarations for logical decoding utility
+ *    functions for internal use.
+ *
+ * Copyright (c) 2024, PostgreSQL Global Development Group
+ *
+ * src/include/replication/snapbuild_internal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef SNAPBUILD_INTERNAL_H
+#define SNAPBUILD_INTERNAL_H
+
+#include "port/pg_crc32c.h"
+#include "replication/reorderbuffer.h"
+#include "replication/snapbuild.h"
+
+/*
+ * This struct contains the current state of the snapshot building
+ * machinery. It is exposed to the public, so pay attention when changing its
+ * contents.
+ */
+struct SnapBuild
+{
+       /* how far are we along building our first full snapshot */
+       SnapBuildState state;
+
+       /* private memory context used to allocate memory for this module. */
+       MemoryContext context;
+
+       /* all transactions < than this have committed/aborted */
+       TransactionId xmin;
+
+       /* all transactions >= than this are uncommitted */
+       TransactionId xmax;
+
+       /*
+        * Don't replay commits from an LSN < this LSN. This can be set externally
+        * but it will also be advanced (never retreat) from within snapbuild.c.
+        */
+       XLogRecPtr      start_decoding_at;
+
+       /*
+        * LSN at which two-phase decoding was enabled or LSN at which we found a
+        * consistent point at the time of slot creation.
+        *
+        * The prepared transactions, that were skipped because previously
+        * two-phase was not enabled or are not covered by initial snapshot, need
+        * to be sent later along with commit prepared and they must be before
+        * this point.
+        */
+       XLogRecPtr      two_phase_at;
+
+       /*
+        * Don't start decoding WAL until the "xl_running_xacts" information
+        * indicates there are no running xids with an xid smaller than this.
+        */
+       TransactionId initial_xmin_horizon;
+
+       /* Indicates if we are building full snapshot or just catalog one. */
+       bool            building_full_snapshot;
+
+       /*
+        * Indicates if we are using the snapshot builder for the creation of a
+        * logical replication slot. If it's true, the start point for decoding
+        * changes is not determined yet. So we skip snapshot restores to properly
+        * find the start point. See SnapBuildFindSnapshot() for details.
+        */
+       bool            in_slot_creation;
+
+       /*
+        * Snapshot that's valid to see the catalog state seen at this moment.
+        */
+       Snapshot        snapshot;
+
+       /*
+        * LSN of the last location we are sure a snapshot has been serialized to.
+        */
+       XLogRecPtr      last_serialized_snapshot;
+
+       /*
+        * The reorderbuffer we need to update with usable snapshots et al.
+        */
+       ReorderBuffer *reorder;
+
+       /*
+        * TransactionId at which the next phase of initial snapshot building will
+        * happen. InvalidTransactionId if not known (i.e. SNAPBUILD_START), or
+        * when no next phase necessary (SNAPBUILD_CONSISTENT).
+        */
+       TransactionId next_phase_at;
+
+       /*
+        * Array of transactions which could have catalog changes that committed
+        * between xmin and xmax.
+        */
+       struct
+       {
+               /* number of committed transactions */
+               size_t          xcnt;
+
+               /* available space for committed transactions */
+               size_t          xcnt_space;
+
+               /*
+                * Until we reach a CONSISTENT state, we record commits of all
+                * transactions, not just the catalog changing ones. Record when that
+                * changes so we know we cannot export a snapshot safely anymore.
+                */
+               bool            includes_all_transactions;
+
+               /*
+                * Array of committed transactions that have modified the catalog.
+                *
+                * As this array is frequently modified we do *not* keep it in
+                * xidComparator order. Instead we sort the array when building &
+                * distributing a snapshot.
+                *
+                * TODO: It's unclear whether that reasoning has much merit. Every
+                * time we add something here after becoming consistent will also
+                * require distributing a snapshot. Storing them sorted would
+                * potentially also make it easier to purge (but more complicated wrt
+                * wraparound?). Should be improved if sorting while building the
+                * snapshot shows up in profiles.
+                */
+               TransactionId *xip;
+       }                       committed;
+
+       /*
+        * Array of transactions and subtransactions that had modified catalogs
+        * and were running when the snapshot was serialized.
+        *
+        * We normally rely on some WAL record types such as HEAP2_NEW_CID to know
+        * if the transaction has changed the catalog. But it could happen that
+        * the logical decoding decodes only the commit record of the transaction
+        * after restoring the previously serialized snapshot in which case we
+        * will miss adding the xid to the snapshot and end up looking at the
+        * catalogs with the wrong snapshot.
+        *
+        * Now to avoid the above problem, we serialize the transactions that had
+        * modified the catalogs and are still running at the time of snapshot
+        * serialization. We fill this array while restoring the snapshot and then
+        * refer it while decoding commit to ensure if the xact has modified the
+        * catalog. We discard this array when all the xids in the list become old
+        * enough to matter. See SnapBuildPurgeOlderTxn for details.
+        */
+       struct
+       {
+               /* number of transactions */
+               size_t          xcnt;
+
+               /* This array must be sorted in xidComparator order */
+               TransactionId *xip;
+       }                       catchange;
+};
+
+/* -----------------------------------
+ * Snapshot serialization support
+ * -----------------------------------
+ */
+
+/*
+ * We store current state of struct SnapBuild on disk in the following manner:
+ *
+ * struct SnapBuildOnDisk;
+ * TransactionId * committed.xcnt; (*not xcnt_space*)
+ * TransactionId * catchange.xcnt;
+ *
+ * Check if the SnapBuildOnDiskConstantSize and SnapBuildOnDiskNotChecksummedSize
+ * macros need to be updated when modifying the SnapBuildOnDisk struct.
+ */
+typedef struct SnapBuildOnDisk
+{
+       /* first part of this struct needs to be version independent */
+
+       /* data not covered by checksum */
+       uint32          magic;
+       pg_crc32c       checksum;
+
+       /* data covered by checksum */
+
+       /* version, in case we want to support pg_upgrade */
+       uint32          version;
+       /* how large is the on disk data, excluding the constant sized part */
+       uint32          length;
+
+       /* version dependent part */
+       SnapBuild       builder;
+
+       /* variable amount of TransactionIds follows */
+} SnapBuildOnDisk;
+
+#endif                                                 /* SNAPBUILD_INTERNAL_H */