
Signed-off-by: Xu Wang <gesaint@linux.vnet.ibm.com> --- libxkutil/xmlgen.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 231 insertions(+), 0 deletions(-) diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c index 7e8801d..d1e1c94 100644 --- a/libxkutil/xmlgen.c +++ b/libxkutil/xmlgen.c @@ -42,6 +42,237 @@ typedef const char *(*devfn_t)(xmlNodePtr node, struct domain *dominfo); typedef const char *(*poolfn_t)(xmlNodePtr node, struct virt_pool *pool); typedef const char *(*resfn_t)(xmlNodePtr node, struct virt_pool_res *res); +/* + * Parse all attributes of node into xml. + * + * @node: The root node. + * @head: The link list saved all data to be parsed. + * @parent_id: Node id of attributes. + * @parent_name: Node name of attributes. + * + * If @parent_id or @parent_name is not as a condition, plese set them into + * -1 or NULL. + */ +static struct others *props_to_xml(xmlNodePtr node, + struct others *head, + int parent_id, + const char *parent_name) +{ + struct others *tmp = head; + + if (head == NULL) { + CU_DEBUG("others is null."); + goto out; + } + + while (tmp) { + if (compare_param_int(tmp->parent_id, parent_id) && + compare_param_str(tmp->parent_name, parent_name) && + tmp->type == TYPE_PROP && + tmp->status == ACTIVE) { + xmlNewProp(node, BAD_CAST tmp->name, BAD_CAST tmp->value); + tmp->status = INACTIVE; + } + tmp = tmp->next; + } + +out: + return head; +} + +/* + * Parse all data in others link list to a xml data structure. + * The link list returned after operation. + * + * @root: The root node of xml to be built. + * @head: The link list saved all data needed. + * @parent_id: Parent node id of root node. + * @parent_name: Parent node name of root node. + * + * @parent_id/@parent_name is not mandatory (please set them + * as -1/NULL) but others not. + */ +static struct others *others_to_xml(xmlNodePtr root, + struct others *head, + int parent_id, + const char *parent_name) +{ + struct others *tmp = head; + xmlNodePtr new_node = NULL; + + if (head == NULL) { + CU_DEBUG("others is null."); + goto out; + } + + /* fetch all node items from others to build structure of xml */ + while (tmp) { + if (compare_param_int(tmp->parent_id, parent_id) && + compare_param_str(tmp->parent_name, parent_name) && + tmp->type == TYPE_NODE && + tmp->status == ACTIVE) { + new_node = xmlNewChild(root, NULL, + BAD_CAST tmp->name, + BAD_CAST tmp->value); + + if (new_node == NULL) { + CU_DEBUG("xmlNewChild failed."); + goto out; + } + + tmp->status = INACTIVE; + + /* find all properties of this node and build new tag in xml */ + head = props_to_xml(new_node, + head, + tmp->id, + (char *)new_node->name); + + /* recursive build sub node of tmp */ + head = others_to_xml(new_node, + head, + tmp->id, + (char *)new_node->name); + + } + tmp = tmp->next; + } + +out: + return head; +} + +/* + * Restore data in the member of virtual device structure back to others link + * list. The new link list would be returned after operation finished. + * + * @head: The link list data to be added into. + * @id: Id of new node to be added. + * @name: Name of new node to be added. + * @value: Value of new node to be added. + * @type: Type of new node to be added. + * TYPE_NODE: The value is from a node of xml. + * TYPE_PROP: The value is from a attribute of a node. + * @parent_id: Parent node id of new node to be added. + * @parent_name: Parent node name of new node to be added. + * + * Among parameters above @id/@parent_id/@parent_name is not + * mandatory. They should be set as -1/-1/NULL if caller needn't + * set them. + */ +static struct others *add_node_to_others(struct others *head, + int id, + const char *name, + const char *value, + enum others_type type, + int parent_id, + const char *parent_name) +{ + struct others *tmp = head; + struct others *new_node = NULL; + + /* Check if there is such a node with INACTIVE status in others */ + while (tmp) { + if (compare_param_int(tmp->id, id) && + STREQ(tmp->name, name) && + tmp->type == type && + compare_param_int(tmp->parent_id, parent_id) && + compare_param_str(tmp->parent_name, parent_name) && + tmp->status == INACTIVE) { + if (tmp->value) { + free(tmp->value); + } + if (value) { + tmp->value = strdup(value); + } else { + tmp->value = NULL; + } + tmp->status = ACTIVE; + + return head; + } + tmp = tmp->next; + } + + /* Create a new node */ + new_node = calloc(1, sizeof(*new_node)); + if (new_node == NULL) { + CU_DEBUG("calloc failed."); + return NULL; + } + + new_node->id = id; + + if (name == NULL) { + CU_DEBUG("name is null"); + return NULL; + } + new_node->name = strdup(name); + + if (value) { + new_node->value = strdup(value); + } else { + new_node->value = NULL; + } + + new_node->type = type; + + new_node->parent_id = parent_id; + + if (parent_name) { + new_node->parent_name = strdup(parent_name); + } else { + new_node->parent_name = NULL; + } + + if (head == NULL) { + new_node->next = NULL; + } else { + new_node->next = head; + } + + return new_node; +} + +static int get_id_of_others(struct others *others, + const char *name, + const char *value, + enum others_type type, + int parent_id, + const char *parent_name) +{ + struct others *tmp = others; + + while (tmp) { + if (STREQ(tmp->name, name) && + compare_param_str(tmp->value, value) && + tmp->type == type && + compare_param_int(tmp->parent_id, parent_id) && + compare_param_str(tmp->parent_name, parent_name)) { + return tmp->id; + } + tmp = tmp->next; + } + + return -1; +} + +/* + * Check if there is node(s) with ACTIVE status. If such node(s) exists + * means operation failed. Some node of xml missed. + */ +static const char *check_others_active(struct others *others) +{ + while (others) { + if (others->status == ACTIVE) { + return "There are active nodes in others."; + } + others = others->next; + } + + return NULL; +} + static const char *console_xml(xmlNodePtr root, struct domain *dominfo) { int i; -- 1.7.1