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

@ -339,7 +339,7 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogRecPtr ReadRecPtr, XLogRecord
config->already_displayed_records++;
printf("rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, bkp: %u%u%u%u, desc: ",
printf("rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, bkp: %u%u%u%u, desc: %s ",
desc->rm_name,
record->xl_len, record->xl_tot_len,
record->xl_xid,
@ -348,7 +348,8 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogRecPtr ReadRecPtr, XLogRecord
!!(XLR_BKP_BLOCK(0) & record->xl_info),
!!(XLR_BKP_BLOCK(1) & record->xl_info),
!!(XLR_BKP_BLOCK(2) & record->xl_info),
!!(XLR_BKP_BLOCK(3) & record->xl_info));
!!(XLR_BKP_BLOCK(3) & record->xl_info),
desc->rm_identify(record->xl_info));
/* the desc routine will printf the description directly to stdout */
desc->rm_desc(NULL, record);

View File

@ -27,8 +27,8 @@
#include "storage/standby.h"
#include "utils/relmapper.h"
#define PG_RMGR(symname,name,redo,desc,startup,cleanup) \
{ name, desc, },
#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup) \
{ name, desc, identify},
const RmgrDescData RmgrDescTable[RM_MAX_ID + 1] = {
#include "access/rmgrlist.h"

View File

@ -14,6 +14,7 @@ typedef struct RmgrDescData
{
const char *rm_name;
void (*rm_desc) (StringInfo buf, XLogRecord *record);
const char *(*rm_identify) (uint8 info);
} RmgrDescData;
extern const RmgrDescData RmgrDescTable[];

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)

View File

@ -49,5 +49,6 @@ extern void TruncateCLOG(TransactionId oldestXact);
extern void clog_redo(XLogRecPtr lsn, XLogRecord *record);
extern void clog_desc(StringInfo buf, XLogRecord *record);
extern const char *clog_identify(uint8 info);
#endif /* CLOG_H */

View File

@ -74,6 +74,7 @@ extern void ginUpdateStats(Relation index, const GinStatsData *stats);
/* ginxlog.c */
extern void gin_redo(XLogRecPtr lsn, XLogRecord *record);
extern void gin_desc(StringInfo buf, XLogRecord *record);
extern const char *gin_identify(uint8 info);
extern void gin_xlog_startup(void);
extern void gin_xlog_cleanup(void);

View File

