From 10eafa32914f2458f3bb30073724758a95a82310 Mon Sep 17 00:00:00 2001 From: shishir gowda Date: Wed, 16 Mar 2011 03:35:46 +0000 Subject: TOP: glusterd/mgmt related changes Signed-off-by: shishir gowda Signed-off-by: Vijay Bellur BUG: 2516 (Implement gluster volume top command) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2516 --- xlators/mgmt/glusterd/src/glusterd-handler.c | 18 +- xlators/mgmt/glusterd/src/glusterd-op-sm.c | 262 ++++++++++++++++++++++++++- xlators/mgmt/glusterd/src/glusterd-op-sm.h | 8 +- xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 3 +- 4 files changed, 278 insertions(+), 13 deletions(-) (limited to 'xlators/mgmt/glusterd') diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index d4e2dd34..e4334af4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -2981,7 +2981,7 @@ glusterd_handle_cli_profile_volume (rpcsvc_request_t *req) gf_boolean_t free_volname = _gf_true; int lock_fail = 0; glusterd_op_t cli_op = GD_OP_PROFILE_VOLUME; - + dict_t *tmp_dict = NULL; GF_ASSERT (req); @@ -3021,13 +3021,27 @@ glusterd_handle_cli_profile_volume (rpcsvc_request_t *req) goto out; } + tmp_dict = dict_new(); + if (!tmp_dict) + goto out; + dict_unserialize (cli_req.dict_req.dict_req_val, + cli_req.dict_req.dict_req_len, &tmp_dict); + + dict_copy (tmp_dict, dict); + ret = glusterd_op_begin (req, cli_op, dict, _gf_true); out: glusterd_friend_sm (); glusterd_op_sm (); - if (ret) + + if (tmp_dict) + dict_unref (tmp_dict); + + if (ret) dict_unref (dict); + if (cli_req.dict_req.dict_req_val) + free (cli_req.dict_req.dict_req_val); if (free_volname) free (cli_req.volname); // malloced by xdr if (ret) { diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 99b0609b..87c246a8 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -47,6 +47,7 @@ #include "glusterd-volgen.h" #include "syscall.h" #include "cli1.h" +#include "common-utils.h" #include #include @@ -181,21 +182,22 @@ glusterd_op_sm_inject_all_acc () int glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickinfo, - gd1_mgmt_brick_op_req **req) + gd1_mgmt_brick_op_req **req, dict_t *dict) { int ret = -1; gd1_mgmt_brick_op_req *brick_req = NULL; - dict_t *dict = NULL; + gf1_cli_top_op top_op = 0; + double throughput = 0; + double time = 0; + int32_t blk_size = 0; + int32_t blk_count = 0; GF_ASSERT (op < GD_OP_MAX); GF_ASSERT (op > GD_OP_NONE); GF_ASSERT (req); - dict = dict_new (); - if (!dict) - goto out; - switch (op) { + switch (op) { case GD_OP_REMOVE_BRICK: case GD_OP_STOP_VOLUME: brick_req = GF_CALLOC (1, sizeof (*brick_req), @@ -218,12 +220,47 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin brick_req->op = GF_BRICK_XLATOR_INFO; brick_req->name = brickinfo->path; - break; + + ret = dict_get_int32 (dict, "top-op", (int32_t*)&top_op); + if (ret) + goto cont; + if (top_op == GF_CLI_TOP_READ_PERF || + top_op == GF_CLI_TOP_WRITE_PERF) { + + ret = dict_get_int32 (dict, "blk-size", &blk_size); + if (ret) { + goto cont; + } + ret = dict_get_int32 (dict, "blk-cnt", &blk_count); + if (ret) + goto out; + if (top_op == GF_CLI_TOP_READ_PERF) + ret = glusterd_volume_stats_read_perf ( + brickinfo->path, blk_size, blk_count, + &throughput, &time); + else if (!ret && top_op == GF_CLI_TOP_WRITE_PERF) + ret = glusterd_volume_stats_write_perf ( + brickinfo->path, blk_size, blk_count, + &throughput, &time); + + if (ret) + goto out; + + ret = dict_set_double (dict, "throughput", + throughput); + if (ret) + goto out; + ret = dict_set_double (dict, "time", time); + if (ret) + goto out; + } + break; default: goto out; break; } +cont: ret = dict_allocate_and_serialize (dict, &brick_req->input.input_val, (size_t*)&brick_req->input.input_len); if (ret) @@ -232,8 +269,6 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin ret = 0; out: - if (dict) - dict_unref (dict); if (ret && brick_req) GF_FREE (brick_req); gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); @@ -2039,6 +2074,15 @@ glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) ret = -1; goto out; } + } else if (GF_CLI_STATS_TOP == stats_op) { + if (glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof (msg), "volume %s is not started.", + volinfo->volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } } out: @@ -5440,6 +5484,7 @@ glusterd_op_stats_volume (dict_t *dict, char **op_errstr, latency_value = gf_strdup ("off"); break; case GF_CLI_STATS_INFO: + case GF_CLI_STATS_TOP: //info is already collected in brick op. //just goto out; ret = 0; @@ -6806,6 +6851,7 @@ glusterd_bricks_select_stop_volume (dict_t *dict, char **op_errstr) glusterd_brickinfo_t *brickinfo = NULL; glusterd_pending_node_t *pending_node = NULL; + ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); if (ret) goto out; @@ -6911,6 +6957,7 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) int32_t stats_op = GF_CLI_STATS_NONE; glusterd_brickinfo_t *brickinfo = NULL; glusterd_pending_node_t *pending_node = NULL; + char *brick = NULL; this = THIS; GF_ASSERT (this); @@ -6928,6 +6975,7 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) snprintf (msg, sizeof (msg), "Volume %s does not exists", volname); + *op_errstr = gf_strdup (msg); gf_log ("", GF_LOG_ERROR, "%s", msg); goto out; } @@ -6960,6 +7008,46 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) } } break; + + case GF_CLI_STATS_TOP: + ret = dict_get_str (dict, "brick", &brick); + if (!ret) { + ret = glusterd_volume_brickinfo_get_by_brick (brick, + volinfo, &brickinfo); + if (ret) + goto out; + + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } else { + pending_node->node = brickinfo; + list_add_tail (&pending_node->list, + &opinfo.pending_bricks); + pending_node = NULL; + goto out; + } + } + ret = 0; + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (!glusterd_is_brick_started (brickinfo)) { + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } else { + pending_node->node = brickinfo; + list_add_tail (&pending_node->list, + &opinfo.pending_bricks); + pending_node = NULL; + } + } + } + break; + default: GF_ASSERT (0); gf_log ("glusterd", GF_LOG_ERROR, "Invalid profile op: %d", @@ -7747,4 +7835,160 @@ int32_t glusterd_opinfo_unlock(){ return (pthread_mutex_unlock(&opinfo.lock)); } +int32_t +glusterd_volume_stats_write_perf (char *brick_path, int32_t blk_size, + int32_t blk_count, double *throughput, double *time) +{ + int32_t fd = -1; + int32_t input_fd = -1; + char export_path[1024]; + char *buf = NULL; + int32_t iter = 0; + int32_t ret = -1; + int64_t total_blks = 0; + struct timeval begin, end = {0, }; + + + GF_VALIDATE_OR_GOTO ("stripe", brick_path, out); + + snprintf (export_path, sizeof(export_path), "%s/%s", + brick_path, ".gf_tmp_stats_perf"); + fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); + if (fd == -1) + return errno; + buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); + + if (!buf) + return ret; + + input_fd = open("/dev/zero", O_RDONLY); + if (input_fd == -1) + return errno; + gettimeofday (&begin, NULL); + for (iter = 0; iter < blk_count; iter++) { + ret = read (input_fd, buf, blk_size); + if (ret != blk_size) { + ret = -1; + goto out; + } + ret = write (fd, buf, blk_size); + if (ret != blk_size) { + ret = -1; + goto out; + } + total_blks += ret; + } + ret = 0; + if (total_blks != (blk_size * blk_count)) { + gf_log ("glusterd", GF_LOG_WARNING, "Errors in write"); + ret = -1; + goto out; + } + + gettimeofday (&end, NULL); + *time = (end.tv_sec - begin.tv_sec) * 1e6 + + (end.tv_usec - begin.tv_usec); + + *throughput = total_blks / *time; + gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f MBps time %.2f secs bytes " + "written %"PRId64, *throughput, *time / 1e6, total_blks); +out: + if (fd >= 0) + close (fd); + if (input_fd >= 0) + close (input_fd); + if (buf) + GF_FREE (buf); + unlink (export_path); + return ret; +} + +int32_t +glusterd_volume_stats_read_perf (char *brick_path, int32_t blk_size, + int32_t blk_count, double *throughput, double *time) +{ + int32_t fd = -1; + int32_t output_fd = -1; + int32_t input_fd = -1; + char export_path[1024]; + char *buf = NULL; + int32_t iter = 0; + int32_t ret = -1; + int64_t total_blks = 0; + struct timeval begin, end = {0, }; + + + GF_VALIDATE_OR_GOTO ("glusterd", brick_path, out); + + snprintf (export_path, sizeof(export_path), "%s/%s", + brick_path, ".gf_tmp_stats_perf"); + fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); + if (fd == -1) + return errno; + buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); + + if (!buf) + return ret; + + output_fd = open("/dev/null", O_RDWR); + if (output_fd == -1) + return errno; + input_fd = open("/dev/zero", O_RDONLY); + if (input_fd == -1) + return errno; + for (iter = 0; iter < blk_count; iter++) { + ret = read (input_fd, buf, blk_size); + if (ret != blk_size) { + ret = -1; + goto out; + } + ret = write (fd, buf, blk_size); + if (ret != blk_size) { + ret = -1; + goto out; + } + } + + + lseek (fd, 0L, 0); + gettimeofday (&begin, NULL); + for (iter = 0; iter < blk_count; iter++) { + ret = read (fd, buf, blk_size); + if (ret != blk_size) { + ret = -1; + goto out; + } + ret = write (output_fd, buf, blk_size); + if (ret != blk_size) { + ret = -1; + goto out; + } + total_blks += ret; + } + ret = 0; + if (total_blks != (blk_size * blk_count)) { + gf_log ("glusterd", GF_LOG_WARNING, "Errors in write"); + ret = -1; + goto out; + } + + gettimeofday (&end, NULL); + *time = (end.tv_sec - begin.tv_sec) * 1e6 + + (end.tv_usec - begin.tv_usec); + + *throughput = total_blks / *time; + gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f MBps time %.2f secs bytes " + "read %"PRId64, *throughput, *time / 1e6, total_blks); +out: + if (fd >= 0) + close (fd); + if (input_fd >= 0) + close (input_fd); + if (output_fd >= 0) + close (output_fd); + if (buf) + GF_FREE (buf); + unlink (export_path); + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index ff507abb..206418df 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -262,7 +262,7 @@ int32_t glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr); int glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickinfo, - gd1_mgmt_brick_op_req **req); + gd1_mgmt_brick_op_req **req, dict_t *dict); int32_t glusterd_handle_brick_rsp (glusterd_brickinfo_t *brickinfo, glusterd_op_t op, dict_t *rsp_dict, dict_t *ctx_dict, @@ -272,4 +272,10 @@ int32_t glusterd_op_init_ctx (glusterd_op_t op); int32_t glusterd_op_fini_ctx (glusterd_op_t op); +int32_t +glusterd_volume_stats_read_perf (char *brick_path, int32_t blk_size, + int32_t blk_count, double *throughput, double *time); +int32_t +glusterd_volume_stats_write_perf (char *brick_path, int32_t blk_size, + int32_t blk_count, double *throughput, double *time); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 966a8a94..ca420142 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -1763,7 +1763,8 @@ glusterd3_1_brick_op (call_frame_t *frame, xlator_t *this, continue; ret = glusterd_brick_op_build_payload (req_ctx->op, brickinfo, - (gd1_mgmt_brick_op_req **)&req); + (gd1_mgmt_brick_op_req **)&req, + req_ctx->dict); if (ret) goto out; -- cgit