InitSequencer.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2005-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #include <cstdarg>
00018 
00019 #include "InitSequencer.h"
00020 #include "../util/Singleton.h"
00021 
00022 namespace oasys {
00023 
00025 //
00026 // InitSequencer
00027 //
00028 template<> InitSequencer* Singleton<InitSequencer>::instance_;
00029 
00031 struct InitStepSort {
00032     bool operator()(InitStep* left, InitStep* right)
00033     {
00034         return left->time() > right->time();
00035     }
00036 };
00037 
00038 
00039 InitSequencer::InitSequencer()
00040     : Logger("InitSequencer", "/oasys/init_sequencer")
00041 {
00042 }
00043 
00044 int 
00045 InitSequencer::start(std::string step, Plan* plan)
00046 {
00047     (void)plan;
00048     
00049     int err;
00050     
00051     add_extra_deps(); 
00052     mark_dep(step);
00053     err = topo_sort();
00054     if (err != 0) 
00055     {
00056         return err;
00057     }
00058 
00059     err = run_steps();
00060     if (err != 0)
00061     {
00062         return err;
00063     }
00064 
00065     return 0;
00066 }
00067 
00068 void 
00069 InitSequencer::add_step(InitStep* step)
00070 {
00071     ASSERT(step != 0);
00072     
00073     if (steps_.find(step->name()) != steps_.end()) 
00074     {
00075         log_warn("Step %s already known to sequencer, ignoring", 
00076                  step->name().c_str());
00077         return;
00078     }
00079 
00080     steps_[step->name()] = step;
00081 }
00082 
00083 InitStep*
00084 InitSequencer::get_step(const std::string& name)
00085 {
00086     ASSERT(steps_.find(name) != steps_.end());
00087     return steps_[name];
00088 }
00089 
00090 void
00091 InitSequencer::reset()
00092 {
00093     for (StepMap::iterator i = steps_.begin(); 
00094          i != steps_.end(); ++i)
00095     {
00096         i->second->done_ = false;
00097     }
00098 }
00099 
00100 void 
00101 InitSequencer::print_dot()
00102 {
00103     std::string dotfile;
00104 
00105     log_info("digraph G {");
00106     for (StepMap::const_iterator i = steps_.begin(); 
00107          i != steps_.end(); ++i)
00108     {
00109         InitStep* step = i->second;
00110 
00111         log_info("\t\"%s\";", step->name().c_str());
00112 
00113         for (InitStep::DepList::const_iterator i = step->dependencies().begin();
00114              i != step->dependencies().end(); ++i)
00115         {
00116             log_info("\t\"%s\" -> \"%s\";", i->c_str(), step->name().c_str());
00117         }
00118     }    
00119     log_info("}");
00120 }
00121 
00122 int
00123 InitSequencer::run_steps()
00124 {
00125     std::vector<InitStep*> step_list;
00126 
00127     for (StepMap::iterator i = steps_.begin(); 
00128          i != steps_.end(); ++i)
00129     {
00130         step_list.push_back(i->second);
00131     }
00132     std::sort(step_list.begin(), step_list.end(), InitStepSort());
00133     
00134     int err = 0;
00135     for (std::vector<InitStep*>::iterator i = step_list.begin();
00136          i != step_list.end(); ++i)
00137     {
00138         InitStep* step = *i;
00139 
00140         log_debug("step %d %s", step->time(), step->name().c_str());
00141         if (step->mark_ && !step->done())
00142         {
00143             log_debug("running %s", step->name().c_str());
00144             ASSERT(step->dep_are_satisfied());
00145             err = step->run();
00146             if (err != 0) 
00147             {
00148                 log_warn("%s had an error, stopping...", step->name().c_str());
00149                 break;
00150             }
00151         }
00152     }
00153     return err;
00154 }
00155 
00156 int 
00157 InitSequencer::topo_sort()
00158 {
00159     std::vector<InitStep*> step_stack;
00160     ReverseDepEdges edges;
00161 
00162     // make backwards edges
00163     for (StepMap::iterator i = steps_.begin(); i != steps_.end(); ++i)
00164     {
00165         InitStep* step = i->second;
00166         step->time_    = -1;
00167 
00168         for (ReverseDepList::const_iterator j = step->dependencies().begin();
00169              j != step->dependencies().end(); ++j)
00170         {
00171             log_debug("%s edge to %s", j->c_str(), step->name().c_str());
00172             edges[*j].push_back(step->name());
00173         }
00174 
00175         // parentless, so can be started at any time        
00176         if (step->dependencies().size() == 0)
00177         {
00178             step_stack.push_back(step);
00179         }
00180     }
00181     
00182     // Perform the DFS from each dependency-less node
00183     dfs_time_ = 0;
00184     while (step_stack.size() > 0)
00185     {
00186         InitStep* step = step_stack.back();
00187         step_stack.pop_back();        
00188         dfs(step, edges);
00189     }
00190 
00191 #ifndef NDEBUG
00192     for (StepMap::iterator i = steps_.begin(); 
00193          i != steps_.end(); ++i)
00194     {
00195         InitStep* step = i->second;
00196         log_debug("step %s has time %d", step->name().c_str(), step->time_);
00197     }
00198 #endif // NDEBUG
00199 
00200     return 0;
00201 }
00202     
00203 void 
00204 InitSequencer::dfs(InitStep* step, ReverseDepEdges& edges)
00205 {
00206     for (ReverseDepList::const_iterator i = edges[step->name()].begin();
00207          i != edges[step->name()].end(); ++i)
00208     {
00209         if (steps_[*i]->time_ == -1)
00210         {
00211             dfs(steps_[*i], edges);
00212         }
00213     }
00214     
00215     step->time_ = dfs_time_;
00216     ++dfs_time_;
00217 }
00218 
00219 void 
00220 InitSequencer::mark_dep(const std::string& target)
00221 {
00222     std::vector<InitStep*> step_stack;
00223     
00224     log_debug("target is %s", target.c_str());
00225     for (StepMap::iterator i = steps_.begin(); 
00226          i != steps_.end(); ++i)
00227     {
00228         i->second->mark_ = false;
00229     }
00230 
00231    
00232     ASSERT(steps_.find(target) != steps_.end());
00233    
00234     step_stack.push_back(steps_[target]);
00235 
00236     while (step_stack.size() > 0) 
00237     {
00238         InitStep* step = step_stack.back();
00239         step_stack.pop_back();
00240 
00241         if (!step->mark_) 
00242         {
00243             step->mark_ = true;
00244             log_debug("%s is a dependent step", step->name().c_str());
00245         }        
00246 
00247         for (InitStep::DepList::const_iterator i = step->dependencies().begin();
00248              i != step->dependencies().end(); ++i)
00249         {
00250             if (steps_.find(*i) == steps_.end())
00251             {
00252                 PANIC("%s is dependent on %s which is bogus", 
00253                       step->name().c_str(), i->c_str());
00254             }
00255             
00256             if(!steps_[*i]->mark_)
00257             {
00258                 step_stack.push_back(steps_[*i]);
00259             }
00260         }
00261     }
00262 }
00263 
00264 void
00265 InitSequencer::add_extra_dep(InitExtraDependency* extra_dep)
00266 {
00267     extra_dependencies_.push_back(extra_dep);
00268 }
00269 
00270 void
00271 InitSequencer::add_extra_deps()
00272 {
00273     for (std::vector<InitExtraDependency*>::iterator i = extra_dependencies_.begin();
00274          i != extra_dependencies_.end(); ++i)
00275     {
00276         // Check that these modules are legit
00277         ASSERT(steps_.find((*i)->new_dep_)  != steps_.end());
00278         ASSERT(steps_.find((*i)->depender_) != steps_.end());        
00279 
00280         log_debug("extra dependency of %s to %s", 
00281                   (*i)->depender_.c_str(), (*i)->new_dep_.c_str());
00282 
00283         steps_[(*i)->depender_]->add_dep((*i)->new_dep_);
00284     }
00285     
00286     // clear these after the first add
00287     extra_dependencies_.clear();
00288 }
00289 
00291 //
00292 // InitStep
00293 //
00294 InitStep::InitStep(const std::string& the_namespace, 
00295                    const std::string& name)
00296     : done_(false),
00297       name_(the_namespace + "::" + name),
00298       mark_(false),
00299       time_(-1)
00300 {
00301     Singleton<InitSequencer>::instance()->add_step(this);    
00302 }
00303 
00304 InitStep::InitStep(const std::string& the_namespace, 
00305                    const std::string& name, int depsize, ...)
00306     : done_(false),
00307       name_(the_namespace + "::" + name),
00308       mark_(false),
00309       time_(-1)
00310 {
00311     va_list ap;
00312     va_start(ap, depsize);
00313     for (int i=0; i<depsize; ++i)
00314     {
00315         dependencies_.push_back(va_arg(ap, const char*));
00316     }
00317     va_end(ap);
00318     
00319     Singleton<InitSequencer>::instance()->add_step(this);
00320 }
00321 
00322 InitStep::InitStep(const std::string& the_namespace, 
00323                    const std::string& name, const DepList& deps)
00324     : done_(false),
00325       name_(the_namespace + "::" + name),
00326       dependencies_(deps),
00327       mark_(false),
00328       time_(-1)
00329 {
00330     Singleton<InitSequencer>::instance()->add_step(this);
00331 }
00332 
00333 int
00334 InitStep::run()
00335 { 
00336     int err = run_component(); 
00337     if (!err) 
00338     {
00339         done_ = true; 
00340     }
00341 
00342     return err;
00343 }
00344 
00345 bool
00346 InitStep::dep_are_satisfied()
00347 {
00348     bool sat = true;
00349     for (DepList::const_iterator i = dependencies_.begin();
00350          i != dependencies_.end(); ++i)
00351     {
00352         sat &= Singleton<InitSequencer>::instance()->get_step(*i)->done();
00353     }
00354 
00355     return sat;
00356 }
00357 
00358 } // namespace oasys

Generated on Sat Sep 8 08:43:28 2007 for DTN Reference Implementation by  doxygen 1.5.3