CMS 3D CMS Logo

InitMsgCollection.cc

Go to the documentation of this file.
00001 
00009 #include "DataFormats/Streamer/interface/StreamedProducts.h"
00010 #include "EventFilter/StorageManager/interface/InitMsgCollection.h"
00011 #include "FWCore/Framework/interface/EventSelector.h"
00012 #include "FWCore/Utilities/interface/DebugMacros.h"
00013 #include "FWCore/Utilities/interface/Exception.h"
00014 #include "IOPool/Streamer/interface/DumpTools.h"
00015 #include "IOPool/Streamer/interface/OtherMessage.h"
00016 #include "IOPool/Streamer/interface/StreamerInputSource.h"
00017 #include "IOPool/Streamer/interface/Utilities.h"
00018 
00019 #include "boost/algorithm/string/trim.hpp"
00020 #include <iostream>
00021 
00022 using namespace stor;
00023 using namespace edm;
00024 
00028 InitMsgCollection::InitMsgCollection()
00029 {
00030   FDEBUG(5) << "Executing constructor for InitMsgCollection" << std::endl;
00031   initMsgList_.clear();
00032   outModNameTable_.clear();
00033 
00034   serializedFullSet_.reset(new InitMsgBuffer(2 * sizeof(Header)));
00035   OtherMessageBuilder fullSetMsg(&(*serializedFullSet_)[0], Header::INIT_SET);
00036 }
00037 
00041 InitMsgCollection::~InitMsgCollection()
00042 {
00043   FDEBUG(5) << "Executing destructor for InitMsgCollection" << std::endl;
00044 }
00045 
00046 #if 0
00047     // 29-Apr-2008 KAB - replaced the following methods as part of the switch
00048     // to the newer HLT output module selection scheme (in which the HLT
00049     // output module needs to be explicitly specified)
00050     //
00051     // testAndAddIfUnique() replaced by addIfUnique()
00052     // getElementForSelection() replaced by getElementForOutputModule()
00053     //
00054     bool testAndAddIfUnique(InitMsgView const& initMsgView);
00055     InitMsgSharedPtr getElementForSelection(Strings const& triggerSelection);
00056 
00075 bool InitMsgCollection::testAndAddIfUnique(InitMsgView const& initMsgView)
00076 {
00077   boost::mutex::scoped_lock sl(listLock_);
00078 
00079   // initially, assume that we will want to include the new message
00080   bool addToList = true;
00081 
00082   // test the message to verify that its full trigger list is not empty
00083   std::string inputOMLabel = initMsgView.outputModuleLabel();
00084   Strings inputTriggerList;
00085   initMsgView.hltTriggerNames(inputTriggerList);
00086   if (inputTriggerList.size() == 0) {
00087     addToList = false; // useless unless we remove the exception...
00088     throw cms::Exception("InitMsgCollection", "testAndAddIfUnique:")
00089       << "The full trigger list specified for the \"" << inputOMLabel
00090       << "\" output module is empty!" << std::endl;
00091   }
00092 
00093   // test the message to verify that its trigger selection is valid
00094   // in the context of its full trigger list
00095   Strings inputSelectionList;
00096   initMsgView.hltTriggerSelections(inputSelectionList);
00097   if (! EventSelector::selectionIsValid(inputSelectionList,
00098                                         inputTriggerList)) {
00099     addToList = false; // useless unless we remove the exception...
00100     throw cms::Exception("InitMsgCollection", "testAndAddIfUnique:")
00101       << "The trigger selection specified for the \"" << inputOMLabel
00102       << "\" output module is not valid for the full trigger list!"
00103       << std::endl;
00104   }
00105 
00106   // if this is the first INIT message that we've seen, we just add it
00107   if (initMsgList_.size() == 0) {
00108     this->add(initMsgView);
00109   }
00110 
00111   // if this is a subsequent INIT message, we have to run some tests
00112   else {
00113 
00114     // loop over the existing messages
00115     std::vector<InitMsgSharedPtr>::const_iterator msgIter;
00116     for (msgIter = initMsgList_.begin(); msgIter != initMsgList_.end(); msgIter++) {
00117       InitMsgSharedPtr serializedProds = *msgIter;
00118       InitMsgView existingInitMsg(&(*serializedProds)[0]);
00119       std::string existingOMLabel = existingInitMsg.outputModuleLabel();
00120 
00121       // independent of everything else that we check, the full trigger list
00122       // in *every* INIT message must match the full trigger list in every
00123       // other INIT message.  If the list of trigger paths are not the same,
00124       // how could we ever hope to compare selection lists or trigger results?
00125 
00126       // check that the full trigger lists are identical
00127       Strings existingTriggerList;
00128       existingInitMsg.hltTriggerNames(existingTriggerList);
00129       if (inputTriggerList != existingTriggerList) {
00130         addToList = false; // useless unless we remove the exception...
00131         throw cms::Exception("InitMsgCollection", "testAndAddIfUnique:")
00132           << "INIT messages from the \"" << inputOMLabel << "\" and \""
00133           << existingOMLabel << "\" output modules have "
00134           << "different HLT full trigger lists!" << std::endl;
00135       }
00136 
00137       // fetch the trigger selection list to be used in later tests
00138       Strings existingSelectionList;
00139       existingInitMsg.hltTriggerSelections(existingSelectionList);
00140 
00141       // check if the output module labels match
00142       if (inputOMLabel == existingOMLabel) {
00143 
00144         // if the output module labels match, and everything else in the
00145         // messages match, then we presume that the new message is just
00146         // a duplicate sent from the Nth filter unit.  If something in
00147         // the INIT messages do not match, we have the
00148         // odd situation in which multiple filter units are sending us
00149         // INIT messages from what they claim is same output module, but
00150         // is not really.
00151 
00152         // check that the trigger selections are identical
00153         if (EventSelector::testSelectionOverlap(inputSelectionList,
00154                                                 existingSelectionList,
00155                                                 existingTriggerList) !=
00156             evtSel::ExactMatch) {
00157           addToList = false; // useless unless we remove the exception...
00158           throw cms::Exception("InitMsgCollection", "testAndAddIfUnique:")
00159             << "INIT messages from the \"" << inputOMLabel
00160             << "\" output module in different filter units have "
00161             << "different HLT trigger selections!" << std::endl;
00162         }
00163 
00164         // check that the product lists are identical
00165         std::auto_ptr<SendJobHeader> header =
00166           StreamerInputSource::deserializeRegistry(initMsgView);
00167         std::auto_ptr<SendJobHeader> refheader =
00168           StreamerInputSource::deserializeRegistry(existingInitMsg);
00169         if (! registryIsSubset(*header, *refheader) ||
00170             ! registryIsSubset(*refheader, *header)) {
00171           addToList = false; // useless unless we remove the exception...
00172           throw cms::Exception("InitMsgCollection", "testAndAddIfUnique:")
00173             << "INIT messages from the \"" << inputOMLabel
00174             << "\" output module in different filter units have "
00175             << "different product lists!" << std::endl;
00176         }
00177 
00178         // at this point, do we return or continue with tests against
00179         // the remaining INIT messages in the list?
00180         // Let's return because A) the new message exactly matches an
00181         // existing one in the list, and B) the messages in the list should
00182         // have passed all of the remaining tests to get in the list.
00183         addToList = false;  // not really needed since we return...
00184         return addToList;
00185       }
00186       else {
00187 
00188         // if the output module labels don't match, check if the trigger
00189         // selection in the new INIT message overlaps with the selection
00190         // in the existing message.  If it does, that is a problem because
00191         // we need the trigger selection lists to be non-overlapping (so
00192         // that masked TriggerResults can possibly only match one
00193         // selection list)
00194 
00195         // check that the trigger selections do not overlap
00196         if (EventSelector::testSelectionOverlap(inputSelectionList,
00197                                                 existingSelectionList,
00198                                                 existingTriggerList) !=
00199             evtSel::NoOverlap) {
00200           addToList = false; // useless unless we remove the exception...
00201           throw cms::Exception("InitMsgCollection", "testAndAddIfUnique:")
00202             << "INIT messages from the \"" << inputOMLabel << "\" and \""
00203             << existingOMLabel << "\" output modules have "
00204             << "overlapping HLT trigger selections: ("
00205             << stringsToText(inputSelectionList, 10) << ") and ("
00206             << stringsToText(existingSelectionList, 10) << ")."
00207             << std::endl;
00208         }
00209       }
00210     }
00211 
00212     // if we've found no problems, add the new message to the collection
00213     if (addToList) {
00214       this->add(initMsgView);
00215     }
00216   }
00217 
00218   // indicate whether the message was added or not
00219   return addToList;
00220 }
00221 
00238 InitMsgSharedPtr
00239 InitMsgCollection::getElementForSelection(Strings const& triggerSelection)
00240 {
00241   boost::mutex::scoped_lock sl(listLock_);
00242 
00243   InitMsgSharedPtr serializedProds;
00244   if (initMsgList_.size() > 0) {
00245 
00246     // check that the input trigger selection is valid
00247     InitMsgSharedPtr workingMessage = initMsgList_[0];
00248     InitMsgView existingInitMsg(&(*workingMessage)[0]);
00249     Strings fullTriggerList;
00250     existingInitMsg.hltTriggerNames(fullTriggerList);
00251     if (! EventSelector::selectionIsValid(triggerSelection,
00252                                           fullTriggerList)) {
00253       std::string msg = "The specified trigger selection list (";
00254       msg.append(stringsToText(triggerSelection, 10));
00255       msg.append(") contains paths not in the full trigger list!");
00256       throw cms::Exception("InitMsgCollection", "getElementForSelection:")
00257         << msg << std::endl;
00258     }
00259 
00260     // loop over the existing messages
00261     std::vector<InitMsgSharedPtr>::const_iterator msgIter;
00262     for (msgIter = initMsgList_.begin(); msgIter != initMsgList_.end(); msgIter++) {
00263       workingMessage = *msgIter;
00264       InitMsgView workingInitMsg(&(*workingMessage)[0]);
00265 
00266       Strings workingSelectionList;
00267       workingInitMsg.hltTriggerSelections(workingSelectionList);
00268 
00269       evtSel::OverlapResult overlapResult =
00270         EventSelector::testSelectionOverlap(triggerSelection,
00271                                             workingSelectionList,
00272                                             fullTriggerList);
00273       if (overlapResult == evtSel::ExactMatch ||
00274           overlapResult == evtSel::PartialOverlap) {
00275         if (serializedProds.get() == NULL) {
00276           serializedProds = workingMessage;
00277         }
00278         else {
00279           std::string msg = "The specified trigger selection list (";
00280           msg.append(stringsToText(triggerSelection, 10));
00281           msg.append(") matches triggers from more than one HLT output module!");
00282           throw cms::Exception("InitMsgCollection", "getElementForSelection:")
00283             << msg << std::endl;
00284         }
00285       }
00286     }
00287   }
00288 
00289   return serializedProds;
00290 }
00291 
00292 #endif
00293 
00309 bool InitMsgCollection::addIfUnique(InitMsgView const& initMsgView)
00310 {
00311   boost::mutex::scoped_lock sl(listLock_);
00312 
00313   // test the output module label for validity
00314   std::string inputOMLabel = initMsgView.outputModuleLabel();
00315   std::string trimmedOMLabel = boost::algorithm::trim_copy(inputOMLabel);
00316   if (trimmedOMLabel.empty()) {
00317     throw cms::Exception("InitMsgCollection", "addIfUnique:")
00318       << "Invalid INIT message: the HLT output module label is empty!"
00319       << std::endl;
00320   }
00321 
00322   // initially, assume that we will want to include the new message
00323   bool addToList = true;
00324 
00325   // if this is the first INIT message that we've seen, we just add it
00326   if (initMsgList_.size() == 0) {
00327     this->add(initMsgView);
00328   }
00329 
00330   // if this is a subsequent INIT message, check if it is unique
00331   else {
00332 
00333     // loop over the existing messages
00334     std::vector<InitMsgSharedPtr>::const_iterator msgIter;
00335     for (msgIter = initMsgList_.begin(); msgIter != initMsgList_.end(); msgIter++) {
00336       InitMsgSharedPtr serializedProds = *msgIter;
00337       InitMsgView existingInitMsg(&(*serializedProds)[0]);
00338       std::string existingOMLabel = existingInitMsg.outputModuleLabel();
00339 
00340       // check if the output module labels match
00341       if (inputOMLabel == existingOMLabel) {
00342         // we already have a copy of the INIT message
00343         addToList = false;
00344         break;
00345       }
00346     }
00347 
00348     // if we've found no problems, add the new message to the collection
00349     if (addToList) {
00350       this->add(initMsgView);
00351     }
00352   }
00353 
00354   // indicate whether the message was added or not
00355   return addToList;
00356 }
00357 
00377 InitMsgSharedPtr
00378 InitMsgCollection::getElementForOutputModule(std::string requestedOMLabel)
00379 {
00380   boost::mutex::scoped_lock sl(listLock_);
00381   InitMsgSharedPtr serializedProds;
00382 
00383   // handle the special case of an empty request
00384   // (If we want to use class methods to check the collection size and
00385   // fetch the last element in the collection, then we would need to 
00386   // switch to recursive mutexes...)
00387   if (requestedOMLabel.empty()) {
00388     if (initMsgList_.size() == 1) {
00389       serializedProds = initMsgList_.back();
00390     }
00391     else if (initMsgList_.size() > 1) {
00392       std::string msg = "Invalid INIT message lookup: the requested ";
00393       msg.append("HLT output module label is empty but there are multiple ");
00394       msg.append("HLT output modules to choose from.");
00395       throw cms::Exception("InitMsgCollection", "getElementForOutputModule:")
00396         << msg << std::endl;
00397     }
00398   }
00399 
00400   else {
00401     // loop over the existing messages
00402     std::vector<InitMsgSharedPtr>::const_iterator msgIter;
00403     for (msgIter = initMsgList_.begin(); msgIter != initMsgList_.end(); msgIter++) {
00404       InitMsgSharedPtr workingMessage = *msgIter;
00405       InitMsgView existingInitMsg(&(*workingMessage)[0]);
00406       std::string existingOMLabel = existingInitMsg.outputModuleLabel();
00407       
00408       // check if the output module labels match
00409       if (requestedOMLabel == existingOMLabel) {
00410         serializedProds = workingMessage;
00411         break;
00412       }
00413     }
00414   }
00415 
00416   return serializedProds;
00417 }
00418 
00425 InitMsgSharedPtr InitMsgCollection::getLastElement()
00426 {
00427   boost::mutex::scoped_lock sl(listLock_);
00428 
00429   InitMsgSharedPtr ptrToLast;
00430   if (initMsgList_.size() > 0) {
00431     ptrToLast = initMsgList_.back();
00432   }
00433   return ptrToLast;
00434 }
00435 
00443 InitMsgSharedPtr InitMsgCollection::getElementAt(unsigned int index)
00444 {
00445   boost::mutex::scoped_lock sl(listLock_);
00446 
00447   InitMsgSharedPtr ptrToElement;
00448   if (index >= 0 && index < initMsgList_.size()) {
00449     ptrToElement = initMsgList_[index];
00450   }
00451   return ptrToElement;
00452 }
00453 
00457 void InitMsgCollection::clear()
00458 {
00459   boost::mutex::scoped_lock sl(listLock_);
00460   initMsgList_.clear();
00461   outModNameTable_.clear();
00462 }
00463 
00469 int InitMsgCollection::size()
00470 {
00471   boost::mutex::scoped_lock sl(listLock_);
00472   return initMsgList_.size();
00473 }
00474 
00480 std::string InitMsgCollection::getSelectionHelpString()
00481 {
00482   // nothing much we can say if the collection is empty
00483   if (initMsgList_.size() == 0) {
00484     return "No information is available about the available triggers.";
00485   }
00486 
00487   // list the full set of available triggers
00488   std::string helpString;
00489   helpString.append("The full list of trigger paths is the following:");
00490 
00491   // we can just use the list from the first entry since all
00492   // subsequent entries are forced to be the same
00493   InitMsgSharedPtr serializedProds = initMsgList_[0];
00494   InitMsgView existingInitMsg(&(*serializedProds)[0]);
00495   Strings existingTriggerList;
00496   existingInitMsg.hltTriggerNames(existingTriggerList);
00497   for (unsigned int idx = 0; idx < existingTriggerList.size(); idx++) {
00498     helpString.append("\n    " + existingTriggerList[idx]);
00499   }
00500 
00501   // list the output modules (INIT messages)
00502   helpString.append("\nThe registered HLT output modules and their ");
00503   helpString.append("trigger selections are the following:");
00504 
00505   // loop over the existing messages
00506   std::vector<InitMsgSharedPtr>::const_iterator msgIter;
00507   for (msgIter = initMsgList_.begin(); msgIter != initMsgList_.end(); msgIter++) {
00508     serializedProds = *msgIter;
00509     InitMsgView workingInitMsg(&(*serializedProds)[0]);
00510     helpString.append("\n  *** Output module \"");
00511     helpString.append(workingInitMsg.outputModuleLabel());
00512     helpString.append("\" ***");
00513     Strings workingSelectionList;
00514     workingInitMsg.hltTriggerSelections(workingSelectionList);
00515     for (unsigned int idx = 0; idx < workingSelectionList.size(); idx++) {
00516       helpString.append("\n    " + workingSelectionList[idx]);
00517     }
00518   }
00519 
00520   // return the result
00521   return helpString;
00522 }
00523 
00530 std::string InitMsgCollection::getOutputModuleName(uint32 outputModuleId)
00531 {
00532   if (outModNameTable_.find(outputModuleId) == outModNameTable_.end())
00533   {
00534     return "";
00535   }
00536   else {
00537     return outModNameTable_[outputModuleId];
00538   }
00539 }
00540 
00551 std::string InitMsgCollection::stringsToText(Strings const& list,
00552                                              unsigned int maxCount)
00553 {
00554   std::string resultString = "";
00555   unsigned int elementCount = list.size();
00556   if (maxCount > 0 && maxCount < elementCount) {elementCount = maxCount;}
00557   for (unsigned int idx = 0; idx < elementCount; idx++)
00558   {
00559     resultString.append(list[idx]);
00560     if (idx < (elementCount-1)) {
00561       resultString.append(", ");
00562     }
00563   }
00564   if (elementCount < list.size())
00565   {
00566     resultString.append(", ...");
00567   }
00568   return resultString;
00569 }
00570 
00576 void InitMsgCollection::add(InitMsgView const& initMsgView)
00577 {
00578   // add the message to the internal list
00579   InitMsgSharedPtr serializedProds(new InitMsgBuffer(initMsgView.size()));
00580   initMsgList_.push_back(serializedProds);
00581   std::copy(initMsgView.startAddress(),
00582             initMsgView.startAddress()+initMsgView.size(),
00583             &(*serializedProds)[0]);
00584 
00585   // add the module ID name to the name map
00586   outModNameTable_[initMsgView.outputModuleId()] =
00587     initMsgView.outputModuleLabel();
00588 
00589   // calculate various sizes needed for adding the message to
00590   // the serialized version of the full set
00591   OtherMessageView fullSetView(&(*serializedFullSet_)[0]);
00592   unsigned int oldBodySize = fullSetView.bodySize();
00593   unsigned int oldBufferSize = serializedFullSet_->size();
00594   unsigned int newBodySize = oldBodySize + initMsgView.size();
00595   unsigned int newBufferSize = oldBufferSize + initMsgView.size();
00596 
00597   // add the message to the serialized full set of messages
00598   serializedFullSet_->resize(newBufferSize);
00599   OtherMessageBuilder fullSetMsg(&(*serializedFullSet_)[0],
00600                                  Header::INIT_SET,
00601                                  newBodySize);
00602   uint8 *copyPtr = fullSetMsg.msgBody() + oldBodySize;
00603   std::copy(initMsgView.startAddress(),
00604             initMsgView.startAddress()+initMsgView.size(),
00605             copyPtr);
00606 }

Generated on Tue Jun 9 17:34:57 2009 for CMSSW by  doxygen 1.5.4