>From ba1e4848383fb277fb1aca48f9253abc69a6af9d Mon Sep 17 00:00:00 2001
From: Abhijit Menon-Sen <ams@2ndQuadrant.com>
Date: Fri, 19 Sep 2014 13:14:26 +0530
Subject: Clearly separate rm_identify and rm_desc outputs

rm_identify returns NULL or a name based on the #define corresponding to
xl_info. rm_desc adds additional detail if there is any to be had. Now
we can just glue the output together in xlog.c.
---
 src/backend/access/rmgrdesc/clogdesc.c    | 13 +-----
 src/backend/access/rmgrdesc/dbasedesc.c   |  6 +--
 src/backend/access/rmgrdesc/gindesc.c     | 14 +-----
 src/backend/access/rmgrdesc/gistdesc.c    |  6 +--
 src/backend/access/rmgrdesc/heapdesc.c    | 40 +++--------------
 src/backend/access/rmgrdesc/mxactdesc.c   | 16 ++-----
 src/backend/access/rmgrdesc/nbtdesc.c     | 72 +++++--------------------------
 src/backend/access/rmgrdesc/relmapdesc.c  |  4 +-
 src/backend/access/rmgrdesc/seqdesc.c     | 12 ++----
 src/backend/access/rmgrdesc/smgrdesc.c    |  7 +--
 src/backend/access/rmgrdesc/spgdesc.c     | 22 ++++------
 src/backend/access/rmgrdesc/standbydesc.c |  7 +--
 src/backend/access/rmgrdesc/tblspcdesc.c  |  7 +--
 src/backend/access/rmgrdesc/xactdesc.c    | 15 ++-----
 src/backend/access/rmgrdesc/xlogdesc.c    | 27 ++++--------
 src/backend/access/transam/xlog.c         | 36 ++++++++++++++--
 src/include/access/xlog_internal.h        |  6 +++
 17 files changed, 94 insertions(+), 216 deletions(-)

diff --git a/src/backend/access/rmgrdesc/clogdesc.c b/src/backend/access/rmgrdesc/clogdesc.c
index 08f225d..8beb6d0 100644
--- a/src/backend/access/rmgrdesc/clogdesc.c
+++ b/src/backend/access/rmgrdesc/clogdesc.c
@@ -23,22 +23,13 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/dbasedesc.c b/src/backend/access/rmgrdesc/dbasedesc.c
index 38f3a39..e36988a 100644
--- a/src/backend/access/rmgrdesc/dbasedesc.c
+++ b/src/backend/access/rmgrdesc/dbasedesc.c
@@ -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,11 +36,9 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/gindesc.c b/src/backend/access/rmgrdesc/gindesc.c
index 115ad5b..dd4c791 100644
--- a/src/backend/access/rmgrdesc/gindesc.c
+++ b/src/backend/access/rmgrdesc/gindesc.c
@@ -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,24 +161,18 @@ 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;
 	}
 }
 
diff --git a/src/backend/access/rmgrdesc/gistdesc.c b/src/backend/access/rmgrdesc/gistdesc.c
index e4f288b..f2ed1f6 100644
--- a/src/backend/access/rmgrdesc/gistdesc.c
+++ b/src/backend/access/rmgrdesc/gistdesc.c
@@ -50,21 +50,17 @@ 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;
 	}
 }
 
diff --git a/src/backend/access/rmgrdesc/heapdesc.c b/src/backend/access/rmgrdesc/heapdesc.c
index 91a8e72..cd9d59d 100644
--- a/src/backend/access/rmgrdesc/heapdesc.c
+++ b/src/backend/access/rmgrdesc/heapdesc.c
@@ -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,13 +160,10 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/mxactdesc.c b/src/backend/access/rmgrdesc/mxactdesc.c
index d77b1c8..177aebe 100644
--- a/src/backend/access/rmgrdesc/mxactdesc.c
+++ b/src/backend/access/rmgrdesc/mxactdesc.c
@@ -52,32 +52,24 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/nbtdesc.c b/src/backend/access/rmgrdesc/nbtdesc.c
index 821715c..7eb3bbd 100644
--- a/src/backend/access/rmgrdesc/nbtdesc.c
+++ b/src/backend/access/rmgrdesc/nbtdesc.c
@@ -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,14 +113,11 @@ 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;
 	}
 }
 
