00001
00003
00004 #include "EventFilter/StorageManager/interface/TriggerSelector.h"
00005
00006 #include "FWCore/Framework/interface/TriggerNamesService.h"
00007 #include "FWCore/Utilities/interface/RegexMatch.h"
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009
00010 #include <iostream>
00011 #include <boost/regex.hpp>
00012 #include <algorithm>
00013 #include <cassert>
00014
00015 namespace stor
00016 {
00017
00018
00019
00020 TriggerSelector::TriggerSelector
00021 (
00022 Strings const& pathspecs,
00023 Strings const& names
00024 ):
00025 useOld_(true)
00026 {
00027 acceptAll_=false;
00028 eventSelector_.reset( new edm::EventSelector(pathspecs,names));
00029 }
00030
00031 TriggerSelector::TriggerSelector
00032 (
00033 edm::ParameterSet const& config,
00034 Strings const& triggernames,
00035 bool old_
00036 ):
00037 useOld_(old_)
00038 {
00039 acceptAll_=false;
00040 if (old_) {
00041
00042 eventSelector_.reset( new edm::EventSelector(config, triggernames));
00043 return;
00044 }
00045 if (!config.empty()) {
00046
00047
00048 try {
00049 std::string myPath = trim(config.getParameter<std::string>("TriggerSelector"));
00050 if (!myPath.empty()) {
00051 init(myPath, triggernames);
00052 return;
00053 }
00054 }
00055 catch(...) {}
00056
00057
00058 try {
00059 Strings paths;
00060 paths = config.getParameter<Strings>("SelectEvents");
00061 if (!paths.empty()) {
00062 useOld_=true;
00063 eventSelector_.reset( new edm::EventSelector(config, triggernames));
00064 return;
00065 }
00066 }
00067 catch(...) {}
00068 }
00069
00070
00071 acceptAll_=true;
00072 }
00073
00074 TriggerSelector::TriggerSelector
00075 (
00076 std::string const & expression,
00077 Strings const& triggernames
00078 ):
00079 useOld_(false)
00080 {
00081 init (trim(expression),triggernames);
00082 }
00083
00084 void
00085 TriggerSelector::init
00086 (
00087 std::string const& expression,
00088 Strings const& triggernames
00089 )
00090 {
00091
00092 if (expression.empty())
00093 {
00094 acceptAll_ = true;
00095 return;
00096 }
00097 if (expression.size()==1 && expression.at(0)=='*') acceptAll_=true;
00098 else acceptAll_=false;
00099
00100
00101 {
00102 using namespace boost;
00103 std::string temp;
00104 temp = regex_replace( expression , regex(".AND."), "&&");
00105 expression_ = regex_replace( temp, regex(".and."), "&&");
00106 temp = regex_replace( expression_, regex(".OR."), "||");
00107 expression_ = regex_replace( temp, regex(".or."), "||");
00108 }
00109
00110
00111 masterElement_.reset( new TreeElement(expression_,triggernames));
00112 }
00113
00114
00115
00116
00117 std::vector<std::string>
00118 TriggerSelector::getEventSelectionVString(edm::ParameterSet const& pset)
00119 {
00120 return edm::EventSelector::getEventSelectionVString(pset);
00121 }
00122
00123 bool TriggerSelector::acceptEvent(edm::TriggerResults const& tr) const
00124 {
00125 if (useOld_) {
00126 return eventSelector_->acceptEvent(tr);
00127 }
00128
00129 if (acceptAll_) return true;
00130
00131 return masterElement_->returnStatus(tr);
00132 }
00133
00134 bool
00135 TriggerSelector::acceptEvent
00136 (
00137 unsigned char const* array_of_trigger_results,
00138 int number_of_trigger_paths
00139 ) const
00140 {
00141
00142 if (useOld_)
00143 return eventSelector_->acceptEvent(array_of_trigger_results,number_of_trigger_paths);
00144
00145 if (acceptAll_) return true;
00146
00147
00148 edm::HLTGlobalStatus tr(number_of_trigger_paths);
00149 int byteIndex = 0;
00150 int subIndex = 0;
00151 for (int pathIndex = 0; pathIndex < number_of_trigger_paths; ++pathIndex)
00152 {
00153 int state = array_of_trigger_results[byteIndex] >> (subIndex * 2);
00154 state &= 0x3;
00155 edm::HLTPathStatus pathStatus(static_cast<edm::hlt::HLTState>(state));
00156 tr[pathIndex] = pathStatus;
00157 ++subIndex;
00158 if (subIndex == 4)
00159 { ++byteIndex;
00160 subIndex = 0;
00161 }
00162 }
00163
00164
00165 return masterElement_->returnStatus(tr);
00166 }
00167
00168
00169 TriggerSelector::TreeElement::TreeElement
00170 (
00171 std::string const& inputString,
00172 Strings const& tr,
00173 TreeElement* parentElement
00174 ) :
00175 op_(NonInit),
00176 trigBit_(-1)
00177 {
00178 std::string str_ = trim(inputString);
00179 children_.clear();
00180 parent_ = parentElement;
00181
00182 size_t offset_=0;
00183 bool occurrences_=false;
00184
00185 if (str_.empty())
00186 throw edm::Exception(edm::errors::Configuration)
00187 << "Syntax Error (empty element)" << std::endl;
00188
00189 static const size_t bopsSize_ = 2;
00190 static const std::string binaryOperators_[bopsSize_] = {"||","&&"};
00191
00192 for (size_t opr=0;opr<bopsSize_;opr++) {
00193 bool exitloop_=false;
00194 while(!exitloop_) {
00195 size_t t_end_;
00196
00197 std::string tmpStr = str_.substr(offset_);
00198 t_end_ = tmpStr.find(binaryOperators_[opr]);
00199 if (debug_) std::cout << "offset: " << offset_ << " length: " << t_end_ <<" string: " << tmpStr << std::endl;
00200
00201 if (t_end_ == std::string::npos) {
00202
00203 if (occurrences_) children_.push_back(new TreeElement(tmpStr,tr,this));
00204 break;
00205 }
00206 t_end_ += offset_;
00207 if (t_end_==0 || t_end_+2>=str_.size())
00208 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
00209 else {
00210
00211 int brackets_=0;
00212 for (size_t k=offset_;k<t_end_;k++) {
00213 if (str_.at(k)=='(') brackets_++;
00214 if (str_.at(k)==')') brackets_--;
00215 if (brackets_<0)
00216 throw edm::Exception(edm::errors::Configuration)
00217 << "Syntax Error (brackets)\n";
00218 }
00219 if (brackets_==0) {
00220 std::string next = str_.substr(offset_,t_end_-offset_);
00221 children_.push_back(new TreeElement(next,tr,this));
00222 occurrences_=true;
00223 offset_ = t_end_+2;
00224 }
00225 else {
00226
00227 int bracketcnt_ = 0;
00228 for (size_t k=offset_;true;k++) {
00229 if (k>=str_.size()) {
00230 if (bracketcnt_!=0)
00231 throw edm::Exception(edm::errors::Configuration)
00232 << "Syntax Error (brackets)\n";
00233 exitloop_=true;
00234 if (occurrences_) {
00235 children_.push_back(new TreeElement(str_.substr(offset_),tr,this));
00236 }
00237 break;
00238 }
00239
00240 if (k>=t_end_+2 && bracketcnt_==0) {
00241 std::string temp = str_.substr(k);
00242 size_t pos = temp.find(binaryOperators_[opr]);
00243 if (pos == std::string::npos) {
00244 exitloop_=true;
00245 if (occurrences_) {
00246 children_.push_back(new TreeElement(str_.substr(offset_),tr,this));
00247 }
00248 break;
00249 }
00250 else {
00251 int brcount_ = 0;
00252 for (size_t s=0;s<pos;s++) {
00253
00254 if (temp.at(pos)=='(') brcount_++;
00255 if (temp.at(pos)==')') brcount_--;
00256 if (brcount_<0)
00257 throw edm::Exception(edm::errors::Configuration)
00258 << "Syntax error (brackets)\n";
00259 }
00260 if (brcount_!=0)
00261 throw edm::Exception(edm::errors::Configuration)
00262 << "Syntax error (brackets)\n";
00263
00264 children_.push_back(new TreeElement(str_.substr(offset_,pos+k),tr,this));
00265 offset_=k+pos+2;
00266 occurrences_=true;
00267 if (offset_>=str_.size())
00268 throw edm::Exception(edm::errors::Configuration)
00269 << "Syntax Error (operator is not unary)\n";
00270 break;
00271 }
00272
00273 }
00274
00275
00276 if (str_.at(k)=='(') bracketcnt_++;
00277 if (str_.at(k)==')') bracketcnt_--;
00278
00279 }
00280 }
00281 }
00282
00283 }
00284 if (occurrences_) {
00285 if (opr==0) op_=OR;
00286 else op_=AND;
00287 return;
00288 }
00289 }
00290
00291 if (str_.empty()) {
00292 op_=AND;
00293 if (debug_) std::cout << "warning: empty element (will return true)"<< std::endl;
00294 return;
00295 }
00296
00297 if (str_.at(0)=='!') {
00298 op_=NOT;
00299 std::string next = str_.substr(1);
00300 children_.push_back(new TreeElement(next,tr,this));
00301 return;
00302 }
00303 size_t beginBlock_ =str_.find('(');
00304 size_t endBlock_ =str_.rfind(')');
00305 bool found_lbracket = (beginBlock_ != std::string::npos);
00306 bool found_rbracket = (endBlock_ != std::string::npos);
00307
00308 if (found_lbracket != found_rbracket) {
00309 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
00310 }
00311 else if (found_lbracket && found_rbracket)
00312 {
00313 if (beginBlock_>=endBlock_) {
00314 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
00315 }
00316 if (beginBlock_!=0 || endBlock_!=str_.size()-1)
00317 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (invalid character)\n";
00318
00319 std::string next = str_.substr(beginBlock_+1,endBlock_-beginBlock_-1);
00320
00321 children_.push_back(new TreeElement(next,tr,this));
00322 op_=BR;
00323 return;
00324 }
00325 else if (!found_lbracket && !found_rbracket)
00326 {
00327 bool ignore_if_missing = true;
00328 size_t chr_pos = str_.find("@");
00329 if (chr_pos!= std::string::npos) {
00330 ignore_if_missing=false;
00331 str_=str_.substr(0,chr_pos);
00332 }
00333
00334 std::vector<Strings::const_iterator> matches = edm::regexMatch(tr,str_);
00335 if (matches.empty()) {
00336 if (!ignore_if_missing)
00337 throw edm::Exception(edm::errors::Configuration) << "Trigger name (or match) not present" << std::endl;
00338 else {
00339 if (debug_)
00340 std::cout << "TriggerSelector: Couldn't match any triggers from: "<< str_<< std::endl
00341 << " Node will not be added "<< std::endl;
00342 op_=OR;
00343 return;
00344 }
00345 }
00346 if (matches.size()==1) {
00347
00348 trigBit_ = distance(tr.begin(),matches[0]);
00349 if (debug_) std::cout << "added trigger path: " << trigBit_ << std::endl;
00350 return;
00351 }
00352 if (matches.size()>1) {
00353 op_=OR;
00354 for (size_t l=0;l<matches.size();l++)
00355 children_.push_back(new TreeElement(*(matches[l]),tr,this));
00356 }
00357 }
00358 }
00359
00360 std::string TriggerSelector::trim(std::string input)
00361 {
00362 if (!input.empty())
00363 {
00364 std::string::size_type pos = input.find_first_not_of(" ");
00365 if (pos != std::string::npos)
00366 input.erase(0,pos);
00367
00368 pos = input.find_last_not_of(" ");
00369 if (pos != std::string::npos)
00370 input.erase(pos+1);
00371 }
00372 return input;
00373 }
00374
00375 std::string TriggerSelector::makeXMLString(std::string const& input)
00376 {
00377 std::string output;
00378 if (!input.empty()) {
00379 for (size_t pos=0;pos<input.size();pos++) {
00380 char ch = input.at(pos);
00381 if (ch=='&') output.append("&");
00382 else output.append(1,ch);
00383 }
00384 }
00385 return output;
00386 }
00387
00388
00389 bool TriggerSelector::TreeElement::returnStatus
00390 (
00391 edm::HLTGlobalStatus const& trStatus
00392 ) const
00393 {
00394
00395 if (children_.empty()) {
00396
00397 if (op_==OR || op_==NOT) return false;
00398 if (op_==AND || op_==BR) return true;
00399
00400 if (trigBit_<0 || (unsigned int)trigBit_>=trStatus.size())
00401 throw edm::Exception(edm::errors::Configuration)
00402 << "Internal Error: array out of bounds " << std::endl;
00403
00404 if ((trStatus[trigBit_]).state() == edm::hlt::Pass) return true;
00405
00406
00407 return false;
00408 }
00409 if (op_==NOT) {
00410 return !children_[0]->returnStatus(trStatus);
00411 }
00412 if (op_==BR) {
00413 return children_[0]->returnStatus(trStatus);
00414 }
00415 if (op_==AND) {
00416 bool status = true;
00417 for (size_t i=0;i<children_.size();i++) status = status && children_[i]->returnStatus(trStatus);
00418 return status;
00419 }
00420 else if (op_==OR) {
00421 bool status = false;
00422 for (size_t i=0;i<children_.size();i++) status = status || children_[i]->returnStatus(trStatus);
00423 return status;
00424 }
00425 throw edm::Exception(edm::errors::Configuration) << "Internal error: reached end of returnStatus(...) op:state= " << op_ << std::endl;
00426 return false;
00427 }
00428
00429
00430 TriggerSelector::TreeElement::~TreeElement()
00431 {
00432 for (std::vector<TreeElement*>::iterator it=children_.begin();it!=children_.end();it++)
00433 delete *it;
00434 children_.clear();
00435 }
00436
00437 }
00438
00439