diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-handler.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 1388 | 
1 files changed, 1388 insertions, 0 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c new file mode 100644 index 000000000..00067a566 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -0,0 +1,1388 @@ +/* +  Copyright (c) 2006-2009 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is 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 <inttypes.h> + + +#include "globals.h" +#include "glusterfs.h" +#include "compat.h" +#include "dict.h" +#include "protocol-common.h" +#include "xlator.h" +#include "logging.h" +#include "timer.h" +#include "defaults.h" +#include "compat.h" +#include "compat-errno.h" +#include "statedump.h" +#include "glusterd-mem-types.h" +#include "glusterd.h" +#include "glusterd-sm.h" +#include "glusterd-op-sm.h" +#include "glusterd-utils.h" +#include "gd-xdr.h" +#include "cli-xdr.h" +#include "rpc-clnt.h" + +#include <sys/resource.h> +#include <inttypes.h> + +/* for default_*_cbk functions */ +#include "defaults.c" +#include "common-utils.h" + + +/*typedef int32_t (*glusterd_mop_t) (call_frame_t *frame, +                            gf_hdr_common_t *hdr, size_t hdrlen);*/ + +//static glusterd_mop_t glusterd_ops[GF_MOP_MAXVALUE]; + + + +static int +glusterd_friend_find_by_hostname (const char *hoststr,  +                                  glusterd_peerinfo_t  **peerinfo) +{ +        int                     ret = -1; +        glusterd_conf_t         *priv = NULL; +        glusterd_peerinfo_t     *entry = NULL; + +        GF_ASSERT (hoststr); +        GF_ASSERT (peerinfo); + +        *peerinfo = NULL; +        priv    = THIS->private; + +        GF_ASSERT (priv); + +        list_for_each_entry (entry, &priv->peers, uuid_list) { +                if (entry->hostname && (!strncmp (entry->hostname, hoststr, +                                        sizeof (entry->hostname)))) { +                         +                        gf_log ("glusterd", GF_LOG_NORMAL, +                                 "Friend %s found.. state: %d", hoststr, +                                  entry->state.state); +                        *peerinfo = entry; +                        return 0; +                } +        } + +        return ret; +} + +static int +glusterd_friend_find_by_uuid (uuid_t uuid,  +                              glusterd_peerinfo_t  **peerinfo) +{ +        int                     ret = -1; +        glusterd_conf_t         *priv = NULL; +        glusterd_peerinfo_t     *entry = NULL; + +        GF_ASSERT (peerinfo); + +        *peerinfo = NULL; +        priv    = THIS->private; + +        GF_ASSERT (priv); + +        list_for_each_entry (entry, &priv->peers, uuid_list) { +                if (!uuid_compare (entry->uuid, uuid)) { +                         +                        gf_log ("glusterd", GF_LOG_NORMAL, +                                 "Friend found.. state: %d", +                                  entry->state.state); +                        *peerinfo = entry; +                        return 0; +                } +        } + +        return ret; +} + +static int +glusterd_handle_friend_req (rpcsvc_request_t *req, uuid_t  uuid, char *hostname) +{ +        int                             ret = -1; +        glusterd_peerinfo_t             *peerinfo = NULL; +        glusterd_friend_sm_event_t      *event = NULL; +        glusterd_friend_req_ctx_t       *ctx = NULL; + + +        ret = glusterd_friend_find (uuid, hostname, &peerinfo); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_NORMAL,  +                         "Unable to find peer"); + +        } + +        ret = glusterd_friend_sm_new_event  +                        (GD_FRIEND_EVENT_RCVD_FRIEND_REQ, &event); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "event generation failed: %d", ret); +                return ret; +        } + +        event->peerinfo = peerinfo; + +        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_friend_req_ctx_t); + +        if (!ctx) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                ret = -1; +                goto out; +        } + +        uuid_copy (ctx->uuid, uuid); +        if (hostname) +                ctx->hostname = gf_strdup (hostname); +        ctx->req = req; + +        event->ctx = ctx; + +        ret = glusterd_friend_sm_inject_event (event); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to inject event %d, " +                        "ret = %d", event->event, ret); +                goto out; +        } +        +        ret = 0; + +out: +        if (0 != ret) { +                if (ctx && ctx->hostname) +                        GF_FREE (ctx->hostname); +                if (ctx) +                        GF_FREE (ctx); +        } + +        return ret; +} + + + + + +int +glusterd_friend_find (uuid_t uuid, char *hostname,  +                      glusterd_peerinfo_t **peerinfo) +{ +        int     ret = -1; + +        if (uuid) { +                ret = glusterd_friend_find_by_uuid (uuid, peerinfo); + +                if (ret) { +                        gf_log ("glusterd", GF_LOG_NORMAL,  +                                 "Unable to find peer by uuid"); +                } else { +                        goto out; +                } + +        } + +        if (hostname) { +                ret = glusterd_friend_find_by_hostname (hostname, peerinfo); + +                if (ret) { +                        gf_log ("glusterd", GF_LOG_NORMAL, +                                "Unable to find hostname: %s", hostname); +                } else { +                        goto out; +                } +        } + +out: +        return ret; +} + +int +glusterd_handle_cluster_lock (rpcsvc_request_t *req) +{ +        gd1_mgmt_cluster_lock_req       lock_req = {{0},}; +        int32_t                         ret = -1; +        char                            str[50] = {0,}; +        glusterd_op_sm_event_t          *event = NULL; +        glusterd_op_lock_ctx_t          *ctx = NULL; + +        GF_ASSERT (req); + +        if (!gd_xdr_to_mgmt_friend_req (req->msg[0], &lock_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } +        uuid_unparse (lock_req.uuid, str); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received LOCK from uuid: %s", str); + +        ret = glusterd_op_sm_new_event (GD_OP_EVENT_LOCK, &event); + +        if (ret) { +                //respond back here +                return ret; +        } +                 +        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_stage_ctx_t); + +        if (!ctx) { +                //respond here +                return -1; +        } + +        uuid_copy (ctx->uuid, lock_req.uuid); +        ctx->req = req; +        event->ctx = ctx; + +        ret = glusterd_op_sm_inject_event (event); + +out: +        gf_log ("", GF_LOG_NORMAL, "Returning %d", ret); + +        return ret; +} + +int +glusterd_handle_stage_op (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        char                            str[50]; +        gd1_mgmt_stage_op_req           *stage_req = NULL; +        glusterd_op_sm_event_t          *event = NULL; +        glusterd_op_stage_ctx_t         *ctx = NULL;  + +        GF_ASSERT (req); + +        stage_req = GF_CALLOC (1, sizeof (*stage_req),  +                               gf_gld_mt_mop_stage_req_t); + +        GF_ASSERT (stage_req); + +        if (!gd_xdr_to_mgmt_stage_op_req (req->msg[0], stage_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        uuid_unparse (stage_req->uuid, str); +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received stage op from uuid: %s", str); + +        ret = glusterd_op_sm_new_event (GD_OP_EVENT_STAGE_OP, &event); + +        if (ret) { +                //respond back here +                return ret; +        } +                 +        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_stage_ctx_t); + +        if (!ctx) { +                //respond here +                return -1; +        } + +        //CHANGE THIS +        ctx->stage_req = &stage_req; +        ctx->req   = req; +        event->ctx = ctx; + +        ret = glusterd_op_sm_inject_event (event); + +out:         +        return ret; +} + +int +glusterd_handle_commit_op (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        char                            str[50]; +        glusterd_op_sm_event_t          *event = NULL; +        gd1_mgmt_commit_op_req          commit_req = {{0},}; +        glusterd_op_commit_ctx_t        *ctx = NULL;  + +        GF_ASSERT (req); + +        if (!gd_xdr_to_mgmt_commit_op_req (req->msg[0], &commit_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        uuid_unparse (commit_req.uuid, str); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received commit op from uuid: %s", str); + +        ret = glusterd_op_sm_new_event (GD_OP_EVENT_COMMIT_OP, &event); + +        if (ret) { +                //respond back here +                return ret; +        } +                 +        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_commit_ctx_t); + +        if (!ctx) { +                //respond here +                return -1; +        } + +        ctx->req = req; +        //CHANGE THIS +        ctx->stage_req   = &commit_req; +        event->ctx = ctx; + +        ret = glusterd_op_sm_inject_event (event); + +out: +        return ret; +} + +int +glusterd_handle_cli_probe (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_probe_req               cli_req = {0,}; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_probe_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_NORMAL, "Received CLI probe req"); + + +        ret = glusterd_probe_begin (req, cli_req.hostname); + +out: +        return ret; +} + +int +glusterd_handle_create_volume (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_create_vol_req          cli_req = {0,}; +        dict_t                          *dict = NULL; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_create_vol_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_NORMAL, "Received create volume req"); + +        if (cli_req.bricks.bricks_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); + +                ret = dict_unserialize (cli_req.bricks.bricks_val,  +                                        cli_req.bricks.bricks_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        goto out; +                } +        } + +        ret = glusterd_create_volume (req, dict); + +out: +        return ret; +} + +int +glusterd_op_lock_send_resp (rpcsvc_request_t *req, int32_t status) +{ + +        gd1_mgmt_cluster_lock_rsp       rsp = {{0},}; +        int                             ret = -1; + +        GF_ASSERT (req); +        glusterd_get_uuid (&rsp.uuid); +        rsp.op_ret = status; + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,  +                                     gd_xdr_serialize_mgmt_cluster_lock_rsp); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Responded, ret: %d", ret); + +        return 0; +} + +int +glusterd_op_unlock_send_resp (rpcsvc_request_t *req, int32_t status) +{ + +        gd1_mgmt_cluster_unlock_rsp     rsp = {{0},}; +        int                             ret = -1; + +        GF_ASSERT (req); +        rsp.op_ret = status; +        glusterd_get_uuid (&rsp.uuid); + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,  +                                     gd_xdr_serialize_mgmt_cluster_unlock_rsp); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Responded to unlock, ret: %d", ret); + +        return ret; +} + +int +glusterd_handle_cluster_unlock (rpcsvc_request_t *req) +{ +        gd1_mgmt_cluster_unlock_req     unlock_req = {{0}, }; +        int32_t                         ret = -1; +        char                            str[50] = {0, }; +        glusterd_op_lock_ctx_t          *ctx = NULL; +        glusterd_op_sm_event_t          *event = NULL; + +        GF_ASSERT (req); + +        if (!gd_xdr_to_mgmt_friend_req (req->msg[0], &unlock_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        uuid_unparse (unlock_req.uuid, str); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received UNLOCK from uuid: %s", str); + +        ret = glusterd_op_sm_new_event (GD_OP_EVENT_UNLOCK, &event); + +        if (ret) { +                //respond back here +                return ret; +        } +                 +        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_lock_ctx_t); + +        if (!ctx) { +                //respond here +                return -1; +        } +        event->ctx = ctx; +        uuid_copy (ctx->uuid, unlock_req.uuid); +        ctx->req = req; + +        ret = glusterd_op_sm_inject_event (event); + +out: +        return ret; +} + +int +glusterd_op_stage_send_resp (rpcsvc_request_t   *req,  +                             int32_t op, int32_t status) +{ + +        gd1_mgmt_stage_op_rsp           rsp = {{0},}; +        int                             ret = -1; + +        GF_ASSERT (req); +        rsp.op_ret = status; +        glusterd_get_uuid (&rsp.uuid); +        rsp.op = op; + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,  +                                     gd_xdr_serialize_mgmt_stage_op_rsp); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Responded to stage, ret: %d", ret); + +        return ret; +} + +int +glusterd_op_commit_send_resp (rpcsvc_request_t *req,  +                               int32_t op, int32_t status) +{ +        gd1_mgmt_commit_op_rsp          rsp = {{0}, }; +        int                             ret = -1; + +        GF_ASSERT (req); +        rsp.op_ret = status; +        glusterd_get_uuid (&rsp.uuid); +        rsp.op = op; + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,  +                                     gd_xdr_serialize_mgmt_commit_op_rsp); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Responded to commit, ret: %d", ret); + +        return ret; +} + +int +glusterd_handle_incoming_friend_req (rpcsvc_request_t *req) +{ +        int32_t                 ret = -1; +        gd1_mgmt_friend_req     friend_req = {{0},}; +        char                    str[50]; + +        GF_ASSERT (req); +        if (!gd_xdr_to_mgmt_friend_req (req->msg[0], &friend_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } +        uuid_unparse (friend_req.uuid, str); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received probe from uuid: %s", str); + +        ret = glusterd_handle_friend_req (req, friend_req.uuid,  +                                          friend_req.hostname); + +out: + +        return ret; +} + +int +glusterd_handle_probe_query (rpcsvc_request_t *req) +{ +        int32_t             ret = -1; +        char                str[50]; +        xlator_t            *this = NULL; +        glusterd_conf_t     *conf = NULL; +        gd1_mgmt_probe_req  probe_req = {{0},}; +        gd1_mgmt_probe_rsp  rsp = {{0},}; +        char                hostname[1024] = {0}; + +        GF_ASSERT (req); + +        probe_req.hostname = hostname; + +        if (!gd_xdr_to_mgmt_probe_req (req->msg[0], &probe_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + + +        uuid_unparse (probe_req.uuid, str); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received probe from uuid: %s", str); + + +        this = THIS; + +        conf = this->private; + +        uuid_copy (rsp.uuid, conf->uuid); +        rsp.hostname = gf_strdup (probe_req.hostname); + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,  +                                     gd_xdr_serialize_mgmt_probe_rsp); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Responded to %s, ret: %d", probe_req.hostname, ret); + +out: +        return ret; +} + +/*int +glusterd_handle_friend_req_resp (call_frame_t *frame, +                                 gf_hdr_common_t *rsp_hdr, size_t hdrlen) +{ +        gf_mop_probe_rsp_t      *rsp = NULL; +        int32_t                 ret = -1; +        char                    str[50]; +        glusterd_peerinfo_t     *peerinfo = NULL; +        int32_t                 op_ret = -1; +        glusterd_friend_sm_event_type_t event_type = GD_FRIEND_EVENT_NONE; +        glusterd_friend_sm_event_t      *event = NULL; + +        GF_ASSERT (rsp_hdr); + +        rsp   = gf_param (rsp_hdr); +        uuid_unparse (rsp->uuid, str); + +        op_ret = rsp_hdr->rsp.op_ret; + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received %s from uuid: %s, host: %s",  +                (op_ret)?"RJT":"ACC", str, rsp->hostname); + +        ret = glusterd_friend_find (rsp->uuid, rsp->hostname, &peerinfo); + +        if (ret) { +                GF_ASSERT (0); +        } + +        if (op_ret)  +                event_type = GD_FRIEND_EVENT_RCVD_ACC; +        else +                event_type = GD_FRIEND_EVENT_RCVD_RJT; + +        ret = glusterd_friend_sm_new_event (event_type, &event); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, +                         "Unable to get event"); +                return ret; +        } + +        event->peerinfo = peerinfo; +        ret = glusterd_friend_sm_inject_event (event); + +        gf_log ("glusterd", GF_LOG_NORMAL, "Received resp to friend req"); + +        return 0; +}*/ + +/*int +glusterd_handle_probe_resp (call_frame_t *frame, gf_hdr_common_t *rsp_hdr,  +                            size_t hdrlen) +{ +        gf_mop_probe_rsp_t      *rsp = NULL; +        int32_t                 ret = -1; +        char                    str[50]; +        glusterd_peerinfo_t        *peerinfo = NULL; +        glusterd_friend_sm_event_t *event = NULL; +        glusterd_peerinfo_t        *dup_peerinfo = NULL; + +        GF_ASSERT (rsp_hdr); + +        rsp   = gf_param (rsp_hdr); +        uuid_unparse (rsp->uuid, str); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Received probe resp from uuid: %s, host: %s",  +                str, rsp->hostname); + +        ret = glusterd_friend_find (rsp->uuid, rsp->hostname, &peerinfo); + +        if (ret) { +                GF_ASSERT (0); +        } + +        if (!peerinfo->hostname) { +                glusterd_friend_find_by_hostname (rsp->hostname, &dup_peerinfo); +                GF_ASSERT (dup_peerinfo); +                GF_ASSERT (dup_peerinfo->hostname); +                peerinfo->hostname = gf_strdup (rsp->hostname); +                peerinfo->trans = dup_peerinfo->trans; +                list_del_init (&dup_peerinfo->uuid_list); +                GF_FREE (dup_peerinfo->hostname); +                GF_FREE (dup_peerinfo); +        } +        GF_ASSERT (peerinfo->hostname); +        uuid_copy (peerinfo->uuid, rsp->uuid); + +        ret = glusterd_friend_sm_new_event  +                        (GD_FRIEND_EVENT_INIT_FRIEND_REQ, &event); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, +                         "Unable to get event"); +                return ret; +        } + +        event->peerinfo = peerinfo; +        ret = glusterd_friend_sm_inject_event (event); + +        return 0; +}*/ + +/* +static glusterd_mop_t glusterd_ops[GF_MOP_MAXVALUE] = { +        [GF_MOP_PROBE_QUERY]     = glusterd_handle_probe_query, +        [GF_MOP_FRIEND_REQ]      = glusterd_handle_incoming_friend_req, +        [GF_MOP_STAGE_OP]        = glusterd_handle_stage_op, +        [GF_MOP_COMMIT_OP]       = glusterd_handle_commit_op, +        [GF_MOP_CLUSTER_LOCK]    = glusterd_handle_cluster_lock, +        [GF_MOP_CLUSTER_UNLOCK]  = glusterd_handle_cluster_unlock, +}; + +static glusterd_mop_t glusterd_resp_ops [GF_MOP_MAXVALUE] = { +        [GF_MOP_PROBE_QUERY]    = glusterd_handle_probe_resp, +        [GF_MOP_FRIEND_REQ]     = glusterd_handle_friend_req_resp, +}; +*/ + +/*int +glusterd_xfer_probe_msg (glusterd_peerinfo_t *peerinfo, xlator_t *this) +{ +        gf_hdr_common_t       *hdr = NULL; +        gf_mop_probe_req_t    *req = NULL; +        size_t                hdrlen = -1; +        int                   ret = -1; +        glusterd_conf_t       *priv = NULL; +        call_frame_t          *dummy_frame = NULL; +        int                   len = 0; + +        GF_ASSERT (peerinfo); +        GF_ASSERT (this); + +        priv = this->private; +        GF_ASSERT (priv); + +        len = STRLEN_0 (peerinfo->hostname); +        hdrlen = gf_hdr_len (req, len); +        hdr    = gf_hdr_new (req, len); + +        GF_VALIDATE_OR_GOTO (this->name, hdr, unwind); + +        req         = gf_param (hdr); +        memcpy (&req->uuid, &priv->uuid, sizeof(uuid_t)); +        strncpy (req->hostname, peerinfo->hostname, len); + +        dummy_frame = create_frame (this, this->ctx->pool); + +        if (!dummy_frame) +                goto unwind; + +        dummy_frame->local = peerinfo->trans; + +        ret = glusterd_xfer (dummy_frame, this, +                             peerinfo->trans, +                             GF_OP_TYPE_MOP_REQUEST, GF_MOP_PROBE_QUERY, +                             hdr, hdrlen, NULL, 0, NULL); + +        return ret; + +unwind: +        if (hdr) +                GF_FREE (hdr); + +        return 0; +}*/ + +/*int +glusterd_xfer_friend_req_msg (glusterd_peerinfo_t *peerinfo, xlator_t *this) +{ +        gf_hdr_common_t       *hdr = NULL; +        gf_mop_probe_req_t    *req = NULL; +        size_t                hdrlen = -1; +        int                   ret = -1; +        glusterd_conf_t       *priv = NULL; +        call_frame_t          *dummy_frame = NULL; +        int                   len = 0; + +        GF_ASSERT (peerinfo); +        GF_ASSERT (this); + +        priv = this->private; +        GF_ASSERT (priv); + +        len = STRLEN_0 (peerinfo->hostname); +        hdrlen = gf_hdr_len (req, len); +        hdr    = gf_hdr_new (req, len); + +        GF_VALIDATE_OR_GOTO (this->name, hdr, unwind); + +        req         = gf_param (hdr); +        memcpy (&req->uuid, &priv->uuid, sizeof(uuid_t)); +        strncpy (req->hostname, peerinfo->hostname, len); + +        dummy_frame = create_frame (this, this->ctx->pool); + +        if (!dummy_frame) +                goto unwind; + +        dummy_frame->local = peerinfo->trans; + +        ret = glusterd_xfer (dummy_frame, this, +                             peerinfo->trans, +                             GF_OP_TYPE_MOP_REQUEST, GF_MOP_FRIEND_REQ, +                             hdr, hdrlen, NULL, 0, NULL); + +        return ret; + +unwind: +        if (hdr) +                GF_FREE (hdr); + +        //STACK_UNWIND (frame, -1, EINVAL, NULL); +        return 0; +}*/ + +/*int +glusterd_xfer_cluster_lock_req (xlator_t *this, int32_t *lock_count) +{ +        gd1_mgmt_cluster_lock_req       req = {{0},}; +        int                             ret = -1; +        glusterd_conf_t                 *priv = NULL; +        call_frame_t                    *dummy_frame = NULL; +        glusterd_peerinfo_t             *peerinfo = NULL; +        int                             pending_lock = 0; +        rpc_clnt_procedure_t            *proc = NULL; + +        GF_ASSERT (this); +        GF_ASSERT (lock_count); + +        priv = this->private; +        GF_ASSERT (priv); + +        uuid_copy (req.uuid, priv->uuid); + +        dummy_frame = create_frame (this, this->ctx->pool); + +        if (!dummy_frame) +                goto unwind; + + +        list_for_each_entry (peerinfo, &priv->peers, uuid_list) { +                GF_ASSERT (peerinfo); + +                if (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED)  +                        continue; + +         +                ret = glusterd_submit_request (peerinfo, &req, dummy_frame,  +                                               prog, GD_MGMT_PROBE_QUERY, +                                               NULL, gd_xdr_from_mgmt_probe_req, +                                               this); +                if (!ret) +                        pending_lock++; +        } + +        gf_log ("glusterd", GF_LOG_NORMAL, "Sent lock req to %d peers", +                                            pending_lock); +        *lock_count = pending_lock; + +unwind: + +        return ret; +}*/ + +/*int +glusterd_xfer_cluster_unlock_req (xlator_t *this, int32_t *pending_count) +{ +        gf_hdr_common_t       *hdr = NULL; +        gf_mop_cluster_unlock_req_t    *req = NULL; +        size_t                hdrlen = -1; +        int                   ret = -1; +        glusterd_conf_t       *priv = NULL; +        call_frame_t          *dummy_frame = NULL; +        glusterd_peerinfo_t   *peerinfo = NULL; +        int                   pending_unlock = 0; + +        GF_ASSERT (this); +        GF_ASSERT (pending_count); + +        priv = this->private; +        GF_ASSERT (priv); + +        hdrlen = gf_hdr_len (req, 0); +        hdr    = gf_hdr_new (req, 0); + +        GF_VALIDATE_OR_GOTO (this->name, hdr, unwind); + +        req         = gf_param (hdr); +        uuid_copy (req->uuid, priv->uuid); + +        dummy_frame = create_frame (this, this->ctx->pool); + +        if (!dummy_frame) +                goto unwind; + + +        list_for_each_entry (peerinfo, &priv->peers, uuid_list) { +                GF_ASSERT (peerinfo); + +                if (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED)  +                        continue; + +         +                ret = glusterd_xfer (dummy_frame, this, +                                     peerinfo->trans, +                                     GF_OP_TYPE_MOP_REQUEST,  +                                     GF_MOP_CLUSTER_UNLOCK, +                                     hdr, hdrlen, NULL, 0, NULL); +                if (!ret) +                        pending_unlock++; +        } + +        gf_log ("glusterd", GF_LOG_NORMAL, "Sent unlock req to %d peers", +                                            pending_unlock); +        *pending_count = pending_unlock; + +unwind: +        if (hdr) +                GF_FREE (hdr); + +        return ret; +}*/ + + +int +glusterd_friend_add (const char *hoststr, +                     glusterd_peer_state_t state, +                     uuid_t *uuid, +                     struct rpc_clnt    *rpc, +                     glusterd_peerinfo_t **friend) +{ +        int                     ret = 0; +        glusterd_conf_t         *priv = NULL; +        glusterd_peerinfo_t     *peerinfo = NULL; +        dict_t                  *options = NULL; +        char                    *port_str = NULL; +        int                     port_num = 0; +        struct rpc_clnt_config  rpc_cfg = {0,}; + +        priv = THIS->private; + +        peerinfo = GF_CALLOC (1, sizeof(*peerinfo), gf_gld_mt_peerinfo_t); + +        if (!peerinfo) +                return -1; + +        if (friend) +                *friend = peerinfo; + +        peerinfo->state.state = state; +        if (hoststr) { +                peerinfo->hostname = gf_strdup (hoststr); +                rpc_cfg.remote_host = gf_strdup (hoststr); +        } +        INIT_LIST_HEAD (&peerinfo->uuid_list); + +        list_add_tail (&peerinfo->uuid_list, &priv->peers); + +        if (uuid) { +                uuid_copy (peerinfo->uuid, *uuid); +        }  + + +        if (hoststr) { +                options = dict_new (); +                if (!options) +                        return -1; + +                ret = dict_set_str (options, "remote-host", (char *)hoststr); +                if (ret) +                        goto out; + + +                port_str = getenv ("GLUSTERD_REMOTE_PORT"); +                port_num = atoi (port_str); +                rpc_cfg.remote_port = port_num; + +                gf_log ("glusterd", GF_LOG_NORMAL, "remote-port: %d", port_num); + +                //ret = dict_set_int32 (options, "remote-port", GLUSTERD_DEFAULT_PORT);  +                ret = dict_set_int32 (options, "remote-port", port_num);  +                if (ret) +                        goto out; + +                ret = dict_set_str (options, "transport.address-family", "inet"); +                if (ret) +                        goto out; + +                rpc = rpc_clnt_init (&rpc_cfg, options, THIS->ctx, THIS->name); + +                if (!rpc) { +                        gf_log ("glusterd", GF_LOG_ERROR,  +                                "rpc init failed for peer: %s!", hoststr); +                        ret = -1; +                        goto out; +                } +         +                ret = rpc_clnt_register_notify (rpc, glusterd_rpc_notify, +                                                peerinfo); + +                peerinfo->rpc = rpc; + +        } + +        gf_log ("glusterd", GF_LOG_NORMAL, "connect returned %d", ret); + +out: +        return ret; + +} + +/*int +glusterd_friend_probe (const char *hoststr) +{ +        int                     ret = -1; +        glusterd_peerinfo_t     *peerinfo = NULL; + + +        ret = glusterd_friend_find (NULL, (char *)hoststr, &peerinfo); + +        if (ret) { +                //We should not reach this state ideally +                GF_ASSERT (0); +                goto out;  +        } +         +        ret = glusterd_xfer_probe_msg (peerinfo, THIS); +         +out: +        return ret; +}*/ + +int +glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr) +{ +        int                             ret = -1; +        glusterd_peerinfo_t             *peerinfo = NULL; +        glusterd_friend_sm_event_t      *event = NULL; +        glusterd_probe_ctx_t            *ctx = NULL; + +        GF_ASSERT (hoststr); +        GF_ASSERT (req); + +        ret = glusterd_friend_find (NULL, (char *)hoststr, &peerinfo); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_NORMAL, "Unable to find peerinfo" +                                " for host: %s", hoststr); +                ret = glusterd_friend_add ((char *)hoststr, GD_PEER_STATE_NONE,  +                                           NULL, NULL, &peerinfo); +        } + +        ret = glusterd_friend_sm_new_event  +                        (GD_FRIEND_EVENT_PROBE, &event); +         +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get new event"); +                return ret; +        } + +        ctx = GF_CALLOC (1, sizeof(*ctx), gf_gld_mt_probe_ctx_t); + +        if (!ctx) { +                return ret; +        } + +        ctx->hostname = gf_strdup (hoststr); +        ctx->req = req; + +        event->peerinfo = peerinfo; +        event->ctx = ctx; + +        ret = glusterd_friend_sm_inject_event (event); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to inject event %d, " +                        "ret = %d", event->event, ret); +                return ret; +        } + +        return ret; +} + +/*int +glusterd_interpret (xlator_t *this, transport_t *trans, +                    char *hdr_p, size_t hdrlen, struct iobuf *iobuf) +{ +        glusterd_connection_t       *conn = NULL; +        gf_hdr_common_t             *hdr = NULL; +        xlator_t                    *bound_xl = NULL; +        call_frame_t                *frame = NULL; +        peer_info_t                 *peerinfo = NULL; +        int32_t                      type = -1; +        int32_t                      op = -1; +        int32_t                      ret = 0; + +        hdr  = (gf_hdr_common_t *)hdr_p; +        type = ntoh32 (hdr->type); +        op   = ntoh32 (hdr->op); + +        conn = trans->xl_private; +        if (conn) +                bound_xl = conn->bound_xl; + +        if (GF_MOP_PROBE_QUERY != op) { +                //ret = glusterd_validate_sender (hdr, hdrlen); +        } + +        peerinfo = &trans->peerinfo; +        switch (type) { + +        case GF_OP_TYPE_MOP_REQUEST: +                if ((op < 0) || (op >= GF_MOP_MAXVALUE)) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "invalid mop %"PRId32" from  %s", +                                op, peerinfo->identifier); +                        break; +                } +                frame = glusterd_get_frame_for_call (trans, hdr); +		frame->op = op; +                ret = glusterd_ops[op] (frame, hdr, hdrlen); +                break; + +        case GF_OP_TYPE_MOP_REPLY: +                if ((op < 0) || (op >= GF_MOP_MAXVALUE)) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "invalid mop %"PRId32" from  %s", +                                op, peerinfo->identifier); +                        break; +                } +                ret = glusterd_resp_ops[op] (frame, hdr, hdrlen); +                gf_log ("glusterd", GF_LOG_NORMAL, "Obtained MOP response"); +                break; + + +        default: +                gf_log (this->name, GF_LOG_ERROR, +                        "Unknown type: %d", type); +                ret = -1; +                break; +        } + +        return ret; +} +*/ + +int +glusterd_xfer_friend_add_resp (rpcsvc_request_t *req, char *hostname) +{ +        gd1_mgmt_friend_rsp  rsp = {{0}, }; +        int32_t              ret = -1; +        xlator_t             *this = NULL; +        glusterd_conf_t      *conf = NULL; + +        GF_ASSERT (hostname); + +        rsp.op_ret = 0; +        this = THIS; +        GF_ASSERT (this); + +        conf = this->private; + +        uuid_copy (rsp.uuid, conf->uuid); +        rsp.hostname = gf_strdup (hostname); + + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,  +                                     gd_xdr_serialize_mgmt_friend_rsp); + +        gf_log ("glusterd", GF_LOG_NORMAL,  +                "Responded to %s, ret: %d", hostname, ret); +        return ret; +} + +int +glusterd_xfer_cli_probe_resp (rpcsvc_request_t *req, int32_t op_ret, +                              int32_t op_errno, char *hostname) +{ +        gf1_cli_probe_rsp    rsp = {0, }; +        int32_t              ret = -1; + +        GF_ASSERT (req); + +        rsp.op_ret = op_ret; +        rsp.op_errno = op_errno; +        rsp.hostname = hostname; + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL,  +                                     gf_xdr_serialize_cli_probe_rsp); + +        gf_log ("glusterd", GF_LOG_NORMAL, "Responded to CLI, ret: %d",ret); + +        return ret; +} + +int32_t +glusterd_op_txn_begin () +{ +        int32_t                 ret = -1; +        glusterd_conf_t         *priv = NULL; +        glusterd_op_sm_event_t     *event = NULL; +        int32_t                 locked = 0; + +        priv = THIS->private; +        GF_ASSERT (priv); + +        ret = glusterd_lock (priv->uuid); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "Unable to acquire local lock, ret: %d", ret); +                goto out; +        } + +        locked = 1; +        gf_log ("glusterd", GF_LOG_NORMAL, "Acquired local lock"); + +        ret = glusterd_op_sm_new_event (GD_OP_EVENT_START_LOCK, &event); + +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "Unable to get event, ret: %d", ret); +                goto out; +        } + +        ret = glusterd_op_sm_inject_event (event); + +        gf_log ("glusterd", GF_LOG_NORMAL, "Returning %d", ret); + +out: +        if (locked && ret) +                glusterd_unlock (priv->uuid); +        return ret; +} + +int32_t +glusterd_create_volume (rpcsvc_request_t *req, dict_t *dict) +{ +        int32_t      ret       = -1; +        char        *volname   = NULL; +        char        *bricks    = NULL; +        int          type      = 0; +        int          sub_count = 2; +        int          count     = 0; +        char         cmd_str[8192] = {0,}; + +        GF_ASSERT (req); +        GF_ASSERT (dict); + +        glusterd_op_set_op (GD_OP_CREATE_VOLUME); + +        glusterd_op_set_ctx (GD_OP_CREATE_VOLUME, dict); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) +                goto out; + +        ret = dict_get_int32 (dict, "type", &type); +        if (ret) +                goto out; + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) +                goto out; + +        ret = dict_get_str (dict, "bricks", &bricks); +        if (ret) +                goto out; + +        switch (type) { +        case GF_CLUSTER_TYPE_REPLICATE: +        { +                ret = dict_get_int32 (dict, "replica-count", &sub_count); +                if (ret) +                        goto out; +                snprintf (cmd_str, 8192, +                          "glusterfs-volgen -n %s -c /etc/glusterd -r 1 %s", +                          volname, bricks); +                system (cmd_str); +                break; +        } +        case GF_CLUSTER_TYPE_STRIPE: +        { +                ret = dict_get_int32 (dict, "stripe-count", &sub_count); +                if (ret) +                        goto out; +                snprintf (cmd_str, 8192, +                          "glusterfs-volgen -n %s -c /etc/glusterd -r 0 %s", +                          volname, bricks); +                system (cmd_str); +                break; +        } +        case GF_CLUSTER_TYPE_NONE: +        { +                snprintf (cmd_str, 8192, +                          "glusterfs-volgen -n %s -c /etc/glusterd %s", +                          volname, bricks); +                system (cmd_str); +                break; +        } +        } + +        ret = glusterd_op_txn_begin (); + +out: +        return ret; +} + + +int +glusterd_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, +                     void *data) +{ +        xlator_t        *this = NULL; +        char            *handshake = NULL; +        glusterd_conf_t     *conf = NULL; +        int             ret = 0; + +        this = mydata; +        conf = this->private; + + +        switch (event) { +        case RPC_CLNT_CONNECT: +        { +                // connect happened, send 'get_supported_versions' mop +                ret = dict_get_str (this->options, "disable-handshake", +                                    &handshake); + +                gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT"); + +                if ((ret < 0) || (strcasecmp (handshake, "on"))) { +                        //ret = client_handshake (this, conf->rpc); + +                } else { +                        //conf->rpc->connected = 1; +                        ret = default_notify (this, GF_EVENT_CHILD_UP, NULL); +                }  +                break; +        } + +        case RPC_CLNT_DISCONNECT: + +                //Inject friend disconnected here + +                gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT"); + +                default_notify (this, GF_EVENT_CHILD_DOWN, NULL); +                break; + +        default: +                gf_log (this->name, GF_LOG_TRACE, +                        "got some other RPC event %d", event); +                ret = 0; +                break; +        } + +        return ret; +}  | 