@ -452,6 +452,7 @@ extern SplitedPageLayout *gistSplit(Relation r, Page page, IndexTuple *itup,
/* gistxlog.c */
extern void gist_redo(XLogRecPtr lsn, XLogRecord *record);
extern void gist_desc(StringInfo buf, XLogRecord *record);
extern const char *gist_identify(uint8 info);
extern void gist_xlog_startup(void);
extern void gist_xlog_cleanup(void);

View File

@ -357,5 +357,6 @@ extern OffsetNumber _hash_binsearch_last(Page page, uint32 hash_value);
/* hash.c */
extern void hash_redo(XLogRecPtr lsn, XLogRecord *record);
extern void hash_desc(StringInfo buf, XLogRecord *record);
extern const char *hash_identify(uint8 info);
#endif /* HASH_H */

View File

@ -357,8 +357,10 @@ extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
extern void heap_redo(XLogRecPtr lsn, XLogRecord *record);
extern void heap_desc(StringInfo buf, XLogRecord *record);
extern const char *heap_identify(uint8 info);
extern void heap2_redo(XLogRecPtr lsn, XLogRecord *record);
extern void heap2_desc(StringInfo buf, XLogRecord *record);
extern const char *heap2_identify(uint8 info);
extern void heap_xlog_logical_rewrite(XLogRecPtr lsn, XLogRecord *r);
extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode,

View File

@ -136,6 +136,7 @@ extern void multixact_twophase_postabort(TransactionId xid, uint16 info,
extern void multixact_redo(XLogRecPtr lsn, XLogRecord *record);
extern void multixact_desc(StringInfo buf, XLogRecord *record);
extern const char *multixact_identify(uint8 info);
extern char *mxid_to_string(MultiXactId multi, int nmembers,
MultiXactMember *members);

View File

@ -726,5 +726,6 @@ extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2);
*/
extern void btree_redo(XLogRecPtr lsn, XLogRecord *record);
extern void btree_desc(StringInfo buf, XLogRecord *record);
extern const char *btree_identify(uint8 info);
#endif /* NBTREE_H */

View File

@ -19,7 +19,7 @@ typedef uint8 RmgrId;
* Note: RM_MAX_ID must fit in RmgrId; widening that type will affect the XLOG
* file format.
*/
#define PG_RMGR(symname,name,redo,desc,startup,cleanup) \
#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup) \
symname,
typedef enum RmgrIds

View File

@ -25,20 +25,20 @@
*/
/* symbol name, textual name, redo, desc, startup, cleanup */
PG_RMGR(RM_XLOG_ID, "XLOG", xlog_redo, xlog_desc, NULL, NULL)
PG_RMGR(RM_XACT_ID, "Transaction", xact_redo, xact_desc, NULL, NULL)
PG_RMGR(RM_SMGR_ID, "Storage", smgr_redo, smgr_desc, NULL, NULL)
PG_RMGR(RM_CLOG_ID, "CLOG", clog_redo, clog_desc, NULL, NULL)
PG_RMGR(RM_DBASE_ID, "Database", dbase_redo, dbase_desc, NULL, NULL)
PG_RMGR(RM_TBLSPC_ID, "Tablespace", tblspc_redo, tblspc_desc, NULL, NULL)
PG_RMGR(RM_MULTIXACT_ID, "MultiXact", multixact_redo, multixact_desc, NULL, NULL)
PG_RMGR(RM_RELMAP_ID, "RelMap", relmap_redo, relmap_desc, NULL, NULL)
PG_RMGR(RM_STANDBY_ID, "Standby", standby_redo, standby_desc, NULL, NULL)
PG_RMGR(RM_HEAP2_ID, "Heap2", heap2_redo, heap2_desc, NULL, NULL)
PG_RMGR(RM_HEAP_ID, "Heap", heap_redo, heap_desc, NULL, NULL)
PG_RMGR(RM_BTREE_ID, "Btree", btree_redo, btree_desc, NULL, NULL)
PG_RMGR(RM_HASH_ID, "Hash", hash_redo, hash_desc, NULL, NULL)
PG_RMGR(RM_GIN_ID, "Gin", gin_redo, gin_desc, gin_xlog_startup, gin_xlog_cleanup)
PG_RMGR(RM_GIST_ID, "Gist", gist_redo, gist_desc, gist_xlog_startup, gist_xlog_cleanup)
PG_RMGR(RM_SEQ_ID, "Sequence", seq_redo, seq_desc, NULL, NULL)
PG_RMGR(RM_SPGIST_ID, "SPGist", spg_redo, spg_desc, spg_xlog_startup, spg_xlog_cleanup)
PG_RMGR(RM_XLOG_ID, "XLOG", xlog_redo, xlog_desc, xlog_identify, NULL, NULL)
PG_RMGR(RM_XACT_ID, "Transaction", xact_redo, xact_desc, xact_identify, NULL, NULL)
PG_RMGR(RM_SMGR_ID, "Storage", smgr_redo, smgr_desc, smgr_identify, NULL, NULL)
PG_RMGR(RM_CLOG_ID, "CLOG", clog_redo, clog_desc, clog_identify, NULL, NULL)
PG_RMGR(RM_DBASE_ID, "Database", dbase_redo, dbase_desc, dbase_identify, NULL, NULL)
PG_RMGR(RM_TBLSPC_ID, "Tablespace", tblspc_redo, tblspc_desc, tblspc_identify, NULL, NULL)
PG_RMGR(RM_MULTIXACT_ID, "MultiXact", multixact_redo, multixact_desc, multixact_identify, NULL, NULL)
PG_RMGR(RM_RELMAP_ID, "RelMap", relmap_redo, relmap_desc, relmap_identify, NULL, NULL)
PG_RMGR(RM_STANDBY_ID, "Standby", standby_redo, standby_desc, standby_identify, NULL, NULL)
PG_RMGR(RM_HEAP2_ID, "Heap2", heap2_redo, heap2_desc, heap2_identify, NULL, NULL)
PG_RMGR(RM_HEAP_ID, "Heap", heap_redo, heap_desc, heap_identify, NULL, NULL)
PG_RMGR(RM_BTREE_ID, "Btree", btree_redo, btree_desc, btree_identify, NULL, NULL)
PG_RMGR(RM_HASH_ID, "Hash", hash_redo, hash_desc, hash_identify, NULL, NULL)
PG_RMGR(RM_GIN_ID, "Gin", gin_redo, gin_desc, gin_identify, gin_xlog_startup, gin_xlog_cleanup)
PG_RMGR(RM_GIST_ID, "Gist", gist_redo, gist_desc, gist_identify, gist_xlog_startup, gist_xlog_cleanup)
PG_RMGR(RM_SEQ_ID, "Sequence", seq_redo, seq_desc, seq_identify, NULL, NULL)
PG_RMGR(RM_SPGIST_ID, "SPGist", spg_redo, spg_desc, spg_identify, spg_xlog_startup, spg_xlog_cleanup)

View File

@ -198,6 +198,7 @@ extern Datum spgvacuumcleanup(PG_FUNCTION_ARGS);
/* spgxlog.c */
extern void spg_redo(XLogRecPtr lsn, XLogRecord *record);
extern void spg_desc(StringInfo buf, XLogRecord *record);
extern const char *spg_identify(uint8 info);
extern void spg_xlog_startup(void);
extern void spg_xlog_cleanup(void);

View File

@ -256,5 +256,6 @@ extern int xactGetCommittedChildren(TransactionId **ptr);
extern void xact_redo(XLogRecPtr lsn, XLogRecord *record);
extern void xact_desc(StringInfo buf, XLogRecord *record);
extern const char *xact_identify(uint8 info);
#endif /* XACT_H */

View File

@ -304,6 +304,7 @@ extern Buffer RestoreBackupBlock(XLogRecPtr lsn, XLogRecord *record,
extern void xlog_redo(XLogRecPtr lsn, XLogRecord *record);
extern void xlog_desc(StringInfo buf, XLogRecord *record);
extern const char *xlog_identify(uint8 info);
extern void issue_xlog_fsync(int fd, XLogSegNo segno);

View File

@ -239,6 +239,14 @@ struct XLogRecord;
* This struct must be kept in sync with the PG_RMGR definition in
* rmgr.c.
*
* rm_identify must return a name for the record based on xl_info (without
* reference to the rmid). For example, XLOG_BTREE_VACUUM would be named
* "VACUUM". rm_desc can then be called to obtain additional detail for the
* record, if available (e.g. the last block).
*
* The return value from rm_identify is a pointer to a statically allocated
* buffer, and only valid until the next invocation of the callback.
*
* RmgrTable[] is indexed by RmgrId values (see rmgrlist.h).
*/
typedef struct RmgrData
@ -246,6 +254,7 @@ typedef struct RmgrData
const char *rm_name;
void (*rm_redo) (XLogRecPtr lsn, struct XLogRecord *rptr);
void (*rm_desc) (StringInfo buf, struct XLogRecord *rptr);
const char *(*rm_identify) (uint8 info);
void (*rm_startup) (void);
void (*rm_cleanup) (void);
} RmgrData;

View File

@ -45,5 +45,6 @@ extern void log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum);
extern void smgr_redo(XLogRecPtr lsn, XLogRecord *record);
extern void smgr_desc(StringInfo buf, XLogRecord *record);
extern const char *smgr_identify(uint8 info);
#endif /* STORAGE_XLOG_H */

