@@ -1047,6 +1047,7 @@ MtmCheckClusterLock()
1047
1047
Mtm -> nNodes += Mtm -> nLockers ;
1048
1048
Mtm -> nLockers = 0 ;
1049
1049
Mtm -> nodeLockerMask = 0 ;
1050
+ MtmCheckQuorum ();
1050
1051
}
1051
1052
}
1052
1053
break ;
@@ -1056,14 +1057,17 @@ MtmCheckClusterLock()
1056
1057
/**
1057
1058
* Build internode connectivity mask. 1 - means that node is disconnected.
1058
1059
*/
1059
- static void
1060
+ static bool
1060
1061
MtmBuildConnectivityMatrix (nodemask_t * matrix , bool nowait )
1061
1062
{
1062
1063
int i , j , n = MtmNodes ;
1063
1064
for (i = 0 ; i < n ; i ++ ) {
1064
1065
if (i + 1 != MtmNodeId ) {
1065
1066
void * data = PaxosGet (psprintf ("node-mask-%d" , i + 1 ), NULL , NULL , nowait );
1066
- matrix [i ] = data ? * (nodemask_t * )data : 0 ;
1067
+ if (data == NULL ) {
1068
+ return false;
1069
+ }
1070
+ matrix [i ] = * (nodemask_t * )data ;
1067
1071
} else {
1068
1072
matrix [i ] = Mtm -> connectivityMask ;
1069
1073
}
@@ -1074,21 +1078,25 @@ MtmBuildConnectivityMatrix(nodemask_t* matrix, bool nowait)
1074
1078
matrix [i ] |= ((matrix [j ] >> i ) & 1 ) << j ;
1075
1079
}
1076
1080
}
1081
+ return true;
1077
1082
}
1078
1083
1079
1084
1080
1085
/**
1081
1086
* Build connectivity graph, find clique in it and extend disabledNodeMask by nodes not included in clique.
1082
1087
* This function returns false if current node is excluded from cluster, true otherwise
1083
1088
*/
1084
- void MtmRefreshClusterStatus (bool nowait )
1089
+ bool MtmRefreshClusterStatus (bool nowait )
1085
1090
{
1086
1091
nodemask_t mask , clique ;
1087
1092
nodemask_t matrix [MAX_NODES ];
1088
1093
int clique_size ;
1089
1094
int i ;
1090
1095
1091
- MtmBuildConnectivityMatrix (matrix , nowait );
1096
+ if (!MtmBuildConnectivityMatrix (matrix , nowait )) {
1097
+ /* RAFT is not available */
1098
+ return false;
1099
+ }
1092
1100
1093
1101
clique = MtmFindMaxClique (matrix , MtmNodes , & clique_size );
1094
1102
if (clique_size >= MtmNodes /2 + 1 ) { /* have quorum */
@@ -1108,6 +1116,7 @@ void MtmRefreshClusterStatus(bool nowait)
1108
1116
BIT_CLEAR (Mtm -> disabledNodeMask , i );
1109
1117
}
1110
1118
}
1119
+ MtmCheckQuorum ();
1111
1120
MtmUnlock ();
1112
1121
if (BIT_CHECK (Mtm -> disabledNodeMask , MtmNodeId - 1 )) {
1113
1122
if (Mtm -> status == MTM_ONLINE ) {
@@ -1120,9 +1129,27 @@ void MtmRefreshClusterStatus(bool nowait)
1120
1129
}
1121
1130
} else {
1122
1131
elog (WARNING , "Clique %lx has no quorum" , clique );
1132
+ Mtm -> status = MTM_IN_MINORITY ;
1123
1133
}
1134
+ return true;
1124
1135
}
1125
1136
1137
+ void MtmCheckQuorum (void )
1138
+ {
1139
+ if (Mtm -> nNodes < MtmNodes /2 + 1 ) {
1140
+ if (Mtm -> status == MTM_ONLINE ) { /* out of quorum */
1141
+ elog (WARNING , "Node is in minority: disabled mask %lx" , Mtm -> disabledNodeMask );
1142
+ Mtm -> status = MTM_IN_MINORITY ;
1143
+ }
1144
+ } else {
1145
+ if (Mtm -> status == MTM_IN_MINORITY ) {
1146
+ elog (WARNING , "Node is in majority: dissbled mask %lx" , Mtm -> disabledNodeMask );
1147
+ Mtm -> status = MTM_ONLINE ;
1148
+ }
1149
+ }
1150
+ }
1151
+
1152
+
1126
1153
void MtmOnNodeDisconnect (int nodeId )
1127
1154
{
1128
1155
BIT_SET (Mtm -> connectivityMask , nodeId - 1 );
@@ -1131,7 +1158,15 @@ void MtmOnNodeDisconnect(int nodeId)
1131
1158
/* Wait more than socket KEEPALIVE timeout to let other nodes update their statuses */
1132
1159
MtmSleep (MtmKeepaliveTimeout );
1133
1160
1134
- MtmRefreshClusterStatus (false);
1161
+ if (!MtmRefreshClusterStatus (false)) {
1162
+ MtmLock (LW_EXCLUSIVE );
1163
+ if (!BIT_CHECK (Mtm -> disabledNodeMask , nodeId - 1 )) {
1164
+ BIT_SET (Mtm -> disabledNodeMask , nodeId - 1 );
1165
+ Mtm -> nNodes -= 1 ;
1166
+ MtmCheckQuorum ();
1167
+ }
1168
+ MtmUnlock ();
1169
+ }
1135
1170
}
1136
1171
1137
1172
void MtmOnNodeConnect (int nodeId )
@@ -1633,6 +1668,7 @@ void MtmDropNode(int nodeId, bool dropSlot)
1633
1668
}
1634
1669
BIT_SET (Mtm -> disabledNodeMask , nodeId - 1 );
1635
1670
Mtm -> nNodes -= 1 ;
1671
+ MtmCheckQuorum ();
1636
1672
if (!MtmIsBroadcast ())
1637
1673
{
1638
1674
MtmBroadcastUtilityStmt (psprintf ("select mtm.drop_node(%d,%s)" , nodeId , dropSlot ? "true" : "false" ), true);
@@ -1647,6 +1683,7 @@ void MtmDropNode(int nodeId, bool dropSlot)
1647
1683
static void
1648
1684
MtmReplicationShutdownHook (struct PGLogicalShutdownHookArgs * args )
1649
1685
{
1686
+ elog (WARNING , "Logical replication to node %d is stopped" , MtmReplicationNodeId );
1650
1687
MtmOnNodeDisconnect (MtmReplicationNodeId );
1651
1688
}
1652
1689
0 commit comments