InitSequencer.cc

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

Generated on Fri Dec 22 14:47:59 2006 for DTN Reference Implementation by  doxygen 1.5.1