[sheepdog] [PATCH v2 1/3] sheep: generalize the option parsing
Liu Yuan
namei.unix at gmail.com
Fri Aug 23 14:40:52 CEST 2013
Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
include/option.h | 6 ++
lib/option.c | 28 +++++++++
sheep/sheep.c | 176 ++++++++++++++++++++++--------------------------------
3 files changed, 105 insertions(+), 105 deletions(-)
diff --git a/include/option.h b/include/option.h
index 51867fd..3a1eb20 100644
--- a/include/option.h
+++ b/include/option.h
@@ -22,9 +22,15 @@ struct sd_option {
const char *help;
};
+struct option_parser {
+ const char *option;
+ int (*parser)(char *);
+};
+
char *build_short_options(const struct sd_option *opts);
struct option *build_long_options(const struct sd_option *opts);
const char *option_get_help(const struct sd_option *, int);
+int option_parse(char *arg, const char *delim, struct option_parser *parsers);
#define sd_for_each_option(opt, opts) \
for (opt = (opts); opt->name; opt++)
diff --git a/lib/option.c b/lib/option.c
index c4b2557..39a4c52 100644
--- a/lib/option.c
+++ b/lib/option.c
@@ -10,8 +10,11 @@
*/
#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
#include "option.h"
+#include "logger.h"
char *build_short_options(const struct sd_option *sd_opts)
{
@@ -57,3 +60,28 @@ const char *option_get_help(const struct sd_option *sd_opts, int ch)
}
return NULL;
}
+
+int option_parse(char *arg, const char *delim, struct option_parser *parsers)
+{
+ char *savep, *opt;
+ struct option_parser *iter = NULL;
+
+ opt = strtok_r(arg, delim, &savep);
+ do {
+ for (iter = parsers; iter->option; iter++) {
+ int len = strlen(iter->option);
+
+ if (!strncmp(iter->option, opt, len)) {
+ if (iter->parser(opt + len) < 0)
+ return -1;
+ break;
+ }
+ }
+ if (!iter->option) {
+ sd_err("invalid option %s", opt);
+ return -1;
+ }
+ } while ((opt = strtok_r(NULL, delim, &savep)));
+
+ return 0;
+}
diff --git a/sheep/sheep.c b/sheep/sheep.c
index 90c35f9..e9c7eb5 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -258,146 +258,100 @@ static void crash_handler(int signo)
static struct system_info __sys;
struct system_info *sys = &__sys;
-static void parse_arg(char *arg, const char *delim, void (*fn)(char *))
+static int cache_size_parser(char *s)
{
- char *savep, *s;
-
- s = strtok_r(arg, delim, &savep);
- do {
- fn(s);
- } while ((s = strtok_r(NULL, delim, &savep)));
-}
-
-static void object_cache_size_set(char *s)
-{
- const char *header = "size=";
- int len = strlen(header);
- char *size, *p;
- uint64_t cache_size;
const uint32_t max_cache_size = UINT32_MAX;
+ uint64_t cache_size;
+ char *p;
- assert(!strncmp(s, header, len));
-
- size = s + len;
- cache_size = strtoull(size, &p, 10);
- if (size == p || max_cache_size < cache_size)
+ cache_size = strtoull(s, &p, 10);
+ if (s == p || max_cache_size < cache_size)
goto err;
sys->object_cache_size = cache_size;
- return;
+ return 0;
err:
sd_err("Invalid object cache option '%s': size must be an integer "
"between 1 and %" PRIu32 " inclusive", s, max_cache_size);
- exit(1);
+ return -1;
}
-static void object_cache_directio_set(char *s)
+static int cache_directio_parser(char *s)
{
- assert(!strcmp(s, "directio"));
sys->object_cache_directio = true;
+ return 0;
}
static char ocpath[PATH_MAX];
-static void object_cache_dir_set(char *s)
-{
- char *p = s;
- p = p + strlen("dir=");
- snprintf(ocpath, sizeof(ocpath), "%s", p);
+static int cache_dir_parser(char *s)
+{
+ snprintf(ocpath, sizeof(ocpath), "%s", s);
+ return 0;
}
-static void _object_cache_set(char *s)
-{
- int i;
-
- struct object_cache_arg {
- const char *name;
- void (*set)(char *);
- };
-
- struct object_cache_arg object_cache_args[] = {
- { "size=", object_cache_size_set },
- { "directio", object_cache_directio_set },
- { "dir=", object_cache_dir_set },
- { NULL, NULL },
- };
-
- for (i = 0; object_cache_args[i].name; i++) {
- const char *n = object_cache_args[i].name;
-
- if (!strncmp(s, n, strlen(n))) {
- object_cache_args[i].set(s);
- return;
- }
- }
+static struct option_parser cache_parsers[] = {
+ { "size=", cache_size_parser },
+ { "directio", cache_directio_parser },
+ { "dir=", cache_dir_parser },
+ { NULL, NULL },
+};
- sd_err("invalid object cache arg: %s", s);
- exit(1);
+static char *io_addr, *io_pt;
+static int ionic_host_parser(char *s)
+{
+ io_addr = s;
+ return 0;
}
-static void object_cache_set(char *arg)
+static int ionic_port_parser(char *s)
{
- sys->enable_object_cache = true;
- sys->object_cache_size = 0;
-
- parse_arg(arg, ",", _object_cache_set);
-
- if (sys->object_cache_size == 0) {
- sd_err("object cache size is not set");
- exit(1);
- }
+ io_pt = s;
+ return 0;
}
+static struct option_parser ionic_parsers[] = {
+ { "host=", ionic_host_parser },
+ { "port=", ionic_port_parser },
+ { NULL, NULL },
+};
+
static char jpath[PATH_MAX];
static bool jskip;
static ssize_t jsize;
#define MIN_JOURNAL_SIZE (64) /* 64M */
-static void init_journal_arg(char *arg)
+static int journal_dir_parser(char *s)
{
- const char *d = "dir=", *sz = "size=", *sp = "skip";
- int dl = strlen(d), szl = strlen(sz), spl = strlen(sp);
-
- if (!strncmp(d, arg, dl)) {
- arg += dl;
- snprintf(jpath, sizeof(jpath), "%s", arg);
- } else if (!strncmp(sz, arg, szl)) {
- arg += szl;
- jsize = strtoll(arg, NULL, 10);
- if (jsize < MIN_JOURNAL_SIZE || jsize == LLONG_MAX) {
- sd_err("invalid size %s, must be bigger than %u(M)",
- arg,
- MIN_JOURNAL_SIZE);
- exit(1);
- }
- } else if (!strncmp(sp, arg, spl)) {
- jskip = true;
- } else {
- sd_err("invalid paramters %s", arg);
- exit(1);
- }
+ snprintf(jpath, sizeof(jpath), "%s", s);
+ return 0;
}
-static char *io_addr, *io_pt;
-static void init_io_arg(char *arg)
+static int journal_size_parser(char *s)
{
- const char *host = "host=", *port = "port=";
- int hl = strlen(host), pl = strlen(port);
-
- if (!strncmp(host, arg, hl)) {
- arg += hl;
- io_addr = arg;
- } else if (!strncmp(port, arg, pl)) {
- arg += hl;
- io_pt = arg;
- } else {
- sd_err("invalid paramters %s. Use '-i host=a.b.c.d,port=xxx'",
- arg);
- exit(1);
+ jsize = strtoll(s, NULL, 10);
+ if (jsize < MIN_JOURNAL_SIZE || jsize == LLONG_MAX) {
+ sd_err("invalid size %s, must be bigger than %u(M)",
+ s, MIN_JOURNAL_SIZE);
+ return -1;
}
+ return 0;
}
+static int journal_skip_parser(char *s)
+{
+ jskip = true;
+ return 0;
+}
+
+static struct option_parser journal_parsers[] = {
+ { "dir=", journal_dir_parser },
+ { "size=", journal_size_parser },
+ { "skip", journal_skip_parser },
+ { NULL, NULL },
+};
+
static size_t get_nr_nodes(void)
{
struct vnode_info *vinfo;
@@ -672,10 +626,21 @@ int main(int argc, char **argv)
sys->cdrv_option = get_cdrv_option(sys->cdrv, optarg);
break;
case 'w':
- object_cache_set(optarg);
+ sys->enable_object_cache = true;
+ sys->object_cache_size = 0;
+
+ if (option_parse(optarg, ",", cache_parsers) < 0)
+ exit(1);
+
+ if (sys->object_cache_size == 0) {
+ sd_err("object cache size is not set");
+ exit(1);
+ }
break;
case 'i':
- parse_arg(optarg, ",", init_io_arg);
+ if (option_parse(optarg, ",", ionic_parsers) < 0)
+ exit(1);
+
if (!str_to_addr(io_addr, sys->this_node.nid.io_addr)) {
sd_err("Bad addr: '%s'", io_addr);
exit(1);
@@ -690,7 +655,8 @@ int main(int argc, char **argv)
break;
case 'j':
uatomic_set_true(&sys->use_journal);
- parse_arg(optarg, ",", init_journal_arg);
+ if (option_parse(optarg, ",", journal_parsers) < 0)
+ exit(1);
if (!jsize) {
sd_err("you must specify size for journal");
exit(1);
--
1.7.9.5
More information about the sheepdog
mailing list