]> granicus.if.org Git - postgresql/commitdiff
Move some pg_dump function around.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 27 Mar 2013 16:10:40 +0000 (18:10 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 27 Mar 2013 16:10:40 +0000 (18:10 +0200)
Move functions used only by pg_dump and pg_restore from dumputils.c to a new
file, pg_backup_utils.c. dumputils.c is linked into psql and some programs
in bin/scripts, so it seems good to keep it slim. The parallel functionality
is moved to parallel.c, as is exit_horribly, because the interesting code in
exit_horribly is parallel-related.

This refactoring gets rid of the on_exit_msg_func function pointer. It was
problematic, because a modern gcc version with -Wmissing-format-attribute
complained if it wasn't marked with PF_PRINTF_ATTRIBUTE, but the ancient gcc
version that Tom Lane's old HP-UX box has didn't accept that attribute on a
function pointer, and gave an error. We still use a similar function pointer
trick for getLocalPQBuffer() function, to use a thread-local version of that
in parallel mode on Windows, but that dodges the problem because it doesn't
take printf-like arguments.

19 files changed:
src/bin/pg_dump/Makefile
src/bin/pg_dump/common.c
src/bin/pg_dump/compress_io.c
src/bin/pg_dump/dumputils.c
src/bin/pg_dump/dumputils.h
src/bin/pg_dump/parallel.c
src/bin/pg_dump/parallel.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_backup_custom.c
src/bin/pg_dump/pg_backup_db.c
src/bin/pg_dump/pg_backup_directory.c
src/bin/pg_dump/pg_backup_null.c
src/bin/pg_dump/pg_backup_tar.c
src/bin/pg_dump/pg_backup_utils.c [new file with mode: 0644]
src/bin/pg_dump/pg_backup_utils.h [new file with mode: 0644]
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump_sort.c
src/bin/pg_dump/pg_dumpall.c
src/bin/pg_dump/pg_restore.c

index 6336edc65bd026be960040eb47df3fc51c164657..8dcc702c6929883ac3cdadd3da4e7dc50a360423 100644 (file)
@@ -19,8 +19,8 @@ include $(top_builddir)/src/Makefile.global
 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 parallel.o \
-       pg_backup_directory.o dumputils.o compress_io.o $(WIN32RES)
+       pg_backup_null.o pg_backup_tar.o pg_backup_directory.o \
+       pg_backup_utils.o parallel.o compress_io.o dumputils.o $(WIN32RES)
 
 KEYWRDOBJS = keywords.o kwlookup.o
 
index b8832af250d1b8bcc8140930fd91141baf6f1634..ae52ac11ededabac24c4f471ae439119f2a3f46d 100644 (file)
@@ -14,6 +14,7 @@
  *-------------------------------------------------------------------------
  */
 #include "pg_backup_archiver.h"
+#include "pg_backup_utils.h"
 
 #include <ctype.h>
 
index 0308f66c49f54f717ad1106ddf5bf950ebc67762..1dd31fbe2c640dfb3f42f483d430b21fa405a35b 100644 (file)
@@ -53,7 +53,7 @@
  */
 
 #include "compress_io.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
 #include "parallel.h"
 
 /*----------------------
index 31e56ef7fb524b266e668fda2efbf6b1a8ed0c5c..9c55147c816104210757e09910923b1077b070bf 100644 (file)
 extern const ScanKeyword FEScanKeywords[];
 extern const int NumFEScanKeywords;
 
-/* Globals exported by this file */
-int                    quote_all_identifiers = 0;
-const char *progname = NULL;
-
-#define MAX_ON_EXIT_NICELY                             20
-
-static struct
-{
-       on_exit_nicely_callback function;
-       void       *arg;
-}      on_exit_nicely_list[MAX_ON_EXIT_NICELY];
-
-static int     on_exit_nicely_index;
-void           (*on_exit_msg_func) (const char *modulename, const char *fmt, va_list ap) = vwrite_msg;
-
 #define supports_grant_options(version) ((version) >= 70400)
 
 static bool parseAclItem(const char *item, const char *type,
@@ -49,68 +34,24 @@ static bool parseAclItem(const char *item, const char *type,
 static char *copyAclUserName(PQExpBuffer output, char *input);
 static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
           const char *subname);
-static PQExpBuffer getThreadLocalPQExpBuffer(void);
-
-#ifdef WIN32
-static void shutdown_parallel_dump_utils(int code, void *unused);
-static bool parallel_init_done = false;
-static DWORD tls_index;
-static DWORD mainThreadId;
+static PQExpBuffer defaultGetLocalPQExpBuffer(void);
 
-static void
-shutdown_parallel_dump_utils(int code, void *unused)
-{
-       /* Call the cleanup function only from the main thread */
-       if (mainThreadId == GetCurrentThreadId())
-               WSACleanup();
-}
-#endif
-
-void
-init_parallel_dump_utils(void)
-{
-#ifdef WIN32
-       if (!parallel_init_done)
-       {
-               WSADATA         wsaData;
-               int                     err;
-
-               tls_index = TlsAlloc();
-               mainThreadId = GetCurrentThreadId();
-               err = WSAStartup(MAKEWORD(2, 2), &wsaData);
-               if (err != 0)
-               {
-                       fprintf(stderr, _("WSAStartup failed: %d\n"), err);
-                       exit_nicely(1);
-               }
-               on_exit_nicely(shutdown_parallel_dump_utils, NULL);
-               parallel_init_done = true;
-       }
-#endif
-}
+/* Globals exported by this file */
+int                    quote_all_identifiers = 0;
+PQExpBuffer (*getLocalPQExpBuffer) (void) = defaultGetLocalPQExpBuffer;
 
 /*
- * Non-reentrant but reduces memory leakage. (On Windows the memory leakage
- * will be one buffer per thread, which is at least better than one per call).
+ * Returns a temporary PQExpBuffer, valid until the next call to the function.
+ * This is used by fmtId and fmtQualifiedId.
+ *
+ * Non-reentrant and non-thread-safe but reduces memory leakage. You can
+ * replace this with a custom version by setting the getLocalPQExpBuffer
+ * function pointer.
  */
 static PQExpBuffer
-getThreadLocalPQExpBuffer(void)
+defaultGetLocalPQExpBuffer(void)
 {
-       /*
-        * The Tls code goes awry if we use a static var, so we provide for both
-        * static and auto, and omit any use of the static var when using Tls.
-        */
-       static PQExpBuffer s_id_return = NULL;
-       PQExpBuffer id_return;
-
-#ifdef WIN32
-       if (parallel_init_done)
-               id_return = (PQExpBuffer) TlsGetValue(tls_index);               /* 0 when not set */
-       else
-               id_return = s_id_return;
-#else
-       id_return = s_id_return;
-#endif
+       static PQExpBuffer id_return = NULL;
 
        if (id_return)                          /* first time through? */
        {
@@ -121,15 +62,6 @@ getThreadLocalPQExpBuffer(void)
        {
                /* new buffer */
                id_return = createPQExpBuffer();
-#ifdef WIN32
-               if (parallel_init_done)
-                       TlsSetValue(tls_index, id_return);
-               else
-                       s_id_return = id_return;
-#else
-               s_id_return = id_return;
-#endif
-
        }
 
        return id_return;
@@ -144,7 +76,7 @@ getThreadLocalPQExpBuffer(void)
 const char *
 fmtId(const char *rawid)
 {
-       PQExpBuffer id_return = getThreadLocalPQExpBuffer();
+       PQExpBuffer id_return = getLocalPQExpBuffer();
 
        const char *cp;
        bool            need_quotes = false;
@@ -238,7 +170,7 @@ fmtQualifiedId(int remoteVersion, const char *schema, const char *id)
        }
        appendPQExpBuffer(lcl_pqexp, "%s", fmtId(id));
 
-       id_return = getThreadLocalPQExpBuffer();
+       id_return = getLocalPQExpBuffer();
 
        appendPQExpBuffer(id_return, "%s", lcl_pqexp->data);
        destroyPQExpBuffer(lcl_pqexp);
@@ -1278,118 +1210,6 @@ emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer,
 }
 
 
-/*
- * Parse a --section=foo command line argument.
- *
- * Set or update the bitmask in *dumpSections according to arg.
- * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and
- * pg_restore so they can know if this has even been called.
- */
-void
-set_dump_section(const char *arg, int *dumpSections)
-{
-       /* if this is the first call, clear all the bits */
-       if (*dumpSections == DUMP_UNSECTIONED)
-               *dumpSections = 0;
-
-       if (strcmp(arg, "pre-data") == 0)
-               *dumpSections |= DUMP_PRE_DATA;
-       else if (strcmp(arg, "data") == 0)
-               *dumpSections |= DUMP_DATA;
-       else if (strcmp(arg, "post-data") == 0)
-               *dumpSections |= DUMP_POST_DATA;
-       else
-       {
-               fprintf(stderr, _("%s: unrecognized section name: \"%s\"\n"),
-                               progname, arg);
-               fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
-                               progname);
-               exit_nicely(1);
-       }
-}
-
-
-/*
- * Write a printf-style message to stderr.
- *
- * The program name is prepended, if "progname" has been set.
- * Also, if modulename isn't NULL, that's included too.
- * Note that we'll try to translate the modulename and the fmt string.
- */
-void
-write_msg(const char *modulename, const char *fmt,...)
-{
-       va_list         ap;
-
-       va_start(ap, fmt);
-       vwrite_msg(modulename, fmt, ap);
-       va_end(ap);
-}
-
-/*
- * As write_msg, but pass a va_list not variable arguments.
- */
-void
-vwrite_msg(const char *modulename, const char *fmt, va_list ap)
-{
-       if (progname)
-       {
-               if (modulename)
-                       fprintf(stderr, "%s: [%s] ", progname, _(modulename));
-               else
-                       fprintf(stderr, "%s: ", progname);
-       }
-       vfprintf(stderr, _(fmt), ap);
-}
-
-
-/*
- * Fail and die, with a message to stderr.     Parameters as for write_msg.
- */
-void
-exit_horribly(const char *modulename, const char *fmt,...)
-{
-       va_list         ap;
-
-       va_start(ap, fmt);
-       on_exit_msg_func(modulename, fmt, ap);
-       va_end(ap);
-
-       exit_nicely(1);
-}
-
-/* Register a callback to be run when exit_nicely is invoked. */
-void
-on_exit_nicely(on_exit_nicely_callback function, void *arg)
-{
-       if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
-               exit_horribly(NULL, "out of on_exit_nicely slots\n");
-       on_exit_nicely_list[on_exit_nicely_index].function = function;
-       on_exit_nicely_list[on_exit_nicely_index].arg = arg;
-       on_exit_nicely_index++;
-}
-
-/*
- * Run accumulated on_exit_nicely callbacks in reverse order and then exit
- * quietly.  This needs to be thread-safe.
- */
-void
-exit_nicely(int code)
-{
-       int                     i;
-
-       for (i = on_exit_nicely_index - 1; i >= 0; i--)
-               (*on_exit_nicely_list[i].function) (code,
-                                                                                       on_exit_nicely_list[i].arg);
-
-#ifdef WIN32
-       if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
-               ExitThread(code);
-#endif
-
-       exit(code);
-}
-
 void
 simple_string_list_append(SimpleStringList *list, const char *val)
 {
index 5734c336178d65f5030ff5a0a8bbbc143aacc92e..356e8ebd32daed486c7a7a1af6ee57ec6789d844 100644 (file)
 #include "libpq-fe.h"
 #include "pqexpbuffer.h"
 
-typedef enum                                   /* bits returned by set_dump_section */
-{
-       DUMP_PRE_DATA = 0x01,
-       DUMP_DATA = 0x02,
-       DUMP_POST_DATA = 0x04,
-       DUMP_UNSECTIONED = 0xff
-} DumpSections;
-
 typedef struct SimpleStringListCell
 {
        struct SimpleStringListCell *next;
@@ -40,14 +32,9 @@ typedef struct SimpleStringList
 } SimpleStringList;
 
 
-typedef void (*on_exit_nicely_callback) (int code, void *arg);
-
 extern int     quote_all_identifiers;
-extern const char *progname;
-extern void (*on_exit_msg_func) (const char *modulename, const char *fmt, va_list ap)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
+extern PQExpBuffer (*getLocalPQExpBuffer) (void);
 
-extern void init_parallel_dump_utils(void);
 extern const char *fmtId(const char *identifier);
 extern const char *fmtQualifiedId(int remoteVersion,
                           const char *schema, const char *id);
@@ -79,17 +66,6 @@ extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name,
 extern void emitShSecLabels(PGconn *conn, PGresult *res,
                                PQExpBuffer buffer, const char *target, const char *objname);
 extern void set_dump_section(const char *arg, int *dumpSections);
-extern void
-write_msg(const char *modulename, const char *fmt,...)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
-extern void
-vwrite_msg(const char *modulename, const char *fmt, va_list ap)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
-extern void
-exit_horribly(const char *modulename, const char *fmt,...)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3), noreturn));
-extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
-extern void exit_nicely(int code) __attribute__((noreturn));
 
 extern void simple_string_list_append(SimpleStringList *list, const char *val);
 extern bool simple_string_list_member(SimpleStringList *list, const char *val);
