From: Andres Freund Date: Thu, 19 Sep 2019 18:57:50 +0000 (-0700) Subject: WIP: Move stringinfo to common/ X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=7f20f9d809e6bd6ab34ba51aa914ad75b8e5c46d;p=users%2Fandresfreund%2Fpostgres.git WIP: Move stringinfo to common/ TODO: - header still in lib/, there's a lot of includes. Move anyway/ - Reconsider MaxAllocSize - cleanup Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- diff --git a/src/backend/lib/Makefile b/src/backend/lib/Makefile index 3c1ee1df83..9a0c508e90 100644 --- a/src/backend/lib/Makefile +++ b/src/backend/lib/Makefile @@ -13,6 +13,6 @@ top_builddir = ../../.. include $(top_builddir)/src/Makefile.global OBJS = binaryheap.o bipartite_match.o bloomfilter.o dshash.o hyperloglog.o \ - ilist.o integerset.o knapsack.o pairingheap.o rbtree.o stringinfo.o + ilist.o integerset.o knapsack.o pairingheap.o rbtree.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/bin/pg_waldump/compat.c b/src/bin/pg_waldump/compat.c index 0e0dca7d1a..5db83880fb 100644 --- a/src/bin/pg_waldump/compat.c +++ b/src/bin/pg_waldump/compat.c @@ -21,7 +21,6 @@ #include #include "utils/datetime.h" -#include "lib/stringinfo.h" /* copied from timestamp.c */ pg_time_t @@ -63,29 +62,3 @@ timestamptz_to_str(TimestampTz dt) return buf; } - -/* - * Provide a hacked up compat layer for StringInfos so xlog desc functions can - * be linked/called. - */ -void -appendStringInfo(StringInfo str, const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); -} - -void -appendStringInfoString(StringInfo str, const char *string) -{ - appendStringInfo(str, "%s", string); -} - -void -appendStringInfoChar(StringInfo str, char ch) -{ - appendStringInfo(str, "%c", ch); -} diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index b95d467805..2379e77090 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -530,6 +530,9 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record) int block_id; uint8 info = XLogRecGetInfo(record); XLogRecPtr xl_prev = XLogRecGetPrev(record); + StringInfoData str; + + initStringInfo(&str); XLogDumpRecordLen(record, &rec_len, &fpi_len); @@ -537,16 +540,16 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record) 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) { @@ -558,68 +561,75 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record) 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); } /* diff --git a/src/common/Makefile b/src/common/Makefile index e88370901a..dfc143258e 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -49,8 +49,8 @@ LIBS += $(PTHREAD_LIBS) OBJS_COMMON = base64.o config_info.o controldata_utils.o d2s.o exec.o f2s.o \ file_perm.o ip.o keywords.o kwlookup.o link-canary.o md5.o \ pgarr.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \ - rmtree.o saslprep.o scram-common.o string.o unicode_norm.o \ - username.o wait_error.o + rmtree.o saslprep.o scram-common.o string.o stringinfo.o \ + unicode_norm.o username.o wait_error.o ifeq ($(with_openssl),yes) OBJS_COMMON += sha2_openssl.o diff --git a/src/backend/lib/stringinfo.c b/src/common/stringinfo.c similarity index 88% rename from src/backend/lib/stringinfo.c rename to src/common/stringinfo.c index 99c83c1549..d4f52850e5 100644 --- a/src/backend/lib/stringinfo.c +++ b/src/common/stringinfo.c @@ -2,21 +2,35 @@ * * 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" /* @@ -275,14 +289,29 @@ enlargeStringInfo(StringInfo str, int needed) * 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 */