#include "fsfw/events/eventmatching/EventMatchTree.h" #include "fsfw/events/eventmatching/EventIdRangeMatcher.h" #include "fsfw/events/eventmatching/ReporterRangeMatcher.h" #include "fsfw/events/eventmatching/SeverityRangeMatcher.h" EventMatchTree::EventMatchTree(StorageManagerIF* storageBackend, bool invertedMatch) : MatchTree(end(), 1), factory(storageBackend), invertedMatch(invertedMatch) {} EventMatchTree::~EventMatchTree() {} bool EventMatchTree::match(EventMessage* number) { if (invertedMatch) { return !MatchTree::match(number); } else { return MatchTree::match(number); } } ReturnValue_t EventMatchTree::addMatch(EventId_t idFrom, EventId_t idTo, bool idInverted, object_id_t reporterFrom, object_id_t reporterTo, bool reporterInverted) { if (idFrom == 0) { // Assuming all events shall be forwarded. idTo = 0; idInverted = true; } if (idTo == 0) { idTo = idFrom; } iterator lastTest; ReturnValue_t result = findOrInsertRangeMatcher( begin(), idFrom, idTo, idInverted, &lastTest); if (result != returnvalue::OK) { return result; } if (reporterFrom == 0) { // No need to add another AND branch return returnvalue::OK; } if (reporterTo == 0) { reporterTo = reporterFrom; } return findOrInsertRangeMatcher( lastTest.left(), reporterFrom, reporterTo, reporterInverted, &lastTest); } ReturnValue_t EventMatchTree::removeMatch(EventId_t idFrom, EventId_t idTo, bool idInverted, object_id_t reporterFrom, object_id_t reporterTo, bool reporterInverted) { iterator foundElement; if (idFrom == 0) { // Assuming a "forward all events" request. idTo = 0; idInverted = true; } if (idTo == 0) { idTo = idFrom; } foundElement = findRangeMatcher(begin(), idFrom, idTo, idInverted); if (foundElement == end()) { return NO_MATCH; // Can't tell if too detailed or just not found. } if (reporterFrom == 0) { if (foundElement.left() == end()) { return removeElementAndReconnectChildren(foundElement); } else { return TOO_GENERAL_REQUEST; } } if (reporterTo == 0) { reporterTo = reporterFrom; } foundElement = findRangeMatcher( foundElement.left(), reporterFrom, reporterTo, reporterInverted); if (foundElement == end()) { return NO_MATCH; } else { return removeElementAndReconnectChildren(foundElement); } } template inline ReturnValue_t EventMatchTree::findOrInsertRangeMatcher(iterator start, VALUE_T idFrom, VALUE_T idTo, bool inverted, iterator* lastTest) { bool attachToBranch = AND; iterator iter = start; while (iter != end()) { INSERTION_T* matcher = static_cast(*iter); attachToBranch = OR; *lastTest = iter; if ((matcher->rangeMatcher.lowerBound == idFrom) && (matcher->rangeMatcher.upperBound == idTo) && (matcher->rangeMatcher.inverted == inverted)) { return returnvalue::OK; } else { iter = iter.right(); } } // Only reached if nothing was found. SerializeableMatcherIF* newContent = factory.generate(idFrom, idTo, inverted); if (newContent == NULL) { return FULL; } Node* newNode = factory.generate(newContent); if (newNode == NULL) { // Need to make sure partially generated content is deleted, otherwise, that's a leak. factory.destroy(static_cast(newContent)); return FULL; } *lastTest = insert(attachToBranch, *lastTest, newNode); if (*lastTest == end()) { // This actaully never fails, so creating a dedicated returncode seems an overshoot. return returnvalue::FAILED; } return returnvalue::OK; } template EventMatchTree::iterator EventMatchTree::findRangeMatcher(iterator start, VALUE_T idFrom, VALUE_T idTo, bool inverted) { iterator iter = start; while (iter != end()) { INSERTION_T* matcher = static_cast(*iter); if ((matcher->rangeMatcher.lowerBound == idFrom) && (matcher->rangeMatcher.upperBound == idTo) && (matcher->rangeMatcher.inverted == inverted)) { break; } else { iter = iter.right(); // next OR element } } return iter; } ReturnValue_t EventMatchTree::cleanUpElement(iterator position) { factory.destroy(position.element->value); // If deletion fails, delete element anyway, nothing we can do. // SHOULDO: Throw event, or write debug output. return factory.destroy(position.element); }