00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <cstdarg>
00018
00019 #include "InitSequencer.h"
00020 #include "../util/Singleton.h"
00021
00022 namespace oasys {
00023
00025
00026
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
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
00176 if (step->dependencies().size() == 0)
00177 {
00178 step_stack.push_back(step);
00179 }
00180 }
00181
00182
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
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
00287 extra_dependencies_.clear();
00288 }
00289
00291
00292
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 }