From 48532a1617ed59b5aaef247eace7a5cb67a1c69c Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Wed, 1 Apr 2009 11:29:19 +0530 Subject: Here is the v2 of the patch which introduces APIs to read controller specific stats. Added Makefile.am updates which I had missed in the previous post. New APIs to read controller specific statistics. This patch introduces 3 new APIs which can be used to read controller statistics iteratively. (Eg. stats from memory.stat etc) Reading of stats is initiated by cgroup_read_stats_begin() API, which returns the first stat of the requested controller in addition to returing a handle that should be used in subsequent reads. cgroup_read_stats_next() API can be used to read the remaining stats one by one. This needs the handle returned by cgroup_read_stats_begin(). cgroup_read_stats_end() API will terminate the stats reading iteration initiated by cgroup_read_stats_begin(). Changelog: v2 - Update tests/Makefile.am so that it generates appropriate rules for tests/read_stats.c in the Makefile. This is in addition to the manual updates done to the generated file tests/Makefile.in. v1 - cgroup_read_stats apis now work with relative cgroup path names instead of absolute path names. v0 - Initial post. Signed-off-by: Bharata B Rao Signed-off-by: Balbir Singh --- src/api.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libcgroup.map | 3 ++ 2 files changed, 105 insertions(+) (limited to 'src') diff --git a/src/api.c b/src/api.c index 2d57351..a45802e 100644 --- a/src/api.c +++ b/src/api.c @@ -20,6 +20,9 @@ * * Code initiated and designed by Dhaval Giani. All faults are most likely * his mistake. + * + * Bharata B Rao is willing is take blame + * for mistakes in APIs for reading statistics. */ #include @@ -2321,3 +2324,102 @@ int cgroup_walk_tree_begin(char *controller, char *base_path, const int depth, *handle = fts; return ret; } + +/* + * This parses a stat line which is in the form of (name value) pair + * separated by a space. + */ +int cg_read_stat(FILE *fp, struct cgroup_stat *stat) +{ + int ret = 0; + char *line = NULL; + size_t len = 0; + ssize_t read; + char *token, *saveptr; + + read = getline(&line, &len, fp); + if (read == -1) + return ECGEOF; + + token = strtok_r(line, " ", &saveptr); + if (!token) { + ret = ECGINVAL; + goto out_free; + } + strncpy(stat->name, token, FILENAME_MAX); + + token = strtok_r(NULL, " ", &saveptr); + if (!token) { + ret = ECGINVAL; + goto out_free; + } + strncpy(stat->value, token, CG_VALUE_MAX); + +out_free: + free(line); + return 0; +} + +int cgroup_read_stats_end(void **handle) +{ + FILE *fp; + + if (!cgroup_initialized) + return ECGROUPNOTINITIALIZED; + + if (!handle) + return ECGINVAL; + + fp = (FILE *)*handle; + fclose(fp); + return 0; +} + +int cgroup_read_stats_next(void **handle, struct cgroup_stat *stat) +{ + int ret = 0; + FILE *fp; + + if (!cgroup_initialized) + return ECGROUPNOTINITIALIZED; + + if (!handle || !stat) + return ECGINVAL; + + fp = (FILE *)*handle; + ret = cg_read_stat(fp, stat); + *handle = fp; + return ret; +} + +/* + * TODO: Need to decide a better place to put this function. + */ +int cgroup_read_stats_begin(char *controller, char *path, void **handle, + struct cgroup_stat *stat) +{ + int ret = 0; + char stat_file[FILENAME_MAX]; + FILE *fp; + + if (!cgroup_initialized) + return ECGROUPNOTINITIALIZED; + + if (!stat || !handle) + return ECGINVAL; + + if (!cg_build_path(path, stat_file, controller)) + return ECGOTHER; + + sprintf(stat_file, "%s/%s.stat", stat_file, controller); + + fp = fopen(stat_file, "r"); + if (!fp) { + cgroup_dbg("fopen failed\n"); + return ECGINVAL; + } + + ret = cg_read_stat(fp, stat); + *handle = fp; + return ret; +} diff --git a/src/libcgroup.map b/src/libcgroup.map index 1989f90..dd44fd7 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -52,5 +52,8 @@ global: cgroup_walk_tree_begin; cgroup_walk_tree_next; cgroup_walk_tree_end; + cgroup_read_stats_begin; + cgroup_read_stats_next; + cgroup_read_stats_end; } CGROUP_0.32.1; -- cgit