diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-sm.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-sm.c | 837 |
1 files changed, 700 insertions, 137 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c index b55fdd567..c671edf68 100644 --- a/xlators/mgmt/glusterd/src/glusterd-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-sm.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2006-2009 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is GF_FREE software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ + Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ #ifndef _CONFIG_H #define _CONFIG_H @@ -27,9 +17,8 @@ #include <sys/resource.h> #include <libgen.h> -#include <uuid/uuid.h> +#include "uuid.h" -//#include "transport.h" #include "fnmatch.h" #include "xlator.h" #include "protocol-common.h" @@ -42,10 +31,155 @@ #include "compat-errno.h" #include "statedump.h" #include "glusterd-sm.h" +#include "glusterd-op-sm.h" #include "glusterd-utils.h" +#include "glusterd-store.h" static struct list_head gd_friend_sm_queue; +static char *glusterd_friend_sm_state_names[] = { + "Establishing Connection", + "Probe Sent to Peer", + "Probe Received from Peer", + "Peer in Cluster", + "Accepted peer request", + "Sent and Received peer request", + "Peer Rejected", + "Peer detach in progress", + "Probe Received from peer", + "Connected to Peer", + "Peer is connected and Accepted", + "Invalid State" +}; + +static char *glusterd_friend_sm_event_names[] = { + "GD_FRIEND_EVENT_NONE", + "GD_FRIEND_EVENT_PROBE", + "GD_FRIEND_EVENT_INIT_FRIEND_REQ", + "GD_FRIEND_EVENT_RCVD_ACC", + "GD_FRIEND_EVENT_LOCAL_ACC", + "GD_FRIEND_EVENT_RCVD_RJT", + "GD_FRIEND_EVENT_LOCAL_RJT", + "GD_FRIEND_EVENT_RCVD_FRIEND_REQ", + "GD_FRIEND_EVENT_INIT_REMOVE_FRIEND", + "GD_FRIEND_EVENT_RCVD_REMOVE_FRIEND", + "GD_FRIEND_EVENT_REMOVE_FRIEND", + "GD_FRIEND_EVENT_CONNECTED", + "GD_FRIEND_EVENT_MAX" +}; + +char* +glusterd_friend_sm_state_name_get (int state) +{ + if (state < 0 || state >= GD_FRIEND_STATE_MAX) + return glusterd_friend_sm_state_names[GD_FRIEND_STATE_MAX]; + return glusterd_friend_sm_state_names[state]; +} + +char* +glusterd_friend_sm_event_name_get (int event) +{ + if (event < 0 || event >= GD_FRIEND_EVENT_MAX) + return glusterd_friend_sm_event_names[GD_FRIEND_EVENT_MAX]; + return glusterd_friend_sm_event_names[event]; +} + +void +glusterd_destroy_probe_ctx (glusterd_probe_ctx_t *ctx) +{ + if (!ctx) + return; + + GF_FREE (ctx->hostname); + GF_FREE (ctx); +} + +void +glusterd_destroy_friend_req_ctx (glusterd_friend_req_ctx_t *ctx) +{ + if (!ctx) + return; + + if (ctx->vols) + dict_unref (ctx->vols); + GF_FREE (ctx->hostname); + GF_FREE (ctx); +} + +void +glusterd_destroy_friend_update_ctx (glusterd_friend_update_ctx_t *ctx) +{ + if (!ctx) + return; + GF_FREE (ctx->hostname); + GF_FREE (ctx); +} + +int +glusterd_broadcast_friend_delete (char *hostname, uuid_t uuid) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + xlator_t *this = NULL; + glusterd_friend_update_ctx_t ctx = {{0},}; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_conf_t *priv = NULL; + dict_t *friends = NULL; + char key[100] = {0,}; + int32_t count = 0; + + this = THIS; + priv = this->private; + + GF_ASSERT (priv); + + ctx.hostname = hostname; + ctx.op = GD_FRIEND_UPDATE_DEL; + + friends = dict_new (); + if (!friends) + goto out; + + snprintf (key, sizeof (key), "op"); + ret = dict_set_int32 (friends, key, ctx.op); + if (ret) + goto out; + + snprintf (key, sizeof (key), "hostname"); + ret = dict_set_str (friends, key, hostname); + if (ret) + goto out; + + ret = dict_set_int32 (friends, "count", count); + if (ret) + goto out; + + list_for_each_entry (peerinfo, &priv->peers, uuid_list) { + if (!peerinfo->connected || !peerinfo->peer) + continue; + + ret = dict_set_static_ptr (friends, "peerinfo", peerinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "failed to set peerinfo"); + goto out; + } + + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_UPDATE]; + if (proc->fn) { + ret = proc->fn (NULL, this, friends); + } + } + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + +out: + if (friends) + dict_unref (friends); + + return ret; +} + + static int glusterd_ac_none (glusterd_friend_sm_event_t *event, void *ctx) { @@ -67,6 +201,58 @@ glusterd_ac_error (glusterd_friend_sm_event_t *event, void *ctx) } static int +glusterd_ac_reverse_probe_begin (glusterd_friend_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_friend_sm_event_t *new_event = NULL; + glusterd_probe_ctx_t *new_ev_ctx = NULL; + + GF_ASSERT (event); + GF_ASSERT (ctx); + + peerinfo = event->peerinfo; + ret = glusterd_friend_sm_new_event + (GD_FRIEND_EVENT_PROBE, &new_event); + + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get new new_event"); + ret = -1; + goto out; + } + + new_ev_ctx = GF_CALLOC (1, sizeof(*new_ev_ctx), gf_gld_mt_probe_ctx_t); + + if (!new_ev_ctx) { + ret = -1; + goto out; + } + + new_ev_ctx->hostname = gf_strdup (peerinfo->hostname); + new_ev_ctx->port = peerinfo->port; + new_ev_ctx->req = NULL; + + new_event->peerinfo = peerinfo; + new_event->ctx = new_ev_ctx; + + ret = glusterd_friend_sm_inject_event (new_event); + + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to inject new_event %d, " + "ret = %d", new_event->event, ret); + } + +out: + if (ret) { + GF_FREE (new_event); + GF_FREE (new_ev_ctx->hostname); + GF_FREE (new_ev_ctx); + } + gf_log ("", GF_LOG_DEBUG, "returning with %d", ret); + return ret; +} + +static int glusterd_ac_friend_add (glusterd_friend_sm_event_t *event, void *ctx) { int ret = 0; @@ -76,7 +262,6 @@ glusterd_ac_friend_add (glusterd_friend_sm_event_t *event, void *ctx) glusterd_conf_t *conf = NULL; xlator_t *this = NULL; - GF_ASSERT (event); peerinfo = event->peerinfo; @@ -84,9 +269,10 @@ glusterd_ac_friend_add (glusterd_friend_sm_event_t *event, void *ctx) conf = this->private; GF_ASSERT (conf); - GF_ASSERT (conf->mgmt); - proc = &conf->mgmt->proctable[GD_MGMT_FRIEND_ADD]; + if (!peerinfo->peer) + goto out; + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_ADD]; if (proc->fn) { frame = create_frame (this, this->ctx->pool); if (!frame) { @@ -96,13 +282,6 @@ glusterd_ac_friend_add (glusterd_friend_sm_event_t *event, void *ctx) ret = proc->fn (frame, this, event); } -/* ret = glusterd_xfer_friend_req_msg (peerinfo, THIS); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to probe: %s", hostname); - } -*/ - out: gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); @@ -113,17 +292,17 @@ static int glusterd_ac_friend_probe (glusterd_friend_sm_event_t *event, void *ctx) { int ret = -1; - char *hostname = NULL; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; glusterd_conf_t *conf = NULL; xlator_t *this = NULL; glusterd_probe_ctx_t *probe_ctx = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + dict_t *dict = NULL; GF_ASSERT (ctx); probe_ctx = ctx; - hostname = probe_ctx->hostname; this = THIS; @@ -132,36 +311,58 @@ glusterd_ac_friend_probe (glusterd_friend_sm_event_t *event, void *ctx) conf = this->private; GF_ASSERT (conf); - if (!conf->mgmt) - goto out; + ret = glusterd_friend_find (NULL, probe_ctx->hostname, &peerinfo); + if (ret) { + //We should not reach this state ideally + GF_ASSERT (0); + goto out; + } - proc = &conf->mgmt->proctable[GD_MGMT_PROBE_QUERY]; + if (!peerinfo->peer) + goto out; + proc = &peerinfo->peer->proctable[GLUSTERD_PROBE_QUERY]; if (proc->fn) { frame = create_frame (this, this->ctx->pool); if (!frame) { goto out; } frame->local = ctx; - ret = proc->fn (frame, this, hostname); - } + dict = dict_new (); + if (!dict) + goto out; + ret = dict_set_str (dict, "hostname", probe_ctx->hostname); + if (ret) + goto out; + ret = dict_set_int32 (dict, "port", probe_ctx->port); + if (ret) + goto out; -/* ret = glusterd_friend_probe (hostname); + ret = dict_set_static_ptr (dict, "peerinfo", peerinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "failed to set peerinfo"); + goto out; + } + + ret = proc->fn (frame, this, dict); + if (ret) + goto out; - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to probe: %s", hostname); } -*/ + out: + if (dict) + dict_unref (dict); gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); return ret; } static int -glusterd_ac_send_friend_remove_req (glusterd_friend_sm_event_t *event, void *ctx) +glusterd_ac_send_friend_remove_req (glusterd_friend_sm_event_t *event, + void *data) { int ret = 0; glusterd_peerinfo_t *peerinfo = NULL; @@ -169,7 +370,9 @@ glusterd_ac_send_friend_remove_req (glusterd_friend_sm_event_t *event, void *ctx call_frame_t *frame = NULL; glusterd_conf_t *conf = NULL; xlator_t *this = NULL; - + glusterd_friend_sm_event_type_t event_type = GD_FRIEND_EVENT_NONE; + glusterd_probe_ctx_t *ctx = NULL; + glusterd_friend_sm_event_t *new_event = NULL; GF_ASSERT (event); peerinfo = event->peerinfo; @@ -178,28 +381,178 @@ glusterd_ac_send_friend_remove_req (glusterd_friend_sm_event_t *event, void *ctx conf = this->private; GF_ASSERT (conf); - GF_ASSERT (conf->mgmt); - proc = &conf->mgmt->proctable[GD_MGMT_FRIEND_REMOVE]; + ctx = event->ctx; + + if (!peerinfo->connected) { + event_type = GD_FRIEND_EVENT_REMOVE_FRIEND; + + ret = glusterd_friend_sm_new_event (event_type, &new_event); + + if (!ret) { + new_event->peerinfo = peerinfo; + ret = glusterd_friend_sm_inject_event (new_event); + } else { + gf_log ("glusterd", GF_LOG_ERROR, + "Unable to get event"); + } + + if (ctx) + ret = glusterd_xfer_cli_deprobe_resp (ctx->req, ret, 0, + NULL, + ctx->hostname, + ctx->dict); + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ctx) { + glusterd_broadcast_friend_delete (ctx->hostname, NULL); + glusterd_destroy_probe_ctx (ctx); + } + goto out; + } + + if (!peerinfo->peer) + goto out; + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_REMOVE]; if (proc->fn) { frame = create_frame (this, this->ctx->pool); if (!frame) { goto out; } - frame->local = ctx; + frame->local = data; ret = proc->fn (frame, this, event); } -/* ret = glusterd_xfer_friend_req_msg (peerinfo, THIS); +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to probe: %s", hostname); + return ret; +} + +static gf_boolean_t +glusterd_should_update_peer (glusterd_peerinfo_t *peerinfo, + glusterd_peerinfo_t *cur_peerinfo) +{ + gf_boolean_t is_valid = _gf_false; + + if ((peerinfo == cur_peerinfo) || + (peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED)) + is_valid = _gf_true; + + return is_valid; +} + +static int +glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_peerinfo_t *cur_peerinfo = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + rpc_clnt_procedure_t *proc = NULL; + xlator_t *this = NULL; + glusterd_friend_update_ctx_t ev_ctx = {{0}}; + glusterd_conf_t *priv = NULL; + dict_t *friends = NULL; + char key[100] = {0,}; + char *dup_buf = NULL; + int32_t count = 0; + + GF_ASSERT (event); + cur_peerinfo = event->peerinfo; + + this = THIS; + priv = this->private; + + GF_ASSERT (priv); + + ev_ctx.op = GD_FRIEND_UPDATE_ADD; + + friends = dict_new (); + if (!friends) + goto out; + + snprintf (key, sizeof (key), "op"); + ret = dict_set_int32 (friends, key, ev_ctx.op); + if (ret) + goto out; + + list_for_each_entry (peerinfo, &priv->peers, uuid_list) { + if (!glusterd_should_update_peer (peerinfo, cur_peerinfo)) + continue; + + count++; + snprintf (key, sizeof (key), "friend%d.uuid", count); + dup_buf = gf_strdup (uuid_utoa (peerinfo->uuid)); + ret = dict_set_dynstr (friends, key, dup_buf); + if (ret) + goto out; + snprintf (key, sizeof (key), "friend%d.hostname", count); + ret = dict_set_str (friends, key, peerinfo->hostname); + if (ret) + goto out; + gf_log ("", GF_LOG_INFO, "Added uuid: %s, host: %s", + dup_buf, peerinfo->hostname); + } + + ret = dict_set_int32 (friends, "count", count); + if (ret) + goto out; + + list_for_each_entry (peerinfo, &priv->peers, uuid_list) { + if (!peerinfo->connected || !peerinfo->peer) + continue; + + if (!glusterd_should_update_peer (peerinfo, cur_peerinfo)) + continue; + + ret = dict_set_static_ptr (friends, "peerinfo", peerinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "failed to set peerinfo"); + goto out; + } + + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_UPDATE]; + if (proc->fn) { + ret = proc->fn (NULL, this, friends); + } } -*/ -out: gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); +out: + if (friends) + dict_unref (friends); + + return ret; +} + +static int +glusterd_peer_detach_cleanup (glusterd_conf_t *priv) +{ + int ret = -1; + glusterd_volinfo_t *volinfo = NULL; + glusterd_volinfo_t *tmp_volinfo = NULL; + + GF_ASSERT (priv); + + list_for_each_entry_safe (volinfo,tmp_volinfo, + &priv->volumes, vol_list) { + if (!glusterd_friend_contains_vol_bricks (volinfo, + MY_UUID)) { + gf_log (THIS->name, GF_LOG_INFO, + "Deleting stale volume %s", volinfo->volname); + ret = glusterd_delete_volume (volinfo); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Error deleting stale volume"); + goto out; + } + } + } + ret = 0; +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -210,20 +563,41 @@ glusterd_ac_handle_friend_remove_req (glusterd_friend_sm_event_t *event, int ret = 0; glusterd_peerinfo_t *peerinfo = NULL; glusterd_friend_req_ctx_t *ev_ctx = NULL; + glusterd_friend_sm_event_t *new_event = NULL; + glusterd_conf_t *priv = NULL; GF_ASSERT (ctx); ev_ctx = ctx; peerinfo = event->peerinfo; GF_ASSERT (peerinfo); - uuid_clear (peerinfo->uuid); + priv = THIS->private; + GF_ASSERT (priv); - ret = glusterd_xfer_friend_remove_resp (ev_ctx->req, ev_ctx->hostname); + ret = glusterd_xfer_friend_remove_resp (ev_ctx->req, ev_ctx->hostname, + ev_ctx->port); - rpc_clnt_destroy (peerinfo->rpc); - peerinfo->rpc = NULL; + list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + ret = glusterd_friend_sm_new_event (GD_FRIEND_EVENT_REMOVE_FRIEND, + &new_event); + if (ret) + goto out; + + new_event->peerinfo = peerinfo; + + ret = glusterd_friend_sm_inject_event (new_event); + if (ret) + goto out; + } + ret = glusterd_peer_detach_cleanup (priv); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, + "Peer detach cleanup was not successful"); + ret = 0; + } +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } @@ -233,13 +607,15 @@ glusterd_ac_friend_remove (glusterd_friend_sm_event_t *event, void *ctx) { int ret = -1; - ret = glusterd_friend_cleanup (event->peerinfo); + ret = glusterd_friend_remove_cleanup_vols (event->peerinfo->uuid); + if (ret) + gf_log (THIS->name, GF_LOG_WARNING, "Volumes cleanup failed"); + ret = glusterd_friend_cleanup (event->peerinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Cleanup returned: %d", ret); + gf_log (THIS->name, GF_LOG_ERROR, "Cleanup returned: %d", ret); } - return 0; } @@ -260,9 +636,12 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) uuid_t uuid; glusterd_peerinfo_t *peerinfo = NULL; glusterd_friend_req_ctx_t *ev_ctx = NULL; + glusterd_friend_update_ctx_t *new_ev_ctx = NULL; glusterd_friend_sm_event_t *new_event = NULL; glusterd_friend_sm_event_type_t event_type = GD_FRIEND_EVENT_NONE; int status = 0; + int32_t op_ret = -1; + int32_t op_errno = 0; GF_ASSERT (ctx); ev_ctx = ctx; @@ -272,11 +651,19 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) uuid_copy (peerinfo->uuid, ev_ctx->uuid); //Build comparison logic here. + ret = glusterd_compare_friend_data (ev_ctx->vols, &status, + peerinfo->hostname); + if (ret) + goto out; - if (!status) + if (GLUSTERD_VOL_COMP_RJT != status) { event_type = GD_FRIEND_EVENT_LOCAL_ACC; - else + op_ret = 0; + } else { event_type = GD_FRIEND_EVENT_LOCAL_RJT; + op_errno = GF_PROBE_VOLUME_CONFLICT; + op_ret = -1; + } ret = glusterd_friend_sm_new_event (event_type, &new_event); @@ -285,10 +672,27 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) } new_event->peerinfo = peerinfo; + + new_ev_ctx = GF_CALLOC (1, sizeof (*new_ev_ctx), + gf_gld_mt_friend_update_ctx_t); + if (!new_ev_ctx) { + ret = -1; + goto out; + } + + uuid_copy (new_ev_ctx->uuid, ev_ctx->uuid); + new_ev_ctx->hostname = gf_strdup (ev_ctx->hostname); + new_ev_ctx->op = GD_FRIEND_UPDATE_ADD; + + new_event->ctx = new_ev_ctx; + glusterd_friend_sm_inject_event (new_event); - ret = glusterd_xfer_friend_add_resp (ev_ctx->req, ev_ctx->hostname); + ret = glusterd_xfer_friend_add_resp (ev_ctx->req, ev_ctx->hostname, + peerinfo->hostname, ev_ctx->port, + op_ret, op_errno); +out: gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); return ret; @@ -303,10 +707,11 @@ glusterd_friend_sm_transition_state (glusterd_peerinfo_t *peerinfo, GF_ASSERT (state); GF_ASSERT (peerinfo); - //peerinfo->state.state = state; + (void) glusterd_sm_tr_log_transition_add (&peerinfo->sm_log, + peerinfo->state.state, + state[event_type].next_state, + event_type); - gf_log ("", GF_LOG_NORMAL, "Transitioning from %d to %d", - peerinfo->state.state, state[event_type].next_state); peerinfo->state.state = state[event_type].next_state; return 0; } @@ -321,11 +726,60 @@ glusterd_sm_t glusterd_state_default [] = { {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_RJT {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_error}, //EV_INIT_REMOVE_FRIEND - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_send_friend_remove_req}, //EV_INIT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_probe}, //EVENT_CONNECTED {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_MAX }; +glusterd_sm_t glusterd_state_probe_rcvd [] = { + {GD_FRIEND_STATE_PROBE_RCVD, glusterd_ac_none}, + {GD_FRIEND_STATE_PROBE_RCVD, glusterd_ac_none}, //EV_PROBE + {GD_FRIEND_STATE_PROBE_RCVD, glusterd_ac_none}, //EV_INIT_FRIEND_REQ + {GD_FRIEND_STATE_PROBE_RCVD, glusterd_ac_none}, //EVENT_RCVD_ACC + {GD_FRIEND_STATE_PROBE_RCVD, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC + {GD_FRIEND_STATE_PROBE_RCVD, glusterd_ac_none}, //EVENT_RCVD_RJT + {GD_FRIEND_STATE_PROBE_RCVD, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT + {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_send_friend_remove_req}, //EV_INIT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, //EVENT_CONNECTED + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_MAX +}; + +glusterd_sm_t glusterd_state_connected_rcvd [] = { + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, //EV_PROBE + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, //EV_INIT_FRIEND_REQ + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, //EVENT_RCVD_ACC + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_reverse_probe_begin}, //EVENT_RCVD_LOCAL_ACC + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, //EVENT_RCVD_RJT + {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_send_friend_remove_req}, //EV_INIT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, //EVENT_CONNECTED + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none}, //EVENT_MAX +}; + +glusterd_sm_t glusterd_state_connected_accepted [] = { + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_friend_probe}, //EV_PROBE + {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_friend_add}, //EV_INIT_FRIEND_REQ + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, //EVENT_RCVD_ACC + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, //EVENT_RCVD_RJT + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, //EVENT_RCV_FRIEND_REQ + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_send_friend_remove_req}, //EV_INIT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, //EVENT_CONNECTED + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_none}, //EVENT_MAX +}; glusterd_sm_t glusterd_state_req_sent [] = { {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none}, //EVENT_NONE, @@ -336,22 +790,26 @@ glusterd_sm_t glusterd_state_req_sent [] = { {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_RJT {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_INIT_REMOVE_FRIEND, - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_send_friend_remove_req}, //EVENT_INIT_REMOVE_FRIEND, + {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none},//EVENT_CONNECTED {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none},//EVENT_MAX }; glusterd_sm_t glusterd_state_req_rcvd [] = { {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_NONE, - {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_friend_probe}, //EVENT_PROBE, - {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_friend_add}, //EVENT_INIT_FRIEND_REQ, + {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_PROBE, + {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_INIT_FRIEND_REQ, {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_RCVD_ACC - {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC + {GD_FRIEND_STATE_REQ_ACCEPTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_RCVD_RJT - {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT + {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_RCV_FRIEND_REQ - {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_error}, //EVENT_INIT_REMOVE_FRIEND, - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_send_friend_remove_req}, //EVENT_INIT_REMOVE_FRIEND, + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_handle_friend_remove_req}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_CONNECTED_RCVD, glusterd_ac_none},//EVENT_CONNECTED {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none},//EVENT_MAX }; @@ -360,12 +818,14 @@ glusterd_sm_t glusterd_state_befriended [] = { {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_PROBE, {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_INIT_FRIEND_REQ, {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_ACC - {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC - {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_RJT - {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT - {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCV_FRIEND_REQ + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_send_friend_update}, //EVENT_RCVD_LOCAL_ACC + {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_RJT + {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_send_friend_remove_req}, //EVENT_INIT_REMOVE_FRIEND, - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_handle_friend_remove_req}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_handle_friend_remove_req}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_friend_add},//EVENT_CONNECTED {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none},//EVENT_MAX }; @@ -373,13 +833,15 @@ glusterd_sm_t glusterd_state_req_sent_rcvd [] = { {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_NONE, {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_PROBE, {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_INIT_FRIEND_REQ, - {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_ACC + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_send_friend_update}, //EVENT_RCVD_ACC {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_RJT {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_RCV_FRIEND_REQ {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_send_friend_remove_req}, //EVENT_INIT_REMOVE_FRIEND, - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_handle_friend_remove_req}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none},//EVENT_CONNECTED {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none},//EVENT_MAX }; @@ -387,13 +849,15 @@ glusterd_sm_t glusterd_state_rejected [] = { {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_NONE, {GD_FRIEND_STATE_REJECTED, glusterd_ac_friend_probe}, //EVENT_PROBE, {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_friend_add}, //EVENT_INIT_FRIEND_REQ, - {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_ACC - {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_ACC + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_RJT {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_INIT_REMOVE_FRIEND - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_send_friend_remove_req}, //EVENT_INIT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_handle_friend_remove_req}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_REJECTED, glusterd_ac_friend_add},//EVENT_CONNECTED {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none},//EVENT_MAX }; @@ -401,18 +865,20 @@ glusterd_sm_t glusterd_state_req_accepted [] = { {GD_FRIEND_STATE_REQ_ACCEPTED, glusterd_ac_none}, //EVENT_NONE, {GD_FRIEND_STATE_REQ_ACCEPTED, glusterd_ac_none}, //EVENT_PROBE, {GD_FRIEND_STATE_REQ_ACCEPTED, glusterd_ac_none}, //EVENT_INIT_FRIEND_REQ, - {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_ACC - {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_ACC + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_send_friend_update}, //EVENT_RCVD_ACC + {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_send_friend_update}, //EVENT_RCVD_LOCAL_ACC {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_RJT {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_LOCAL_RJT {GD_FRIEND_STATE_REQ_ACCEPTED, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_INIT_REMOVE_FRIEND - {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_REQ_ACCEPTED, glusterd_ac_send_friend_remove_req}, //EVENT_INIT_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_handle_friend_remove_req}, //EVENT_RCVD_REMOVE_FRIEND + {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_CONNECTED_ACCEPTED, glusterd_ac_reverse_probe_begin},//EVENT_CONNECTED {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none},//EVENT_MAX }; glusterd_sm_t glusterd_state_unfriend_sent [] = { - {GD_FRIEND_STATE_REQ_ACCEPTED, glusterd_ac_none}, //EVENT_NONE, + {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_none}, //EVENT_NONE, {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_error}, //EVENT_PROBE, {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_none}, //EVENT_INIT_FRIEND_REQ, {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_none}, //EVENT_RCVD_ACC @@ -421,7 +887,9 @@ glusterd_sm_t glusterd_state_unfriend_sent [] = { {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_error}, //EVENT_RCVD_LOCAL_RJT {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_error}, //EVENT_RCV_FRIEND_REQ {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_none}, //EVENT_INIT_REMOVE_FRIEND + {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_none}, //EVENT_RCVD_REMOVE_FRIEND {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_remove}, //EVENT_REMOVE_FRIEND + {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_none},//EVENT_CONNECTED {GD_FRIEND_STATE_UNFRIEND_SENT, glusterd_ac_none},//EVENT_MAX }; @@ -430,10 +898,13 @@ glusterd_sm_t *glusterd_friend_state_table [] = { glusterd_state_req_sent, glusterd_state_req_rcvd, glusterd_state_befriended, + glusterd_state_req_accepted, glusterd_state_req_sent_rcvd, glusterd_state_rejected, - glusterd_state_req_accepted, glusterd_state_unfriend_sent, + glusterd_state_probe_rcvd, + glusterd_state_connected_rcvd, + glusterd_state_connected_accepted }; int @@ -462,78 +933,170 @@ int glusterd_friend_sm_inject_event (glusterd_friend_sm_event_t *event) { GF_ASSERT (event); - gf_log ("glusterd", GF_LOG_NORMAL, "Enqueuing event: %d", - event->event); + gf_log ("glusterd", GF_LOG_DEBUG, "Enqueue event: '%s'", + glusterd_friend_sm_event_name_get (event->event)); list_add_tail (&event->list, &gd_friend_sm_queue); return 0; } +void +glusterd_destroy_friend_event_context (glusterd_friend_sm_event_t *event) +{ + if (!event) + return; + + switch (event->event) { + case GD_FRIEND_EVENT_RCVD_FRIEND_REQ: + case GD_FRIEND_EVENT_RCVD_REMOVE_FRIEND: + glusterd_destroy_friend_req_ctx (event->ctx); + break; + case GD_FRIEND_EVENT_LOCAL_ACC: + case GD_FRIEND_EVENT_LOCAL_RJT: + case GD_FRIEND_EVENT_RCVD_ACC: + case GD_FRIEND_EVENT_RCVD_RJT: + glusterd_destroy_friend_update_ctx (event->ctx); + break; + default: + break; + } +} + +gf_boolean_t +gd_does_peer_affect_quorum (glusterd_friend_sm_state_t old_state, + glusterd_friend_sm_event_type_t event_type, + glusterd_peerinfo_t *peerinfo) +{ + gf_boolean_t affects = _gf_false; + + //When glusterd comes up with friends in BEFRIENDED state in store, + //wait until compare-data happens. + if ((old_state == GD_FRIEND_STATE_BEFRIENDED) && + (event_type != GD_FRIEND_EVENT_RCVD_ACC) && + (event_type != GD_FRIEND_EVENT_LOCAL_ACC)) + goto out; + if ((peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED) + && peerinfo->connected) { + affects = _gf_true; + } +out: + return affects; +} int glusterd_friend_sm () { - glusterd_friend_sm_event_t *event = NULL; - glusterd_friend_sm_event_t *tmp = NULL; - int ret = -1; - glusterd_friend_sm_ac_fn handler = NULL; - glusterd_sm_t *state = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_friend_sm_event_type_t event_type = 0; + glusterd_friend_sm_event_t *event = NULL; + glusterd_friend_sm_event_t *tmp = NULL; + int ret = -1; + glusterd_friend_sm_ac_fn handler = NULL; + glusterd_sm_t *state = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_friend_sm_event_type_t event_type = 0; + gf_boolean_t is_await_conn = _gf_false; + gf_boolean_t quorum_action = _gf_false; + glusterd_friend_sm_state_t old_state = GD_FRIEND_STATE_DEFAULT; + + while (!list_empty (&gd_friend_sm_queue)) { + list_for_each_entry_safe (event, tmp, &gd_friend_sm_queue, list) { + + list_del_init (&event->list); + event_type = event->event; + peerinfo = event->peerinfo; + if (!peerinfo) { + gf_log ("glusterd", GF_LOG_CRITICAL, "Received" + " event %s with empty peer info", + glusterd_friend_sm_event_name_get (event_type)); + + GF_FREE (event); + continue; + } + gf_log ("", GF_LOG_DEBUG, "Dequeued event of type: '%s'", + glusterd_friend_sm_event_name_get (event_type)); + - list_for_each_entry_safe (event, tmp, &gd_friend_sm_queue, list) { + old_state = peerinfo->state.state; + state = glusterd_friend_state_table[peerinfo->state.state]; - list_del_init (&event->list); - peerinfo = event->peerinfo; - event_type = event->event; + GF_ASSERT (state); - if (!peerinfo && - (GD_FRIEND_EVENT_PROBE == event_type || - GD_FRIEND_EVENT_RCVD_FRIEND_REQ == event_type)) { - ret = glusterd_friend_add (NULL, - GD_FRIEND_STATE_DEFAULT, - NULL, NULL, &peerinfo); + handler = state[event_type].handler; + GF_ASSERT (handler); + + ret = handler (event, event->ctx); + if (ret == GLUSTERD_CONNECTION_AWAITED) { + is_await_conn = _gf_true; + ret = 0; + } if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to add peer, " - "ret = %d", ret); + gf_log ("glusterd", GF_LOG_ERROR, "handler returned: " + "%d", ret); + glusterd_destroy_friend_event_context (event); + GF_FREE (event); continue; } - GF_ASSERT (peerinfo); - event->peerinfo = peerinfo; - } - - state = glusterd_friend_state_table[peerinfo->state.state]; - - GF_ASSERT (state); + if ((GD_FRIEND_EVENT_REMOVE_FRIEND == event_type) || + (GD_FRIEND_EVENT_INIT_REMOVE_FRIEND == event_type)){ + glusterd_destroy_friend_event_context (event); + GF_FREE (event); + continue; + } - handler = state[event_type].handler; - GF_ASSERT (handler); + ret = glusterd_friend_sm_transition_state (peerinfo, + state, event_type); - ret = handler (event, event->ctx); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to transition" + " state from '%s' to '%s' for event '%s'", + glusterd_friend_sm_state_name_get(peerinfo->state.state), + glusterd_friend_sm_state_name_get(state[event_type].next_state), + glusterd_friend_sm_event_name_get(event_type)); + goto out; + } - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "handler returned: " - "%d", ret); - return ret; - } + if (gd_does_peer_affect_quorum (old_state, event_type, + peerinfo)) { + peerinfo->quorum_contrib = QUORUM_UP; + if (peerinfo->quorum_action) { + peerinfo->quorum_action = _gf_false; + quorum_action = _gf_true; + } + } - ret = glusterd_friend_sm_transition_state (peerinfo, state, event_type); + ret = glusterd_store_peerinfo (peerinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to transition" - "state from %d to %d", peerinfo->state.state, - state[event_type].next_state); - return ret; + glusterd_destroy_friend_event_context (event); + GF_FREE (event); + if (is_await_conn) + break; } - - GF_FREE (event); + if (is_await_conn) + break; } - ret = 0; - +out: + if (quorum_action) { + /* When glusterd is restarted, it needs to wait until the 'friends' view + * of the volumes settle, before it starts any of the internal daemons. + * + * Every friend that was part of the cluster, would send its + * cluster-view, 'our' way. For every friend, who belongs to + * a partition which has a different cluster-view from our + * partition, we may update our cluster-view. For subsequent + * friends from that partition would agree with us, if the first + * friend wasn't rejected. For every first friend, whom we agreed with, + * we would need to start internal daemons/bricks belonging to the + * new volumes. + * glusterd_spawn_daemons calls functions that are idempotent. ie, + * the functions spawn process(es) only if they are not started yet. + * + * */ + glusterd_spawn_daemons (NULL); + glusterd_do_quorum_action (); + } return ret; } |
