[PATCH v2 0/2] Implementation of a linked list helper

From: "Eduardo Lima (Etrunko)" <eblima@br.ibm.com> This series provides a generic linked list implementation for libxkutil that is based on the one originally developed for the libvirt domain events support recently integrated upstream. As test case I ported the ComputerSystemIndication provider code to use this list implementation. In the near future it will be also used by the event loop that I am currently working on to allow systems with libvirt older than 0.9.0 to make use of the same feature. Other possible use cases would be to port the code of libxkutil/*_parsing* to also use the list implementation instead of static arrays. Changes from v1: - Fix version iformation in Makefile.am -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima@br.ibm.com Eduardo Lima (Etrunko) (2): libxkutil: Linked list helper CSI: Use list helper implementation libxkutil/Makefile.am | 51 ++++++-- libxkutil/list_util.c | 231 +++++++++++++++++++++++++++++++++++ libxkutil/list_util.h | 76 ++++++++++++ src/Virt_ComputerSystemIndication.c | 95 ++++----------- 4 files changed, 370 insertions(+), 83 deletions(-) create mode 100644 libxkutil/list_util.c create mode 100644 libxkutil/list_util.h -- 1.7.7.5

From: "Eduardo Lima (Etrunko)" <eblima@br.ibm.com> Signed-off-by: Eduardo Lima (Etrunko) <eblima@br.ibm.com> --- libxkutil/Makefile.am | 51 ++++++++--- libxkutil/list_util.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++ libxkutil/list_util.h | 76 ++++++++++++++++ 3 files changed, 344 insertions(+), 14 deletions(-) create mode 100644 libxkutil/list_util.c create mode 100644 libxkutil/list_util.h diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am index f1adc03..8d436ad 100644 --- a/libxkutil/Makefile.am +++ b/libxkutil/Makefile.am @@ -1,21 +1,44 @@ # Copyright IBM Corp. 2007 +AM_CFLAGS = \ + $(CFLAGS_STRICT) \ + -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE@.conf\" -AM_CFLAGS = $(CFLAGS_STRICT) \ - -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE@.conf\" +noinst_HEADERS = \ + cs_util.h \ + misc_util.h \ + device_parsing.h \ + xmlgen.h \ + infostore.h \ + pool_parsing.h \ + acl_parsing.h \ + list_util.h -noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \ - pool_parsing.h acl_parsing.h +lib_LTLIBRARIES = \ + libxkutil.la -lib_LTLIBRARIES = libxkutil.la +libxkutil_la_SOURCES = \ + cs_util_instance.c \ + misc_util.c \ + device_parsing.c \ + xmlgen.c \ + infostore.c \ + pool_parsing.c \ + acl_parsing.c \ + list_util.c -libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \ - xmlgen.c infostore.c pool_parsing.c acl_parsing.c -libxkutil_la_LDFLAGS = -version-info @VERSION_INFO@ -libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \ - @LIBUUID_LIBS@ +libxkutil_la_LDFLAGS = \ + -version-info @VERSION_INFO@ -noinst_PROGRAMS = xml_parse_test +libxkutil_la_LIBADD = \ + @LIBVIRT_LIBS@ \ + @LIBUUID_LIBS@ -xml_parse_test_SOURCES = xml_parse_test.c -xml_parse_test_LDADD = libxkutil.la \ - @LIBVIRT_LIBS@ +noinst_PROGRAMS = \ + xml_parse_test + +xml_parse_test_SOURCES = \ + xml_parse_test.c + +xml_parse_test_LDADD = \ + libxkutil.la \ + @LIBVIRT_LIBS@ diff --git a/libxkutil/list_util.c b/libxkutil/list_util.c new file mode 100644 index 0000000..9f14aeb --- /dev/null +++ b/libxkutil/list_util.c @@ -0,0 +1,231 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Eduardo Lima (Etrunko) <eblima@br.ibm.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdlib.h> + +#include "list_util.h" + +struct _list_node_t { + list_node_t *prev; + list_node_t *next; + void *data; +}; + +list_t *list_new(list_data_free_cb free_cb, list_data_cmp_cb cmp_cb) +{ + list_t *l = calloc(1, sizeof(*l)); + if (l == NULL) + return NULL; + + l->free_cb = free_cb; + l->cmp_cb = cmp_cb; + return l; +} + +void list_free(list_t *list) +{ + list_node_t *n; + + if (list == NULL || list->head == NULL) + return; + + n = list->head; + + do { + if (list->free_cb) + list->free_cb(n->data); + + n = n->next; + free(n->prev); + } while (n != list->head); + + free(list); +} + +void list_append(list_t *list, void *data) +{ + list_node_t *n; + + if (list == NULL) + return; + + n = calloc(1, sizeof(*n)); + + if (n == NULL) + return; + + n->data = data; + + if (list->head == NULL) { /* empty list */ + n->next = n->prev = n; + list->head = n; + goto end; + } + + n->next = list->head; + n->prev = list->head->prev; + + list->head->prev->next = n; + list->head->prev = n; + + end: + list->count += 1; +} + +void list_prepend(list_t *list, void *data) +{ + list_append(list, data); + list->head = list->head->prev; +} + +void *list_find(list_t *list, void *user_data) +{ + list_node_t *n = list_find_node(list, user_data); + return list_node_data_get(n); +} + +list_node_t *list_find_node(list_t *list, void *user_data) +{ + list_node_t *n; + + if (list == NULL || list->head == NULL || list->cmp_cb == NULL) + return NULL; + + n = list->head; + do { + if (list->cmp_cb(n->data, user_data) == 0) + return n; + + n = n->next; + } while (n != list->head); + + return NULL; +} + +void list_remove(list_t *list, void *data) +{ + list_node_t *n = list_find_node(list, data); + list_remove_node(list, n); +} + +void list_remove_node(list_t *list, list_node_t *node) +{ + if (list == NULL || list->head == NULL || node == NULL) + return; + + if (node->next == node) { /* only 1 item */ + list->head = NULL; + } else { + if (node == list->head) /* first node */ + list->head = node->next; + + node->prev->next = node->next; + node->next->prev = node->prev; + } + + if (list->free_cb) + list->free_cb(node->data); + + free(node); + list->count -= 1; +} + +void list_foreach(list_t *list, list_foreach_cb cb, void *user_data) +{ + list_node_t *node; + + if (list == NULL || list->head == NULL) + return; + + node = list->head; + do { + cb(node->data, user_data); + node = node->next; + } while (node != list->head); +} + +void *list_node_data_get(list_node_t *node) +{ + if (node == NULL) + return NULL; + + return node->data; +} + +void list_node_data_set(list_node_t *node, void *data) +{ + if (node == NULL) + return; + + node->data = data; +} + +void *list_first(list_t *list) +{ + return list_node_data_get(list->head); +} + +list_node_t *list_first_node(list_t *list) +{ + return list->head; +} + +void *list_last(list_t *list) +{ + return list_node_data_get(list_last_node(list)); +} + +list_node_t *list_last_node(list_t *list) +{ + if (list == NULL) + return NULL; + + return list->head->prev; +} + +void *list_node_next(list_node_t *node) +{ + return list_node_data_get(list_node_next_node(node)); +} + +list_node_t *list_node_next_node(list_node_t *node) +{ + if (node == NULL) + return NULL; + + return node->next; +} + +void *list_node_prev(list_node_t *node) +{ + return list_node_data_get(list_node_prev_node(node)); +} + +list_node_t *list_node_prev_node(list_node_t *node) +{ + if (node == NULL) + return NULL; + + return node->prev; +} diff --git a/libxkutil/list_util.h b/libxkutil/list_util.h new file mode 100644 index 0000000..96c0338 --- /dev/null +++ b/libxkutil/list_util.h @@ -0,0 +1,76 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Eduardo Lima (Etrunko) <eblima@br.ibm.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LIST_UTIL_H +#define __LIST_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _list_node_t list_node_t; + +typedef void (*list_data_free_cb)(void *data); +typedef int (*list_data_cmp_cb)(void *list_data, void *user_data); +typedef void (*list_foreach_cb)(void *list_data, void *user_data); + +typedef struct _list_t list_t; +struct _list_t { + int count; + list_node_t *head; + list_data_free_cb free_cb; + list_data_cmp_cb cmp_cb; +}; + +list_t *list_new(list_data_free_cb free_cb, list_data_cmp_cb cmp_cb); +void list_free(list_t *list); + +void list_append(list_t *list, void *data); +void list_prepend(list_t *list, void *data); + +void *list_find(list_t *list, void *user_data); +list_node_t *list_find_node(list_t *list, void *user_data); + +void list_remove(list_t *list, void *data); +void list_remove_node(list_t *list, list_node_t *node); + +void list_foreach(list_t *list, list_foreach_cb cb, void *user_data); + +inline void *list_node_data_get(list_node_t *node); +inline void list_node_data_set(list_node_t *node, void *data); + +inline void *list_first(list_t *list); +inline list_node_t *list_first_node(list_t *list); + +inline void *list_last(list_t *list); +inline list_node_t *list_last_node(list_t *list); + +inline void *list_node_next(list_node_t *node); +inline list_node_t *list_node_next_node(list_node_t *node); + +inline void *list_node_prev(list_node_t *node); +inline list_node_t *list_node_prev_node(list_node_t *node); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __LIST_UTIL_H */ -- 1.7.7.5

