diff options
Diffstat (limited to 'src/bin/pg_dump/pg_backup_utils.c')
-rw-r--r-- | src/bin/pg_dump/pg_backup_utils.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/bin/pg_dump/pg_backup_utils.c b/src/bin/pg_dump/pg_backup_utils.c new file mode 100644 index 0000000..c709a40 --- /dev/null +++ b/src/bin/pg_dump/pg_backup_utils.c @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_utils.c + * Utility routines shared by pg_dump and pg_restore + * + * + * Portions Copyright (c) 1996-2021, 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 "parallel.h" +#include "pg_backup_utils.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 + { + pg_log_error("unrecognized section name: \"%s\"", arg); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + 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) + { + pg_log_fatal("out of on_exit_nicely slots"); + exit_nicely(1); + } + 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 + * without printing any message. + * + * If running in a parallel worker thread on Windows, we only exit the thread, + * not the whole process. + * + * Note that in parallel operation on Windows, the callback(s) will be run + * by each thread since the list state is necessarily shared by all threads; + * each callback must contain logic to ensure it does only what's appropriate + * for its thread. On Unix, callbacks are also run by each process, but only + * for callbacks established before we fork off the child processes. (It'd + * be cleaner to reset the list after fork(), and let each child establish + * its own callbacks; but then the behavior would be completely inconsistent + * between Windows and Unix. For now, just be sure to establish callbacks + * before forking to avoid inconsistency.) + */ +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) + _endthreadex(code); +#endif + + exit(code); +} |