diff options
author | Anand Avati <avati@gluster.com> | 2010-06-07 12:37:34 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2010-06-07 11:58:50 -0700 |
commit | 79241696fbdebe2583298f12cbaee068ce60c655 (patch) | |
tree | 42e60d351e328fa34f17242c6c3359a8c01e8fa3 /libglusterfs/src/graph.c | |
parent | c4ebd25a176d6d51d702b1009e261c3c27237a48 (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.c | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c new file mode 100644 index 00000000000..a59b427bffe --- /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; +} + + |