diff options
author | Taeung Song <treeze.taeung@gmail.com> | 2016-04-14 03:53:18 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-04-14 08:00:42 -0400 |
commit | 20105ca1240c3d3ac8cc79bf195022e5e5c1c3fb (patch) | |
tree | 6df34d0dddab226e68a47dd4e019cb6d2714b989 /tools/perf/util/config.c | |
parent | ecfd7a9c044e98fc3da8937e652080bc5abe7918 (diff) |
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>
Diffstat (limited to 'tools/perf/util/config.c')
-rw-r--r-- | tools/perf/util/config.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 664490b8b327..dad7d8272168 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <subcmd/exec-cmd.h> | 13 | #include <subcmd/exec-cmd.h> |
14 | #include "util/hist.h" /* perf_hist_config */ | 14 | #include "util/hist.h" /* perf_hist_config */ |
15 | #include "util/llvm-utils.h" /* perf_llvm_config */ | 15 | #include "util/llvm-utils.h" /* perf_llvm_config */ |
16 | #include "config.h" | ||
16 | 17 | ||
17 | #define MAXNAME (256) | 18 | #define MAXNAME (256) |
18 | 19 | ||
@@ -524,6 +525,178 @@ out: | |||
524 | return ret; | 525 | return ret; |
525 | } | 526 | } |
526 | 527 | ||
528 | static struct perf_config_section *find_section(struct list_head *sections, | ||
529 | const char *section_name) | ||
530 | { | ||
531 | struct perf_config_section *section; | ||
532 | |||
533 | list_for_each_entry(section, sections, node) | ||
534 | if (!strcmp(section->name, section_name)) | ||
535 | return section; | ||
536 | |||
537 | return NULL; | ||
538 | } | ||
539 | |||
540 | static struct perf_config_item *find_config_item(const char *name, | ||
541 | struct perf_config_section *section) | ||
542 | { | ||
543 | struct perf_config_item *item; | ||
544 | |||
545 | list_for_each_entry(item, §ion->items, node) | ||
546 | if (!strcmp(item->name, name)) | ||
547 | return item; | ||
548 | |||
549 | return NULL; | ||
550 | } | ||
551 | |||
552 | static struct perf_config_section *add_section(struct list_head *sections, | ||
553 | const char *section_name) | ||
554 | { | ||
555 | struct perf_config_section *section = zalloc(sizeof(*section)); | ||
556 | |||
557 | if (!section) | ||
558 | return NULL; | ||
559 | |||
560 | INIT_LIST_HEAD(§ion->items); | ||
561 | section->name = strdup(section_name); | ||
562 | if (!section->name) { | ||
563 | pr_debug("%s: strdup failed\n", __func__); | ||
564 | free(section); | ||
565 | return NULL; | ||
566 | } | ||
567 | |||
568 | list_add_tail(§ion->node, sections); | ||
569 | return section; | ||
570 | } | ||
571 | |||
572 | static struct perf_config_item *add_config_item(struct perf_config_section *section, | ||
573 | const char *name) | ||
574 | { | ||
575 | struct perf_config_item *item = zalloc(sizeof(*item)); | ||
576 | |||
577 | if (!item) | ||
578 | return NULL; | ||
579 | |||
580 | item->name = strdup(name); | ||
581 | if (!item->name) { | ||
582 | pr_debug("%s: strdup failed\n", __func__); | ||
583 | free(item); | ||
584 | return NULL; | ||
585 | } | ||
586 | |||
587 | list_add_tail(&item->node, §ion->items); | ||
588 | return item; | ||
589 | } | ||
590 | |||
591 | static int set_value(struct perf_config_item *item, const char *value) | ||
592 | { | ||
593 | char *val = strdup(value); | ||
594 | |||
595 | if (!val) | ||
596 | return -1; | ||
597 | |||
598 | zfree(&item->value); | ||
599 | item->value = val; | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int collect_config(const char *var, const char *value, | ||
604 | void *perf_config_set) | ||
605 | { | ||
606 | int ret = -1; | ||
607 | char *ptr, *key; | ||
608 | char *section_name, *name; | ||
609 | struct perf_config_section *section = NULL; | ||
610 | struct perf_config_item *item = NULL; | ||
611 | struct perf_config_set *set = perf_config_set; | ||
612 | struct list_head *sections = &set->sections; | ||
613 | |||
614 | key = ptr = strdup(var); | ||
615 | if (!key) { | ||
616 | pr_debug("%s: strdup failed\n", __func__); | ||
617 | return -1; | ||
618 | } | ||
619 | |||
620 | section_name = strsep(&ptr, "."); | ||
621 | name = ptr; | ||
622 | if (name == NULL || value == NULL) | ||
623 | goto out_free; | ||
624 | |||
625 | section = find_section(sections, section_name); | ||
626 | if (!section) { | ||
627 | section = add_section(sections, section_name); | ||
628 | if (!section) | ||
629 | goto out_free; | ||
630 | } | ||
631 | |||
632 | item = find_config_item(name, section); | ||
633 | if (!item) { | ||
634 | item = add_config_item(section, name); | ||
635 | if (!item) | ||
636 | goto out_free; | ||
637 | } | ||
638 | |||
639 | ret = set_value(item, value); | ||
640 | return ret; | ||
641 | |||
642 | out_free: | ||
643 | free(key); | ||
644 | perf_config_set__delete(set); | ||
645 | return -1; | ||
646 | } | ||
647 | |||
648 | struct perf_config_set *perf_config_set__new(void) | ||
649 | { | ||
650 | struct perf_config_set *set = zalloc(sizeof(*set)); | ||
651 | |||
652 | if (set) { | ||
653 | INIT_LIST_HEAD(&set->sections); | ||
654 | perf_config(collect_config, set); | ||
655 | } | ||
656 | |||
657 | return set; | ||
658 | } | ||
659 | |||
660 | static void perf_config_item__delete(struct perf_config_item *item) | ||
661 | { | ||
662 | zfree(&item->name); | ||
663 | zfree(&item->value); | ||
664 | free(item); | ||
665 | } | ||
666 | |||
667 | static void perf_config_section__purge(struct perf_config_section *section) | ||
668 | { | ||
669 | struct perf_config_item *item, *tmp; | ||
670 | |||
671 | list_for_each_entry_safe(item, tmp, §ion->items, node) { | ||
672 | list_del_init(&item->node); | ||
673 | perf_config_item__delete(item); | ||
674 | } | ||
675 | } | ||
676 | |||
677 | static void perf_config_section__delete(struct perf_config_section *section) | ||
678 | { | ||
679 | perf_config_section__purge(section); | ||
680 | zfree(§ion->name); | ||
681 | free(section); | ||
682 | } | ||
683 | |||
684 | static void perf_config_set__purge(struct perf_config_set *set) | ||
685 | { | ||
686 | struct perf_config_section *section, *tmp; | ||
687 | |||
688 | list_for_each_entry_safe(section, tmp, &set->sections, node) { | ||
689 | list_del_init(§ion->node); | ||
690 | perf_config_section__delete(section); | ||
691 | } | ||
692 | } | ||
693 | |||
694 | void perf_config_set__delete(struct perf_config_set *set) | ||
695 | { | ||
696 | perf_config_set__purge(set); | ||
697 | free(set); | ||
698 | } | ||
699 | |||
527 | /* | 700 | /* |
528 | * Call this to report error for your variable that should not | 701 | * Call this to report error for your variable that should not |
529 | * get a boolean value (i.e. "[my] var" means "true"). | 702 | * get a boolean value (i.e. "[my] var" means "true"). |