index dedf4311b9efa0566c57ba3453559a4af862d38e..ae0d329ea212ff1284efaafdaba0c32078107093 100644 (file)
@@ -16,9 +16,9 @@
  *-------------------------------------------------------------------------
  */
 
-#include "pg_backup_db.h"
+#include "postgres_fe.h"
 
-#include "dumputils.h"
+#include "pg_backup_utils.h"
 #include "parallel.h"
 
 #ifndef WIN32
@@ -78,10 +78,6 @@ static const char *modulename = gettext_noop("parallel archiver");
 
 static ParallelSlot *GetMyPSlot(ParallelState *pstate);
 static void
-parallel_exit_msg_func(const char *modulename,
-                                          const char *fmt, va_list ap)
-__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
-static void
 parallel_msg_master(ParallelSlot *slot, const char *modulename,
                                        const char *fmt, va_list ap)
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
@@ -112,6 +108,47 @@ static char *readMessageFromPipe(int fd);
 #define messageEquals(msg, pattern) \
        (strcmp(msg, pattern) == 0)
 
+#ifdef WIN32
+static void shutdown_parallel_dump_utils(int code, void *unused);
+bool parallel_init_done = false;
+static DWORD tls_index;
+DWORD mainThreadId;
+#endif
+
+
+#ifdef WIN32
+static void
+shutdown_parallel_dump_utils(int code, void *unused)
+{
+       /* Call the cleanup function only from the main thread */
+       if (mainThreadId == GetCurrentThreadId())
+               WSACleanup();
+}
+#endif
+
+void
+init_parallel_dump_utils(void)
+{
+#ifdef WIN32
+       if (!parallel_init_done)
+       {
+               WSADATA         wsaData;
+               int                     err;
+
+               tls_index = TlsAlloc();
+               mainThreadId = GetCurrentThreadId();
+               err = WSAStartup(MAKEWORD(2, 2), &wsaData);
+               if (err != 0)
+               {
+                       fprintf(stderr, _("WSAStartup failed: %d\n"), err);
+                       exit_nicely(1);
+               }
+               on_exit_nicely(shutdown_parallel_dump_utils, NULL);
+               parallel_init_done = true;
+       }
+#endif
+}
+
 static ParallelSlot *
 GetMyPSlot(ParallelState *pstate)
 {
@@ -129,29 +166,44 @@ GetMyPSlot(ParallelState *pstate)
 }
 
 /*
- * This is the function that will be called from exit_horribly() to print the
- * error message. If the worker process does exit_horribly(), we forward its
+ * Fail and die, with a message to stderr.     Parameters as for write_msg.
+ *
+ * This is defined in parallel.c, because in parallel mode, things are more
+ * complicated. If the worker process does exit_horribly(), we forward its
  * last words to the master process. The master process then does
  * exit_horribly() with this error message itself and prints it normally.
  * After printing the message, exit_horribly() on the master will shut down
  * the remaining worker processes.
  */