From: "Eduardo Lima (Etrunko)" <eblima@br.ibm.com> Signed-off-by: Eduardo Lima (Etrunko) <eblima@br.ibm.com> --- src/Virt_ComputerSystemIndication.c | 95 ++++++++++------------------------- 1 files changed, 26 insertions(+), 69 deletions(-) diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c index eb1a71c..ed1c48d 100644 --- a/src/Virt_ComputerSystemIndication.c +++ b/src/Virt_ComputerSystemIndication.c @@ -19,6 +19,10 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include <unistd.h> #include <stdio.h> #include <fcntl.h> @@ -34,11 +38,11 @@ #include <libvirt/virterror.h> #include <libcmpiutil/libcmpiutil.h> -#include <misc_util.h> #include <libcmpiutil/std_indication.h> -#include <cs_util.h> -#include "config.h" +#include <misc_util.h> +#include <cs_util.h> +#include <list_util.h> #include "Virt_ComputerSystem.h" #include "Virt_ComputerSystemIndication.h" @@ -64,8 +68,6 @@ struct _csi_dom_xml_t { char uuid[VIR_UUID_STRING_BUFLEN]; char *name; char *xml; - csi_dom_xml_t *next; - csi_dom_xml_t *prev; }; typedef struct _csi_thread_data_t csi_thread_data_t; @@ -73,7 +75,7 @@ struct _csi_thread_data_t { CMPI_THREAD_TYPE id; int active_filters; int dom_count; - csi_dom_xml_t *dom_list; + list_t *dom_list; struct ind_args *args; }; @@ -83,15 +85,24 @@ static bool lifecycle_enabled = false; static csi_thread_data_t csi_thread_data[CSI_NUM_PLATFORMS] = {{0}, {0}, {0}}; /* - * Domain list manipulation + * Domain manipulation */ -static void csi_dom_xml_free(csi_dom_xml_t *dom) +static void csi_dom_xml_free(void *data) { + csi_dom_xml_t *dom = (csi_dom_xml_t *) data; free(dom->xml); free(dom->name); free(dom); } +static int csi_dom_xml_cmp(void *data, void *cmp_cb_data) +{ + csi_dom_xml_t *dom = (csi_dom_xml_t *) data; + const char *uuid = (const char *) cmp_cb_data; + + return strcmp(dom->uuid, uuid); +} + static int csi_dom_xml_set(csi_dom_xml_t *dom, virDomainPtr dom_ptr, CMPIStatus *s) { const char *name; @@ -149,65 +160,10 @@ static csi_dom_xml_t *csi_dom_xml_new(virDomainPtr dom_ptr, CMPIStatus *s) static void csi_thread_dom_list_append(csi_thread_data_t *thread, csi_dom_xml_t *dom) { - /* empty list */ - if (thread->dom_list == NULL) { - dom->next = dom->prev = dom; - thread->dom_list = dom; - goto end; - } - - dom->next = thread->dom_list; - dom->prev = thread->dom_list->prev; - - thread->dom_list->prev->next = dom; - thread->dom_list->prev = dom; - - end: - thread->dom_count += 1; -} - -static csi_dom_xml_t *csi_thread_dom_list_find(csi_thread_data_t *thread, - const char *uuid) -{ - csi_dom_xml_t *dom; - if (thread->dom_list == NULL) - return NULL; - - dom = thread->dom_list; - - do { - if (STREQ(dom->uuid, uuid)) - return dom; - - dom = dom->next; - } while (dom != thread->dom_list); + thread->dom_list = list_new(csi_dom_xml_free, csi_dom_xml_cmp); - return NULL; -} - -static void csi_thread_dom_list_remove(csi_thread_data_t *thread, - csi_dom_xml_t *dom) -{ - if (dom->next == dom) { /* Only one node */ - thread->dom_list = NULL; - } else { - if (thread->dom_list == dom) /* First node */ - thread->dom_list = dom->next; - - dom->prev->next = dom->next; - dom->next->prev = dom->prev; - } - - thread->dom_count -= 1; - - csi_dom_xml_free(dom); -} - -static void csi_thread_dom_list_free(csi_thread_data_t *thread) -{ - while(thread->dom_list != NULL) - csi_thread_dom_list_remove(thread, thread->dom_list); + list_append(thread->dom_list, dom); } static void csi_free_thread_data(void *data) @@ -217,7 +173,8 @@ static void csi_free_thread_data(void *data) if (data == NULL) return; - csi_thread_dom_list_free(thread); + list_free(thread->dom_list); + thread->dom_list = NULL; stdi_free_ind_args(&thread->args); } @@ -511,7 +468,7 @@ static int update_domain_list(virConnectPtr conn, csi_thread_data_t *thread) CMPIStatus s = {CMPI_RC_OK, NULL}; int i, count; - csi_thread_dom_list_free(thread); + list_free(thread->dom_list); count = get_domain_list(conn, &dom_ptr_list); @@ -573,7 +530,7 @@ static int csi_domain_event_cb(virConnectPtr conn, if (cs_event != CS_CREATED) { char uuid[VIR_UUID_STRING_BUFLEN] = {0}; virDomainGetUUIDString(dom, &uuid[0]); - dom_xml = csi_thread_dom_list_find(thread, uuid); + dom_xml = list_find(thread->dom_list, uuid); } if (dom_xml == NULL) { @@ -594,7 +551,7 @@ static int csi_domain_event_cb(virConnectPtr conn, } } else if (event == VIR_DOMAIN_EVENT_DEFINED && detail == VIR_DOMAIN_EVENT_UNDEFINED_REMOVED) { - csi_thread_dom_list_remove(thread, dom_xml); + list_remove(thread->dom_list, dom_xml); } end: -- 1.7.7.5
participants (1)
-
Eduardo Lima (Etrunko)