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,
!!(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);
#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"
{
const char *rm_name;
void (*rm_desc) (StringInfo buf, XLogRecord *record);
+ const char *(*rm_identify) (uint8 info);
} RmgrDescData;
extern const RmgrDescData RmgrDescTable[];
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);
+const char *
+clog_identify(uint8 info)
+{
+ const char *id = NULL;
+
+ switch (info)
+ {
+ case CLOG_ZEROPAGE:
+ id = "ZEROPAGE";
+ break;
+ case CLOG_TRUNCATE:
+ id = "TRUNCATE";
+ break;
}
- else
- appendStringInfoString(buf, "UNKNOWN");
+
+ return id;
}
{
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);
}
{
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;
}
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:
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',
{
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",
}
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)");
}
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);
+ }
+}
+
+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;
}
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);
+ }
+}
+
+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;
}
hash_desc(StringInfo buf, XLogRecord *record)
{
}
+
+const char *
+hash_identify(uint8 info)
+{
+ return NULL;
+}
{
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);
{
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);
{
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);
{
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);
{
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)
{
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);
{
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);
}
{
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);
{
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));
}
{
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;
}
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;
}
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;
}
{
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);
{
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;
{
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);
{
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",
{
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);
{
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");
+ }
+}
+
+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;
}
{
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;
}
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;
}
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)
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;
}
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,
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);
+ }
+}
+
+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;
}
{
int i;
- appendStringInfo(buf, " nextXid %u latestCompletedXid %u oldestRunningXid %u",
+ appendStringInfo(buf, "nextXid %u latestCompletedXid %u oldestRunningXid %u",
xlrec->nextXid,
xlrec->latestCompletedXid,
xlrec->oldestRunningXid);
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);
}
{
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;
}
{
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;
}
{
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)
* 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;
}
{
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",
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);
}
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)
}
}
- 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,
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;
}
#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"
#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);
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);
(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);
}
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
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)
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 */
/* 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);
/* 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);
/* 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 */
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,
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);
*/
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 */
* 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
*/
/* 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)
/* 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);
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 */
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);
* 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
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;
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 */
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);
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 */
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 */
/* 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
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 */