# HG changeset patch # User Louis Opter # Date 1293900400 -3600 # Node ID 8339ab15527d5687edc35fccad0780ef5253515c # Parent e2b88f50e13658f6c481e2d164845d6964b1c70a Add running/stopped containers global statistics and refactor some things diff -r e2b88f50e136 -r 8339ab15527d CMakeLists.txt --- a/CMakeLists.txt Sat Jan 01 16:18:17 2011 +0100 +++ b/CMakeLists.txt Sat Jan 01 17:46:40 2011 +0100 @@ -40,6 +40,7 @@ compat/strlcat.c close.c container.c + globals.c open.c utils.c ${PROBES_SRC} diff -r e2b88f50e136 -r 8339ab15527d _lxcstats.h --- a/_lxcstats.h Sat Jan 01 16:18:17 2011 +0100 +++ b/_lxcstats.h Sat Jan 01 17:46:40 2011 +0100 @@ -6,6 +6,8 @@ # define NSEC_PER_SEC 1000000000L +# define LXC_DIR "/var/lib/lxc/" + # define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) struct dirent; @@ -14,14 +16,17 @@ * Store all informations needed to get statistics from a cgroup * hierarchy. */ -struct _lxcst_controller { - char *cgroup_dir; /**< Mount point of the cgroup hierarchy. */ +struct _lxcst_controller { + char *cgroup_dir; /**< Mount point of the cgroup hierarchy. */ + const char *lxc_dir; /**< LXC configuration directory (LXC_DIR). */ }; +extern struct lxcst_globals _lxcst_globals; + /** * Allocate a new lxcst structure for the given container. */ -struct lxcst *_lxcst_container_new(struct _lxcst_controller *, const char *); +struct lxcst *_lxcst_container_new(const struct _lxcst_controller *, const char *); /** * Free a lxcst structure. @@ -29,19 +34,26 @@ void _lxcst_container_delete(struct lxcst *); /** + * Get the total number of LXC containers on this machine. + */ +int _lxcst_container_count(const struct _lxcst_controller *ct); + +/** * Get statistics on a container. */ int _lxcst_container_read_infos(struct lxcst *); +/** + * Reset the global statistics structure. + */ +void _lxcst_globals_reset(void); + char *_lxcst_join_path(char *, size_t , const char *, const char *); /** - * Used to select only directories with scandir. We can't directly use it with - * scandir because we need the cgroup_dir. - * - * @return true if the given directory entry is a directory. + * @return true if the given path is a directory. */ -int _lxcst_isdir(const struct _lxcst_controller *, const struct dirent *); +int _lxcst_isdir(const char *); /** * Allocate a buffer and read an entire file in it. diff -r e2b88f50e136 -r 8339ab15527d container.c --- a/container.c Sat Jan 01 16:18:17 2011 +0100 +++ b/container.c Sat Jan 01 17:46:40 2011 +0100 @@ -18,7 +18,7 @@ } struct lxcst * -_lxcst_container_new(struct _lxcst_controller *ct, const char *name) +_lxcst_container_new(const struct _lxcst_controller *ct, const char *name) { char buf[256]; struct lxcst *c; @@ -56,6 +56,32 @@ } } +/* + * Should be equivalent to the number of directories found under /var/lib/lxc/ + */ +int +_lxcst_container_count(const struct _lxcst_controller *ct) +{ + int n; + struct dirent **c_vec; + int count; + char buf[PATH_MAX]; + + n = scandir(ct->lxc_dir, &c_vec, &_lxcst_unselect_current_and_parent, NULL); + if (n != -1) { + count = n; + while (n--) { + if (!_lxcst_isdir(_lxcst_join_path(buf, sizeof(buf), ct->lxc_dir, c_vec[n]->d_name))) + --count; + free(c_vec[n]); + } + free(c_vec); + return (count); + } + + return (-1); +} + int _lxcst_container_read_infos(struct lxcst *c) { @@ -76,16 +102,20 @@ int n; struct dirent **c_vec; struct lxcst *c; + char buf[PATH_MAX]; assert(hdl); assert(hdl->cgroup_dir); assert(cb); + _lxcst_globals_reset(); + n = scandir(hdl->cgroup_dir, &c_vec, &_lxcst_unselect_current_and_parent, NULL); if (n > 0) { while (n--) { - if (_lxcst_isdir(hdl, c_vec[n])) { + if (_lxcst_isdir(_lxcst_join_path(buf, sizeof(buf), hdl->cgroup_dir, c_vec[n]->d_name))) { c = _lxcst_container_new(hdl, c_vec[n]->d_name); + _lxcst_globals.running_containers++; if (c && _lxcst_container_read_infos(c) == 0 && cb(ctx, c)) { errno = EINTR; @@ -99,6 +129,14 @@ return (-1); } + n = _lxcst_container_count(hdl); + if (n == -1) { + warn("can't get the total number of containers"); + return (-1); + } + + _lxcst_globals.stopped_containers = n - _lxcst_globals.running_containers; + return (0); abort_by_cb: diff -r e2b88f50e136 -r 8339ab15527d globals.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/globals.c Sat Jan 01 17:46:40 2011 +0100 @@ -0,0 +1,22 @@ +#include + +#include +#include + +#include "lxcstats.h" +#include "_lxcstats.h" + +struct lxcst_globals _lxcst_globals = { 0, 0 }; + +void +_lxcst_globals_reset(void) +{ + memset(&_lxcst_globals, 0, sizeof(_lxcst_globals)); +} + +void +lxcst_globals_statistics(struct lxcst_globals *sb) +{ + assert(sb); + memcpy(sb, &_lxcst_globals, sizeof(*sb)); +} diff -r e2b88f50e136 -r 8339ab15527d lxcstats.h --- a/lxcstats.h Sat Jan 01 16:18:17 2011 +0100 +++ b/lxcstats.h Sat Jan 01 17:46:40 2011 +0100 @@ -27,8 +27,8 @@ * Note: see how lxc-info gets these infos. */ struct lxcst_globals { - uint32_t running_containers; - uint32_t stopped_containers; + uint16_t running_containers; + uint16_t stopped_containers; }; /** @@ -51,7 +51,10 @@ int lxcst_close(lxcst_handle *hdl); /** - * @brief Collect statistic on all containers. + * @brief Collect statistics on all containers. + * + * Walk the cgroup pseudo filesystem and get statistics for all found + * containers. Also refresh the global statistics struture. * * @param [in] hdl The pointer returned by lxcst_handle. * @param [in] cb A function pointer to a callback which takes a pointer to an @@ -61,7 +64,20 @@ * lxcst_span_containers stops and return with -1 with errno set to EINTR. * * @return 0 on success, -1 on error with errno set. + * + * @see lxcst_globals_statistics + * @see struct lxcst */ int lxcst_span_containers(lxcst_handle *hdl, int (*cb)(void *, const struct lxcst *), void *ctx); +/** + * @brief Get a copy of the global LXC statistics object. + * + * @param [out] sb A pointer to a struct lxcst_globals. + * + * @see struct lxcst_globals + * @see lxcst_span_containers + */ +void lxcst_globals_statistics(struct lxcst_globals *sb); + #endif diff -r e2b88f50e136 -r 8339ab15527d open.c --- a/open.c Sat Jan 01 16:18:17 2011 +0100 +++ b/open.c Sat Jan 01 17:46:40 2011 +0100 @@ -48,6 +48,8 @@ if (!c->cgroup_dir) goto free_controller; + c->lxc_dir = LXC_DIR; + return (c); free_controller: diff -r e2b88f50e136 -r 8339ab15527d tests/CMakeLists.txt --- a/tests/CMakeLists.txt Sat Jan 01 16:18:17 2011 +0100 +++ b/tests/CMakeLists.txt Sat Jan 01 17:46:40 2011 +0100 @@ -11,6 +11,7 @@ SET(TESTS close + container_count open read_file read_big_file diff -r e2b88f50e136 -r 8339ab15527d tests/container_count.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/container_count.c Sat Jan 01 17:46:40 2011 +0100 @@ -0,0 +1,30 @@ +#include + +#include +#include +#include + +#include "lxcstats.h" +#include "_lxcstats.h" + +int +main(int argc, char *argv[]) +{ + lxcst_handle *hdl; + int count; + + hdl = lxcst_open(); + if (!hdl) + err(EXIT_FAILURE, "lxcst_open failed"); + + count = _lxcst_container_count(hdl); + if (count == -1) + err(EXIT_FAILURE, "_lxcst_container_count failed"); + + printf("%s: %d containers.\n", *argv, count); + + lxcst_close(hdl); + + return (EXIT_SUCCESS); + (void)argc; +} diff -r e2b88f50e136 -r 8339ab15527d tests/open.c --- a/tests/open.c Sat Jan 01 16:18:17 2011 +0100 +++ b/tests/open.c Sat Jan 01 17:46:40 2011 +0100 @@ -12,8 +12,9 @@ hdl = lxcst_open(); - if (hdl) { - printf("%s: mnt_dir=%s.\n", *argv, hdl->cgroup_dir); + if (hdl && hdl->cgroup_dir && hdl->lxc_dir) { + printf("%s: cgroup_dir=%s.\n", *argv, hdl->cgroup_dir); + printf("%s: lxc_dir=%s.\n", *argv, hdl->lxc_dir); return (EXIT_SUCCESS); } diff -r e2b88f50e136 -r 8339ab15527d tests/span_containers.c --- a/tests/span_containers.c Sat Jan 01 16:18:17 2011 +0100 +++ b/tests/span_containers.c Sat Jan 01 17:46:40 2011 +0100 @@ -23,7 +23,8 @@ int main(int argc, char *argv[]) { - lxcst_handle *hdl; + lxcst_handle *hdl; + struct lxcst_globals globals; hdl = lxcst_open(); if (!hdl) @@ -35,6 +36,13 @@ printf("%s: spanned %d containers.\n", *argv, n); + lxcst_globals_statistics(&globals); + + if (globals.running_containers != n) + errx(EXIT_FAILURE, "running_containers != spanned containers"); + + printf("%s: %d running containers, %d stopped containers.\n", *argv, globals.running_containers, globals.stopped_containers); + return (EXIT_SUCCESS); (void)argc; } diff -r e2b88f50e136 -r 8339ab15527d utils.c --- a/utils.c Sat Jan 01 16:18:17 2011 +0100 +++ b/utils.c Sat Jan 01 17:46:40 2011 +0100 @@ -29,15 +29,12 @@ } int -_lxcst_isdir(const struct _lxcst_controller *hdl, const struct dirent *d) +_lxcst_isdir(const char *path) { struct stat sb; - char buf[PATH_MAX]; - _lxcst_join_path(buf, sizeof(buf), hdl->cgroup_dir, d->d_name); - - if (stat(buf, &sb) == -1) { - warn("can't stat file: %s", buf); + if (stat(path, &sb) == -1) { + warn("can't stat path: %s", path); return (0); }