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 }
00040
00041 }
00042
00043
00044 NodePtr ScheduleValidator::findPathHead(std::string pathName){
00045
00046 for (PathContainer::iterator pathIt = nodes_.begin(), pathItEnd = nodes_.end();
00047 pathIt != pathItEnd; ++pathIt) {
00048
00049 if ((*pathIt)->type() != "path" &&
00050 (*pathIt)->type() != "endpath") continue;
00051 if ((*pathIt)->name() == pathName) return ((*pathIt)->wrapped());
00052
00053 }
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 }
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
00088 for (std::list<NodePtr>::iterator leafIt = leaves_.begin(), leafItEnd = leaves_.end();
00089 leafIt != leafItEnd; ++leafIt) {
00090
00091 DependencyList dep;
00092
00093
00094 Node* p = (*leafIt)->getParent();
00095 Node* son = (*leafIt).get();
00096
00097
00098
00099 while (p){
00100
00101 if (p->type() == "&") {
00102 son = p;
00103 p = p->getParent();
00104 continue;
00105 }
00106
00107 OperatorNode* node = dynamic_cast<OperatorNode*>(p);
00108
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 }
00121
00122 dep.sort();
00123 dep.unique();
00124
00125
00126
00127 leafName = (*leafIt)->name();
00128 removeUnaries(leafName);
00129
00130
00131 mergeDependencies(leafName, dep);
00132
00133 }
00134
00135 validatePaths();
00136
00137 }
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
00156
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
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
00242 if (node->type() == "operand") {
00243 std::string nodeName = node->name();
00244 removeUnaries(nodeName);
00245 dep.push_back(nodeName);
00246 }
00247
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 }
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 }