Patchwork [v4,BUG:1750,2/3] implemented graph printing

login
register
Submitter Csaba Henk
Date 2010-10-02 13:00:38
Message ID <1286024439-32587-2-git-send-email-csaba@gluster.com>
Download mbox | patch
Permalink /patch/5190/
State Accepted
Headers show

Comments

Csaba Henk - 2010-10-02 13:00:38
Signed-off-by: Csaba Henk <csaba@gluster.com>
---
 libglusterfs/src/Makefile.am       |    4 +-
 libglusterfs/src/graph-mem-types.h |   32 ++++++
 libglusterfs/src/graph-print.c     |  200 ++++++++++++++++++++++++++++++++++++
 libglusterfs/src/graph-utils.h     |   29 +++++
 libglusterfs/src/mem-pool.c        |   25 +++--
 libglusterfs/src/mem-pool.h        |    4 +
 6 files changed, 285 insertions(+), 9 deletions(-)
 create mode 100644 libglusterfs/src/graph-mem-types.h
 create mode 100644 libglusterfs/src/graph-print.c
 create mode 100644 libglusterfs/src/graph-utils.h

Patch

diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am
index 3513419..71a088d 100644
--- a/libglusterfs/src/Makefile.am
+++ b/libglusterfs/src/Makefile.am
@@ -6,9 +6,9 @@  libglusterfs_la_LIBADD = @LEXLIB@
 
 lib_LTLIBRARIES = libglusterfs.la
 
-libglusterfs_la_SOURCES = dict.c graph.lex.c y.tab.c xlator.c logging.c  hashfn.c defaults.c common-utils.c timer.c inode.c call-stub.c compat.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c syscall.c iobuf.c globals.c statedump.c stack.c checksum.c $(CONTRIBDIR)/md5/md5.c $(CONTRIBDIR)/rbtree/rb.c rbthash.c latency.c graph.c $(CONTRIBDIR)/uuid/clear.c $(CONTRIBDIR)/uuid/copy.c $(CONTRIBDIR)/uuid/gen_uuid.c $(CONTRIBDIR)/uuid/pack.c $(CONTRIBDIR)/uuid/tst_uuid.c $(CONTRIBDIR)/uuid/parse.c $(CONTRIBDIR)/uuid/unparse.c $(CONTRIBDIR)/uuid/uuid_time.c $(CONTRIBDIR)/uuid/compare.c $(CONTRIBDIR)/uuid/isnull.c $(CONTRIBDIR)/uuid/unpack.c syncop.c
+libglusterfs_la_SOURCES = dict.c graph.lex.c y.tab.c xlator.c logging.c  hashfn.c defaults.c common-utils.c timer.c inode.c call-stub.c compat.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c syscall.c iobuf.c globals.c statedump.c stack.c checksum.c $(CONTRIBDIR)/md5/md5.c $(CONTRIBDIR)/rbtree/rb.c rbthash.c latency.c graph.c $(CONTRIBDIR)/uuid/clear.c $(CONTRIBDIR)/uuid/copy.c $(CONTRIBDIR)/uuid/gen_uuid.c $(CONTRIBDIR)/uuid/pack.c $(CONTRIBDIR)/uuid/tst_uuid.c $(CONTRIBDIR)/uuid/parse.c $(CONTRIBDIR)/uuid/unparse.c $(CONTRIBDIR)/uuid/uuid_time.c $(CONTRIBDIR)/uuid/compare.c $(CONTRIBDIR)/uuid/isnull.c $(CONTRIBDIR)/uuid/unpack.c syncop.c graph-print.c
 
-noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h  xlator.h  stack.h timer.h list.h inode.h call-stub.h compat.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h syscall.h iobuf.h globals.h statedump.h checksum.h $(CONTRIBDIR)/md5/md5.h $(CONTRIBDIR)/rbtree/rb.h rbthash.h iatt.h latency.h mem-types.h $(CONTRIBDIR)/uuid/uuidd.h $(CONTRIBDIR)/uuid/uuid.h $(CONTRIBDIR)/uuid/uuidP.h $(CONTRIBDIR)/uuid/uuid_types.h syncop.h
+noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h  xlator.h  stack.h timer.h list.h inode.h call-stub.h compat.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h syscall.h iobuf.h globals.h statedump.h checksum.h $(CONTRIBDIR)/md5/md5.h $(CONTRIBDIR)/rbtree/rb.h rbthash.h iatt.h latency.h mem-types.h $(CONTRIBDIR)/uuid/uuidd.h $(CONTRIBDIR)/uuid/uuid.h $(CONTRIBDIR)/uuid/uuidP.h $(CONTRIBDIR)/uuid/uuid_types.h syncop.h graph-utils.h graph-mem-types.h
 
 EXTRA_DIST = graph.l graph.y
 
