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 size_t brackets_=0;
00212 for (size_t k=offset_;k<t_end_;k++) {
00213 if (str_.at(k)=='(')
00214 {
00215 brackets_++;
00216 }
00217 else if (str_.at(k)==')')
00218 {
00219 if (brackets_ == 0)
00220 {
00221 throw edm::Exception(edm::errors::Configuration)
00222 << "Syntax Error (brackets)\n";
00223 }
00224 else
00225 {
00226 brackets_--;
00227 }
00228 }
00229 }
00230 if (brackets_==0) {
00231 std::string next = str_.substr(offset_,t_end_-offset_);
00232 children_.push_back(new TreeElement(next,tr,this));
00233 occurrences_=true;
00234 offset_ = t_end_+2;
00235 }
00236 else {
00237
00238 int bracketcnt_ = 0;
00239 for (size_t k=offset_;true;k++) {
00240 if (k>=str_.size()) {
00241 if (bracketcnt_!=0)
00242 throw edm::Exception(edm::errors::Configuration)
00243 << "Syntax Error (brackets)\n";
00244 exitloop_=true;
00245 if (occurrences_) {
00246 children_.push_back(new TreeElement(str_.substr(offset_),tr,this));
00247 }
00248 break;
00249 }
00250
00251 if (k>=t_end_+2 && bracketcnt_==0) {
00252 std::string temp = str_.substr(k);
00253 size_t pos = temp.find(binaryOperators_[opr]);
00254 if (pos == std::string::npos) {
00255 exitloop_=true;
00256 if (occurrences_) {
00257 children_.push_back(new TreeElement(str_.substr(offset_),tr,this));
00258 }
00259 break;
00260 }
00261 else {
00262 int brcount_ = 0;
00263 for (size_t s=0;s<pos;s++) {
00264
00265 if (temp.at(pos)=='(')
00266 {
00267 brcount_++;
00268 }
00269 else if (temp.at(pos)==')')
00270 {
00271 if (brcount_ == 0)
00272 {
00273 throw edm::Exception(edm::errors::Configuration)
00274 << "Syntax error (brackets)\n";
00275 }
00276 else
00277 {
00278 brcount_--;
00279 }
00280 }
00281 }
00282 if (brcount_!=0)
00283 throw edm::Exception(edm::errors::Configuration)
00284 << "Syntax error (brackets)\n";
00285
00286 children_.push_back(new TreeElement(str_.substr(offset_,pos+k),tr,this));
00287 offset_=k+pos+2;
00288 occurrences_=true;
00289 if (offset_>=str_.size())
00290 throw edm::Exception(edm::errors::Configuration)
00291 << "Syntax Error (operator is not unary)\n";
00292 break;
00293 }
00294
00295 }
00296
00297
00298 if (str_.at(k)=='(') bracketcnt_++;
00299 if (str_.at(k)==')') bracketcnt_--;
00300
00301 }
00302 }
00303 }
00304
00305 }
00306 if (occurrences_) {
00307 if (opr==0) op_=OR;
00308 else op_=AND;
00309 return;
00310 }
00311 }
00312
00313 if (str_.empty()) {
00314 op_=AND;
00315 if (debug_) std::cout << "warning: empty element (will return true)"<< std::endl;
00316 return;
00317 }
00318
00319 if (str_.at(0)=='!') {
00320 op_=NOT;
00321 std::string next = str_.substr(1);
00322 children_.push_back(new TreeElement(next,tr,this));
00323 return;
00324 }
00325 size_t beginBlock_ =str_.find('(');
00326 size_t endBlock_ =str_.rfind(')');
00327 bool found_lbracket = (beginBlock_ != std::string::npos);
00328 bool found_rbracket = (endBlock_ != std::string::npos);
00329
00330 if (found_lbracket != found_rbracket) {
00331 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
00332 }
00333 else if (found_lbracket && found_rbracket)
00334 {
00335 if (beginBlock_>=endBlock_) {
00336 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
00337 }
00338 if (beginBlock_!=0 || endBlock_!=str_.size()-1)
00339 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (invalid character)\n";
00340
00341 std::string next = str_.substr(beginBlock_+1,endBlock_-beginBlock_-1);
00342
00343 children_.push_back(new TreeElement(next,tr,this));
00344 op_=BR;
00345 return;
00346 }
00347 else if (!found_lbracket && !found_rbracket)
00348 {
00349 bool ignore_if_missing = true;
00350 size_t chr_pos = str_.find("@");
00351 if (chr_pos!= std::string::npos) {
00352 ignore_if_missing=false;
00353 str_=str_.substr(0,chr_pos);
00354 }
00355
00356 std::vector<Strings::const_iterator> matches = edm::regexMatch(tr,str_);
00357 if (matches.empty()) {
00358 if (!ignore_if_missing)
00359 throw edm::Exception(edm::errors::Configuration) << "Trigger name (or match) not present" << std::endl;
00360 else {
00361 if (debug_)
00362 std::cout << "TriggerSelector: Couldn't match any triggers from: "<< str_<< std::endl
00363 << " Node will not be added "<< std::endl;
00364 op_=OR;
00365 return;
00366 }
00367 }
00368 if (matches.size()==1) {
00369
00370 trigBit_ = distance(tr.begin(),matches[0]);
00371 if (debug_) std::cout << "added trigger path: " << trigBit_ << std::endl;
00372 return;
00373 }
00374 if (matches.size()>1) {
00375 op_=OR;
00376 for (size_t l=0;l<matches.size();l++)
00377 children_.push_back(new TreeElement(*(matches[l]),tr,this));
00378 }
00379 }
00380 }
00381
00382 std::string TriggerSelector::trim(std::string input)
00383 {
00384 if (!input.empty())
00385 {
00386 std::string::size_type pos = input.find_first_not_of(" ");
00387 if (pos != std::string::npos)
00388 input.erase(0,pos);
00389
00390 pos = input.find_last_not_of(" ");
00391 if (pos != std::string::npos)
00392 input.erase(pos+1);
00393 }
00394 return input;
00395 }
00396
00397 std::string TriggerSelector::makeXMLString(std::string const& input)
00398 {
00399 std::string output;
00400 if (!input.empty()) {
00401 for (size_t pos=0;pos<input.size();pos++) {
00402 char ch = input.at(pos);
00403 if (ch=='&') output.append("&");
00404 else output.append(1,ch);
00405 }
00406 }
00407 return output;
00408 }
00409
00410
00411 bool TriggerSelector::TreeElement::returnStatus
00412 (
00413 edm::HLTGlobalStatus const& trStatus
00414 ) const
00415 {
00416
00417 if (children_.empty()) {
00418
00419 if (op_==OR || op_==NOT) return false;
00420 if (op_==AND || op_==BR) return true;
00421
00422 if (trigBit_<0 || (unsigned int)trigBit_>=trStatus.size())
00423 throw edm::Exception(edm::errors::Configuration)
00424 << "Internal Error: array out of bounds " << std::endl;
00425
00426 if ((trStatus[trigBit_]).state() == edm::hlt::Pass) return true;
00427
00428
00429 return false;
00430 }
00431 if (op_==NOT) {
00432 return !children_[0]->returnStatus(trStatus);
00433 }
00434 if (op_==BR) {
00435 return children_[0]->returnStatus(trStatus);
00436 }
00437 if (op_==AND) {
00438 bool status = true;
00439 for (size_t i=0;i<children_.size();i++) status = status && children_[i]->returnStatus(trStatus);
00440 return status;
00441 }
00442 else if (op_==OR) {
00443 bool status = false;
00444 for (size_t i=0;i<children_.size();i++) status = status || children_[i]->returnStatus(trStatus);
00445 return status;
00446 }
00447 throw edm::Exception(edm::errors::Configuration) << "Internal error: reached end of returnStatus(...) op:state= " << op_ << std::endl;
00448 return false;
00449 }
00450
00451
00452 TriggerSelector::TreeElement::~TreeElement()
00453 {
00454 for (std::vector<TreeElement*>::iterator it=children_.begin();it!=children_.end();it++)
00455 delete *it;
00456 children_.clear();
00457 }
00458
00459 }
00460
00461