completed voting subsystem for legions

This commit is contained in:
Roberto De Ioris
2012-12-29 19:13:43 +01:00
parent 6f7b158942
commit 374317cffd
3 changed files with 53 additions and 54 deletions
+48 -54
View File
@@ -203,9 +203,9 @@ static void legions_check_nodes() {
struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *);
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid) {
static void legions_report_quorum(struct uwsgi_legion *ul, uint64_t best_valor, char *best_uuid, int votes) {
struct uwsgi_legion_node *nodes = ul->nodes_head;
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum);
uwsgi_log("\n[uwsgi-legion] --- WE HAVE QUORUM FOR LEGION %s !!! (valor: %llu uuid: %.*s checksum: %llu votes: %d) ---\n", ul->legion, best_valor, 36, best_uuid, ul->checksum, votes);
while (nodes) {
uwsgi_log("[uwsgi-legion-node] node: %.*s valor: %llu uuid: %.*s last_seen: %d vote_valor: %llu vote_uuid: %.*s\n", nodes->name_len, nodes->name, nodes->valor, 36, nodes->uuid, nodes->last_seen, nodes->lord_valor, 36, nodes->lord_uuid);
nodes = nodes->next;
@@ -258,34 +258,29 @@ static void legions_check_nodes_step2() {
// ... ok let's see if all of the nodes agree on the lord
// ... but first check if i am not alone...
int have_quorum = 0;
if (!ul->nodes_head) {
have_quorum = 1;
}
else {
struct uwsgi_legion_node *nodes = ul->nodes_head;
while (nodes) {
if (nodes->checksum != ul->checksum) {
have_quorum = 0;
break;
}
if (nodes->lord_valor != best_valor) {
have_quorum = 0;
break;
}
if (memcmp(nodes->lord_uuid, best_uuid, 36)) {
have_quorum = 0;
break;
}
have_quorum++;
nodes = nodes->next;
int votes = 1;
struct uwsgi_legion_node *nodes = ul->nodes_head;
while (nodes) {
if (nodes->checksum != ul->checksum) {
votes = 0;
break;
}
if (nodes->lord_valor != best_valor) {
votes = 0;
break;
}
if (memcmp(nodes->lord_uuid, best_uuid, 36)) {
votes = 0;
break;
}
votes++;
nodes = nodes->next;
}
if (have_quorum) {
if (votes >= ul->quorum) {
if (i_am_the_best) {
if (!ul->i_am_the_lord) {
legions_report_quorum(ul, best_valor, best_uuid);
legions_report_quorum(ul, best_valor, best_uuid, votes);
uwsgi_log("[uwsgi-legion] i am now the Lord of the Legion %s\n", ul->legion);
// triggering lord hooks
struct uwsgi_string_list *usl = ul->lord_hooks;
@@ -301,7 +296,7 @@ static void legions_check_nodes_step2() {
}
else {
if (ul->i_am_the_lord) {
legions_report_quorum(ul, best_valor, best_uuid);
legions_report_quorum(ul, best_valor, best_uuid, votes);
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
@@ -370,6 +365,7 @@ static void *legion_loop(void *foobar) {
if (!uwsgi.legion_tolerance)
uwsgi.legion_tolerance = 15;
int first_round = 1;
for (;;) {
int timeout = uwsgi.legion_freq;
time_t now = uwsgi_now();
@@ -489,35 +485,12 @@ static void *legion_loop(void *foobar) {
}
// skip the first round if i no packet is received
if (first_round) {
first_round = 0;
continue;
}
legions_check_nodes_step2();
/*
if (ul->lord > 0) {
if (legion_msg.valor > ul->valor) {
uwsgi_log("[uwsgi-legion] a new Lord (name: %.*s pid: %d) raised for Legion %s...\n", legion_msg.name_len, legion_msg.name, (int) legion_msg.pid, ul->legion);
// no more lord, trigger unlord hooks
struct uwsgi_string_list *usl = ul->unlord_hooks;
while(usl) {
int ret = uwsgi_legion_action_call("unlord", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, unlord hook returned: %d\n", ret);
}
usl = usl->next;
}
ul->last_seen_lord = uwsgi_now();
ul->lord = 0;
continue;
}
}
if (legion_msg.valor > ul->valor) {
// a lord
ul->last_seen_lord = uwsgi_now();
}
else if (legion_msg.valor == ul->valor) {
uwsgi_log("[uwsgi-legion] a node with the same valor announced itself !!!\n");
}
*/
}
return NULL;
@@ -697,6 +670,27 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
usl->custom_ptr = sin;
}
void uwsgi_opt_legion_quorum(char *opt, char *value, void *foobar) {
char *legion = uwsgi_str(value);
char *space = strchr(legion, ' ');
if (!space) {
uwsgi_log("invalid legion-quorum syntax, must be <legion> <quorum>\n");
exit(1);
}
*space = 0;
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
if (!ul) {
uwsgi_log("unknown legion: %s\n", legion);
exit(1);
}
ul->quorum = atoi(space+1);
}
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
char *legion = uwsgi_str(value);
+1
View File
@@ -340,6 +340,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
#endif
+4
View File
@@ -541,7 +541,10 @@ struct uwsgi_legion {
char uuid[37];
int socket;
int quorum;
uint64_t checksum;
char lord_uuid[36];
uint64_t lord_valor;
@@ -3606,6 +3609,7 @@ char *uwsgi_strip(char *);
#ifdef UWSGI_SSL
void uwsgi_opt_legion(char *, char *, void *);
void uwsgi_opt_legion_node(char *, char *, void *);
void uwsgi_opt_legion_quorum(char *, char *, void *);
void uwsgi_opt_legion_hook(char *, char *, void *);
void uwsgi_legion_add(struct uwsgi_legion *);
char *uwsgi_ssl_rand(size_t);