Replace XLOG_INCLUDE_XID flag with a more localized flag.
authorAmit Kapila
Tue, 2 Nov 2021 03:05:29 +0000 (08:35 +0530)
committerAmit Kapila
Tue, 2 Nov 2021 03:05:29 +0000 (08:35 +0530)
Commit 0bead9af484c introduced XLOG_INCLUDE_XID flag to indicate that the
WAL record contains subXID-to-topXID association. It uses that flag later
to mark in CurrentTransactionState that top-xid is logged so that we
should not try to log it again with the next WAL record in the current
subtransaction. However, we can use a localized variable to pass that
information.

In passing, change the related function and variable names to make them
consistent with what the code is actually doing.

Author: Dilip Kumar
Reviewed-by: Alvaro Herrera, Amit Kapila
Discussion: https://postgr.es/m/[email protected]

src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/access/transam/xloginsert.c
src/include/access/xact.h
src/include/access/xlog.h

index ca6f6d57d3663bf2d7c04a52e51a42da3c1b3909..8e35c432f5c6090ec3712e6c3b5bcf454e0798ae 100644 (file)
@@ -205,7 +205,7 @@ typedef struct TransactionStateData
    bool        didLogXid;      /* has xid been included in WAL record? */
    int         parallelModeLevel;  /* Enter/ExitParallelMode counter */
    bool        chain;          /* start a new block after this one */
-   bool        assigned;       /* assigned to top-level XID */
+   bool        topXidLogged;   /* for a subxact: is top-level XID logged? */
    struct TransactionStateData *parent;    /* back link to parent */
 } TransactionStateData;
 
@@ -238,7 +238,7 @@ typedef struct SerializedTransactionState
 static TransactionStateData TopTransactionStateData = {
    .state = TRANS_DEFAULT,
    .blockState = TBLOCK_DEFAULT,
-   .assigned = false,
+   .topXidLogged = false,
 };
 
 /*
@@ -529,6 +529,56 @@ MarkCurrentTransactionIdLoggedIfAny(void)
        CurrentTransactionState->didLogXid = true;
 }
 
+/*
+ * IsSubxactTopXidLogPending
+ *
+ * This is used to decide whether we need to WAL log the top-level XID for
+ * operation in a subtransaction.  We require that for logical decoding, see
+ * LogicalDecodingProcessRecord.
+ *
+ * This returns true if wal_level >= logical and we are inside a valid
+ * subtransaction, for which the assignment was not yet written to any WAL
+ * record.
+ */
+bool
+IsSubxactTopXidLogPending(void)
+{
+   /* check whether it is already logged */
+   if (CurrentTransactionState->topXidLogged)
+       return false;
+
+   /* wal_level has to be logical */
+   if (!XLogLogicalInfoActive())
+       return false;
+
+   /* we need to be in a transaction state */
+   if (!IsTransactionState())
+       return false;
+
+   /* it has to be a subtransaction */
+   if (!IsSubTransaction())
+       return false;
+
+   /* the subtransaction has to have a XID assigned */
+   if (!TransactionIdIsValid(GetCurrentTransactionIdIfAny()))
+       return false;
+
+   return true;
+}
+
+/*
+ * MarkSubxactTopXidLogged
+ *
+ * Remember that the top transaction id for the current subtransaction is WAL
+ * logged now.
+ */
+void
+MarkSubxactTopXidLogged(void)
+{
+   Assert(IsSubxactTopXidLogPending());
+
+   CurrentTransactionState->topXidLogged = true;
+}
 
 /*
  * GetStableLatestTransactionId
@@ -5174,7 +5224,7 @@ PushTransaction(void)
    GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
    s->prevXactReadOnly = XactReadOnly;
    s->parallelModeLevel = 0;
-   s->assigned = false;
+   s->topXidLogged = false;
 
    CurrentTransactionState = s;
 
@@ -6106,50 +6156,3 @@ xact_redo(XLogReaderState *record)
    else
        elog(PANIC, "xact_redo: unknown op code %u", info);
 }
-
-/*
- * IsSubTransactionAssignmentPending
- *
- * This is used to decide whether we need to WAL log the top-level XID for
- * operation in a subtransaction.  We require that for logical decoding, see
- * LogicalDecodingProcessRecord.
- *
- * This returns true if wal_level >= logical and we are inside a valid
- * subtransaction, for which the assignment was not yet written to any WAL
- * record.
- */
-bool
-IsSubTransactionAssignmentPending(void)
-{
-   /* wal_level has to be logical */
-   if (!XLogLogicalInfoActive())
-       return false;
-
-   /* we need to be in a transaction state */
-   if (!IsTransactionState())
-       return false;
-
-   /* it has to be a subtransaction */
-   if (!IsSubTransaction())
-       return false;
-
-   /* the subtransaction has to have a XID assigned */
-   if (!TransactionIdIsValid(GetCurrentTransactionIdIfAny()))
-       return false;
-
-   /* and it should not be already 'assigned' */
-   return !CurrentTransactionState->assigned;
-}
-
-/*
- * MarkSubTransactionAssigned
- *
- * Mark the subtransaction assignment as completed.
- */
-void
-MarkSubTransactionAssigned(void)
-{
-   Assert(IsSubTransactionAssignmentPending());
-
-   CurrentTransactionState->assigned = true;
-}
index f547efd2944172ea7c2258006dfa5436d0088e7d..6aca1fd75d99c2327d858bef09b69e8437049f62 100644 (file)
@@ -999,6 +999,9 @@ static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt);
  * 'flags' gives more in-depth control on the record being inserted. See
  * XLogSetRecordFlags() for details.
  *
