WIP: Move stringinfo to common/
authorAndres Freund <andres@anarazel.de>
Thu, 19 Sep 2019 18:57:50 +0000 (11:57 -0700)
committerAndres Freund <andres@anarazel.de>
Fri, 20 Sep 2019 03:17:26 +0000 (20:17 -0700)
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:

src/backend/lib/Makefile
src/bin/pg_waldump/compat.c
src/bin/pg_waldump/pg_waldump.c
src/common/Makefile
src/common/stringinfo.c [moved from src/backend/lib/stringinfo.c with 88% similarity]

index 3c1ee1df83abccc3619f69d0023655a3f336f1fb..9a0c508e9082c873ced63eb1f43e2538cc06d71a 100644 (file)
@@ -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
index 0e0dca7d1ad28f632c327a1eedd78e9c980cce7e..5db83880fb78a163a764e374450292d845724339 100644 (file)
@@ -21,7 +21,6 @@
 #include <time.h>
 
 #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);
-}
index b95d467805a99c8d5e28fcdd58a8b81b8842f670..2379e77090d2dd0b2d2ceed8c79b7ceaebf5ce3b 100644 (file)
@@ -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);
 }
 
 /*
index e88370901ae176e3d953aff3b27472cc59e12fd5..dfc143258ed81b339b5290382935b5f6aa727421 100644 (file)
@@ -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
similarity index 88%
rename from src/backend/lib/stringinfo.c
rename to src/common/stringinfo.c
index 99c83c1549c5c2873ba966516bd9a2474e22f102..d4f52850e52e83055cd36fba4bbd1486b6145012 100644 (file)
@@ -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 */