00001 #include <cstdarg>
00002
00003 #include "InitSequencer.h"
00004 #include "../util/Singleton.h"
00005
00006 namespace oasys {
00007
00009
00010
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
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
00160 if (step->dependencies().size() == 0)
00161 {
00162 step_stack.push_back(step);
00163 }
00164 }
00165
00166
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
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
00271 extra_dependencies_.clear();
00272 }
00273
00275
00276
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 }