1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-29 10:41:53 +03:00

Move some pg_dump function around.

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.
This commit is contained in:
Heikki Linnakangas
2013-03-27 18:10:40 +02:00
parent 1cea9bbb21
commit 7800a71291
19 changed files with 336 additions and 247 deletions

View File

@ -25,21 +25,6 @@
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);
static PQExpBuffer defaultGetLocalPQExpBuffer(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 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)
{