1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-13 16:22:44 +03:00

Add rmgr callback to name xlog record types for display purposes.

This is primarily useful for the upcoming pg_xlogdump --stats feature,
but also allows to remove some duplicated code in the rmgr_desc
routines.

Due to the separation and harmonization, the output of dipsplayed
records changes somewhat. But since this isn't enduser oriented
content that's ok.

It's potentially desirable to further change pg_xlogdump's display of
records. It previously wasn't possible to show the record type
separately from the description forcing it to be in the last
column. But that's better done in a separate commit.

Author: Abhijit Menon-Sen, slightly editorialized by me
Reviewed-By: Álvaro Herrera, Andres Freund, and Heikki Linnakangas
Discussion: 20140604104716.GA3989@toroid.org
This commit is contained in:
Andres Freund
2014-09-19 15:17:12 +02:00
parent 7e3f728353
commit 728f152e07
40 changed files with 593 additions and 239 deletions

View File

@@ -23,20 +23,29 @@ clog_desc(StringInfo buf, XLogRecord *record)
char *rec = XLogRecGetData(record);
uint8 info = record->xl_info & ~XLR_INFO_MASK;
if (info == CLOG_ZEROPAGE)
if (info == CLOG_ZEROPAGE || info == CLOG_TRUNCATE)
{
int pageno;
memcpy(&pageno, rec, sizeof(int));
appendStringInfo(buf, "zeropage: %d", pageno);
appendStringInfo(buf, "%d", pageno);
}
else if (info == CLOG_TRUNCATE)
{
int pageno;
memcpy(&pageno, rec, sizeof(int));
appendStringInfo(buf, "truncate before: %d", pageno);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
clog_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case CLOG_ZEROPAGE:
id = "ZEROPAGE";
break;
case CLOG_TRUNCATE:
id = "TRUNCATE";
break;
}
return id;
}

View File

@@ -28,7 +28,7 @@ dbase_desc(StringInfo buf, XLogRecord *record)
{
xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) rec;
appendStringInfo(buf, "create db: copy dir %u/%u to %u/%u",
appendStringInfo(buf, "copy dir %u/%u to %u/%u",
xlrec->src_db_id, xlrec->src_tablespace_id,
xlrec->db_id, xlrec->tablespace_id);
}
@@ -36,9 +36,25 @@ dbase_desc(StringInfo buf, XLogRecord *record)
{
xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec;
appendStringInfo(buf, "drop db: dir %u/%u",
appendStringInfo(buf, "dir %u/%u",
xlrec->db_id, xlrec->tablespace_id);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
dbase_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_DBASE_CREATE:
id = "CREATE";
break;
case XLOG_DBASE_DROP:
id = "DROP";
break;
}
return id;
}

View File

@@ -85,11 +85,9 @@ gin_desc(StringInfo buf, XLogRecord *record)
switch (info)
{
case XLOG_GIN_CREATE_INDEX:
appendStringInfoString(buf, "Create index, ");
desc_node(buf, *(RelFileNode *) rec, GIN_ROOT_BLKNO);
break;
case XLOG_GIN_CREATE_PTREE:
appendStringInfoString(buf, "Create posting tree, ");
desc_node(buf, ((ginxlogCreatePostingTree *) rec)->node, ((ginxlogCreatePostingTree *) rec)->blkno);
break;
case XLOG_GIN_INSERT:
@@ -97,7 +95,6 @@ gin_desc(StringInfo buf, XLogRecord *record)
ginxlogInsert *xlrec = (ginxlogInsert *) rec;
char *payload = rec + sizeof(ginxlogInsert);
appendStringInfoString(buf, "Insert item, ");
desc_node(buf, xlrec->node, xlrec->blkno);
appendStringInfo(buf, " isdata: %c isleaf: %c",
(xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
@@ -142,7 +139,6 @@ gin_desc(StringInfo buf, XLogRecord *record)
{
ginxlogSplit *xlrec = (ginxlogSplit *) rec;
appendStringInfoString(buf, "Page split, ");
desc_node(buf, ((ginxlogSplit *) rec)->node, ((ginxlogSplit *) rec)->lblkno);
appendStringInfo(buf, " isrootsplit: %c", (((ginxlogSplit *) rec)->flags & GIN_SPLIT_ROOT) ? 'T' : 'F');
appendStringInfo(buf, " isdata: %c isleaf: %c",
@@ -151,14 +147,12 @@ gin_desc(StringInfo buf, XLogRecord *record)
}
break;
case XLOG_GIN_VACUUM_PAGE:
appendStringInfoString(buf, "Vacuum page, ");
desc_node(buf, ((ginxlogVacuumPage *) rec)->node, ((ginxlogVacuumPage *) rec)->blkno);
break;
case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
{
ginxlogVacuumDataLeafPage *xlrec = (ginxlogVacuumDataLeafPage *) rec;
appendStringInfoString(buf, "Vacuum data leaf page, ");
desc_node(buf, xlrec->node, xlrec->blkno);
if (record->xl_info & XLR_BKP_BLOCK(0))
appendStringInfo(buf, " (full page image)");
@@ -167,23 +161,59 @@ gin_desc(StringInfo buf, XLogRecord *record)
}
break;
case XLOG_GIN_DELETE_PAGE:
appendStringInfoString(buf, "Delete page, ");
desc_node(buf, ((ginxlogDeletePage *) rec)->node, ((ginxlogDeletePage *) rec)->blkno);
break;
case XLOG_GIN_UPDATE_META_PAGE:
appendStringInfoString(buf, "Update metapage, ");
desc_node(buf, ((ginxlogUpdateMeta *) rec)->node, GIN_METAPAGE_BLKNO);
break;
case XLOG_GIN_INSERT_LISTPAGE:
appendStringInfoString(buf, "Insert new list page, ");
desc_node(buf, ((ginxlogInsertListPage *) rec)->node, ((ginxlogInsertListPage *) rec)->blkno);
break;
case XLOG_GIN_DELETE_LISTPAGE:
appendStringInfo(buf, "Delete list pages (%d), ", ((ginxlogDeleteListPages *) rec)->ndeleted);
appendStringInfo(buf, "%d pages, ", ((ginxlogDeleteListPages *) rec)->ndeleted);
desc_node(buf, ((ginxlogDeleteListPages *) rec)->node, GIN_METAPAGE_BLKNO);
break;
default:
appendStringInfo(buf, "unknown gin op code %u", info);
break;
}
}
const char *
gin_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_GIN_CREATE_INDEX:
id = "CREATE_INDEX";
break;
case XLOG_GIN_CREATE_PTREE:
id = "CREATE_PTREE";
break;
case XLOG_GIN_INSERT:
id = "INSERT";
break;
case XLOG_GIN_SPLIT:
id = "SPLIT";
break;
case XLOG_GIN_VACUUM_PAGE:
id = "VACUUM_PAGE";
break;
case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
id = "VACUUM_DATA_LEAF_PAGE";
break;
case XLOG_GIN_DELETE_PAGE:
id = "DELETE_PAGE";
break;
case XLOG_GIN_UPDATE_META_PAGE:
id = "UPDATE_META_PAGE";
break;
case XLOG_GIN_INSERT_LISTPAGE:
id = "INSERT_LISTPAGE";
break;
case XLOG_GIN_DELETE_LISTPAGE:
id = "DELETE_LISTPAGE";
break;
}
return id;
}

