diff options
| author | Kaushal M <kaushal@redhat.com> | 2012-02-15 16:18:25 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2012-02-15 21:45:27 -0800 | 
| commit | 26800453aacd76e6edc36c078aaacbe7c16aa75e (patch) | |
| tree | 3f25a508ac5f2a85871a4890cb798464dafd6671 | |
| parent | c8d47f056ef69d2a644646fd24e8f58de4c0e70e (diff) | |
cli: Enable output in XML
This patch enables gluster cli to output data in xml format. XML output can be
obtained by passing "--xml" as an argument.
A new "volume list" command, which lists the volumes present in a cluster, has
been added. This can be used for obtaining a quick list of volumes.
Several commands, including "volume top", "volume profile", "volume status" and
"volume info", "volume list", have custom XML output routines. Other commands
use either one of the 2 generic output routines, cli_xml_output_str() &
cli_xml_output_dict().
NOTE: When using "all" for "volume status" and "volume info" the XML output will
have multiple roots.
Change-Id: I6117baa02ec06fda116177dbd401f66521263ac6
BUG: 790713
Signed-off-by: Kaushal M <kaushal@redhat.com>
Reviewed-on: http://review.gluster.com/2753
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amarts@redhat.com>
Reviewed-by: Vijay Bellur <vijay@gluster.com>
| -rw-r--r-- | cli/src/Makefile.am | 8 | ||||
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 31 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 594 | ||||
| -rw-r--r-- | cli/src/cli-xml-output.c | 2258 | ||||
| -rw-r--r-- | cli/src/cli.c | 5 | ||||
| -rw-r--r-- | cli/src/cli.h | 26 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 1 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 59 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 1 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 3 | 
10 files changed, 2891 insertions, 95 deletions
diff --git a/cli/src/Makefile.am b/cli/src/Makefile.am index b76a9efd344..80028361886 100644 --- a/cli/src/Makefile.am +++ b/cli/src/Makefile.am @@ -2,13 +2,13 @@ sbin_PROGRAMS = gluster  gluster_SOURCES = cli.c registry.c input.c cli-cmd.c cli-rl.c \  	 cli-cmd-volume.c cli-cmd-peer.c cli-rpc-ops.c cli-cmd-parser.c\ -	 cli-cmd-system.c cli-cmd-misc.c +	 cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c  gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD)\  		$(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \  		$(top_builddir)/rpc/rpc-lib/src/libgfrpc.la -gluster_LDFLAGS = $(GF_LDFLAGS) $(GF_GLUSTERFS_LDFLAGS) +gluster_LDFLAGS = $(GF_LDFLAGS) $(GF_GLUSTERFS_LDFLAGS) $(LIBXML2_LIBS)  noinst_HEADERS = cli.h cli-mem-types.h cli-cmd.h  AM_CFLAGS = -fPIC -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS)\ @@ -17,8 +17,8 @@ AM_CFLAGS = -fPIC -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS)\  	-DDATADIR=\"$(localstatedir)\" \  	-DCONFDIR=\"$(sysconfdir)/glusterfs\" $(GF_GLUSTERFS_CFLAGS)\  	-DGSYNCD_PREFIX=\"$(libexecdir)/glusterfs\"\ -	-DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) -DSBIN_DIR=\"$(sbindir)\" - +	-DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) -DSBIN_DIR=\"$(sbindir)\"\ +	$(LIBXML2_CFLAGS)  CLEANFILES = diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 521e3eb84f7..9c7a43b9f85 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1653,6 +1653,33 @@ out:          return ret;  } +int +cli_cmd_volume_list_cbk (struct cli_state *state, struct cli_cmd_word *word, +                         const char **words, int wordcount) +{ +        int                     ret = -1; +        call_frame_t            *frame = NULL; +        rpc_clnt_procedure_t    *proc = NULL; +        int                     sent = 0; + +        frame = create_frame (THIS, THIS->ctx->pool); +        if (!frame) +                goto out; + +        proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_VOLUME]; +        if (proc->fn) { +                ret = proc->fn (frame, THIS, NULL); +        } + +out: +        if (ret) { +                cli_cmd_sent_status_get (&sent); +                if (sent == 0) +                        cli_out ("Volume list failed"); +        } + +        return ret; +}  struct cli_cmd volume_cmds[] = {          { "volume info [all|<VOLNAME>]", @@ -1754,6 +1781,10 @@ struct cli_cmd volume_cmds[] = {           cli_cmd_volume_statedump_cbk,           "perform statedump on bricks"}, +        {"volume list", +         cli_cmd_volume_list_cbk, +         "list all volumes in cluster"}, +          { NULL, NULL, NULL }  }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 78b2980ade7..8d22f1b1d58 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -91,13 +91,13 @@ rpc_clnt_prog_t cli_pmap_prog = {          .progver    = GLUSTER_PMAP_VERSION,  }; -  int  gf_cli3_1_probe_cbk (struct rpc_req *req, struct iovec *iov,                          int count, void *myframe)  { -        gf1_cli_probe_rsp    rsp   = {0,}; +        gf1_cli_probe_rsp     rsp   = {0,};          int                   ret   = -1; +        char                  msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -115,18 +115,23 @@ gf_cli3_1_probe_cbk (struct rpc_req *req, struct iovec *iov,           if (!rsp.op_ret) {                  switch (rsp.op_errno) {                          case GF_PROBE_SUCCESS: -                                cli_out ("Probe successful"); +                                snprintf (msg, sizeof (msg), +                                          "Probe successful");                                  break;                          case GF_PROBE_LOCALHOST: -                                cli_out ("Probe on localhost not needed"); +                                snprintf (msg, sizeof (msg), +                                          "Probe on localhost not needed");                                  break;                          case GF_PROBE_FRIEND: -                                cli_out ("Probe on host %s port %d already" -                                         " in peer list", rsp.hostname, rsp.port); +                                snprintf (msg, sizeof (msg), +                                          "Probe on host %s port %d already" +                                          " in peer list", rsp.hostname, +                                          rsp.port);                                  break;                          default: -                                cli_out ("Probe returned with unknown errno %d", -                                        rsp.op_errno); +                                snprintf (msg, sizeof (msg), +                                          "Probe returned with unknown errno %d", +                                           rsp.op_errno);                                  break;                  }           } @@ -134,33 +139,52 @@ gf_cli3_1_probe_cbk (struct rpc_req *req, struct iovec *iov,          if (rsp.op_ret) {                  switch (rsp.op_errno) {                          case GF_PROBE_ANOTHER_CLUSTER: -                                cli_out ("%s is already part of " -                                         "another cluster", rsp.hostname); +                                snprintf (msg, sizeof (msg), +                                          "%s is already part of another" +                                          " cluster", rsp.hostname);                                  break;                          case GF_PROBE_VOLUME_CONFLICT: -                                cli_out ("Atleast one volume on %s conflicts " -                                         "with existing volumes in the " -                                         "cluster", rsp.hostname); +                                snprintf (msg, sizeof (msg), +                                          "Atleast one volume on %s conflicts " +                                          "with existing volumes in the " +                                          "cluster", rsp.hostname);                                  break;                          case GF_PROBE_UNKNOWN_PEER: -                                cli_out ("%s responded with 'unknown peer' error, " -                                         "this could happen if %s doesn't have" -                                         " localhost in its peer database", -                                         rsp.hostname, rsp.hostname); +                                snprintf (msg, sizeof (msg), +                                          "%s responded with 'unknown peer'" +                                          " error, this could happen if %s " +                                          "doesn't have localhost in its peer" +                                          " database", rsp.hostname, +                                          rsp.hostname);                                  break;                          case GF_PROBE_ADD_FAILED: -                                cli_out ("Failed to add peer information " -                                         "on %s" , rsp.hostname); +                                snprintf (msg, sizeof (msg), +                                          "Failed to add peer information " +                                          "on %s" , rsp.hostname);                                  break;                          default: -                                cli_out ("Probe unsuccessful\nProbe returned " -                                         "with unknown errno %d", rsp.op_errno); +                                snprintf (msg, sizeof (msg), +                                          "Probe unsuccessful\nProbe returned " +                                          "with unknown errno %d", +                                          rsp.op_errno);                                  break;                  }                  gf_log ("glusterd",GF_LOG_ERROR,"Probe failed with op_ret %d"                          " and op_errno %d", rsp.op_ret, rsp.op_errno);          } + +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("peerProbe", msg, rsp.op_ret, +                                          rsp.op_errno, NULL); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -174,6 +198,7 @@ gf_cli3_1_deprobe_cbk (struct rpc_req *req, struct iovec *iov,  {          gf1_cli_deprobe_rsp    rsp   = {0,};          int                   ret   = -1; +        char                  msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -191,34 +216,48 @@ gf_cli3_1_deprobe_cbk (struct rpc_req *req, struct iovec *iov,          if (rsp.op_ret) {                  switch (rsp.op_errno) {                          case GF_DEPROBE_LOCALHOST: -                                cli_out ("%s is localhost", -                                         rsp.hostname); +                                snprintf (msg, sizeof (msg), +                                          "%s is localhost", rsp.hostname);                                  break;                          case GF_DEPROBE_NOT_FRIEND: -                                cli_out ("%s is not part of cluster", -                                         rsp.hostname); +                                snprintf (msg, sizeof (msg), +                                          "%s is not part of cluster", +                                          rsp.hostname);                                  break;                          case GF_DEPROBE_BRICK_EXIST: -                                cli_out ("Brick(s) with the peer %s exist in " -                                         "cluster", rsp.hostname); +                                snprintf (msg, sizeof (msg), +                                          "Brick(s) with the peer %s exist in " +                                          "cluster", rsp.hostname);                                  break;                          case GF_DEPROBE_FRIEND_DOWN: -                                cli_out ("One of the peers is probably down." -                                         " Check with 'peer status'."); +                                snprintf (msg, sizeof (msg), +                                          "One of the peers is probably down." +                                          " Check with 'peer status'.");                                  break;                          default: -                                cli_out ("Detach unsuccessful\nDetach returned " -                                         "with unknown errno %d", -                                         rsp.op_errno); +                                snprintf (msg, sizeof (msg), +                                          "Detach unsuccessful\nDetach returned" +                                          " with unknown errno %d", +                                          rsp.op_errno);                                  break;                  }                  gf_log ("glusterd",GF_LOG_ERROR,"Detach failed with op_ret %d"                          " and op_errno %d", rsp.op_ret, rsp.op_errno);          } else { -                cli_out ("Detach successful"); +                snprintf (msg, sizeof (msg), "Detach successful");          } - +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("peerDetach", msg, rsp.op_ret, +                                          rsp.op_errno, NULL); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -254,7 +293,6 @@ gf_cli3_1_list_friends_cbk (struct rpc_req *req, struct iovec *iov,                  goto out;          } -          gf_log ("cli", GF_LOG_INFO, "Received resp to list: %d",                  rsp.op_ret); @@ -285,6 +323,17 @@ gf_cli3_1_list_friends_cbk (struct rpc_req *req, struct iovec *iov,                          goto out;                  } +#if (HAVE_LIB_XML) +                if (global_state->mode & GLUSTER_MODE_XML) { +                        ret = cli_xml_output_dict ("peerStatus", dict, +                                                   rsp.op_ret, rsp.op_errno, +                                                   NULL); +                        if (ret) +                                gf_log ("cli", GF_LOG_ERROR, +                                        "Error ouputting to xml"); +                        goto out; +                } +#endif                  ret = dict_get_int32 (dict, "count", &count);                  if (ret) { @@ -475,6 +524,18 @@ gf_cli3_1_get_volume_cbk (struct rpc_req *req, struct iovec *iov,                  }          } +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_vol_info (dict, rsp.op_ret, +                                               rsp.op_errno, rsp.op_errstr); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                } +                goto out; +        } +#endif +          while ( i < count) {                  cli_out (" ");                  snprintf (key, 256, "volume%d.name", i); @@ -660,6 +721,18 @@ gf_cli3_1_create_volume_cbk (struct rpc_req *req, struct iovec *iov,          ret = dict_get_str (dict, "volname", &volname);          gf_log ("cli", GF_LOG_INFO, "Received resp to create volume"); + +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_dict ("volCreate", dict, rsp.op_ret, +                                           rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +          if (rsp.op_ret && strcmp (rsp.op_errstr, ""))                  cli_out ("%s", rsp.op_errstr);          else @@ -718,6 +791,17 @@ gf_cli3_1_delete_volume_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to delete volume"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_dict ("volDelete", dict, rsp.op_ret, +                                           rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +          if (rsp.op_ret && strcmp (rsp.op_errstr, ""))                  cli_out ("%s", rsp.op_errstr);          else @@ -776,6 +860,17 @@ gf_cli3_1_start_volume_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to start volume"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_dict ("volStart", dict, rsp.op_ret, +                                           rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +          if (rsp.op_ret && strcmp (rsp.op_errstr, ""))                  cli_out ("%s", rsp.op_errstr);          else @@ -835,6 +930,17 @@ gf_cli3_1_stop_volume_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to stop volume"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_dict ("volStop", dict, rsp.op_ret, +                                           rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +          if (rsp.op_ret && strcmp (rsp.op_errstr, ""))                  cli_out ("%s", rsp.op_errstr);          else @@ -869,6 +975,7 @@ gf_cli3_1_defrag_volume_cbk (struct rpc_req *req, struct iovec *iov,          uint64_t                 files   = 0;          uint64_t                 size    = 0;          uint64_t                 lookup  = 0; +        char                     msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -937,24 +1044,29 @@ gf_cli3_1_defrag_volume_cbk (struct rpc_req *req, struct iovec *iov,          if (cmd == GF_DEFRAG_CMD_STOP) {                  if (rsp.op_ret == -1) {                          if (strcmp (rsp.op_errstr, "")) -                                cli_out ("%s", rsp.op_errstr); +                                snprintf (msg, sizeof (msg), +                                          "%s", rsp.op_errstr);                          else -                                cli_out ("rebalance volume %s stop failed", -                                         volname); +                                snprintf (msg, sizeof (msg), +                                          "rebalance volume %s stop failed", +                                          volname);                  } else { -                        cli_out ("stopped rebalance process of volume %s \n" -                                 "(after rebalancing %"PRId64" files totaling " -                                 "%"PRId64" bytes)", volname, files, size); +                        snprintf (msg, sizeof (msg), +                                  "stopped rebalance process of volume %s \n" +                                  "(after rebalancing %"PRId64" files totaling" +                                  " %"PRId64" bytes)", volname, files, size);                  }                  goto done;          }          if (cmd == GF_DEFRAG_CMD_STATUS) {                  if (rsp.op_ret == -1) {                          if (strcmp (rsp.op_errstr, "")) -                                cli_out ("%s", rsp.op_errstr); +                                snprintf (msg, sizeof (msg), +                                          "%s", rsp.op_errstr);                          else -                                cli_out ("failed to get the status of " -                                         "rebalance process"); +                                snprintf (msg, sizeof (msg), +                                          "failed to get the status of " +                                          "rebalance process");                          goto done;                  } @@ -988,36 +1100,51 @@ gf_cli3_1_defrag_volume_cbk (struct rpc_req *req, struct iovec *iov,                          break;                  }                  if (files && (rsp.op_errno == 1)) { -                        cli_out ("rebalance %s: fixed layout %"PRId64, -                                 status, files); +                        snprintf (msg, sizeof (msg), +                                  "rebalance %s: fixed layout %"PRId64, +                                  status, files);                          goto done;                  }                  if (files && (rsp.op_errno == 6)) { -                        cli_out ("rebalance %s: fixed layout %"PRId64, -                                 status, files); +                        snprintf (msg, sizeof (msg), +                                  "rebalance %s: fixed layout %"PRId64, +                                  status, files);                          goto done;                  }                  if (files) { -                        cli_out ("rebalance %s: rebalanced %"PRId64 -                                 " files of size %"PRId64" (total files" -                                 " scanned %"PRId64")", status, -                                 files, size, lookup); +                        snprintf (msg, sizeof (msg), +                                  "rebalance %s: rebalanced %"PRId64 +                                  " files of size %"PRId64" (total files" +                                  " scanned %"PRId64")", status, +                                  files, size, lookup);                          goto done;                  } -                cli_out ("rebalance %s", status); +                snprintf (msg, sizeof (msg), "rebalance %s", status);                  goto done;          }          /* All other possibility is about starting a volume */          if (rsp.op_ret && strcmp (rsp.op_errstr, "")) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);          else -                cli_out ("starting rebalance on volume %s has been %s", -                         volname, (rsp.op_ret) ? "unsuccessful": -                         "successful"); +                snprintf (msg, sizeof (msg), +                          "starting rebalance on volume %s has been %s", +                          volname, (rsp.op_ret) ? "unsuccessful": +                          "successful");  done: +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volRebalance", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1041,6 +1168,7 @@ gf_cli3_1_rename_volume_cbk (struct rpc_req *req, struct iovec *iov,  {          gf_cli_rsp              rsp   = {0,};          int                     ret   = -1; +        char                    msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1054,9 +1182,21 @@ gf_cli3_1_rename_volume_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to probe"); -        cli_out ("Rename volume %s", (rsp.op_ret) ? "unsuccessful": -                                        "successful"); +        snprintf (msg, sizeof (msg), "Rename volume %s", +                  (rsp.op_ret) ? "unsuccessful": "successful"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volRename", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1070,6 +1210,7 @@ gf_cli3_1_reset_volume_cbk (struct rpc_req *req, struct iovec *iov,  {          gf_cli_rsp           rsp   = {0,};          int                  ret   = -1; +        char                 msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1084,11 +1225,23 @@ gf_cli3_1_reset_volume_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to reset");          if (rsp.op_ret &&  strcmp (rsp.op_errstr, "")) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);          else -                cli_out ("reset volume %s", (rsp.op_ret) ? "unsuccessful": -                                "successful"); +                snprintf (msg, sizeof (msg), "reset volume %s", +                          (rsp.op_ret) ? "unsuccessful": "successful"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volReset", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1104,6 +1257,7 @@ gf_cli3_1_set_volume_cbk (struct rpc_req *req, struct iovec *iov,          int                  ret   = -1;          dict_t               *dict = NULL;          char                 *help_str = NULL; +        char                 msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1118,7 +1272,7 @@ gf_cli3_1_set_volume_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to set");          if (rsp.op_ret &&  strcmp (rsp.op_errstr, "")) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);          dict = dict_new (); @@ -1133,11 +1287,23 @@ gf_cli3_1_set_volume_cbk (struct rpc_req *req, struct iovec *iov,                  goto out;          if (dict_get_str (dict, "help-str", &help_str)) -                cli_out ("Set volume %s", (rsp.op_ret) ? "unsuccessful": -                                                         "successful"); +                snprintf (msg, sizeof (msg), "Set volume %s", +                          (rsp.op_ret) ? "unsuccessful": "successful");          else -                cli_out ("%s", help_str); +                snprintf (msg, sizeof (msg), "%s", help_str); + +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volSet", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1151,6 +1317,7 @@ gf_cli3_1_add_brick_cbk (struct rpc_req *req, struct iovec *iov,  {          gf_cli_rsp                  rsp   = {0,};          int                         ret   = -1; +        char                        msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1166,10 +1333,23 @@ gf_cli3_1_add_brick_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to add brick");          if (rsp.op_ret && strcmp (rsp.op_errstr, "")) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);          else -                cli_out ("Add Brick %s", (rsp.op_ret) ? "unsuccessful": -                                                        "successful"); +                snprintf (msg, sizeof (msg), "Add Brick %s", +                          (rsp.op_ret) ? "unsuccessful": "successful"); + +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volAddBrick", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1191,6 +1371,7 @@ gf_cli3_remove_brick_status_cbk (struct rpc_req *req, struct iovec *iov,          uint64_t                 files   = 0;          uint64_t                 size    = 0;          dict_t                  *dict    = NULL; +        char                     msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1263,24 +1444,39 @@ gf_cli3_remove_brick_status_cbk (struct rpc_req *req, struct iovec *iov,                          "failed to get size of xfer");          if (files && (rsp.op_errno == 1)) { -                cli_out ("remove-brick %s: fixed layout %"PRId64, -                         status,files); +                snprintf (msg, sizeof (msg), +                          "remove-brick %s: fixed layout %"PRId64, +                          status,files);                  goto out;          }          if (files && (rsp.op_errno == 6)) { -                cli_out ("remove-brick %s: fixed layout %"PRId64, -                         status, files); +                snprintf (msg, sizeof (msg), +                          "remove-brick %s: fixed layout %"PRId64, +                          status, files);                  goto out;          }          if (files) { -                cli_out ("remove-brick %s: decommissioned %"PRId64 -                         " files of size %"PRId64, status, -                         files, size); +                snprintf (msg, sizeof (msg), +                          "remove-brick %s: decommissioned %"PRId64 +                          " files of size %"PRId64, status, +                          files, size);                  goto out;          } -        cli_out ("remove-brick %s", status); +        snprintf (msg, sizeof (msg), "remove-brick %s", status); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volRemoveBrick", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);  out:          if (rsp.dict.dict_val)                  free (rsp.dict.dict_val); //malloced by xdr @@ -1297,6 +1493,7 @@ gf_cli3_1_remove_brick_cbk (struct rpc_req *req, struct iovec *iov,  {          gf_cli_rsp                      rsp   = {0,};          int                             ret   = -1; +        char                            msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1311,11 +1508,22 @@ gf_cli3_1_remove_brick_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_INFO, "Received resp to remove brick");          if (rsp.op_ret && strcmp (rsp.op_errstr, "")) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);          else -                cli_out ("Remove Brick %s", (rsp.op_ret) ? "unsuccessful": -                                                           "successful"); +                snprintf (msg, sizeof (msg), "Remove Brick %s", +                          (rsp.op_ret) ? "unsuccessful": "successful"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volRemoveBrick", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1344,6 +1552,7 @@ gf_cli3_1_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,          gf1_cli_replace_op               replace_op       = 0;          char                            *rb_operation_str = NULL;          dict_t                          *rsp_dict         = NULL; +        char                             msg[1024]         = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1457,9 +1666,21 @@ gf_cli3_1_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,          }          gf_log ("cli", GF_LOG_INFO, "Received resp to replace brick"); -        cli_out ("%s", -                 rb_operation_str ? rb_operation_str : "Unknown operation"); +        snprintf (msg,sizeof (msg), "%s", +                  rb_operation_str ? rb_operation_str : "Unknown operation"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volReplaceBrick", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1484,6 +1705,7 @@ gf_cli3_1_log_rotate_cbk (struct rpc_req *req, struct iovec *iov,  {          gf_cli_rsp             rsp   = {0,};          int                    ret   = -1; +        char                   msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1498,11 +1720,23 @@ gf_cli3_1_log_rotate_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_DEBUG, "Received resp to log rotate");          if (rsp.op_ret && strcmp (rsp.op_errstr, "")) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);          else -                cli_out ("log rotate %s", (rsp.op_ret) ? "unsuccessful": -                                                         "successful"); +                snprintf (msg, sizeof (msg), "log rotate %s", +                          (rsp.op_ret) ? "unsuccessful": "successful"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volLogRotate", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -1519,6 +1753,7 @@ gf_cli3_1_sync_volume_cbk (struct rpc_req *req, struct iovec *iov,  {          gf_cli_rsp                     rsp   = {0,};          int                            ret   = -1; +        char                           msg[1024] = {0,};          if (-1 == req->rpc_status) {                  goto out; @@ -1533,10 +1768,23 @@ gf_cli3_1_sync_volume_cbk (struct rpc_req *req, struct iovec *iov,          gf_log ("cli", GF_LOG_DEBUG, "Received resp to sync");          if (rsp.op_ret && strcmp (rsp.op_errstr, "")) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);          else -                cli_out ("volume sync: %s", +                snprintf (msg, sizeof (msg), "volume sync: %s",                           (rsp.op_ret) ? "unsuccessful": "successful"); + +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volSync", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -3063,6 +3311,17 @@ gf_cli3_1_gsync_set_cbk (struct rpc_req *req, struct iovec *iov,          if (ret)                  goto out; +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_dict ("volGeoRep", dict, rsp.op_ret, +                                           rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +          if (rsp.op_ret) {                  cli_out ("%s", rsp.op_errstr ? rsp.op_errstr :                           GEOREP" command unsuccessful"); @@ -3388,6 +3647,18 @@ gf_cli3_1_profile_volume_cbk (struct rpc_req *req, struct iovec *iov,                  dict->extra_stdfree = rsp.dict.dict_val;          } +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_vol_profile (dict, rsp.op_ret, +                                                  rsp.op_errno, +                                                  rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +          ret = dict_get_str (dict, "volname", &volname);          if (ret)                  goto out; @@ -3573,6 +3844,20 @@ gf_cli3_1_top_volume_cbk (struct rpc_req *req, struct iovec *iov,                  ret = 0;                  goto out;          } + +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_vol_top (dict, rsp.op_ret, +                                              rsp.op_errno, +                                              rsp.op_errstr); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                } +                goto out; +        } +#endif +          ret = dict_get_int32 (dict, "count", &brick_count);          if (ret)                  goto out; @@ -4708,7 +4993,6 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov,                  ret = 0;                  goto out;          } -          ret = dict_get_int32 (dict, "count", &count);          if (ret)                  goto out; @@ -4717,6 +5001,18 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov,                  goto out;          } +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_vol_status (dict, rsp.op_ret, +                                                 rsp.op_errno, rsp.op_errstr); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                } +                goto out; +        } +#endif +          status.brick = GF_CALLOC (1, PATH_MAX + 256, gf_common_mt_strdup);          switch (cmd & GF_CLI_STATUS_MASK) { @@ -5086,6 +5382,17 @@ gf_cli3_1_heal_volume_cbk (struct rpc_req *req, struct iovec *iov,          if (local)                  dict = local->dict; +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_dict ("volHeal", dict, rsp.op_ret, +                                           rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +          ret = dict_get_str (dict, "volname", &volname);          if (ret) {                  gf_log (THIS->name, GF_LOG_ERROR, "failed to get volname"); @@ -5167,6 +5474,7 @@ gf_cli3_1_statedump_volume_cbk (struct rpc_req *req, struct iovec *iov,  {          gf_cli_rsp                      rsp = {0,};          int                             ret = -1; +        char                            msg[1024] = {0,};          if (-1 == req->rpc_status)                  goto out; @@ -5178,10 +5486,22 @@ gf_cli3_1_statedump_volume_cbk (struct rpc_req *req, struct iovec *iov,          }          gf_log ("cli", GF_LOG_DEBUG, "Recieved response to statedump");          if (rsp.op_ret) -                cli_out ("%s", rsp.op_errstr); +                snprintf (msg, sizeof(msg), "%s", rsp.op_errstr);          else -                cli_out ("Volume statedump sucessful"); +                snprintf (msg, sizeof (msg), "Volume statedump sucessful"); +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_str ("volStatedump", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif + +        cli_out ("%s", msg);          ret = rsp.op_ret;  out: @@ -5227,6 +5547,99 @@ out:          return ret;  } +int32_t +gf_cli3_1_list_volume_cbk (struct rpc_req *req, struct iovec *iov, +                                int count, void *myframe) +{ +        int             ret = -1; +        gf_cli_rsp      rsp = {0,}; +        dict_t          *dict = NULL; +        int             vol_count = 0;; +        char            *volname = NULL; +        char            key[1024] = {0,}; +        int             i = 0; + +        if (-1 == req->rpc_status) +                goto out; +        ret = xdr_to_generic (*iov, &rsp, +                              (xdrproc_t)xdr_gf_cli_rsp); +        if (ret < 0) { +                gf_log (THIS->name, GF_LOG_ERROR, "XDR decoding failed"); +                goto out; +        } + +        dict = dict_new (); +        if (!dict) { +                ret = -1; +                goto out; +        } + +        ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +#if (HAVE_LIB_XML) +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_vol_list (dict, rsp.op_ret, rsp.op_errno, +                                               rsp.op_errstr); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } +#endif +        if (rsp.op_ret) +                cli_out ("%s", rsp.op_errstr); +        else { +                ret = dict_get_int32 (dict, "count", &vol_count); +                if (ret) +                        goto out; + +                if (vol_count == 0) { +                        cli_out ("No volumes present in cluster"); +                        goto out; +                } +                cli_out ("%d %s present in cluster", vol_count, +                         ((vol_count == 1) ? "volume" : "volumes")); + +                for (i = 0; i < vol_count; i++) { +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "volume%d", i); +                        ret = dict_get_str (dict, key, &volname); +                        if (ret) +                                goto out; +                        cli_out ("\t%d. %s", i+1, volname); +                } +        } + +        ret = rsp.op_ret; + +out: +        cli_cmd_broadcast_response (ret); +        return ret; +} + +int32_t +gf_cli3_1_list_volume (call_frame_t *frame, xlator_t *this, void *data) +{ +        int             ret = -1; +        gf_cli_req      req = {{0,}}; + +        if (!frame || !this) +                goto out; + +        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +                              GLUSTER_CLI_LIST_VOLUME, NULL, +                              this, gf_cli3_1_list_volume_cbk, +                              (xdrproc_t)xdr_gf_cli_req); + +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 },          [GLUSTER_CLI_PROBE]            = {"PROBE_QUERY", gf_cli3_1_probe}, @@ -5261,6 +5674,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {          [GLUSTER_CLI_UMOUNT]           = {"UMOUNT", gf_cli3_1_umount},          [GLUSTER_CLI_HEAL_VOLUME]      = {"HEAL_VOLUME", gf_cli3_1_heal_volume},          [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", gf_cli3_1_statedump_volume}, +        [GLUSTER_CLI_LIST_VOLUME]      = {"LIST_VOLUME", gf_cli3_1_list_volume},  };  struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c new file mode 100644 index 00000000000..3e081277bfc --- /dev/null +++ b/cli/src/cli-xml-output.c @@ -0,0 +1,2258 @@ +/* +  Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include <cli.h> +#include <cli1-xdr.h> + +#if (HAVE_LIB_XML) + +#include <libxml/encoding.h> +#include <libxml/xmlwriter.h> + +#define XML_RET_CHECK_AND_GOTO(ret, label)      do {            \ +                if (ret < 0) {                                  \ +                        ret = -1;                               \ +                        goto label;                             \ +                }                                               \ +        }while (0);                                             \ + +int +cli_begin_xml_output (xmlTextWriterPtr *writer, xmlBufferPtr *buf) +{ +        int             ret = -1; + +        *buf = xmlBufferCreateSize (8192); +        if (buf == NULL) { +                ret = -1; +                goto out; +        } +        xmlBufferSetAllocationScheme (*buf, XML_BUFFER_ALLOC_DOUBLEIT); + +        *writer = xmlNewTextWriterMemory (*buf, 0); +        if (writer == NULL) { +                ret = -1; +                goto out; +        } + +        ret = xmlTextWriterStartDocument (*writer, "1.0", "UTF-8", "yes"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <cliOutput> */ +        ret = xmlTextWriterStartElement (*writer, (xmlChar *)"cliOutput"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_end_xml_output (xmlTextWriterPtr writer, xmlBufferPtr buf) +{ +        int             ret = -1; + +        /* </cliOutput> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = xmlTextWriterEndDocument (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        cli_out ("%s", (const char *)buf->content); + +        xmlFreeTextWriter (writer); +        xmlBufferFree (buf); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_common (xmlTextWriterPtr writer, int op_ret, int op_errno, +                       char *op_errstr) +{ +        int             ret = -1; + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opRet", +                                               "%d", op_ret); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opErrno", +                                               "%d", op_errno); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opErrstr", +                                               "%s", op_errstr); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_str (char *op, char *str, int op_ret, int op_errno, +                    char *op_errstr) +{ +        int                     ret = -1; +        xmlTextWriterPtr        writer = NULL; +        xmlBufferPtr            buf = NULL; + +        ret = cli_begin_xml_output (&writer, &buf); +        if (ret) +                goto out; + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) +                goto out; + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"cliOp", +                                               "%s", op); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"output", +                                               "%s", str); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = cli_end_xml_output (writer, buf); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +void +cli_xml_output_data_pair (dict_t *this, char *key, data_t *value, +                          void *data) +{ +        int                     ret = -1; +        xmlTextWriterPtr        *writer = NULL; + +        writer = (xmlTextWriterPtr *)data; + +        ret = xmlTextWriterWriteFormatElement (*writer, (xmlChar *)key, +                                               "%s", value->data); + +        return; +} + +int +cli_xml_output_dict ( char *op, dict_t *dict, int op_ret, int op_errno, +                      char *op_errstr) +{ +        int                     ret = -1; +        xmlTextWriterPtr        writer = NULL; +        xmlBufferPtr            buf = NULL; + +        ret = cli_begin_xml_output (&writer, &buf); +        if (ret) +                goto out; +        /* <"op"> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)op); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        dict_foreach (dict, cli_xml_output_data_pair, &writer); + +        /* </"op"> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = cli_end_xml_output (writer, buf); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_common (xmlTextWriterPtr writer, dict_t *dict, +                                  int   brick_index, int *online) +{ +        int             ret = -1; +        char            *hostname = NULL; +        char            *path = NULL; +        int             port = 0; +        int             status = 0; +        int             pid = 0; +        char            key[1024] = {0,}; + +        snprintf (key, sizeof (key), "brick%d.hostname", brick_index); +        ret = dict_get_str (dict, key, &hostname); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hostname", +                                               "%s", hostname); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.path", brick_index); +        ret = dict_get_str (dict, key, &path); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"path", +                                               "%s", path); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.port", brick_index); +        ret = dict_get_int32 (dict, key, &port); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"port", +                                               "%d", port); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.status", brick_index); +        ret = dict_get_int32 (dict, key, &status); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"status", +                                               "%d", status); +        XML_RET_CHECK_AND_GOTO (ret, out); +        *online = status; + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.pid", brick_index); +        ret = dict_get_int32 (dict, key, &pid); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"pid", +                                               "%d", pid); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_detail (xmlTextWriterPtr writer, dict_t *dict, +                                  int brick_index) +{ +        int             ret = -1; +        uint64_t        size_total = 0; +        uint64_t        size_free = 0; +        char            *device = NULL; +        uint64_t        block_size = 0; +        char            *mnt_options = NULL; +        char            *fs_name = NULL; +        char            *inode_size = NULL; +        uint64_t        inodes_total = 0; +        uint64_t        inodes_free = 0; +        char            key[1024] = {0,}; + +        snprintf (key, sizeof (key), "brick%d.total", brick_index); +        ret = dict_get_uint64 (dict, key, &size_total); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"sizeTotal", +                                               "%"PRIu64, size_total); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.free", brick_index); +        ret = dict_get_uint64 (dict, key, &size_free); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"sizeFree", +                                               "%"PRIu64, size_free); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.device", brick_index); +        ret = dict_get_str (dict, key, &device); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"device", +                                               "%s", device); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.block_size", brick_index); +        ret = dict_get_uint64 (dict, key, &block_size); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"blockSize", +                                               "%"PRIu64, block_size); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mnt_options", brick_index); +        ret = dict_get_str (dict, key, &mnt_options); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"mntOptions", +                                               "%s", mnt_options); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.fs_name", brick_index); +        ret = dict_get_str (dict, key, &fs_name); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"fsName", +                                               "%s", fs_name); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* inode details are only available for ext 2/3/4 & xfs */ +        if (!IS_EXT_FS(fs_name) || strcmp (fs_name, "xfs")) { +                        ret = 0; +                        goto out; +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.inode_size", brick_index); +        ret = dict_get_str (dict, key, &inode_size); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"inodeSize", +                                               "%s", fs_name); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.total_inodes", brick_index); +        ret = dict_get_uint64 (dict, key, &inodes_total); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"inodesTotal", +                                               "%"PRIu64, inodes_total); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.free_inodes", brick_index); +        ret = dict_get_uint64 (dict, key, &inodes_free); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"inodesFree", +                                               "%"PRIu64, inodes_free); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_mempool (xmlTextWriterPtr writer, dict_t *dict, +                                   char *prefix) +{ +        int             ret = -1; +        int             mempool_count = 0; +        char            *name = NULL; +        int             hotcount = 0; +        int             coldcount = 0; +        uint64_t        paddedsizeof = 0; +        uint64_t        alloccount = 0; +        int             maxalloc = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        /* <mempool> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"mempool"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.mempool-count", prefix); +        ret = dict_get_int32 (dict, key, &mempool_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", +                                               "%d", mempool_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < mempool_count; i++) { +                /* <pool> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"pool"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.pool%d.name", prefix, i); +                ret = dict_get_str (dict, key, &name); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"name", +                                                       "%s", name); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.pool%d.hotcount", prefix, i); +                ret = dict_get_int32 (dict, key, &hotcount); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"hotCount", +                                                       "%d", hotcount); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.pool%d.coldcount", prefix, i); +                ret = dict_get_int32 (dict, key, &coldcount); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"coldCount", +                                                       "%d", coldcount); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.pool%d.paddedsizeof", +                          prefix, i); +                ret = dict_get_uint64 (dict, key, &paddedsizeof); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"padddedSizeOf", "%"PRIu64, +                         paddedsizeof); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.pool%d.alloccount", prefix, i); +                ret = dict_get_uint64 (dict, key, &alloccount); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"allocCount", +                                                       "%"PRIu64, alloccount); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.pool%d.max_alloc", prefix, i); +                ret = dict_get_int32 (dict, key, &maxalloc); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"maxAlloc", +                                                       "%d", maxalloc); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                /* </pool> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </mempool> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_mem (xmlTextWriterPtr writer, dict_t *dict, +                               int brick_index) +{ +        int             ret = -1; +        int             arena = 0; +        int             ordblks = 0; +        int             smblks = 0; +        int             hblks = 0; +        int             hblkhd = 0; +        int             usmblks = 0; +        int             fsmblks = 0; +        int             uordblks = 0; +        int             fordblks = 0; +        int             keepcost = 0; +        char            key[1024] = {0,}; + +        /* <memStatus> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"memStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <mallinfo> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"mallinfo"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "brick%d.mallinfo.arena", brick_index); +        ret = dict_get_int32 (dict, key, &arena); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"arena", +                                               "%d", arena); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.ordblks", brick_index); +        ret = dict_get_int32 (dict, key, &ordblks); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"ordblks", +                                               "%d", ordblks); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.smblks", brick_index); +        ret = dict_get_int32 (dict, key, &smblks); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"smblks", +                                               "%d", smblks); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.hblks", brick_index); +        ret = dict_get_int32 (dict, key, &hblks); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hblks", +                                               "%d", hblks); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.hblkhd", brick_index); +        ret = dict_get_int32 (dict, key, &hblkhd); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hblkhd", +                                               "%d", hblkhd); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.usmblks", brick_index); +        ret = dict_get_int32 (dict, key, &usmblks); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"usmblks", +                                               "%d", usmblks); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.fsmblks", brick_index); +        ret = dict_get_int32 (dict, key, &fsmblks); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"fsmblks", +                                               "%d", fsmblks); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.uordblks", brick_index); +        ret = dict_get_int32 (dict, key, &uordblks); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"uordblks", +                                               "%d", uordblks); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.fordblks", brick_index); +        ret = dict_get_int32 (dict, key, &fordblks); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"fordblks", +                                               "%d", fordblks); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d.mallinfo.keepcost", brick_index); +        ret = dict_get_int32 (dict, key, &keepcost); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"keepcost", +                                               "%d", keepcost); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </mallinfo> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "brick%d", brick_index); +        ret = cli_xml_output_vol_status_mempool (writer, dict, key); +        if (ret) +                goto out; + +        /* </memStatus> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_clients (xmlTextWriterPtr writer, dict_t *dict, +                                   int brick_index) +{ +        int             ret = -1; +        int             client_count = 0; +        char            *hostname = NULL; +        uint64_t        bytes_read = 0; +        uint64_t        bytes_write = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        /* <clientsStatus> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"clientsStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "brick%d.clientcount", brick_index); +        ret = dict_get_int32 (dict, key, &client_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, +                                               (xmlChar *)"clientCount", +                                               "%d", client_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < client_count; i++) { +                /* <client> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"client"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "brick%d.client%d.hostname", +                          brick_index, i); +                ret = dict_get_str (dict, key, &hostname); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"hostname", +                                                       "%s", hostname); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "brick%d.client%d.bytesread", +                          brick_index, i); +                ret = dict_get_uint64 (dict, key, &bytes_read); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"bytesRead", +                                                       "%"PRIu64, bytes_read); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "brick%d.client%d.byteswrite", +                          brick_index, i); +                ret = dict_get_uint64 (dict, key, &bytes_write); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"bytesWrite", +                                                       "%"PRIu64, bytes_write); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                /* </client> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </clientsStatus> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_inode_entry (xmlTextWriterPtr writer, dict_t *dict, +                                       char *prefix) +{ +        int             ret = -1; +        char            *gfid = NULL; +        uint64_t        nlookup = 0; +        uint32_t        ref = 0; +        int             ia_type = 0; +        char            key[1024] = {0,}; + +        /* <inode> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"inode"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.gfid", prefix); +        ret = dict_get_str (dict, key, &gfid); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"gfid", +                                               "%s", gfid); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key,0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.nlookup", prefix); +        ret = dict_get_uint64 (dict, key, &nlookup); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nLookup", +                                               "%"PRIu64, nlookup); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key,0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.ref", prefix); +        ret = dict_get_uint32 (dict, key, &ref); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"ref", +                                               "%"PRIu32, ref); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key,0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.ia_type", prefix); +        ret = dict_get_int32 (dict, key, &ia_type); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"iaType", +                                               "%d", ia_type); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </inode> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_itable (xmlTextWriterPtr writer, dict_t *dict, +                                  char *prefix) +{ +        int             ret = -1; +        uint32_t        active_size = 0; +        uint32_t        lru_size = 0; +        uint32_t        purge_size = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        snprintf (key, sizeof (key), "%s.active_size", prefix); +        ret = dict_get_uint32 (dict, key, &active_size); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"activeSize", +                                               "%"PRIu32, active_size); +        XML_RET_CHECK_AND_GOTO (ret, out); +        if (active_size != 0) { +                /* <active> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"active"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                for (i = 0; i < active_size; i++) { +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%s.active%d", prefix, i); +                        ret = cli_xml_output_vol_status_inode_entry +                                (writer, dict, key); +                        if (ret) +                                goto out; +                } +                /* </active> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.lru_size", prefix); +        ret = dict_get_uint32 (dict, key, &lru_size); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"lruSize", +                                               "%"PRIu32, lru_size); +        XML_RET_CHECK_AND_GOTO (ret, out); +        if (lru_size != 0) { +                /* <lru> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"lru"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                for (i = 0; i < lru_size; i++) { +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%s.lru%d", prefix, i); +                        ret = cli_xml_output_vol_status_inode_entry +                                (writer, dict, key); +                        if (ret) +                                goto out; +                } +                /* </lru> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.purge_size", prefix); +        ret = dict_get_uint32 (dict, key, &purge_size); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"purgeSize", +                                               "%"PRIu32, purge_size); +        XML_RET_CHECK_AND_GOTO (ret, out); +        if (purge_size != 0) { +                /* <purge> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"purge"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                for (i = 0; i < purge_size; i++) { +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%s.purge%d", prefix, i); +                        ret = cli_xml_output_vol_status_inode_entry +                                (writer, dict, key); +                        if (ret) +                                goto out; +                } +                /* </purge> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_inode (xmlTextWriterPtr writer, dict_t *dict, +                                 int brick_index) +{ +        int             ret = -1; +        int             conn_count = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        /* <inodeStatus> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"inodeStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "brick%d.conncount", brick_index); +        ret = dict_get_int32 (dict, key, &conn_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"connections", +                                               "%d", conn_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < conn_count; i++) { +                /* <connection> */ +                ret = xmlTextWriterStartElement (writer, +                                                 (xmlChar *)"connection"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "brick%d.conn%d.itable", +                          brick_index, i); +                ret = cli_xml_output_vol_status_itable (writer, dict, key); +                if (ret) +                        goto out; + +                /* </connection> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </inodeStatus> */ +        ret= xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_fdtable (xmlTextWriterPtr writer, dict_t *dict, +                                   char *prefix) +{ +        int             ret = -1; +        int             refcount = 0; +        uint32_t        maxfds = 0; +        int             firstfree = 0; +        int             openfds = 0; +        int             fd_pid = 0; +        int             fd_refcount = 0; +        int             fd_flags = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        /* <fdTable> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"fdTable"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.refcount", prefix); +        ret = dict_get_int32 (dict, key, &refcount); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"refCount", +                                               "%d", refcount); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.maxfds", prefix); +        ret = dict_get_uint32 (dict, key, &maxfds); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxFds", +                                               "%"PRIu32, maxfds); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.firstfree", prefix); +        ret = dict_get_int32 (dict, key, &firstfree); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"firstFree", +                                               "%d", firstfree); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.openfds", prefix); +        ret = dict_get_int32 (dict, key, &openfds); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"openFds", +                                               "%d", openfds); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < maxfds; i++) { +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.fdentry%d.pid", prefix, i); +                ret = dict_get_int32 (dict, key, &fd_pid); +                if (ret) +                        continue; + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.fdentry%d.refcount", +                          prefix, i); +                ret = dict_get_int32 (dict, key, &fd_refcount); +                if (ret) +                        continue; + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.fdentry%d.flags", prefix, i); +                ret = dict_get_int32 (dict, key, &fd_flags); +                if (ret) +                        continue; + +                /* <fd> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"fd"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"entry", +                                                       "%d", i+1); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"pid", +                                                       "%d", fd_pid); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"refCount", +                                                       "%d", fd_refcount); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"flags", +                                                       "%d", fd_flags); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                /* </fd> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </fdTable> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_fd (xmlTextWriterPtr writer, dict_t *dict, +                              int brick_index) +{ +        int             ret = -1; +        int             conn_count = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        /* <fdStatus> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"fdStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "brick%d.conncount", brick_index); +        ret = dict_get_int32 (dict, key, &conn_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"connections", +                                               "%d", conn_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < conn_count; i++) { +                /* <connection> */ +                ret = xmlTextWriterStartElement (writer, +                                                 (xmlChar *)"connection"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "brick%d.conn%d.fdtable", +                          brick_index, i); +                ret = cli_xml_output_vol_status_fdtable (writer, dict, key); +                if (ret) +                        goto out; + +                /* </connection> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </fdStatus> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_callframe (xmlTextWriterPtr writer, dict_t *dict, +                                     char *prefix) +{ +        int             ret = -1; +        int             ref_count = 0; +        char            *translator = NULL; +        int             complete = 0; +        char            *parent = NULL; +        char            *wind_from = NULL; +        char            *wind_to = NULL; +        char            *unwind_from = NULL; +        char            *unwind_to = NULL; +        char            key[1024] = {0,}; + +        /* <callFrame> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"callFrame"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.refcount", prefix); +        ret = dict_get_int32 (dict, key, &ref_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"refCount", +                                               "%d", ref_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.translator", prefix); +        ret = dict_get_str (dict, key, &translator); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"translator", +                                               "%s", translator); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.complete", prefix); +        ret = dict_get_int32 (dict, key, &complete); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"complete", +                                               "%d", complete); +        XML_RET_CHECK_AND_GOTO (ret ,out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.parent", prefix); +        ret = dict_get_str (dict, key, &parent); +        if (!ret) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"parent", +                                                       "%s", parent); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.windfrom", prefix); +        ret = dict_get_str (dict, key, &wind_from); +        if (!ret) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"windFrom", +                                                       "%s", wind_from); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.windto", prefix); +        ret = dict_get_str (dict, key, &wind_to); +        if (!ret) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"windTo", +                                                       "%s", wind_to); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.unwindfrom", prefix); +        ret = dict_get_str (dict, key, &unwind_from); +        if (!ret) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"unwindFrom", +                                                       "%s", unwind_from); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.unwindto", prefix); +        ret = dict_get_str (dict, key, &unwind_to); +        if (!ret) { +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"unwindTo", +                                                       "%s", unwind_to); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </callFrame> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_callstack (xmlTextWriterPtr writer, dict_t *dict, +                                     char *prefix) +{ +        int             ret = -1; +        int             uid = 0; +        int             gid = 0; +        int             pid = 0; +        uint64_t        unique = 0; +        int             frame_count = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        /* <callStack> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"callStack"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%s.uid", prefix); +        ret = dict_get_int32 (dict, key, &uid); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"uid", +                                               "%d", uid); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.gid", prefix); +        ret = dict_get_int32 (dict, key, &gid); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"gid", +                                               "%d", gid); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.pid", prefix); +        ret = dict_get_int32 (dict, key, &pid); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"pid", +                                               "%d", pid); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.unique", prefix); +        ret = dict_get_uint64 (dict, key, &unique); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"unique", +                                               "%"PRIu64, unique); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%s.count", prefix); +        ret = dict_get_int32 (dict, key, &frame_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"frameCount", +                                               "%d", frame_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < frame_count; i++) { +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%s.frame%d", prefix, i); +                ret = cli_xml_output_vol_status_callframe (writer, dict, +                                                           key); +                if (ret) +                        goto out; +        } + +        /* </callStack> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status_callpool (xmlTextWriterPtr writer, dict_t *dict, +                                    int brick_index) +{ +        int             ret = -1; +        int             call_count = 0; +        char            key[1024] = {0,}; +        int             i = 0; + +        /* <callpoolStatus> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"callpoolStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "brick%d.callpool.count", brick_index); +        ret = dict_get_int32 (dict, key, &call_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", +                                               "%d", call_count); + +        for (i = 0; i < call_count; i++) { +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "brick%d.callpool.stack%d", +                          brick_index, i); +                ret = cli_xml_output_vol_status_callstack (writer, dict, +                                                           key); +                if (ret) +                        goto out; +        } + +        /* </callpoolStatus> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, +                           char *op_errstr) +{ +        int                     ret = -1; +        xmlTextWriterPtr        writer = NULL; +        xmlBufferPtr            buf = NULL; +        char                    *volname = NULL; +        int                     brick_count = 0; +        uint32_t                cmd = GF_CLI_STATUS_NONE; +        int                     online = 0; +        int                     i; + +        ret = cli_begin_xml_output (&writer, &buf); +        if (ret) +                goto out; + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) +                goto out; + +        /* <volStatus> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volStatus"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"volName", +                                               "%s", volname); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"brickCount", +                                               "%d", brick_count); +        if (ret) +                goto out; + +        ret = dict_get_uint32 (dict, "cmd", &cmd); +        if (ret) +                goto out; + +        for (i = 0; i < brick_count; i++) { +                /* <brick> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"brick"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = cli_xml_output_vol_status_common (writer, dict, i, +                                                        &online); +                if (ret) +                        goto out; + +                switch (cmd & GF_CLI_STATUS_MASK) { +                case GF_CLI_STATUS_DETAIL: +                        ret = cli_xml_output_vol_status_detail (writer, +                                                                dict, i); +                        if (ret) +                                goto out; +                        break; + +                case GF_CLI_STATUS_MEM: +                        if (online) { +                                ret = cli_xml_output_vol_status_mem +                                        (writer, dict, i); +                                if (ret) +                                        goto out; +                        } +                        break; + +                case GF_CLI_STATUS_CLIENTS: +                        if (online) { +                                ret = cli_xml_output_vol_status_clients +                                        (writer, dict, i); +                                if (ret) +                                        goto out; +                        } +                        break; + +                case GF_CLI_STATUS_INODE: +                        if (online) { +                                ret = cli_xml_output_vol_status_inode +                                        (writer, dict, i); +                                if (ret) +                                        goto out; +                        } +                        break; + +                case GF_CLI_STATUS_FD: +                        if (online) { +                                ret = cli_xml_output_vol_status_fd +                                        (writer, dict, i); +                                if (ret) +                                        goto out; +                        } +                        break; + +                case GF_CLI_STATUS_CALLPOOL: +                        if (online) { +                                ret = cli_xml_output_vol_status_callpool +                                        (writer, dict, i); +                                if (ret) +                                        goto out; +                        } +                        break; + +                default: +                        goto out; + +                } +                /* </brick> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </volStatus> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        ret = cli_end_xml_output (writer, buf); +        if (ret) +                goto out; + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_top_rw_perf (xmlTextWriterPtr writer, dict_t *dict, +                                int brick_index, int member_index) +{ +        int             ret = -1; +        char            *filename = NULL; +        uint64_t        throughput = 0; +        long int        time_sec = 0; +        long int        time_usec = 0; +        struct tm       *tm = NULL; +        char            timestr[256] = {0,}; +        char            key[1024] = {0,}; + +        /* <file> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"file"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%d-filename-%d", brick_index, +                  member_index); +        ret = dict_get_str (dict, key, &filename); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"filename", +                                               "%s", filename); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-value-%d", brick_index, member_index); +        ret = dict_get_uint64 (dict, key, &throughput); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", +                                               "%"PRIu64, throughput); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-time-sec-%d", brick_index, +                  member_index); +        ret = dict_get_int32 (dict, key, (int32_t *)&time_sec); +        if (ret) +                goto out; + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-time-usec-%d", brick_index, +                  member_index); +        ret = dict_get_int32 (dict, key, (int32_t *)&time_usec); +        if (ret) +                goto out; + +        tm = localtime (&time_sec); +        if (!tm) { +                ret = -1; +                goto out; +        } +        strftime (timestr, sizeof (timestr), "%Y-%m-%d %H:%M:%S", tm); +        snprintf (timestr + strlen (timestr), +                  sizeof (timestr) - strlen (timestr), +                  ".%"GF_PRI_SUSECONDS, time_usec); +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"time", +                                               "%s", timestr); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </file> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_top_other (xmlTextWriterPtr writer, dict_t *dict, +                                int brick_index, int member_index) +{ +        int             ret = -1; +        char            *filename = NULL; +        uint64_t        count = 0; +        char            key[1024] = {0,}; + +        /* <file> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"file"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        snprintf (key, sizeof (key), "%d-filename-%d", brick_index, +                  member_index); +        ret = dict_get_str (dict, key, &filename); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"filename", +                                               "%s", filename); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-value-%d", brick_index, member_index); +        ret = dict_get_uint64 (dict, key, &count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", +                                               "%"PRIu64, count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </file> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, +                        char *op_errstr) +{ +        int                     ret = -1; +        xmlTextWriterPtr        writer = NULL; +        xmlBufferPtr            buf = NULL; +        int                     brick_count = 0; +        int                     top_op = GF_CLI_TOP_NONE; +        char                    *brick_name = NULL; +        int                     members = 0; +        uint64_t                current_open = 0; +        uint64_t                max_open = 0; +        char                    *max_open_time = NULL; +        double                  throughput = 0.0; +        double                  time_taken = 0.0; +        char                    key[1024] = {0,}; +        int                     i = 0; +        int                     j = 0; + +        ret = cli_begin_xml_output (&writer, &buf); +        if (ret) +                goto out; + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) +                goto out; + +        /* <volTop> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volTop"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"brickCount", +                                               "%d", brick_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "1-top-op", &top_op); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"topOp", +                                               "%d", top_op); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        while (i < brick_count) { +                i++; + +                /* <brick> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"brick"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-brick", i); +                ret = dict_get_str (dict, key, &brick_name); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"name", +                                                       "%s", brick_name); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key , sizeof (key), "%d-members", i); +                ret = dict_get_int32 (dict, key, &members); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"members", +                                                       "%d", members); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                switch (top_op) { +                case GF_CLI_TOP_OPEN: +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%d-current-open", i); +                        ret = dict_get_uint64 (dict, key, ¤t_open); +                        if (ret) +                                goto out; +                        ret = xmlTextWriterWriteFormatElement +                                (writer, (xmlChar *)"currentOpen", "%"PRIu64, +                                 current_open); +                        XML_RET_CHECK_AND_GOTO (ret, out); + +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%d-max-open", i); +                        ret = dict_get_uint64 (dict, key, &max_open); +                        if (ret) +                                goto out; +                        ret = xmlTextWriterWriteFormatElement +                                (writer, (xmlChar *)"maxOpen", "%"PRIu64, +                                 max_open); +                        XML_RET_CHECK_AND_GOTO (ret, out); + +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%d-max-openfd-time", i); +                        ret = dict_get_str (dict, key, &max_open_time); +                        if (ret) +                                goto out; +                        ret = xmlTextWriterWriteFormatElement +                                (writer, (xmlChar *)"maxOpenTime", "%s", +                                 max_open_time); +                        XML_RET_CHECK_AND_GOTO (ret, out); + +                case GF_CLI_TOP_READ: +                case GF_CLI_TOP_WRITE: +                case GF_CLI_TOP_OPENDIR: +                case GF_CLI_TOP_READDIR: +                        if (!members) +                                continue; + +                        break; + +                case GF_CLI_TOP_READ_PERF: +                case GF_CLI_TOP_WRITE_PERF: +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%d-throughput", i); +                        ret = dict_get_double (dict, key, &throughput); +                        if (!ret) { +                                memset (key, 0, sizeof (key)); +                                snprintf (key, sizeof (key), "%d-time", i); +                                ret = dict_get_double (dict, key, &time_taken); +                        } + +                        if (!ret) { +                                ret = xmlTextWriterWriteFormatElement +                                        (writer, (xmlChar *)"throughput", +                                         "%f", throughput); +                                XML_RET_CHECK_AND_GOTO (ret, out); + +                                ret = xmlTextWriterWriteFormatElement +                                        (writer, (xmlChar *)"timeTaken", +                                         "%f", time_taken); +                        } + +                        if (!members) +                                continue; + +                        break; + +                default: +                        ret = -1; +                        goto out; +                } + +                for (j = 1; j <= members; j++) { +                        if (top_op == GF_CLI_TOP_READ_PERF || +                            top_op == GF_CLI_TOP_WRITE_PERF) { +                                ret = cli_xml_output_vol_top_rw_perf +                                        (writer, dict, i, j); +                        } else { +                                ret = cli_xml_output_vol_top_other +                                        (writer, dict, i, j); +                        } +                        if (ret) +                                goto out; +                } + + +                /* </brick> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </volTop> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); +        ret = cli_end_xml_output (writer, buf); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_profile_stats (xmlTextWriterPtr writer, dict_t *dict, +                                  int brick_index, int interval) +{ +        int                     ret = -1; +        uint64_t                read_count = 0; +        uint64_t                write_count = 0; +        uint64_t                hits = 0; +        double                  avg_latency = 0.0; +        double                  max_latency = 0.0; +        double                  min_latency = 0.0; +        uint64_t                duration = 0; +        uint64_t                total_read = 0; +        uint64_t                total_write = 0; +        char                    key[1024] = {0}; +        int                     i = 0; + +        /* <cumulativeStats> || <intervalStats> */ +        if (interval == -1) +                ret = xmlTextWriterStartElement (writer, +                                                 (xmlChar *)"cumulativeStats"); +        else +                ret = xmlTextWriterStartElement (writer, +                                                 (xmlChar *)"intervalStats"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <blockStats> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"blockStats"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < 32; i++) { +                /* <block> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"block"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"size", "%"PRIu32, (1 << i)); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-%d-read-%d", brick_index, +                          interval, (1 << i)); +                ret = dict_get_uint64 (dict, key, &read_count); +                if (ret) +                        read_count = 0; +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"reads", "%"PRIu64, read_count); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-%d-write-%d", brick_index, +                          interval, (1 << i)); +                ret = dict_get_uint64 (dict, key, &write_count); +                if (ret) +                        write_count = 0; +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"writes", "%"PRIu64, write_count); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                /* </block> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </blockStats> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* <fopStats> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"fopStats"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < GF_FOP_MAXVALUE; i++) { +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-%d-%d-hits", brick_index, +                          interval, i); +                ret = dict_get_uint64 (dict, key, &hits); +                if (ret) +                        goto cont; + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-%d-%d-avglatency", brick_index, +                          interval, i); +                ret = dict_get_double (dict, key, &avg_latency); +                if (ret) +                        goto cont; + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-%d-%d-minlatency", brick_index, +                          interval, i); +                ret = dict_get_double (dict, key, &min_latency); +                if (ret) +                        goto cont; + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-%d-%d-maxlatency", brick_index, +                          interval, i); +                ret = dict_get_double (dict, key, &max_latency); +                if (ret) +                        goto cont; + +                /* <fop> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"fop"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"name","%s", gf_fop_list[i]); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"hits", "%"PRIu64, hits); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"avgLatency", "%f", avg_latency); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"minLatency", "%f", min_latency); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"maxLatency", "%f", max_latency); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                /* </fop> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); + +cont: +                hits = 0; +                avg_latency = 0.0; +                min_latency = 0.0; +                max_latency = 0.0; +        } + +        /* </fopStats> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-%d-duration", brick_index, interval); +        ret = dict_get_uint64 (dict, key, &duration); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"duration", +                                               "%"PRIu64, duration); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-%d-total-read", brick_index, interval); +        ret = dict_get_uint64 (dict, key, &total_read); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"totalRead", +                                               "%"PRIu64, total_read); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-%d-total-write", brick_index, interval); +        ret = dict_get_uint64 (dict, key, &total_write); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"totalWrite", +                                               "%"PRIu64, total_write); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </cumulativeStats> || </intervalStats> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_profile (dict_t *dict, int op_ret, int op_errno, +                            char *op_errstr) +{ +        int                     ret = -1; +        xmlTextWriterPtr        writer = NULL; +        xmlBufferPtr            buf = NULL; +        char                    *volname = NULL; +        int                     op = GF_CLI_STATS_NONE; +        int                     brick_count = 0; +        char                    *brick_name = NULL; +        int                     interval = 0; +        char                    key[1024] = {0,}; +        int                     i = 0; + +        ret = cli_begin_xml_output (&writer, &buf); +        if (ret) +                goto out; + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) +                goto out; + +        /* <volProfile> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volProfile"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"volname", +                                               "%s", volname); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "op", &op); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"profileOp", +                                               "%d", op); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        if (op != GF_CLI_STATS_INFO) +                goto cont; + +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"brickCount", +                                               "%d", brick_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        while (i < brick_count) { +                i++; + +                /* <brick> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"brick"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%d-brick", i); +                ret = dict_get_str (dict, key, &brick_name); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement +                        (writer, (xmlChar *)"brickName", "%s", brick_name); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                snprintf (key, sizeof (key), "%d-cumulative", i); +                ret = dict_get_int32 (dict, key, &interval); +                if (ret == 0) { +                        ret = cli_xml_output_vol_profile_stats +                                (writer, dict, i, interval); +                        if (ret) +                                goto out; +                } + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "%d-interval", i); +                ret = dict_get_int32 (dict, key, &interval); +                if (ret == 0) { +                        ret = cli_xml_output_vol_profile_stats +                                (writer, dict, i, interval); +                        if (ret) +                                goto out; +                } + +                /* </brick> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +cont: +        /* </volProfile> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = cli_end_xml_output (writer, buf); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; + +} + +int +cli_xml_output_vol_list (dict_t *dict, int op_ret, int op_errno, +                         char *op_errstr) +{ +        int                     ret = -1; +        xmlTextWriterPtr        writer = NULL; +        xmlBufferPtr            buf = NULL; +        int                     count = 0; +        char                    *volname = NULL; +        char                    key[1024] = {0,}; +        int                     i = 0; + +        ret = cli_begin_xml_output (&writer, &buf); +        if (ret) +                goto out; + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) +                goto out; + +        /* <volList> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volList"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", +                                               "%d", count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < count; i++) { +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d", i); +                ret = dict_get_str (dict, key, &volname); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"volume", +                                                       "%s", volname); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </volList> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = cli_end_xml_output (writer, buf); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_info_option (xmlTextWriterPtr writer, char *substr, +                                char *optstr, char *valstr) +{ +        int             ret = -1; +        char            *ptr1 = NULL; +        char            *ptr2 = NULL; + +        ptr1 = substr; +        ptr2 = optstr; + +        while (ptr1) { +                if (*ptr1 != *ptr2) +                        break; +                ptr1++; +                ptr2++; +                if (!ptr1) +                        goto out; +                if (!ptr2) +                        goto out; +        } +        if (*ptr2 == '\0') +                goto out; + +        /* <option> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"option"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"name", +                                               "%s", ptr2); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"value", +                                               "%s", valstr); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        /* </option> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_info_options (xmlTextWriterPtr writer, dict_t *dict, +                                 char *prefix) +{ +        int             ret = -1; +        int             opt_count = 0; +        data_pair_t     *pairs = 0; +        data_t          *value = 0; +        char            *ptr = NULL; +        char            key[1024] = {0,}; +        int             i = 0; + +        pairs = dict->members_list; +        if (!pairs) { +                ret = -1; +                goto out; +        } + +        snprintf (key, sizeof (key), "%s.opt_count", prefix); +        ret = dict_get_int32 (dict, key, &opt_count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"optCount", +                                               "%d", opt_count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        while (i < opt_count) { +                snprintf (key, sizeof (key), "%s.option.", prefix); +                while (pairs) { +                        ptr = strstr (pairs->key, "option."); +                        if (ptr) { +                                value = pairs->value; +                                if (!value) { +                                        ret = -1; +                                        goto out; +                                } +                                ret = cli_xml_output_vol_info_option +                                        (writer, key, pairs->key, value->data); +                                if (ret) +                                        goto out; +                        } +                        pairs = pairs->next; +                } +                i++; +        } +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +cli_xml_output_vol_info (dict_t *dict, int op_ret, int op_errno, +                         char *op_errstr) +{ +        int                     ret = -1; +        xmlTextWriterPtr        writer = NULL; +        xmlBufferPtr            buf = NULL; +        int                     count = 0; +        char                    *volname = NULL; +        char                    *volume_id = NULL; +        int                     type = 0; +        int                     status = 0; +        int                     brick_count = 0; +        int                     dist_count = 0; +        int                     stripe_count = 0; +        int                     replica_count = 0; +        int                     transport = 0; +        char                    *brick = NULL; +        char                    key[1024] = {0,}; +        int                     i = 0; +        int                     j = 1; + +        ret = cli_begin_xml_output (&writer, &buf); +        if (ret) +                goto out; + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) +                goto out; + +        /* <volInfo> */ +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volInfo"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) +                goto out; +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", +                                               "%d", count); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i = 0; i < count; i++) { +                /* <volume> */ +                ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.name", i); +                ret = dict_get_str (dict, key, &volname); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"name", +                                                       "%s", volname); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.volume_id", i); +                ret = dict_get_str (dict, key, &volume_id); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"id", +                                                       "%s", volume_id); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.type", i); +                ret = dict_get_int32 (dict, key, &type); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"type", +                                                       "%d", type); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.status", i); +                ret = dict_get_int32 (dict, key, &status); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"status", +                                                       "%d", status); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.brick_count", i); +                ret = dict_get_int32 (dict, key, &brick_count); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"brickCount", +                                                       "%d", brick_count); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.dist_count", i); +                ret = dict_get_int32 (dict, key, &dist_count); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"distCount", +                                                       "%d", dist_count); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.stripe_count", i); +                ret = dict_get_int32 (dict, key, &stripe_count); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"stripeCount", +                                                       "%d", stripe_count); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.replica_count", i); +                ret = dict_get_int32 (dict, key, &replica_count); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"replicaCount", +                                                       "%d", replica_count); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d.transport", i); +                ret = dict_get_int32 (dict, key, &transport); +                if (ret) +                        goto out; +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"transport", +                                                       "%d", transport); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                while (j <= brick_count) { +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "volume%d.brick%d", i, j); +                        ret = dict_get_str (dict, key, &brick); +                        if (ret) +                                goto out; +                        ret = xmlTextWriterWriteFormatElement +                                (writer, (xmlChar *)"brick", "%s", brick); +                        XML_RET_CHECK_AND_GOTO (ret, out); +                        j++; +                } + +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d", i); +                ret = cli_xml_output_vol_info_options (writer, dict, key); +                if (ret) +                        goto out; + +                /* </volume> */ +                ret = xmlTextWriterEndElement (writer); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } + +        /* </volInfo> */ +        ret = xmlTextWriterEndElement (writer); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = cli_end_xml_output (writer, buf); +        if (ret) +                goto out; +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} +#endif diff --git a/cli/src/cli.c b/cli/src/cli.c index 78c76c53fd1..70204cabeb5 100644 --- a/cli/src/cli.c +++ b/cli/src/cli.c @@ -327,6 +327,11 @@ cli_opt_parse (char *opt, struct cli_state *state)                  exit (0);          } +        if (strcmp (opt, "xml") == 0) { +                state->mode |= GLUSTER_MODE_XML; +                return 0; +        } +          oarg = strtail (opt, "mode=");          if (oarg) {                  if (strcmp (oarg, "script") == 0) { diff --git a/cli/src/cli.h b/cli/src/cli.h index e091e7004a8..0814065a0fd 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -46,7 +46,7 @@ enum argp_option_keys {  #define GLUSTER_MODE_SCRIPT    (1 << 0)  #define GLUSTER_MODE_ERR_FATAL (1 << 1) - +#define GLUSTER_MODE_XML       (1 << 2)  struct cli_state;  struct cli_cmd_word;  struct cli_cmd_tree; @@ -264,4 +264,28 @@ cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status);  void  cli_print_line (int len); + +#if (HAVE_LIB_XML) +int +cli_xml_output_str (char *op, char *str, int op_ret, int op_errno, char *op_errstr); + +int +cli_xml_output_dict (char *op, dict_t *dict, int op_ret, int op_errno, char *op_errstr); + +int +cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, char *op_errstr); + +int +cli_xml_output_vol_profile (dict_t *dict, int op_ret, int op_errno, char *op_errstr); + +int +cli_xml_output_vol_status (dict_t *dict, int op_ret, int op_errno, char *op_errstr); + +int +cli_xml_output_vol_list (dict_t *dict, int op_ret, int op_errno, char *op_errstr); + +int +cli_xml_output_vol_info (dict_t *dict, int op_ret, int op_errno, char *op_errstr); +#endif +  #endif /* __CLI_H__ */ diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 97199609133..08f6194a926 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -154,6 +154,7 @@ enum gluster_cli_procnum {          GLUSTER_CLI_UMOUNT,          GLUSTER_CLI_HEAL_VOLUME,          GLUSTER_CLI_STATEDUMP_VOLUME, +        GLUSTER_CLI_LIST_VOLUME,          GLUSTER_CLI_MAXVALUE,  }; diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index f2980e7efda..257930720a4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -883,6 +883,64 @@ out:          return ret;  } +int +glusterd_handle_cli_list_volume (rpcsvc_request_t *req) +{ +        int                     ret = -1; +        dict_t                  *dict = NULL; +        glusterd_conf_t         *priv = NULL; +        glusterd_volinfo_t      *volinfo = NULL; +        int                     count = 0; +        char                    key[1024] = {0,}; +        gf_cli_rsp              rsp = {0,}; + +        GF_ASSERT (req); + +        priv = THIS->private; +        GF_ASSERT (priv); + +        dict = dict_new (); +        if (!dict) +                goto out; + +        list_for_each_entry (volinfo, &priv->volumes, vol_list) { +                memset (key, 0, sizeof (key)); +                snprintf (key, sizeof (key), "volume%d", count); +                ret = dict_set_str (dict, key, volinfo->volname); +                if (ret) +                        goto out; +                count++; +        } + +        ret = dict_set_int32 (dict, "count", count); +        if (ret) +                goto out; + +        ret = dict_allocate_and_serialize (dict, &rsp.dict.dict_val, +                                           (size_t *)&rsp.dict.dict_len); +        if (ret) +                goto out; + +        ret = 0; + +out: +        rsp.op_ret = ret; +        if (ret) +                rsp.op_errstr = "Error listing volumes"; +        else +                rsp.op_errstr = ""; + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL, +                                     (xdrproc_t)xdr_gf_cli_rsp); + +        if (dict) +                dict_unref (dict); + +        glusterd_friend_sm (); +        glusterd_op_sm (); +        return ret; +} +  int32_t  glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx)  { @@ -2839,6 +2897,7 @@ rpcsvc_actor_t gd_svc_cli_actors[] = {          [GLUSTER_CLI_UMOUNT]        = { "UMOUNT", GLUSTER_CLI_UMOUNT, glusterd_handle_umount, NULL, NULL, 1},          [GLUSTER_CLI_HEAL_VOLUME]  = { "HEAL_VOLUME", GLUSTER_CLI_HEAL_VOLUME, glusterd_handle_cli_heal_volume, NULL, NULL, 0},          [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", GLUSTER_CLI_STATEDUMP_VOLUME, glusterd_handle_cli_statedump_volume, NULL, NULL, 0}, +        [GLUSTER_CLI_LIST_VOLUME] = {"LIST_VOLUME", GLUSTER_CLI_LIST_VOLUME, glusterd_handle_cli_list_volume, NULL, NULL, 0},  };  struct rpcsvc_program gd_svc_cli_prog = { diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 21d8ab0aca0..275e1ccffba 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -146,6 +146,7 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret,          case GD_OP_REPLACE_BRICK:          case GD_OP_STATUS_VOLUME:          case GD_OP_SET_VOLUME: +        case GD_OP_LIST_VOLUME:          {                  /*nothing specific to be done*/                  break; diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 3c671da641c..bea15689bc2 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -77,6 +77,7 @@ typedef enum glusterd_op_ {          GD_OP_REBALANCE,          GD_OP_HEAL_VOLUME,          GD_OP_STATEDUMP_VOLUME, +        GD_OP_LIST_VOLUME,          GD_OP_MAX,  } glusterd_op_t; @@ -541,6 +542,8 @@ int glusterd_handle_defrag_start (glusterd_volinfo_t *volinfo, char *op_errstr,                                    size_t len, int cmd, defrag_cbk_fn_t cbk);  int glusterd_handle_cli_heal_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_list_volume (rpcsvc_request_t *req); +  /* op-sm functions */  int glusterd_op_stage_heal_volume (dict_t *dict, char **op_errstr);  int glusterd_op_heal_volume (dict_t *dict, char **op_errstr);  | 
