File indexing completed on 2023-03-17 10:59:07
0001 #include "TriggerSelector.h"
0002
0003 #include "DataFormats/Common/interface/HLTPathStatus.h"
0004 #include "DataFormats/Common/interface/TriggerResults.h"
0005 #include "FWCore/Framework/interface/EventSelector.h"
0006 #include "FWCore/Framework/interface/TriggerNamesService.h"
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008 #include "FWCore/Utilities/interface/RegexMatch.h"
0009
0010 #include <iostream>
0011 #include <algorithm>
0012
0013 #include <boost/regex.hpp>
0014
0015 namespace dqmservices {
0016
0017
0018
0019 TriggerSelector::TriggerSelector(Strings const& pathspecs, Strings const& triggernames) : useOld_(true) {
0020 acceptAll_ = false;
0021 eventSelector_.reset(new edm::EventSelector(pathspecs, triggernames));
0022 }
0023
0024 TriggerSelector::TriggerSelector(std::string const& expression, Strings const& triggernames) : useOld_(false) {
0025 init(trim(expression), triggernames);
0026 }
0027
0028 void TriggerSelector::init(std::string const& expression, Strings const& triggernames) {
0029
0030 if (expression.empty()) {
0031 acceptAll_ = true;
0032 return;
0033 }
0034 if (expression.size() == 1 && expression.at(0) == '*')
0035 acceptAll_ = true;
0036 else
0037 acceptAll_ = false;
0038
0039
0040 {
0041 using namespace boost;
0042 std::string temp;
0043 temp = regex_replace(expression, regex(".AND."), "&&");
0044 expression_ = regex_replace(temp, regex(".and."), "&&");
0045 temp = regex_replace(expression_, regex(".OR."), "||");
0046 expression_ = regex_replace(temp, regex(".or."), "||");
0047 }
0048
0049
0050 masterElement_.reset(new TreeElement(expression_, triggernames));
0051 }
0052
0053 bool TriggerSelector::acceptEvent(edm::TriggerResults const& tr) const {
0054 if (useOld_) {
0055 return eventSelector_->acceptEvent(tr);
0056 }
0057
0058 if (acceptAll_)
0059 return true;
0060
0061 return masterElement_->returnStatus(tr);
0062 }
0063
0064 bool TriggerSelector::acceptEvent(unsigned char const* array_of_trigger_results, int number_of_trigger_paths) const {
0065 if (useOld_)
0066 return eventSelector_->acceptEvent(array_of_trigger_results, number_of_trigger_paths);
0067
0068 if (acceptAll_)
0069 return true;
0070
0071
0072 edm::HLTGlobalStatus tr(number_of_trigger_paths);
0073 int byteIndex = 0;
0074 int subIndex = 0;
0075 for (int pathIndex = 0; pathIndex < number_of_trigger_paths; ++pathIndex) {
0076 int state = array_of_trigger_results[byteIndex] >> (subIndex * 2);
0077 state &= 0x3;
0078 edm::HLTPathStatus pathStatus(static_cast<edm::hlt::HLTState>(state));
0079 tr[pathIndex] = pathStatus;
0080 ++subIndex;
0081 if (subIndex == 4) {
0082 ++byteIndex;
0083 subIndex = 0;
0084 }
0085 }
0086
0087
0088 masterElement_->returnStatus(tr);
0089 return masterElement_->returnStatus(tr);
0090 }
0091
0092 TriggerSelector::TreeElement::TreeElement(std::string const& inputString,
0093 Strings const& tr,
0094 TreeElement* parentElement)
0095 : op_(NonInit), trigBit_(-1) {
0096 std::string str_ = trim(inputString);
0097 children_.clear();
0098 parent_ = parentElement;
0099
0100 size_t offset_ = 0;
0101 bool occurrences_ = false;
0102
0103 if (str_.empty())
0104 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (empty element)";
0105
0106 static const size_t bopsSize_ = 2;
0107 static const std::string binaryOperators_[bopsSize_] = {"||", "&&"};
0108
0109 for (size_t opr = 0; opr < bopsSize_; opr++) {
0110 bool exitloop_ = false;
0111 while (!exitloop_) {
0112 size_t t_end_;
0113
0114 std::string tmpStr = str_.substr(offset_);
0115 t_end_ = tmpStr.find(binaryOperators_[opr]);
0116 if (debug_)
0117 std::cout << "offset: " << offset_ << " length: " << t_end_ << " string: " << tmpStr << std::endl;
0118
0119 if (t_end_ == std::string::npos) {
0120
0121 if (occurrences_)
0122 children_.push_back(new TreeElement(tmpStr, tr, this));
0123 break;
0124 }
0125 t_end_ += offset_;
0126 if (t_end_ == 0 || t_end_ + 2 >= str_.size())
0127 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
0128 else {
0129
0130 size_t brackets_ = 0;
0131 for (size_t k = offset_; k < t_end_; k++) {
0132 if (str_.at(k) == '(') {
0133 brackets_++;
0134 } else if (str_.at(k) == ')') {
0135 if (brackets_ == 0) {
0136 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0137 } else {
0138 brackets_--;
0139 }
0140 }
0141 }
0142 if (brackets_ == 0) {
0143 std::string next = str_.substr(offset_, t_end_ - offset_);
0144 children_.push_back(new TreeElement(next, tr, this));
0145 occurrences_ = true;
0146 offset_ = t_end_ + 2;
0147 } else {
0148
0149 int bracketcnt_ = 0;
0150 for (size_t k = offset_; true; k++) {
0151 if (k >= str_.size()) {
0152 if (bracketcnt_ != 0)
0153 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0154 exitloop_ = true;
0155 if (occurrences_) {
0156 children_.push_back(new TreeElement(str_.substr(offset_), tr, this));
0157 }
0158 break;
0159 }
0160
0161 if (k >= t_end_ + 2 && bracketcnt_ == 0) {
0162 std::string temp = str_.substr(k);
0163 size_t pos = temp.find(binaryOperators_[opr]);
0164 if (pos == std::string::npos) {
0165 exitloop_ = true;
0166 if (occurrences_) {
0167 children_.push_back(new TreeElement(str_.substr(offset_), tr, this));
0168 }
0169 break;
0170 } else {
0171 int brcount_ = 0;
0172 for (size_t s = 0; s < pos; s++) {
0173
0174 if (temp.at(pos) == '(') {
0175 brcount_++;
0176 } else if (temp.at(pos) == ')') {
0177 if (brcount_ == 0) {
0178 throw edm::Exception(edm::errors::Configuration) << "Syntax error (brackets)\n";
0179 } else {
0180 brcount_--;
0181 }
0182 }
0183 }
0184 if (brcount_ != 0)
0185 throw edm::Exception(edm::errors::Configuration) << "Syntax error (brackets)\n";
0186
0187 children_.push_back(new TreeElement(str_.substr(offset_, pos + k), tr, this));
0188 offset_ = k + pos + 2;
0189 occurrences_ = true;
0190 if (offset_ >= str_.size())
0191 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
0192 break;
0193 }
0194 }
0195
0196 if (str_.at(k) == '(')
0197 bracketcnt_++;
0198 if (str_.at(k) == ')')
0199 bracketcnt_--;
0200 }
0201 }
0202 }
0203 }
0204 if (occurrences_) {
0205 if (opr == 0)
0206 op_ = OR;
0207 else
0208 op_ = AND;
0209 return;
0210 }
0211 }
0212
0213 if (str_.empty()) {
0214 op_ = AND;
0215 if (debug_)
0216 std::cout << "warning: empty element (will return true)" << std::endl;
0217 return;
0218 }
0219
0220 if (str_.at(0) == '!') {
0221 op_ = NOT;
0222 std::string next = str_.substr(1);
0223 children_.push_back(new TreeElement(next, tr, this));
0224 return;
0225 }
0226 size_t beginBlock_ = str_.find('(');
0227 size_t endBlock_ = str_.rfind(')');
0228 bool found_lbracket = (beginBlock_ != std::string::npos);
0229 bool found_rbracket = (endBlock_ != std::string::npos);
0230
0231 if (found_lbracket != found_rbracket) {
0232 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0233 } else if (found_lbracket && found_rbracket) {
0234 if (beginBlock_ >= endBlock_) {
0235 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0236 }
0237 if (beginBlock_ != 0 || endBlock_ != str_.size() - 1)
0238 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (invalid character)\n";
0239
0240 std::string next = str_.substr(beginBlock_ + 1, endBlock_ - beginBlock_ - 1);
0241
0242 children_.push_back(new TreeElement(next, tr, this));
0243 op_ = BR;
0244 return;
0245 } else if (!found_lbracket && !found_rbracket)
0246 {
0247 bool ignore_if_missing = true;
0248 size_t chr_pos = str_.find('@');
0249 if (chr_pos != std::string::npos) {
0250 ignore_if_missing = false;
0251 str_ = str_.substr(0, chr_pos);
0252 }
0253
0254 std::vector<Strings::const_iterator> matches = edm::regexMatch(tr, str_);
0255 if (matches.empty()) {
0256 if (!ignore_if_missing)
0257 throw edm::Exception(edm::errors::Configuration) << "Trigger name (or match) not present";
0258 else {
0259 if (debug_)
0260 std::cout << "TriggerSelector: Couldn't match any triggers from: " << str_ << std::endl
0261 << " Node will not be added " << std::endl;
0262 op_ = OR;
0263 return;
0264 }
0265 }
0266 if (matches.size() == 1) {
0267
0268 trigBit_ = distance(tr.begin(), matches[0]);
0269 if (debug_)
0270 std::cout << "added trigger path: " << trigBit_ << std::endl;
0271 return;
0272 }
0273 if (matches.size() > 1) {
0274 op_ = OR;
0275 for (size_t l = 0; l < matches.size(); l++)
0276 children_.push_back(new TreeElement(*(matches[l]), tr, this));
0277 }
0278 }
0279 }
0280
0281 std::string TriggerSelector::trim(std::string input) {
0282 if (!input.empty()) {
0283 std::string::size_type pos = input.find_first_not_of(' ');
0284 if (pos != std::string::npos)
0285 input.erase(0, pos);
0286
0287 pos = input.find_last_not_of(' ');
0288 if (pos != std::string::npos)
0289 input.erase(pos + 1);
0290 }
0291 return input;
0292 }
0293
0294 std::string TriggerSelector::makeXMLString(std::string const& input) {
0295 std::string output;
0296 if (!input.empty()) {
0297 for (size_t pos = 0; pos < input.size(); pos++) {
0298 char ch = input.at(pos);
0299 if (ch == '&')
0300 output.append("&");
0301 else
0302 output.append(1, ch);
0303 }
0304 }
0305 return output;
0306 }
0307
0308 bool TriggerSelector::TreeElement::returnStatus(edm::HLTGlobalStatus const& trStatus) const {
0309 if (children_.empty()) {
0310 if (op_ == OR || op_ == NOT)
0311 return false;
0312 if (op_ == AND || op_ == BR)
0313 return true;
0314
0315 if (trigBit_ < 0 || (unsigned int)trigBit_ >= trStatus.size())
0316 throw edm::Exception(edm::errors::Configuration) << "Internal Error: array out of bounds.";
0317
0318 if ((trStatus[trigBit_]).state() == edm::hlt::Pass)
0319 return true;
0320
0321
0322 return false;
0323 }
0324 if (op_ == NOT) {
0325 return !children_[0]->returnStatus(trStatus);
0326 }
0327 if (op_ == BR) {
0328 return children_[0]->returnStatus(trStatus);
0329 }
0330 if (op_ == AND) {
0331 bool status = true;
0332 for (size_t i = 0; i < children_.size(); i++)
0333 status = status && children_[i]->returnStatus(trStatus);
0334 return status;
0335 } else if (op_ == OR) {
0336 bool status = false;
0337 for (size_t i = 0; i < children_.size(); i++)
0338 status = status || children_[i]->returnStatus(trStatus);
0339 return status;
0340 }
0341 throw edm::Exception(edm::errors::Configuration)
0342 << "Internal error: reached end of returnStatus(...), op:state = " << op_;
0343 return false;
0344 }
0345
0346 TriggerSelector::TreeElement::~TreeElement() {
0347 for (std::vector<TreeElement*>::iterator it = children_.begin(); it != children_.end(); it++)
0348 delete *it;
0349 children_.clear();
0350 }
0351 }