Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pg_backup_utils.c
4 : * Utility routines shared by pg_dump and pg_restore
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * src/bin/pg_dump/pg_backup_utils.c
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #include "postgres_fe.h"
15 :
16 : #include "parallel.h"
17 : #include "pg_backup_utils.h"
18 :
19 : /* Globals exported by this file */
20 : const char *progname = NULL;
21 :
22 : #define MAX_ON_EXIT_NICELY 20
23 :
24 : static struct
25 : {
26 : on_exit_nicely_callback function;
27 : void *arg;
28 : } on_exit_nicely_list[MAX_ON_EXIT_NICELY];
29 :
30 : static int on_exit_nicely_index;
31 :
32 : /*
33 : * Parse a --section=foo command line argument.
34 : *
35 : * Set or update the bitmask in *dumpSections according to arg.
36 : * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and
37 : * pg_restore so they can know if this has even been called.
38 : */
39 : void
3665 heikki.linnakangas 40 CBC 6 : set_dump_section(const char *arg, int *dumpSections)
41 : {
42 : /* if this is the first call, clear all the bits */
43 6 : if (*dumpSections == DUMP_UNSECTIONED)
44 6 : *dumpSections = 0;
45 :
46 6 : if (strcmp(arg, "pre-data") == 0)
47 2 : *dumpSections |= DUMP_PRE_DATA;
48 4 : else if (strcmp(arg, "data") == 0)
49 2 : *dumpSections |= DUMP_DATA;
50 2 : else if (strcmp(arg, "post-data") == 0)
51 2 : *dumpSections |= DUMP_POST_DATA;
52 : else
53 : {
1469 peter 54 UBC 0 : pg_log_error("unrecognized section name: \"%s\"", arg);
366 tgl 55 0 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
3665 heikki.linnakangas 56 0 : exit_nicely(1);
57 : }
3665 heikki.linnakangas 58 CBC 6 : }
59 :
60 :
61 : /* Register a callback to be run when exit_nicely is invoked. */
62 : void
63 163 : on_exit_nicely(on_exit_nicely_callback function, void *arg)
64 : {
65 163 : if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
366 tgl 66 UBC 0 : pg_fatal("out of on_exit_nicely slots");
3665 heikki.linnakangas 67 CBC 163 : on_exit_nicely_list[on_exit_nicely_index].function = function;
68 163 : on_exit_nicely_list[on_exit_nicely_index].arg = arg;
69 163 : on_exit_nicely_index++;
70 163 : }
71 :
72 : /*
73 : * Run accumulated on_exit_nicely callbacks in reverse order and then exit
74 : * without printing any message.
75 : *
76 : * If running in a parallel worker thread on Windows, we only exit the thread,
77 : * not the whole process.
78 : *
79 : * Note that in parallel operation on Windows, the callback(s) will be run
80 : * by each thread since the list state is necessarily shared by all threads;
81 : * each callback must contain logic to ensure it does only what's appropriate
82 : * for its thread. On Unix, callbacks are also run by each process, but only
83 : * for callbacks established before we fork off the child processes. (It'd
84 : * be cleaner to reset the list after fork(), and let each child establish
85 : * its own callbacks; but then the behavior would be completely inconsistent
86 : * between Windows and Unix. For now, just be sure to establish callbacks
87 : * before forking to avoid inconsistency.)
88 : */
89 : void
90 193 : exit_nicely(int code)
91 : {
92 : int i;
93 :
94 323 : for (i = on_exit_nicely_index - 1; i >= 0; i--)
2040 peter_e 95 130 : on_exit_nicely_list[i].function(code,
96 : on_exit_nicely_list[i].arg);
97 :
98 : #ifdef WIN32
99 : if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
100 : _endthreadex(code);
101 : #endif
102 :
3665 heikki.linnakangas 103 193 : exit(code);
104 : }
|