12a457
From cb4d2f75273f850a5f324663f8fb685ff9ef24ed Mon Sep 17 00:00:00 2001
12a457
From: hari gowtham <hgowtham@redhat.com>
12a457
Date: Thu, 28 Apr 2016 11:48:23 +0530
12a457
Subject: [PATCH 138/139] heal/xml : xml implementation of heal info and splitbrain info
12a457
12a457
Current output:
12a457
heal didn't have xml output.
12a457
12a457
expected output with patch:
12a457
gluster v heal v1 info --xml
12a457
12a457
<cliOutput>
12a457
  <healInfo>
12a457
    <bricks>
12a457
      <brick hostUuid="3677edbb-0a6a-415e-b0ee-b846ff93259c">
12a457
        <name>10.70.42.183:/home/bricks/b1</name>
12a457
        <status>Connected</status>
12a457
        <numberOfEntries>0</numberOfEntries>
12a457
      </brick>
12a457
      <brick hostUuid="3677edbb-0a6a-415e-b0ee-b846ff93259c">
12a457
        <name>10.70.42.183:/home/bricks/b2</name>
12a457
        <status>Connected</status>
12a457
        <numberOfEntries>0</numberOfEntries>
12a457
      </brick>
12a457
    </bricks>
12a457
  </healInfo>
12a457
  <opRet>0</opRet>
12a457
  <opErrno>0</opErrno>
12a457
  <opErrstr/>
12a457
</cliOutput>
12a457
12a457
gluster v heal v1 info split-brain --xml
12a457
12a457
<cliOutput>
12a457
  <healInfo>
12a457
    <bricks>
12a457
      <brick hostUuid="3677edbb-0a6a-415e-b0ee-b846ff93259c">
12a457
        <name>10.70.42.183:/home/bricks/b1</name>
12a457
        <status>Connected</status>
12a457
        <numberOfEntries>0</numberOfEntries>
12a457
      </brick>
12a457
      <brick hostUuid="3677edbb-0a6a-415e-b0ee-b846ff93259c">
12a457
        <name>10.70.42.183:/home/bricks/b2</name>
12a457
        <status>Connected</status>
12a457
        <numberOfEntries>0</numberOfEntries>
12a457
      </brick>
12a457
    </bricks>
12a457
  </healInfo>
12a457
  <opRet>0</opRet>
12a457
  <opErrno>0</opErrno>
12a457
  <opErrstr/>
12a457
</cliOutput>
12a457
12a457
 >Change-Id: I20ad5eb7950d4721364ab46089e3af515162db82
12a457
 >BUG: 1331287
12a457
 >Signed-off-by: hari gowtham <hgowtham@redhat.com>
12a457
 >Reviewed-on: http://review.gluster.org/14100
12a457
 >Reviewed-by: Ravishankar N <ravishankar@redhat.com>
12a457
 >Tested-by: Ravishankar N <ravishankar@redhat.com>
12a457
 >Smoke: Gluster Build System <jenkins@build.gluster.com>
12a457
 >NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
12a457
 >Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
12a457
 >CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
12a457
12a457
BUG: 1313370
12a457
Change-Id: I1f06bdebcf99128fd94f523dc447466b93aeb37d
12a457
Signed-off-by: hari gowtham <hgowtham@redhat.com>
12a457
Reviewed-on: https://code.engineering.redhat.com/gerrit/73855
12a457
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
12a457
Tested-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
12a457
---
12a457
 cli/src/cli-cmd-volume.c |   10 +-
12a457
 heal/src/glfs-heal.c     |  413 ++++++++++++++++++++++++++++++++++++++++------
12a457
 2 files changed, 371 insertions(+), 52 deletions(-)
12a457
12a457
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
12a457
index 26936c2..614e4f6 100644
12a457
--- a/cli/src/cli-cmd-volume.c
12a457
+++ b/cli/src/cli-cmd-volume.c
12a457
@@ -2139,6 +2139,9 @@ cli_launch_glfs_heal (int heal_op, dict_t *options)
12a457
 
