gator: Version 5.14
[android-sdk/arm-ds5-gator.git] / daemon / ConfigurationXML.cpp
1 /**
2  * Copyright (C) ARM Limited 2010-2013. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
9 #include <string.h>
10 #include <stdlib.h>
11 #include <dirent.h>
12 #include "ConfigurationXML.h"
13 #include "Driver.h"
14 #include "Logging.h"
15 #include "OlyUtility.h"
16 #include "SessionData.h"
18 static const char* ATTR_COUNTER           = "counter";
19 static const char* ATTR_REVISION          = "revision";
20 static const char* ATTR_TITLE             = "title";
21 static const char* ATTR_NAME              = "name";
22 static const char* ATTR_EVENT             = "event";
23 static const char* ATTR_COUNT             = "count";
24 static const char* ATTR_PER_CPU           = "per_cpu";
25 static const char* ATTR_DESCRIPTION       = "description";
26 static const char* ATTR_EBS               = "supports_event_based_sampling";
27 static const char* ATTR_DISPLAY           = "display";
28 static const char* ATTR_UNITS             = "units";
29 static const char* ATTR_MODIFIER          = "modifier";
30 static const char* ATTR_AVERAGE_SELECTION = "average_selection";
32 ConfigurationXML::ConfigurationXML() {
33         const char * configuration_xml;
34         unsigned int configuration_xml_len;
35         getDefaultConfigurationXml(configuration_xml, configuration_xml_len);
36         
37         char path[PATH_MAX];
39         if (gSessionData->mConfigurationXMLPath) {
40                 strncpy(path, gSessionData->mConfigurationXMLPath, PATH_MAX);
41         } else {
42                 if (util->getApplicationFullPath(path, PATH_MAX) != 0) {
43                         logg->logMessage("Unable to determine the full path of gatord, the cwd will be used");
44                 }
45                 strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1);
46         }
47         mConfigurationXML = util->readFromDisk(path);
49         for (int retryCount = 0; retryCount < 2; ++retryCount) {
50                 if (mConfigurationXML == NULL) {
51                         logg->logMessage("Unable to locate configuration.xml, using default in binary");
52                         // null-terminate configuration_xml
53                         mConfigurationXML = (char*)malloc(configuration_xml_len + 1);
54                         memcpy(mConfigurationXML, (const void*)configuration_xml, configuration_xml_len);
55                         mConfigurationXML[configuration_xml_len] = 0;
56                 }
58                 int ret = parse(mConfigurationXML);
59                 if (ret == 1) {
60                         // remove configuration.xml on disk to use the default
61                         if (remove(path) != 0) {
62                                 logg->logError(__FILE__, __LINE__, "Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk");
63                                 handleException();
64                         }
65                         logg->logMessage("Invalid configuration.xml file detected and removed");
67                         // Free the current configuration and reload
68                         free((void*)mConfigurationXML);
69                         mConfigurationXML = NULL;
70                         continue;
71                 }
73                 break;
74         }
75         
76         validate();
77 }
79 ConfigurationXML::~ConfigurationXML() {
80         if (mConfigurationXML) {
81                 free((void*)mConfigurationXML);
82         }
83 }
85 int ConfigurationXML::parse(const char* configurationXML) {
86         mxml_node_t *tree, *node;
87         int ret;
89         // clear counter overflow
90         gSessionData->mCounterOverflow = false;
91         mIndex = 0;
93         // disable all counters prior to parsing the configuration xml
94         for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
95                 gSessionData->mCounters[i].setEnabled(false);
96         }
98         tree = mxmlLoadString(NULL, configurationXML, MXML_NO_CALLBACK);
100         node = mxmlGetFirstChild(tree);
101         while (node && mxmlGetType(node) != MXML_ELEMENT)
102                 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
103         
104         ret = configurationsTag(node);
106         node = mxmlGetFirstChild(node);
107         while (node) {
108                 if (mxmlGetType(node) != MXML_ELEMENT) {
109                         node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
110                         continue;
111                 }
112                 configurationTag(node);
113                 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
114         }
116         mxmlDelete(tree);
118         return ret;
121 void ConfigurationXML::validate(void) {
122         for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
123                 const Counter & counter = gSessionData->mCounters[i];
124                 if (counter.isEnabled()) {
125                         if (strcmp(counter.getType(), "") == 0) {
126                                 logg->logError(__FILE__, __LINE__, "Invalid required attribute in configuration.xml:\n  counter=\"%s\"\n  title=\"%s\"\n  name=\"%s\"\n  event=%d\n", counter.getType(), counter.getTitle(), counter.getName(), counter.getEvent());
127                                 handleException();
128                         }
130                         // iterate through the remaining enabled performance counters
131                         for (int j = i + 1; j < MAX_PERFORMANCE_COUNTERS; j++) {
132                                 const Counter & counter2 = gSessionData->mCounters[j];
133                                 if (counter2.isEnabled()) {
134                                         // check if the types are the same
135                                         if (strcmp(counter.getType(), counter2.getType()) == 0) {
136                                                 logg->logError(__FILE__, __LINE__, "Duplicate performance counter type in configuration.xml: %s", counter.getType());
137                                                 handleException();
138                                         }
139                                 }
140                         }
141                 }
142         }
145 #define CONFIGURATION_REVISION 2
146 int ConfigurationXML::configurationsTag(mxml_node_t *node) {
147         const char* revision_string;
148         
149         revision_string = mxmlElementGetAttr(node, ATTR_REVISION);
150         if (!revision_string) {
151                 return 1; //revision issue;
152         }
154         int revision = strtol(revision_string, NULL, 10);
155         if (revision < CONFIGURATION_REVISION) {
156                 return 1; // revision issue
157         }
159         return 0;
162 void ConfigurationXML::configurationTag(mxml_node_t *node) {
163         // handle all other performance counters
164         if (mIndex >= MAX_PERFORMANCE_COUNTERS) {
165                 gSessionData->mCounterOverflow = true;
166                 return;
167         }
169         // read attributes
170         Counter & counter = gSessionData->mCounters[mIndex];
171         counter.clear();
172         if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER));
173         if (mxmlElementGetAttr(node, ATTR_TITLE)) counter.setTitle(mxmlElementGetAttr(node, ATTR_TITLE));
174         if (mxmlElementGetAttr(node, ATTR_NAME)) counter.setName(mxmlElementGetAttr(node, ATTR_NAME));
175         if (mxmlElementGetAttr(node, ATTR_DESCRIPTION)) counter.setDescription(mxmlElementGetAttr(node, ATTR_DESCRIPTION));
176         if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16));
177         if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10));
178         if (mxmlElementGetAttr(node, ATTR_PER_CPU)) counter.setPerCPU(util->stringToBool(mxmlElementGetAttr(node, ATTR_PER_CPU), false));
179         if (mxmlElementGetAttr(node, ATTR_EBS)) counter.setEBSCapable(util->stringToBool(mxmlElementGetAttr(node, ATTR_EBS), false));
180         if (mxmlElementGetAttr(node, ATTR_DISPLAY)) counter.setDisplay(mxmlElementGetAttr(node, ATTR_DISPLAY));
181         if (mxmlElementGetAttr(node, ATTR_UNITS)) counter.setUnits(mxmlElementGetAttr(node, ATTR_UNITS));
182         if (mxmlElementGetAttr(node, ATTR_MODIFIER)) counter.setModifier(strtol(mxmlElementGetAttr(node, ATTR_MODIFIER), NULL, 10));
183         if (mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION)) counter.setAverageSelection(util->stringToBool(mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION), false));
184         counter.setEnabled(true);
186         // Associate a driver with each counter
187         for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
188                 if (driver->claimCounter(counter)) {
189                         if (counter.getDriver() != NULL) {
190                                 logg->logError(__FILE__, __LINE__, "More than one driver has claimed %s: %s", counter.getTitle(), counter.getName());
191                                 handleException();
192                         }
193                         counter.setDriver(driver);
194                 }
195         }
197         // If no driver is associated with the counter, disable it
198         if (counter.getDriver() == NULL) {
199                 logg->logMessage("No driver has claimed %s (%s: %s)", counter.getType(), counter.getTitle(), counter.getName());
200                 counter.setEnabled(false);
201         }
203         // update counter index
204         mIndex++;
207 void ConfigurationXML::getDefaultConfigurationXml(const char * & xml, unsigned int & len) {
208 #include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
209         xml = (const char *)configuration_xml;
210         len = configuration_xml_len;