View File

@@ -50,20 +50,37 @@ gist_desc(StringInfo buf, XLogRecord *record)
switch (info)
{
case XLOG_GIST_PAGE_UPDATE:
appendStringInfoString(buf, "page_update: ");
out_gistxlogPageUpdate(buf, (gistxlogPageUpdate *) rec);
break;
case XLOG_GIST_PAGE_SPLIT:
out_gistxlogPageSplit(buf, (gistxlogPageSplit *) rec);
break;
case XLOG_GIST_CREATE_INDEX:
appendStringInfo(buf, "create_index: rel %u/%u/%u",
appendStringInfo(buf, "rel %u/%u/%u",
((RelFileNode *) rec)->spcNode,
((RelFileNode *) rec)->dbNode,
((RelFileNode *) rec)->relNode);
break;
default:
appendStringInfo(buf, "unknown gist op code %u", info);
break;
}
}
const char *
gist_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_GIST_PAGE_UPDATE:
id = "PAGE_UPDATE";
break;
case XLOG_GIST_PAGE_SPLIT:
id = "PAGE_SPLIT";
break;
case XLOG_GIST_CREATE_INDEX:
id = "CREATE_INDEX";
break;
}
return id;
}

View File

@@ -20,3 +20,9 @@ void
hash_desc(StringInfo buf, XLogRecord *record)
{
}
const char *
hash_identify(uint8 info)
{
return NULL;
}

View File

