From 26aaf97b683d6258c098859e6b1268e1f5da242f Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Tue, 5 Nov 2019 14:56:40 -0800 Subject: [PATCH] Make StringInfo available to frontend code. There's plenty places in frontend code that could benefit from a string buffer implementation. Some because it yields simpler and faster code, and some others because of the desire to share code between backend and frontend. While there is a string buffer implementation available to frontend code, libpq's PQExpBuffer, it is clunkier than stringinfo, it introduces a libpq dependency, doesn't allow for sharing between frontend and backend code, and has a higher API/ABI stability requirement due to being exposed via libpq. Therefore it seems best to just making StringInfo being usable by frontend code. There's not much to do for that, except for rewriting two subsequent elog/ereport calls into others types of error reporting, and deciding on a maximum string length. For the maximum string size I decided to privately define MaxAllocSize to the same value as used in the backend. It seems likely that we'll want to reconsider this for both backend and frontend code in the not too far away future. For now I've left stringinfo.h in lib/, rather than common/, to reduce the likelihood of unnecessary breakage. We could alternatively decide to provide a redirecting stringinfo.h in lib/, or just not provide compatibility. Author: Andres Freund Reviewed-By: Kyotaro Horiguchi, Daniel Gustafsson Discussion: https://postgr.es/m/20190920051857.2fhnvhvx4qdddviz@alap3.anarazel.de --- src/backend/lib/Makefile | 1 - src/bin/pg_waldump/compat.c | 27 -------------- src/bin/pg_waldump/pg_waldump.c | 7 +++- src/common/Makefile | 1 + src/{backend/lib => common}/stringinfo.c | 47 +++++++++++++++++++----- src/include/lib/stringinfo.h | 7 ++-- src/tools/msvc/Mkvcbuild.pm | 2 +- 7 files changed, 49 insertions(+), 43 deletions(-) rename src/{backend/lib => common}/stringinfo.c (86%) diff --git a/src/backend/lib/Makefile b/src/backend/lib/Makefile index dbea67bc37..9dad31398a 100644 --- a/src/backend/lib/Makefile +++ b/src/backend/lib/Makefile @@ -23,6 +23,5 @@ OBJS = \ knapsack.o \ pairingheap.o \ rbtree.o \ - stringinfo.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 7b389a20c9..5db83880fb 100644 --- a/src/bin/pg_waldump/compat.c +++ b/src/bin/pg_waldump/compat.c @@ -20,7 +20,6 @@ #include -#include "lib/stringinfo.h" #include "utils/datetime.h" /* copied from timestamp.c */ @@ -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 8e4bff6aa3..1524e5eb1e 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -514,6 +514,7 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record) int block_id; uint8 info = XLogRecGetInfo(record); XLogRecPtr xl_prev = XLogRecGetPrev(record); + StringInfoData s; XLogDumpRecordLen(record, &rec_len, &fpi_len); @@ -530,8 +531,10 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record) else printf("desc: %s ", id); - /* the desc routine will printf the description directly to stdout */ - desc->rm_desc(NULL, record); + initStringInfo(&s); + desc->rm_desc(&s, record); + printf("%s", s.data); + pfree(s.data); if (!config->bkp_details) { diff --git a/src/common/Makefile b/src/common/Makefile index 4fd487a4ec..ffb0f6edff 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -67,6 +67,7 @@ OBJS_COMMON = \ saslprep.o \ scram-common.o \ string.o \ + stringinfo.o \ unicode_norm.o \ username.o \ wait_error.o diff --git a/src/backend/lib/stringinfo.c b/src/common/stringinfo.c similarity index 86% rename from src/backend/lib/stringinfo.c rename to src/common/stringinfo.c index 99c83c1549..a50e587da9 100644 --- a/src/backend/lib/stringinfo.c +++ b/src/common/stringinfo.c @@ -2,21 +2,34 @@ * * 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 extensible string data type (currently limited to a + * length of 1GB). 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" /* @@ -261,10 +274,10 @@ appendBinaryStringInfoNT(StringInfo str, const char *data, int datalen) * can save some palloc overhead by enlarging the buffer before starting * to store data in it. * - * NB: because we use repalloc() to enlarge the buffer, the string buffer - * will remain allocated in the same memory context that was current when - * initStringInfo was called, even if another context is now current. - * This is the desired and indeed critical behavior! + * NB: In the backend, because we use repalloc() to enlarge the buffer, the + * string buffer will remain allocated in the same memory context that was + * current when initStringInfo was called, even if another context is now + * current. This is the desired and indeed critical behavior! */ void enlargeStringInfo(StringInfo str, int needed) @@ -276,13 +289,29 @@ enlargeStringInfo(StringInfo str, int needed) * an overflow or infinite loop in the following. */ if (needed < 0) /* should not happen */ + { +#ifndef FRONTEND elog(ERROR, "invalid string enlargement request size: %d", needed); +#else + fprintf(stderr, "invalid string enlargement request size: %d\n", needed); + exit(EXIT_FAILURE); +#endif + } if (((Size) needed) >= (MaxAllocSize - (Size) str->len)) + { +#ifndef FRONTEND 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 + fprintf(stderr, + _("out of memory\n\nCannot enlarge string buffer containing %d bytes by %d more bytes.\n"), + str->len, needed); + exit(EXIT_FAILURE); +#endif + } needed += str->len + 1; /* total space required now */ diff --git a/src/include/lib/stringinfo.h b/src/include/lib/stringinfo.h index c4842778c5..e27942728e 100644 --- a/src/include/lib/stringinfo.h +++ b/src/include/lib/stringinfo.h @@ -3,9 +3,10 @@ * stringinfo.h * Declarations/definitions for "StringInfo" functions. * - * 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 extensible string data type (currently limited to a + * length of 1GB). 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 diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 7a103e6140..9a0963a050 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -123,7 +123,7 @@ sub mkvcbuild base64.c config_info.c controldata_utils.c d2s.c exec.c f2s.c file_perm.c ip.c keywords.c kwlookup.c link-canary.c md5.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c - saslprep.c scram-common.c string.c unicode_norm.c username.c + saslprep.c scram-common.c string.c stringinfo.c unicode_norm.c username.c wait_error.c); if ($solution->{options}->{openssl})