66char const * const MtmNeighborEventMnem [] =
77{
88 "MTM_NEIGHBOR_CLIQUE_DISABLE" ,
9- "MTM_NEIGHBOR_RECEIVER_START" ,
9+ "MTM_NEIGHBOR_WAL_RECEIVER_START" ,
10+ "MTM_NEIGHBOR_WAL_SENDER_START" ,
11+ "MTM_NEIGHBOR_HEARTBEAT_TIMEOUT" ,
1012 "MTM_NEIGHBOR_RECOVERY_CAUGHTUP"
1113};
1214
@@ -23,9 +25,6 @@ char const* const MtmEventMnem[] =
2325 "MTM_RECOVERY_FINISH1" ,
2426 "MTM_RECOVERY_FINISH2" ,
2527
26- "MTM_WAL_RECEIVER_START" ,
27- "MTM_WAL_SENDER_START" ,
28-
2928 "MTM_NONRECOVERABLE_ERROR"
3029};
3130
@@ -37,39 +36,61 @@ static void MtmSwitchClusterMode(MtmNodeStatus mode);
3736void
3837MtmStateProcessNeighborEvent (int node_id , MtmNeighborEvent ev )
3938{
40- MTM_LOG1 ("[STATE] Processing %s" , MtmNeighborEventMnem [ev ]);
39+ MTM_LOG1 ("[STATE] Processing %s for node %u " , MtmNeighborEventMnem [ev ], node_id );
4140
4241 switch (ev )
4342 {
4443 case MTM_NEIGHBOR_CLIQUE_DISABLE :
4544 MtmDisableNode (node_id );
4645 break ;
4746
48- case MTM_NEIGHBOR_RECEIVER_START :
49- /*
50- * This functions is called by pglogical receiver main function when receiver background worker is started.
51- * We switch to ONLINE mode when all receivers are connected.
52- * As far as background worker can be restarted multiple times, use node bitmask.
53- */
47+ case MTM_NEIGHBOR_HEARTBEAT_TIMEOUT :
48+ MtmLock (LW_EXCLUSIVE );
49+ BIT_SET (SELF_CONNECTIVITY_MASK , node_id - 1 );
50+ BIT_SET (Mtm -> reconnectMask , node_id - 1 );
51+ MtmUnlock ();
52+ break ;
53+
54+ case MTM_NEIGHBOR_WAL_RECEIVER_START :
5455 MtmLock (LW_EXCLUSIVE );
55- if (!BIT_CHECK (Mtm -> pglogicalReceiverMask , node_id )) {
56- BIT_SET (Mtm -> pglogicalReceiverMask , node_id );
57- if (BIT_CHECK (Mtm -> disabledNodeMask , node_id )) {
56+ if (!BIT_CHECK (Mtm -> pglogicalReceiverMask , node_id - 1 )) {
57+ BIT_SET (Mtm -> pglogicalReceiverMask , node_id - 1 );
58+ if (BIT_CHECK (Mtm -> disabledNodeMask , node_id - 1 )) {
5859 MtmEnableNode (node_id );
5960 }
60- MtmStateProcessEvent (MTM_WAL_RECEIVER_START );
61+
62+ if (++ Mtm -> nReceivers == Mtm -> nLiveNodes - 1 && Mtm -> nSenders == Mtm -> nLiveNodes - 1
63+ && (Mtm -> status == MTM_RECOVERED || Mtm -> status == MTM_CONNECTED ))
64+ {
65+ BIT_CLEAR (Mtm -> originLockNodeMask , MtmNodeId - 1 ); /* recovery is completed: release cluster lock */
66+ MtmSwitchClusterMode (MTM_ONLINE );
67+ }
6168 }
6269 MtmUnlock ();
6370 break ;
6471
72+ case MTM_NEIGHBOR_WAL_SENDER_START :
73+ if (!BIT_CHECK (Mtm -> pglogicalSenderMask , node_id - 1 )) {
74+ BIT_SET (Mtm -> pglogicalSenderMask , node_id - 1 );
75+ if (++ Mtm -> nSenders == Mtm -> nLiveNodes - 1 && Mtm -> nReceivers == Mtm -> nLiveNodes - 1
76+ && (Mtm -> status == MTM_RECOVERED || Mtm -> status == MTM_CONNECTED ))
77+ {
78+ /* All logical replication connections from and to this node are established, so we can switch cluster to online mode */
79+ BIT_CLEAR (Mtm -> originLockNodeMask , MtmNodeId - 1 ); /* recovery is completed: release cluster lock */
80+ MtmSwitchClusterMode (MTM_ONLINE );
81+ }
82+ }
83+ break ;
84+
6585 case MTM_NEIGHBOR_RECOVERY_CAUGHTUP :
66- Assert (BIT_CHECK (Mtm -> disabledNodeMask , node_id ));
67- BIT_CLEAR (Mtm -> originLockNodeMask , node_id );
68- BIT_CLEAR (Mtm -> disabledNodeMask , node_id );
69- BIT_SET (Mtm -> recoveredNodeMask , node_id );
86+ Assert (BIT_CHECK (Mtm -> disabledNodeMask , node_id - 1 ));
87+ BIT_CLEAR (Mtm -> originLockNodeMask , node_id - 1 );
88+ BIT_CLEAR (Mtm -> disabledNodeMask , node_id - 1 );
89+ BIT_SET (Mtm -> recoveredNodeMask , node_id - 1 );
7090 Mtm -> nLiveNodes += 1 ;
7191 MtmCheckQuorum ();
7292 break ;
93+
7394 }
7495}
7596
@@ -114,7 +135,7 @@ MtmStateProcessEvent(MtmEvent ev)
114135 if (Mtm -> nLiveNodes < Mtm -> nAllNodes /2 + 1 )
115136 {
116137 /* no quorum */
117- MTM_ELOG (WARNING , "Node is out of quorum: only %d nodes of %d are accessible" , Mtm -> nLiveNodes , Mtm -> nAllNodes );
138+ // MTM_ELOG(WARNING, "Node is out of quorum: only %d nodes of %d are accessible", Mtm->nLiveNodes, Mtm->nAllNodes);
118139 MtmSwitchClusterMode (MTM_IN_MINORITY );
119140 }
120141 else if (Mtm -> status == MTM_INITIALIZATION )
@@ -185,28 +206,6 @@ MtmStateProcessEvent(MtmEvent ev)
185206 break ;
186207
187208
188- case MTM_WAL_RECEIVER_START :
189- MTM_ELOG (LOG , "[STATE] Start %d receivers and %d senders from %d cluster status %s" , Mtm -> nReceivers + 1 , Mtm -> nSenders , Mtm -> nLiveNodes - 1 , MtmNodeStatusMnem [Mtm -> status ]);
190- if (++ Mtm -> nReceivers == Mtm -> nLiveNodes - 1 && Mtm -> nSenders == Mtm -> nLiveNodes - 1
191- && (Mtm -> status == MTM_RECOVERED || Mtm -> status == MTM_CONNECTED ))
192- {
193- BIT_CLEAR (Mtm -> originLockNodeMask , MtmNodeId - 1 ); /* recovery is completed: release cluster lock */
194- MtmSwitchClusterMode (MTM_ONLINE );
195- }
196- break ;
197-
198-
199- case MTM_WAL_SENDER_START :
200- if (++ Mtm -> nSenders == Mtm -> nLiveNodes - 1 && Mtm -> nReceivers == Mtm -> nLiveNodes - 1
201- && (Mtm -> status == MTM_RECOVERED || Mtm -> status == MTM_CONNECTED ))
202- {
203- /* All logical replication connections from and to this node are established, so we can switch cluster to online mode */
204- BIT_CLEAR (Mtm -> originLockNodeMask , MtmNodeId - 1 ); /* recovery is completed: release cluster lock */
205- MtmSwitchClusterMode (MTM_ONLINE );
206- }
207- break ;
208-
209-
210209 case MTM_NONRECOVERABLE_ERROR :
211210 // MTM_ELOG(WARNING, "Node is excluded from cluster because of non-recoverable error %d, %s, pid=%u",
212211 // edata->sqlerrcode, edata->message, getpid());
@@ -234,13 +233,10 @@ MtmSwitchClusterMode(MtmNodeStatus mode)
234233 */
235234void MtmDisableNode (int nodeId )
236235{
237- timestamp_t now = MtmGetSystemTime ();
238- MTM_ELOG (WARNING , "Disable node %d at xlog position %llx, last status change time %d msec ago" , nodeId , (long64 )GetXLogInsertRecPtr (),
239- (int )USEC_TO_MSEC (now - Mtm -> nodes [nodeId - 1 ].lastStatusChangeTime ));
240236 BIT_SET (Mtm -> disabledNodeMask , nodeId - 1 );
241237 Mtm -> nConfigChanges += 1 ;
242238 Mtm -> nodes [nodeId - 1 ].timeline += 1 ;
243- Mtm -> nodes [nodeId - 1 ].lastStatusChangeTime = now ;
239+ Mtm -> nodes [nodeId - 1 ].lastStatusChangeTime = MtmGetSystemTime () ;
244240 Mtm -> nodes [nodeId - 1 ].lastHeartbeat = 0 ; /* defuse watchdog until first heartbeat is received */
245241 if (nodeId != MtmNodeId ) {
246242 Mtm -> nLiveNodes -= 1 ;
@@ -269,7 +265,6 @@ void MtmEnableNode(int nodeId)
269265 if (nodeId != MtmNodeId ) {
270266 Mtm -> nLiveNodes += 1 ;
271267 }
272- // MTM_ELOG(WARNING, "Enable node %d at xlog position %llx", nodeId, (long64)GetXLogInsertRecPtr());
273268 }
274269 MtmCheckQuorum ();
275270}
@@ -282,15 +277,49 @@ static void MtmCheckQuorum(void)
282277{
283278 int nVotingNodes = MtmGetNumberOfVotingNodes ();
284279
285- if (Mtm -> nLiveNodes >= nVotingNodes /2 + 1 || (Mtm -> nLiveNodes == (nVotingNodes + 1 )/2 && MtmMajorNode )) { /* have quorum */
286- if ( Mtm -> status == MTM_IN_MINORITY ) {
287- // MTM_LOG1("Node is in majority: disabled mask %llx", Mtm->disabledNodeMask);
280+ if (Mtm -> nLiveNodes >= nVotingNodes /2 + 1 || (Mtm -> nLiveNodes == (nVotingNodes + 1 )/2 && MtmMajorNode ))
281+ {
282+ if ( Mtm -> status == MTM_IN_MINORITY )
288283 MtmSwitchClusterMode (MTM_ONLINE );
289- }
290- } else {
291- if ( Mtm -> status == MTM_ONLINE ) { /* out of quorum */
292- // MTM_ELOG(WARNING, "Node is in minority: disabled mask %llx", Mtm->disabledNodeMask);
284+ }
285+ else
286+ {
287+ if ( Mtm -> status == MTM_ONLINE )
293288 MtmSwitchClusterMode (MTM_IN_MINORITY );
294- }
295289 }
296290}
291+
292+ void MtmOnNodeDisconnect (int nodeId )
293+ {
294+ if (BIT_CHECK (SELF_CONNECTIVITY_MASK , nodeId - 1 ))
295+ return ;
296+
297+ MTM_LOG1 ("[STATE] NodeDisconnect for node %u" , nodeId );
298+
299+ MtmLock (LW_EXCLUSIVE );
300+ BIT_SET (SELF_CONNECTIVITY_MASK , nodeId - 1 );
301+ BIT_SET (Mtm -> reconnectMask , nodeId - 1 );
302+ MtmUnlock ();
303+ }
304+
305+ void MtmOnNodeConnect (int nodeId )
306+ {
307+ if (!BIT_CHECK (SELF_CONNECTIVITY_MASK , nodeId - 1 ))
308+ return ;
309+
310+ MTM_LOG1 ("[STATE] NodeConnect for node %u" , nodeId );
311+
312+ MtmLock (LW_EXCLUSIVE );
313+ BIT_CLEAR (SELF_CONNECTIVITY_MASK , nodeId - 1 );
314+ BIT_SET (Mtm -> reconnectMask , nodeId - 1 );
315+ MtmUnlock ();
316+ }
317+
318+ void MtmReconnectNode (int nodeId )
319+ {
320+ MTM_LOG1 ("[STATE] ReconnectNode for node %u" , nodeId );
321+ MtmLock (LW_EXCLUSIVE );
322+ BIT_SET (Mtm -> reconnectMask , nodeId - 1 );
323+ MtmUnlock ();
324+ }
325+
0 commit comments