6
6
char const * const MtmNeighborEventMnem [] =
7
7
{
8
8
"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" ,
10
12
"MTM_NEIGHBOR_RECOVERY_CAUGHTUP"
11
13
};
12
14
@@ -23,9 +25,6 @@ char const* const MtmEventMnem[] =
23
25
"MTM_RECOVERY_FINISH1" ,
24
26
"MTM_RECOVERY_FINISH2" ,
25
27
26
- "MTM_WAL_RECEIVER_START" ,
27
- "MTM_WAL_SENDER_START" ,
28
-
29
28
"MTM_NONRECOVERABLE_ERROR"
30
29
};
31
30
@@ -37,39 +36,61 @@ static void MtmSwitchClusterMode(MtmNodeStatus mode);
37
36
void
38
37
MtmStateProcessNeighborEvent (int node_id , MtmNeighborEvent ev )
39
38
{
40
- MTM_LOG1 ("[STATE] Processing %s" , MtmNeighborEventMnem [ev ]);
39
+ MTM_LOG1 ("[STATE] Processing %s for node %u " , MtmNeighborEventMnem [ev ], node_id );
41
40
42
41
switch (ev )
43
42
{
44
43
case MTM_NEIGHBOR_CLIQUE_DISABLE :
45
44
MtmDisableNode (node_id );
46
45
break ;
47
46
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 :
54
55
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 )) {
58
59
MtmEnableNode (node_id );
59
60
}
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
+ }
61
68
}
62
69
MtmUnlock ();
63
70
break ;
64
71
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
+
65
85
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 );
70
90
Mtm -> nLiveNodes += 1 ;
71
91
MtmCheckQuorum ();
72
92
break ;
93
+
73
94
}
74
95
}
75
96
@@ -114,7 +135,7 @@ MtmStateProcessEvent(MtmEvent ev)
114
135
if (Mtm -> nLiveNodes < Mtm -> nAllNodes /2 + 1 )
115
136
{
116
137
/* 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);
118
139
MtmSwitchClusterMode (MTM_IN_MINORITY );
119
140
}
120
141
else if (Mtm -> status == MTM_INITIALIZATION )
@@ -185,28 +206,6 @@ MtmStateProcessEvent(MtmEvent ev)
185
206
break ;
186
207
187
208
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
-
210
209
case MTM_NONRECOVERABLE_ERROR :
211
210
// MTM_ELOG(WARNING, "Node is excluded from cluster because of non-recoverable error %d, %s, pid=%u",
212
211
// edata->sqlerrcode, edata->message, getpid());
@@ -234,13 +233,10 @@ MtmSwitchClusterMode(MtmNodeStatus mode)
234
233
*/
235
234
void MtmDisableNode (int nodeId )
236
235
{
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 ));
240
236
BIT_SET (Mtm -> disabledNodeMask , nodeId - 1 );
241
237
Mtm -> nConfigChanges += 1 ;
242
238
Mtm -> nodes [nodeId - 1 ].timeline += 1 ;
243
- Mtm -> nodes [nodeId - 1 ].lastStatusChangeTime = now ;
239
+ Mtm -> nodes [nodeId - 1 ].lastStatusChangeTime = MtmGetSystemTime () ;
244
240
Mtm -> nodes [nodeId - 1 ].lastHeartbeat = 0 ; /* defuse watchdog until first heartbeat is received */
245
241
if (nodeId != MtmNodeId ) {
246
242
Mtm -> nLiveNodes -= 1 ;
@@ -269,7 +265,6 @@ void MtmEnableNode(int nodeId)
269
265
if (nodeId != MtmNodeId ) {
270
266
Mtm -> nLiveNodes += 1 ;
271
267
}
272
- // MTM_ELOG(WARNING, "Enable node %d at xlog position %llx", nodeId, (long64)GetXLogInsertRecPtr());
273
268
}
274
269
MtmCheckQuorum ();
275
270
}
@@ -282,15 +277,49 @@ static void MtmCheckQuorum(void)
282
277
{
283
278
int nVotingNodes = MtmGetNumberOfVotingNodes ();
284
279
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 )
288
283
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 )
293
288
MtmSwitchClusterMode (MTM_IN_MINORITY );
294
- }
295
289
}
296
290
}
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