Create libpgcommon, and move pg_malloc et al to it

libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines.  We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.

The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.

At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly.  To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc().  This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.

This lets us clean up some places that were already with
localized hacks.

Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that.  libpgcommon infrastructure was authored by Álvaro.
This commit is contained in:
Alvaro Herrera 2013-02-12 10:33:40 -03:00
parent 0cb1fac3b1
commit 8396447cdb
59 changed files with 332 additions and 684 deletions

View File

@ -50,9 +50,6 @@ struct options
/* function prototypes */
static void help(const char *progname);
void get_opts(int, char **, struct options *);
void *pg_malloc(size_t size);
void *pg_realloc(void *ptr, size_t size);
char *pg_strdup(const char *str);
void add_one_elt(char *eltname, eary *eary);
char *get_comma_elts(eary *eary);
PGconn *sql_conn(struct options *);
@ -201,53 +198,6 @@ help(const char *progname)
progname, progname);
}
void *
pg_malloc(size_t size)
{
void *ptr;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
ptr = malloc(size);
if (!ptr)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
return ptr;
}
void *
pg_realloc(void *ptr, size_t size)
{
void *result;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
result = realloc(ptr, size);
if (!result)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
return result;
}
char *
pg_strdup(const char *str)
{
char *result = strdup(str);
if (!result)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
return result;
}
/*
* add_one_elt
*

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/check.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/controldata.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/dump.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/exec.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/file.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/function.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/info.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/option.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "miscadmin.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/page.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/parallel.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -35,7 +35,7 @@
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -451,10 +451,6 @@ void
prep_status(const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
void check_ok(void);
char *pg_strdup(const char *s);
void *pg_malloc(size_t size);
void *pg_realloc(void *ptr, size_t size);
void pg_free(void *ptr);
const char *getErrorText(int errNum);
unsigned int str2uint(const char *str);
void pg_putenv(const char *var, const char *val);

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/relfilenode.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/server.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/tablespace.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/util.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"
@ -213,55 +213,6 @@ get_user_info(char **user_name)
}
void *
pg_malloc(size_t size)
{
void *p;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
p = malloc(size);
if (p == NULL)
pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
return p;
}
void *
pg_realloc(void *ptr, size_t size)
{
void *p;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
p = realloc(ptr, size);
if (p == NULL)
pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
return p;
}
void
pg_free(void *ptr)
{
if (ptr != NULL)
free(ptr);
}
char *
pg_strdup(const char *s)
{
char *result = strdup(s);
if (result == NULL)
pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
return result;
}
/*
* getErrorText()
*

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/version.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -7,7 +7,7 @@
* contrib/pg_upgrade/version_old_8_3.c
*/
#include "postgres.h"
#include "postgres_fe.h"
#include "pg_upgrade.h"

View File

