From 66825f283a28c591af673a9fa752e5f5dd8302db Mon Sep 17 00:00:00 2001 From: Amar Tumballi Date: Fri, 25 Feb 2011 08:35:36 +0000 Subject: glusterd: keep mgmt program peerinfo specific With different version of glusterd in different machines, its not possible to support using just one mgmt program. Instead each peerinfo structure should have its own mgmt programs, so one glusterd can support multiple versions Signed-off-by: Amar Tumballi Signed-off-by: Anand V. Avati BUG: 2333 (make glusterd more rpc friendly) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2333 --- xlators/mgmt/glusterd/src/glusterd-handshake.c | 201 ++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) (limited to 'xlators/mgmt/glusterd/src/glusterd-handshake.c') diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 213bcc6fb48..b8218e7fd0f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -24,20 +24,22 @@ #endif #include "xlator.h" +#include "defaults.h" #include "glusterfs.h" #include "compat-errno.h" #include "glusterd.h" #include "glusterd-utils.h" +#include "glusterd-op-sm.h" #include "glusterfs3.h" #include "protocol-common.h" #include "rpcsvc.h" +extern struct rpc_clnt_program glusterd3_1_mgmt_prog; typedef ssize_t (*gfs_serialize_t) (struct iovec outmsg, void *data); - static size_t build_volfile_path (const char *volname, char *path, size_t path_len) @@ -211,3 +213,200 @@ struct rpcsvc_program gluster_handshake_prog = { .actors = gluster_handshake_actors, .numactors = GF_HNDSK_MAXVALUE, }; + +char *glusterd_dump_proc[GF_DUMP_MAXVALUE] = { + [GF_DUMP_NULL] = "NULL", + [GF_DUMP_DUMP] = "DUMP", +}; + +rpc_clnt_prog_t glusterd_dump_prog = { + .progname = "GLUSTERD-DUMP", + .prognum = GLUSTER_DUMP_PROGRAM, + .progver = GLUSTER_DUMP_VERSION, + .procnames = glusterd_dump_proc, +}; + +static int +glusterd_event_connected_inject (glusterd_peerctx_t *peerctx) +{ + GF_ASSERT (peerctx); + + glusterd_friend_sm_event_t *event = NULL; + glusterd_probe_ctx_t *ctx = NULL; + int ret = -1; + glusterd_peerinfo_t *peerinfo = NULL; + + + ret = glusterd_friend_sm_new_event + (GD_FRIEND_EVENT_CONNECTED, &event); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get new event"); + goto out; + } + + ctx = GF_CALLOC (1, sizeof(*ctx), gf_gld_mt_probe_ctx_t); + + if (!ctx) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Memory not available"); + goto out; + } + + peerinfo = peerctx->peerinfo; + ctx->hostname = gf_strdup (peerinfo->hostname); + ctx->port = peerinfo->port; + ctx->req = peerctx->args.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_CONNECTED ret = %d", ret); + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; +} + +int +glusterd_set_clnt_mgmt_program (glusterd_peerinfo_t *peerinfo, + gf_prog_detail *prog) +{ + gf_prog_detail *trav = NULL; + int ret = -1; + + if (!peerinfo || !prog) + goto out; + + trav = prog; + + while (trav) { + /* Select 'programs' */ + if ((glusterd3_1_mgmt_prog.prognum == trav->prognum) && + (glusterd3_1_mgmt_prog.progver == trav->progver)) { + peerinfo->mgmt = &glusterd3_1_mgmt_prog; + gf_log ("", GF_LOG_INFO, + "Using Program %s, Num (%"PRId64"), " + "Version (%"PRId64")", + trav->progname, trav->prognum, trav->progver); + ret = 0; + break; + } + if (ret) { + gf_log ("", GF_LOG_TRACE, + "%s (%"PRId64") not supported", trav->progname, + trav->progver); + } + trav = trav->next; + } + +out: + return ret; +} + +int +glusterd_peer_dump_version_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + int ret = -1; + gf_dump_rsp rsp = {0,}; + xlator_t *this = NULL; + gf_prog_detail *trav = NULL; + gf_prog_detail *next = NULL; + call_frame_t *frame = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_peerctx_t *peerctx = NULL; + + this = THIS; + frame = myframe; + peerctx = frame->local; + peerinfo = peerctx->peerinfo; + + if (-1 == req->rpc_status) { + gf_log ("", GF_LOG_ERROR, + "error through RPC layer, retry again later"); + goto out; + } + + ret = xdr_to_dump_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "failed to decode XDR"); + goto out; + } + if (-1 == rsp.op_ret) { + gf_log (frame->this->name, GF_LOG_ERROR, + "failed to get the 'versions' from remote server"); + goto out; + } + + /* Make sure we assign the proper program to peer */ + ret = glusterd_set_clnt_mgmt_program (peerinfo, rsp.prog); + if (ret) { + gf_log ("", GF_LOG_WARNING, "failed to set the mgmt program"); + goto out; + } + + ret = default_notify (this, GF_EVENT_CHILD_UP, NULL); + + if (GD_MODE_ON == peerctx->args.mode) { + ret = glusterd_event_connected_inject (peerctx); + peerctx->args.req = NULL; + } else if (GD_MODE_SWITCH_ON == peerctx->args.mode) { + peerctx->args.mode = GD_MODE_ON; + } + + glusterd_friend_sm (); + glusterd_op_sm (); + + ret = 0; +out: + + /* don't use GF_FREE, buffer was allocated by libc */ + if (rsp.prog) { + trav = rsp.prog; + while (trav) { + next = trav->next; + free (trav->progname); + free (trav); + trav = next; + } + } + + STACK_DESTROY (frame->root); + + if (ret != 0) + rpc_transport_disconnect (peerinfo->rpc->conn.trans); + + return 0; +} + + +int +glusterd_peer_handshake (xlator_t *this, struct rpc_clnt *rpc, + glusterd_peerctx_t *peerctx) +{ + call_frame_t *frame = NULL; + gf_dump_req req = {0,}; + int ret = 0; + + frame = create_frame (this, this->ctx->pool); + if (!frame) + goto out; + + frame->local = peerctx; + + req.gfs_id = 0xcafe; + + ret = glusterd_submit_request (peerctx->peerinfo, &req, frame, + &glusterd_dump_prog, GF_DUMP_DUMP, + NULL, xdr_from_dump_req, this, + glusterd_peer_dump_version_cbk); +out: + return ret; +} -- cgit