• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdlib.h>
17 
18 #include "test-malloc-info-stats-print.h"
19 #include "libxml/parser.h"
20 
get_text_from_children(xmlNodePtr children)21 static const xmlChar *get_text_from_children(xmlNodePtr children)
22 {
23 	for (xmlNodePtr child_node = children; child_node != NULL; child_node = child_node->next) {
24 		if (child_node->type == XML_TEXT_NODE) {
25 			return child_node->content;
26 		}
27 	}
28 	return NULL;
29 }
30 
get_attribute(const char * attr_name,xmlNodePtr node)31 static const xmlChar *get_attribute(const char *attr_name, xmlNodePtr node)
32 {
33 	for (xmlAttrPtr curr_attr = node->properties; curr_attr != NULL; curr_attr = curr_attr->next) {
34 		if (xmlStrEqual(curr_attr->name, (const xmlChar *) attr_name)) {
35 			return get_text_from_children(curr_attr->children);
36 		}
37 	}
38 	return NULL;
39 }
40 
find_child_node_with_attr(const char * name,const char * attr_name,const char * attr_value,xmlNodePtr parent)41 static xmlNodePtr find_child_node_with_attr(const char *name, const char *attr_name, const char *attr_value, xmlNodePtr parent)
42 {
43 	if (parent == NULL) {
44 		return NULL;
45 	}
46 	for (xmlNodePtr curr_node = parent->children; curr_node != NULL; curr_node = curr_node->next) {
47 		if (curr_node->type == XML_ELEMENT_NODE && xmlStrEqual(curr_node->name, (xmlChar *) name)) {
48 			if (attr_name == NULL) {
49 				return curr_node;
50 			}
51 			if (xmlStrEqual(get_attribute(attr_name, curr_node), (const xmlChar *) attr_value)) {
52 				return curr_node;
53 			}
54 		}
55 	}
56 	return NULL;
57 }
58 
find_child_node(const char * name,xmlNodePtr parent)59 static xmlNodePtr find_child_node(const char *name, xmlNodePtr parent)
60 {
61 	return find_child_node_with_attr(name, NULL, NULL, parent);
62 }
63 
get_node_text(xmlNodePtr node_ptr)64 static const char *get_node_text(xmlNodePtr node_ptr)
65 {
66 	if (node_ptr == NULL) {
67 		return NULL;
68 	}
69 	return (const char *) get_text_from_children(node_ptr->children);
70 }
71 
stderr_stats_cb(void)72 static void stderr_stats_cb(void)
73 {
74 	malloc_info(0, stderr);
75 }
76 
parse_amount(const char * s)77 static long long parse_amount(const char *s)
78 {
79 	if (s == NULL) {
80 		return -1;
81 	}
82 	char *end_ptr;
83 	long long result = strtoll(s, &end_ptr, 10);
84 	if (end_ptr != s + strlen(s)) {
85 		return -1;
86 	}
87 	if (result < 0) {
88 		return -1;
89 	}
90 	return result;
91 }
92 
find_thread_in_document(xmlDocPtr doc_ptr,const char * thread_id)93 static xmlNodePtr find_thread_in_document(xmlDocPtr doc_ptr, const char *thread_id)
94 {
95 	xmlNodePtr root_element = xmlDocGetRootElement(doc_ptr);
96 	return find_child_node_with_attr("thread", "id", thread_id, find_child_node("threads", root_element));
97 }
98 
populate_thread_stats(const char * output,const char * thread_id,malloc_thread_stats_t * stats)99 static int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats)
100 {
101 	xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
102 	if (doc_ptr == NULL) {
103 		return 0;
104 	}
105 	xmlNodePtr thread_root = find_thread_in_document(doc_ptr, thread_id);
106 	long long total_allocated_memory =
107 		parse_amount(get_node_text(find_child_node("total_allocated_memory", thread_root)));
108 	long long total_mmapped_memory =
109 		parse_amount(get_node_text(find_child_node("total_mmapped_memory", thread_root)));
110 	long long mmapped_regions =
111 		parse_amount(get_node_text(find_child_node("mmapped_regions", thread_root)));
112 	xmlFreeDoc(doc_ptr);
113 
114 	if (total_allocated_memory == -1 || total_mmapped_memory == -1 || mmapped_regions == -1) {
115 		return 0;
116 	}
117 	stats->total_allocated_memory = total_allocated_memory;
118 	stats->total_mmapped_memory = total_mmapped_memory;
119 	stats->mmapped_regions = mmapped_regions;
120 	return 1;
121 }
122 
populate_total_free_heap_space(const char * output,long long * total_free_heap_space)123 static int populate_total_free_heap_space(const char *output, long long *total_free_heap_space)
124 {
125 	xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
126 	if (doc_ptr == NULL) {
127 		return 0;
128 	}
129 	xmlNodePtr heap_space_root = find_child_node("total_free_heap_space", xmlDocGetRootElement(doc_ptr));
130 	long long total_free_heap_space_parsed = parse_amount(get_node_text(heap_space_root));
131 	xmlFreeDoc(doc_ptr);
132 
133 	if (total_free_heap_space_parsed == -1) {
134 		return 0;
135 	}
136 	*total_free_heap_space = total_free_heap_space_parsed;
137 	return 1;
138 }
139 
is_thread_in_output(const char * output,const char * thread_id)140 static int is_thread_in_output(const char *output, const char *thread_id)
141 {
142 	xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
143 	if (doc_ptr == NULL) {
144 		return 0;
145 	}
146 	int result = find_thread_in_document(doc_ptr, thread_id) != NULL;
147 	xmlFreeDoc(doc_ptr);
148 	return result;
149 }
150