postgresql/src/bin/pg_dump/parallel.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

86 lines
2.3 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* parallel.h
*
* Parallel support for pg_dump and pg_restore
*
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* src/bin/pg_dump/parallel.h
*
*-------------------------------------------------------------------------
*/
#ifndef PG_DUMP_PARALLEL_H
#define PG_DUMP_PARALLEL_H
#include <limits.h>
#include "pg_backup_archiver.h"
/* Function to call in leader process on completion of a worker task */
typedef void (*ParallelCompletionPtr) (ArchiveHandle *AH,
TocEntry *te,
int status,
void *callback_data);
/* Wait options for WaitForWorkers */
typedef enum
{
WFW_NO_WAIT,
WFW_GOT_STATUS,
WFW_ONE_IDLE,
WFW_ALL_IDLE
} WFW_WaitOption;
/*
* Maximum number of parallel jobs allowed.
*
* On Windows we can only have at most MAXIMUM_WAIT_OBJECTS (= 64 usually)
* parallel jobs because that's the maximum limit for the
* WaitForMultipleObjects() call.
*/
#ifdef WIN32
#define PG_MAX_JOBS MAXIMUM_WAIT_OBJECTS
#else
#define PG_MAX_JOBS INT_MAX
#endif
/* ParallelSlot is an opaque struct known only within parallel.c */
typedef struct ParallelSlot ParallelSlot;
/* Overall state for parallel.c */
typedef struct ParallelState
{
int numWorkers; /* allowed number of workers */
/* these arrays have numWorkers entries, one per worker: */
TocEntry **te; /* item being worked on, or NULL */
ParallelSlot *parallelSlot; /* private info about each worker */
} ParallelState;
#ifdef WIN32
extern bool parallel_init_done;
extern DWORD mainThreadId;
#endif
extern void init_parallel_dump_utils(void);
extern bool IsEveryWorkerIdle(ParallelState *pstate);
extern void WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate,
WFW_WaitOption mode);
extern ParallelState *ParallelBackupStart(ArchiveHandle *AH);
extern void DispatchJobForTocEntry(ArchiveHandle *AH,
ParallelState *pstate,
TocEntry *te,
T_Action act,
ParallelCompletionPtr callback,
void *callback_data);
extern void ParallelBackupEnd(ArchiveHandle *AH, ParallelState *pstate);
Redesign handling of SIGTERM/control-C in parallel pg_dump/pg_restore. Formerly, Unix builds of pg_dump/pg_restore would trap SIGINT and similar signals and set a flag that was tested in various data-transfer loops. This was prone to errors of omission (cf commit 3c8aa6654); and even if the client-side response was prompt, we did nothing that would cause long-running SQL commands (e.g. CREATE INDEX) to terminate early. Also, the master process would effectively do nothing at all upon receipt of SIGINT; the only reason it seemed to work was that in typical scenarios the signal would also be delivered to the child processes. We should support termination when a signal is delivered only to the master process, though. Windows builds had no console interrupt handler, so they would just fall over immediately at control-C, again leaving long-running SQL commands to finish unmolested. To fix, remove the flag-checking approach altogether. Instead, allow the Unix signal handler to send a cancel request directly and then exit(1). In the master process, also have it forward the signal to the children. On Windows, add a console interrupt handler that behaves approximately the same. The main difference is that a single execution of the Windows handler can send all the cancel requests since all the info is available in one process, whereas on Unix each process sends a cancel only for its own database connection. In passing, fix an old problem that DisconnectDatabase tends to send a cancel request before exiting a parallel worker, even if nothing went wrong. This is at least a waste of cycles, and could lead to unexpected log messages, or maybe even data loss if it happened in pg_restore (though in the current code the problem seems to affect only pg_dump). The cause was that after a COPY step, pg_dump was leaving libpq in PGASYNC_BUSY state, causing PQtransactionStatus() to report PQTRANS_ACTIVE. That's normally harmless because the next PQexec() will silently clear the PGASYNC_BUSY state; but in a parallel worker we might exit without any additional SQL commands after a COPY step. So add an extra PQgetResult() call after a COPY to allow libpq to return to PGASYNC_IDLE state. This is a bug fix, IMO, so back-patch to 9.3 where parallel dump/restore were introduced. Thanks to Kyotaro Horiguchi for Windows testing and code suggestions. Original-Patch: <7005.1464657274@sss.pgh.pa.us> Discussion: <20160602.174941.256342236.horiguchi.kyotaro@lab.ntt.co.jp>
2016-06-02 19:27:53 +02:00
extern void set_archive_cancel_info(ArchiveHandle *AH, PGconn *conn);
#endif /* PG_DUMP_PARALLEL_H */