
From: Xu Wang <cngesaint@gmail.com> Signed-off-by: Xu Wang <gesaint@linux.vnet.ibm.com> --- libxkutil/device_parsing.c | 297 +++++++++++++++++++++++++++++++++++++++++++++ libxkutil/device_parsing.h | 17 +++ 2 files changed, 314 insertions(+) diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c index 6cdcfa9..610712f 100644 --- a/libxkutil/device_parsing.c +++ b/libxkutil/device_parsing.c @@ -452,6 +452,303 @@ static int parse_device_address(xmlNode *anode, struct device_address *devaddr) return 0; } +/* + * 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 mandatory. + */ +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 603f29a..92d8638 100644 --- a/libxkutil/device_parsing.h +++ b/libxkutil/device_parsing.h @@ -299,6 +299,23 @@ 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); + +bool compare_parent(const char *a, const char *b); + +void print_others(struct others *head); + +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.8.3.1