12a457
         switch (heal_op) {
12a457
         case GF_SHD_OP_INDEX_SUMMARY:
12a457
+                if (global_state->mode & GLUSTER_MODE_XML) {
12a457
+                        runner_add_args (&runner, "xml", NULL);
12a457
+                }
12a457
                 break;
12a457
         case GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE:
12a457
                 ret = dict_get_str (options, "file", &filename);
12a457
@@ -2160,6 +2163,9 @@ cli_launch_glfs_heal (int heal_op, dict_t *options)
12a457
                 break;
12a457
         case GF_SHD_OP_SPLIT_BRAIN_FILES:
12a457
                 runner_add_args (&runner, "split-brain-info", NULL);
12a457
+                if (global_state->mode & GLUSTER_MODE_XML) {
12a457
+                        runner_add_args (&runner, "xml", NULL);
12a457
+                }
12a457
                 break;
12a457
         default:
12a457
                 ret = -1;
12a457
@@ -2229,8 +2235,10 @@ cli_cmd_volume_heal_cbk (struct cli_state *state, struct cli_cmd_word *word,
12a457
 out:
12a457
         if (ret) {
12a457
                 cli_cmd_sent_status_get (&sent);
12a457
-                if ((sent == 0) && (parse_error == 0))
12a457
+                if ((sent == 0) && (parse_error == 0) &&
12a457
+                    !(global_state->mode & GLUSTER_MODE_XML)) {
12a457
                         cli_out ("Volume heal failed.");
12a457
+                }
12a457
         }
12a457
 
12a457
         CLI_STACK_DESTROY (frame);
12a457
diff --git a/heal/src/glfs-heal.c b/heal/src/glfs-heal.c
12a457
index 19bf417..9865f53 100644
12a457
--- a/heal/src/glfs-heal.c
12a457
+++ b/heal/src/glfs-heal.c
12a457
@@ -22,17 +22,260 @@
12a457
 #include <time.h>
12a457
 #include "glusterfs.h"
12a457
 
12a457
+#if (HAVE_LIB_XML)
12a457
+#include <libxml/encoding.h>
12a457
+#include <libxml/xmlwriter.h>
12a457
+
12a457
+xmlTextWriterPtr glfsh_writer;
12a457
+xmlDocPtr        glfsh_doc = NULL;
12a457
+#endif
12a457
+
12a457
+#define XML_RET_CHECK_AND_GOTO(ret, label)      do {            \
12a457
+                if (ret < 0) {                                  \
12a457
+                        ret = -1;                               \
12a457
+                        goto label;                             \
12a457
+                }                                               \
12a457
+                else                                            \
12a457
+                        ret = 0;                                \
12a457
+        } while (0)                                             \
12a457
+
12a457
+typedef void    (*print_status) (dict_t *, char *, uuid_t, uint64_t *,
12a457
+                 gf_boolean_t flag);
12a457
+
12a457
+int glfsh_heal_splitbrain_file (glfs_t *fs, xlator_t *top_subvol,
12a457
+                                loc_t *rootloc, char *file, dict_t *xattr_req);
12a457
+
12a457
+
12a457
+typedef struct glfs_info {
12a457
+        int (*init)(void);
12a457
+        int (*print_brick_from_xl)(xlator_t *xl, loc_t *rootloc);
12a457
+        int (*print_heal_op_status)(int ret, uint64_t num_entries,
12a457
+                        char *fmt_str);
12a457
+        void (*print_heal_status)(char *path, uuid_t gfid, char *status);
12a457
+        void (*print_spb_status)(char *path, uuid_t gfid, char *status);
12a457
+        int (*end) (int op_ret, char *op_errstr);
12a457
+} glfsh_info_t;
12a457
+
12a457
+glfsh_info_t *glfsh_output = NULL;
12a457
+int32_t is_xml;
12a457
+
12a457
 #define DEFAULT_HEAL_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs"
12a457
 #define USAGE_STR "Usage: %s <VOLNAME> [bigger-file <FILE> | "\
12a457
                   "latest-mtime <FILE> | "\
12a457
                   "source-brick <HOSTNAME:BRICKNAME> [<FILE>] | "\
12a457
                   "split-brain-info]\n"
12a457
 
12a457
-typedef void    (*print_status) (dict_t *, char *, uuid_t, uint64_t *,
12a457
-                 gf_boolean_t flag);
12a457
+int
12a457
+glfsh_init ()
12a457
+{
12a457
+        return 0;
12a457
+}
12a457
 
12a457
-int glfsh_heal_splitbrain_file (glfs_t *fs, xlator_t *top_subvol,
12a457
-                                loc_t *rootloc, char *file, dict_t *xattr_req);
12a457
+int
12a457
+glfsh_end (int op_ret, char *op_errstr)
12a457
+{
12a457
+        if (op_errstr)
12a457
+                printf ("%s\n", op_errstr);
12a457
+        return 0;
12a457
+}
12a457
+
12a457
+void
12a457
+glfsh_print_hr_spb_status (char *path, uuid_t gfid, char *status)
12a457
+{
12a457
+        printf ("%s\n", path);
12a457
+        return;
12a457
+}
12a457
+
12a457
+void
12a457
+glfsh_print_hr_heal_status (char *path, uuid_t gfid, char *status)
12a457
+{
12a457
+        printf ("%s%s\n", path, status);
12a457
+}
12a457
+
12a457
+#if (HAVE_LIB_XML)
12a457
+
12a457
+int
12a457
+glfsh_xml_init ()
12a457
+{
12a457
+        int     ret     = -1;
12a457
+        glfsh_writer = xmlNewTextWriterDoc (&glfsh_doc, 0);
12a457
+        if (glfsh_writer == NULL) {
12a457
+                return -1;
12a457
+        }
12a457
+
12a457
+        ret = xmlTextWriterStartDocument (glfsh_writer, "1.0", "UTF-8",
12a457
+                        "yes");
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+
12a457
+        /* <cliOutput> */
12a457
+        ret = xmlTextWriterStartElement (glfsh_writer,
12a457
+                        (xmlChar *)"cliOutput");
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+
12a457
+        /* <healInfo> */
12a457
+        xmlTextWriterStartElement (glfsh_writer,
12a457
+                        (xmlChar *)"healInfo");
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+        /* <bricks> */
12a457
+        xmlTextWriterStartElement (glfsh_writer,
12a457
+                        (xmlChar *)"bricks");
12a457
+xml_out:
12a457
+        return ret;
12a457
+}
12a457
+
12a457
+int
12a457
+glfsh_xml_end (int op_ret, char *op_errstr)
12a457
+{
12a457
+        int                     ret             = -1;
12a457
+        int                     op_errno        = 0;
12a457
+        gf_boolean_t            alloc           = _gf_false;
12a457
+
12a457
+        if (op_ret < 0) {
12a457
+                op_errno = -op_ret;
12a457
+                op_ret = -1;
12a457
+                if (op_errstr == NULL) {
12a457
+                        op_errstr = gf_strdup (strerror (op_errno));
12a457
+                        alloc = _gf_true;
12a457
+                }
12a457
+        } else {
12a457
+                op_errstr = NULL;
12a457
+        }
12a457
+
12a457
+        /* </bricks> */
12a457
+        ret = xmlTextWriterEndElement (glfsh_writer);
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+
12a457
+        /* </healInfo> */
12a457
+        ret = xmlTextWriterEndElement (glfsh_writer);
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+
12a457
+        ret = xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                        (xmlChar *)"opRet", "%d", op_ret);
12a457
+
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+
12a457
+        ret = xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                        (xmlChar *)"opErrno",
12a457
+                        "%d", op_errno);
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+
12a457
+        if (op_errstr)
12a457
+                ret = xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                                (xmlChar *)"opErrstr",
12a457
+                                "%s", op_errstr);
12a457
+        else
12a457
+                ret = xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                                (xmlChar *)"opErrstr",
12a457
+                                "%s", "");
12a457
+        ret = xmlTextWriterEndDocument (glfsh_writer);
12a457
+        XML_RET_CHECK_AND_GOTO (ret, xml_out);
12a457
+
12a457
+
12a457
+        /* Dump xml document to stdout and pretty format it */
12a457
+        xmlSaveFormatFileEnc ("-", glfsh_doc, "UTF-8", 1);
12a457
+
12a457
+        xmlFreeTextWriter (glfsh_writer);
12a457
+        xmlFreeDoc (glfsh_doc);
12a457
+xml_out:
12a457
+        if (alloc)
12a457
+                GF_FREE (op_errstr);
12a457
+        return ret;
12a457
+}
12a457
+
12a457
+int
12a457
+glfsh_print_xml_heal_op_status (int ret, uint64_t num_entries, char *fmt_str)
12a457
+{
12a457
+        if (ret < 0 && num_entries == 0) {
12a457
+                xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                                (xmlChar *)"status",
12a457
+                                "%s", strerror (-ret));
12a457
+                if (fmt_str) {
12a457
+                        xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                                        (xmlChar *)"numberOfEntries",
12a457
+                                        "-");
12a457
+                }
12a457
+                goto out;
12a457
+        } else if (ret == 0) {
12a457
+                xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                                                 (xmlChar *)"status",
12a457
+                                                 "%s", "Connected");
12a457
+        }
12a457
+
12a457
+        if (ret < 0) {
12a457
+                if (fmt_str) {
12a457
+                        xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                                        (xmlChar *)"status",
12a457
+                                        "Failed to process entries completely. "
12a457
+                                        "(%s)%s %"PRIu64"", strerror (-ret),
12a457
+                                        fmt_str,
12a457
+                                        num_entries);
12a457
+                }
12a457
+        } else {
12a457
+                if (fmt_str)
12a457
+                        xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                                        (xmlChar *)"numberOfEntries",
12a457
+                                        "%"PRIu64"", num_entries);
12a457
+        }
12a457
+out:
12a457
+        return xmlTextWriterEndElement (glfsh_writer);
12a457
+}
12a457
+
12a457
+void
12a457
+glfsh_print_xml_file_status (char *path, uuid_t gfid, char *status)
12a457
+{
12a457
+        xmlTextWriterStartElement (glfsh_writer, (xmlChar *)"file");
12a457
+        xmlTextWriterWriteFormatAttribute (glfsh_writer, (xmlChar *)"gfid",
12a457
+                                           "%s", uuid_utoa (gfid));
12a457
+        xmlTextWriterWriteFormatString (glfsh_writer, "%s", path);
12a457
+        xmlTextWriterEndElement (glfsh_writer);
12a457
+        return;
12a457
+}
12a457
+
12a457
+int
12a457
+glfsh_print_xml_brick_from_xl (xlator_t *xl, loc_t *rootloc)
12a457
+{
12a457
+        char    *remote_host = NULL;
12a457
+        char    *remote_subvol = NULL;
12a457
+        char    *uuid = NULL;
12a457
+        int     ret = 0;
12a457
+        int     x_ret = 0;
12a457
+
12a457
+        ret = dict_get_str (xl->options, "remote-host", &remote_host);
12a457
+        if (ret < 0)
12a457
+                goto print;
12a457
+
12a457
+        ret = dict_get_str (xl->options, "remote-subvolume", &remote_subvol);
12a457
+        if (ret < 0)
12a457
+                goto print;
12a457
+        ret = syncop_getxattr (xl, rootloc, &xl->options,
12a457
+                        GF_XATTR_NODE_UUID_KEY, NULL, NULL);
12a457
+        if (ret < 0)
12a457
+                goto print;
12a457
+
12a457
+        ret = dict_get_str (xl->options, GF_XATTR_NODE_UUID_KEY, &uuid);
12a457
+        if (ret < 0)
12a457
+                goto print;
12a457
+print:
12a457
+
12a457
+        x_ret = xmlTextWriterStartElement (glfsh_writer, (xmlChar *)"brick");
12a457
+        XML_RET_CHECK_AND_GOTO (x_ret, xml_out);
12a457
+        x_ret = xmlTextWriterWriteFormatAttribute (glfsh_writer,
12a457
+                        (xmlChar *)"hostUuid", "%s", uuid?uuid:"-");
12a457
+        XML_RET_CHECK_AND_GOTO (x_ret, xml_out);
12a457
+
12a457
+        if (ret < 0) {
12a457
+                x_ret = xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                        (xmlChar *)"name", "%s", "information not available");
12a457
+                XML_RET_CHECK_AND_GOTO (x_ret, xml_out);
12a457
+        } else {
12a457
+                x_ret = xmlTextWriterWriteFormatElement (glfsh_writer,
12a457
+                        (xmlChar *)"name", "%s:%s", remote_host, remote_subvol);
12a457
+                XML_RET_CHECK_AND_GOTO (x_ret, xml_out);
12a457
+        }
12a457
+xml_out:
12a457
+        return ret;
12a457
+}
12a457
+#endif
12a457
 
