summaryrefslogtreecommitdiffstats
path: root/src/backend/access/rmgrdesc/nbtdesc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/rmgrdesc/nbtdesc.c')
-rw-r--r--src/backend/access/rmgrdesc/nbtdesc.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/backend/access/rmgrdesc/nbtdesc.c b/src/backend/access/rmgrdesc/nbtdesc.c
new file mode 100644
index 0000000..e4fbaa4
--- /dev/null
+++ b/src/backend/access/rmgrdesc/nbtdesc.c
@@ -0,0 +1,252 @@
+/*-------------------------------------------------------------------------
+ *
+ * nbtdesc.c
+ * rmgr descriptor routines for access/nbtree/nbtxlog.c
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/access/rmgrdesc/nbtdesc.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/nbtxlog.h"
+#include "access/rmgrdesc_utils.h"
+
+static void delvacuum_desc(StringInfo buf, char *block_data,
+ uint16 ndeleted, uint16 nupdated);
+
+void
+btree_desc(StringInfo buf, XLogReaderState *record)
+{
+ char *rec = XLogRecGetData(record);
+ uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
+
+ switch (info)
+ {
+ case XLOG_BTREE_INSERT_LEAF:
+ case XLOG_BTREE_INSERT_UPPER:
+ case XLOG_BTREE_INSERT_META:
+ case XLOG_BTREE_INSERT_POST:
+ {
+ xl_btree_insert *xlrec = (xl_btree_insert *) rec;
+
+ appendStringInfo(buf, "off: %u", xlrec->offnum);
+ break;
+ }
+ case XLOG_BTREE_SPLIT_L:
+ case XLOG_BTREE_SPLIT_R:
+ {
+ xl_btree_split *xlrec = (xl_btree_split *) rec;
+
+ appendStringInfo(buf, "level: %u, firstrightoff: %d, newitemoff: %d, postingoff: %d",
+ xlrec->level, xlrec->firstrightoff,
+ xlrec->newitemoff, xlrec->postingoff);
+ break;
+ }
+ case XLOG_BTREE_DEDUP:
+ {
+ xl_btree_dedup *xlrec = (xl_btree_dedup *) rec;
+
+ appendStringInfo(buf, "nintervals: %u", xlrec->nintervals);
+ break;
+ }
+ case XLOG_BTREE_VACUUM:
+ {
+ xl_btree_vacuum *xlrec = (xl_btree_vacuum *) rec;
+
+ appendStringInfo(buf, "ndeleted: %u, nupdated: %u",
+ xlrec->ndeleted, xlrec->nupdated);
+
+ if (XLogRecHasBlockData(record, 0))
+ delvacuum_desc(buf, XLogRecGetBlockData(record, 0, NULL),
+ xlrec->ndeleted, xlrec->nupdated);
+ break;
+ }
+ case XLOG_BTREE_DELETE:
+ {
+ xl_btree_delete *xlrec = (xl_btree_delete *) rec;
+
+ appendStringInfo(buf, "snapshotConflictHorizon: %u, ndeleted: %u, nupdated: %u",
+ xlrec->snapshotConflictHorizon,
+ xlrec->ndeleted, xlrec->nupdated);
+
+ if (XLogRecHasBlockData(record, 0))
+ delvacuum_desc(buf, XLogRecGetBlockData(record, 0, NULL),
+ xlrec->ndeleted, xlrec->nupdated);
+ break;
+ }
+ case XLOG_BTREE_MARK_PAGE_HALFDEAD:
+ {
+ xl_btree_mark_page_halfdead *xlrec = (xl_btree_mark_page_halfdead *) rec;
+
+ appendStringInfo(buf, "topparent: %u, leaf: %u, left: %u, right: %u",
+ xlrec->topparent, xlrec->leafblk, xlrec->leftblk, xlrec->rightblk);
+ break;
+ }
+ case XLOG_BTREE_UNLINK_PAGE_META:
+ case XLOG_BTREE_UNLINK_PAGE:
+ {
+ xl_btree_unlink_page *xlrec = (xl_btree_unlink_page *) rec;
+
+ appendStringInfo(buf, "left: %u, right: %u, level: %u, safexid: %u:%u, ",
+ xlrec->leftsib, xlrec->rightsib, xlrec->level,
+ EpochFromFullTransactionId(xlrec->safexid),
+ XidFromFullTransactionId(xlrec->safexid));
+ appendStringInfo(buf, "leafleft: %u, leafright: %u, leaftopparent: %u",
+ xlrec->leafleftsib, xlrec->leafrightsib,
+ xlrec->leaftopparent);
+ break;
+ }
+ case XLOG_BTREE_NEWROOT:
+ {
+ xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
+
+ appendStringInfo(buf, "level: %u", xlrec->level);
+ break;
+ }
+ case XLOG_BTREE_REUSE_PAGE:
+ {
+ xl_btree_reuse_page *xlrec = (xl_btree_reuse_page *) rec;
+
+ appendStringInfo(buf, "rel: %u/%u/%u, snapshotConflictHorizon: %u:%u",
+ xlrec->locator.spcOid, xlrec->locator.dbOid,
+ xlrec->locator.relNumber,
+ EpochFromFullTransactionId(xlrec->snapshotConflictHorizon),
+ XidFromFullTransactionId(xlrec->snapshotConflictHorizon));
+ break;
+ }
+ case XLOG_BTREE_META_CLEANUP:
+ {
+ xl_btree_metadata *xlrec;
+
+ xlrec = (xl_btree_metadata *) XLogRecGetBlockData(record, 0,
+ NULL);
+ appendStringInfo(buf, "last_cleanup_num_delpages: %u",
+ xlrec->last_cleanup_num_delpages);
+ break;
+ }
+ }
+}
+
+const char *
+btree_identify(uint8 info)
+{
+ const char *id = NULL;
+
+ switch (info & ~XLR_INFO_MASK)
+ {
+ case XLOG_BTREE_INSERT_LEAF:
+ id = "INSERT_LEAF";
+ break;
+ case XLOG_BTREE_INSERT_UPPER:
+ id = "INSERT_UPPER";
+ break;
+ case XLOG_BTREE_INSERT_META:
+ id = "INSERT_META";
+ break;
+ case XLOG_BTREE_SPLIT_L:
+ id = "SPLIT_L";
+ break;
+ case XLOG_BTREE_SPLIT_R:
+ id = "SPLIT_R";
+ break;
+ case XLOG_BTREE_INSERT_POST:
+ id = "INSERT_POST";
+ break;
+ case XLOG_BTREE_DEDUP:
+ id = "DEDUP";
+ break;
+ case XLOG_BTREE_VACUUM:
+ id = "VACUUM";
+ break;
+ case XLOG_BTREE_DELETE:
+ id = "DELETE";
+ break;
+ case XLOG_BTREE_MARK_PAGE_HALFDEAD:
+ id = "MARK_PAGE_HALFDEAD";
+ break;
+ case XLOG_BTREE_UNLINK_PAGE:
+ id = "UNLINK_PAGE";
+ break;
+ case XLOG_BTREE_UNLINK_PAGE_META:
+ id = "UNLINK_PAGE_META";
+ break;
+ case XLOG_BTREE_NEWROOT:
+ id = "NEWROOT";
+ break;
+ case XLOG_BTREE_REUSE_PAGE:
+ id = "REUSE_PAGE";
+ break;
+ case XLOG_BTREE_META_CLEANUP:
+ id = "META_CLEANUP";
+ break;
+ }
+
+ return id;
+}
+
+static void
+delvacuum_desc(StringInfo buf, char *block_data,
+ uint16 ndeleted, uint16 nupdated)
+{
+ OffsetNumber *deletedoffsets;
+ OffsetNumber *updatedoffsets;
+ xl_btree_update *updates;
+
+ /* Output deleted page offset number array */
+ appendStringInfoString(buf, ", deleted:");
+ deletedoffsets = (OffsetNumber *) block_data;
+ array_desc(buf, deletedoffsets, sizeof(OffsetNumber), ndeleted,
+ &offset_elem_desc, NULL);
+
+ /*
+ * Output updates as an array of "update objects", where each element
+ * contains a page offset number from updated array. (This is not the
+ * most literal representation of the underlying physical data structure
+ * that we could use. Readability seems more important here.)
+ */
+ appendStringInfoString(buf, ", updated: [");
+ updatedoffsets = (OffsetNumber *) (block_data + ndeleted *
+ sizeof(OffsetNumber));
+ updates = (xl_btree_update *) ((char *) updatedoffsets +
+ nupdated *
+ sizeof(OffsetNumber));
+ for (int i = 0; i < nupdated; i++)
+ {
+ OffsetNumber off = updatedoffsets[i];
+
+ Assert(OffsetNumberIsValid(off));
+ Assert(updates->ndeletedtids > 0);
+
+ /*
+ * "ptid" is the symbol name used when building each xl_btree_update's
+ * array of offsets into a posting list tuple's ItemPointerData array.
+ * xl_btree_update describes a subset of the existing TIDs to delete.
+ */
+ appendStringInfo(buf, "{ off: %u, nptids: %u, ptids: [",
+ off, updates->ndeletedtids);
+ for (int p = 0; p < updates->ndeletedtids; p++)
+ {
+ uint16 *ptid;
+
+ ptid = (uint16 *) ((char *) updates + SizeOfBtreeUpdate) + p;
+ appendStringInfo(buf, "%u", *ptid);
+
+ if (p < updates->ndeletedtids - 1)
+ appendStringInfoString(buf, ", ");
+ }
+ appendStringInfoString(buf, "] }");
+ if (i < nupdated - 1)
+ appendStringInfoString(buf, ", ");
+
+ updates = (xl_btree_update *)
+ ((char *) updates + SizeOfBtreeUpdate +
+ updates->ndeletedtids * sizeof(uint16));
+ }
+ appendStringInfoString(buf, "]");
+}