diff options
author | Amar Tumballi <amar@gluster.com> | 2011-02-25 08:35:36 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2011-03-01 02:05:40 -0800 |
commit | 66825f283a28c591af673a9fa752e5f5dd8302db (patch) | |
tree | 7ddbd46f3dec68930caeeccfd35b773c162cf086 /xlators/mgmt/glusterd/src/glusterd-handshake.c | |
parent | 204fc1205af14bdd98d9a86b9f7293c5b7f6747a (diff) |
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 <amar@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 2333 (make glusterd more rpc friendly)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2333
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-handshake.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 201 |
1 files changed, 200 insertions, 1 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 213bcc6fb..b8218e7fd 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; +} |