From 698e481f5f55b967b5c60dba4bc577f8baa20ff4 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Fri, 16 Oct 2020 17:09:29 +0530 Subject: [PATCH] Make it easy to print LSN The commit introduces following macros and functions to make it easy to use LSNs in printf variants, elog, ereport and appendStringInfo variants. LSN_FORMAT - macro representing the format in which LSN is printed LSN_FORMAT_ARG - macro to pass LSN as an argument to the above format pg_lsn_out_internal - a function which returns palloc'ed char array containing string representation of given LSN. pg_lsn_out_buffer - similar to above but accepts and returns a char array of size (MAXPG_LSNLEN + 1) The commit also has some example usages of these. Ashutosh Bapat --- contrib/pageinspect/rawpage.c | 3 +- src/backend/access/rmgrdesc/replorigindesc.c | 5 +- src/backend/access/rmgrdesc/xlogdesc.c | 3 +- src/backend/access/transam/xlog.c | 8 ++-- src/backend/utils/adt/pg_lsn.c | 49 ++++++++++++++------ src/include/access/xlogdefs.h | 7 +++ src/include/utils/pg_lsn.h | 3 ++ 7 files changed, 55 insertions(+), 23 deletions(-) diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index c0181506a5..2cd055a5f0 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -261,8 +261,7 @@ page_header(PG_FUNCTION_ARGS) { char lsnchar[64]; - snprintf(lsnchar, sizeof(lsnchar), "%X/%X", - (uint32) (lsn >> 32), (uint32) lsn); + snprintf(lsnchar, sizeof(lsnchar), LSN_FORMAT, LSN_FORMAT_ARG(lsn)); values[0] = CStringGetTextDatum(lsnchar); } else diff --git a/src/backend/access/rmgrdesc/replorigindesc.c b/src/backend/access/rmgrdesc/replorigindesc.c index 19e14f910b..a3f49b5750 100644 --- a/src/backend/access/rmgrdesc/replorigindesc.c +++ b/src/backend/access/rmgrdesc/replorigindesc.c @@ -29,10 +29,9 @@ replorigin_desc(StringInfo buf, XLogReaderState *record) xlrec = (xl_replorigin_set *) rec; - appendStringInfo(buf, "set %u; lsn %X/%X; force: %d", + appendStringInfo(buf, "set %u; lsn " LSN_FORMAT "; force: %d", xlrec->node_id, - (uint32) (xlrec->remote_lsn >> 32), - (uint32) xlrec->remote_lsn, + LSN_FORMAT_ARG(xlrec->remote_lsn), xlrec->force); break; } diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c index 3200f777f5..22bdae5d9a 100644 --- a/src/backend/access/rmgrdesc/xlogdesc.c +++ b/src/backend/access/rmgrdesc/xlogdesc.c @@ -89,8 +89,7 @@ xlog_desc(StringInfo buf, XLogReaderState *record) XLogRecPtr startpoint; memcpy(&startpoint, rec, sizeof(XLogRecPtr)); - appendStringInfo(buf, "%X/%X", - (uint32) (startpoint >> 32), (uint32) startpoint); + appendStringInfo(buf, LSN_FORMAT, LSN_FORMAT_ARG(startpoint)); } else if (info == XLOG_PARAMETER_CHANGE) { diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 13f1d8c3dc..2436af5244 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -79,6 +79,7 @@ #include "utils/pg_rusage.h" #include "utils/snapmgr.h" #include "utils/timestamp.h" +#include "utils/pg_lsn.h" extern uint32 bootstrap_data_checksum_version; @@ -5886,15 +5887,16 @@ recoveryStopsAfter(XLogReaderState *record) recoveryTargetInclusive && record->ReadRecPtr >= recoveryTargetLSN) { + char buf[MAXPG_LSNLEN + 1]; + recoveryStopAfter = true; recoveryStopXid = InvalidTransactionId; recoveryStopLSN = record->ReadRecPtr; recoveryStopTime = 0; recoveryStopName[0] = '\0'; ereport(LOG, - (errmsg("recovery stopping after WAL location (LSN) \"%X/%X\"", - (uint32) (recoveryStopLSN >> 32), - (uint32) recoveryStopLSN))); + (errmsg("recovery stopping after WAL location (LSN) \"%s\"", + pg_lsn_out_buffer(recoveryStopLSN, buf)))); return true; } diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c index ad0a7bd869..403a20c568 100644 --- a/src/backend/utils/adt/pg_lsn.c +++ b/src/backend/utils/adt/pg_lsn.c @@ -19,7 +19,6 @@ #include "utils/numeric.h" #include "utils/pg_lsn.h" -#define MAXPG_LSNLEN 17 #define MAXPG_LSNCOMPONENT 8 /*---------------------------------------------------------- @@ -81,18 +80,7 @@ Datum pg_lsn_out(PG_FUNCTION_ARGS) { XLogRecPtr lsn = PG_GETARG_LSN(0); - char buf[MAXPG_LSNLEN + 1]; - char *result; - uint32 id, - off; - - /* Decode ID and offset */ - id = (uint32) (lsn >> 32); - off = (uint32) lsn; - - snprintf(buf, sizeof buf, "%X/%X", id, off); - result = pstrdup(buf); - PG_RETURN_CSTRING(result); + PG_RETURN_CSTRING(pg_lsn_out_internal(lsn)); } Datum @@ -317,3 +305,38 @@ pg_lsn_mii(PG_FUNCTION_ARGS) /* Convert to pg_lsn */ return DirectFunctionCall1(numeric_pg_lsn, res); } + +/* + * pg_lsn_out_internal + * + * Returns palloc'ed string representation of an LSN. Used by pg_lsn_out() but + * is useful to print LSN in non-performance critical paths. The caller may + * pfree the returned memory chunk. + */ +char * +pg_lsn_out_internal(XLogRecPtr lsn) +{ + char buf[MAXPG_LSNLEN + 1]; + + snprintf(buf, sizeof(buf), LSN_FORMAT, LSN_FORMAT_ARG(lsn)); + + return pstrdup(buf); +} + +/* + * pg_lsn_out_buffer + * + * Similar to the above function but saves the string representation of LSN in + * the given buffer which is expected to be at least MAXPG_LSNLEN long. It can + * be used in performance critical paths to avoid expensive memory allocation. + * + * The function returns pointer to the input buffer so that it can be used in + * printf variants. + */ +char * +pg_lsn_out_buffer(XLogRecPtr lsn, char *buf) +{ + snprintf(buf, sizeof(buf), LSN_FORMAT, LSN_FORMAT_ARG(lsn)); + + return buf; +} diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h index e1f5812213..c704ca2454 100644 --- a/src/include/access/xlogdefs.h +++ b/src/include/access/xlogdefs.h @@ -35,6 +35,13 @@ typedef uint64 XLogRecPtr; */ #define FirstNormalUnloggedLSN ((XLogRecPtr) 1000) +/* Handy macros to print LSN */ +#define LSN_FORMAT "%X/%X" +#define LSN_FORMAT_ARG(lsn) (uint32) ((lsn) >> 32), (uint32) (lsn) + +/* Maximum length of string representation of an LSN */ +#define MAXPG_LSNLEN 17 + /* * XLogSegNo - physical log file sequence number. */ diff --git a/src/include/utils/pg_lsn.h b/src/include/utils/pg_lsn.h index 25d6c5b38e..7a8637d2bd 100644 --- a/src/include/utils/pg_lsn.h +++ b/src/include/utils/pg_lsn.h @@ -26,4 +26,7 @@ extern XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error); +extern char *pg_lsn_out_internal(XLogRecPtr lsn); +extern char *pg_lsn_out_buffer(XLogRecPtr lsn, char *buf); + #endif /* PG_LSN_H */ -- 2.17.1