-static void
-parallel_exit_msg_func(const char *modulename, const char *fmt, va_list ap)
+void
+exit_horribly(const char *modulename, const char *fmt,...)
 {
+       va_list         ap;
        ParallelState *pstate = shutdown_info.pstate;
        ParallelSlot *slot;
 
-       Assert(pstate);
+       va_start(ap, fmt);
 
-       slot = GetMyPSlot(pstate);
-
-       if (!slot)
-               /* We're the parent, just write the message out */
+       if (pstate == NULL)
+       {
+               /* Not in parallel mode, just write to stderr */
                vwrite_msg(modulename, fmt, ap);
+       }
        else
-               /* If we're a worker process, send the msg to the master process */
-               parallel_msg_master(slot, modulename, fmt, ap);
+       {
+               slot = GetMyPSlot(pstate);
+
+               if (!slot)
+                       /* We're the parent, just write the message out */
+                       vwrite_msg(modulename, fmt, ap);
+               else
+                       /* If we're a worker process, send the msg to the master process */
+                       parallel_msg_master(slot, modulename, fmt, ap);
+       }
+
+       va_end(ap);
+
+       exit_nicely(1);
 }
 
 /* Sends the error message from the worker to the master process */
@@ -172,6 +224,54 @@ parallel_msg_master(ParallelSlot *slot, const char *modulename,
        sendMessageToMaster(pipefd, buf);
 }
 