12a457
 int
12a457
 glfsh_link_inode_update_loc (loc_t *loc, struct iatt *iattr)
12a457
@@ -51,25 +294,14 @@ out:
12a457
         return ret;
12a457
 }
12a457
 
12a457
-
12a457
-void
12a457
-glfsh_print_heal_op_status (int ret, uint64_t num_entries,
12a457
-                            gf_xl_afr_op_t heal_op)
12a457
+int
12a457
+glfsh_print_hr_heal_op_status (int ret, uint64_t num_entries, char *fmt_str)
12a457
 {
12a457
-        char *fmt_str = NULL;
12a457
-
12a457
-        if (heal_op == GF_SHD_OP_INDEX_SUMMARY)
12a457
-                fmt_str = "Number of entries:";
12a457
-        else if (heal_op == GF_SHD_OP_SPLIT_BRAIN_FILES)
12a457
-                fmt_str = "Number of entries in split-brain:";
12a457
-        else if (heal_op == GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK)
12a457
-                fmt_str = "Number of healed entries:";
12a457
-
12a457
         if (ret < 0 && num_entries == 0) {
12a457
                 printf ("Status: %s\n", strerror (-ret));
12a457
                 if (fmt_str)
12a457
                         printf ("%s -\n", fmt_str);
12a457
-                return;
12a457
+                goto out;
12a457
         } else if (ret == 0) {
12a457
                 printf ("Status: Connected\n");
12a457
         }
12a457
@@ -77,13 +309,31 @@ glfsh_print_heal_op_status (int ret, uint64_t num_entries,
12a457
         if (ret < 0) {
12a457
                 if (fmt_str)
12a457
                         printf ("Status: Failed to process entries completely. "
12a457
-                                "(%s)\n%s: %"PRIu64"\n",
12a457
+                                "(%s)\n%s %"PRIu64"\n",
12a457
                          strerror (-ret), fmt_str, num_entries);
12a457
         } else {
12a457
                 if (fmt_str)
12a457
                         printf ("%s %"PRIu64"\n", fmt_str, num_entries);
12a457
         }
12a457
-        return;
12a457
+out:
12a457
+        printf ("\n");
12a457
+        return 0;
12a457
+}
12a457
+
12a457
+int
12a457
+glfsh_print_heal_op_status (int ret, uint64_t num_entries,
12a457
+                            gf_xl_afr_op_t heal_op)
12a457
+{
12a457
+        char *fmt_str = NULL;
12a457
+
12a457
+        if (heal_op == GF_SHD_OP_INDEX_SUMMARY)
12a457
+                fmt_str = "Number of entries:";
12a457
+        else if (heal_op == GF_SHD_OP_SPLIT_BRAIN_FILES)
12a457
+                fmt_str = "Number of entries in split-brain:";
12a457
+        else if (heal_op == GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK)
12a457
+                fmt_str = "Number of healed entries:";
12a457
+
12a457
+        return glfsh_output->print_heal_op_status (ret, num_entries, fmt_str);
12a457
 }
12a457
 
12a457
 int
12a457
@@ -179,6 +429,7 @@ glfsh_print_spb_status (dict_t *dict, char *path, uuid_t gfid,
12a457
         gf_boolean_t    pending         = _gf_false;
12a457
         gf_boolean_t    split_b         = _gf_false;
12a457
         char            *value          = NULL;
12a457
+        char            gfid_str[64]    = {0};
12a457
 
12a457
         ret = dict_get_str (dict, "heal-info", &value);
12a457
         if (ret)
12a457
@@ -199,8 +450,9 @@ glfsh_print_spb_status (dict_t *dict, char *path, uuid_t gfid,
12a457
         if (split_b) {
12a457
                 if (!flag || (flag && !pending)) {
12a457
                         (*num_entries)++;
12a457
-                        printf ("%s\n",
12a457
-                        path ? path : uuid_utoa (gfid));
12a457
+                        glfsh_output->print_spb_status (path ? path :
12a457
+                                                uuid_utoa_r (gfid, gfid_str),
12a457
+                                                gfid, NULL);
12a457
                 }
12a457
         }
12a457
         return;
12a457
@@ -214,6 +466,7 @@ glfsh_print_heal_status (dict_t *dict, char *path, uuid_t gfid,
12a457
         gf_boolean_t    pending         = _gf_false;
12a457
         char            *status         = NULL;
12a457
         char            *value          = NULL;
12a457
+        char            gfid_str[64]    = {0};
12a457
 
12a457
         ret = dict_get_str (dict, "heal-info", &value);
12a457
         if (ret || (!strcmp (value, "no-heal")))
12a457
@@ -267,8 +520,10 @@ out:
12a457
                 status = NULL;
12a457
 
12a457
         (*num_entries)++;
12a457
-        printf ("%s%s\n",
12a457
-                path ? path : uuid_utoa (gfid), status ? status : "");
12a457
+        glfsh_output->print_heal_status (path ? path :
12a457
+                                                uuid_utoa_r (gfid, gfid_str),
12a457
+                                         gfid,
12a457
+                                         status ? status : "");
12a457
 
12a457
         GF_FREE (status);
12a457
         return;
12a457
@@ -418,7 +673,7 @@ out:
12a457
 }
12a457
 
12a457
 static int
12a457
-glfsh_print_brick_from_xl (xlator_t *xl)
12a457
+glfsh_print_brick_from_xl (xlator_t *xl, loc_t *rootloc)
12a457
 {
12a457
         char    *remote_host = NULL;
12a457
         char    *remote_subvol = NULL;
12a457
@@ -478,7 +733,7 @@ out:
12a457
         return ret;
12a457
 }
12a457
 
12a457
-void
12a457
+int
12a457
 glfsh_print_pending_heals (glfs_t *fs, xlator_t *top_subvol, loc_t *rootloc,
12a457
                            xlator_t *xl, gf_xl_afr_op_t heal_op, gf_boolean_t
12a457
                            is_parent_replicate)
12a457
@@ -491,12 +746,11 @@ glfsh_print_pending_heals (glfs_t *fs, xlator_t *top_subvol, loc_t *rootloc,
12a457
         xattr_req = dict_new();
12a457
         if (!xattr_req)
12a457
                 goto out;
12a457
-
12a457
         ret = dict_set_int32 (xattr_req, "heal-op", heal_op);
12a457
         if (ret)
12a457
                 goto out;
12a457
 
12a457
-        ret = glfsh_print_brick_from_xl (xl);
12a457
+        ret = glfsh_output->print_brick_from_xl (xl, rootloc);
12a457
         if (ret < 0)
12a457
                 goto out;
12a457
 
12a457
@@ -520,7 +774,8 @@ out:
12a457
         if (xattr_req)
12a457
                 dict_unref (xattr_req);
12a457
         glfsh_print_heal_op_status (ret, total, heal_op);
12a457
-        return;
12a457
+        return ret;
12a457
+
12a457
 }
12a457
 
12a457
 static int
12a457
@@ -607,7 +862,6 @@ glfsh_gather_heal_info (glfs_t *fs, xlator_t *top_subvol, loc_t *rootloc,
12a457
                                                            (heal_xl->type,
12a457
                                                            "cluster/replicate"));
12a457
                                 THIS = old_THIS;
12a457
-                                printf ("\n");
12a457
                         }
12a457
                 }
12a457
 
12a457
@@ -842,6 +1096,27 @@ cleanup (glfs_t *fs)
12a457
 #endif
12a457
 }
