qnetd: Make it easier to add algorithms

Put the algorithms into an array of structure pointers
(a bit like corosync services) so we can easily add more
without having huge switch statements.

I haven't added any code to the client end that parses the
name into the enum. Yet.

Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
This commit is contained in:
Christine Caulfield 2015-10-06 13:40:03 +01:00 committed by Jan Friesse
parent 118e56ec7c
commit b1504098f4
8 changed files with 121 additions and 55 deletions

View File

@ -61,6 +61,8 @@
#include "dynar.h"
#include "timer-list.h"
#include "qnetd-algorithm.h"
#include "qnetd-algo-test.h"
#include "qnetd-algo-ffsplit.h"
#include "qnetd-cluster-list.h"
#include "qnetd-client-send.h"
@ -1383,6 +1385,16 @@ qnetd_instance_destroy(struct qnetd_instance *instance)
return (0);
}
static void algorithms_register(void)
{
if (qnetd_algo_test_register() != TLV_REPLY_ERROR_CODE_NO_ERROR) {
errx(1, "Failed to register decision algorithm 'test' ");
}
if (qnetd_algo_ffsplit_register() != TLV_REPLY_ERROR_CODE_NO_ERROR) {
errx(1, "Failed to register decision algorithm 'ffsplit' ");
}
}
static void
signal_int_handler(int sig)
{
@ -1490,6 +1502,8 @@ main(int argc, char *argv[])
global_server_socket = instance.server.socket;
signal_handlers_register();
algorithms_register();
/*
* MAIN LOOP
*/

View File

@ -105,3 +105,17 @@ qnetd_algo_ffsplit_vote_info_reply_received(struct qnetd_client *client, uint32_
return (TLV_REPLY_ERROR_CODE_UNSUPPORTED_DECISION_ALGORITHM_MESSAGE);
}
static struct qnetd_algorithm qnetd_algo_ffsplit = {
.init = qnetd_algo_ffsplit_client_init,
.config_node_list_received = qnetd_algo_ffsplit_config_node_list_received,
.membership_node_list_received = qnetd_algo_ffsplit_membership_node_list_received,
.client_disconnect = qnetd_algo_ffsplit_client_disconnect,
.ask_for_vote_received = qnetd_algo_ffsplit_ask_for_vote_received,
.vote_info_reply_received = qnetd_algo_ffsplit_vote_info_reply_received,
};
enum tlv_reply_error_code qnetd_algo_ffsplit_register()
{
return qnetd_algorithm_register(TLV_DECISION_ALGORITHM_TYPE_FFSPLIT, &qnetd_algo_ffsplit);
}

View File

@ -62,6 +62,8 @@ extern enum tlv_reply_error_code qnetd_algo_ffsplit_ask_for_vote_received(
extern enum tlv_reply_error_code qnetd_algo_ffsplit_vote_info_reply_received(
struct qnetd_client *client, uint32_t msg_seq_num);
extern enum tlv_reply_error_code qnetd_algo_ffsplit_register(void);
#ifdef __cplusplus
}
#endif

View File

@ -247,3 +247,18 @@ qnetd_algo_test_vote_info_reply_received(struct qnetd_client *client, uint32_t m
return (TLV_REPLY_ERROR_CODE_NO_ERROR);
}
static struct qnetd_algorithm qnetd_algo_test = {
.init = qnetd_algo_test_client_init,
.config_node_list_received = qnetd_algo_test_config_node_list_received,
.membership_node_list_received = qnetd_algo_test_membership_node_list_received,
.client_disconnect = qnetd_algo_test_client_disconnect,
.ask_for_vote_received = qnetd_algo_test_ask_for_vote_received,
.vote_info_reply_received = qnetd_algo_test_vote_info_reply_received,
};
enum tlv_reply_error_code qnetd_algo_test_register()
{
return qnetd_algorithm_register(TLV_DECISION_ALGORITHM_TYPE_TEST, &qnetd_algo_test);
}

View File

@ -62,6 +62,8 @@ extern enum tlv_reply_error_code qnetd_algo_test_ask_for_vote_received(
extern enum tlv_reply_error_code qnetd_algo_test_vote_info_reply_received(
struct qnetd_client *client, uint32_t msg_seq_num);
extern enum tlv_reply_error_code qnetd_algo_test_register(void);
#ifdef __cplusplus
}
#endif

View File

@ -40,23 +40,19 @@
#include "qnetd-algo-test.h"
#include "qnetd-algo-ffsplit.h"
static struct qnetd_algorithm *qnetd_algorithm[MAX_QNETD_ALGORITHMS];
enum tlv_reply_error_code
qnetd_algorithm_client_init(struct qnetd_client *client)
{
if (client->decision_algorithm >= MAX_QNETD_ALGORITHMS ||
qnetd_algorithm[client->decision_algorithm] == NULL) {
switch (client->decision_algorithm) {
case TLV_DECISION_ALGORITHM_TYPE_TEST:
return (qnetd_algo_test_client_init(client));
break;
case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT:
return (qnetd_algo_ffsplit_client_init(client));
break;
default:
errx(1, "qnetd_algorithm_client_init unhandled decision algorithm");
break;
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
}
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
return qnetd_algorithm[client->decision_algorithm]->init(client);
}
enum tlv_reply_error_code
@ -64,24 +60,17 @@ qnetd_algorithm_config_node_list_received(struct qnetd_client *client,
uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
const struct node_list *nodes, int initial, enum tlv_vote *result_vote)
{
if (client->decision_algorithm >= MAX_QNETD_ALGORITHMS ||
qnetd_algorithm[client->decision_algorithm] == NULL) {
switch (client->decision_algorithm) {
case TLV_DECISION_ALGORITHM_TYPE_TEST:
return (qnetd_algo_test_config_node_list_received(client, msg_seq_num,
config_version_set, config_version, nodes, initial, result_vote));
break;
case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT:
return (qnetd_algo_ffsplit_config_node_list_received(client, msg_seq_num,
config_version_set, config_version, nodes, initial, result_vote));
break;
default:
errx(1, "qnetd_algorithm_config_node_list_received unhandled "
"decision algorithm");
break;
"decision algorithm");
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
}
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
return qnetd_algorithm[client->decision_algorithm]->config_node_list_received(
client, msg_seq_num,
config_version_set, config_version, nodes, initial, result_vote);
}
enum tlv_reply_error_code
@ -91,59 +80,45 @@ qnetd_algorithm_membership_node_list_received(struct qnetd_client *client,
const struct node_list *nodes, enum tlv_vote *result_vote)
{
switch (client->decision_algorithm) {
case TLV_DECISION_ALGORITHM_TYPE_TEST:
return (qnetd_algo_test_membership_node_list_received(client, msg_seq_num,
config_version_set, config_version, ring_id, quorate, nodes, result_vote));
break;
case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT:
return (qnetd_algo_ffsplit_membership_node_list_received(client, msg_seq_num,
config_version_set, config_version, ring_id, quorate, nodes, result_vote));
break;
default:
if (client->decision_algorithm >= MAX_QNETD_ALGORITHMS ||
qnetd_algorithm[client->decision_algorithm] == NULL) {
errx(1, "qnetd_algorithm_membership_node_list_received unhandled "
"decision algorithm");
break;
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
}
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
return qnetd_algorithm[client->decision_algorithm]->membership_node_list_received(
client, msg_seq_num,
config_version_set, config_version, ring_id, quorate, nodes, result_vote);
}
void
qnetd_algorithm_client_disconnect(struct qnetd_client *client, int server_going_down)
{
if (client->decision_algorithm >= MAX_QNETD_ALGORITHMS ||
qnetd_algorithm[client->decision_algorithm] == NULL) {
switch (client->decision_algorithm) {
case TLV_DECISION_ALGORITHM_TYPE_TEST:
qnetd_algo_test_client_disconnect(client, server_going_down);
break;
case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT:
qnetd_algo_ffsplit_client_disconnect(client, server_going_down);
break;
default:
errx(1, "qnetd_algorithm_client_disconnect unhandled decision algorithm");
break;
return;
}
qnetd_algorithm[client->decision_algorithm]->client_disconnect(client, server_going_down);
}
enum tlv_reply_error_code
qnetd_algorithm_ask_for_vote_received(struct qnetd_client *client, uint32_t msg_seq_num,
enum tlv_vote *result_vote)
{
if (client->decision_algorithm >= MAX_QNETD_ALGORITHMS ||
qnetd_algorithm[client->decision_algorithm] == NULL) {
switch (client->decision_algorithm) {
case TLV_DECISION_ALGORITHM_TYPE_TEST:
return (qnetd_algo_test_ask_for_vote_received(client, msg_seq_num, result_vote));
break;
case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT:
return (qnetd_algo_ffsplit_ask_for_vote_received(client, msg_seq_num, result_vote));
break;
default:
errx(1, "qnetd_algorithm_ask_for_vote_received unhandled decision algorithm");
break;
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
}
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
return qnetd_algorithm[client->decision_algorithm]->ask_for_vote_received(
client, msg_seq_num, result_vote);
}
enum tlv_reply_error_code
@ -164,3 +139,18 @@ qnetd_algorithm_vote_info_reply_received(struct qnetd_client *client, uint32_t m
return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
}
enum tlv_reply_error_code
qnetd_algorithm_register(enum tlv_decision_algorithm_type algorithm_number, struct qnetd_algorithm *algorithm)
{
if (algorithm_number >= MAX_QNETD_ALGORITHMS) {
return TLV_REPLY_ERROR_CODE_UNSUPPORTED_DECISION_ALGORITHM;
}
if (qnetd_algorithm[algorithm_number] != NULL) {
return TLV_REPLY_ERROR_CODE_DECISION_ALGORITHM_ALREADY_REGISTERED;
}
qnetd_algorithm[algorithm_number] = algorithm;
return TLV_REPLY_ERROR_CODE_NO_ERROR;
}

View File

@ -66,6 +66,34 @@ extern enum tlv_reply_error_code qnetd_algorithm_ask_for_vote_received(
extern enum tlv_reply_error_code qnetd_algorithm_vote_info_reply_received(
struct qnetd_client *client, uint32_t msg_seq_num);
struct qnetd_algorithm {
enum tlv_reply_error_code (*init)(struct qnetd_client *client);
void (*client_disconnect)(struct qnetd_client *client, int server_going_down);
enum tlv_reply_error_code (*membership_node_list_received)(
struct qnetd_client *client,
uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
const struct node_list *nodes, enum tlv_vote *result_vote);
enum tlv_reply_error_code (*config_node_list_received)(
struct qnetd_client *client,
uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
const struct node_list *nodes, int initial, enum tlv_vote *result_vote);
enum tlv_reply_error_code (*ask_for_vote_received)(
struct qnetd_client *client, uint32_t msg_seq_num, enum tlv_vote *result_vote);
enum tlv_reply_error_code (*vote_info_reply_received)(struct qnetd_client *client, uint32_t msg_seq_num);
};
extern enum tlv_reply_error_code qnetd_algorithm_register(
enum tlv_decision_algorithm_type algorithm_number, struct qnetd_algorithm *algorithm);
#define MAX_QNETD_ALGORITHMS 10
#ifdef __cplusplus
}
#endif

View File

@ -90,6 +90,7 @@ enum tlv_reply_error_code {
TLV_REPLY_ERROR_CODE_UNSUPPORTED_DECISION_ALGORITHM = 12,
TLV_REPLY_ERROR_CODE_INVALID_HEARTBEAT_INTERVAL = 13,
TLV_REPLY_ERROR_CODE_UNSUPPORTED_DECISION_ALGORITHM_MESSAGE = 14,
TLV_REPLY_ERROR_CODE_DECISION_ALGORITHM_ALREADY_REGISTERED = 15,
};
enum tlv_decision_algorithm_type {