perf config: Introduce perf_config_set class

This infrastructure code was designed for upcoming features of
'perf config'.

That collect config key-value pairs from user and system config files
(i.e. user wide ~/.perfconfig and system wide $(sysconfdir)/perfconfig)
to manage perf's configs.

Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1460620401-23430-2-git-send-email-treeze.taeung@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Taeung Song 2016-04-14 16:53:18 +09:00 committed by Arnaldo Carvalho de Melo
parent ecfd7a9c04
commit 20105ca124
2 changed files with 199 additions and 0 deletions

View File

@ -13,6 +13,7 @@
#include <subcmd/exec-cmd.h>
#include "util/hist.h" /* perf_hist_config */
#include "util/llvm-utils.h" /* perf_llvm_config */
#include "config.h"
#define MAXNAME (256)
@ -524,6 +525,178 @@ out:
return ret;
}
static struct perf_config_section *find_section(struct list_head *sections,
const char *section_name)
{
struct perf_config_section *section;
list_for_each_entry(section, sections, node)
if (!strcmp(section->name, section_name))
return section;
return NULL;
}
static struct perf_config_item *find_config_item(const char *name,
struct perf_config_section *section)
{
struct perf_config_item *item;
list_for_each_entry(item, &section->items, node)
if (!strcmp(item->name, name))
return item;
return NULL;
}
static struct perf_config_section *add_section(struct list_head *sections,
const char *section_name)
{
struct perf_config_section *section = zalloc(sizeof(*section));
if (!section)
return NULL;
INIT_LIST_HEAD(&section->items);
section->name = strdup(section_name);
if (!section->name) {
pr_debug("%s: strdup failed\n", __func__);
free(section);
return NULL;
}
list_add_tail(&section->node, sections);
return section;
}
static struct perf_config_item *add_config_item(struct perf_config_section *section,
const char *name)
{
struct perf_config_item *item = zalloc(sizeof(*item));
if (!item)
return NULL;
item->name = strdup(name);
if (!item->name) {
pr_debug("%s: strdup failed\n", __func__);
free(item);
return NULL;
}
list_add_tail(&item->node, &section->items);
return item;
}
static int set_value(struct perf_config_item *item, const char *value)
{
char *val = strdup(value);
if (!val)
return -1;
zfree(&item->value);
item->value = val;
return 0;
}
static int collect_config(const char *var, const char *value,
void *perf_config_set)
{
int ret = -1;
char *ptr, *key;
char *section_name, *name;
struct perf_config_section *section = NULL;
struct perf_config_item *item = NULL;
struct perf_config_set *set = perf_config_set;
struct list_head *sections = &set->sections;
key = ptr = strdup(var);
if (!key) {
pr_debug("%s: strdup failed\n", __func__);
return -1;
}
section_name = strsep(&ptr, ".");
name = ptr;
if (name == NULL || value == NULL)
goto out_free;
section = find_section(sections, section_name);
if (!section) {
section = add_section(sections, section_name);
if (!section)
goto out_free;
}
item = find_config_item(name, section);
if (!item) {
item = add_config_item(section, name);
if (!item)
goto out_free;
}
ret = set_value(item, value);
return ret;
out_free:
free(key);
perf_config_set__delete(set);
return -1;
}
struct perf_config_set *perf_config_set__new(void)
{
struct perf_config_set *set = zalloc(sizeof(*set));
if (set) {
INIT_LIST_HEAD(&set->sections);
perf_config(collect_config, set);
}
return set;
}
static void perf_config_item__delete(struct perf_config_item *item)
{
zfree(&item->name);
zfree(&item->value);
free(item);
}
static void perf_config_section__purge(struct perf_config_section *section)
{
struct perf_config_item *item, *tmp;
list_for_each_entry_safe(item, tmp, &section->items, node) {
list_del_init(&item->node);
perf_config_item__delete(item);
}
}
static void perf_config_section__delete(struct perf_config_section *section)
{
perf_config_section__purge(section);
zfree(&section->name);
free(section);
}
static void perf_config_set__purge(struct perf_config_set *set)
{
struct perf_config_section *section, *tmp;
list_for_each_entry_safe(section, tmp, &set->sections, node) {
list_del_init(&section->node);
perf_config_section__delete(section);
}
}
void perf_config_set__delete(struct perf_config_set *set)
{
perf_config_set__purge(set);
free(set);
}
/*
* Call this to report error for your variable that should not
* get a boolean value (i.e. "[my] var" means "true").

26
tools/perf/util/config.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef __PERF_CONFIG_H
#define __PERF_CONFIG_H
#include <stdbool.h>
#include <linux/list.h>
struct perf_config_item {
char *name;
char *value;
struct list_head node;
};
struct perf_config_section {
char *name;
struct list_head items;
struct list_head node;
};
struct perf_config_set {
struct list_head sections;
};
struct perf_config_set *perf_config_set__new(void);
void perf_config_set__delete(struct perf_config_set *set);
#endif /* __PERF_CONFIG_H */