diff options
| -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 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 1 | ||||
| -rw-r--r-- | rpc/xdr/src/cli1-xdr.c | 12 | ||||
| -rw-r--r-- | rpc/xdr/src/cli1-xdr.h | 19 | ||||
| -rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 12 | 
8 files changed, 434 insertions, 1 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 1dd963b66..87792c08c 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 f7f333001..3bd54a6fb 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 7daa76341..2a7aa17fc 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 1db78746a..33a6fa187 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__ */ diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 30434d0d9..8483fbcf4 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -197,6 +197,7 @@ enum gluster_cli_procnum {          GLUSTER_CLI_GSYNC_SET,          GLUSTER_CLI_PROFILE_VOLUME,          GLUSTER_CLI_QUOTA, +        GLUSTER_CLI_TOP_VOLUME,          GLUSTER_CLI_MAXVALUE,  }; diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c index c51546a8e..fa24ad90b 100644 --- a/rpc/xdr/src/cli1-xdr.c +++ b/rpc/xdr/src/cli1-xdr.c @@ -108,6 +108,15 @@ xdr_gf1_cli_stats_op (XDR *xdrs, gf1_cli_stats_op *objp)  }  bool_t +xdr_gf1_cli_top_op (XDR *xdrs, gf1_cli_top_op *objp) +{ + +         if (!xdr_enum (xdrs, (enum_t *) objp)) +                 return FALSE; +        return TRUE; +} + +bool_t  xdr_gf1_cli_probe_req (XDR *xdrs, gf1_cli_probe_req *objp)  { @@ -764,6 +773,9 @@ xdr_gf1_cli_stats_volume_req (XDR *xdrs, gf1_cli_stats_volume_req *objp)  		 return FALSE;  	 if (!xdr_gf1_cli_stats_op (xdrs, &objp->op))  		 return FALSE; +	 if (!xdr_bytes (xdrs, (char **)&objp->dict_req.dict_req_val, (u_int *) &objp->dict_req.dict_req_len, ~0)) +		 return FALSE; +  	return TRUE;  } diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index 865eb793a..dba583492 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -100,9 +100,22 @@ enum gf1_cli_stats_op {  	GF_CLI_STATS_START = 1,  	GF_CLI_STATS_STOP = 2,  	GF_CLI_STATS_INFO = 3, +        GF_CLI_STATS_TOP = 4,  };  typedef enum gf1_cli_stats_op gf1_cli_stats_op; +enum gf1_cli_top_op { +        GF_CLI_TOP_NONE = 0, +        GF_CLI_TOP_OPEN = 0 + 1, +        GF_CLI_TOP_READ = 0 + 2, +        GF_CLI_TOP_WRITE = 0 + 3, +        GF_CLI_TOP_OPENDIR = 0 + 4, +        GF_CLI_TOP_READDIR = 0 + 5, +        GF_CLI_TOP_READ_PERF = 0 + 6, +        GF_CLI_TOP_WRITE_PERF = 0 + 7, +}; +typedef enum gf1_cli_top_op gf1_cli_top_op; +  struct gf1_cli_probe_req {  	char *hostname;  	int port; @@ -475,6 +488,10 @@ typedef struct gf1_cli_gsync_set_rsp gf1_cli_gsync_set_rsp;  struct gf1_cli_stats_volume_req {  	char *volname;  	gf1_cli_stats_op op; +	struct { +		u_int dict_req_len; +		char* dict_req_val; +	} dict_req;  };  typedef struct gf1_cli_stats_volume_req gf1_cli_stats_volume_req; @@ -499,6 +516,7 @@ extern  bool_t xdr_gf1_cli_get_volume (XDR *, gf1_cli_get_volume*);  extern  bool_t xdr_gf1_cli_sync_volume (XDR *, gf1_cli_sync_volume*);  extern  bool_t xdr_gf1_cli_op_flags (XDR *, gf1_cli_op_flags*);  extern  bool_t xdr_gf1_cli_gsync_set (XDR *, gf1_cli_gsync_set*); +extern  bool_t xdr_gf1_cli_top_op (XDR *, gf1_cli_top_op*);  extern  bool_t xdr_gf1_cli_stats_op (XDR *, gf1_cli_stats_op*);  extern  bool_t xdr_gf_quota_type (XDR *, gf_quota_type*);  extern  bool_t xdr_gf1_cli_probe_req (XDR *, gf1_cli_probe_req*); @@ -558,6 +576,7 @@ extern bool_t xdr_gf1_cli_sync_volume ();  extern bool_t xdr_gf1_cli_op_flags ();  extern bool_t xdr_gf1_cli_gsync_set ();  extern bool_t xdr_gf1_cli_stats_op (); +extern bool_t xdr_gf1_cli_top_op ();  extern bool_t xdr_gf_quota_type ();  extern bool_t xdr_gf1_cli_probe_req ();  extern bool_t xdr_gf1_cli_probe_rsp (); diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index f352b6f36..035927f89 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -58,6 +58,18 @@ enum gf1_cli_stats_op {          GF_CLI_STATS_START = 1,          GF_CLI_STATS_STOP  = 2,          GF_CLI_STATS_INFO  = 3 +        GF_CLI_STATS_TOP = 4 +}; + +enum gf1_cli_top_op { +        GF_CLI_TOP_NONE = 0, +        GF_CLI_TOP_OPEN, +        GF_CLI_TOP_READ, +        GF_CLI_TOP_WRITE, +        GF_CLI_TOP_OPENDIR, +        GF_CLI_TOP_READDIR, +        GF_CLI_TOP_READ_PERF, +        GF_CLI_TOP_WRITE_PERF  };   struct gf1_cli_probe_req {  | 
