CMS 3D CMS Logo

ScheduleValidator.cc

Go to the documentation of this file.
00001 
00010 static const char CVSId[] = "$Id: ScheduleValidator.cc,v 1.24 2007/11/11 00:24:43 wmtan Exp $";
00011 
00012 #include "FWCore/ParameterSet/src/ScheduleValidator.h"
00013 #include "FWCore/ParameterSet/interface/OperatorNode.h"
00014 #include "FWCore/Utilities/interface/EDMException.h"
00015 #include "FWCore/Utilities/interface/Algorithms.h"
00016 
00017 #include <sstream>
00018 #include <iterator>
00019 #include <iosfwd>
00020 using namespace edm;
00021 using namespace edm::pset;
00022  
00023 ScheduleValidator::ScheduleValidator(const ScheduleValidator::PathContainer& 
00024                                      pathFragments,
00025                                      const ParameterSet& processPSet): 
00026   nodes_(pathFragments),
00027   processPSet_(processPSet),
00028   leaves_(),
00029   dependencies_() 
00030 {
00031  
00032   std::vector<std::string> paths = processPSet.getParameter<std::vector<std::string> >("@paths");
00033 
00034   for(std::vector<std::string>::const_iterator pathIt = paths.begin(), pathItEnd = paths.end();
00035       pathIt != pathItEnd; 
00036       ++pathIt) {
00037     NodePtr head = findPathHead(*pathIt);
00038     gatherLeafNodes(head);
00039   }//for
00040 
00041 }
00042 
00043 
00044 NodePtr ScheduleValidator::findPathHead(std::string pathName){
00045   // std::cout << "in findPathHead" << std::endl;
00046   for (PathContainer::iterator pathIt = nodes_.begin(), pathItEnd = nodes_.end();
00047        pathIt != pathItEnd; ++pathIt) {
00048 //std::cout << "  looking at " << (*pathIt)->type() << " " << (*pathIt)->name << std::endl;
00049     if ((*pathIt)->type() != "path" &&
00050         (*pathIt)->type() != "endpath") continue;
00051     if ((*pathIt)->name() == pathName) return ((*pathIt)->wrapped());
00052 
00053   }// for
00054   throw edm::Exception(errors::Configuration) << "Cannot find a path named " << pathName;
00055   NodePtr ret;
00056   return ret;
00057 }
00058 
00059 void ScheduleValidator::gatherLeafNodes(NodePtr& basenode){
00060 
00061   if (basenode->type() == "," || basenode->type() == "&"){
00062     OperatorNode* onode = dynamic_cast<OperatorNode*>(basenode.get());
00063     gatherLeafNodes(onode->left());
00064     gatherLeafNodes(onode->right());
00065 
00066   } else {
00067     leaves_.push_back(basenode);
00068   }
00069 
00070 }// gatherLeafNodes
00071 
00072 
00073 
00074 
00075 void ScheduleValidator::validate(){
00076 
00077   dependencies_.clear();
00078 
00079   std::string leafName;
00080   std::string sonName;
00081   std::string leftName;
00082 
00083   leafName.reserve(100);
00084   sonName.reserve(100);
00085   leftName.reserve(100);
00086 
00087   // iterate on leaf nodes
00088   for (std::list<NodePtr>::iterator leafIt = leaves_.begin(), leafItEnd = leaves_.end();
00089         leafIt != leafItEnd; ++leafIt) {
00090     
00091     DependencyList dep;
00092 
00093     // follow the tree up thru parent nodes  
00094     Node* p = (*leafIt)->getParent();
00095     Node* son = (*leafIt).get();
00096     
00097     // make sure we don't redescend right of our parent
00098     
00099     while  (p){
00100       // if we got operator '&' continue
00101       if (p->type() == "&") {
00102         son = p;
00103         p = p->getParent(); 
00104         continue;
00105       }
00106 
00107       OperatorNode* node = dynamic_cast<OperatorNode*>(p);
00108       // make sure we don't redescend where we came from
00109 
00110       sonName = son->name();
00111       removeUnaries(sonName);
00112 
00113       leftName = node->left()->name();
00114       removeUnaries(leftName);
00115 
00116       if (sonName != leftName) findDeps(node->left(), dep);
00117       
00118       son = p;
00119       p = p->getParent();
00120     } // while
00121         
00122     dep.sort();   
00123     dep.unique(); // removes duplicates
00124 
00125     // insert the list of deps
00126 
00127     leafName = (*leafIt)->name();
00128     removeUnaries(leafName);
00129 
00130   //  validateDependencies(leafName, *leafIt,  dep);
00131     mergeDependencies(leafName, dep);
00132 
00133   }//for leaf
00134 
00135   validatePaths();
00136      
00137 }// validate
00138 
00139 
00140 void ScheduleValidator::removeUnaries(std::string & name)
00141 {
00142   if(name.size() > 0
00143     && (name[0] == '!' || name[0] == '-') )
00144   {
00145     name.erase(0,1);
00146   }
00147 }
00148 
00149 
00150 void ScheduleValidator::validateDependencies(const std::string & leafName, const NodePtr & leafNode, const DependencyList& dep)
00151 {
00152   Dependencies::iterator depIt = dependencies_.find(leafName);
00153   if (depIt != dependencies_.end()) {
00154     DependencyList& old_deplist = (*depIt).second;
00155     // if the list is different from an existing one
00156     // then we have an inconsitency
00157     if (old_deplist != dep) {
00158 
00159       std::ostringstream olddepstr,newdepstr;
00160       copy_all(old_deplist, std::ostream_iterator<std::string>(olddepstr,","));
00161       copy_all(dep, std::ostream_iterator<std::string>(newdepstr,","));
00162       std::string olddeps = olddepstr.str();
00163       if(olddeps == "") olddeps = "<NOTHING>";
00164       std::string newdeps = newdepstr.str();
00165       if(newdeps == "") newdeps = "<NOTHING>";
00166 
00167       throw edm::Exception(errors::Configuration,"InconsistentSchedule")
00168         << "Inconsistent schedule for module "
00169         << leafName
00170         << "\n"
00171         << "Depends on " << olddeps
00172         << " but also on " << newdeps
00173         << "\n"
00174         << "Second set of dependencies comes from: " << leafNode->traceback();
00175     }
00176   }
00177   else {
00178     dependencies_[leafName] = dep;
00179   }
00180 
00181 }
00182 
00183 
00184 void ScheduleValidator::mergeDependencies(const std::string & leafName, DependencyList& deps)
00185 {
00186   dependencies_[leafName].merge(deps);
00187   dependencies_[leafName].unique();
00188 }
00189 
00190 
00191 void ScheduleValidator::validatePaths()
00192 {
00193  std::vector<std::string> paths = processPSet_.getParameter<std::vector<std::string> >("@paths");
00194   for(std::vector<std::string>::const_iterator pathItr = paths.begin(); pathItr != paths.end(); ++pathItr)
00195   {
00196     validatePath(*pathItr);
00197   }
00198 }
00199 
00200 
00201 void ScheduleValidator::validatePath(const std::string & path) 
00202 {
00203   std::vector<std::string> schedule = processPSet_.getParameter<std::vector<std::string> >(path);
00204   std::vector<std::string>::iterator module = schedule.begin(),
00205     lastModule = schedule.end();
00206   for( ; module != lastModule; ++module)
00207   {
00208      removeUnaries(*module);
00209      Dependencies::iterator depList = dependencies_.find(*module);
00210      if(depList == dependencies_.end())
00211      {
00212         throw edm::Exception(errors::Configuration,"InconsistentSchedule")
00213          << "No dependecies calculated for " << *module;
00214      }
00215      else 
00216      {
00217        DependencyList::iterator depItr = depList->second.begin(),
00218           lastDep = depList->second.end();
00219        for( ; depItr != lastDep; ++depItr)
00220        {
00221          // make sure each dependency is in the schedule before module
00222          if(std::find(schedule.begin(), module, *depItr) == module)
00223          {
00224            std::ostringstream pathdump;
00225            copy_all(schedule, std::ostream_iterator<std::string>(pathdump," "));
00226            
00227            throw edm::Exception(errors::Configuration,"InconsistentSchedule")
00228           << "Module " << *module << " depends on " << *depItr
00229           << "\n"
00230           << " but path " << path << "  contains "  << pathdump.str()
00231           << "\n";
00232          }
00233        }
00234      }
00235   }
00236 }
00237 
00238 
00239 void ScheduleValidator::findDeps(NodePtr& node, DependencyList& dep){
00240 
00241   // if we have an operand, add it to the list of dependencies
00242   if (node->type() == "operand") {
00243     std::string nodeName = node->name();
00244     removeUnaries(nodeName);
00245     dep.push_back(nodeName);
00246   }
00247   // else follow the tree, unless the leaf is contained in the node
00248   else{
00249 
00250     OperatorNode* opnode = dynamic_cast<OperatorNode*>(node.get());
00251     
00252     findDeps(opnode->left(),dep);
00253     findDeps(opnode->right(),dep);
00254            
00255   }
00256 }// findDeps
00257 
00258 
00259 std::string 
00260 ScheduleValidator::dependencies(const std::string& modulename) const{
00261 
00262 
00263   Dependencies::const_iterator depIt = dependencies_.find(modulename);
00264   if (depIt == dependencies_.end()){
00265     std::ostringstream err;
00266     throw edm::Exception(errors::Configuration,"ScheduleDependencies")
00267       << "Error : Dependecies for "
00268       << modulename << " were not calculated";
00269   }
00270 
00271   std::ostringstream deplist;
00272   copy_all((*depIt).second, std::ostream_iterator<std::string>(deplist,","));
00273   return deplist.str();
00274 
00275 }

Generated on Tue Jun 9 17:36:31 2009 for CMSSW by  doxygen 1.5.4