@@ -51,17 +51,12 @@ heap_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_insert *xlrec = (xl_heap_insert *) rec;
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
appendStringInfoString(buf, "insert(init): ");
else
appendStringInfoString(buf, "insert: ");
out_target(buf, &(xlrec->target));
}
else if (info == XLOG_HEAP_DELETE)
{
xl_heap_delete *xlrec = (xl_heap_delete *) rec;
appendStringInfoString(buf, "delete: ");
out_target(buf, &(xlrec->target));
appendStringInfoChar(buf, ' ');
out_infobits(buf, xlrec->infobits_set);
@@ -70,10 +65,6 @@ heap_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_update *xlrec = (xl_heap_update *) rec;
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
appendStringInfoString(buf, "update(init): ");
else
appendStringInfoString(buf, "update: ");
out_target(buf, &(xlrec->target));
appendStringInfo(buf, " xmax %u ", xlrec->old_xmax);
out_infobits(buf, xlrec->old_infobits_set);
@@ -86,10 +77,6 @@ heap_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_update *xlrec = (xl_heap_update *) rec;
if (record->xl_info & XLOG_HEAP_INIT_PAGE) /* can this case happen? */
appendStringInfoString(buf, "hot_update(init): ");
else
appendStringInfoString(buf, "hot_update: ");
out_target(buf, &(xlrec->target));
appendStringInfo(buf, " xmax %u ", xlrec->old_xmax);
out_infobits(buf, xlrec->old_infobits_set);
@@ -102,7 +89,7 @@ heap_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_lock *xlrec = (xl_heap_lock *) rec;
appendStringInfo(buf, "lock %u: ", xlrec->locking_xid);
appendStringInfo(buf, "xid %u: ", xlrec->locking_xid);
out_target(buf, &(xlrec->target));
appendStringInfoChar(buf, ' ');
out_infobits(buf, xlrec->infobits_set);
@@ -111,11 +98,8 @@ heap_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_inplace *xlrec = (xl_heap_inplace *) rec;
appendStringInfoString(buf, "inplace: ");
out_target(buf, &(xlrec->target));
}
else
appendStringInfoString(buf, "UNKNOWN");
}
void
heap2_desc(StringInfo buf, XLogRecord *record)
@@ -128,7 +112,7 @@ heap2_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_clean *xlrec = (xl_heap_clean *) rec;
appendStringInfo(buf, "clean: rel %u/%u/%u; blk %u remxid %u",
appendStringInfo(buf, "rel %u/%u/%u; blk %u remxid %u",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->block,
xlrec->latestRemovedXid);
@@ -137,27 +121,22 @@ heap2_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec;
appendStringInfo(buf, "freeze_page: rel %u/%u/%u; blk %u; cutoff xid %u ntuples %u",
appendStringInfo(buf, "rel %u/%u/%u; blk %u; cutoff xid %u ntuples %u",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->block,
xlrec->cutoff_xid, xlrec->ntuples);
}
else if (info == XLOG_HEAP2_REWRITE)
{
appendStringInfoString(buf, "heap rewrite:");
}
else if (info == XLOG_HEAP2_CLEANUP_INFO)
{
xl_heap_cleanup_info *xlrec = (xl_heap_cleanup_info *) rec;
appendStringInfo(buf, "cleanup info: remxid %u",
xlrec->latestRemovedXid);
appendStringInfo(buf, "remxid %u", xlrec->latestRemovedXid);
}
else if (info == XLOG_HEAP2_VISIBLE)
{
xl_heap_visible *xlrec = (xl_heap_visible *) rec;
appendStringInfo(buf, "visible: rel %u/%u/%u; blk %u",
appendStringInfo(buf, "rel %u/%u/%u; blk %u",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->block);
}
@@ -165,10 +144,6 @@ heap2_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec;
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
appendStringInfoString(buf, "multi-insert (init): ");
else
appendStringInfoString(buf, "multi-insert: ");
appendStringInfo(buf, "rel %u/%u/%u; blk %u; %d tuples",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode,
xlrec->blkno, xlrec->ntuples);
@@ -177,7 +152,7 @@ heap2_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec;
appendStringInfo(buf, "lock updated: xmax %u msk %04x; ", xlrec->xmax,
appendStringInfo(buf, "xmax %u msk %04x; ", xlrec->xmax,
xlrec->infobits_set);
out_target(buf, &(xlrec->target));
}
@@ -185,11 +160,91 @@ heap2_desc(StringInfo buf, XLogRecord *record)
{
xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec;
appendStringInfo(buf, "new_cid: ");
out_target(buf, &(xlrec->target));
appendStringInfo(buf, "; cmin: %u, cmax: %u, combo: %u",
xlrec->cmin, xlrec->cmax, xlrec->combocid);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
static const char *
append_init(const char *str)
{
static char x[32];
strcpy(x, str);
strcat(x, "+INIT");
return x;
}
const char *
heap_identify(uint8 info)
{
const char *id = NULL;
switch (info & XLOG_HEAP_OPMASK)
{
case XLOG_HEAP_INSERT:
id = "INSERT";
break;
case XLOG_HEAP_DELETE:
id = "DELETE";
break;
case XLOG_HEAP_UPDATE:
id = "UPDATE";
break;
case XLOG_HEAP_HOT_UPDATE:
id = "HOT_UPDATE";
break;
case XLOG_HEAP_LOCK:
id = "LOCK";
break;
case XLOG_HEAP_INPLACE:
id = "INPLACE";
break;
}
if (info & XLOG_HEAP_INIT_PAGE)
id = append_init(id);
return id;
}
const char *
heap2_identify(uint8 info)
{
const char *id = NULL;
switch (info & XLOG_HEAP_OPMASK)
{
case XLOG_HEAP2_CLEAN:
id = "CLEAN";
break;
case XLOG_HEAP2_FREEZE_PAGE:
id = "FREEZE_PAGE";
break;
case XLOG_HEAP2_CLEANUP_INFO:
id = "CLEANUP_INFO";
break;
case XLOG_HEAP2_VISIBLE:
id = "VISIBLE";
break;
case XLOG_HEAP2_MULTI_INSERT:
id = "MULTI_INSERT";
break;
case XLOG_HEAP2_LOCK_UPDATED:
id = "LOCK_UPDATED";
break;
case XLOG_HEAP2_NEW_CID:
id = "NEW_CID";
break;
case XLOG_HEAP2_REWRITE:
id = "REWRITE";
break;
}
if (info & XLOG_HEAP_INIT_PAGE)
id = append_init(id);
return id;
}

View File

@@ -52,30 +52,43 @@ multixact_desc(StringInfo buf, XLogRecord *record)
char *rec = XLogRecGetData(record);
uint8 info = record->xl_info & ~XLR_INFO_MASK;
if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE ||
info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
{
int pageno;
memcpy(&pageno, rec, sizeof(int));
appendStringInfo(buf, "zero offsets page: %d", pageno);
}
else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
{
int pageno;
memcpy(&pageno, rec, sizeof(int));
appendStringInfo(buf, "zero members page: %d", pageno);
appendStringInfo(buf, "%d", pageno);
}
else if (info == XLOG_MULTIXACT_CREATE_ID)
{
xl_multixact_create *xlrec = (xl_multixact_create *) rec;
int i;
appendStringInfo(buf, "create mxid %u offset %u nmembers %d: ", xlrec->mid,
appendStringInfo(buf, "%u offset %u nmembers %d: ", xlrec->mid,
xlrec->moff, xlrec->nmembers);
for (i = 0; i < xlrec->nmembers; i++)
out_member(buf, &xlrec->members[i]);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
multixact_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_MULTIXACT_ZERO_OFF_PAGE:
id = "ZERO_OFF_PAGE";
break;
case XLOG_MULTIXACT_ZERO_MEM_PAGE:
id = "ZERO_MEM_PAGE";
break;
case XLOG_MULTIXACT_CREATE_ID:
id = "CREATE_ID";
break;
}
return id;
}

View File

@@ -34,74 +34,26 @@ btree_desc(StringInfo buf, XLogRecord *record)
switch (info)
{
case XLOG_BTREE_INSERT_LEAF:
{
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
appendStringInfoString(buf, "insert: ");
out_target(buf, &(xlrec->target));
break;
}
case XLOG_BTREE_INSERT_UPPER:
{
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
appendStringInfoString(buf, "insert_upper: ");
out_target(buf, &(xlrec->target));
break;
}
case XLOG_BTREE_INSERT_META:
{
xl_btree_insert *xlrec = (xl_btree_insert *) rec;
appendStringInfoString(buf, "insert_meta: ");
out_target(buf, &(xlrec->target));
break;
}
case XLOG_BTREE_SPLIT_L:
{
xl_btree_split *xlrec = (xl_btree_split *) rec;
appendStringInfo(buf, "split_l: rel %u/%u/%u ",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode);
appendStringInfo(buf, "left %u, right %u, next %u, level %u, firstright %d",
xlrec->leftsib, xlrec->rightsib, xlrec->rnext,
xlrec->level, xlrec->firstright);
break;
}
case XLOG_BTREE_SPLIT_R:
{
xl_btree_split *xlrec = (xl_btree_split *) rec;
appendStringInfo(buf, "split_r: rel %u/%u/%u ",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode);
appendStringInfo(buf, "left %u, right %u, next %u, level %u, firstright %d",
xlrec->leftsib, xlrec->rightsib, xlrec->rnext,
xlrec->level, xlrec->firstright);
break;
}
case XLOG_BTREE_SPLIT_L_ROOT:
{
xl_btree_split *xlrec = (xl_btree_split *) rec;
appendStringInfo(buf, "split_l_root: rel %u/%u/%u ",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode);
appendStringInfo(buf, "left %u, right %u, next %u, level %u, firstright %d",
xlrec->leftsib, xlrec->rightsib, xlrec->rnext,
xlrec->level, xlrec->firstright);
break;
}
case XLOG_BTREE_SPLIT_R_ROOT:
{
xl_btree_split *xlrec = (xl_btree_split *) rec;
appendStringInfo(buf, "split_r_root: rel %u/%u/%u ",
appendStringInfo(buf, "rel %u/%u/%u ",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode);
appendStringInfo(buf, "left %u, right %u, next %u, level %u, firstright %d",
xlrec->leftsib, xlrec->rightsib, xlrec->rnext,
xlrec->leftsib, xlrec->rightsib, xlrec->rnext,
xlrec->level, xlrec->firstright);
break;
}
@@ -109,7 +61,7 @@ btree_desc(StringInfo buf, XLogRecord *record)
{
xl_btree_vacuum *xlrec = (xl_btree_vacuum *) rec;
appendStringInfo(buf, "vacuum: rel %u/%u/%u; blk %u, lastBlockVacuumed %u",
appendStringInfo(buf, "rel %u/%u/%u; blk %u, lastBlockVacuumed %u",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->block,
xlrec->lastBlockVacuumed);
@@ -119,8 +71,8 @@ btree_desc(StringInfo buf, XLogRecord *record)
{
xl_btree_delete *xlrec = (xl_btree_delete *) rec;
appendStringInfo(buf, "delete: index %u/%u/%u; iblk %u, heap %u/%u/%u;",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode,
appendStringInfo(buf, "index %u/%u/%u; iblk %u, heap %u/%u/%u;",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode,
xlrec->block,
xlrec->hnode.spcNode, xlrec->hnode.dbNode, xlrec->hnode.relNode);
break;
@@ -129,7 +81,6 @@ btree_desc(StringInfo buf, XLogRecord *record)
{
xl_btree_mark_page_halfdead *xlrec = (xl_btree_mark_page_halfdead *) rec;
appendStringInfoString(buf, "mark_page_halfdead: ");
out_target(buf, &(xlrec->target));
appendStringInfo(buf, "; topparent %u; leaf %u; left %u; right %u",
xlrec->topparent, xlrec->leafblk, xlrec->leftblk, xlrec->rightblk);
@@ -140,8 +91,8 @@ btree_desc(StringInfo buf, XLogRecord *record)
{
xl_btree_unlink_page *xlrec = (xl_btree_unlink_page *) rec;
appendStringInfo(buf, "unlink_page: rel %u/%u/%u; ",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode);
appendStringInfo(buf, "rel %u/%u/%u; ",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode);
appendStringInfo(buf, "dead %u; left %u; right %u; btpo_xact %u; ",
xlrec->deadblk, xlrec->leftsib, xlrec->rightsib, xlrec->btpo_xact);
appendStringInfo(buf, "leaf %u; leafleft %u; leafright %u; topparent %u",
@@ -152,7 +103,7 @@ btree_desc(StringInfo buf, XLogRecord *record)
{
xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
appendStringInfo(buf, "newroot: rel %u/%u/%u; root %u lev %u",
appendStringInfo(buf, "rel %u/%u/%u; root %u lev %u",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode,
xlrec->rootblk, xlrec->level);
@@ -162,13 +113,64 @@ btree_desc(StringInfo buf, XLogRecord *record)
{
xl_btree_reuse_page *xlrec = (xl_btree_reuse_page *) rec;
appendStringInfo(buf, "reuse_page: rel %u/%u/%u; latestRemovedXid %u",
appendStringInfo(buf, "rel %u/%u/%u; latestRemovedXid %u",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode, xlrec->latestRemovedXid);
xlrec->node.relNode, xlrec->latestRemovedXid);
break;
}
default:
appendStringInfoString(buf, "UNKNOWN");
break;
}
}
const char *
btree_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
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_SPLIT_L_ROOT:
id = "SPLIT_L_ROOT";
break;
case XLOG_BTREE_SPLIT_R_ROOT:
id = "SPLIT_R_ROOT";
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;
}
return id;
}

View File

@@ -26,9 +26,22 @@ relmap_desc(StringInfo buf, XLogRecord *record)
{
xl_relmap_update *xlrec = (xl_relmap_update *) rec;
appendStringInfo(buf, "update relmap: database %u tablespace %u size %u",
appendStringInfo(buf, "database %u tablespace %u size %u",
xlrec->dbid, xlrec->tsid, xlrec->nbytes);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
relmap_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_RELMAP_UPDATE:
id = "UPDATE";
break;
}
return id;
}

View File

@@ -25,13 +25,22 @@ seq_desc(StringInfo buf, XLogRecord *record)
xl_seq_rec *xlrec = (xl_seq_rec *) rec;
if (info == XLOG_SEQ_LOG)
appendStringInfoString(buf, "log: ");
else
appendStringInfo(buf, "rel %u/%u/%u",
xlrec->node.spcNode, xlrec->node.dbNode,
xlrec->node.relNode);
}
const char *
seq_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
appendStringInfoString(buf, "UNKNOWN");
return;
case XLOG_SEQ_LOG:
id = "LOG";
break;
}
appendStringInfo(buf, "rel %u/%u/%u",
xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode);
return id;
}

View File

@@ -29,7 +29,7 @@ smgr_desc(StringInfo buf, XLogRecord *record)
xl_smgr_create *xlrec = (xl_smgr_create *) rec;
char *path = relpathperm(xlrec->rnode, xlrec->forkNum);
appendStringInfo(buf, "file create: %s", path);
appendStringInfo(buf, "%s", path);
pfree(path);
}
else if (info == XLOG_SMGR_TRUNCATE)
@@ -37,10 +37,25 @@ smgr_desc(StringInfo buf, XLogRecord *record)
xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;
char *path = relpathperm(xlrec->rnode, MAIN_FORKNUM);
appendStringInfo(buf, "file truncate: %s to %u blocks", path,
xlrec->blkno);
appendStringInfo(buf, "%s to %u blocks", path, xlrec->blkno);
pfree(path);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
smgr_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_SMGR_CREATE:
id = "CREATE";
break;
case XLOG_SMGR_TRUNCATE:
id = "TRUNCATE";
break;
}
return id;
}

View File

@@ -32,32 +32,32 @@ spg_desc(StringInfo buf, XLogRecord *record)
switch (info)
{
case XLOG_SPGIST_CREATE_INDEX:
appendStringInfo(buf, "create_index: rel %u/%u/%u",
appendStringInfo(buf, "rel %u/%u/%u",
((RelFileNode *) rec)->spcNode,
((RelFileNode *) rec)->dbNode,
((RelFileNode *) rec)->relNode);
break;
case XLOG_SPGIST_ADD_LEAF:
out_target(buf, ((spgxlogAddLeaf *) rec)->node);
appendStringInfo(buf, "add leaf to page: %u",
appendStringInfo(buf, "%u",
((spgxlogAddLeaf *) rec)->blknoLeaf);
break;
case XLOG_SPGIST_MOVE_LEAFS:
out_target(buf, ((spgxlogMoveLeafs *) rec)->node);
appendStringInfo(buf, "move %u leafs from page %u to page %u",
appendStringInfo(buf, "%u leafs from page %u to page %u",
((spgxlogMoveLeafs *) rec)->nMoves,
((spgxlogMoveLeafs *) rec)->blknoSrc,
((spgxlogMoveLeafs *) rec)->blknoDst);
break;
case XLOG_SPGIST_ADD_NODE:
out_target(buf, ((spgxlogAddNode *) rec)->node);
appendStringInfo(buf, "add node to %u:%u",
appendStringInfo(buf, "%u:%u",
((spgxlogAddNode *) rec)->blkno,
((spgxlogAddNode *) rec)->offnum);
break;
case XLOG_SPGIST_SPLIT_TUPLE:
out_target(buf, ((spgxlogSplitTuple *) rec)->node);
appendStringInfo(buf, "split node %u:%u to %u:%u",
appendStringInfo(buf, "%u:%u to %u:%u",
((spgxlogSplitTuple *) rec)->blknoPrefix,
((spgxlogSplitTuple *) rec)->offnumPrefix,
((spgxlogSplitTuple *) rec)->blknoPostfix,
@@ -65,26 +65,61 @@ spg_desc(StringInfo buf, XLogRecord *record)
break;
case XLOG_SPGIST_PICKSPLIT:
out_target(buf, ((spgxlogPickSplit *) rec)->node);
appendStringInfoString(buf, "split leaf page");
break;
case XLOG_SPGIST_VACUUM_LEAF:
out_target(buf, ((spgxlogVacuumLeaf *) rec)->node);
appendStringInfo(buf, "vacuum leaf tuples on page %u",
appendStringInfo(buf, "page %u",
((spgxlogVacuumLeaf *) rec)->blkno);
break;
case XLOG_SPGIST_VACUUM_ROOT:
out_target(buf, ((spgxlogVacuumRoot *) rec)->node);
appendStringInfo(buf, "vacuum leaf tuples on root page %u",
appendStringInfo(buf, "page %u",
((spgxlogVacuumRoot *) rec)->blkno);
break;
case XLOG_SPGIST_VACUUM_REDIRECT:
out_target(buf, ((spgxlogVacuumRedirect *) rec)->node);
appendStringInfo(buf, "vacuum redirect tuples on page %u, newest XID %u",
appendStringInfo(buf, "page %u, newest XID %u",
((spgxlogVacuumRedirect *) rec)->blkno,
((spgxlogVacuumRedirect *) rec)->newestRedirectXid);
break;
default:
appendStringInfo(buf, "unknown spgist op code %u", info);
break;
}
}
const char *
spg_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_SPGIST_CREATE_INDEX:
id = "CREATE_INDEX";
break;
case XLOG_SPGIST_ADD_LEAF:
id = "ADD_LEAF";
break;
case XLOG_SPGIST_MOVE_LEAFS:
id = "MOVE_LEAFS";
break;
case XLOG_SPGIST_ADD_NODE:
id = "ADD_NODE";
break;
case XLOG_SPGIST_SPLIT_TUPLE:
id = "SPLIT_TUPLE";
break;
case XLOG_SPGIST_PICKSPLIT:
id = "PICKSPLIT";
break;
case XLOG_SPGIST_VACUUM_LEAF:
id = "VACUUM_LEAF";
break;
case XLOG_SPGIST_VACUUM_ROOT:
id = "VACUUM_ROOT";
break;
case XLOG_SPGIST_VACUUM_REDIRECT:
id = "VACUUM_REDIRECT";
break;
}
return id;
}

View File

@@ -21,7 +21,7 @@ standby_desc_running_xacts(StringInfo buf, xl_running_xacts *xlrec)
{
int i;
appendStringInfo(buf, " nextXid %u latestCompletedXid %u oldestRunningXid %u",
appendStringInfo(buf, "nextXid %u latestCompletedXid %u oldestRunningXid %u",
xlrec->nextXid,
xlrec->latestCompletedXid,
xlrec->oldestRunningXid);
@@ -47,10 +47,8 @@ standby_desc(StringInfo buf, XLogRecord *record)
xl_standby_locks *xlrec = (xl_standby_locks *) rec;
int i;
appendStringInfoString(buf, "AccessExclusive locks:");
for (i = 0; i < xlrec->nlocks; i++)
appendStringInfo(buf, " xid %u db %u rel %u",
appendStringInfo(buf, "xid %u db %u rel %u ",
xlrec->locks[i].xid, xlrec->locks[i].dbOid,
xlrec->locks[i].relOid);
}
@@ -58,9 +56,24 @@ standby_desc(StringInfo buf, XLogRecord *record)
{
xl_running_xacts *xlrec = (xl_running_xacts *) rec;
appendStringInfoString(buf, "running xacts:");
standby_desc_running_xacts(buf, xlrec);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
standby_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_STANDBY_LOCK:
id = "LOCK";
break;
case XLOG_RUNNING_XACTS:
id = "RUNNING_XACTS";
break;
}
return id;
}

View File

@@ -27,15 +27,30 @@ tblspc_desc(StringInfo buf, XLogRecord *record)
{
xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) rec;
appendStringInfo(buf, "create tablespace: %u \"%s\"",
xlrec->ts_id, xlrec->ts_path);
appendStringInfo(buf, "%u \"%s\"", xlrec->ts_id, xlrec->ts_path);
}
else if (info == XLOG_TBLSPC_DROP)
{
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) rec;
appendStringInfo(buf, "drop tablespace: %u", xlrec->ts_id);
appendStringInfo(buf, "%u", xlrec->ts_id);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
tblspc_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_TBLSPC_CREATE:
id = "CREATE";
break;
case XLOG_TBLSPC_DROP:
id = "DROP";
break;
}
return id;
}

View File

@@ -146,39 +146,32 @@ xact_desc(StringInfo buf, XLogRecord *record)
{
xl_xact_commit_compact *xlrec = (xl_xact_commit_compact *) rec;
appendStringInfoString(buf, "commit: ");
xact_desc_commit_compact(buf, xlrec);
}
else if (info == XLOG_XACT_COMMIT)
{
xl_xact_commit *xlrec = (xl_xact_commit *) rec;
appendStringInfoString(buf, "commit: ");
xact_desc_commit(buf, xlrec);
}
else if (info == XLOG_XACT_ABORT)
{
xl_xact_abort *xlrec = (xl_xact_abort *) rec;
appendStringInfoString(buf, "abort: ");
xact_desc_abort(buf, xlrec);
}
else if (info == XLOG_XACT_PREPARE)
{
appendStringInfoString(buf, "prepare");
}
else if (info == XLOG_XACT_COMMIT_PREPARED)
{
xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
appendStringInfo(buf, "commit prepared %u: ", xlrec->xid);
appendStringInfo(buf, "%u: ", xlrec->xid);
xact_desc_commit(buf, &xlrec->crec);
}
else if (info == XLOG_XACT_ABORT_PREPARED)
{
xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
appendStringInfo(buf, "abort prepared %u: ", xlrec->xid);
appendStringInfo(buf, "%u: ", xlrec->xid);
xact_desc_abort(buf, &xlrec->arec);
}
else if (info == XLOG_XACT_ASSIGNMENT)
@@ -190,9 +183,40 @@ xact_desc(StringInfo buf, XLogRecord *record)
* interested in the top-level xid that issued the record and which
* xids are being reported here.
*/
appendStringInfo(buf, "xid assignment xtop %u: ", xlrec->xtop);
appendStringInfo(buf, "xtop %u: ", xlrec->xtop);
xact_desc_assignment(buf, xlrec);
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
xact_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_XACT_COMMIT:
id = "COMMIT";
break;
case XLOG_XACT_PREPARE:
id = "PREPARE";
break;
case XLOG_XACT_ABORT:
id = "ABORT";
break;
case XLOG_XACT_COMMIT_PREPARED:
id = "COMMIT_PREPARED";
break;
case XLOG_XACT_ABORT_PREPARED:
id = "ABORT_PREPARED";
break;
case XLOG_XACT_ASSIGNMENT:
id = "ASSIGNMENT";
break;
case XLOG_XACT_COMMIT_COMPACT:
id = "COMMIT_COMPACT";
break;
}
return id;
}

View File

@@ -42,7 +42,7 @@ xlog_desc(StringInfo buf, XLogRecord *record)
{
CheckPoint *checkpoint = (CheckPoint *) rec;
appendStringInfo(buf, "checkpoint: redo %X/%X; "
appendStringInfo(buf, "redo %X/%X; "
"tli %u; prev tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
"oldest xid %u in DB %u; oldest multi %u in DB %u; "
"oldest running xid %u; %s",
@@ -61,33 +61,24 @@ xlog_desc(StringInfo buf, XLogRecord *record)
checkpoint->oldestActiveXid,
(info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
}
else if (info == XLOG_NOOP)
{
appendStringInfoString(buf, "xlog no-op");
}
else if (info == XLOG_NEXTOID)
{
Oid nextOid;
memcpy(&nextOid, rec, sizeof(Oid));
appendStringInfo(buf, "nextOid: %u", nextOid);
}
else if (info == XLOG_SWITCH)
{
appendStringInfoString(buf, "xlog switch");
appendStringInfo(buf, "%u", nextOid);
}
else if (info == XLOG_RESTORE_POINT)
{
xl_restore_point *xlrec = (xl_restore_point *) rec;
appendStringInfo(buf, "restore point: %s", xlrec->rp_name);
appendStringInfo(buf, "%s", xlrec->rp_name);
}
else if (info == XLOG_FPI)
{
BkpBlock *bkp = (BkpBlock *) rec;
appendStringInfo(buf, "full-page image: %s block %u",
appendStringInfo(buf, "%s block %u",
relpathperm(bkp->node, bkp->fork),
bkp->block);
}
@@ -96,7 +87,7 @@ xlog_desc(StringInfo buf, XLogRecord *record)
XLogRecPtr startpoint;
memcpy(&startpoint, rec, sizeof(XLogRecPtr));
appendStringInfo(buf, "backup end: %X/%X",
appendStringInfo(buf, "%X/%X",
(uint32) (startpoint >> 32), (uint32) startpoint);
}
else if (info == XLOG_PARAMETER_CHANGE)
@@ -118,7 +109,7 @@ xlog_desc(StringInfo buf, XLogRecord *record)
}
}
appendStringInfo(buf, "parameter change: max_connections=%d max_worker_processes=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
appendStringInfo(buf, "max_connections=%d max_worker_processes=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
xlrec.MaxConnections,
xlrec.max_worker_processes,
xlrec.max_prepared_xacts,
@@ -130,17 +121,60 @@ xlog_desc(StringInfo buf, XLogRecord *record)
bool fpw;
memcpy(&fpw, rec, sizeof(bool));
appendStringInfo(buf, "full_page_writes: %s", fpw ? "true" : "false");
appendStringInfo(buf, "%s", fpw ? "true" : "false");
}
else if (info == XLOG_END_OF_RECOVERY)
{
xl_end_of_recovery xlrec;
memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
appendStringInfo(buf, "end_of_recovery: tli %u; prev tli %u; time %s",
appendStringInfo(buf, "tli %u; prev tli %u; time %s",
xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
timestamptz_to_str(xlrec.end_time));
}
else
appendStringInfoString(buf, "UNKNOWN");
}
const char *
xlog_identify(uint8 info)
{
const char *id = NULL;
switch (info)
{
case XLOG_CHECKPOINT_SHUTDOWN:
id = "CHECKPOINT_SHUTDOWN";
break;
case XLOG_CHECKPOINT_ONLINE:
id = "CHECKPOINT_ONLINE";
break;
case XLOG_NOOP:
id = "NOOP";
break;
case XLOG_NEXTOID:
id = "NEXTOID";
break;
case XLOG_SWITCH:
id = "SWITCH";
break;
case XLOG_BACKUP_END:
id = "BACKUP_END";
break;
case XLOG_PARAMETER_CHANGE:
id = "PARAMETER_CHANGE";
break;
case XLOG_RESTORE_POINT:
id = "RESTORE_POINT";
break;
case XLOG_FPW_CHANGE:
id = "FPW_CHANGE";
break;
case XLOG_END_OF_RECOVERY:
id = "END_OF_RECOVERY";
break;
case XLOG_FPI:
id = "FPI";
break;
}
return id;
}

View File

@@ -25,8 +25,8 @@
#include "utils/relmapper.h"
/* must be kept in sync with RmgrData definition in xlog_internal.h */
#define PG_RMGR(symname,name,redo,desc,startup,cleanup) \
{ name, redo, desc, startup, cleanup },
#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup) \
{ name, redo, desc, identify, startup, cleanup },
const RmgrData RmgrTable[RM_MAX_ID + 1] = {
#include "access/rmgrlist.h"

View File

@@ -799,6 +799,7 @@ static bool CheckForStandbyTrigger(void);
#ifdef WAL_DEBUG
static void xlog_outrec(StringInfo buf, XLogRecord *record);
#endif
static void xlog_outdesc(StringInfo buf, RmgrId rmid, XLogRecord *record);
static void pg_start_backup_callback(int code, Datum arg);
static bool read_backup_label(XLogRecPtr *checkPointLoc,
bool *backupEndRequired, bool *backupFromStandby);
@@ -1287,7 +1288,7 @@ begin:;
appendBinaryStringInfo(&recordbuf, rdata->data, rdata->len);
appendStringInfoString(&buf, " - ");
RmgrTable[rechdr->xl_rmid].rm_desc(&buf, (XLogRecord *) recordbuf.data);
xlog_outdesc(&buf, rechdr->xl_rmid, (XLogRecord *) recordbuf.data);
}
elog(LOG, "%s", buf.data);
@@ -6710,7 +6711,7 @@ StartupXLOG(void)
(uint32) (EndRecPtr >> 32), (uint32) EndRecPtr);
xlog_outrec(&buf, record);
appendStringInfoString(&buf, " - ");
RmgrTable[record->xl_rmid].rm_desc(&buf, record);
xlog_outdesc(&buf, record->xl_rmid, record);
elog(LOG, "%s", buf.data);
pfree(buf.data);
}
@@ -9624,11 +9625,30 @@ xlog_outrec(StringInfo buf, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK(i))
appendStringInfo(buf, "; bkpb%d", i);
}
appendStringInfo(buf, ": %s", RmgrTable[record->xl_rmid].rm_name);
}
#endif /* WAL_DEBUG */
/*
* Returns a string describing an XLogRecord, consisting of its identity
* optionally followed by a colon, a space, and a further description.
*/
static void
xlog_outdesc(StringInfo buf, RmgrId rmid, XLogRecord *record)
{
const char *id;
appendStringInfoString(buf, RmgrTable[rmid].rm_name);
appendStringInfoChar(buf, '/');
id = RmgrTable[rmid].rm_identify(record->xl_info);
if (id == NULL)
appendStringInfo(buf, "UNKNOWN (%X): ", record->xl_info);
else
appendStringInfo(buf, "%s: ", id);
RmgrTable[rmid].rm_desc(buf, record);
}
/*
* Return the (possible) sync flag used for opening a file, depending on the
@@ -10664,7 +10684,7 @@ rm_redo_error_callback(void *arg)
StringInfoData buf;
initStringInfo(&buf);
RmgrTable[record->xl_rmid].rm_desc(&buf, record);
xlog_outdesc(&buf, record->xl_rmid, record);
/* don't bother emitting empty description */
if (buf.len > 0)