+/*
+ * A thread-local version of getLocalPQExpBuffer().
+ *
+ * Non-reentrant but reduces memory leakage. (On Windows the memory leakage
+ * will be one buffer per thread, which is at least better than one per call).
+ */
+static PQExpBuffer
+getThreadLocalPQExpBuffer(void)
+{
+       /*
+        * The Tls code goes awry if we use a static var, so we provide for both
+        * static and auto, and omit any use of the static var when using Tls.
+        */
+       static PQExpBuffer s_id_return = NULL;
+       PQExpBuffer id_return;
+
+#ifdef WIN32
+       if (parallel_init_done)
+               id_return = (PQExpBuffer) TlsGetValue(tls_index);               /* 0 when not set */
+       else
+               id_return = s_id_return;
+#else
+       id_return = s_id_return;
+#endif
+
+       if (id_return)                          /* first time through? */
+       {
+               /* same buffer, just wipe contents */
+               resetPQExpBuffer(id_return);
+       }
+       else
+       {
+               /* new buffer */
+               id_return = createPQExpBuffer();
+#ifdef WIN32
+               if (parallel_init_done)
+                       TlsSetValue(tls_index, id_return);
+               else
+                       s_id_return = id_return;
+#else
+               s_id_return = id_return;
+#endif
+
+       }
+
+       return id_return;
+}
+
 /*
  * pg_dump and pg_restore register the Archive pointer for the exit handler
  * (called from exit_horribly). This function mainly exists so that we can
@@ -408,7 +508,7 @@ ParallelBackupStart(ArchiveHandle *AH, RestoreOptions *ropt)
         * set and falls back to AHX otherwise.
         */
        shutdown_info.pstate = pstate;
