int block_id;
uint8 info = XLogRecGetInfo(record);
XLogRecPtr xl_prev = XLogRecGetPrev(record);
+ StringInfoData str;
+
+ initStringInfo(&str);
XLogDumpRecordLen(record, &rec_len, &fpi_len);
if (id == NULL)
id = psprintf("UNKNOWN (%x)", info & ~XLR_INFO_MASK);
- printf("rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, ",
- desc->rm_name,
- rec_len, XLogRecGetTotalLen(record),
- XLogRecGetXid(record),
- (uint32) (record->ReadRecPtr >> 32), (uint32) record->ReadRecPtr,
- (uint32) (xl_prev >> 32), (uint32) xl_prev);
- printf("desc: %s ", id);
+ appendStringInfo(&str,
+ "rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, ",
+ desc->rm_name,
+ rec_len, XLogRecGetTotalLen(record),
+ XLogRecGetXid(record),
+ (uint32) (record->ReadRecPtr >> 32), (uint32) record->ReadRecPtr,
+ (uint32) (xl_prev >> 32), (uint32) xl_prev);
+ appendStringInfo(&str, "desc: %s ", id);
- /* the desc routine will printf the description directly to stdout */
- desc->rm_desc(NULL, record);
+ desc->rm_desc(&str, record);
if (!config->bkp_details)
{
XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blk);
if (forknum != MAIN_FORKNUM)
- printf(", blkref #%u: rel %u/%u/%u fork %s blk %u",
- block_id,
- rnode.spcNode, rnode.dbNode, rnode.relNode,
- forkNames[forknum],
- blk);
+ appendStringInfo(&str,
+ ", blkref #%u: rel %u/%u/%u fork %s blk %u",
+ block_id,
+ rnode.spcNode, rnode.dbNode, rnode.relNode,
+ forkNames[forknum],
+ blk);
else
- printf(", blkref #%u: rel %u/%u/%u blk %u",
- block_id,
- rnode.spcNode, rnode.dbNode, rnode.relNode,
- blk);
+ appendStringInfo(&str,
+ ", blkref #%u: rel %u/%u/%u blk %u",
+ block_id,
+ rnode.spcNode, rnode.dbNode, rnode.relNode,
+ blk);
if (XLogRecHasBlockImage(record, block_id))
{
if (XLogRecBlockImageApply(record, block_id))
- printf(" FPW");
+ appendStringInfoString(&str, " FPW");
else
- printf(" FPW for WAL verification");
+ appendStringInfoString(&str, " FPW for WAL verification");
}
}
- putchar('\n');
+ appendStringInfoChar(&str, '\n');
}
else
{
/* print block references (detailed format) */
- putchar('\n');
+ appendStringInfoChar(&str, '\n');
for (block_id = 0; block_id <= record->max_block_id; block_id++)
{
if (!XLogRecHasBlockRef(record, block_id))
continue;
XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blk);
- printf("\tblkref #%u: rel %u/%u/%u fork %s blk %u",
- block_id,
- rnode.spcNode, rnode.dbNode, rnode.relNode,
- forkNames[forknum],
- blk);
+ appendStringInfo(&str,
+ "\tblkref #%u: rel %u/%u/%u fork %s blk %u",
+ block_id,
+ rnode.spcNode, rnode.dbNode, rnode.relNode,
+ forkNames[forknum],
+ blk);
if (XLogRecHasBlockImage(record, block_id))
{
if (record->blocks[block_id].bimg_info &
BKPIMAGE_IS_COMPRESSED)
{
- printf(" (FPW%s); hole: offset: %u, length: %u, "
- "compression saved: %u\n",
- XLogRecBlockImageApply(record, block_id) ?
- "" : " for WAL verification",
- record->blocks[block_id].hole_offset,
- record->blocks[block_id].hole_length,
- BLCKSZ -
- record->blocks[block_id].hole_length -
- record->blocks[block_id].bimg_len);
+ appendStringInfo(&str,
+ " (FPW%s); hole: offset: %u, length: %u, "
+ "compression saved: %u\n",
+ XLogRecBlockImageApply(record, block_id) ?
+ "" : " for WAL verification",
+ record->blocks[block_id].hole_offset,
+ record->blocks[block_id].hole_length,
+ BLCKSZ -
+ record->blocks[block_id].hole_length -
+ record->blocks[block_id].bimg_len);
}
else
{
- printf(" (FPW%s); hole: offset: %u, length: %u\n",
- XLogRecBlockImageApply(record, block_id) ?
- "" : " for WAL verification",
- record->blocks[block_id].hole_offset,
- record->blocks[block_id].hole_length);
+ appendStringInfo(&str,
+ " (FPW%s); hole: offset: %u, length: %u\n",
+ XLogRecBlockImageApply(record, block_id) ?
+ "" : " for WAL verification",
+ record->blocks[block_id].hole_offset,
+ record->blocks[block_id].hole_length);
}
}
- putchar('\n');
}
}
+
+ printf("%s", str.data);
+ free(str.data);
}
/*
*
* stringinfo.c
*
- * StringInfo provides an indefinitely-extensible string data type.
- * It can be used to buffer either ordinary C strings (null-terminated text)
- * or arbitrary binary data. All storage is allocated with palloc().
+ * StringInfo provides an indefinitely-extensible string data type. It can be
+ * used to buffer either ordinary C strings (null-terminated text) or
+ * arbitrary binary data. All storage is allocated with palloc() (falling
+ * back to malloc in frontend code).
*
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * src/backend/lib/stringinfo.c
+ * src/common/stringinfo.c
*
*-------------------------------------------------------------------------
*/
+
+
+#ifndef FRONTEND
+
#include "postgres.h"
+#include "utils/memutils.h"
+
+#else
+
+#include "postgres_fe.h"
+
+/* It's possible we could use a different value for this in frontend code */
+#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
+
+#endif
#include "lib/stringinfo.h"
-#include "utils/memutils.h"
/*
* Guard against out-of-range "needed" values. Without this, we can get
* an overflow or infinite loop in the following.
*/
- if (needed < 0) /* should not happen */
+#ifndef FRONTEND
+ if (unlikely(needed < 0)) /* should not happen */
elog(ERROR, "invalid string enlargement request size: %d", needed);
- if (((Size) needed) >= (MaxAllocSize - (Size) str->len))
+ if (unlikely(((Size) needed) >= (MaxAllocSize - (Size) str->len)))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("out of memory"),
errdetail("Cannot enlarge string buffer containing %d bytes by %d more bytes.",
str->len, needed)));
+#else
+ if (unlikely(needed < 0)) /* should not happen */
+ {
+ fprintf(stderr, "invalid string enlargement request size: %d", needed);
+ exit(EXIT_FAILURE);
+ }
+ if (unlikely(((Size) needed) >= (MaxAllocSize - (Size) str->len)))
+ {
+ fprintf(stderr,
+ _("out of memory\n\nCannot enlarge string buffer containing %d bytes by %d more bytes."),
+ str->len, needed);
+ exit(EXIT_FAILURE);
+ }
+#endif
needed += str->len + 1; /* total space required now */