@ -320,59 +320,6 @@ static char *select_only = {
static void setalarm(int seconds);
static void *threadRun(void *arg);
/*
* routines to check mem allocations and fail noisily.
*/
static void *
pg_malloc(size_t size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
return result;
}
static void *
pg_realloc(void *ptr, size_t size)
{
void *result;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
result = realloc(ptr, size);
if (!result)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
return result;
}
static char *
pg_strdup(const char *s)
{
char *result;
result = strdup(s);
if (!result)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
return result;
}
static void
usage(void)
{

View File

@ -13,6 +13,7 @@ top_builddir = ..
include Makefile.global
SUBDIRS = \
common \
port \
timezone \
backend \

View File

@ -243,14 +243,15 @@ LD = @LD@
with_gnu_ld = @with_gnu_ld@
ld_R_works = @ld_R_works@
# We want -L for libpgport.a to be first in LDFLAGS. We also need LDFLAGS
# to be a "recursively expanded" variable, else adjustments to rpathdir
# don't work right. So we must NOT do LDFLAGS := something, meaning this has
# to be done first and elsewhere we must only do LDFLAGS += something.
# We want -L for libpgport.a and libpgcommon.a to be first in LDFLAGS. We
# also need LDFLAGS to be a "recursively expanded" variable, else adjustments
# to rpathdir don't work right. So we must NOT do LDFLAGS := something,
# meaning this has to be done first and elsewhere we must only do LDFLAGS +=
# something.
ifdef PGXS
LDFLAGS = -L$(libdir)
else
LDFLAGS = -L$(top_builddir)/src/port
LDFLAGS = -L$(top_builddir)/src/port -L$(top_builddir)/src/common
endif
LDFLAGS += @LDFLAGS@
@ -400,16 +401,17 @@ endif
libpq = -L$(libpq_builddir) -lpq
# This macro is for use by client executables (not libraries) that use libpq.
# We force clients to pull symbols from the non-shared library libpgport
# rather than pulling some libpgport symbols from libpq just because
# libpq uses those functions too. This makes applications less
# We force clients to pull symbols from the non-shared libraries libpgport
# and libpgcommon rather than pulling some libpgport symbols from libpq just
# because libpq uses those functions too. This makes applications less
# dependent on changes in libpq's usage of pgport. To do this we link to
# pgport before libpq. This does cause duplicate -lpgport's to appear
# on client link lines.
ifdef PGXS
libpq_pgport = -L$(libdir) -lpgport $(libpq)
libpq_pgport = -L$(libdir) -lpgport -lpgcommon $(libpq)
else
libpq_pgport = -L$(top_builddir)/src/port -lpgport $(libpq)
libpq_pgport = -L$(top_builddir)/src/port -lpgport \
-L$(top_builddir)/src/common -lpgcommon $(libpq)
endif
@ -418,6 +420,7 @@ submake-libpq:
submake-libpgport:
$(MAKE) -C $(top_builddir)/src/port all
$(MAKE) -C $(top_builddir)/src/common all
.PHONY: submake-libpq submake-libpgport
@ -496,7 +499,7 @@ endif
LIBOBJS = @LIBOBJS@
LIBS := -lpgport $(LIBS)
LIBS := -lpgport -lpgcommon $(LIBS)
# to make ws2_32.lib the last library, and always link with shfolder,
# so SHGetFolderName isn't picked up from shell32.dll

View File

@ -26,17 +26,6 @@
#include "storage/fd.h"
#include "miscadmin.h"
/*
* On Windows, call non-macro versions of palloc; we can't reference
* CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
*/
#if defined(WIN32) || defined(__CYGWIN__)
#undef palloc
#undef pstrdup
#define palloc(sz) pgport_palloc(sz)
#define pstrdup(str) pgport_pstrdup(str)
#endif
static void fsync_fname(char *fname, bool isdir);

View File

@ -634,6 +634,42 @@ MemoryContextAllocZeroAligned(MemoryContext context, Size size)
return ret;
}
void *
palloc(Size size)
{
/* duplicates MemoryContextAlloc to avoid increased overhead */
AssertArg(MemoryContextIsValid(CurrentMemoryContext));
if (!AllocSizeIsValid(size))
elog(ERROR, "invalid memory alloc request size %lu",
(unsigned long) size);
CurrentMemoryContext->isReset = false;
return (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
}
void *
palloc0(Size size)
{
/* duplicates MemoryContextAllocZero to avoid increased overhead */
void *ret;
AssertArg(MemoryContextIsValid(CurrentMemoryContext));
if (!AllocSizeIsValid(size))
elog(ERROR, "invalid memory alloc request size %lu",
(unsigned long) size);
CurrentMemoryContext->isReset = false;
ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
MemSetAligned(ret, 0, size);
return ret;
}
/*
* pfree
* Release an allocated chunk.
@ -715,6 +751,12 @@ MemoryContextStrdup(MemoryContext context, const char *string)
return nstr;
}
char *
pstrdup(const char *in)
{
return MemoryContextStrdup(CurrentMemoryContext, in);
}
/*
* pnstrdup
* Like pstrdup(), but append null byte to a
@ -729,39 +771,3 @@ pnstrdup(const char *in, Size len)
out[len] = '\0';
return out;
}
#if defined(WIN32) || defined(__CYGWIN__)
/*
* Memory support routines for libpgport on Win32
*
* Win32 can't load a library that PGDLLIMPORTs a variable
* if the link object files also PGDLLIMPORT the same variable.
* For this reason, libpgport can't reference CurrentMemoryContext
* in the palloc macro calls.
*
* To fix this, we create several functions here that allow us to
* manage memory without doing the inline in libpgport.
*/
void *
pgport_palloc(Size sz)
{
return palloc(sz);
}
char *
pgport_pstrdup(const char *str)
{
return pstrdup(str);
}
/* Doesn't reference a PGDLLIMPORT variable, but here for completeness. */
void
pgport_pfree(void *pointer)
{
pfree(pointer);
}
#endif

View File

@ -200,8 +200,6 @@ const char *subdirs[] = {
static char bin_path[MAXPGPATH];
static char backend_exec[MAXPGPATH];
static void *pg_malloc(size_t size);
static char *pg_strdup(const char *s);
static char **replace_token(char **lines,
const char *token, const char *replacement);
@ -317,43 +315,6 @@ do { \
#define DIR_SEP "\\"
#endif
/*
* routines to check mem allocations and fail noisily.
*
* Note that we can't call exit_nicely() on a memory failure, as it calls
* rmtree() which needs memory allocation. So we just exit with a bang.
*/
static void *
pg_malloc(size_t size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
exit(1);
}
return result;
}
static char *
pg_strdup(const char *s)
{
char *result;
result = strdup(s);
if (!result)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
exit(1);
}
return result;
}
static char *
escape_quotes(const char *src)
{

View File

@ -25,43 +25,6 @@ int dbgetpassword = 0; /* 0=auto, -1=never, 1=always */
static char *dbpassword = NULL;
PGconn *conn = NULL;
/*
* strdup() and malloc() replacements that print an error and exit
* if something goes wrong. Can never return NULL.
*/
char *
pg_strdup(const char *s)
{
char *result;
result = strdup(s);
if (!result)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
exit(1);
}
return result;
}
void *
pg_malloc0(size_t size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
exit(1);
}
MemSet(result, 0, size);
return result;
}
/*
* Connect to the server. Returns a valid PGconn pointer if connected,
* or NULL on non-permanent error. On permanent error, the function will

View File

@ -15,8 +15,4 @@ extern PGconn *conn;
exit(code); \
}
extern char *pg_strdup(const char *s);
extern void *pg_malloc0(size_t size);
extern PGconn *GetConnection(void);

View File

@ -118,8 +118,6 @@ write_stderr(const char *fmt,...)
/* This extension allows gcc to check the format string for consistency with
the supplied arguments. */
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
static void *pg_malloc(size_t size);
static char *pg_strdup(const char *s);
static void do_advice(void);
static void do_help(void);
static void set_mode(char *modeopt);
@ -225,42 +223,6 @@ write_stderr(const char *fmt,...)
va_end(ap);
}
/*
* routines to check memory allocations and fail noisily.
*/
static void *
pg_malloc(size_t size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{
write_stderr(_("%s: out of memory\n"), progname);
exit(1);
}
return result;
}
static char *
pg_strdup(const char *s)
{
char *result;
result = strdup(s);
if (!result)
{
write_stderr(_("%s: out of memory\n"), progname);
exit(1);
}
return result;
}
/*
* Given an already-localized string, print it to stdout unless the
* user has specified that no messages should be printed.

View File

@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
OBJS= pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
pg_backup_null.o pg_backup_tar.o \
pg_backup_directory.o dumpmem.o dumputils.o compress_io.o $(WIN32RES)
pg_backup_directory.o dumputils.o compress_io.o $(WIN32RES)
KEYWRDOBJS = keywords.o kwlookup.o
@ -35,8 +35,8 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq
pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
$(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
pg_dumpall: pg_dumpall.o dumputils.o dumpmem.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
$(CC) $(CFLAGS) pg_dumpall.o dumputils.o dumpmem.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
pg_dumpall: pg_dumpall.o dumputils.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
$(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
install: all installdirs
$(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X)

View File

@ -18,8 +18,6 @@
#include <ctype.h>
#include "catalog/pg_class.h"
#include "dumpmem.h"
#include "dumputils.h"
/*

View File

@ -53,7 +53,6 @@
*/
#include "compress_io.h"
#include "dumpmem.h"
#include "dumputils.h"
/*----------------------

View File

@ -1,76 +0,0 @@
/*-------------------------------------------------------------------------
*
* dumpmem.c
* Memory allocation routines used by pg_dump, pg_dumpall, and pg_restore
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/bin/pg_dump/dumpmem.c
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include "dumputils.h"
#include "dumpmem.h"
/*
* Safer versions of some standard C library functions. If an
* out-of-memory condition occurs, these functions will bail out via exit();
*therefore, their return value is guaranteed to be non-NULL.
*/
char *
pg_strdup(const char *string)
{
char *tmp;
if (!string)
exit_horribly(NULL, "cannot duplicate null pointer\n");
tmp = strdup(string);
if (!tmp)
exit_horribly(NULL, "out of memory\n");
return tmp;
}
void *
pg_malloc(size_t size)
{
void *tmp;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
tmp = malloc(size);
if (!tmp)
exit_horribly(NULL, "out of memory\n");
return tmp;
}
void *
pg_malloc0(size_t size)
{
void *tmp;
tmp = pg_malloc(size);
MemSet(tmp, 0, size);
return tmp;
}
void *
pg_realloc(void *ptr, size_t size)
{
void *tmp;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
tmp = realloc(ptr, size);
if (!tmp)
exit_horribly(NULL, "out of memory\n");
return tmp;
}

