At 2014-06-30 05:19:10 +0000, dilip.ku...@huawei.com wrote: > > I have started reviewing the patch..
Thanks. > 1. Patch applied to git head cleanly. > 2. Compiled in Linux -- Some warnings same as mentioned by furuyao I've attached an updated version of the patch which should fix the warnings by using %zu. > 3. Some compilation error in windows > .\contrib\pg_xlogdump\pg_xlogdump.c(1002) : error C2065: 'optional_argument' > : undeclared identifier > .\contrib\pg_xlogdump\pg_xlogdump.c(1002) : error C2099: initializer is not a > constant > > optional_argument should be added to getopt_long.h file for windows. Hmm. I have no idea what to do about this. I did notice when I wrote the code that nothing else used optional_argument, but I didn't realise that it wouldn't work on Windows. It may be that the best thing to do would be to avoid using optional_argument altogether, and have separate --stats and --stats-per-record options. Thoughts? > Please fix these issues and send the updated patch.. I've also attached a separate patch to factor out the identify_record function into rm_identify functions in the individual rmgr files, so that the code can live next to the respective _desc functions. This allows us to remove a number of #includes from pg_xlogdump, and makes the code a bit more straightforward to read. -- Abhijit
diff --git a/contrib/pg_xlogdump/pg_xlogdump.c b/contrib/pg_xlogdump/pg_xlogdump.c index 824b8c3..1d3e664 100644 --- a/contrib/pg_xlogdump/pg_xlogdump.c +++ b/contrib/pg_xlogdump/pg_xlogdump.c @@ -15,12 +15,28 @@ #include <dirent.h> #include <unistd.h> +#include "access/clog.h" +#include "access/gin_private.h" +#include "access/gist_private.h" +#include "access/heapam_xlog.h" +#include "access/heapam_xlog.h" +#include "access/multixact.h" +#include "access/nbtree.h" +#include "access/spgist_private.h" +#include "access/xact.h" #include "access/xlog.h" #include "access/xlogreader.h" #include "access/transam.h" +#include "catalog/pg_control.h" +#include "catalog/storage_xlog.h" +#include "commands/dbcommands.h" +#include "commands/sequence.h" +#include "commands/tablespace.h" #include "common/fe_memutils.h" #include "getopt_long.h" #include "rmgrdesc.h" +#include "storage/standby.h" +#include "utils/relmapper.h" static const char *progname; @@ -41,6 +57,8 @@ typedef struct XLogDumpConfig int stop_after_records; int already_displayed_records; bool follow; + bool stats; + bool stats_per_record; /* filter options */ int filter_by_rmgr; @@ -48,6 +66,20 @@ typedef struct XLogDumpConfig bool filter_by_xid_enabled; } XLogDumpConfig; +typedef struct Stats +{ + uint64 count; + uint64 rec_len; + uint64 fpi_len; +} Stats; + +typedef struct XLogDumpStats +{ + uint64 count; + Stats rmgr_stats[RM_NEXT_ID]; + Stats record_stats[RM_NEXT_ID][16]; +} XLogDumpStats; + static void fatal_error(const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2))); @@ -322,6 +354,39 @@ XLogDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, } /* + * Store per-rmgr and per-record statistics for a given record. + */ +static void +XLogDumpCountRecord(XLogDumpConfig *config, XLogDumpStats *stats, XLogRecPtr ReadRecPtr, XLogRecord *record) +{ + RmgrId rmid; + uint8 recid; + + if (config->filter_by_rmgr != -1 && + config->filter_by_rmgr != record->xl_rmid) + return; + + if (config->filter_by_xid_enabled && + config->filter_by_xid != record->xl_xid) + return; + + rmid = record->xl_rmid; + recid = (record->xl_info & ~XLR_INFO_MASK) >> 4; + + stats->count++; + + stats->rmgr_stats[rmid].count++; + stats->rmgr_stats[rmid].rec_len += record->xl_len; + stats->rmgr_stats[rmid].fpi_len += + (record->xl_tot_len - record->xl_len - SizeOfXLogRecord); + + stats->record_stats[rmid][recid].count++; + stats->record_stats[rmid][recid].rec_len += record->xl_len; + stats->record_stats[rmid][recid].fpi_len += + (record->xl_tot_len - record->xl_len - SizeOfXLogRecord); +} + +/* * Print a record to stdout */ static void @@ -380,6 +445,476 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogRecPtr ReadRecPtr, XLogRecord } } +/* + * Given an xl_rmid and the high bits of xl_info, returns a string + * describing the record type. + */ +static const char * +identify_record(RmgrId rmid, uint8 info) +{ + const RmgrDescData *desc = &RmgrDescTable[rmid]; + const char *rec; + + rec = psprintf("0x%x", info); + + switch (rmid) + { + case RM_XLOG_ID: + switch (info) + { + case XLOG_CHECKPOINT_SHUTDOWN: + rec = "CHECKPOINT_SHUTDOWN"; + break; + case XLOG_CHECKPOINT_ONLINE: + rec = "CHECKPOINT_ONLINE"; + break; + case XLOG_NOOP: + rec = "NOOP"; + break; + case XLOG_NEXTOID: + rec = "NEXTOID"; + break; + case XLOG_SWITCH: + rec = "SWITCH"; + break; + case XLOG_BACKUP_END: + rec = "BACKUP_END"; + break; + case XLOG_PARAMETER_CHANGE: + rec = "PARAMETER_CHANGE"; + break; + case XLOG_RESTORE_POINT: + rec = "RESTORE_POINT"; + break; + case XLOG_FPW_CHANGE: + rec = "FPW_CHANGE"; + break; + case XLOG_END_OF_RECOVERY: + rec = "END_OF_RECOVERY"; + break; + case XLOG_FPI: + rec = "FPI"; + break; + } + break; + + case RM_XACT_ID: + switch (info) + { + case XLOG_XACT_COMMIT: + rec = "COMMIT"; + break; + case XLOG_XACT_PREPARE: + rec = "PREPARE"; + break; + case XLOG_XACT_ABORT: + rec = "ABORT"; + break; + case XLOG_XACT_COMMIT_PREPARED: + rec = "COMMIT_PREPARED"; + break; + case XLOG_XACT_ABORT_PREPARED: + rec = "ABORT_PREPARED"; + break; + case XLOG_XACT_ASSIGNMENT: + rec = "ASSIGNMENT"; + break; + case XLOG_XACT_COMMIT_COMPACT: + rec = "COMMIT_COMPACT"; + break; + } + break; + + case RM_SMGR_ID: + switch (info) + { + case XLOG_SMGR_CREATE: + rec = "CREATE"; + break; + case XLOG_SMGR_TRUNCATE: + rec = "TRUNCATE"; + break; + } + break; + + case RM_CLOG_ID: + switch (info) + { + case CLOG_ZEROPAGE: + rec = "ZEROPAGE"; + break; + case CLOG_TRUNCATE: + rec = "TRUNCATE"; + break; + } + break; + + case RM_DBASE_ID: + switch (info) + { + case XLOG_DBASE_CREATE: + rec = "CREATE"; + break; + case XLOG_DBASE_DROP: + rec = "DROP"; + break; + } + break; + + case RM_TBLSPC_ID: + switch (info) + { + case XLOG_TBLSPC_CREATE: + rec = "CREATE"; + break; + case XLOG_TBLSPC_DROP: + rec = "DROP"; + break; + } + break; + + case RM_MULTIXACT_ID: + switch (info) + { + case XLOG_MULTIXACT_ZERO_OFF_PAGE: + rec = "ZERO_OFF_PAGE"; + break; + case XLOG_MULTIXACT_ZERO_MEM_PAGE: + rec = "ZERO_MEM_PAGE"; + break; + case XLOG_MULTIXACT_CREATE_ID: + rec = "CREATE_ID"; + break; + } + break; + + case RM_RELMAP_ID: + switch (info) + { + case XLOG_RELMAP_UPDATE: + rec = "UPDATE"; + break; + } + break; + + case RM_STANDBY_ID: + switch (info) + { + case XLOG_STANDBY_LOCK: + rec = "LOCK"; + break; + case XLOG_RUNNING_XACTS: + rec = "RUNNING_XACTS"; + break; + } + break; + + case RM_HEAP2_ID: + switch (info & XLOG_HEAP_OPMASK) + { + case XLOG_HEAP2_CLEAN: + rec = "CLEAN"; + break; + case XLOG_HEAP2_FREEZE_PAGE: + rec = "FREEZE_PAGE"; + break; + case XLOG_HEAP2_CLEANUP_INFO: + rec = "CLEANUP_INFO"; + break; + case XLOG_HEAP2_VISIBLE: + rec = "VISIBLE"; + break; + case XLOG_HEAP2_MULTI_INSERT: + rec = "MULTI_INSERT"; + break; + case XLOG_HEAP2_LOCK_UPDATED: + rec = "LOCK_UPDATED"; + break; + case XLOG_HEAP2_NEW_CID: + rec = "NEW_CID"; + break; + case XLOG_HEAP2_REWRITE: + rec = "REWRITE"; + break; + } + break; + + case RM_HEAP_ID: + { + /* Top bit is XLOG_HEAP_INIT_PAGE, the remaining three bits + * are the opcode. */ + + switch (info & XLOG_HEAP_OPMASK) + { + case XLOG_HEAP_INSERT: + rec = "INSERT"; + break; + case XLOG_HEAP_DELETE: + rec = "DELETE"; + break; + case XLOG_HEAP_UPDATE: + rec = "UPDATE"; + break; + case XLOG_HEAP_HOT_UPDATE: + rec = "HOT_UPDATE"; + break; + case XLOG_HEAP_NEWPAGE: + rec = "NEWPAGE"; + break; + case XLOG_HEAP_LOCK: + rec = "LOCK"; + break; + case XLOG_HEAP_INPLACE: + rec = "INPLACE"; + break; + } + + if (info & XLOG_HEAP_INIT_PAGE) + rec = psprintf("INIT+%s", rec); + } + break; + + case RM_BTREE_ID: + switch (info) + { + case XLOG_BTREE_INSERT_LEAF: + rec = "INSERT_LEAF"; + break; + case XLOG_BTREE_INSERT_UPPER: + rec = "INSERT_UPPER"; + break; + case XLOG_BTREE_INSERT_META: + rec = "INSERT_META"; + break; + case XLOG_BTREE_SPLIT_L: + rec = "SPLIT_L"; + break; + case XLOG_BTREE_SPLIT_R: + rec = "SPLIT_R"; + break; + case XLOG_BTREE_SPLIT_L_ROOT: + rec = "SPLIT_L_ROOT"; + break; + case XLOG_BTREE_SPLIT_R_ROOT: + rec = "SPLIT_R_ROOT"; + break; + case XLOG_BTREE_VACUUM: + rec = "VACUUM"; + break; + case XLOG_BTREE_DELETE: + rec = "DELETE"; + break; + case XLOG_BTREE_MARK_PAGE_HALFDEAD: + rec = "MARK_PAGE_HALFDEAD"; + break; + case XLOG_BTREE_UNLINK_PAGE: + rec = "UNLINK_PAGE"; + break; + case XLOG_BTREE_UNLINK_PAGE_META: + rec = "UNLINK_PAGE_META"; + break; + case XLOG_BTREE_NEWROOT: + rec = "NEWROOT"; + break; + case XLOG_BTREE_REUSE_PAGE: + rec = "REUSE_PAGE"; + break; + } + break; + + case RM_HASH_ID: + break; + + case RM_GIN_ID: + switch (info) + { + case XLOG_GIN_CREATE_INDEX: + rec = "CREATE_INDEX"; + break; + case XLOG_GIN_CREATE_PTREE: + rec = "CREATE_PTREE"; + break; + case XLOG_GIN_INSERT: + rec = "INSERT"; + break; + case XLOG_GIN_SPLIT: + rec = "SPLIT"; + break; + case XLOG_GIN_VACUUM_PAGE: + rec = "VACUUM_PAGE"; + break; + case XLOG_GIN_VACUUM_DATA_LEAF_PAGE: + rec = "VACUUM_DATA_LEAF_PAGE"; + break; + case XLOG_GIN_DELETE_PAGE: + rec = "DELETE_PAGE"; + break; + case XLOG_GIN_UPDATE_META_PAGE: + rec = "UPDATE_META_PAGE"; + break; + case XLOG_GIN_INSERT_LISTPAGE: + rec = "INSERT_LISTPAGE"; + break; + case XLOG_GIN_DELETE_LISTPAGE: + rec = "DELETE_LISTPAGE"; + break; + } + break; + + case RM_GIST_ID: + switch (info) + { + case XLOG_GIST_PAGE_UPDATE: + rec = "PAGE_UPDATE"; + break; + case XLOG_GIST_PAGE_SPLIT: + rec = "PAGE_SPLIT"; + break; + case XLOG_GIST_CREATE_INDEX: + rec = "CREATE_INDEX"; + break; + } + break; + + case RM_SEQ_ID: + switch (info) + { + case XLOG_SEQ_LOG: + rec = "LOG"; + break; + } + break; + + case RM_SPGIST_ID: + switch (info) + { + case XLOG_SPGIST_CREATE_INDEX: + rec = "CREATE_INDEX"; + break; + case XLOG_SPGIST_ADD_LEAF: + rec = "ADD_LEAF"; + break; + case XLOG_SPGIST_MOVE_LEAFS: + rec = "MOVE_LEAFS"; + break; + case XLOG_SPGIST_ADD_NODE: + rec = "ADD_NODE"; + break; + case XLOG_SPGIST_SPLIT_TUPLE: + rec = "SPLIT_TUPLE"; + break; + case XLOG_SPGIST_PICKSPLIT: + rec = "PICKSPLIT"; + break; + case XLOG_SPGIST_VACUUM_LEAF: + rec = "VACUUM_LEAF"; + break; + case XLOG_SPGIST_VACUUM_ROOT: + rec = "VACUUM_ROOT"; + break; + case XLOG_SPGIST_VACUUM_REDIRECT: + rec = "VACUUM_REDIRECT"; + break; + } + break; + + default: + break; + } + + return psprintf("%s/%s", desc->rm_name, rec); +} + +/* + * Display a single row of record counts and sizes for an rmgr or record. + */ +static void +XLogDumpStatsRow(const char *name, + uint64 n, double n_pct, + uint64 rec_len, double rec_len_pct, + uint64 fpi_len, double fpi_len_pct, + uint64 total_len, double total_len_pct) +{ + printf("%-27s %20llu (%6.02f) %20llu (%6.02f) %20llu (%6.02f) %20llu (%6.02f)\n", + name, n, n_pct, rec_len, rec_len_pct, fpi_len, fpi_len_pct, + total_len, total_len_pct); +} + + +/* + * Display summary statistics about the records seen so far. + */ +static void +XLogDumpDisplayStats(XLogDumpConfig *config, XLogDumpStats *stats) +{ + int ri, rj; + uint64 total_count = 0; + uint64 total_rec_len = 0; + uint64 total_fpi_len = 0; + uint64 total_len = 0; + + for (ri = 0; ri < RM_NEXT_ID; ri++) + { + total_count += stats->rmgr_stats[ri].count; + total_rec_len += stats->rmgr_stats[ri].rec_len; + total_fpi_len += stats->rmgr_stats[ri].fpi_len; + } + total_len = total_rec_len+total_fpi_len; + + printf("%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n" + "%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n", + "Type", "N", "(%)", "Record size", "(%)", "FPI size", "(%)", "Combined size", "(%)", + "----", "-", "---", "-----------", "---", "--------", "---", "-------------", "---"); + + for (ri = 0; ri < RM_NEXT_ID; ri++) + { + uint64 count, rec_len, fpi_len; + + if (!config->stats_per_record) + { + const RmgrDescData *desc = &RmgrDescTable[ri]; + + count = stats->rmgr_stats[ri].count; + rec_len = stats->rmgr_stats[ri].rec_len; + fpi_len = stats->rmgr_stats[ri].fpi_len; + + XLogDumpStatsRow(desc->rm_name, + count, 100*(double)count/total_count, + rec_len, 100*(double)rec_len/total_rec_len, + fpi_len, 100*(double)fpi_len/total_fpi_len, + rec_len+fpi_len, 100*(double)(rec_len+fpi_len)/total_len); + } + else + { + for (rj = 0; rj < 16; rj++) + { + count = stats->record_stats[ri][rj].count; + rec_len = stats->record_stats[ri][rj].rec_len; + fpi_len = stats->record_stats[ri][rj].fpi_len; + + if (count == 0) + continue; + + XLogDumpStatsRow(identify_record(ri, rj << 4), + count, 100*(double)count/total_count, + rec_len, 100*(double)rec_len/total_rec_len, + fpi_len, 100*(double)fpi_len/total_fpi_len, + rec_len+fpi_len, 100*(double)(rec_len+fpi_len)/total_len); + } + } + } + + printf("%-27s %20s %8s %20s %8s %20s %8s %20s\n", + "", "--------", "", "--------", "", "--------", "", "--------"); + + printf("%-27s %20llu %-9s%20llu %-9s%20llu %-9s%20llu %-6s\n", + "Total", + stats->count, "", + total_rec_len, psprintf("[%.02f%%]", 100*(double)total_rec_len/total_len), + total_fpi_len, psprintf("[%.02f%%]", 100*(double)total_fpi_len/total_len), + total_len, "[100%]"); +} + static void usage(void) { @@ -401,6 +936,8 @@ usage(void) printf(" (default: 1 or the value used in STARTSEG)\n"); printf(" -V, --version output version information, then exit\n"); printf(" -x, --xid=XID only show records with TransactionId XID\n"); + printf(" -z, --stats[=record] show statistics instead of records\n"); + printf(" (optionally, show per-record statistics)\n"); printf(" -?, --help show this help, then exit\n"); } @@ -412,6 +949,7 @@ main(int argc, char **argv) XLogReaderState *xlogreader_state; XLogDumpPrivate private; XLogDumpConfig config; + XLogDumpStats stats; XLogRecord *record; XLogRecPtr first_record; char *errormsg; @@ -428,6 +966,7 @@ main(int argc, char **argv) {"timeline", required_argument, NULL, 't'}, {"xid", required_argument, NULL, 'x'}, {"version", no_argument, NULL, 'V'}, + {"stats", optional_argument, NULL, 'z'}, {NULL, 0, NULL, 0} }; @@ -438,6 +977,7 @@ main(int argc, char **argv) memset(&private, 0, sizeof(XLogDumpPrivate)); memset(&config, 0, sizeof(XLogDumpConfig)); + memset(&stats, 0, sizeof(XLogDumpStats)); private.timeline = 1; private.startptr = InvalidXLogRecPtr; @@ -451,6 +991,8 @@ main(int argc, char **argv) config.filter_by_rmgr = -1; config.filter_by_xid = InvalidTransactionId; config.filter_by_xid_enabled = false; + config.stats = false; + config.stats_per_record = false; if (argc <= 1) { @@ -458,7 +1000,7 @@ main(int argc, char **argv) goto bad_argument; } - while ((option = getopt_long(argc, argv, "be:?fn:p:r:s:t:Vx:", + while ((option = getopt_long(argc, argv, "be:?fn:p:r:s:t:Vx:z::", long_options, &optindex)) != -1) { switch (option) @@ -551,6 +1093,20 @@ main(int argc, char **argv) } config.filter_by_xid_enabled = true; break; + case 'z': + config.stats = true; + if (optarg) + { + if (strcmp(optarg, "record") == 0) + config.stats_per_record = true; + else + { + fprintf(stderr, "%s: unrecognised argument to --stats: %s\n", + progname, optarg); + goto bad_argument; + } + } + break; default: goto bad_argument; } @@ -711,7 +1267,10 @@ main(int argc, char **argv) /* after reading the first record, continue at next one */ first_record = InvalidXLogRecPtr; - XLogDumpDisplayRecord(&config, xlogreader_state->ReadRecPtr, record); + if (config.stats == true) + XLogDumpCountRecord(&config, &stats, xlogreader_state->ReadRecPtr, record); + else + XLogDumpDisplayRecord(&config, xlogreader_state->ReadRecPtr, record); /* check whether we printed enough */ if (config.stop_after_records > 0 && @@ -719,6 +1278,9 @@ main(int argc, char **argv) break; } + if (config.stats == true) + XLogDumpDisplayStats(&config, &stats); + if (errormsg) fatal_error("error in WAL record at %X/%X: %s\n", (uint32) (xlogreader_state->ReadRecPtr >> 32),
diff --git a/contrib/pg_xlogdump/pg_xlogdump.c b/contrib/pg_xlogdump/pg_xlogdump.c index 03dfd51..47838d4 100644 --- a/contrib/pg_xlogdump/pg_xlogdump.c +++ b/contrib/pg_xlogdump/pg_xlogdump.c @@ -15,28 +15,13 @@ #include <dirent.h> #include <unistd.h> -#include "access/clog.h" -#include "access/gin_private.h" -#include "access/gist_private.h" -#include "access/heapam_xlog.h" -#include "access/heapam_xlog.h" -#include "access/multixact.h" -#include "access/nbtree.h" -#include "access/spgist_private.h" -#include "access/xact.h" -#include "access/xlog.h" #include "access/xlogreader.h" #include "access/transam.h" #include "catalog/pg_control.h" #include "catalog/storage_xlog.h" -#include "commands/dbcommands.h" -#include "commands/sequence.h" -#include "commands/tablespace.h" #include "common/fe_memutils.h" #include "getopt_long.h" #include "rmgrdesc.h" -#include "storage/standby.h" -#include "utils/relmapper.h" static const char *progname; @@ -457,386 +442,6 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogRecPtr ReadRecPtr, XLogRecord } /* - * Given an xl_rmid and the high bits of xl_info, returns a string - * describing the record type. - */ -static const char * -identify_record(RmgrId rmid, uint8 info) -{ - const RmgrDescData *desc = &RmgrDescTable[rmid]; - const char *rec; - - rec = psprintf("0x%x", info); - - switch (rmid) - { - case RM_XLOG_ID: - switch (info) - { - case XLOG_CHECKPOINT_SHUTDOWN: - rec = "CHECKPOINT_SHUTDOWN"; - break; - case XLOG_CHECKPOINT_ONLINE: - rec = "CHECKPOINT_ONLINE"; - break; - case XLOG_NOOP: - rec = "NOOP"; - break; - case XLOG_NEXTOID: - rec = "NEXTOID"; - break; - case XLOG_SWITCH: - rec = "SWITCH"; - break; - case XLOG_BACKUP_END: - rec = "BACKUP_END"; - break; - case XLOG_PARAMETER_CHANGE: - rec = "PARAMETER_CHANGE"; - break; - case XLOG_RESTORE_POINT: - rec = "RESTORE_POINT"; - break; - case XLOG_FPW_CHANGE: - rec = "FPW_CHANGE"; - break; - case XLOG_END_OF_RECOVERY: - rec = "END_OF_RECOVERY"; - break; - case XLOG_FPI: - rec = "FPI"; - break; - } - break; - - case RM_XACT_ID: - switch (info) - { - case XLOG_XACT_COMMIT: - rec = "COMMIT"; - break; - case XLOG_XACT_PREPARE: - rec = "PREPARE"; - break; - case XLOG_XACT_ABORT: - rec = "ABORT"; - break; - case XLOG_XACT_COMMIT_PREPARED: - rec = "COMMIT_PREPARED"; - break; - case XLOG_XACT_ABORT_PREPARED: - rec = "ABORT_PREPARED"; - break; - case XLOG_XACT_ASSIGNMENT: - rec = "ASSIGNMENT"; - break; - case XLOG_XACT_COMMIT_COMPACT: - rec = "COMMIT_COMPACT"; - break; - } - break; - - case RM_SMGR_ID: - switch (info) - { - case XLOG_SMGR_CREATE: - rec = "CREATE"; - break; - case XLOG_SMGR_TRUNCATE: - rec = "TRUNCATE"; - break; - } - break; - - case RM_CLOG_ID: - switch (info) - { - case CLOG_ZEROPAGE: - rec = "ZEROPAGE"; - break; - case CLOG_TRUNCATE: - rec = "TRUNCATE"; - break; - } - break; - - case RM_DBASE_ID: - switch (info) - { - case XLOG_DBASE_CREATE: - rec = "CREATE"; - break; - case XLOG_DBASE_DROP: - rec = "DROP"; - break; - } - break; - - case RM_TBLSPC_ID: - switch (info) - { - case XLOG_TBLSPC_CREATE: - rec = "CREATE"; - break; - case XLOG_TBLSPC_DROP: - rec = "DROP"; - break; - } - break; - - case RM_MULTIXACT_ID: - switch (info) - { - case XLOG_MULTIXACT_ZERO_OFF_PAGE: - rec = "ZERO_OFF_PAGE"; - break; - case XLOG_MULTIXACT_ZERO_MEM_PAGE: - rec = "ZERO_MEM_PAGE"; - break; - case XLOG_MULTIXACT_CREATE_ID: - rec = "CREATE_ID"; - break; - } - break; - - case RM_RELMAP_ID: - switch (info) - { - case XLOG_RELMAP_UPDATE: - rec = "UPDATE"; - break; - } - break; - - case RM_STANDBY_ID: - switch (info) - { - case XLOG_STANDBY_LOCK: - rec = "LOCK"; - break; - case XLOG_RUNNING_XACTS: - rec = "RUNNING_XACTS"; - break; - } - break; - - case RM_HEAP2_ID: - switch (info & XLOG_HEAP_OPMASK) - { - case XLOG_HEAP2_CLEAN: - rec = "CLEAN"; - break; - case XLOG_HEAP2_FREEZE_PAGE: - rec = "FREEZE_PAGE"; - break; - case XLOG_HEAP2_CLEANUP_INFO: - rec = "CLEANUP_INFO"; - break; - case XLOG_HEAP2_VISIBLE: - rec = "VISIBLE"; - break; - case XLOG_HEAP2_MULTI_INSERT: - rec = "MULTI_INSERT"; - break; - case XLOG_HEAP2_LOCK_UPDATED: - rec = "LOCK_UPDATED"; - break; - case XLOG_HEAP2_NEW_CID: - rec = "NEW_CID"; - break; - case XLOG_HEAP2_REWRITE: - rec = "REWRITE"; - break; - } - - if (info & XLOG_HEAP_INIT_PAGE) - rec = psprintf("%s+INIT", rec); - - break; - - case RM_HEAP_ID: - switch (info & XLOG_HEAP_OPMASK) - { - case XLOG_HEAP_INSERT: - rec = "INSERT"; - break; - case XLOG_HEAP_DELETE: - rec = "DELETE"; - break; - case XLOG_HEAP_UPDATE: - rec = "UPDATE"; - break; - case XLOG_HEAP_HOT_UPDATE: - rec = "HOT_UPDATE"; - break; - case XLOG_HEAP_NEWPAGE: - rec = "NEWPAGE"; - break; - case XLOG_HEAP_LOCK: - rec = "LOCK"; - break; - case XLOG_HEAP_INPLACE: - rec = "INPLACE"; - break; - } - - if (info & XLOG_HEAP_INIT_PAGE) - rec = psprintf("%s+INIT", rec); - - break; - - case RM_BTREE_ID: - switch (info) - { - case XLOG_BTREE_INSERT_LEAF: - rec = "INSERT_LEAF"; - break; - case XLOG_BTREE_INSERT_UPPER: - rec = "INSERT_UPPER"; - break; - case XLOG_BTREE_INSERT_META: - rec = "INSERT_META"; - break; - case XLOG_BTREE_SPLIT_L: - rec = "SPLIT_L"; - break; - case XLOG_BTREE_SPLIT_R: - rec = "SPLIT_R"; - break; - case XLOG_BTREE_SPLIT_L_ROOT: - rec = "SPLIT_L_ROOT"; - break; - case XLOG_BTREE_SPLIT_R_ROOT: - rec = "SPLIT_R_ROOT"; - break; - case XLOG_BTREE_VACUUM: - rec = "VACUUM"; - break; - case XLOG_BTREE_DELETE: - rec = "DELETE"; - break; - case XLOG_BTREE_MARK_PAGE_HALFDEAD: - rec = "MARK_PAGE_HALFDEAD"; - break; - case XLOG_BTREE_UNLINK_PAGE: - rec = "UNLINK_PAGE"; - break; - case XLOG_BTREE_UNLINK_PAGE_META: - rec = "UNLINK_PAGE_META"; - break; - case XLOG_BTREE_NEWROOT: - rec = "NEWROOT"; - break; - case XLOG_BTREE_REUSE_PAGE: - rec = "REUSE_PAGE"; - break; - } - break; - - case RM_HASH_ID: - break; - - case RM_GIN_ID: - switch (info) - { - case XLOG_GIN_CREATE_INDEX: - rec = "CREATE_INDEX"; - break; - case XLOG_GIN_CREATE_PTREE: - rec = "CREATE_PTREE"; - break; - case XLOG_GIN_INSERT: - rec = "INSERT"; - break; - case XLOG_GIN_SPLIT: - rec = "SPLIT"; - break; - case XLOG_GIN_VACUUM_PAGE: - rec = "VACUUM_PAGE"; - break; - case XLOG_GIN_VACUUM_DATA_LEAF_PAGE: - rec = "VACUUM_DATA_LEAF_PAGE"; - break; - case XLOG_GIN_DELETE_PAGE: - rec = "DELETE_PAGE"; - break; - case XLOG_GIN_UPDATE_META_PAGE: - rec = "UPDATE_META_PAGE"; - break; - case XLOG_GIN_INSERT_LISTPAGE: - rec = "INSERT_LISTPAGE"; - break; - case XLOG_GIN_DELETE_LISTPAGE: - rec = "DELETE_LISTPAGE"; - break; - } - break; - - case RM_GIST_ID: - switch (info) - { - case XLOG_GIST_PAGE_UPDATE: - rec = "PAGE_UPDATE"; - break; - case XLOG_GIST_PAGE_SPLIT: - rec = "PAGE_SPLIT"; - break; - case XLOG_GIST_CREATE_INDEX: - rec = "CREATE_INDEX"; - break; - } - break; - - case RM_SEQ_ID: - switch (info) - { - case XLOG_SEQ_LOG: - rec = "LOG"; - break; - } - break; - - case RM_SPGIST_ID: - switch (info) - { - case XLOG_SPGIST_CREATE_INDEX: - rec = "CREATE_INDEX"; - break; - case XLOG_SPGIST_ADD_LEAF: - rec = "ADD_LEAF"; - break; - case XLOG_SPGIST_MOVE_LEAFS: - rec = "MOVE_LEAFS"; - break; - case XLOG_SPGIST_ADD_NODE: - rec = "ADD_NODE"; - break; - case XLOG_SPGIST_SPLIT_TUPLE: - rec = "SPLIT_TUPLE"; - break; - case XLOG_SPGIST_PICKSPLIT: - rec = "PICKSPLIT"; - break; - case XLOG_SPGIST_VACUUM_LEAF: - rec = "VACUUM_LEAF"; - break; - case XLOG_SPGIST_VACUUM_ROOT: - rec = "VACUUM_ROOT"; - break; - case XLOG_SPGIST_VACUUM_REDIRECT: - rec = "VACUUM_REDIRECT"; - break; - } - break; - - default: - break; - } - - return psprintf("%s/%s", desc->rm_name, rec); -} - -/* * Display a single row of record counts and sizes for an rmgr or record. */ static void @@ -894,11 +499,10 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogDumpStats *stats) for (ri = 0; ri < RM_NEXT_ID; ri++) { uint64 count, rec_len, fpi_len; + const RmgrDescData *desc = &RmgrDescTable[ri]; if (!config->stats_per_record) { - const RmgrDescData *desc = &RmgrDescTable[ri]; - count = stats->rmgr_stats[ri].count; rec_len = stats->rmgr_stats[ri].rec_len; fpi_len = stats->rmgr_stats[ri].fpi_len; @@ -913,6 +517,8 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogDumpStats *stats) { for (rj = 0; rj < 16; rj++) { + const char *id; + count = stats->record_stats[ri][rj].count; rec_len = stats->record_stats[ri][rj].rec_len; fpi_len = stats->record_stats[ri][rj].fpi_len; @@ -921,7 +527,11 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogDumpStats *stats) if (count == 0) continue; - XLogDumpStatsRow(identify_record(ri, rj << 4), + id = desc->rm_identify(rj << 4); + if (id == NULL) + id = psprintf("0x%x", rj << 4); + + XLogDumpStatsRow(psprintf("%s/%s", desc->rm_name, id), count, 100*(double)count/total_count, rec_len, 100*(double)rec_len/total_rec_len, fpi_len, 100*(double)fpi_len/total_fpi_len, diff --git a/contrib/pg_xlogdump/rmgrdesc.c b/contrib/pg_xlogdump/rmgrdesc.c index cbcaaa6..dc27fd1 100644 --- a/contrib/pg_xlogdump/rmgrdesc.c +++ b/contrib/pg_xlogdump/rmgrdesc.c @@ -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" diff --git a/contrib/pg_xlogdump/rmgrdesc.h b/contrib/pg_xlogdump/rmgrdesc.h index d964118..da805c5 100644 --- a/contrib/pg_xlogdump/rmgrdesc.h +++ b/contrib/pg_xlogdump/rmgrdesc.h @@ -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[]; diff --git a/src/backend/access/rmgrdesc/clogdesc.c b/src/backend/access/rmgrdesc/clogdesc.c index e82baa8..08f225d 100644 --- a/src/backend/access/rmgrdesc/clogdesc.c +++ b/src/backend/access/rmgrdesc/clogdesc.c @@ -40,3 +40,21 @@ clog_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/dbasedesc.c b/src/backend/access/rmgrdesc/dbasedesc.c index 0230716..38f3a39 100644 --- a/src/backend/access/rmgrdesc/dbasedesc.c +++ b/src/backend/access/rmgrdesc/dbasedesc.c @@ -42,3 +42,21 @@ dbase_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/gindesc.c b/src/backend/access/rmgrdesc/gindesc.c index 12d68d7..115ad5b 100644 --- a/src/backend/access/rmgrdesc/gindesc.c +++ b/src/backend/access/rmgrdesc/gindesc.c @@ -187,3 +187,45 @@ gin_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/gistdesc.c b/src/backend/access/rmgrdesc/gistdesc.c index cdac496..e4f288b 100644 --- a/src/backend/access/rmgrdesc/gistdesc.c +++ b/src/backend/access/rmgrdesc/gistdesc.c @@ -67,3 +67,24 @@ gist_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/hashdesc.c b/src/backend/access/rmgrdesc/hashdesc.c index 86a0376..c58461c 100644 --- a/src/backend/access/rmgrdesc/hashdesc.c +++ b/src/backend/access/rmgrdesc/hashdesc.c @@ -20,3 +20,9 @@ void hash_desc(StringInfo buf, XLogRecord *record) { } + +const char * +hash_identify(uint8 info) +{ + return NULL; +} diff --git a/src/backend/access/rmgrdesc/heapdesc.c b/src/backend/access/rmgrdesc/heapdesc.c index 7df18fa..e6149be 100644 --- a/src/backend/access/rmgrdesc/heapdesc.c +++ b/src/backend/access/rmgrdesc/heapdesc.c @@ -202,3 +202,78 @@ heap2_desc(StringInfo buf, XLogRecord *record) else appendStringInfoString(buf, "UNKNOWN"); } + +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_NEWPAGE: + id = "NEWPAGE"; + break; + case XLOG_HEAP_LOCK: + id = "LOCK"; + break; + case XLOG_HEAP_INPLACE: + id = "INPLACE"; + break; + } + + if (info & XLOG_HEAP_INIT_PAGE) + id = psprintf("%s+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 = psprintf("%s+INIT", id); + + return id; +} diff --git a/src/backend/access/rmgrdesc/mxactdesc.c b/src/backend/access/rmgrdesc/mxactdesc.c index 50d9b55..d77b1c8 100644 --- a/src/backend/access/rmgrdesc/mxactdesc.c +++ b/src/backend/access/rmgrdesc/mxactdesc.c @@ -79,3 +79,24 @@ multixact_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/nbtdesc.c b/src/backend/access/rmgrdesc/nbtdesc.c index bf3389c..821715c 100644 --- a/src/backend/access/rmgrdesc/nbtdesc.c +++ b/src/backend/access/rmgrdesc/nbtdesc.c @@ -172,3 +172,57 @@ btree_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/relmapdesc.c b/src/backend/access/rmgrdesc/relmapdesc.c index 06fd4b3..2aebf22 100644 --- a/src/backend/access/rmgrdesc/relmapdesc.c +++ b/src/backend/access/rmgrdesc/relmapdesc.c @@ -32,3 +32,18 @@ relmap_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/seqdesc.c b/src/backend/access/rmgrdesc/seqdesc.c index 42eb9b9..157c7c6 100644 --- a/src/backend/access/rmgrdesc/seqdesc.c +++ b/src/backend/access/rmgrdesc/seqdesc.c @@ -35,3 +35,18 @@ seq_desc(StringInfo buf, XLogRecord *record) 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) + { + case XLOG_SEQ_LOG: + id = "LOG"; + break; + } + + return id; +} diff --git a/src/backend/access/rmgrdesc/smgrdesc.c b/src/backend/access/rmgrdesc/smgrdesc.c index c76c815..0a7a6e2 100644 --- a/src/backend/access/rmgrdesc/smgrdesc.c +++ b/src/backend/access/rmgrdesc/smgrdesc.c @@ -44,3 +44,21 @@ smgr_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/spgdesc.c b/src/backend/access/rmgrdesc/spgdesc.c index ed369b2..76f43ff 100644 --- a/src/backend/access/rmgrdesc/spgdesc.c +++ b/src/backend/access/rmgrdesc/spgdesc.c @@ -88,3 +88,42 @@ spg_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/standbydesc.c b/src/backend/access/rmgrdesc/standbydesc.c index a127d38..77503d4 100644 --- a/src/backend/access/rmgrdesc/standbydesc.c +++ b/src/backend/access/rmgrdesc/standbydesc.c @@ -64,3 +64,21 @@ standby_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/tblspcdesc.c b/src/backend/access/rmgrdesc/tblspcdesc.c index 30b1f06..c947845 100644 --- a/src/backend/access/rmgrdesc/tblspcdesc.c +++ b/src/backend/access/rmgrdesc/tblspcdesc.c @@ -39,3 +39,21 @@ tblspc_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c index 994931e..8ea10c9 100644 --- a/src/backend/access/rmgrdesc/xactdesc.c +++ b/src/backend/access/rmgrdesc/xactdesc.c @@ -196,3 +196,36 @@ xact_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c index 2224da1..04a1f24 100644 --- a/src/backend/access/rmgrdesc/xlogdesc.c +++ b/src/backend/access/rmgrdesc/xlogdesc.c @@ -144,3 +144,48 @@ xlog_desc(StringInfo buf, XLogRecord *record) 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; +} diff --git a/src/backend/access/transam/rmgr.c b/src/backend/access/transam/rmgr.c index c0a7a6f..2645a7a 100644 --- a/src/backend/access/transam/rmgr.c +++ b/src/backend/access/transam/rmgr.c @@ -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" diff --git a/src/include/access/clog.h b/src/include/access/clog.h index be9b867..8562631 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -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 */ diff --git a/src/include/access/gin.h b/src/include/access/gin.h index a0b288d..0ebecb4 100644 --- a/src/include/access/gin.h +++ b/src/include/access/gin.h @@ -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); diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index 03e9903..879f113 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -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); diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 2062801..0a7a82f 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -356,5 +356,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 */ diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h index 05beb00..0e00a11 100644 --- a/src/include/access/heapam_xlog.h +++ b/src/include/access/heapam_xlog.h @@ -369,8 +369,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, diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index f6d2e04..1910e7a 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -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); diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index ed6f697..622383d 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -725,5 +725,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 */ diff --git a/src/include/access/rmgr.h b/src/include/access/rmgr.h index 1b577a2..ff7fe62 100644 --- a/src/include/access/rmgr.h +++ b/src/include/access/rmgr.h @@ -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 diff --git a/src/include/access/rmgrlist.h b/src/include/access/rmgrlist.h index 662fb77..77d4574 100644 --- a/src/include/access/rmgrlist.h +++ b/src/include/access/rmgrlist.h @@ -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) diff --git a/src/include/access/spgist.h b/src/include/access/spgist.h index 7f8655c..f218a83 100644 --- a/src/include/access/spgist.h +++ b/src/include/access/spgist.h @@ -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); diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 10ee943..ff7c426 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -257,5 +257,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 */ diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 85f9cb7..e16d43c 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -299,6 +299,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); diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h index 8c8de38..5839426 100644 --- a/src/include/access/xlog_internal.h +++ b/src/include/access/xlog_internal.h @@ -246,6 +246,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; diff --git a/src/include/catalog/storage_xlog.h b/src/include/catalog/storage_xlog.h index 7081c99..5fc7235 100644 --- a/src/include/catalog/storage_xlog.h +++ b/src/include/catalog/storage_xlog.h @@ -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 */ diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index c2380dc..811713f 100644 --- a/src/include/commands/dbcommands.h +++ b/src/include/commands/dbcommands.h @@ -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); diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h index 8819c00..914d155 100644 --- a/src/include/commands/sequence.h +++ b/src/include/commands/sequence.h @@ -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 */ diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h index 073cb0d..5823bd9 100644 --- a/src/include/commands/tablespace.h +++ b/src/include/commands/tablespace.h @@ -58,5 +58,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 */ diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h index da22fd3..1c63af5 100644 --- a/src/include/storage/standby.h +++ b/src/include/storage/standby.h @@ -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 diff --git a/src/include/utils/relmapper.h b/src/include/utils/relmapper.h index 76bcf18..37937dd 100644 --- a/src/include/utils/relmapper.h +++ b/src/include/utils/relmapper.h @@ -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 */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers