[ltt-dev] [PATCH] lttctl: Rewrite -o option processing
Mathieu Desnoyers
compudj at krystal.dyndns.org
Sat Jan 3 08:59:02 EST 2009
* Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
> Hi, Mathieu
>
> This patch rewrites -o option processing. It makes use of a hierarchical o_option
> struct in the new implementation. IMHO, this design provides a better scalability,
> and easy to expand. The original implementation uses a pretty big static array to
> store options, it wastes too much memory(though it's in user space). This problem is
> also addressed by using a dynamic link-list.
>
Merged into ltt-control 0.63. Thanks !
Mathieu
> Signed-off-by: Gui Jianfeng <guijianfeng at cn.fujitsu.com>
> ---
> lttctl/lttctl.c | 352 ++++++++++++++++++++++++-------------------------------
> 1 files changed, 154 insertions(+), 198 deletions(-)
>
> diff --git a/lttctl/lttctl.c b/lttctl/lttctl.c
> index 4620983..c1a49cd 100644
> --- a/lttctl/lttctl.c
> +++ b/lttctl/lttctl.c
> @@ -6,6 +6,10 @@
> *
> * Copyright 2005 -
> * Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
> + *
> + * Copyright 2008 FUJITSU
> + * Zhao Lei <zhaolei at cn.fujitsu.com>
> + * Gui Jianfeng <guijianfeng at cn.fujitsu.com>
> */
>
> #ifdef HAVE_CONFIG_H
> @@ -27,35 +31,34 @@
> #define OPT_NAMELEN (256)
> #define OPT_VALSTRINGLEN (256)
>
> -enum lttcrl_option_type {
> - option_type_unknown,
> - option_type_string,
> - option_type_int,
> - option_type_uint,
> - option_type_positive,
> - option_type_bool,
> +enum opt_type {
> + CHANNEL,
> +};
> +
> +struct channel_option {
> + char chan_name[OPT_NAMELEN];
> + int enable;
> + int overwrite;
> + int bufnum;
> + int bufsize;
> };
>
> struct lttctl_option {
> - char name1[OPT_NAMELEN];
> - char name2[OPT_NAMELEN];
> - char name3[OPT_NAMELEN];
> union {
> - char v_string[OPT_VALSTRINGLEN];
> - int v_int;
> - unsigned int v_uint;
> - int v_bool:1;
> - } value;
> + struct channel_option chan_opt;
> + } opt_mode;
> + enum opt_type type;
> + struct lttctl_option *next;
> };
>
> +struct lttctl_option *opt_head, *last_opt;
> +
> static int opt_create;
> static int opt_destroy;
> static int opt_start;
> static int opt_pause;
> static int opt_help;
> static const char *opt_transport;
> -static struct lttctl_option opt_options[OPT_MAX];
> -static unsigned int opt_option_n;
> static const char *opt_write;
> static int opt_append;
> static unsigned int opt_dump_threads;
> @@ -214,93 +217,103 @@ static int separate_opt(const char *name, char *name1, char *name2, char *name3)
> return 0;
> }
>
> -/*
> - * get option's type by its name,
> - * can also be used to check is option exists
> - * (return option_type_unknown when not exist)
> - */
> -static enum lttcrl_option_type opt_type(const char *name1, const char *name2,
> - const char *name3)
> +static void init_channel_opt(struct channel_option *opt, char *opt_name)
> {
> - if (!name1 || !name2 || !name3)
> - return option_type_unknown;
> -
> - if (strlen(name1) >= OPT_NAMELEN
> - || strlen(name2) >= OPT_NAMELEN
> - || strlen(name3) >= OPT_NAMELEN)
> - return option_type_unknown;
> -
> - if (strcmp(name1, "channel") == 0) {
> - /* Option is channel class */
> - if (strcmp(name3, "enable") == 0)
> - return option_type_bool;
> - if (strcmp(name3, "overwrite") == 0)
> - return option_type_bool;
> - if (strcmp(name3, "bufnum") == 0)
> - return option_type_uint;
> - if (strcmp(name3, "bufsize") == 0)
> - return option_type_uint;
> - return option_type_unknown;
> + if (opt && opt_name) {
> + opt->enable = -1;
> + opt->overwrite = -1;
> + opt->bufnum = -1;
> + opt->bufsize = -1;
> + strcpy(opt->chan_name, opt_name);
> }
> -
> - /*
> - * Now we only support channel options
> - * other option class' will used in future
> - */
> -
> - return option_type_unknown;
> }
>
> -static struct lttctl_option *find_opt(const char *name1, const char *name2,
> - const char *name3)
> +static struct lttctl_option *find_insert_channel_opt(char *opt_name)
> {
> - int i;
> + struct lttctl_option *iter, *new_opt;
>
> - if (!name1 || !name2 || !name3)
> - return NULL;
> + if (!opt_head) {
> + opt_head = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
> + init_channel_opt(&opt_head->opt_mode.chan_opt, opt_name);
> + opt_head->type = CHANNEL;
> + opt_head->next = NULL;
> + last_opt = opt_head;
> + return opt_head;
> + }
>
> - for (i = 0; i < opt_option_n; i++) {
> - if (strcmp(opt_options[i].name1, name1) == 0
> - && strcmp(opt_options[i].name2, name2) == 0
> - && strcmp(opt_options[i].name3, name3) == 0)
> - return opt_options + i;
> + for (iter = opt_head; iter; iter = iter->next) {
> + if (iter->type != CHANNEL)
> + continue;
> + if (!strcmp(iter->opt_mode.chan_opt.chan_name, opt_name))
> + return iter;
> }
>
> - return NULL;
> + new_opt = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
> + init_channel_opt(&new_opt->opt_mode.chan_opt, opt_name);
> + new_opt->type = CHANNEL;
> + new_opt->next = NULL;
> + last_opt->next = new_opt;
> + last_opt = new_opt;
> + return new_opt;
> }
>
> -static struct lttctl_option *get_opt(const char *name1, const char *name2,
> - const char *name3)
> +int set_channel_opt(struct channel_option *opt, char *opt_name, char *opt_valstr)
> {
> - struct lttctl_option *opt;
> + int opt_val, ret;
>
> - if (!name1 || !name2 || !name3)
> - return NULL;
> + if (!strcmp("enable", opt_name)) {
> + if (opt_valstr[1] != 0) {
> + return -EINVAL;
> + }
> + if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
> + || opt_valstr[0] == '1')
> + opt_val = 1;
> + else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
> + || opt_valstr[0] == '0')
> + opt_val = 0;
> + else {
> + return -EINVAL;
> + }
>
> - opt = find_opt(name1, name2, name3);
> - if (opt)
> - return opt;
> + opt->enable = opt_val;
> + return 0;
> + } else if (!strcmp("overwrite", opt_name)) {
> + if (opt_valstr[1] != 0) {
> + return -EINVAL;
> + }
> + if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
> + || opt_valstr[0] == '1')
> + opt_val = 1;
> + else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
> + || opt_valstr[0] == '0')
> + opt_val = 0;
> + else {
> + return -EINVAL;
> + }
>
> - if (opt_option_n >= OPT_MAX) {
> - fprintf(stderr, "Option number out of range\n");
> - return NULL;
> - }
> + opt->overwrite = opt_val;
> + return 0;
>
> - if (strlen(name1) >= OPT_NAMELEN
> - || strlen(name2) >= OPT_NAMELEN
> - || strlen(name3) >= OPT_NAMELEN) {
> - fprintf(stderr, "Option name too long: %s.%s.%s\n",
> - name1, name2, name3);
> - return NULL;
> + } else if (!strcmp("bufnum", opt_name)) {
> + ret = sscanf(opt_valstr, "%d", &opt_val);
> + if (ret != 1 || opt_val < 0) {
> + return -EINVAL;
> + }
> +
> + opt->bufnum = opt_val;
> + return 0;
> + } else if (!strcmp("bufsize", opt_name)) {
> + ret = sscanf(opt_valstr, "%d", &opt_val);
> + if (ret != 1 || opt_val < 0) {
> + return -EINVAL;
> + }
> +
> + opt->bufsize = opt_val;
> + return 0;
> + } else {
> + return -EINVAL;
> }
>
> - opt = &opt_options[opt_option_n];
> - strcpy(opt->name1, name1);
> - strcpy(opt->name2, name2);
> - strcpy(opt->name3, name3);
> - opt_option_n++;
> -
> - return opt;
> }
>
> static int parst_opt(const char *optarg)
> @@ -314,10 +327,10 @@ static int parst_opt(const char *optarg)
> char name2[OPT_NAMELEN];
> char name3[OPT_NAMELEN];
>
> - enum lttcrl_option_type opttype;
> int opt_intval;
> + int opt_val;
> unsigned int opt_uintval;
> - struct lttctl_option *newopt;
> + struct lttctl_option *opt;
>
> if (!optarg) {
> fprintf(stderr, "Option empty\n");
> @@ -348,84 +361,23 @@ static int parst_opt(const char *optarg)
> /* separate option name into 3 fields */
> ret = separate_opt(opt_name, name1, name2, name3);
> if (ret != 0) {
> - fprintf(stderr, "Option name error: %s\n", optarg);
> + fprintf(stderr, "Option name error1: %s\n", optarg);
> return -EINVAL;
> }
> -
> - /*
> - * check and add option
> - */
> - opttype = opt_type(name1, name2, name3);
> - switch (opttype) {
> - case option_type_unknown:
> - fprintf(stderr, "Option not supported: %s\n", optarg);
> - return -EINVAL;
> - case option_type_string:
> - newopt = get_opt(name1, name2, name3);
> - if (!newopt)
> - return -EINVAL;
> - strcpy(newopt->value.v_string, opt_valstr);
> - return 0;
> - case option_type_int:
> - ret = sscanf(opt_valstr, "%d", &opt_intval);
> - if (ret != 1) {
> - fprintf(stderr, "Option format error: %s\n", optarg);
> - return -EINVAL;
> +
> + if (!strcmp("channel", name1)) {
> + opt = find_insert_channel_opt(name2);
> + if ((ret = set_channel_opt(&opt->opt_mode.chan_opt,
> + name3, opt_valstr) != 0)) {
> + fprintf(stderr, "Option name error2: %s\n", optarg);
> + return ret;
> }
> - newopt = get_opt(name1, name2, name3);
> - if (!newopt)
> - return -EINVAL;
> - newopt->value.v_int = opt_intval;
> - return 0;
> - case option_type_uint:
> - ret = sscanf(opt_valstr, "%u", &opt_uintval);
> - if (ret != 1) {
> - fprintf(stderr, "Option format error: %s\n", optarg);
> - return -EINVAL;
> - }
> - newopt = get_opt(name1, name2, name3);
> - if (!newopt)
> - return -EINVAL;
> - newopt->value.v_uint = opt_uintval;
> - return 0;
> - case option_type_positive:
> - ret = sscanf(opt_valstr, "%u", &opt_uintval);
> - if (ret != 1 || opt_uintval == 0) {
> - fprintf(stderr, "Option format error: %s\n", optarg);
> - return -EINVAL;
> - }
> - newopt = get_opt(name1, name2, name3);
> - if (!newopt)
> - return -EINVAL;
> - newopt->value.v_uint = opt_uintval;
> - return 0;
> - case option_type_bool:
> - if (opt_valstr[1] != 0) {
> - fprintf(stderr, "Option format error: %s\n", optarg);
> - return -EINVAL;
> - }
> - if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
> - || opt_valstr[0] == '1')
> - opt_intval = 1;
> - else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
> - || opt_valstr[0] == '0')
> - opt_intval = 0;
> - else {
> - fprintf(stderr, "Option format error: %s\n", optarg);
> - return -EINVAL;
> - }
> -
> - newopt = get_opt(name1, name2, name3);
> - if (!newopt)
> - return -EINVAL;
> - newopt->value.v_bool = opt_intval;
> - return 0;
> - default:
> - fprintf(stderr, "Internal error on opt %s\n", optarg);
> + } else {
> + fprintf(stderr, "Option name error3: %s\n", optarg);
> return -EINVAL;
> }
> -
> - return 0; /* should not run to here */
> +
> + return 0;
> }
>
> /* parse_arguments
> @@ -438,7 +390,7 @@ static int parst_opt(const char *optarg)
> static int parse_arguments(int argc, char **argv)
> {
> int ret = 0;
> -
> +
> static struct option longopts[] = {
> {"create", no_argument, NULL, 'c'},
> {"destroy", no_argument, NULL, 'd'},
> @@ -654,7 +606,7 @@ static int parse_arguments(int argc, char **argv)
>
> return 0;
> }
> -
> +
> static void show_info(void)
> {
> printf("Linux Trace Toolkit Trace Control " VERSION"\n");
> @@ -665,50 +617,54 @@ static void show_info(void)
> }
> }
>
> +static int lttctl_channel_setup(struct channel_option *opt)
> +{
> + int ret;
> +
> + if (opt->enable != -1) {
> + if ((ret = lttctl_set_channel_enable(opt_tracename,
> + opt->chan_name,
> + opt->enable)) != 0)
> + return ret;
> + }
> + if (opt->overwrite != -1) {
> + if ((ret = lttctl_set_channel_overwrite(opt_tracename,
> + opt->chan_name,
> + opt->overwrite)) != 0)
> + return ret;
> + }
> + if (opt->bufnum != -1) {
> + if ((ret = lttctl_set_channel_subbuf_num(opt_tracename,
> + opt->chan_name,
> + opt->bufnum)) != 0)
> + return ret;
> + }
> + if (opt->bufsize != -1) {
> + if ((ret = lttctl_set_channel_subbuf_size(opt_tracename,
> + opt->chan_name,
> + opt->bufsize)) != 0)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> static int lttctl_create_trace(void)
> {
> int ret;
> int i;
> + struct lttctl_option *opt;
>
> ret = lttctl_setup_trace(opt_tracename);
> if (ret)
> goto setup_trace_fail;
>
> - for (i = 0; i < opt_option_n; i++) {
> - if (strcmp(opt_options[i].name1, "channel") != 0)
> + for (opt = opt_head; opt; opt = opt->next) {
> + if (opt->type != CHANNEL)
> continue;
> -
> - if (strcmp(opt_options[i].name3, "enable") == 0) {
> - ret = lttctl_set_channel_enable(opt_tracename,
> - opt_options[i].name2,
> - opt_options[i].value.v_bool);
> - if (ret)
> - goto set_option_fail;
> - }
> -
> - if (strcmp(opt_options[i].name3, "overwrite") == 0) {
> - ret = lttctl_set_channel_overwrite(opt_tracename,
> - opt_options[i].name2,
> - opt_options[i].value.v_bool);
> - if (ret)
> - goto set_option_fail;
> - }
> -
> - if (strcmp(opt_options[i].name3, "bufnum") == 0) {
> - ret = lttctl_set_channel_subbuf_num(opt_tracename,
> - opt_options[i].name2,
> - opt_options[i].value.v_uint);
> - if (ret)
> - goto set_option_fail;
> - }
> -
> - if (strcmp(opt_options[i].name3, "bufsize") == 0) {
> - ret = lttctl_set_channel_subbuf_size(opt_tracename,
> - opt_options[i].name2,
> - opt_options[i].value.v_uint);
> - if (ret)
> - goto set_option_fail;
> - }
> + ret = lttctl_channel_setup(&opt->opt_mode.chan_opt);
> + if (ret)
> + goto set_option_fail;;
> }
>
> ret = lttctl_set_trans(opt_tracename, opt_transport);
> --
> 1.5.4.rc3
>
>
>
> _______________________________________________
> ltt-dev mailing list
> ltt-dev at lists.casi.polymtl.ca
> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
>
--
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
More information about the lttng-dev
mailing list