View File

@ -1,22 +0,0 @@
/*-------------------------------------------------------------------------
*
* dumpmem.h
* Memory allocation routines used by pg_dump, pg_dumpall, and pg_restore
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/bin/pg_dump/dumpmem.h
*
*-------------------------------------------------------------------------
*/
#ifndef DUMPMEM_H
#define DUMPMEM_H
extern char *pg_strdup(const char *string);
extern void *pg_malloc(size_t size);
extern void *pg_malloc0(size_t size);
extern void *pg_realloc(void *ptr, size_t size);
#endif /* DUMPMEM_H */

View File

@ -17,7 +17,6 @@
#include <ctype.h>
#include "dumputils.h"
#include "dumpmem.h"
#include "parser/keywords.h"

View File

@ -3,7 +3,7 @@ CATALOG_NAME = pg_dump
AVAIL_LANGUAGES = de es fr it ja ko pt_BR sv tr zh_CN zh_TW
GETTEXT_FILES = pg_backup_archiver.c pg_backup_db.c pg_backup_custom.c \
pg_backup_null.c pg_backup_tar.c \
pg_backup_directory.c dumpmem.c dumputils.c compress_io.c \
pg_backup_directory.c dumputils.c compress_io.c \
pg_dump.c common.c pg_dump_sort.c \
pg_restore.c pg_dumpall.c \
../../port/exec.c

View File

@ -21,7 +21,6 @@
*/
#include "pg_backup_db.h"
#include "dumpmem.h"
#include "dumputils.h"
#include <ctype.h>

View File

@ -26,7 +26,6 @@
#include "compress_io.h"
#include "dumputils.h"
#include "dumpmem.h"
/*--------
* Routines in the format interface

View File

@ -11,7 +11,6 @@
*/
#include "pg_backup_db.h"
#include "dumpmem.h"
#include "dumputils.h"
#include <unistd.h>

View File

@ -34,7 +34,6 @@
*/
#include "compress_io.h"
#include "dumpmem.h"
#include "dumputils.h"
#include <dirent.h>

View File

@ -23,7 +23,6 @@
*/
#include "pg_backup_archiver.h"
#include "dumpmem.h"
#include "dumputils.h"
#include <unistd.h> /* for dup */

View File

@ -31,7 +31,6 @@
#include "pg_backup.h"
#include "pg_backup_archiver.h"
#include "pg_backup_tar.h"
#include "dumpmem.h"
#include "dumputils.h"
#include "pgtar.h"

View File

@ -59,7 +59,6 @@
#include "pg_backup_archiver.h"
#include "pg_backup_db.h"
#include "dumpmem.h"
#include "dumputils.h"
extern char *optarg;

View File

@ -15,7 +15,6 @@
*/
#include "pg_backup_archiver.h"
#include "dumputils.h"
#include "dumpmem.h"
/* translator: this is a module name */
static const char *modulename = gettext_noop("sorter");

View File

@ -25,7 +25,6 @@
#include "getopt_long.h"
#include "dumputils.h"
#include "dumpmem.h"
#include "pg_backup.h"
/* version string we expect back from pg_dump */

View File

@ -41,7 +41,6 @@
#include "pg_backup_archiver.h"
#include "dumpmem.h"
#include "dumputils.h"
#include <ctype.h>

View File

@ -54,6 +54,7 @@
#include "access/xlog_internal.h"
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "common/fe_memutils.h"
extern int optind;
extern char *optarg;
@ -420,7 +421,7 @@ ReadControlFile(void)
}
/* Use malloc to ensure we have a maxaligned buffer */
buffer = (char *) malloc(PG_CONTROL_SIZE);
buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
len = read(fd, buffer, PG_CONTROL_SIZE);
if (len < 0)
@ -942,7 +943,7 @@ WriteEmptyXLOG(void)
int nbytes;
/* Use malloc() to ensure buffer is MAXALIGNED */
buffer = (char *) malloc(XLOG_BLCKSZ);
buffer = (char *) pg_malloc(XLOG_BLCKSZ);
page = (XLogPageHeader) buffer;
memset(buffer, 0, XLOG_BLCKSZ);

View File

@ -32,56 +32,6 @@ static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec);
static bool command_no_begin(const char *query);
static bool is_select_command(const char *query);
/*
* "Safe" wrapper around strdup()
*/
char *
pg_strdup(const char *string)
{
char *tmp;
if (!string)
{
psql_error("%s: pg_strdup: cannot duplicate null pointer (internal error)\n",
pset.progname);
exit(EXIT_FAILURE);
}
tmp = strdup(string);
if (!tmp)
{
psql_error("out of memory\n");
exit(EXIT_FAILURE);
}
return tmp;
}
void *
pg_malloc(size_t size)
{
void *tmp;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
tmp = malloc(size);
if (!tmp)
{
psql_error("out of memory\n");
exit(EXIT_FAILURE);
}
return tmp;
}
void *
pg_malloc0(size_t size)
{
void *tmp;
tmp = pg_malloc(size);
MemSet(tmp, 0, size);
return tmp;
}
/*
* setQFout
* -- handler for -o command line option and \o command

View File

@ -14,15 +14,6 @@
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
/*
* Safer versions of some standard C library functions. If an
* out-of-memory condition occurs, these functions will bail out
* safely; therefore, their return value is guaranteed to be non-NULL.
*/
extern char *pg_strdup(const char *string);
extern void *pg_malloc(size_t size);
extern void *pg_malloc0(size_t size);
extern bool setQFout(const char *fname);
extern void

View File

@ -277,55 +277,6 @@ executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
return r;
}
/*
* "Safe" wrapper around strdup(). Pulled from psql/common.c
*/
char *
pg_strdup(const char *string)
{
char *tmp;
if (!string)
{
fprintf(stderr, _("pg_strdup: cannot duplicate null pointer (internal error)\n"));
exit(EXIT_FAILURE);
}
tmp = strdup(string);
if (!tmp)
{
fprintf(stderr, _("out of memory\n"));
exit(EXIT_FAILURE);
}
return tmp;
}
void *
pg_malloc(size_t size)
{
void *tmp;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
tmp = malloc(size);
if (!tmp)
{
fprintf(stderr, _("out of memory\n"));
exit(EXIT_FAILURE);
}
return tmp;
}
void *
pg_malloc0(size_t size)
{
void *tmp;
tmp = pg_malloc(size);
MemSet(tmp, 0, size);
return tmp;
}
/*
* Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
*/

View File

@ -50,8 +50,4 @@ extern bool yesno_prompt(const char *question);
extern void setup_cancel_handler(void);
extern char *pg_strdup(const char *string);
extern void *pg_malloc(size_t size);
extern void *pg_malloc0(size_t size);
#endif /* COMMON_H */

64
src/common/Makefile Normal file
View File

@ -0,0 +1,64 @@
#-------------------------------------------------------------------------
#
# Makefile
# Makefile for src/common
#
# This makefile generates two outputs:
#
# libpgcommon.a - contains object files with FRONTEND defined,
# for use by client application and libraries
#
# libpgcommon_srv.a - contains object files without FRONTEND defined,
# for use only by the backend binaries
#
# IDENTIFICATION
# src/common/Makefile
#
#-------------------------------------------------------------------------
subdir = src/common
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -DFRONTEND $(CPPFLAGS)
LIBS += $(PTHREAD_LIBS)
OBJS_COMMON =
OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o
OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o)
all: libpgcommon.a libpgcommon_srv.a
# libpgcommon is needed by some contrib
install: all installdirs
$(INSTALL_STLIB) libpgcommon.a '$(DESTDIR)$(libdir)/libpgcommon.a'
installdirs:
$(MKDIR_P) '$(DESTDIR)$(libdir)'
uninstall:
rm -f '$(DESTDIR)$(libdir)/libpgcommon.a'
libpgcommon.a: $(OBJS_FRONTEND)
$(AR) $(AROPT) $@ $^
#
# Server versions of object files
#
libpgcommon_srv.a: $(OBJS_SRV)
$(AR) $(AROPT) $@ $^
# Because this uses its own compilation rule, it doesn't use the
# dependency tracking logic from Makefile.global. To make sure that
# dependency tracking works anyway for the *_srv.o files, depend on
# their *.o siblings as well, which do have proper dependencies. It's
# a hack that might fail someday if there is a *_srv.o without a
# corresponding *.o, but it works for now.
%_srv.o: %.c %.o
$(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@
clean distclean maintainer-clean:
rm -f libpgcommon.a libpgcommon_srv.a $(OBJS_FRONTEND) $(OBJS_SRV)

128
src/common/fe_memutils.c Normal file
View File

@ -0,0 +1,128 @@
/*-------------------------------------------------------------------------
*
* fe_memutils.c
* memory management support for frontend code
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/common/fe_memutils.c
*
*-------------------------------------------------------------------------
*/
#ifndef FRONTEND
#error "This file is not expected to be compiled for backend code"
#endif
#include "postgres_fe.h"
void *
pg_malloc(size_t size)
{
void *tmp;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
tmp = malloc(size);
if (!tmp)
{
fprintf(stderr, _("out of memory\n"));
exit(EXIT_FAILURE);
}
return tmp;
}
void *
pg_malloc0(size_t size)
{
void *tmp;
tmp = pg_malloc(size);
MemSet(tmp, 0, size);
return tmp;
}
void *
pg_realloc(void *ptr, size_t size)
{
void *tmp;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
tmp = realloc(ptr, size);
if (!tmp)
{
fprintf(stderr, _("out of memory\n"));
exit(EXIT_FAILURE);
}
return tmp;
}
/*
* "Safe" wrapper around strdup().
*/
char *
pg_strdup(const char *string)
{
char *tmp;
if (!string)
{
fprintf(stderr,
_("cannot duplicate null pointer (internal error)\n"));
exit(EXIT_FAILURE);
}
tmp = strdup(string);
if (!tmp)
{
fprintf(stderr, _("out of memory\n"));
exit(EXIT_FAILURE);
}
return tmp;
}
void
pg_free(void *ptr)
{
if (ptr != NULL)
free(ptr);
}
/*
* Frontend emulation of backend memory management functions. Useful for
* programs that compile backend files.
*/
void *
palloc(Size size)
{
return pg_malloc(size);
}
void *
palloc0(Size size)
{
return pg_malloc0(size);
}
void
pfree(void *pointer)
{
pg_free(pointer);
}
char *
pstrdup(const char *string)
{
return pg_strdup(string);
}
void *
repalloc(void *pointer, Size size)
{
return pg_realloc(pointer, size);
}

View File

@ -0,0 +1,20 @@
/*
* fe_memutils.h
* memory management support for frontend code
*
* Copyright (c) 2003-2013, PostgreSQL Global Development Group
*
* src/include/common/fe_memutils.h
*/
#ifndef FE_MEMUTILS_H
#define FE_MEMUTILS_H
extern char *pg_strdup(const char *string);
extern void *pg_malloc(size_t size);
extern void *pg_malloc0(size_t size);
extern void *pg_realloc(void *pointer, size_t size);
extern void pg_free(void *pointer);
#include "utils/palloc.h"
#endif /* FE_MEMUTILS_H */

View File

@ -24,4 +24,6 @@
#include "c.h"
#include "common/fe_memutils.h"
#endif /* POSTGRES_FE_H */

View File

@ -28,6 +28,8 @@
#ifndef PALLOC_H
#define PALLOC_H
#ifndef FRONTEND
/*
* Type MemoryContextData is declared in nodes/memnodes.h. Most users
* of memory allocation should just treat it as an abstract type, so we
@ -49,10 +51,6 @@ extern void *MemoryContextAlloc(MemoryContext context, Size size);
extern void *MemoryContextAllocZero(MemoryContext context, Size size);
extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
#define palloc(sz) MemoryContextAlloc(CurrentMemoryContext, (sz))
#define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz))
/*
* The result of palloc() is always word-aligned, so we can skip testing
* alignment of the pointer when deciding which MemSet variant to use.
@ -66,20 +64,11 @@ extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \
MemoryContextAllocZero(CurrentMemoryContext, sz) )
extern void pfree(void *pointer);
extern void *repalloc(void *pointer, Size size);
/*
* MemoryContextSwitchTo can't be a macro in standard C compilers.
* But we can make it an inline function if the compiler supports it.
* See STATIC_IF_INLINE in c.h.
*
* This file has to be includable by some non-backend code such as
* pg_resetxlog, so don't expose the CurrentMemoryContext reference
* if FRONTEND is defined.
*/
#ifndef FRONTEND
#ifndef PG_USE_INLINE
extern MemoryContext MemoryContextSwitchTo(MemoryContext context);
@ -94,22 +83,19 @@ MemoryContextSwitchTo(MemoryContext context)
return old;
}
#endif /* PG_USE_INLINE || MCXT_INCLUDE_DEFINITIONS */
#endif /* !FRONTEND */
/*
* These are like standard strdup() except the copied string is
* allocated in a context, not with malloc().
*/
extern char *MemoryContextStrdup(MemoryContext context, const char *string);
#endif /* !FRONTEND */
#define pstrdup(str) MemoryContextStrdup(CurrentMemoryContext, (str))
extern char *pstrdup(const char *in);
extern char *pnstrdup(const char *in, Size len);
#if defined(WIN32) || defined(__CYGWIN__)
extern void *pgport_palloc(Size sz);
extern char *pgport_pstrdup(const char *str);
extern void pgport_pfree(void *pointer);
#endif
extern void *palloc(Size size);
extern void *palloc0(Size size);
extern void pfree(void *pointer);
extern void *repalloc(void *pointer, Size size);
#endif /* PALLOC_H */

