summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-sm.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-sm.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-sm.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c
new file mode 100644
index 00000000000..53a0f5af8f8
--- /dev/null
+++ b/xlators/mgmt/glusterd/src/glusterd-sm.c
@@ -0,0 +1,384 @@
+/*
+ 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/>.
+*/
+
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+#include <time.h>
+#include <sys/uio.h>
+#include <sys/resource.h>
+
+#include <libgen.h>
+#include <uuid/uuid.h>
+
+//#include "transport.h"
+#include "fnmatch.h"
+#include "xlator.h"
+#include "protocol-common.h"
+#include "glusterd.h"
+#include "call-stub.h"
+#include "defaults.h"
+#include "list.h"
+#include "dict.h"
+#include "compat.h"
+#include "compat-errno.h"
+#include "statedump.h"
+#include "glusterd-sm.h"
+
+static struct list_head gd_friend_sm_queue;
+
+static int
+glusterd_ac_none (glusterd_friend_sm_event_t *event, void *ctx)
+{
+ int ret = 0;
+
+ 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;
+ glusterd_peerinfo_t *peerinfo = NULL;
+ rpc_clnt_procedure_t *proc = NULL;
+ call_frame_t *frame = NULL;
+ glusterd_conf_t *conf = NULL;
+ xlator_t *this = NULL;
+
+
+ GF_ASSERT (event);
+ peerinfo = event->peerinfo;
+
+ this = THIS;
+ conf = this->private;
+
+ GF_ASSERT (conf);
+ GF_ASSERT (conf->mgmt);
+
+ proc = &conf->mgmt->proctable[GD_MGMT_FRIEND_ADD];
+ if (proc->fn) {
+ frame = create_frame (this, this->ctx->pool);
+ if (!frame) {
+ goto out;
+ }
+ frame->local = 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);
+
+ return ret;
+}
+
+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;
+
+ GF_ASSERT (ctx);
+
+ probe_ctx = ctx;
+ hostname = probe_ctx->hostname;
+
+ this = THIS;
+
+ GF_ASSERT (this);
+
+ conf = this->private;
+
+ GF_ASSERT (conf);
+ if (!conf->mgmt)
+ goto out;
+
+
+ proc = &conf->mgmt->proctable[GD_MGMT_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);
+ }
+
+
+/* ret = glusterd_friend_probe (hostname);
+
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to probe: %s", hostname);
+ }
+*/
+
+out:
+ gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
+
+ return ret;
+}
+
+/*static int
+glusterd_ac_none (void *ctx)
+{
+ int ret = 0;
+
+ gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
+
+ return ret;
+}*/
+
+static int
+glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx)
+{
+ int ret = 0;
+ uuid_t uuid;
+ glusterd_peerinfo_t *peerinfo = NULL;
+ glusterd_friend_req_ctx_t *ev_ctx = NULL;
+
+ GF_ASSERT (ctx);
+ ev_ctx = ctx;
+ uuid_copy (uuid, ev_ctx->uuid);
+ peerinfo = event->peerinfo;
+ GF_ASSERT (peerinfo);
+ uuid_copy (peerinfo->uuid, ev_ctx->uuid);
+
+ ret = glusterd_xfer_friend_add_resp (ev_ctx->req, ev_ctx->hostname);
+
+ gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
+
+ return ret;
+}
+
+static int
+glusterd_friend_sm_transition_state (glusterd_peerinfo_t *peerinfo,
+ glusterd_sm_t *state,
+ glusterd_friend_sm_event_type_t event_type)
+{
+
+ GF_ASSERT (state);
+ GF_ASSERT (peerinfo);
+
+ //peerinfo->state.state = state;
+
+ 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;
+}
+
+
+glusterd_sm_t glusterd_state_default [] = {
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none},
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_friend_probe},//EV_PROBE
+ {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_friend_add}, //EV_INIT_FRIEND_REQ
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_ACC
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_RCVD_RJT
+ {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_MAX
+};
+
+
+glusterd_sm_t glusterd_state_req_sent [] = {
+ {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none}, //EVENT_NONE,
+ {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none}, //EVENT_PROBE,
+ {GD_FRIEND_STATE_REQ_SENT, glusterd_ac_none}, //EVENT_INIT_FRIEND_REQ,
+ {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCVD_ACC
+ {GD_FRIEND_STATE_REJECTED, glusterd_ac_none}, //EVENT_RCVD_RJT
+ {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND
+ {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_RCVD_ACC
+ {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_RCVD_RJT
+ {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none}, //EVENT_RCV_FRIEND_REQ
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND
+ {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none},//EVENT_MAX
+};
+
+glusterd_sm_t glusterd_state_befriended [] = {
+ {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_NONE,
+ {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_RJT
+ {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none}, //EVENT_RCV_FRIEND_REQ
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND
+ {GD_FRIEND_STATE_BEFRIENDED, glusterd_ac_none},//EVENT_MAX
+};
+
+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_REJECTED, glusterd_ac_none}, //EVENT_RCVD_RJT
+ {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none}, //EVENT_RCV_FRIEND_REQ
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND
+ {GD_FRIEND_STATE_REQ_SENT_RCVD, glusterd_ac_none},//EVENT_MAX
+};
+
+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_RJT
+ {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_handle_friend_add_req}, //EVENT_RCV_FRIEND_REQ
+ {GD_FRIEND_STATE_DEFAULT, glusterd_ac_none}, //EVENT_REMOVE_FRIEND
+ {GD_FRIEND_STATE_REQ_RCVD, glusterd_ac_none},//EVENT_MAX
+};
+
+glusterd_sm_t *glusterd_friend_state_table [] = {
+ glusterd_state_default,
+ glusterd_state_req_sent,
+ glusterd_state_req_rcvd,
+ glusterd_state_befriended,
+ glusterd_state_req_sent_rcvd,
+ glusterd_state_rejected,
+};
+
+int
+glusterd_friend_sm_new_event (glusterd_friend_sm_event_type_t event_type,
+ glusterd_friend_sm_event_t **new_event)
+{
+ glusterd_friend_sm_event_t *event = NULL;
+
+ GF_ASSERT (new_event);
+ GF_ASSERT (GD_FRIEND_EVENT_NONE <= event_type &&
+ GD_FRIEND_EVENT_MAX > event_type);
+
+ event = GF_CALLOC (1, sizeof (*event), gf_gld_mt_friend_sm_event_t);
+
+ if (!event)
+ return -1;
+
+ *new_event = event;
+ event->event = event_type;
+ INIT_LIST_HEAD (&event->list);
+
+ return 0;
+}
+
+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);
+ list_add_tail (&event->list, &gd_friend_sm_queue);
+
+ return 0;
+}
+
+
+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;
+
+ list_for_each_entry_safe (event, tmp, &gd_friend_sm_queue, list) {
+
+ list_del_init (&event->list);
+ peerinfo = event->peerinfo;
+ event_type = event->event;
+
+ if (!peerinfo &&
+ (GD_FRIEND_EVENT_PROBE == event_type ||
+ GD_FRIEND_EVENT_RCVD_FRIEND_REQ == event_type)) {
+ ret = glusterd_friend_add (NULL, GD_PEER_STATE_NONE, NULL, NULL,
+ &peerinfo);
+
+ if (ret) {
+ gf_log ("glusterd", GF_LOG_ERROR, "Unable to add peer, "
+ "ret = %d", ret);
+ continue;
+ }
+ GF_ASSERT (peerinfo);
+ event->peerinfo = peerinfo;
+ }
+
+
+ state = glusterd_friend_state_table[peerinfo->state.state];
+
+ GF_ASSERT (state);
+
+ handler = state[event_type].handler;
+ GF_ASSERT (handler);
+
+ ret = handler (event, event->ctx);
+
+ if (ret) {
+ gf_log ("glusterd", GF_LOG_ERROR, "handler returned: "
+ "%d", ret);
+ return ret;
+ }
+
+ ret = glusterd_friend_sm_transition_state (peerinfo, state, event_type);
+
+ 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;
+ }
+
+ GF_FREE (event);
+ }
+
+
+ ret = 0;
+
+ return ret;
+}
+
+
+int
+glusterd_friend_sm_init ()
+{
+ INIT_LIST_HEAD (&gd_friend_sm_queue);
+ return 0;
+}