+ * 'topxid_included' tells whether the top-transaction id is logged along with
+ * current subtransaction. See XLogRecordAssemble().
+ *
  * The first XLogRecData in the chain must be for the record header, and its
  * data must be MAXALIGNed.  XLogInsertRecord fills in the xl_prev and
  * xl_crc fields in the header, the rest of the header must already be filled
@@ -1014,7 +1017,8 @@ XLogRecPtr
 XLogInsertRecord(XLogRecData *rdata,
                 XLogRecPtr fpw_lsn,
                 uint8 flags,
-                int num_fpi)
+                int num_fpi,
+                bool topxid_included)
 {
    XLogCtlInsert *Insert = &XLogCtl->Insert;
    pg_crc32c   rdata_crc;
@@ -1169,6 +1173,13 @@ XLogInsertRecord(XLogRecData *rdata,
 
    END_CRIT_SECTION();
 
+   /*
+    * Mark top transaction id is logged (if needed) so that we should not try
+    * to log it again with the next WAL record in the current subtransaction.
+    */
+   if (topxid_included)
+       MarkSubxactTopXidLogged();
+
    /*
     * Update shared LogwrtRqst.Write, if we crossed page boundary.
     */
index b492c656d7a56164e426ae43cb75a8ed87f0303d..689384a411fd4afef6d7b1d7fcab8fae062ad15a 100644 (file)
@@ -123,7 +123,8 @@ static MemoryContext xloginsert_cxt;
 
 static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info,
                                       XLogRecPtr RedoRecPtr, bool doPageWrites,
-                                      XLogRecPtr *fpw_lsn, int *num_fpi);
+                                      XLogRecPtr *fpw_lsn, int *num_fpi,
+                                      bool *topxid_included);
 static bool XLogCompressBackupBlock(char *page, uint16 hole_offset,
                                    uint16 hole_length, char *dest, uint16 *dlen);
 
