diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-sm.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-sm.c | 384 | 
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; +}  | 
