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
*-------------------------------------------------------------------------
*/
#include "pg_backup_archiver.h"
+#include "pg_backup_utils.h"
#include <ctype.h>
*/
#include "compress_io.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
#include "parallel.h"
/*----------------------
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,
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? */
{
{
/* 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;
const char *
fmtId(const char *rawid)
{
- PQExpBuffer id_return = getThreadLocalPQExpBuffer();
+ PQExpBuffer id_return = getLocalPQExpBuffer();
const char *cp;
bool need_quotes = false;
}
appendPQExpBuffer(lcl_pqexp, "%s", fmtId(id));
- id_return = getThreadLocalPQExpBuffer();
+ id_return = getLocalPQExpBuffer();
appendPQExpBuffer(id_return, "%s", lcl_pqexp->data);
destroyPQExpBuffer(lcl_pqexp);
}
-/*
- * 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)
{
#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;
} 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);
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);
*-------------------------------------------------------------------------
*/
-#include "pg_backup_db.h"
+#include "postgres_fe.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
#include "parallel.h"
#ifndef WIN32
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)));
#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)
{
}
/*
- * 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 */
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
* 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();
*-------------------------------------------------------------------------
*/
+#ifndef PG_DUMP_PARALLEL_H
+#define PG_DUMP_PARALLEL_H
+
#include "pg_backup_db.h"
struct _archiveHandle;
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);
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 */
*/
#include "pg_backup_db.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
#include "parallel.h"
#include <ctype.h>
*/
#include "compress_io.h"
-#include "dumputils.h"
#include "parallel.h"
+#include "pg_backup_utils.h"
/*--------
* Routines in the format interface
*/
#include "pg_backup_db.h"
+#include "pg_backup_utils.h"
#include "dumputils.h"
+#include "parallel.h"
#include <unistd.h>
#include <ctype.h>
*/
#include "compress_io.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
#include "parallel.h"
#include <dirent.h>
*/
#include "pg_backup_archiver.h"
-#include "dumputils.h"
+#include "pg_backup_utils.h"
+#include "parallel.h"
#include <unistd.h> /* for dup */
#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>
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * 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);
+}
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * 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 */
#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,
*-------------------------------------------------------------------------
*/
#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");
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;
static FILE *OPF;
static char *filename = NULL;
+#define exit_nicely(code) exit(code)
int
main(int argc, char *argv[])
*/
#include "pg_backup_archiver.h"
-
+#include "pg_backup_utils.h"
#include "dumputils.h"
+#include "parallel.h"
#include <ctype.h>