|
|
@@ -61,6 +61,16 @@ struct qnetd_algo_2nodelms_info {
|
|
|
struct tlv_ring_id ring_id;
|
|
|
};
|
|
|
|
|
|
+static int rings_eq(const struct tlv_ring_id *ring_id1, const struct tlv_ring_id *ring_id2)
|
|
|
+{
|
|
|
+ if (ring_id1->node_id == ring_id2->node_id &&
|
|
|
+ ring_id1->seq == ring_id2->seq) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
enum tlv_reply_error_code
|
|
|
qnetd_algo_2nodelms_client_init(struct qnetd_client *client)
|
|
|
@@ -72,7 +82,7 @@ qnetd_algo_2nodelms_client_init(struct qnetd_client *client)
|
|
|
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
|
|
|
}
|
|
|
client->algorithm_data = info;
|
|
|
- info->last_result = TLV_VOTE_ASK_LATER;
|
|
|
+ info->last_result = 0;
|
|
|
return (TLV_REPLY_ERROR_CODE_NO_ERROR);
|
|
|
}
|
|
|
|
|
|
@@ -145,6 +155,23 @@ qnetd_algo_2nodelms_membership_node_list_received(struct qnetd_client *client,
|
|
|
/* Save this now */
|
|
|
memcpy(&info->ring_id, ring_id, sizeof(*ring_id));
|
|
|
|
|
|
+ /* If we're a newcomer and there is another active partition, then we must NACK
|
|
|
+ * to avoid quorum moving to us from already active nodes.
|
|
|
+ */
|
|
|
+ if (info->last_result == 0) {
|
|
|
+ TAILQ_FOREACH(other_client, &client->cluster->client_list, cluster_entries) {
|
|
|
+ struct qnetd_algo_2nodelms_info *other_info = other_client->algorithm_data;
|
|
|
+ if (!rings_eq(&info->ring_id, &other_info->ring_id) &&
|
|
|
+ other_info->last_result == TLV_VOTE_ACK) {
|
|
|
+
|
|
|
+ /* Don't save NACK, we need to know subsequently if we haven't been voting */
|
|
|
+ *result_vote = TLV_VOTE_NACK;
|
|
|
+ qnetd_log(LOG_DEBUG, "algo-2nodelms: we are a new partition and another active partition exists. NACK");
|
|
|
+ return (TLV_REPLY_ERROR_CODE_NO_ERROR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/* If both nodes are present, then we're OK. return a vote */
|
|
|
TAILQ_FOREACH(node_info, nodes, entries) {
|
|
|
if (node_info->node_state == TLV_NODE_STATE_MEMBER) {
|
|
|
@@ -231,7 +258,12 @@ qnetd_algo_2nodelms_ask_for_vote_received(struct qnetd_client *client, uint32_t
|
|
|
qnetd_log(LOG_INFO, "algo-2nodelms: Client %p (cluster %s, node_id %"PRIx32") "
|
|
|
"asked for a vote", client, client->cluster_name, client->node_id);
|
|
|
|
|
|
- *result_vote = info->last_result;
|
|
|
+ if (info->last_result == 0) {
|
|
|
+ *result_vote = TLV_VOTE_ASK_LATER;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ *result_vote = info->last_result;
|
|
|
+ }
|
|
|
|
|
|
return (TLV_REPLY_ERROR_CODE_NO_ERROR);
|
|
|
}
|