[Libvirt-cim] [PATCH V2 03/48] Add basic operations for reading data from xml node

Xu Wang cngesaint at gmail.com
Mon Oct 28 02:45:32 UTC 2013


Signed-off-by: Xu Wang <gesaint at linux.vnet.ibm.com>
---
 libxkutil/device_parsing.c |  297 ++++++++++++++++++++++++++++++++++++++++++++
 libxkutil/device_parsing.h |   25 ++++-
 2 files changed, 320 insertions(+), 2 deletions(-)

diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
index f1da880..e95b0a9 100644
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -404,6 +404,303 @@ char *get_node_content(xmlNode *node)
         return buf;
 }
 
+/* 
+ * This function is just used for debugging. If you found something wrong
+ * please call this function and check the result of output in the logs.
+ */
+void print_others(struct others *head)
+{
+        CU_DEBUG("**************************************************");
+        while (head) {
+                CU_DEBUG("---------------------------");
+                CU_DEBUG("- others id: %d", head->id);
+                CU_DEBUG("- others name: %s", head->name);
+                CU_DEBUG("- others value: %s", head->value);
+                CU_DEBUG("- others type: %d", head->type);
+                CU_DEBUG("- others parent_id: %d", head->parent_id);
+                CU_DEBUG("- others parent_name: %s", head->parent_name);
+                if (head->status == ACTIVE) {
+                        CU_DEBUG("- others status: ACTIVE");
+                } else {
+                        CU_DEBUG("- others status: INACTIVE");
+                }
+                CU_DEBUG("---------------------------");
+                head = head->next;
+        }
+        CU_DEBUG("**************************************************");
+}
+
+/* 
+ * Add one node into head link list. All items are set as parameters.
+ *
+ * @head: The link list head pointer to be added.
+ * @node: Where the value of node come from.
+ * @name: Name of this link list node (maybe a node or an attribute in xml).
+ * @type: TYPE_NODE: Stands for the value from a xml node.
+ *        TYPE_PROP: Means that this value is an attribute of a node.
+ * @parent_id: The id of parent node.
+ * @parent_name: Name of parent node.
+ */
+static struct others *add_others(struct others *head,
+                          xmlNode *node,
+                          const xmlChar *name,
+                          enum others_type type,
+                          int parent_id,
+                          const xmlChar *parent_name)
+{
+        struct others *new = NULL;
+        struct others *end = head;
+
+        new = calloc(1, sizeof(*new));
+        if (new == NULL) {
+                CU_DEBUG("calloc space failed.");
+                return NULL;
+        }
+
+        new->id = 0;
+        new->name = strdup((char *)name);
+        new->parent_id = parent_id;
+        if (parent_name) {
+                new->parent_name = strdup((char *)parent_name);
+        }
+        new->type = type;
+        if (type == TYPE_PROP) {
+                new->value = get_attr_value(node, (char *)name);
+        } else if (type == TYPE_NODE) {
+                new->value = get_node_content(node);
+        }
+        new->next = NULL;
+
+        if (head == NULL) {
+                head = new;
+        } else {
+               /* Seek to the end of link list and calculate conflicts */
+                while (end) {
+                        if (STREQ(end->name, (char *)name) &&
+                            end->type == type) {
+                               /* id conflict, +1 */
+                                new->id++;
+                        }
+                        if (end->next) {
+                                end = end->next;
+                        } else {
+                                break;
+                        }
+                }
+                end->next = new;
+        }
+        new->status = ACTIVE;
+
+        return head;
+}
+
+bool compare_param_int(int a, int b)
+{
+        if (a == -1 || b == -1) {
+                return true;
+        } else if (a == b) {
+                return true;
+        } else {
+                return false;
+        }
+}
+
+bool compare_param_str(const char *a, const char *b)
+{
+        if (a == NULL || b == NULL) {
+                return true;
+        } else if (STREQ(a, b)) {
+                return true;
+        } else {
+                return false;
+        }
+}
+
+/*
+ * This function is the main operation for members of virtual device structure.
+ * The whole data of xml is saved in the others link list. By calling this
+ * function each variable of virtual device could get the value it wanted.
+ * After value was fetched, the node in the others link list to be INACTIVE
+ * status.
+ *
+ * @head: The link list saved all data needed.
+ * @id: Id of name, to identify different nodes but with same name.
+ * @name: Name of node the caller want to get value.
+ * @type: TYPE_NODE: Caller want to get a value of node.
+ *        TYPE_PROP: Caller want to get a value of attribute.
+ * @parent_id: The id of parent node caller want.
+ * @parent_name: The name of parent node caller want.
+ *
+ * If caller doesn't want to point @id, @parent_id or @parent_name,
+ * @id could be set as -1, @parent_id and @parent_name should be
+ * set as NULL.
+ */
+char *fetch_from_others(struct others **head,
+                        int id,
+                        char *name,
+                        enum others_type type,
+                        int parent_id,
+                        char *parent_name)
+{
+        struct others *tmp = *head;
+        char *value = NULL;
+
+        while (tmp) {
+                if (compare_param_int(tmp->id, id) &&
+                    STREQ(tmp->name, name) &&
+                    compare_param_int(tmp->parent_id, parent_id) &&
+                    compare_param_str(tmp->parent_name, parent_name) &&
+                    tmp->type == type &&
+                    tmp->status == ACTIVE) {
+                        value = strdup(tmp->value);
+                        tmp->status = INACTIVE;
+                        return value;
+                }
+                tmp = tmp->next;
+        }
+
+        return NULL;
+}
+
+/*
+ * This function seeks in the others link list and return the result of
+ * seeking. If success the node seeked will to be INACTIVE status.
+ *
+ * @head: The link list head pointer to be seeked.
+ * @id: Id of node to be seeked.
+ * @name: Name of node to be seeked.
+ * @type: TYPE_NODE: The node to be seeked is a node of xml.
+ *        TYPE_PROP: The node to be seeked is a attribute of a node.
+ * @parent_id: Id of parent node which to be seeked.
+ * @parent_name: Name of parent node which to be seeked.
+ *
+ * If the caller doesn't point @id, @parent_id or @parent_name, they should
+ * be set as -1, -1 or NULL. Other parameters is mandantory. 
+ */
+static bool seek_in_others(struct others **head,
+                           int id,
+                           char *name,
+                           enum others_type type,
+                           int parent_id,
+                           char *parent_name)
+{
+        struct others *tmp = *head;
+
+        while (tmp) {
+                if (compare_param_int(tmp->id, id) &&
+                    STREQ(tmp->name, name) &&
+                    compare_param_int(tmp->parent_id, parent_id) &&
+                    compare_param_str(tmp->parent_name, parent_name) &&
+                    tmp->type == type &&
+                    tmp->status == ACTIVE) {
+                        tmp->status = INACTIVE;
+                        return true;
+                }
+                tmp = tmp->next;
+        }
+
+        return false;
+}
+
+struct others *combine_others(struct others *head1,
+                              struct others *head2)
+{
+        struct others *tail1 = head1;
+
+        if (tail1 == NULL) {
+                return head2;
+        }
+
+        while (tail1->next) {
+                tail1 = tail1->next;
+        }
+
+        tail1->next = head2;
+        return head1;
+}
+
+static struct others *seek_to_tail(struct others *others)
+{
+        if (others == NULL) {
+                return NULL;
+        }
+
+        while (others->next) {
+                others = others->next;
+        }
+
+        return others;
+}
+
+/*
+ * Parse all data from xml and build a link list to save it.
+ *
+ * @head: Where data from xml to save.
+ * @node: The root node of xml to be parsed.
+ * @parent_id: Parent node id of root node, usually zero.
+ * @parent_name: Parent node name of root node.
+ */
+static struct others *parse_data_to_others(struct others *head,
+                                    xmlNode *node,
+                                    int parent_id,
+                                    const xmlChar *parent_name)
+{
+        xmlNode *child = NULL;
+        xmlAttrPtr attrPtr = NULL;
+        struct others *tail = NULL;
+        int tail_id = 0;
+
+        /* If name of node is "text", all operations will skip */
+        if (XSTREQ(node->name, "text")) {
+                return head;
+        }
+
+        head = add_others(head,
+                          node,
+                          node->name,
+                          TYPE_NODE,
+                          parent_id,
+                          parent_name);
+
+        if (head == NULL) {
+                goto err;
+        }
+
+        /* tail is the node we added above */
+        tail = seek_to_tail(head);
+        if (tail == NULL) {
+                tail_id = 0;
+        } else {
+                tail_id = tail->id;
+        }
+
+        /* Get properties of node */
+        attrPtr = node->properties;
+        while (attrPtr) {
+                head = add_others(head,
+                                  node,
+                                  attrPtr->name,
+                                  TYPE_PROP,
+                                  tail_id,
+                                  node->name);
+                if (head == NULL) {
+                        goto err;
+                }
+                                  
+                attrPtr = attrPtr->next;
+        }
+
+        for (child = node->children; child != NULL; child = child->next) {
+                /* Recursion to restore child's properties or child if have */
+                head = parse_data_to_others(head, child, tail_id, node->name);
+        }
+
+        return head;
+err:
+        CU_DEBUG("add_others failed.");
+        return NULL;
+}
+
 static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs)
 {
         struct virt_device *vdev = NULL;
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
index 147551a..ee9b515 100644
--- a/libxkutil/device_parsing.h
+++ b/libxkutil/device_parsing.h
@@ -48,10 +48,10 @@ struct others {
         enum others_type type;
         char *value;
         struct others *next;
-        enum status {
+        enum {
                 ACTIVE,
                 INACTIVE
-        };
+        } status;
 };
 
 /* The structure for saving unknown device */
@@ -310,6 +310,27 @@ int attach_device(virDomainPtr dom, struct virt_device *dev);
 int detach_device(virDomainPtr dom, struct virt_device *dev);
 int change_device(virDomainPtr dom, struct virt_device *dev);
 
+char *fetch_from_others(struct others **head,
+                        int id,
+                        char *name,
+                        enum others_type type,
+                        int parent_id,
+                        char *parent_name);
+
+void cleanup_node_of_others(struct others *others);
+
+bool compare_parent(const char *a, const char *b);
+
+void print_others(struct others *head);
+
+void cleanup_others(struct others *others);
+
+struct others *combine_others(struct others *head1, struct others *head2);
+
+bool compare_param_int(int a, int b);
+
+bool compare_param_str(const char *a, const char *b);
+
 #define XSTREQ(x, y) (STREQ((char *)x, y))
 #define STRPROP(d, p, n) (d->p = get_node_content(n))
 
-- 
1.7.1




More information about the Libvirt-cim mailing list