diff options
Diffstat (limited to 'libglusterfs/src/graph-print.c')
| -rw-r--r-- | libglusterfs/src/graph-print.c | 200 | 
1 files changed, 200 insertions, 0 deletions
diff --git a/libglusterfs/src/graph-print.c b/libglusterfs/src/graph-print.c new file mode 100644 index 00000000000..a6c20c735ad --- /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; +}  | 