12a457
 
12a457
+
12a457
+glfsh_info_t glfsh_human_readable = {
12a457
+        .init = glfsh_init,
12a457
+        .print_brick_from_xl = glfsh_print_brick_from_xl,
12a457
+        .print_heal_op_status = glfsh_print_hr_heal_op_status,
12a457
+        .print_heal_status = glfsh_print_hr_heal_status,
12a457
+        .print_spb_status = glfsh_print_hr_spb_status,
12a457
+        .end = glfsh_end
12a457
+};
12a457
+
12a457
+#if (HAVE_LIB_XML)
12a457
+glfsh_info_t glfsh_xml_output = {
12a457
+        .init = glfsh_xml_init,
12a457
+        .print_brick_from_xl = glfsh_print_xml_brick_from_xl,
12a457
+        .print_heal_op_status = glfsh_print_xml_heal_op_status,
12a457
+        .print_heal_status = glfsh_print_xml_file_status,
12a457
+        .print_spb_status = glfsh_print_xml_file_status,
12a457
+        .end = glfsh_xml_end
12a457
+};
12a457
+#endif
12a457
+
12a457
 int
12a457
 main (int argc, char **argv)
12a457
 {
12a457
@@ -854,6 +1129,7 @@ main (int argc, char **argv)
12a457
         char      *hostname = NULL;
12a457
         char      *path = NULL;
12a457
         char      *file = NULL;
12a457
+        char      *op_errstr = NULL;
12a457
         gf_xl_afr_op_t heal_op = -1;
12a457
 
12a457
         if (argc < 2) {
12a457
@@ -861,6 +1137,7 @@ main (int argc, char **argv)
12a457
                 ret = -1;
12a457
                 goto out;
12a457
         }
12a457
+
12a457
         volname = argv[1];
12a457
         switch (argc) {
12a457
         case 2:
12a457
@@ -869,6 +1146,9 @@ main (int argc, char **argv)
12a457
         case 3:
12a457
                 if (!strcmp (argv[2], "split-brain-info")) {
12a457
                         heal_op = GF_SHD_OP_SPLIT_BRAIN_FILES;
12a457
+                } else if (!strcmp (argv[2], "xml")) {
12a457
+                        heal_op = GF_SHD_OP_INDEX_SUMMARY;
12a457
+                        is_xml = 1;
12a457
                 } else {
12a457
                         printf (USAGE_STR, argv[0]);
12a457
                         ret = -1;
12a457
@@ -876,7 +1156,11 @@ main (int argc, char **argv)
12a457
                 }
12a457
                 break;
12a457
         case 4:
12a457
-                if (!strcmp (argv[2], "bigger-file")) {
12a457
+                if ((!strcmp (argv[2], "split-brain-info"))
12a457
+                                && (!strcmp (argv[3], "xml"))) {
12a457
+                        heal_op = GF_SHD_OP_SPLIT_BRAIN_FILES;
12a457
+                        is_xml = 1;
12a457
+                } else if (!strcmp (argv[2], "bigger-file")) {
12a457
                         heal_op = GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE;
12a457
                         file = argv[3];
12a457
                 } else if (!strcmp (argv[2], "latest-mtime")) {
12a457
@@ -910,10 +1194,26 @@ main (int argc, char **argv)
12a457
                 goto out;
12a457
         }
12a457
 
12a457
+        glfsh_output = &glfsh_human_readable;
12a457
+        if (is_xml) {
12a457
+#if (HAVE_LIB_XML)
12a457
+                glfsh_output = &glfsh_xml_output;
12a457
+#else
12a457
+                /*No point doing anything, just fail the command*/
12a457
+                exit (EXIT_FAILURE);
12a457
+#endif
12a457
+
12a457
+        }
12a457
+
12a457
+        ret = glfsh_output->init ();
12a457
+        if (ret)
12a457
+                exit (EXIT_FAILURE);
12a457
+
12a457
         fs = glfs_new (volname);
12a457
         if (!fs) {
12a457
-                ret = -1;
12a457
-                printf ("Not able to initialize volume '%s'\n", volname);
12a457
+                ret = -errno;
12a457
+                gf_asprintf (&op_errstr, "Not able to initialize volume '%s'",
12a457
+                             volname);
12a457
                 goto out;
12a457
         }
12a457
 
12a457
@@ -923,49 +1223,56 @@ main (int argc, char **argv)
12a457
 
12a457
         ret = glfs_set_volfile_server (fs, "unix", DEFAULT_GLUSTERD_SOCKFILE, 0);
12a457
         if (ret) {
12a457
-                printf("Setting the volfile server failed, %s\n", strerror (errno));
12a457
+                ret = -errno;
12a457
+                gf_asprintf (&op_errstr, "Setting the volfile server failed, "
12a457
+                             "%s", strerror (errno));
12a457
                 goto out;
12a457
         }
12a457
         snprintf (logfilepath, sizeof (logfilepath),
12a457
                   DEFAULT_HEAL_LOG_FILE_DIRECTORY"/glfsheal-%s.log", volname);
12a457
         ret = glfs_set_logging(fs, logfilepath, GF_LOG_INFO);
12a457
         if (ret < 0) {
12a457
-                printf ("Failed to set the log file path, %s\n", strerror (errno));
12a457
+                ret = -errno;
12a457
+                gf_asprintf (&op_errstr, "Failed to set the log file path, "
12a457
+                             "%s", strerror (errno));
12a457
                 goto out;
12a457
         }
12a457
 
12a457
         ret = glfs_init (fs);
12a457
         if (ret < 0) {
12a457
-                ret = -1;
12a457
+                ret = -errno;
12a457
                 if (errno == ENOENT) {
12a457
-                        printf ("Volume %s does not exist\n", volname);
12a457
-                }
12a457
-                else {
12a457
-                        printf ("%s: Not able to fetch volfile from "
12a457
-                                 "glusterd\n", volname);
12a457
+                        gf_asprintf (&op_errstr, "Volume %s does not exist",
12a457
+                                     volname);
12a457
+                } else {
12a457
+                        gf_asprintf (&op_errstr, "%s: Not able to fetch "
12a457
+                                     "volfile from glusterd", volname);
12a457
                 }
12a457
                 goto out;
12a457
         }
12a457
 
12a457
         top_subvol = glfs_active_subvol (fs);
12a457
         if (!top_subvol) {
12a457
-                ret = -1;
12a457
+                ret = -errno;
12a457
                 if (errno == ENOTCONN) {
12a457
-                        printf ("Volume %s is not started (Or) All the bricks "
12a457
-                                 "are not running.\n", volname);
12a457
+                        gf_asprintf (&op_errstr, "Volume %s is not started "
12a457
+                                                 "(Or) All the bricks are not "
12a457
+                                                 "running.", volname);
12a457
                 }
12a457
                 else {
12a457
-                        printf ("%s: Not able to mount the volume, %s\n",
12a457
-                                 volname, strerror (errno));
12a457
+                        gf_asprintf (&op_errstr, "%s: Not able to mount the "
12a457
+                                             "volume, %s", volname,
12a457
+                                             strerror (errno));
12a457
                 }
12a457
                 goto out;
12a457
         }
12a457
 
12a457
         ret = glfsh_validate_volume (top_subvol, heal_op);
12a457
         if (ret < 0) {
12a457
-                printf ("Volume %s is not of type %s\n", volname,
12a457
-                        (heal_op == GF_SHD_OP_INDEX_SUMMARY) ?
12a457
-                        "replicate/disperse":"replicate");
12a457
+                ret = -EINVAL;
12a457
+                gf_asprintf (&op_errstr, "Volume %s is not of type %s", volname,
12a457
+                                     (heal_op == GF_SHD_OP_INDEX_SUMMARY) ?
12a457
+                                     "replicate/disperse":"replicate");
12a457
                 goto out;
12a457
         }
12a457
         rootloc.inode = inode_ref (top_subvol->itable->root);
12a457
@@ -987,10 +1294,11 @@ main (int argc, char **argv)
12a457
                                              hostname, path, file);
12a457
                 break;
12a457
         default:
12a457
-                ret = -1;
12a457
+                ret = -EINVAL;
12a457
                 break;
12a457
         }
12a457
 
12a457
+        glfsh_output->end (ret, NULL);
12a457
         loc_wipe (&rootloc);
12a457
         glfs_subvol_done (fs, top_subvol);
12a457
         cleanup (fs);
12a457
@@ -1001,6 +1309,9 @@ out:
12a457
                 glfs_subvol_done (fs, top_subvol);
12a457
         loc_wipe (&rootloc);
12a457
         cleanup (fs);
12a457
-
12a457
+        if (glfsh_output)
12a457
+                glfsh_output->end (ret, op_errstr);
12a457
+        if (op_errstr)
12a457
+                GF_FREE (op_errstr);
12a457
         return ret;
12a457
 }
12a457
-- 
12a457
1.7.1
12a457