View File

@ -64,6 +64,7 @@ extern char *get_database_name(Oid dbid);
extern void dbase_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void dbase_desc(StringInfo buf, XLogRecord *rptr);
extern const char *dbase_identify(uint8 info);
extern void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype);

View File

@ -78,5 +78,6 @@ extern void ResetSequenceCaches(void);
extern void seq_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void seq_desc(StringInfo buf, XLogRecord *rptr);
extern const char *seq_identify(uint8 info);
#endif /* SEQUENCE_H */

View File

@ -57,5 +57,6 @@ extern bool directory_is_empty(const char *path);
extern void tblspc_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void tblspc_desc(StringInfo buf, XLogRecord *rptr);
extern const char *tblspc_identify(uint8 info);
#endif /* TABLESPACE_H */

View File

@ -83,6 +83,7 @@ typedef struct xl_running_xacts
/* Recovery handlers for the Standby Rmgr (RM_STANDBY_ID) */
extern void standby_redo(XLogRecPtr lsn, XLogRecord *record);
extern void standby_desc(StringInfo buf, XLogRecord *record);
extern const char *standby_identify(uint8 info);
/*
* Declarations for GetRunningTransactionData(). Similar to Snapshots, but

View File

@ -60,5 +60,6 @@ extern void RelationMapInitializePhase3(void);
extern void relmap_redo(XLogRecPtr lsn, XLogRecord *record);
extern void relmap_desc(StringInfo buf, XLogRecord *record);
extern const char *relmap_identify(uint8 info);
#endif /* RELMAPPER_H */