summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/graph.c
diff options
context:
space:
mode:
authorAnand Avati <avati@gluster.com>2010-06-07 12:37:34 +0000
committerAnand V. Avati <avati@dev.gluster.com>2010-06-07 11:58:50 -0700
commit79241696fbdebe2583298f12cbaee068ce60c655 (patch)
tree42e60d351e328fa34f17242c6c3359a8c01e8fa3 /libglusterfs/src/graph.c
parentc4ebd25a176d6d51d702b1009e261c3c27237a48 (diff)
dynamic volume changes for graph replacement
Signed-off-by: Anand V. Avati <avati@blackhole.gluster.com> Signed-off-by: Anand V. Avati <avati@dev.gluster.com> BUG: 971 (dynamic volume management) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=971
Diffstat (limited to 'libglusterfs/src/graph.c')
-rw-r--r--libglusterfs/src/graph.c499
1 files changed, 499 insertions, 0 deletions
diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c
new file mode 100644
index 000000000..a59b427bf
--- /dev/null
+++ b/libglusterfs/src/graph.c
@@ -0,0 +1,499 @@
+/*
+ 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 "xlator.h"
+#include <dlfcn.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include "defaults.h"
+
+
+
+
+#if 0
+static void
+_gf_dump_details (int argc, char **argv)
+{
+ extern FILE *gf_log_logfile;
+ int i = 0;
+ char timestr[256];
+ time_t utime = 0;
+ struct tm *tm = NULL;
+ pid_t mypid = 0;
+ struct utsname uname_buf = {{0, }, };
+ int uname_ret = -1;
+
+ utime = time (NULL);
+ tm = localtime (&utime);
+ mypid = getpid ();
+ uname_ret = uname (&uname_buf);
+
+ /* Which git? What time? */
+ strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm);
+ fprintf (gf_log_logfile,
+ "========================================"
+ "========================================\n");
+ fprintf (gf_log_logfile, "Version : %s %s built on %s %s\n",
+ PACKAGE_NAME, PACKAGE_VERSION, __DATE__, __TIME__);
+ fprintf (gf_log_logfile, "git: %s\n",
+ GLUSTERFS_REPOSITORY_REVISION);
+ fprintf (gf_log_logfile, "Starting Time: %s\n", timestr);
+ fprintf (gf_log_logfile, "Command line : ");
+ for (i = 0; i < argc; i++) {
+ fprintf (gf_log_logfile, "%s ", argv[i]);
+ }
+
+ fprintf (gf_log_logfile, "\nPID : %d\n", mypid);
+
+ if (uname_ret == 0) {
+ fprintf (gf_log_logfile, "System name : %s\n",
+ uname_buf.sysname);
+ fprintf (gf_log_logfile, "Nodename : %s\n",
+ uname_buf.nodename);
+ fprintf (gf_log_logfile, "Kernel Release : %s\n",
+ uname_buf.release);
+ fprintf (gf_log_logfile, "Hardware Identifier: %s\n",
+ uname_buf.machine);
+ }
+
+
+ fprintf (gf_log_logfile, "\n");
+ fflush (gf_log_logfile);
+}
+#endif
+
+
+static int
+_log_if_option_is_invalid (xlator_t *xl, data_pair_t *pair)
+{
+ volume_opt_list_t *vol_opt = NULL;
+ volume_option_t *opt = NULL;
+ int i = 0;
+ int index = 0;
+ int found = 0;
+
+ /* Get the first volume_option */
+ list_for_each_entry (vol_opt, &xl->volume_options, list) {
+ /* Warn for extra option */
+ if (!vol_opt->given_opt)
+ break;
+
+ opt = vol_opt->given_opt;
+ for (index = 0;
+ ((index < ZR_OPTION_MAX_ARRAY_SIZE) &&
+ (opt[index].key && opt[index].key[0])); index++)
+ for (i = 0; (i < ZR_VOLUME_MAX_NUM_KEY) &&
+ opt[index].key[i]; i++) {
+ if (fnmatch (opt[index].key[i],
+ pair->key,
+ FNM_NOESCAPE) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ gf_log (xl->name, GF_LOG_WARNING,
+ "option '%s' is not recognized",
+ pair->key);
+ }
+ return 0;
+}
+
+
+int
+glusterfs_graph_insert (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx,
+ const char *type, const char *name)
+{
+ xlator_t *ixl = NULL;
+ xlator_list_t *xlchild = NULL;
+ xlator_list_t *xlparent = NULL;
+
+ ixl = GF_CALLOC (1, sizeof (*ixl), gf_common_mt_xlator_t);
+ if (!ixl)
+ return -1;
+
+ ixl->ctx = ctx;
+ ixl->graph = graph;
+ ixl->options = get_new_dict ();
+ if (!ixl->options)
+ goto err;
+
+ ixl->name = gf_strdup (name);
+ if (!ixl->name)
+ goto err;
+
+ if (xlator_set_type (ixl, type) == -1) {
+ gf_log ("glusterfs", GF_LOG_ERROR,
+ "%s (%s) initialization failed",
+ name, type);
+ return -1;
+ }
+
+
+ /* children */
+ xlchild = GF_CALLOC (sizeof (*xlchild), 1, gf_common_mt_xlator_list_t);
+ if (!xlchild)
+ goto err;
+ xlchild->xlator = graph->top;
+ ixl->children = xlchild; xlchild = NULL;
+
+
+ /* parent */
+ xlparent = GF_CALLOC (sizeof (*xlparent), 1,
+ gf_common_mt_xlator_list_t);
+ if (!xlparent)
+ goto err;
+ xlparent->xlator = ixl;
+
+ ixl->next = graph->first;
+ graph->first = ixl;
+
+ xlparent->next = ((xlator_t *)graph->top)->parents;
+ ((xlator_t *)graph->top)->parents = xlparent;
+
+ graph->top = ixl;
+
+ graph->xl_count++;
+
+ return 0;
+err:
+ xlator_destroy (ixl);
+ return -1;
+}
+
+
+int
+glusterfs_graph_readonly (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
+{
+ int ret = 0;
+ cmd_args_t *cmd_args = NULL;
+
+ cmd_args = &ctx->cmd_args;
+
+ if (!cmd_args->read_only)
+ return 0;
+
+ ret = glusterfs_graph_insert (graph, ctx, "features/read-only",
+ "readonly-autoload");
+ return ret;
+}
+
+
+int
+glusterfs_graph_mac_compat (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
+{
+ int ret = 0;
+ cmd_args_t *cmd_args = NULL;
+
+ cmd_args = &ctx->cmd_args;
+
+#ifdef GF_DARWIN_HOST_OS
+ if (!cmd_args->mac_compat)
+ return 0;
+
+ ret = glusterfs_graph_insert (graph, ctx, ZR_XLATOR_MAC_COMPAT,
+ "mac-compat-autoload");
+#endif
+
+ return ret;
+}
+
+
+static void
+gf_add_cmdline_options (glusterfs_graph_t *graph, cmd_args_t *cmd_args)
+{
+ int ret = 0;
+ xlator_t *trav = NULL;
+ xlator_cmdline_option_t *cmd_option = NULL;
+
+ trav = graph->first;
+
+ while (trav) {
+ list_for_each_entry (cmd_option,
+ &cmd_args->xlator_options, cmd_args) {
+ if (!fnmatch (cmd_option->volume,
+ trav->name, FNM_NOESCAPE)) {
+ ret = dict_set_str (trav->options,
+ cmd_option->key,
+ cmd_option->value);
+ if (ret == 0) {
+ gf_log (trav->name, GF_LOG_WARNING,
+ "adding option '%s' for "
+ "volume '%s' with value '%s'",
+ cmd_option->key, trav->name,
+ cmd_option->value);
+ } else {
+ gf_log (trav->name, GF_LOG_WARNING,
+ "adding option '%s' for "
+ "volume '%s' failed: %s",
+ cmd_option->key, trav->name,
+ strerror (-ret));
+ }
+ }
+ }
+ trav = trav->next;
+ }
+}
+
+
+int
+glusterfs_graph_validate_options (glusterfs_graph_t *graph)
+{
+ volume_opt_list_t *vol_opt = NULL;
+ xlator_t *trav = NULL;
+ int ret = -1;
+
+ trav = graph->first;
+
+ while (trav) {
+ if (list_empty (&trav->volume_options))
+ continue;
+
+ vol_opt = list_entry (trav->volume_options.next,
+ volume_opt_list_t, list);
+
+ ret = validate_xlator_volume_options (trav,
+ vol_opt->given_opt);
+ if (ret) {
+ gf_log (trav->name, GF_LOG_ERROR,
+ "validating translator failed");
+ return ret;
+ }
+ trav = trav->next;
+ }
+
+ return 0;
+}
+
+
+int
+glusterfs_graph_init (glusterfs_graph_t *graph)
+{
+ xlator_t *trav = NULL;
+ int ret = -1;
+
+ trav = graph->first;
+
+ while (trav) {
+ ret = xlator_init (trav);
+ if (ret) {
+ gf_log (trav->name, GF_LOG_ERROR,
+ "initializing translator failed");
+ return ret;
+ }
+ trav = trav->next;
+ }
+
+ return 0;
+}
+
+
+int
+glusterfs_graph_unknown_options (glusterfs_graph_t *graph)
+{
+ data_pair_t *pair = NULL;
+ xlator_t *trav = NULL;
+
+ trav = graph->first;
+
+ /* Validate again phase */
+ while (trav) {
+ pair = trav->options->members_list;
+ while (pair) {
+ _log_if_option_is_invalid (trav, pair);
+ pair = pair->next;
+ }
+ trav = trav->next;
+ }
+
+ return 0;
+}
+
+
+void
+fill_uuid (char *uuid, int size)
+{
+ char hostname[256] = {0,};
+ struct timeval tv = {0,};
+ struct tm now = {0, };
+ char now_str[32];
+
+ if (gettimeofday (&tv, NULL) == -1) {
+ gf_log ("graph", GF_LOG_ERROR,
+ "gettimeofday: failed %s",
+ strerror (errno));
+ }
+
+ if (gethostname (hostname, 256) == -1) {
+ gf_log ("graph", GF_LOG_ERROR,
+ "gethostname: failed %s",
+ strerror (errno));
+ }
+
+ localtime_r (&tv.tv_sec, &now);
+ strftime (now_str, 32, "%Y/%m/%d-%H:%M:%S", &now);
+ snprintf (uuid, size, "%s-%d-%s:%ld",
+ hostname, getpid(), now_str, tv.tv_usec);
+
+ return;
+}
+
+
+int
+glusterfs_graph_settop (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
+{
+ const char *volume_name = NULL;
+ xlator_t *trav = NULL;
+
+ volume_name = ctx->cmd_args.volume_name;
+
+ if (!volume_name) {
+ graph->top = graph->first;
+ return 0;
+ }
+
+ for (trav = graph->first; trav; trav = trav->next) {
+ if (strcmp (trav->name, volume_name) == 0) {
+ graph->top = trav;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+int
+glusterfs_graph_parent_up (glusterfs_graph_t *graph)
+{
+ xlator_t *trav = NULL;
+ int ret = -1;
+
+ trav = graph->first;
+
+ while (trav) {
+ if (!xlator_has_parent (trav)) {
+ ret = xlator_notify (trav, GF_EVENT_PARENT_UP, trav);
+ }
+
+ if (ret)
+ break;
+
+ trav = trav->next;
+ }
+
+ return ret;
+}
+
+
+int
+glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
+{
+ xlator_t *trav = NULL;
+ int ret = 0;
+
+ /* XXX: CHECKSUM */
+
+ /* XXX: attach to -n volname */
+ ret = glusterfs_graph_settop (graph, ctx);
+ if (ret)
+ return -1;
+
+ /* XXX: RO VOLUME */
+ ret = glusterfs_graph_readonly (graph, ctx);
+ if (ret)
+ return -1;
+
+ /* XXX: MAC COMPAT */
+ ret = glusterfs_graph_mac_compat (graph, ctx);
+ if (ret)
+ return -1;
+
+ /* XXX: this->ctx setting */
+ for (trav = graph->first; trav; trav = trav->next) {
+ trav->ctx = ctx;
+ }
+
+ /* XXX: DOB setting */
+ gettimeofday (&graph->dob, NULL);
+
+ fill_uuid (graph->graph_uuid, 128);
+
+ /* XXX: --xlator-option additions */
+ gf_add_cmdline_options (graph, &ctx->cmd_args);
+
+
+ return 0;
+}
+
+
+int
+glusterfs_graph_activate (glusterfs_ctx_t *ctx, glusterfs_graph_t *graph)
+{
+ int ret = 0;
+
+ /* XXX: all xlator options validation */
+ ret = glusterfs_graph_validate_options (graph);
+ if (ret)
+ return ret;
+
+ /* XXX: perform init () */
+ ret = glusterfs_graph_init (graph);
+ if (ret)
+ return ret;
+
+ ret = glusterfs_graph_unknown_options (graph);
+ if (ret)
+ return ret;
+
+ /* XXX: log full graph (_gf_dump_details) */
+
+ list_add (&graph->list, &ctx->graphs);
+ ctx->active = graph;
+
+ /* XXX: attach to master and set active pointer */
+ if (ctx->master)
+ ret = xlator_notify (ctx->master, GF_EVENT_GRAPH_NEW, graph);
+ if (ret)
+ return ret;
+
+ /* XXX: perform parent up */
+ ret = glusterfs_graph_parent_up (graph);
+ if (ret)
+ return ret;
+
+
+ return 0;
+}
+
+
+int
+glusterfs_graph_destroy (glusterfs_graph_t *graph)
+{
+ return 0;
+}
+
+