@@ -209,10 +210,6 @@ XLogResetInsertion(void)
 {
    int         i;
 
-   /* reset the subxact assignment flag (if needed) */
-   if (curinsert_flags & XLOG_INCLUDE_XID)
-       MarkSubTransactionAssigned();
-
    for (i = 0; i < max_registered_block_id; i++)
        registered_buffers[i].in_use = false;
 
@@ -409,8 +406,6 @@ XLogRegisterBufData(uint8 block_id, char *data, int len)
  * - XLOG_MARK_UNIMPORTANT, to signal that the record is not important for
  *  durability, which allows to avoid triggering WAL archiving and other
  *  background activity.
- * - XLOG_INCLUDE_XID, a message-passing hack between XLogRecordAssemble
- *  and XLogResetInsertion.
  */
 void
 XLogSetRecordFlags(uint8 flags)
@@ -465,6 +460,7 @@ XLogInsert(RmgrId rmid, uint8 info)
    {
        XLogRecPtr  RedoRecPtr;
        bool        doPageWrites;
+       bool        topxid_included = false;
        XLogRecPtr  fpw_lsn;
        XLogRecData *rdt;
        int         num_fpi = 0;
@@ -477,9 +473,10 @@ XLogInsert(RmgrId rmid, uint8 info)
        GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);
 
        rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
-                                &fpw_lsn, &num_fpi);
+                                &fpw_lsn, &num_fpi, &topxid_included);
 
-       EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi);
+       EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
+                                 topxid_included);
    } while (EndPos == InvalidXLogRecPtr);
 
    XLogResetInsertion();
@@ -498,11 +495,14 @@ XLogInsert(RmgrId rmid, uint8 info)
  * of all of them, *fpw_lsn is set to the lowest LSN among such pages. This
  * signals that the assembled record is only good for insertion on the
  * assumption that the RedoRecPtr and doPageWrites values were up-to-date.
+ *
+ * *topxid_included is set if the topmost transaction ID is logged with the
+ * current subtransaction.
  */
 static XLogRecData *
 XLogRecordAssemble(RmgrId rmid, uint8 info,
                   XLogRecPtr RedoRecPtr, bool doPageWrites,
-                  XLogRecPtr *fpw_lsn, int *num_fpi)
+                  XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
 {
    XLogRecData *rdt;
    uint32      total_len = 0;
@@ -788,12 +788,12 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
    }
 
    /* followed by toplevel XID, if not already included in previous record */
-   if (IsSubTransactionAssignmentPending())
+   if (IsSubxactTopXidLogPending())
    {
        TransactionId xid = GetTopTransactionIdIfAny();
 
-       /* update the flag (later used by XLogResetInsertion) */
-       XLogSetRecordFlags(XLOG_INCLUDE_XID);
+       /* Set the flag that the top xid is included in the WAL */
+       *topxid_included = true;
 
        *(scratch++) = (char) XLR_BLOCK_ID_TOPLEVEL_XID;
        memcpy(scratch, &xid, sizeof(TransactionId));
index 134f6862da0bc5876f5d11fb750dbfca98e61048..5546d334ad1ede85fd4774f64d0e47329bbf2a4d 100644 (file)
@@ -433,8 +433,8 @@ extern void UnregisterXactCallback(XactCallback callback, void *arg);
 extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
 extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
 
-extern bool IsSubTransactionAssignmentPending(void);
-extern void MarkSubTransactionAssigned(void);
+extern bool IsSubxactTopXidLogPending(void);
+extern void MarkSubxactTopXidLogged(void);
 
 extern int xactGetCommittedChildren(TransactionId **ptr);
 
index 5e2c94a05ff15d73917cc5cc322a7c87e250be97..c0a560204b4a745efe06d5eab2ac735830bcae41 100644 (file)
@@ -212,7 +212,6 @@ extern bool XLOG_DEBUG;
  */
 #define XLOG_INCLUDE_ORIGIN        0x01    /* include the replication origin */
 #define XLOG_MARK_UNIMPORTANT  0x02    /* record not important for durability */
-#define XLOG_INCLUDE_XID       0x04    /* WAL-internal message-passing hack */
 
 
 /* Checkpoint statistics */
@@ -258,7 +257,8 @@ struct XLogRecData;
 extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
                                   XLogRecPtr fpw_lsn,
                                   uint8 flags,
-                                  int num_fpi);
+                                  int num_fpi,
+                                  bool topxid_included);
 extern void XLogFlush(XLogRecPtr RecPtr);
 extern bool XLogBackgroundFlush(void);
 extern bool XLogNeedsFlush(XLogRecPtr RecPtr);