diff options
| author | shishir gowda <shishirng@gluster.com> | 2011-03-16 03:35:16 +0000 | 
|---|---|---|
| committer | Vijay Bellur <vijay@dev.gluster.com> | 2011-03-16 02:35:30 -0700 | 
| commit | 3d1fc9ebe2b0292108dd0737cf8f40d6fcb8cf51 (patch) | |
| tree | fa1e4b0454727a74e829a9cb25893394de8381d4 /cli/src | |
| parent | f208d7148fefd55b4073bda978816d71831ffefa (diff) | |
TOP: cli, rpc/xdr related changes
Signed-off-by: shishir gowda <shishirng@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 2516 (Implement gluster volume top command)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2516
Diffstat (limited to 'cli/src')
| -rw-r--r-- | cli/src/cli-cmd-parser.c | 133 | ||||
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 49 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 206 | ||||
| -rw-r--r-- | cli/src/cli.h | 3 | 
4 files changed, 390 insertions, 1 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 1dd963b66d8..87792c08c7d 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1237,3 +1237,136 @@ out:                  dict_destroy (dict);          return ret;  } + +int32_t +cli_cmd_volume_top_parse (const char **words, int wordcount, +                              dict_t **options) +{ +        dict_t  *dict           = NULL; +        char    *volname        = NULL; +        char    *value          = NULL; +        char    *key            = NULL; +        int      ret            = -1; +        gf1_cli_stats_op op = GF_CLI_STATS_NONE; +        gf1_cli_top_op    top_op = GF_CLI_TOP_NONE; +        int32_t  list_cnt       = 0; +        int      index          = 0; +        int      perf           = 0; +        int32_t  blk_size       = 0; +        int32_t  count          = 0; +        char    *delimiter      = NULL; + +        GF_ASSERT (words); +        GF_ASSERT (options); + +        GF_ASSERT ((strcmp (words[0], "volume")) == 0); +        GF_ASSERT ((strcmp (words[1], "top")) == 0); + +        dict = dict_new (); +        if (!dict) +                goto out; + +        if (wordcount < 4) +                goto out; + +        volname = (char *)words[2]; + +        ret = dict_set_str (dict, "volname", volname); +        if (ret) +                goto out; + +        op = GF_CLI_STATS_TOP; +        ret = dict_set_int32 (dict, "op", (int32_t)op); +        if (ret) +                goto out; + +        if (strcmp (words[3], "open") == 0) { +                top_op = GF_CLI_TOP_OPEN; +        } else if (strcmp (words[3], "read") == 0) { +                top_op = GF_CLI_TOP_READ; +        } else if (strcmp (words[3], "write") == 0) { +                top_op = GF_CLI_TOP_WRITE; +        } else if (strcmp (words[3], "opendir") == 0) { +                top_op = GF_CLI_TOP_OPENDIR; +        } else if (strcmp (words[3], "readdir") == 0) { +                top_op = GF_CLI_TOP_READDIR; +        } else if (strcmp (words[3], "read-perf") == 0) { +                top_op = GF_CLI_TOP_READ_PERF; +                perf = 1; +        } else if (strcmp (words[3], "write-perf") == 0) { +                top_op = GF_CLI_TOP_WRITE_PERF; +                perf = 1; +        } else { +                ret = -1; +                goto out; +        }  +        ret = dict_set_int32 (dict, "top-op", (int32_t)top_op); +        if (ret) +                goto out; + +        for (index = 4; index < wordcount; index+=2) { + +                key = (char *) words[index]; +                value = (char *) words[index+1]; + +                if ( key && !value ) { +                        ret = -1; +                        goto out; +                } +                if (!strcmp (key, "brick")) { +                        delimiter = strchr (value, ':'); +                        if (!delimiter || delimiter == value  +                            || *(delimiter+1) != '/') { +                                cli_out ("wrong brick type: %s, use <HOSTNAME>:" +                                         "<export-dir-abs-path>", value); +                                ret = -1; +                                goto out; +                        } +                        ret = dict_set_str (dict, "brick", value); + +                } else if (!strcmp (key, "list-cnt")) { +                        list_cnt = atoi(value); +                        if (!list_cnt) { +                                list_cnt = 100; +                        } +                        if (list_cnt < 1 || list_cnt > 100) { +                                cli_out ("list-cnt should be between 1 to 100"); +                                ret = -1; +                                goto out; +                        } +                        ret = dict_set_int32 (dict, "list-cnt", list_cnt); +                } else if (perf && !strcmp (key, "bs")){ +                        blk_size = atoi (value); +                        if (blk_size < 0){ +                                cli_out ("block size should be an integer " +                                         "greater than zero"); +                                ret = -1; +                                goto out; +                        } +                        ret = dict_set_int32 (dict, "blk-size", blk_size); +                } else if (perf && !strcmp (key, "count")) { +                        count = atoi(value); +                        if (count < 0 ){ +                                cli_out ("count should be an integer greater " +                                         "zero"); +                                ret = -1; +                                goto out; +                        } +                        ret = dict_set_int32 (dict, "blk-cnt", count); +                } else { +                        ret = -1; +                        goto out; +                } +                if (ret) { +                        gf_log ("", GF_LOG_WARNING, "Dict set failed for " +                                "key %s", key); +                        goto out; +                } +        } +        *options = dict; +out: +        if (ret && dict) +                dict_destroy (dict); +        return ret; +} + diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index f7f333001ee..3bd54a6fb3b 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -901,6 +901,49 @@ out:          return ret;  } +int +cli_cmd_volume_top_cbk (struct cli_state *state, struct cli_cmd_word *word, +                          const char **words, int wordcount) +{ + +        int                     ret      = -1; +        rpc_clnt_procedure_t    *proc    = NULL; +        call_frame_t            *frame   = NULL; +        dict_t                  *options = NULL; +        int                     sent     = 0; +        int                     parse_error = 0; + +        ret = cli_cmd_volume_top_parse (words, wordcount, &options); + +        if (ret) { +                parse_error = 1; +                cli_usage_out (word->pattern); +                goto out; +        } + +        proc = &cli_rpc_prog->proctable[GLUSTER_CLI_TOP_VOLUME]; + +        frame = create_frame (THIS, THIS->ctx->pool); +        if (!frame) +                goto out; + +        if (proc->fn) { +                ret = proc->fn (frame, THIS, options); +        } + +out: +        if (options) +                dict_unref (options); + +        if (ret) { +                cli_cmd_sent_status_get (&sent); +                if ((sent == 0) && (parse_error == 0)) +                        cli_out ("Volume top failed"); +        } + +        return ret; + +}  int  cli_cmd_log_locate_cbk (struct cli_state *state, struct cli_cmd_word *word, @@ -1119,6 +1162,12 @@ struct cli_cmd volume_cmds[] = {            cli_cmd_quota_cbk,            "quota translator specific operations"}, +         { "volume top <VOLNAME> {[open|read|write|opendir|readdir] " +           "|[read-perf|write-perf bs <size> count <count>]} " +           " [brick <brick>] [list-cnt <count>]", +           cli_cmd_volume_top_cbk, +           "volume profile operations"}, +          { NULL, NULL, NULL }  }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 7daa7634158..2a7aa17fcb7 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -3145,6 +3145,210 @@ out:          return ret;  } +int32_t +gf_cli3_1_top_volume_cbk (struct rpc_req *req, struct iovec *iov, +                              int count, void *myframe) +{ +        gf1_cli_stats_volume_rsp        rsp   = {0,}; +        int                               ret   = -1; +        dict_t                            *dict = NULL; +        gf1_cli_stats_op                op = GF_CLI_STATS_NONE; +        char                              key[256] = {0}; +        int                               i = 1; +        int32_t                           brick_count = 0; +        char                              brick[1024]; +        int32_t                           members = 0; +        char                              *filename; +        char                              *bricks; +        uint64_t                           value = 0; +        int32_t                           j = 0; +        gf1_cli_top_op                    top_op = GF_CLI_TOP_NONE; +        uint64_t                          nr_open = 0; +        uint64_t                          max_nr_open = 0; +        double                            throughput = 0; +        double                            time = 0; +        long int                          time_sec = 0; +        long int                           time_usec = 0; +        struct tm                         *tm = NULL; +        char                              timestr[256] = {0, }; + +        if (-1 == req->rpc_status) { +                goto out; +        } + +        gf_log ("cli", GF_LOG_DEBUG, "Received resp to top"); +        ret = gf_xdr_to_cli_stats_volume_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                goto out; +        } + +        if (rsp.op_ret && strcmp (rsp.op_errstr, "")) { +                cli_out (rsp.op_errstr); +        } else { +                cli_out ("volume top %s ", +                         (rsp.op_ret) ? "unsuccessful": "successful"); +        } + +        if (rsp.op_ret) { +                ret = rsp.op_ret; +                goto out; +        } + +        dict = dict_new (); + +        if (!dict) { +                ret = -1; +                goto out; +        } + +        ret = dict_unserialize (rsp.stats_info.stats_info_val, +                                rsp.stats_info.stats_info_len, +                                &dict); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                                "Unable to allocate memory"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "op", (int32_t*)&op); + +        if (op != GF_CLI_STATS_TOP) { +                ret = 0; +                goto out; +        } +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) +                goto out; +        snprintf (key, sizeof (key), "%d-top-op", i); +        ret = dict_get_int32 (dict, key, (int32_t*)&top_op); +        if (ret) +                goto out; +        while (i <= brick_count) { +                snprintf (brick, sizeof (brick), "%d-brick", i); +                ret = dict_get_str (dict, brick, &bricks); +                if (ret) +                        goto out; +                cli_out ("Brick: %s", bricks); +                switch (top_op) { +                case GF_CLI_TOP_OPEN: +                        snprintf (key, sizeof (key), "%d-current-open", i); +                        ret = dict_get_uint64 (dict, key, &nr_open); +                        if (ret) +                                break; +                        snprintf (key, sizeof (key), "%d-max-open", i); +                        ret = dict_get_uint64 (dict, key, &max_nr_open); +                        if (ret) +                                goto out; +                        cli_out ("Current open fd's: %"PRIu64", Max open" +                                " fd's: %"PRIu64, nr_open, max_nr_open); +                case GF_CLI_TOP_READ: +                case GF_CLI_TOP_WRITE: +                case GF_CLI_TOP_OPENDIR: +                case GF_CLI_TOP_READDIR: +                        cli_out ("Count\t\tfilename\n======================="); +                        break; +                case GF_CLI_TOP_READ_PERF: +                case GF_CLI_TOP_WRITE_PERF: +                        snprintf (key, sizeof (key), "%d-throughput", i); +                        ret = dict_get_double (dict, key, &throughput); +                        if (!ret) { +                                snprintf (key, sizeof (key), "%d-time", i); +                                ret = dict_get_double (dict, key, &time); +                        } +                        if (!ret) +                                cli_out ("Throughput %.2f MBps time %.4f secs", throughput, +                                          time / 1e6); + +                        cli_out ("MBps\t\tfilename\t\t time\n========================"); +                        break; +                default: +                        goto out; +                } +                snprintf(key, sizeof (key), "%d-members", i); +                ret = dict_get_int32 (dict, key, &members); +                for (j = 1; j <= members; j++) { +                        snprintf (key, sizeof (key), "%d-filename-%d", i, j); +                        ret = dict_get_str (dict, key, &filename); +                        if (ret) +                                break; +                        snprintf (key, sizeof (key), "%d-value-%d", i, j); +                        ret = dict_get_uint64 (dict, key, &value); +                        if (ret) +                                goto out; +                        if ( top_op == GF_CLI_TOP_READ_PERF || +                                top_op == GF_CLI_TOP_WRITE_PERF) { +                                snprintf (key, sizeof (key), "%d-time-sec-%d", i, j); +                                ret = dict_get_int32 (dict, key, (int32_t *)&time_sec); +                                if (ret) +                                        goto out; +                                snprintf (key, sizeof (key), "%d-time-usec-%d", i, j); +                                ret = dict_get_int32 (dict, key, (int32_t *)&time_usec); +                                if (ret) +                                        goto out; +                                tm    = localtime (&time_sec); +                                if (!tm) +                                        goto out; +                                strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); +                                snprintf (timestr + strlen (timestr), 256 - strlen (timestr), +                                  ".%"GF_PRI_SUSECONDS, time_usec); + +                                cli_out ("%"PRIu64"\t\t%s\t\t%s", value, filename, timestr); +                        } else { +                                cli_out ("%"PRIu64"\t\t%s", value, filename); +                        } +                } +                i++; +        } +        ret = rsp.op_ret; + +out: +        cli_cmd_broadcast_response (ret); + +        if (dict) +                dict_unref (dict); + +        if (rsp.stats_info.stats_info_val) +                free (rsp.stats_info.stats_info_val); +        return ret; +} + +int32_t +gf_cli3_1_top_volume (call_frame_t *frame, xlator_t *this, void *data) +{ +        int                        ret   = -1; +        gf1_cli_stats_volume_req   req   = {0,}; +        dict_t                     *dict = NULL; + +        GF_ASSERT (frame); +        GF_ASSERT (this); +        GF_ASSERT (data); + +        if (!frame || !this || !data) +                goto out; +        dict = data; +        ret = dict_get_str (dict, "volname", &req.volname); +        if (ret) +                goto out; + +        ret = dict_get_int32 (dict, "op", (int32_t*)&req.op); +        if (ret) +                goto out; + +        ret = dict_allocate_and_serialize (dict, +                                           &req.dict_req.dict_req_val, +                                           (size_t *)&req.dict_req.dict_req_len); + +        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +                              GLUSTER_CLI_PROFILE_VOLUME, NULL, +                              gf_xdr_from_cli_stats_volume_req, +                              this, gf_cli3_1_top_volume_cbk); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +}  struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {          [GLUSTER_CLI_NULL]             = {"NULL", NULL }, @@ -3174,7 +3378,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {          [GLUSTER_CLI_GSYNC_SET]        = {"GSYNC_SET", gf_cli3_1_gsync_set},          [GLUSTER_CLI_PROFILE_VOLUME]   = {"PROFILE_VOLUME", gf_cli3_1_profile_volume},          [GLUSTER_CLI_QUOTA]            = {"QUOTA", gf_cli3_1_quota}, - +        [GLUSTER_CLI_TOP_VOLUME]       = {"TOP_VOLUME", gf_cli3_1_top_volume}  };  struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli.h b/cli/src/cli.h index 1db78746a96..33a6fa1879b 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -223,4 +223,7 @@ cli_path_strip_trailing_slashes (char *path);  int32_t  cli_cmd_volume_profile_parse (const char **words, int wordcount,                                dict_t **options); +int32_t +cli_cmd_volume_top_parse (const char **words, int wordcount, +                              dict_t **options);  #endif /* __CLI_H__ */  | 
