[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