diff --git a/libglusterfs/src/graph-mem-types.h b/libglusterfs/src/graph-mem-types.h
new file mode 100644
index 0000000..49feb76
--- /dev/null
+++ b/libglusterfs/src/graph-mem-types.h
@@ -0,0 +1,32 @@ 
+/*
+   Copyright (c) 2010 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/>.
+*/
+
+#ifndef __GRAPH_MEM_TYPES_H__
+#define __GRAPH_MEM_TYPES_H__
+
+#include "mem-types.h"
+
+#define GF_MEM_TYPE_START (gf_common_mt_end + 1)
+
+enum gfd_mem_types_ {
+        gf_graph_mt_buf = GF_MEM_TYPE_START,
+        gfd_mt_end
+};
+#endif
+
diff --git a/libglusterfs/src/graph-print.c b/libglusterfs/src/graph-print.c
new file mode 100644
index 0000000..a6c20c7
--- /dev/null
+++ b/libglusterfs/src/graph-print.c
@@ -0,0 +1,200 @@ 
+/*
+  Copyright (c) 2010 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/uio.h>
+
+#include "common-utils.h"
+#include "xlator.h"
+#include "graph-mem-types.h"
+#include "graph-utils.h"
+
+
+
+struct gf_printer {
+        ssize_t (*write) (struct gf_printer *gp, char *buf, size_t len);
+        void *priv;
+};
+
+static ssize_t
+gp_write_file (struct gf_printer *gp, char *buf, size_t len)
+{
+        FILE *f = gp->priv;
+
+        if (fwrite (buf, len, 1, f) != 1) {
+                gf_log ("graph-print", GF_LOG_ERROR, "fwrite failed (%s)",
+                        strerror (errno));
+
+                return -1;
+        }
+
+        return len;
+}
+
+static ssize_t
+gp_write_buf (struct gf_printer *gp, char *buf, size_t len)
+{
+        struct iovec *iov = gp->priv;
+
+        if (iov->iov_len < len) {
+                gf_log ("graph-print", GF_LOG_ERROR, "buffer full");
+
+                return -1;
+        }
+
+        memcpy (iov->iov_base, buf, len);
+        iov->iov_base += len;
+        iov->iov_len  -= len;
+
+        return len;
+}
+
+static int
+gpprintf (struct gf_printer *gp, const char *format, ...)
+{
+        va_list arg;
+        char *str = NULL;
+        int ret = 0;
+
+        va_start (arg, format);
+        ret = gf_vasprintf (&str, format, arg);
+        va_end (arg);
+
+        if (ret < 0)
+                return ret;
+
+        ret = gp->write (gp, str, ret);
+
+        GF_FREE (str);
+
+        return ret;
+}
+
+static int
+glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph)
+{
+#define GPPRINTF(gp, fmt, ...) do {                    \
+        ret = gpprintf (gp, fmt, ## __VA_ARGS__);      \
+        if (ret == -1)                                 \
+                goto out;                              \
+        else                                           \
+                len += ret;                            \
+} while (0)
+
+        xlator_t      *trav = NULL;
+        data_pair_t   *pair = NULL;
+        xlator_list_t *xch = NULL;
+        int            ret = 0;
+        ssize_t        len = 0;
+
+        if (!graph->first)
+                return 0;
+
+        for (trav = graph->first; trav->next; trav = trav->next);
+        for (; trav; trav = trav->prev) {
+                GPPRINTF (gp, "volume %s\n    type %s\n", trav->name,
+                          trav->type);
+
+                for (pair =  trav->options->members_list; pair && pair->next;
+                     pair = pair->next);
+                for (; pair; pair = pair->prev)
+                        GPPRINTF (gp, "    option %s %s\n", pair->key,
+                                  pair->value->data);
+
+                if (trav->children) {
+                        GPPRINTF (gp, "    subvolumes");
+
+                        for (xch = trav->children; xch; xch = xch->next)
+                                GPPRINTF (gp, " %s", xch->xlator->name);
+
+                        GPPRINTF (gp, "\n");
+                }
+
+                GPPRINTF (gp, "end-volume\n");
+                if (trav != graph->first)
+                        GPPRINTF (gp, "\n");
+        }
+
+ out:
+        if (ret == -1) {
+                gf_log ("graph-print", GF_LOG_ERROR, "printing failed");
+
+                return -1;
+        }
+
+        return len;
+
+#undef GPPRINTF
+}
+
+int
+glusterfs_graph_print_file (FILE *file, glusterfs_graph_t *graph)
+{
+        struct gf_printer gp = { .write = gp_write_file,
+                                 .priv  = file
+                               };
+
+        return glusterfs_graph_print (&gp, graph);
+}
+
+char *
+glusterfs_graph_print_buf (glusterfs_graph_t *graph)
+{
+        FILE *f = NULL;
+        struct iovec iov = {0,};
+        int len = 0;
+        char *buf = NULL;
+        struct gf_printer gp = { .write = gp_write_buf,
+                                 .priv  = &iov
+                               };
+
+        f = fopen ("/dev/null", "a");
+        if (!f) {
+                gf_log ("graph-print", GF_LOG_ERROR,
+                        "cannot open /dev/null (%s)", strerror (errno));
+
+                return NULL;
+        }
+        len = glusterfs_graph_print_file (f, graph);
+        fclose (f);
+        if (len == -1)
+                return NULL;
+
+        buf = GF_CALLOC (1, len + 1, gf_graph_mt_buf);
+        if (!buf) {
+                gf_log ("graph-print", GF_LOG_ERROR, "Out of memory");
+
+                return NULL;
+        }
+        iov.iov_base = buf;
+        iov.iov_len  = len;
+
+        len = glusterfs_graph_print (&gp, graph);
+        if (len == -1) {
+                GF_FREE (buf);
+
+                return NULL;
+        }
+
+        return buf;
+}
diff --git a/libglusterfs/src/graph-utils.h b/libglusterfs/src/graph-utils.h
new file mode 100644
index 0000000..359cdcc
--- /dev/null
+++ b/libglusterfs/src/graph-utils.h
@@ -0,0 +1,29 @@ 
+/*
+   Copyright (c) 2010 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/>.
+*/
+
+#ifndef _GRAPH_H_
+#define _GRAPH_H_
+
+int
+glusterfs_graph_print_file (FILE *file, glusterfs_graph_t *graph);
+
+char *
+glusterfs_graph_print_buf (glusterfs_graph_t *graph);
+
+#endif
diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c
index 3df317a..6b5e390 100644
--- a/libglusterfs/src/mem-pool.c
+++ b/libglusterfs/src/mem-pool.c
@@ -197,9 +197,9 @@  __gf_realloc (void *ptr, size_t size)
 }
 
 int