-       on_exit_msg_func = parallel_exit_msg_func;
+       getLocalPQExpBuffer = getThreadLocalPQExpBuffer;
 
 #ifdef WIN32
        tMasterThreadId = GetCurrentThreadId();
index 7422f12db4e3b83df76707bdec86f54394a2ad6b..a7caa6cdbef98502d109d151797e093bead4d3cd 100644 (file)
@@ -16,6 +16,9 @@
  *-------------------------------------------------------------------------
  */
 
+#ifndef PG_DUMP_PARALLEL_H
+#define PG_DUMP_PARALLEL_H
+
 #include "pg_backup_db.h"
 
 struct _archiveHandle;
@@ -62,6 +65,13 @@ typedef struct ParallelState
        ParallelSlot *parallelSlot;
 } ParallelState;
 
+#ifdef WIN32
+extern bool parallel_init_done;
+extern DWORD mainThreadId;
+#endif
+
+extern void init_parallel_dump_utils(void);
+
 extern int     GetIdleWorker(ParallelState *pstate);
 extern bool IsEveryWorkerIdle(ParallelState *pstate);
 extern void ListenToWorkers(struct _archiveHandle * AH, ParallelState *pstate, bool do_wait);
@@ -77,3 +87,9 @@ extern void DispatchJobForTocEntry(struct _archiveHandle * AH,
 extern void ParallelBackupEnd(struct _archiveHandle * AH, ParallelState *pstate);
 
 extern void checkAborting(struct _archiveHandle * AH);
+
+extern void
+exit_horribly(const char *modulename, const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3), noreturn));
+
+#endif   /* PG_DUMP_PARALLEL_H */
index 39b4f8ecca5909e026a6d50c1b54a967db578854..d202b4222037f843fb1fa429f2ffafbe584a5fe2 100644 (file)
@@ -21,7 +21,7 @@
  */
 
 #include "pg_backup_db.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
 #include "parallel.h"
 
 #include <ctype.h>
