/*
Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#include <fnmatch.h>
#include <sys/wait.h>
#include <dlfcn.h>
#include <utime.h>
#include "xlator.h"
#include "glusterd.h"
#include "defaults.h"
#include "syscall.h"
#include "logging.h"
#include "dict.h"
#include "graph-utils.h"
#include "common-utils.h"
#include "glusterd-store.h"
#include "glusterd-hooks.h"
#include "trie.h"
#include "glusterd-mem-types.h"
#include "cli1-xdr.h"
#include "glusterd-volgen.h"
#include "glusterd-geo-rep.h"
#include "glusterd-utils.h"
#include "glusterd-messages.h"
#include "run.h"
#include "options.h"
#include "glusterd-snapshot-utils.h"
#include "glusterd-svc-mgmt.h"
#include "glusterd-svc-helper.h"
#include "glusterd-snapd-svc-helper.h"
struct gd_validate_reconf_opts {
dict_t *options;
char **op_errstr;
};
extern struct volopt_map_entry glusterd_volopt_map[];
#define RPC_SET_OPT(XL, CLI_OPT, XLATOR_OPT, ERROR_CMD) do { \
char *_value = NULL; \
\
if (dict_get_str (set_dict, CLI_OPT, &_value) == 0) { \
if (xlator_set_option (XL, \
"transport.socket." XLATOR_OPT, _value) != 0) { \
gf_msg ("glusterd", GF_LOG_WARNING, errno, \
GD_MSG_XLATOR_SET_OPT_FAIL, \
"failed to set " XLATOR_OPT); \
ERROR_CMD; \
} \
} \
} while (0 /* CONSTCOND */)
/*********************************************
*
* xlator generation / graph manipulation API
*
*********************************************/
static void
set_graph_errstr (volgen_graph_t *graph, const char *str)
{
if (!graph->errstr)
return;
*graph->errstr = gf_strdup (str);
}
static xlator_t *
xlator_instantiate_va (const char *type, const char *format, va_list arg)
{
xlator_t *xl = NULL;
char *volname = NULL;
int ret = 0;
ret = gf_vasprintf (&volname, format, arg);
if (ret < 0) {
volname = NULL;
goto error;
}
xl = GF_CALLOC (1, sizeof (*xl), gf_common_mt_xlator_t);
if (!xl)
goto error;
ret = xlator_set_type_virtual (xl, type);
if (ret)
goto error;
xl->options = get_new_dict();
if (!xl->options)
goto error;
xl->name = volname;
CDS_INIT_LIST_HEAD (&xl->volume_options);
xl->ctx = THIS->ctx;
return xl;
error:
gf_msg ("glusterd", GF_LOG_ERROR, 0,
GD_MSG_XLATOR_CREATE_FAIL,
"creating xlator of type %s failed",
type);
GF_FREE (volname);
if (xl)
xlator_destroy (xl);
return NULL;
}
static xlator_t *
xlator_instantiate (const char *type, const char *format, ...)
{
va_list arg;
xlator_t *xl;
va_start (arg, format);
xl = xlator_instantiate_va (type, format, arg);
va_end (arg);
return xl;
}
static int
volgen_xlator_link (xlator_t *pxl, xlator_t *cxl)
{
int ret = 0;
ret = glusterfs_xlator_link (pxl, cxl);
if (ret == -1) {
gf_msg ("glusterd", GF_LOG_ERROR, ENOMEM,
GD_MSG_NO_MEMORY,
"Out of memory, cannot link xlators %s <- %s",
pxl->name, cxl->name);
}
return ret;
}
static int
volgen_graph_link (volgen_graph_t *graph, xlator_t *xl)
{
int ret = 0;
/* no need to care about graph->top here */
if (graph->graph.first)
ret = volgen_xlator_link (xl, graph->graph.first);
if (ret == -1) {
gf_msg ("glusterd", GF_LOG_ERROR, 0,
GD_MSG_GRAPH_ENTRY_ADD_FAIL,
"failed to add graph entry %s",
xl->name);
return -1;
}
return 0;
}
static xlator_t *
volgen_graph_add_as (volgen_graph_t *graph, const char *type,
const char *format, ...)
{
va_list arg;
xlator_t *xl = NULL;
va_start (arg, format);
xl = xlator_instantiate_va (type, format, arg);
va_end (arg);
if (!xl)
return NULL;
if (volgen_graph_link (graph, xl)) {
xlator_destroy (xl);
return NULL;
} else
glusterfs_graph_set_first (&graph->graph, xl);
return xl;
}
static xlator_t *
volgen_graph_add_nolink (volgen_graph_t *graph, const char *type,
const char *format, ...)
{
va_list arg;
xlator_t *xl = NULL;
va_start (arg, format);
xl = xlator_instantiate_va (type, format, arg);
va_end (arg);
if (!xl)
return NULL;
glusterfs_graph_set_first (&graph->graph, xl);
return xl;
}
static xlator_t *
volgen_graph_add (volgen_graph_t *graph, char *type, char *volname)
{
char *shorttype = NULL;
shorttype = strrchr (type, '/');
GF_ASSERT (shorttype);
shorttype++;
GF_ASSERT (*shorttype);
return volgen_graph_add_as (graph, type, "%s-%s", volname, shorttype);
}
/* XXX Seems there is no such generic routine?
* Maybe should put to xlator.c ??
*/
static int
xlator_set_option (xlator_t *xl, char *key, char *value)
{
char *dval = NULL;
dval = gf_strdup (value);
if (!dval) {
gf_msg ("glusterd", GF_LOG_ERROR, errno,
GD_MSG_NO_MEMORY,
"failed to set xlator opt: %s[%s] = %s",
xl->name, key, value);
return -1;
}
return dict_set_dynstr (xl->options, key, dval);
}
static int
xlator_get_option (xlator_t *xl, char *key, char **value)
{
GF_ASSERT (xl);
return dict_get_str (xl->options, key, value);
}
static xlator_t *
first_of (volgen_graph_t *graph)
{
return (xlator_t *)graph->graph.first;
}
/**************************
*
* Trie glue
*
*************************/
static int
volopt_selector (int lvl, char **patt, void *param,
int (*optcbk)(char *word, void *param))
{
struct volopt_map_entry *vme = NULL;
char *w = NULL;
int i = 0;
int len = 0;
int ret = 0;
char *dot = NULL;
for (vme = glusterd_volopt_map; vme->key; vme++) {
w = vme->key;
for (i = 0; i < lvl; i++) {
if (patt[i]) {
w = strtail (w, patt[i]);
|