CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/EventFilter/StorageManager/src/TriggerSelector.cc

Go to the documentation of this file.
00001 // $Id: TriggerSelector.cc,v 1.10 2011/11/14 11:49:22 mommsen Exp $
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   //compatibility constructor
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       //old mode forced
00042       eventSelector_.reset( new edm::EventSelector(config, triggernames));
00043       return;
00044     }
00045     if (!config.empty()) {
00046 
00047       //let's see if non empty TriggerSelector is present
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       //now try with the SelectEvents 
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     //if selection parameters aren't present, don't do selection
00070     //log
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     //debug_ = true;
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     //replace all possible alternate operators (.AND. and .OR.)
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     //build decision tree
00111     masterElement_.reset( new TreeElement(expression_,triggernames));
00112   }
00113 
00114   /*
00115         Obsolete
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     // Form HLTGlobalStatus object to represent the array_of_trigger_results
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     // Now make the decision, based on the HLTGlobalStatus tr,
00164     // which we have created from the supplied array of results
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           //right side element
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           //count bracket in preceeding part
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             //operator is inside brackets, find another
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               //look for another operator
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                     //counting check of brackets from last position to operator
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; //a bracket
00345       return;
00346     }
00347     else if (!found_lbracket && !found_rbracket) //assume single trigger or wildcard (parsing)
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)// && !edm::is_glob(str_)) 
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         //Single Trigger match
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("&amp;");
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       //else if ((trStatus[trigBit]).state() == edm::hlt::Fail) return false;
00428 
00429       return false;
00430     }
00431     if (op_==NOT) { //NEGATION
00432       return !children_[0]->returnStatus(trStatus);
00433     }
00434     if (op_==BR) { //BRACKET
00435       return children_[0]->returnStatus(trStatus);
00436     } 
00437     if (op_==AND) { //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) { //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 } // namespace stor
00460 
00461