index c2e94ca084a3470cd31ccf83da8088ce9b40a472..263bcd3c532afb0bf0064bb6da573b48edb5299a 100644 (file)
@@ -25,8 +25,8 @@
  */
 
 #include "compress_io.h"
-#include "dumputils.h"
 #include "parallel.h"
+#include "pg_backup_utils.h"
 
 /*--------
  * Routines in the format interface
index e16c193e3bedfe405137c53be663aae2aa3068e5..cd2ddedada47205bb49f77c445e3d46276fb6617 100644 (file)
@@ -11,7 +11,9 @@
  */
 
 #include "pg_backup_db.h"
+#include "pg_backup_utils.h"
 #include "dumputils.h"
+#include "parallel.h"
 
 #include <unistd.h>
 #include <ctype.h>
index 66151f584b05a1a656c36a8df48c1709cc5419bc..524bde3d6b77194b50718c9650b20c7e6bbd4ad9 100644 (file)
@@ -34,7 +34,7 @@
  */
 
 #include "compress_io.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
 #include "parallel.h"
 
 #include <dirent.h>
index 6ac81982b8d852ce91e506de4b200a7ce26e4f04..c321068b4efadaa617fbcf427dd94b6f44cc3496 100644 (file)
@@ -23,7 +23,8 @@
  */
 
 #include "pg_backup_archiver.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
+#include "parallel.h"
 
 #include <unistd.h>                            /* for dup */
 
index 6465ac3e6c4df520ccb340879b5a896b89ed3fc3..2358b9d160c44ef67ead4fae7250a549c2092ce0 100644 (file)
@@ -31,7 +31,8 @@
 #include "pg_backup.h"
 #include "pg_backup_archiver.h"
 #include "pg_backup_tar.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
+#include "parallel.h"
 #include "pgtar.h"
 
 #include <sys/stat.h>
