115
115
#include "postmaster/syslogger.h"
116
116
#include "postmaster/walsummarizer.h"
117
117
#include "replication/logicallauncher.h"
118
+ #include "replication/slotsync.h"
118
119
#include "replication/walsender.h"
119
120
#include "storage/fd.h"
120
121
#include "storage/ipc.h"
167
168
* they will never become live backends. dead_end children are not assigned a
168
169
* PMChildSlot. dead_end children have bkend_type NORMAL.
169
170
*
170
- * "Special" children such as the startup, bgwriter and autovacuum launcher
171
- * tasks are not in this list. They are tracked via StartupPID and other
172
- * pid_t variables below. (Thus, there can't be more than one of any given
173
- * "special" child process type. We use BackendList entries for any child
174
- * process there can be more than one of.)
171
+ * "Special" children such as the startup, bgwriter, autovacuum launcher, and
172
+ * slot sync worker tasks are not in this list. They are tracked via StartupPID
173
+ * and other pid_t variables below. (Thus, there can't be more than one of any
174
+ * given "special" child process type. We use BackendList entries for any
175
+ * child process there can be more than one of.)
175
176
*/
176
177
typedef struct bkend
177
178
{
@@ -254,7 +255,8 @@ static pid_t StartupPID = 0,
254
255
WalSummarizerPID = 0 ,
255
256
AutoVacPID = 0 ,
256
257
PgArchPID = 0 ,
257
- SysLoggerPID = 0 ;
258
+ SysLoggerPID = 0 ,
259
+ SlotSyncWorkerPID = 0 ;
258
260
259
261
/* Startup process's status */
260
262
typedef enum
@@ -445,6 +447,7 @@ static void StartAutovacuumWorker(void);
445
447
static void MaybeStartWalReceiver (void );
446
448
static void MaybeStartWalSummarizer (void );
447
449
static void InitPostmasterDeathWatchHandle (void );
450
+ static void MaybeStartSlotSyncWorker (void );
448
451
449
452
/*
450
453
* Archiver is allowed to start up at the current postmaster state?
@@ -1822,6 +1825,9 @@ ServerLoop(void)
1822
1825
if (PgArchPID == 0 && PgArchStartupAllowed ())
1823
1826
PgArchPID = StartChildProcess (ArchiverProcess );
1824
1827
1828
+ /* If we need to start a slot sync worker, try to do that now */
1829
+ MaybeStartSlotSyncWorker ();
1830
+
1825
1831
/* If we need to signal the autovacuum launcher, do so now */
1826
1832
if (avlauncher_needs_signal )
1827
1833
{
@@ -2661,6 +2667,8 @@ process_pm_reload_request(void)
2661
2667
signal_child (PgArchPID , SIGHUP );
2662
2668
if (SysLoggerPID != 0 )
2663
2669
signal_child (SysLoggerPID , SIGHUP );
2670
+ if (SlotSyncWorkerPID != 0 )
2671
+ signal_child (SlotSyncWorkerPID , SIGHUP );
2664
2672
2665
2673
/* Reload authentication config files too */
2666
2674
if (!load_hba ())
@@ -3010,6 +3018,7 @@ process_pm_child_exit(void)
3010
3018
AutoVacPID = StartAutoVacLauncher ();
3011
3019
if (PgArchStartupAllowed () && PgArchPID == 0 )
3012
3020
PgArchPID = StartChildProcess (ArchiverProcess );
3021
+ MaybeStartSlotSyncWorker ();
3013
3022
3014
3023
/* workers may be scheduled to start now */
3015
3024
maybe_start_bgworkers ();
@@ -3180,6 +3189,22 @@ process_pm_child_exit(void)
3180
3189
continue ;
3181
3190
}
3182
3191
3192
+ /*
3193
+ * Was it the slot sync worker? Normal exit or FATAL exit can be
3194
+ * ignored (FATAL can be caused by libpqwalreceiver on receiving
3195
+ * shutdown request by the startup process during promotion); we'll
3196
+ * start a new one at the next iteration of the postmaster's main
3197
+ * loop, if necessary. Any other exit condition is treated as a crash.
3198
+ */
3199
+ if (pid == SlotSyncWorkerPID )
3200
+ {
3201
+ SlotSyncWorkerPID = 0 ;
3202
+ if (!EXIT_STATUS_0 (exitstatus ) && !EXIT_STATUS_1 (exitstatus ))
3203
+ HandleChildCrash (pid , exitstatus ,
3204
+ _ ("slot sync worker process" ));
3205
+ continue ;
3206
+ }
3207
+
3183
3208
/* Was it one of our background workers? */
3184
3209
if (CleanupBackgroundWorker (pid , exitstatus ))
3185
3210
{
@@ -3384,7 +3409,7 @@ CleanupBackend(int pid,
3384
3409
3385
3410
/*
3386
3411
* HandleChildCrash -- cleanup after failed backend, bgwriter, checkpointer,
3387
- * walwriter, autovacuum, archiver or background worker.
3412
+ * walwriter, autovacuum, archiver, slot sync worker, or background worker.
3388
3413
*
3389
3414
* The objectives here are to clean up our local state about the child
3390
3415
* process, and to signal all other remaining children to quickdie.
@@ -3546,6 +3571,12 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
3546
3571
else if (PgArchPID != 0 && take_action )
3547
3572
sigquit_child (PgArchPID );
3548
3573
3574
+ /* Take care of the slot sync worker too */
3575
+ if (pid == SlotSyncWorkerPID )
3576
+ SlotSyncWorkerPID = 0 ;
3577
+ else if (SlotSyncWorkerPID != 0 && take_action )
3578
+ sigquit_child (SlotSyncWorkerPID );
3579
+
3549
3580
/* We do NOT restart the syslogger */
3550
3581
3551
3582
if (Shutdown != ImmediateShutdown )
@@ -3686,6 +3717,8 @@ PostmasterStateMachine(void)
3686
3717
signal_child (WalReceiverPID , SIGTERM );
3687
3718
if (WalSummarizerPID != 0 )
3688
3719
signal_child (WalSummarizerPID , SIGTERM );
3720
+ if (SlotSyncWorkerPID != 0 )
3721
+ signal_child (SlotSyncWorkerPID , SIGTERM );
3689
3722
/* checkpointer, archiver, stats, and syslogger may continue for now */
3690
3723
3691
3724
/* Now transition to PM_WAIT_BACKENDS state to wait for them to die */
@@ -3701,13 +3734,13 @@ PostmasterStateMachine(void)
3701
3734
/*
3702
3735
* PM_WAIT_BACKENDS state ends when we have no regular backends
3703
3736
* (including autovac workers), no bgworkers (including unconnected
3704
- * ones), and no walwriter, autovac launcher or bgwriter. If we are
3705
- * doing crash recovery or an immediate shutdown then we expect the
3706
- * checkpointer to exit as well, otherwise not. The stats and
3707
- * syslogger processes are disregarded since they are not connected to
3708
- * shared memory; we also disregard dead_end children here. Walsenders
3709
- * and archiver are also disregarded, they will be terminated later
3710
- * after writing the checkpoint record.
3737
+ * ones), and no walwriter, autovac launcher, bgwriter or slot sync
3738
+ * worker. If we are doing crash recovery or an immediate shutdown
3739
+ * then we expect the checkpointer to exit as well, otherwise not. The
3740
+ * stats and syslogger processes are disregarded since they are not
3741
+ * connected to shared memory; we also disregard dead_end children
3742
+ * here. Walsenders and archiver are also disregarded, they will be
3743
+ * terminated later after writing the checkpoint record.
3711
3744
*/
3712
3745
if (CountChildren (BACKEND_TYPE_ALL - BACKEND_TYPE_WALSND ) == 0 &&
3713
3746
StartupPID == 0 &&
@@ -3717,7 +3750,8 @@ PostmasterStateMachine(void)
3717
3750
(CheckpointerPID == 0 ||
3718
3751
(!FatalError && Shutdown < ImmediateShutdown )) &&
3719
3752
WalWriterPID == 0 &&
3720
- AutoVacPID == 0 )
3753
+ AutoVacPID == 0 &&
3754
+ SlotSyncWorkerPID == 0 )
3721
3755
{
3722
3756
if (Shutdown >= ImmediateShutdown || FatalError )
3723
3757
{
@@ -3815,6 +3849,7 @@ PostmasterStateMachine(void)
3815
3849
Assert (CheckpointerPID == 0 );
3816
3850
Assert (WalWriterPID == 0 );
3817
3851
Assert (AutoVacPID == 0 );
3852
+ Assert (SlotSyncWorkerPID == 0 );
3818
3853
/* syslogger is not considered here */
3819
3854
pmState = PM_NO_CHILDREN ;
3820
3855
}
@@ -4038,6 +4073,8 @@ TerminateChildren(int signal)
4038
4073
signal_child (AutoVacPID , signal );
4039
4074
if (PgArchPID != 0 )
4040
4075
signal_child (PgArchPID , signal );
4076
+ if (SlotSyncWorkerPID != 0 )
4077
+ signal_child (SlotSyncWorkerPID , signal );
4041
4078
}
4042
4079
4043
4080
/*
@@ -4850,6 +4887,7 @@ SubPostmasterMain(int argc, char *argv[])
4850
4887
*/
4851
4888
if (strcmp (argv [1 ], "--forkbackend" ) == 0 ||
4852
4889
strcmp (argv [1 ], "--forkavlauncher" ) == 0 ||
4890
+ strcmp (argv [1 ], "--forkssworker" ) == 0 ||
4853
4891
strcmp (argv [1 ], "--forkavworker" ) == 0 ||
4854
4892
strcmp (argv [1 ], "--forkaux" ) == 0 ||
4855
4893
strcmp (argv [1 ], "--forkbgworker" ) == 0 )
@@ -4953,6 +4991,13 @@ SubPostmasterMain(int argc, char *argv[])
4953
4991
4954
4992
AutoVacWorkerMain (argc - 2 , argv + 2 ); /* does not return */
4955
4993
}
4994
+ if (strcmp (argv [1 ], "--forkssworker" ) == 0 )
4995
+ {
4996
+ /* Restore basic shared memory pointers */
4997
+ InitShmemAccess (UsedShmemSegAddr );
4998
+
4999
+ ReplSlotSyncWorkerMain (argc - 2 , argv + 2 ); /* does not return */
5000
+ }
4956
5001
if (strcmp (argv [1 ], "--forkbgworker" ) == 0 )
4957
5002
{
4958
5003
/* do this as early as possible; in particular, before InitProcess() */
@@ -5498,6 +5543,24 @@ MaybeStartWalSummarizer(void)
5498
5543
}
5499
5544
5500
5545
5546
+ /*
5547
+ * MaybeStartSlotSyncWorker
5548
+ * Start the slot sync worker, if not running and our state allows.
5549
+ *
5550
+ * We allow to start the slot sync worker when we are on a hot standby,
5551
+ * fast or immediate shutdown is not in progress, slot sync parameters
5552
+ * are configured correctly, and it is the first time of worker's launch,
5553
+ * or enough time has passed since the worker was launched last.
5554
+ */
5555
+ static void
5556
+ MaybeStartSlotSyncWorker (void )
5557
+ {
5558
+ if (SlotSyncWorkerPID == 0 && pmState == PM_HOT_STANDBY &&
5559
+ Shutdown <= SmartShutdown && sync_replication_slots &&
5560
+ ValidateSlotSyncParams (LOG ) && SlotSyncWorkerCanRestart ())
5561
+ SlotSyncWorkerPID = StartSlotSyncWorker ();
5562
+ }
5563
+
5501
5564
/*
5502
5565
* Create the opts file
5503
5566
*/
0 commit comments