View File

@ -40,80 +40,6 @@
#endif
#endif
#ifndef FRONTEND
/*
* On Windows, call non-macro versions of palloc; we can't reference
* CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
*/
#if defined(WIN32) || defined(__CYGWIN__)
#undef palloc
#undef pstrdup
#define palloc(sz) pgport_palloc(sz)
#define pstrdup(str) pgport_pstrdup(str)
#endif
#else /* FRONTEND */
/*
* In frontend, fake palloc behavior with these
*/
#undef palloc
#undef pstrdup
#define palloc(sz) fe_palloc(sz)
#define pstrdup(str) fe_pstrdup(str)
#define repalloc(pointer,sz) fe_repalloc(pointer,sz)
#define pfree(pointer) free(pointer)
static void *
fe_palloc(Size size)
{
void *res;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
res = malloc(size);
if (res == NULL)
{
fprintf(stderr, _("out of memory\n"));
exit(1);
}
return res;
}
static char *
fe_pstrdup(const char *string)
{
char *res;
if ((res = strdup(string)) == NULL)
{
fprintf(stderr, _("out of memory\n"));
exit(1);
}
return res;
}
static void *
fe_repalloc(void *pointer, Size size)
{
void *res;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (pointer == NULL && size == 0)
size = 1;
res = realloc(pointer, size);
if (res == NULL)
{
fprintf(stderr, _("out of memory\n"));
exit(1);
}
return res;
}
#endif /* FRONTEND */
#if defined(WIN32) || defined(__CYGWIN__)
/*

View File

@ -86,6 +86,7 @@ sub Install
'Import libraries', $target . '/lib/',
"$conf\\", "postgres\\postgres.lib",
"libpq\\libpq.lib", "libecpg\\libecpg.lib",
"libpgcommon\\libpgcommon.lib",
"libpgport\\libpgport.lib", "libpgtypes\\libpgtypes.lib",
"libecpg_compat\\libecpg_compat.lib");
CopySetOfFiles(

View File

@ -24,6 +24,7 @@ our (@ISA, @EXPORT_OK);
my $solution;
my $libpgport;
my $libpgcommon;
my $postgres;
my $libpq;
@ -35,6 +36,11 @@ my @contrib_uselibpgport = (
'pg_standby', 'pg_archivecleanup',
'pg_test_fsync', 'pg_test_timing',
'pg_upgrade', 'vacuumlo');
my @contrib_uselibpgcommon = (
'oid2name', 'pgbench',
'pg_standby', 'pg_archivecleanup',
'pg_test_fsync', 'pg_test_timing',
'pg_upgrade', 'vacuumlo');
my $contrib_extralibs = { 'pgbench' => ['wsock32.lib'] };
my $contrib_extraincludes =
{ 'tsearch2' => ['contrib/tsearch2'], 'dblink' => ['src/backend'] };
@ -63,10 +69,19 @@ sub mkvcbuild
sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c rint.c win32env.c
win32error.c win32setlocale.c);
our @pgcommonfiles = qw(
fe_memutils.c);
our @pgcommonbkndfiles = qw();
$libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
$libpgport->AddDefine('FRONTEND');
$libpgport->AddFiles('src\port', @pgportfiles);
$libpgcommon = $solution->AddProject('libpgcommon', 'lib', 'misc');
$libpgcommon->AddDefine('FRONTEND');
$libpgcommon->AddFiles('src\common', @pgcommonfiles);
$postgres = $solution->AddProject('postgres', 'exe', '', 'src\backend');
$postgres->AddIncludeDir('src\backend');
$postgres->AddDir('src\backend\port\win32');
@ -81,6 +96,7 @@ sub mkvcbuild
$postgres->ReplaceFile('src\backend\port\pg_latch.c',
'src\backend\port\win32_latch.c');
$postgres->AddFiles('src\port', @pgportfiles);
$postgres->AddFiles('src\common', @pgcommonbkndfiles);
$postgres->AddDir('src\timezone');
$postgres->AddFiles('src\backend\parser', 'scan.l', 'gram.y');
$postgres->AddFiles('src\backend\bootstrap', 'bootscanner.l',
@ -297,7 +313,7 @@ sub mkvcbuild
$ecpg->AddDefine('MINOR_VERSION=9');
$ecpg->AddDefine('PATCHLEVEL=0');
$ecpg->AddDefine('ECPG_COMPILE');
$ecpg->AddReference($libpgport);
$ecpg->AddReference($libpgport, $libpgcommon);
my $pgregress_ecpg =
$solution->AddProject('pg_regress_ecpg', 'exe', 'misc');
@ -307,7 +323,7 @@ sub mkvcbuild
$pgregress_ecpg->AddIncludeDir('src\test\regress');
$pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
$pgregress_ecpg->AddDefine('FRONTEND');
$pgregress_ecpg->AddReference($libpgport);
$pgregress_ecpg->AddReference($libpgport, $libpgcommon);
my $isolation_tester =
$solution->AddProject('isolationtester', 'exe', 'misc');
@ -332,7 +348,7 @@ sub mkvcbuild
$pgregress_isolation->AddIncludeDir('src\test\regress');
$pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
$pgregress_isolation->AddDefine('FRONTEND');
$pgregress_isolation->AddReference($libpgport);
$pgregress_isolation->AddReference($libpgport, $libpgcommon);
# src/bin
my $initdb = AddSimpleFrontend('initdb');
@ -393,7 +409,6 @@ sub mkvcbuild
$pgdumpall->AddIncludeDir('src\backend');
$pgdumpall->AddFile('src\bin\pg_dump\pg_dumpall.c');
$pgdumpall->AddFile('src\bin\pg_dump\dumputils.c');
$pgdumpall->AddFile('src\bin\pg_dump\dumpmem.c');
$pgdumpall->AddFile('src\bin\pg_dump\keywords.c');
$pgdumpall->AddFile('src\backend\parser\kwlookup.c');
@ -407,7 +422,7 @@ sub mkvcbuild
my $zic = $solution->AddProject('zic', 'exe', 'utils');
$zic->AddFiles('src\timezone', 'zic.c', 'ialloc.c', 'scheck.c',
'localtime.c');
$zic->AddReference($libpgport);
$zic->AddReference($libpgport, $libpgcommon);
if ($solution->{options}->{xml})
{
@ -547,7 +562,7 @@ sub mkvcbuild
$proj->AddIncludeDir('src\interfaces\libpq');
$proj->AddIncludeDir('src\bin\pg_dump');
$proj->AddIncludeDir('src\bin\psql');
$proj->AddReference($libpq, $libpgport);
$proj->AddReference($libpq, $libpgport, $libpgcommon);
$proj->AddResourceFile('src\bin\scripts', 'PostgreSQL Utility');
}
@ -561,7 +576,7 @@ sub mkvcbuild
$pgregress->AddFile('src\test\regress\pg_regress_main.c');
$pgregress->AddIncludeDir('src\port');
$pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
$pgregress->AddReference($libpgport);
$pgregress->AddReference($libpgport, $libpgcommon);
$solution->Save();
return $solution->{vcver};
@ -579,7 +594,7 @@ sub AddSimpleFrontend
my $p = $solution->AddProject($n, 'exe', 'bin');
$p->AddDir('src\bin\\' . $n);
$p->AddReference($libpgport);
$p->AddReference($libpgport, $libpgcommon);
if ($uselibpq)
{
$p->AddIncludeDir('src\interfaces\libpq');
@ -730,6 +745,10 @@ sub AdjustContribProj
{
$proj->AddReference($libpgport);
}
if (grep { /^$n$/ } @contrib_uselibpgcommon)
{
$proj->AddReference($libpgcommon);
}
if ($contrib_extralibs->{$n})
{
foreach my $l (@{ $contrib_extralibs->{$n} })

View File

@ -225,7 +225,7 @@ sub AddDir
if ($filter eq "LIBOBJS")
{
if (grep(/$p/, @main::pgportfiles) == 1)
if (grep(/$p/, @main::pgportfiles, @main::pgcommonfiles) == 1)
{
$p =~ s/\.c/\.o/;
$matches .= $p . " ";