diff --git a/src/bin/pg_dump/pg_backup_utils.c b/src/bin/pg_dump/pg_backup_utils.c
new file mode 100644 (file)
index 0000000..dee717c
--- /dev/null
@@ -0,0 +1,126 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_backup_utils.c
+ *     Utility routines shared by pg_dump 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/pg_backup_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include "pg_backup_utils.h"
+#include "parallel.h"
+
+/* Globals exported by this file */
+const char *progname = NULL;
+
+#define MAX_ON_EXIT_NICELY                             20
+
+static struct
+{
+       on_exit_nicely_callback function;
+       void       *arg;
+}      on_exit_nicely_list[MAX_ON_EXIT_NICELY];
+
+static int     on_exit_nicely_index;
+
+/*
+ * Parse a --section=foo command line argument.
+ *
+ * Set or update the bitmask in *dumpSections according to arg.
+ * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and
+ * pg_restore so they can know if this has even been called.
+ */
+void
+set_dump_section(const char *arg, int *dumpSections)
+{
+       /* if this is the first call, clear all the bits */
+       if (*dumpSections == DUMP_UNSECTIONED)
+               *dumpSections = 0;
+
+       if (strcmp(arg, "pre-data") == 0)
+               *dumpSections |= DUMP_PRE_DATA;
+       else if (strcmp(arg, "data") == 0)
+               *dumpSections |= DUMP_DATA;
+       else if (strcmp(arg, "post-data") == 0)
+               *dumpSections |= DUMP_POST_DATA;
+       else
+       {
+               fprintf(stderr, _("%s: unrecognized section name: \"%s\"\n"),
+                               progname, arg);
+               fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+                               progname);
+               exit_nicely(1);
+       }
+}
+
+
+/*
+ * Write a printf-style message to stderr.
+ *
+ * The program name is prepended, if "progname" has been set.
+ * Also, if modulename isn't NULL, that's included too.
+ * Note that we'll try to translate the modulename and the fmt string.
+ */
+void
+write_msg(const char *modulename, const char *fmt,...)
+{
+       va_list         ap;
+
+       va_start(ap, fmt);
+       vwrite_msg(modulename, fmt, ap);
+       va_end(ap);
+}
+
+/*
+ * As write_msg, but pass a va_list not variable arguments.
+ */
+void
+vwrite_msg(const char *modulename, const char *fmt, va_list ap)
+{
+       if (progname)
+       {
+               if (modulename)
+                       fprintf(stderr, "%s: [%s] ", progname, _(modulename));
+               else
+                       fprintf(stderr, "%s: ", progname);
+       }
+       vfprintf(stderr, _(fmt), ap);
+}
+
+/* Register a callback to be run when exit_nicely is invoked. */
+void
+on_exit_nicely(on_exit_nicely_callback function, void *arg)
+{
+       if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
+               exit_horribly(NULL, "out of on_exit_nicely slots\n");
+       on_exit_nicely_list[on_exit_nicely_index].function = function;
+       on_exit_nicely_list[on_exit_nicely_index].arg = arg;
+       on_exit_nicely_index++;
+}
+
+/*
+ * Run accumulated on_exit_nicely callbacks in reverse order and then exit
+ * quietly.  This needs to be thread-safe.
+ */
+void
+exit_nicely(int code)
+{
+       int                     i;
+
+       for (i = on_exit_nicely_index - 1; i >= 0; i--)
+               (*on_exit_nicely_list[i].function) (code,
+                                                                                       on_exit_nicely_list[i].arg);
+
+#ifdef WIN32
+       if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
+               ExitThread(code);
+#endif
+
+       exit(code);
+}
diff --git a/src/bin/pg_dump/pg_backup_utils.h b/src/bin/pg_dump/pg_backup_utils.h
new file mode 100644 (file)
index 0000000..0e31cff
--- /dev/null
@@ -0,0 +1,40 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_backup_utils.h
+ *     Utility routines shared by pg_dump 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/pg_backup_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PG_BACKUP_UTILS_H
+#define PG_BACKUP_UTILS_H
+
+typedef enum                                   /* bits returned by set_dump_section */
+{
+       DUMP_PRE_DATA = 0x01,
+       DUMP_DATA = 0x02,
+       DUMP_POST_DATA = 0x04,
+       DUMP_UNSECTIONED = 0xff
+} DumpSections;
+
+typedef void (*on_exit_nicely_callback) (int code, void *arg);
+
+extern const char *progname;
+
+extern void set_dump_section(const char *arg, int *dumpSections);
+extern void
+write_msg(const char *modulename, const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
+extern void
+vwrite_msg(const char *modulename, const char *fmt, va_list ap)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
+extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
+extern void exit_nicely(int code) __attribute__((noreturn));
+
+#endif   /* PG_BACKUP_UTILS_H */
index e4cf92a1a2c4f1e254901cd6b478f33ee3916661..aa6993a3668707fecb681e1e2c936877e171eeaf 100644 (file)
@@ -59,7 +59,9 @@
 
 #include "pg_backup_archiver.h"
 #include "pg_backup_db.h"
+#include "pg_backup_utils.h"
 #include "dumputils.h"
+#include "parallel.h"
 
 extern char *optarg;
 extern int     optind,
index 8a6d36329df7c8a8007a485d73a957de16b96084..141e71342c7044fb1c1e638f4d24f0c37b5bdba6 100644 (file)
@@ -14,7 +14,8 @@
  *-------------------------------------------------------------------------
  */
 #include "pg_backup_archiver.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
+#include "parallel.h"
 
 /* translator: this is a module name */
 static const char *modulename = gettext_noop("sorter");
index 040cd94e5b5a743e859f8c9b68eb69dd17bff96a..78f702f897309511218b019a7dd99fac9e92b597 100644 (file)
@@ -63,6 +63,7 @@ static PGresult *executeQuery(PGconn *conn, const char *query);
 static void executeCommand(PGconn *conn, const char *query);
 
 static char pg_dump_bin[MAXPGPATH];
+static const char *progname;
 static PQExpBuffer pgdumpopts;
 static char *connstr = "";
 static bool skip_acls = false;
@@ -82,6 +83,7 @@ static int    server_version;
 static FILE *OPF;
 static char *filename = NULL;
 
+#define exit_nicely(code) exit(code)
 
 int
 main(int argc, char *argv[])
index 0cc17fd416e56138c709751f715e3f5463dbf3b9..c585098c72b5f8b9c120bdee79a019e33981782c 100644 (file)
@@ -40,8 +40,9 @@
  */
 
 #include "pg_backup_archiver.h"
-
+#include "pg_backup_utils.h"
 #include "dumputils.h"
+#include "parallel.h"
 
 #include <ctype.h>