diff --git a/src/backend/access/rmgrdesc/relmapdesc.c b/src/backend/access/rmgrdesc/relmapdesc.c
index 2aebf22..39dcfb5 100644
--- a/src/backend/access/rmgrdesc/relmapdesc.c
+++ b/src/backend/access/rmgrdesc/relmapdesc.c
@@ -26,11 +26,9 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/seqdesc.c b/src/backend/access/rmgrdesc/seqdesc.c
index 157c7c6..d44fe62 100644
--- a/src/backend/access/rmgrdesc/seqdesc.c
+++ b/src/backend/access/rmgrdesc/seqdesc.c
@@ -25,15 +25,9 @@ seq_desc(StringInfo buf, XLogRecord *record)
 	xl_seq_rec *xlrec = (xl_seq_rec *) rec;
 
 	if (info == XLOG_SEQ_LOG)
-		appendStringInfoString(buf, "log: ");
-	else
-	{
-		appendStringInfoString(buf, "UNKNOWN");
-		return;
-	}
-
-	appendStringInfo(buf, "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);
 }
 
 const char *
diff --git a/src/backend/access/rmgrdesc/smgrdesc.c b/src/backend/access/rmgrdesc/smgrdesc.c
index 0a7a6e2..ee711bc 100644
--- a/src/backend/access/rmgrdesc/smgrdesc.c
+++ b/src/backend/access/rmgrdesc/smgrdesc.c
@@ -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,12 +37,9 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/spgdesc.c b/src/backend/access/rmgrdesc/spgdesc.c
index 76f43ff..74b2177 100644
--- a/src/backend/access/rmgrdesc/spgdesc.c
+++ b/src/backend/access/rmgrdesc/spgdesc.c
@@ -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,22 @@ 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);
+							 ((spgxlogVacuumRedirect *) rec)->newestRedirectXid);
 			break;
 	}
 }
diff --git a/src/backend/access/rmgrdesc/standbydesc.c b/src/backend/access/rmgrdesc/standbydesc.c
index 77503d4..436b27c 100644
--- a/src/backend/access/rmgrdesc/standbydesc.c
+++ b/src/backend/access/rmgrdesc/standbydesc.c
@@ -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,11 +56,8 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/tblspcdesc.c b/src/backend/access/rmgrdesc/tblspcdesc.c
index c947845..effeaf6 100644
--- a/src/backend/access/rmgrdesc/tblspcdesc.c
+++ b/src/backend/access/rmgrdesc/tblspcdesc.c
@@ -27,17 +27,14 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c
index 8ea10c9..11e64af 100644
--- a/src/backend/access/rmgrdesc/xactdesc.c
+++ b/src/backend/access/rmgrdesc/xactdesc.c
@@ -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,11 +183,9 @@ 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 *
diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index 04a1f24..cdefaf5 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -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,19 +121,17 @@ 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 *
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 34f2fc0..1265eca 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -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);
 				}
@@ -9629,6 +9630,35 @@ xlog_outrec(StringInfo buf, XLogRecord *record)
 }
 #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;
+
+	id = RmgrTable[rmid].rm_identify(record->xl_info);
+	if (id == NULL)
+		appendStringInfo(buf, "%X", record->xl_info);
+	else
+	{
+		StringInfoData desc;
+
+		initStringInfo(&desc);
+		RmgrTable[rmid].rm_desc(&desc, record);
+
+		appendStringInfoString(buf, id);
+		if (desc.len > 0)
+		{
+			appendStringInfoString(buf, ": ");
+			appendStringInfoString(buf, desc.data);
+			pfree(desc.data);
+		}
+	}
+}
+
 
 /*
  * Return the (possible) sync flag used for opening a file, depending on the
@@ -10664,7 +10694,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)
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index d53520a..fd0553a 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -239,6 +239,12 @@ 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).
+ *
  * RmgrTable[] is indexed by RmgrId values (see rmgrlist.h).
  */
 typedef struct RmgrData
-- 
1.9.1

