1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-22 17:42:17 +03:00
Files
postgres/src/backend/access/rmgrdesc/nbtdesc.c
Bruce Momjian 50e6eb731d Update copyright for 2025
Backpatch-through: 13
2025-01-01 11:21:55 -05:00

255 lines
7.0 KiB
C

/*-------------------------------------------------------------------------
*
* nbtdesc.c
* rmgr descriptor routines for access/nbtree/nbtxlog.c
*
* Portions Copyright (c) 1996-2025, 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, isCatalogRel: %c",
xlrec->snapshotConflictHorizon,
xlrec->ndeleted, xlrec->nupdated,
xlrec->isCatalogRel ? 'T' : 'F');
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, isCatalogRel: %c",
xlrec->locator.spcOid, xlrec->locator.dbOid,
xlrec->locator.relNumber,
EpochFromFullTransactionId(xlrec->snapshotConflictHorizon),
XidFromFullTransactionId(xlrec->snapshotConflictHorizon),
xlrec->isCatalogRel ? 'T' : 'F');
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));
}
appendStringInfoChar(buf, ']');
}