From c02e43d9933c63a30f4c9498d103c07de71ad5be Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Tue, 10 Aug 2010 15:06:18 +0530 Subject: [PATCH] Changelog: - update comments: - emphasize that 'dictionary' is not hash - emphasize that order is important - better describe what CG_DICT_DONT_FREE_ITEMS frees For subsequent patch (update cgconfig parser to accept quoted-strings as parameter values), I need a simple storage of name-value pairs, so let's create simple linked-list framework. It's internal only, these functions should probably never get public, It is indeed very simple, it can only add items to the end and iterate through the items, while preserving their order. It does *not* provide random access to its items and it is *not* based on hash structure (at least for now). Signed-off-by: Jan Safranek Signed-off-by: Balbir Singh --- src/api.c | 112 +++++++++++++++++++++++++++++++++++++++ src/libcgroup-internal.h | 74 ++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) diff --git a/src/api.c b/src/api.c index 195e0e6a..4bd6b463 100644 --- a/src/api.c +++ b/src/api.c @@ -3528,3 +3528,115 @@ int cgroup_get_procs(char *name, char *controller, pid_t **pids, int *size) return 0; } + + +int cgroup_dictionary_create(struct cgroup_dictionary **dict, + int flags) +{ + *dict = (struct cgroup_dictionary *) calloc( + 1, sizeof(struct cgroup_dictionary)); + + if (!dict) + return ECGFAIL; + (*dict)->flags = flags; + return 0; +} + + +int cgroup_dictionary_add(struct cgroup_dictionary *dict, + const char *name, const char *value) +{ + struct cgroup_dictionary_item *it; + + if (!dict) + return ECGINVAL; + + it = (struct cgroup_dictionary_item *) malloc( + sizeof(struct cgroup_dictionary_item)); + if (!it) + return ECGFAIL; + + it->next = NULL; + it->name = name; + it->value = value; + + if (dict->tail) { + dict->tail->next = it; + dict->tail = it; + } else { + /* it is the first item */ + dict->tail = it; + dict->head = it; + } + return 0; +} + +int cgroup_dictionary_free(struct cgroup_dictionary *dict) +{ + struct cgroup_dictionary_item *it; + + if (!dict) + return ECGINVAL; + + it = dict->head; + while (it) { + struct cgroup_dictionary_item *del = it; + it = it->next; + if (!(dict->flags & CG_DICT_DONT_FREE_ITEMS)) { + free((void *)del->value); + free((void *)del->name); + } + free(del); + } + + free(dict); + return 0; +} + +int cgroup_dictionary_iterator_begin(struct cgroup_dictionary *dict, + void **handle, const char **name, const char **value) +{ + struct cgroup_dictionary_iterator *iter; + + *handle = NULL; + + if (!dict) + return ECGINVAL; + + iter = (struct cgroup_dictionary_iterator *) malloc( + sizeof(struct cgroup_dictionary_iterator)); + if (!iter) + return ECGFAIL; + + iter->item = dict->head; + *handle = iter; + return cgroup_dictionary_iterator_next(handle, name, value); +} + +int cgroup_dictionary_iterator_next(void **handle, + const char **name, const char **value) +{ + struct cgroup_dictionary_iterator *iter; + + if (!handle) + return ECGINVAL; + + iter = *handle; + if (!iter->item) + return ECGEOF; + + *name = iter->item->name; + *value = iter->item->value; + iter->item = iter->item->next; + return 0; +} + +void cgroup_dictionary_iterator_end(void **handle) +{ + if (!handle) + return; + + free(*handle); + *handle = NULL; +} + diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index d232111a..92b9fd8d 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -128,6 +128,47 @@ struct cgroup_tree_handle { int flags; }; +/** + * Internal item of dictionary. Linked list is sufficient for now - we need + * only 'add' operation and simple iterator. In future, this might be easily + * rewritten to dynamic array when random access is needed, + * just keep in mind that the order is important and the iterator should + * return the items in the order they were added there. + */ +struct cgroup_dictionary_item { + const char *name; + const char *value; + struct cgroup_dictionary_item *next; +}; + +/* Flags for cgroup_dictionary_create */ +/** + * All items (i.e. both name and value strings) stored in the dictionary + * should *NOT* be free()d on cgroup_dictionary_free(), + * only the dictionary helper structures (i.e. underlying linked list) + * should be freed. + */ +#define CG_DICT_DONT_FREE_ITEMS 1 + +/** + * Dictionary of (name, value) items. + * The dictionary keeps its order, iterator iterates in the same order + * as the items were added there. It is *not* hash-style structure, + * it does not provide random access to its items nor quick search. + * This structure should be opaque to users of the dictionary, underlying data + * structure might change anytime and without warnings. + */ +struct cgroup_dictionary { + struct cgroup_dictionary_item *head; + struct cgroup_dictionary_item *tail; + int flags; +}; + +/** Opaque iterator of an dictionary. */ +struct cgroup_dictionary_iterator { + struct cgroup_dictionary_item *item; +}; + /** * per thread errno variable, to be used when return code is ECGOTHER */ @@ -164,6 +205,39 @@ int cgroup_config_insert_into_mount_table(char *name, char *mount_point); int cgroup_config_insert_into_namespace_table(char *name, char *mount_point); void cgroup_config_cleanup_mount_table(void); void cgroup_config_cleanup_namespace_table(void); + +/** + * Create an empty dictionary. + */ +extern int cgroup_dictionary_create(struct cgroup_dictionary **dict, + int flags); +/** + * Add an item to existing dictionary. + */ +extern int cgroup_dictionary_add(struct cgroup_dictionary *dict, + const char *name, const char *value); +/** + * Fully destroy existing dictionary. Depending on flags passed to + * cgroup_dictionary_create(), names and values might get destroyed too. + */ +extern int cgroup_dictionary_free(struct cgroup_dictionary *dict); + +/** + * Start iterating through a dictionary. The items are returned in the same + * order as they were added using cgroup_dictionary_add(). + */ +extern int cgroup_dictionary_iterator_begin(struct cgroup_dictionary *dict, + void **handle, const char **name, const char **value); +/** + * Continue iterating through the dictionary. + */ +extern int cgroup_dictionary_iterator_next(void **handle, + const char **name, const char **value); +/** + * Finish iteration through the dictionary. + */ +extern void cgroup_dictionary_iterator_end(void **handle); + __END_DECLS #endif -- 2.47.2