From abc3535c0d237bf7968b7092e545f2ff422af954 Mon Sep 17 00:00:00 2001 From: Drew Richardson Date: Sat, 28 Mar 2015 12:00:00 -0700 Subject: gator: Version 5.21 Signed-off-by: Drew Richardson --- daemon/EventsXML.cpp | 179 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 167 insertions(+), 12 deletions(-) (limited to 'daemon/EventsXML.cpp') diff --git a/daemon/EventsXML.cpp b/daemon/EventsXML.cpp index d905bba..3fe5ecd 100644 --- a/daemon/EventsXML.cpp +++ b/daemon/EventsXML.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) ARM Limited 2013-2014. All rights reserved. + * Copyright (C) ARM Limited 2013-2015. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,10 +13,35 @@ #include "OlyUtility.h" #include "SessionData.h" +class XMLList { +public: + XMLList(XMLList *const prev, mxml_node_t *const node) : mPrev(prev), mNode(node) {} + + XMLList *getPrev() { return mPrev; } + mxml_node_t *getNode() const { return mNode; } + void setNode(mxml_node_t *const node) { mNode = node; } + + static void free(XMLList *list) { + while (list != NULL) { + XMLList *prev = list->getPrev(); + delete list; + list = prev; + } + } + +private: + XMLList *const mPrev; + mxml_node_t *mNode; + + // Intentionally unimplemented + XMLList(const XMLList &); + XMLList &operator=(const XMLList &); +}; + mxml_node_t *EventsXML::getTree() { #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len char path[PATH_MAX]; - mxml_node_t *xml; + mxml_node_t *xml = NULL; FILE *fl; // Avoid unused variable warning @@ -25,19 +50,147 @@ mxml_node_t *EventsXML::getTree() { // Load the provided or default events xml if (gSessionData->mEventsXMLPath) { strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX); - } else { - util->getApplicationFullPath(path, PATH_MAX); - strncat(path, "events.xml", PATH_MAX - strlen(path) - 1); + fl = fopen(path, "r"); + if (fl) { + xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); + fclose(fl); + } } - fl = fopen(path, "r"); - if (fl) { - xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); - fclose(fl); - } else { + if (xml == NULL) { logg->logMessage("Unable to locate events.xml, using default"); xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); } + // Append additional events XML + if (gSessionData->mEventsXMLAppend) { + fl = fopen(gSessionData->mEventsXMLAppend, "r"); + if (fl == NULL) { + logg->logError("Unable to open additional events XML %s", gSessionData->mEventsXMLAppend); + handleException(); + } + mxml_node_t *append = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); + fclose(fl); + + mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); + if (!events) { + logg->logError("Unable to find node in the events.xml, please ensure the first two lines of events XML starts with:\n" + "\n" + ""); + handleException(); + } + + XMLList *categoryList = NULL; + XMLList *eventList = NULL; + { + // Make list of all categories in xml + mxml_node_t *node = xml; + while (true) { + node = mxmlFindElement(node, xml, "category", NULL, NULL, MXML_DESCEND); + if (node == NULL) { + break; + } + categoryList = new XMLList(categoryList, node); + } + + // Make list of all events in xml + node = xml; + while (true) { + node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); + if (node == NULL) { + break; + } + eventList = new XMLList(eventList, node); + } + } + + // Handle events + for (mxml_node_t *node = mxmlFindElement(append, append, "event", NULL, NULL, MXML_DESCEND), + *next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND); + node != NULL; + node = next, next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND)) { + const char *const category = mxmlElementGetAttr(mxmlGetParent(node), "name"); + const char *const title = mxmlElementGetAttr(node, "title"); + const char *const name = mxmlElementGetAttr(node, "name"); + if (category == NULL || title == NULL || name == NULL) { + logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); + handleException(); + } + + // Replace any duplicate events + for (XMLList *event = eventList; event != NULL; event = event->getPrev()) { + const char *const category2 = mxmlElementGetAttr(mxmlGetParent(event->getNode()), "name"); + const char *const title2 = mxmlElementGetAttr(event->getNode(), "title"); + const char *const name2 = mxmlElementGetAttr(event->getNode(), "name"); + if (category2 == NULL || title2 == NULL || name2 == NULL) { + logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); + handleException(); + } + + if (strcmp(category, category2) == 0 && strcmp(title, title2) == 0 && strcmp(name, name2) == 0) { + logg->logMessage("Replacing counter %s %s: %s", category, title, name); + mxml_node_t *parent = mxmlGetParent(event->getNode()); + mxmlDelete(event->getNode()); + mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); + event->setNode(node); + break; + } + } + } + + // Handle categories + for (mxml_node_t *node = mxmlFindElement(append, append, "category", NULL, NULL, MXML_DESCEND), + *next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND); + node != NULL; + node = next, next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND)) { + // After replacing duplicate events, a category may be empty + if (mxmlGetFirstChild(node) == NULL) { + continue; + } + + const char *const name = mxmlElementGetAttr(node, "name"); + if (name == NULL) { + logg->logError("Not all event XML categories have the required name attribute"); + handleException(); + } + + // Merge identically named categories + bool merged = false; + for (XMLList *category = categoryList; category != NULL; category = category->getPrev()) { + const char *const name2 = mxmlElementGetAttr(category->getNode(), "name"); + if (name2 == NULL) { + logg->logError("Not all event XML categories have the required name attribute"); + handleException(); + } + + if (strcmp(name, name2) == 0) { + logg->logMessage("Merging category %s", name); + while (true) { + mxml_node_t *child = mxmlGetFirstChild(node); + if (child == NULL) { + break; + } + mxmlAdd(category->getNode(), MXML_ADD_AFTER, mxmlGetLastChild(category->getNode()), child); + } + merged = true; + break; + } + } + + if (merged) { + continue; + } + + // Add new categories + logg->logMessage("Appending category %s", name); + mxmlAdd(events, MXML_ADD_AFTER, mxmlGetLastChild(events), node); + } + + XMLList::free(eventList); + XMLList::free(categoryList); + + mxmlDelete(append); + } + return xml; } @@ -47,7 +200,9 @@ char *EventsXML::getXML() { // Add dynamic events from the drivers mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); if (!events) { - logg->logError(__FILE__, __LINE__, "Unable to find node in the events.xml"); + logg->logError("Unable to find node in the events.xml, please ensure the first two lines of events XML are:\n" + "\n" + ""); handleException(); } for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) { @@ -68,7 +223,7 @@ void EventsXML::write(const char *path) { char *buf = getXML(); if (util->writeToDisk(file, buf) < 0) { - logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); + logg->logError("Error writing %s\nPlease verify the path.", file); handleException(); } -- cgit v1.2.3