-gf_asprintf (char **string_ptr, const char *format, ...)
+gf_vasprintf (char **string_ptr, const char *format, va_list arg)
 {
-	va_list arg;
+        va_list arg_save;
 	char    *str = NULL;
 	int     size = 0;
 	int     rv = 0;
@@ -207,13 +207,12 @@  gf_asprintf (char **string_ptr, const char *format, ...)
 	if (!string_ptr || !format)
 		return -1;
 
-	va_start (arg, format);
+        va_copy (arg_save, arg);
+
 	size = vsnprintf (NULL, 0, format, arg);
 	size++;
-	va_start (arg, format);
 	str = GF_MALLOC (size, gf_common_mt_asprintf);
 	if (str == NULL) {
-		va_end (arg);
 		/*
 		 * Strictly speaking, GNU asprintf doesn't do this,
 		 * but the caller isn't checking the return value.
@@ -222,13 +221,25 @@  gf_asprintf (char **string_ptr, const char *format, ...)
                          "failed to allocate memory");
 		return -1;
 	}
-	rv = vsnprintf( str, size, format, arg);
-	va_end (arg);
+	rv = vsnprintf (str, size, format, arg_save);
 
 	*string_ptr = str;
 	return (rv);
 }
 
+int
+gf_asprintf (char **string_ptr, const char *format, ...)
+{
+	va_list arg;
+	int     rv = 0;
+
+	va_start (arg, format);
+	rv = gf_vasprintf (string_ptr, format, arg);
+	va_end (arg);
+
+	return rv;
+}
+
 void
 __gf_free (void *free_ptr)
 {
diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h
index 0b467bb..21ff4c8 100644
--- a/libglusterfs/src/mem-pool.h
+++ b/libglusterfs/src/mem-pool.h
@@ -26,6 +26,7 @@ 
 #include <stdlib.h>
 #include <inttypes.h>
 #include <string.h>
+#include <stdarg.h>
 
 
 #define MALLOC(size) malloc(size)
@@ -61,6 +62,9 @@  void *
 __gf_realloc (void *ptr, size_t size);
 
 int
+gf_vasprintf (char **string_ptr, const char *format, va_list arg);
+
+int
 gf_asprintf (char **string_ptr, const char *format, ...);
 
 #define GF_CALLOC(nmemb, size, type) __gf_calloc (nmemb, size, type)