00001
00002 #include "FWCore/Framework/src/EPStates.h"
00003 #include "FWCore/Framework/interface/IEventProcessor.h"
00004
00005 #include <cassert>
00006 #include <exception>
00007 #include <sstream>
00008 #include <string>
00009
00010 namespace statemachine {
00011 namespace {
00012 int const INVALID_RUN_NUMBER = 0;
00013 int const INVALID_LUMI = 0;
00014 Run const INVALID_RUN(edm::ProcessHistoryID(), INVALID_RUN_NUMBER);
00015 HandleLumis::LumiID const InvalidLumiID = HandleLumis::LumiID(edm::ProcessHistoryID(), INVALID_RUN_NUMBER, INVALID_LUMI);
00016 }
00017
00018 Run::Run(edm::ProcessHistoryID const& phid, int runNumber) :
00019 processHistoryID_(phid),
00020 runNumber_(runNumber) {
00021 }
00022
00023 Lumi::Lumi(int id) : id_(id) {}
00024
00025 Machine::Machine(edm::IEventProcessor* ep,
00026 FileMode fileMode,
00027 EmptyRunLumiMode emptyRunLumiMode) :
00028 ep_(ep),
00029 fileMode_(fileMode),
00030 emptyRunLumiMode_(emptyRunLumiMode) {
00031 }
00032
00033 edm::IEventProcessor& Machine::ep() const { return *ep_; }
00034 FileMode Machine::fileMode() const { return fileMode_; }
00035 EmptyRunLumiMode Machine::emptyRunLumiMode() const { return emptyRunLumiMode_; }
00036
00037 void Machine::startingNewLoop(File const&) {
00038 ep_->startingNewLoop();
00039 }
00040
00041 void Machine::startingNewLoop(Stop const&) {
00042 if(ep_->alreadyHandlingException()) return;
00043 ep_->startingNewLoop();
00044 }
00045
00046 void Machine::rewindAndPrepareForNextLoop(Restart const&) {
00047 ep_->prepareForNextLoop();
00048 ep_->rewindInput();
00049 }
00050
00051 Starting::Starting(my_context ctx) : my_base(ctx) { }
00052
00053 Starting::~Starting() { }
00054
00055 HandleFiles::HandleFiles(my_context ctx) :
00056 my_base(ctx),
00057 ep_(context<Machine>().ep()),
00058 exitCalled_(false) { }
00059
00060 void HandleFiles::exit() {
00061 if(ep_.alreadyHandlingException()) return;
00062 exitCalled_ = true;
00063 closeFiles();
00064 }
00065
00066 HandleFiles::~HandleFiles() {
00067 if(!exitCalled_) {
00068 try {
00069 closeFiles();
00070 }
00071 catch(...) {
00072 std::string message("Another exception was caught while trying to clean up files after the primary fatal exception.");
00073 ep_.setExceptionMessageFiles(message);
00074 }
00075 }
00076 }
00077
00078 void HandleFiles::closeFiles() {
00079 ep_.respondToCloseInputFile();
00080 ep_.closeInputFile();
00081 ep_.respondToCloseOutputFiles();
00082 ep_.closeOutputFiles();
00083 }
00084
00085 void HandleFiles::goToNewInputFile() {
00086 ep_.respondToCloseInputFile();
00087 ep_.closeInputFile();
00088
00089 ep_.readFile();
00090 ep_.respondToOpenInputFile();
00091 }
00092
00093 bool HandleFiles::shouldWeCloseOutput() {
00094 if(context<Machine>().fileMode() == NOMERGE) return true;
00095 return ep_.shouldWeCloseOutput();
00096 }
00097
00098 EndingLoop::EndingLoop(my_context ctx) :
00099 my_base(ctx),
00100 ep_(context<Machine>().ep()) {
00101 if(ep_.alreadyHandlingException() || ep_.endOfLoop()) post_event(Stop());
00102 else post_event(Restart());
00103 }
00104
00105 EndingLoop::~EndingLoop() { }
00106
00107 sc::result EndingLoop::react(Stop const&) {
00108 return terminate();
00109 }
00110
00111 Error::Error(my_context ctx) :
00112 my_base(ctx),
00113 ep_(context<Machine>().ep()) {
00114 post_event(Stop());
00115 ep_.doErrorStuff();
00116 }
00117
00118 Error::~Error() { }
00119
00120 class HandleNewInputFile1;
00121 class NewInputAndOutputFiles;
00122
00123 FirstFile::FirstFile(my_context ctx) :
00124 my_base(ctx),
00125 ep_(context<Machine>().ep()) {
00126 openFiles();
00127 }
00128
00129 FirstFile::~FirstFile() { }
00130
00131 sc::result FirstFile::react(File const&) {
00132 if(context<HandleFiles>().shouldWeCloseOutput()) {
00133 return transit<NewInputAndOutputFiles>();
00134 } else {
00135 return transit<HandleNewInputFile1>();
00136 }
00137 }
00138
00139 void FirstFile::openFiles() {
00140 ep_.readFile();
00141 ep_.respondToOpenInputFile();
00142
00143 ep_.openOutputFiles();
00144 ep_.respondToOpenOutputFiles();
00145 }
00146
00147 HandleNewInputFile1::HandleNewInputFile1(my_context ctx) :
00148 my_base(ctx) {
00149 context<HandleFiles>().goToNewInputFile();
00150 }
00151
00152 HandleNewInputFile1::~HandleNewInputFile1() { }
00153
00154 sc::result HandleNewInputFile1::react(File const&) {
00155 if(context<HandleFiles>().shouldWeCloseOutput()) {
00156 return transit<NewInputAndOutputFiles>();
00157 } else {
00158 return transit<HandleNewInputFile1>();
00159 }
00160 }
00161
00162 NewInputAndOutputFiles::NewInputAndOutputFiles(my_context ctx) :
00163 my_base(ctx),
00164 ep_(context<Machine>().ep()) {
00165 goToNewInputAndOutputFiles();
00166 }
00167
00168 NewInputAndOutputFiles::~NewInputAndOutputFiles() { }
00169
00170 sc::result NewInputAndOutputFiles::react(File const&) {
00171 if(context<HandleFiles>().shouldWeCloseOutput()) {
00172 return transit<NewInputAndOutputFiles>();
00173 } else {
00174 return transit<HandleNewInputFile1>();
00175 }
00176 }
00177
00178 void NewInputAndOutputFiles::goToNewInputAndOutputFiles() {
00179 ep_.respondToCloseInputFile();
00180 ep_.closeInputFile();
00181
00182 ep_.respondToCloseOutputFiles();
00183 ep_.closeOutputFiles();
00184
00185 ep_.readFile();
00186 ep_.respondToOpenInputFile();
00187
00188 ep_.openOutputFiles();
00189 ep_.respondToOpenOutputFiles();
00190 }
00191
00192 HandleRuns::HandleRuns(my_context ctx) :
00193 my_base(ctx),
00194 ep_(context<Machine>().ep()),
00195 exitCalled_(false),
00196 beginRunCalled_(false),
00197 currentRun_(INVALID_RUN),
00198 runException_(false) { }
00199
00200 void HandleRuns::exit() {
00201 if(ep_.alreadyHandlingException()) return;
00202 exitCalled_ = true;
00203 finalizeRun();
00204 }
00205
00206 HandleRuns::~HandleRuns() {
00207 if(!exitCalled_) {
00208 try {
00209 finalizeRun();
00210 }
00211 catch(...) {
00212 std::string message("Another exception was caught while trying to clean up runs after the primary fatal exception.");
00213 ep_.setExceptionMessageRuns(message);
00214 }
00215 }
00216 }
00217
00218 bool HandleRuns::beginRunCalled() const { return beginRunCalled_; }
00219 Run const& HandleRuns::currentRun() const { return currentRun_; }
00220 bool HandleRuns::runException() const { return runException_; }
00221
00222 void HandleRuns::setupCurrentRun() {
00223
00224 runException_ = true;
00225 currentRun_ = ep_.readAndCacheRun(false);
00226 runException_ = false;
00227
00228 if(context<Machine>().emptyRunLumiMode() != doNotHandleEmptyRunsAndLumis) {
00229 beginRun(currentRun());
00230 }
00231 }
00232
00233 void HandleRuns::beginRun(Run const& run) {
00234 beginRunCalled_ = true;
00235
00236 runException_ = true;
00237 ep_.beginRun(run);
00238 runException_ = false;
00239 }
00240
00241 void HandleRuns::endRun(Run const& run) {
00242 beginRunCalled_ = false;
00243
00244 runException_ = true;
00245 ep_.endRun(run);
00246 runException_ = false;
00247 }
00248
00249 void HandleRuns::finalizeRun(Run const&) {
00250 finalizeRun();
00251 }
00252
00253 void HandleRuns::finalizeRun() {
00254
00255 if(runException_) return;
00256 runException_ = true;
00257
00258 if(beginRunCalled_) endRun(currentRun());
00259 ep_.writeRun(currentRun_);
00260 ep_.deleteRunFromCache(currentRun_);
00261 currentRun_ = INVALID_RUN;
00262 runException_ = false;
00263 }
00264
00265 void HandleRuns::beginRunIfNotDoneAlready() {
00266 if(!beginRunCalled_) beginRun(currentRun());
00267 }
00268
00269 NewRun::NewRun(my_context ctx) :
00270 my_base(ctx) {
00271 assert(context<HandleRuns>().currentRun() == INVALID_RUN);
00272 context<HandleRuns>().setupCurrentRun();
00273
00274
00275
00276
00277 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00278 }
00279
00280 NewRun::~NewRun() { }
00281
00282 sc::result NewRun::react(Run const& run) {
00283 if(run == context<HandleRuns>().currentRun()) {
00284 return transit<ContinueRun1>();
00285 }
00286 context<HandleRuns>().finalizeRun();
00287 return transit<NewRun>();
00288 }
00289
00290 sc::result NewRun::react(File const&) {
00291 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00292 return transit<HandleNewInputFile2>();
00293 }
00294 return forward_event();
00295 }
00296
00297 HandleNewInputFile2::HandleNewInputFile2(my_context ctx) :
00298 my_base(ctx) {
00299 context<HandleFiles>().goToNewInputFile();
00300 checkInvariant();
00301 }
00302
00303 HandleNewInputFile2::~HandleNewInputFile2() {
00304 checkInvariant();
00305 }
00306
00307 bool HandleNewInputFile2::checkInvariant() {
00308 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00309 return true;
00310 }
00311
00312 sc::result HandleNewInputFile2::react(Run const& run) {
00313 checkInvariant();
00314
00315 if(context<HandleRuns>().currentRun() != run) {
00316 return transit<NewRun, HandleRuns, Run>(&HandleRuns::finalizeRun, run);
00317 } else {
00318 return transit<ContinueRun1>();
00319 }
00320 }
00321
00322 sc::result HandleNewInputFile2::react(File const&) {
00323 checkInvariant();
00324 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00325 return transit<HandleNewInputFile2>();
00326 }
00327 return forward_event();
00328 }
00329
00330 ContinueRun1::ContinueRun1(my_context ctx) :
00331 my_base(ctx),
00332 ep_(context<Machine>().ep()) {
00333 ep_.readAndCacheRun(true);
00334 checkInvariant();
00335 }
00336
00337 ContinueRun1::~ContinueRun1() {
00338 checkInvariant();
00339 }
00340
00341 bool ContinueRun1::checkInvariant() {
00342 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00343 return true;
00344 }
00345
00346 sc::result ContinueRun1::react(Run const& run) {
00347 checkInvariant();
00348 if(context<HandleRuns>().currentRun() != run) {
00349 return transit<NewRun, HandleRuns, Run>(&HandleRuns::finalizeRun, run);
00350 } else {
00351 return transit<ContinueRun1>();
00352 }
00353 }
00354
00355 sc::result ContinueRun1::react(File const&) {
00356 checkInvariant();
00357 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00358 return transit<HandleNewInputFile2>();
00359 }
00360 return forward_event();
00361 }
00362
00363 HandleLumis::LumiID::LumiID(edm::ProcessHistoryID const& phid, int run, int lumi) :
00364 processHistoryID_(phid),
00365 run_(run),
00366 lumi_(lumi) {
00367 }
00368
00369 HandleLumis::HandleLumis(my_context ctx) :
00370 my_base(ctx),
00371 ep_(context<Machine>().ep()),
00372 exitCalled_(false),
00373 currentLumiEmpty_(true),
00374 currentLumi_(InvalidLumiID),
00375 lumiException_(false) {
00376 checkInvariant();
00377 }
00378
00379 void HandleLumis::exit() {
00380 if(ep_.alreadyHandlingException()) return;
00381 exitCalled_ = true;
00382 checkInvariant();
00383 if(!lumiException_ && !context<HandleRuns>().runException()) {
00384 finalizeLumi();
00385 }
00386 }
00387
00388 HandleLumis::~HandleLumis() {
00389 if(!exitCalled_) {
00390 try {
00391 checkInvariant();
00392 if(!lumiException_ && !context<HandleRuns>().runException()) {
00393 finalizeLumi();
00394 }
00395 }
00396 catch(...) {
00397 std::string message("Another exception was caught while trying to clean up lumis after the primary fatal exception.");
00398 ep_.setExceptionMessageLumis(message);
00399 }
00400 }
00401 }
00402
00403 bool HandleLumis::checkInvariant() {
00404 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00405 return true;
00406 }
00407
00408 HandleLumis::LumiID const& HandleLumis::currentLumi() const { return currentLumi_; }
00409
00410 bool HandleLumis::currentLumiEmpty() const { return currentLumiEmpty_; }
00411
00412 void HandleLumis::setupCurrentLumi() {
00413
00414 Run const& run = context<HandleRuns>().currentRun();
00415 assert(run != INVALID_RUN);
00416 lumiException_ = true;
00417 currentLumi_ = HandleLumis::LumiID(run.processHistoryID(), run.runNumber(), ep_.readAndCacheLumi(false));
00418
00419 if(context<Machine>().emptyRunLumiMode() == handleEmptyRunsAndLumis) {
00420 assert(context<HandleRuns>().beginRunCalled());
00421 ep_.beginLumi(currentLumi().processHistoryID(), currentLumi().run(), currentLumi().lumi());
00422 }
00423
00424 lumiException_ = false;
00425
00426 currentLumiEmpty_ = true;
00427 }
00428
00429 void HandleLumis::finalizeLumi() {
00430
00431 lumiException_ = true;
00432
00433 if(!currentLumiEmpty_ ||
00434 context<Machine>().emptyRunLumiMode() == handleEmptyRunsAndLumis) {
00435 ep_.endLumi(currentLumi().processHistoryID(), currentLumi().run(), currentLumi().lumi());
00436 }
00437
00438 ep_.writeLumi(currentLumi().processHistoryID(), currentLumi().run(), currentLumi().lumi());
00439 ep_.deleteLumiFromCache(currentLumi().processHistoryID(), currentLumi().run(), currentLumi().lumi());
00440 currentLumi_ = InvalidLumiID;
00441
00442 lumiException_ = false;
00443 }
00444
00445 void HandleLumis::markLumiNonEmpty() {
00446 if(currentLumiEmpty_) {
00447
00448 if(context<Machine>().emptyRunLumiMode() != handleEmptyRunsAndLumis) {
00449 lumiException_ = true;
00450 ep_.beginLumi(currentLumi().processHistoryID(), currentLumi().run(), currentLumi().lumi());
00451 lumiException_ = false;
00452 }
00453 currentLumiEmpty_ = false;
00454 }
00455 }
00456
00457 FirstLumi::FirstLumi(my_context ctx) :
00458 my_base(ctx) {
00459 context<HandleLumis>().setupCurrentLumi();
00460 checkInvariant();
00461 }
00462
00463 FirstLumi::~FirstLumi() {
00464 checkInvariant();
00465 }
00466
00467 bool FirstLumi::checkInvariant() {
00468 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00469 assert(context<HandleLumis>().currentLumi().processHistoryID() == context<HandleRuns>().currentRun().processHistoryID());
00470 assert(context<HandleLumis>().currentLumi().run() == context<HandleRuns>().currentRun().runNumber());
00471 assert(context<HandleLumis>().currentLumi().lumi() != INVALID_LUMI);
00472 assert(context<HandleLumis>().currentLumiEmpty() == true);
00473 return true;
00474 }
00475
00476 sc::result FirstLumi::react(Lumi const& lumi) {
00477 if(lumi.id() == context<HandleLumis>().currentLumi().lumi()) {
00478 return transit<ContinueLumi>();
00479 }
00480 return transit<AnotherLumi>();
00481 }
00482
00483 sc::result FirstLumi::react(File const&) {
00484 checkInvariant();
00485 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00486 return transit<HandleNewInputFile3>();
00487 }
00488 return forward_event();
00489 }
00490
00491 AnotherLumi::AnotherLumi(my_context ctx) :
00492 my_base(ctx) {
00493 context<HandleLumis>().finalizeLumi();
00494 context<HandleLumis>().setupCurrentLumi();
00495 checkInvariant();
00496 }
00497
00498 AnotherLumi::~AnotherLumi() {
00499 checkInvariant();
00500 }
00501
00502 bool AnotherLumi::checkInvariant() {
00503 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00504 assert(context<HandleLumis>().currentLumi().processHistoryID() == context<HandleRuns>().currentRun().processHistoryID());
00505 assert(context<HandleLumis>().currentLumi().run() == context<HandleRuns>().currentRun().runNumber());
00506 assert(context<HandleLumis>().currentLumi().lumi() != INVALID_LUMI);
00507 assert(context<HandleLumis>().currentLumiEmpty() == true);
00508 return true;
00509 }
00510
00511 sc::result AnotherLumi::react(Lumi const& lumi) {
00512 if(lumi.id() == context<HandleLumis>().currentLumi().lumi()) {
00513 return transit<ContinueLumi>();
00514 }
00515 return transit<AnotherLumi>();
00516 }
00517
00518 sc::result AnotherLumi::react(File const&) {
00519 checkInvariant();
00520 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00521 return transit<HandleNewInputFile3>();
00522 }
00523 return forward_event();
00524 }
00525
00526 HandleEvent::HandleEvent(my_context ctx) :
00527 my_base(ctx),
00528 ep_(context<Machine>().ep()) {
00529 readAndProcessEvent();
00530 checkInvariant();
00531 }
00532
00533 HandleEvent::~HandleEvent() {
00534 checkInvariant();
00535 }
00536
00537 bool HandleEvent::checkInvariant() {
00538 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00539 assert(context<HandleRuns>().beginRunCalled());
00540 assert(context<HandleLumis>().currentLumi().processHistoryID() == context<HandleRuns>().currentRun().processHistoryID());
00541 assert(context<HandleLumis>().currentLumi().run() == context<HandleRuns>().currentRun().runNumber());
00542 assert(context<HandleLumis>().currentLumi().lumi() != INVALID_LUMI);
00543 assert(context<HandleLumis>().currentLumiEmpty() == false);
00544 return true;
00545 }
00546
00547 sc::result HandleEvent::react(File const&) {
00548 checkInvariant();
00549 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00550 return transit<HandleNewInputFile3>();
00551 }
00552 return forward_event();
00553 }
00554
00555 void HandleEvent::readAndProcessEvent() {
00556 markNonEmpty();
00557 ep_.readAndProcessEvent();
00558 if(ep_.shouldWeStop()) post_event(Stop());
00559 }
00560
00561 void HandleEvent::markNonEmpty() {
00562 context<HandleRuns>().beginRunIfNotDoneAlready();
00563 context<HandleLumis>().markLumiNonEmpty();
00564 }
00565
00566
00567 HandleNewInputFile3::HandleNewInputFile3(my_context ctx) :
00568 my_base(ctx) {
00569 context<HandleFiles>().goToNewInputFile();
00570 checkInvariant();
00571 }
00572
00573 HandleNewInputFile3::~HandleNewInputFile3() {
00574 checkInvariant();
00575 }
00576
00577 bool HandleNewInputFile3::checkInvariant() {
00578 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00579 assert(context<HandleLumis>().currentLumi().processHistoryID() == context<HandleRuns>().currentRun().processHistoryID());
00580 assert(context<HandleLumis>().currentLumi().run() == context<HandleRuns>().currentRun().runNumber());
00581 assert(context<HandleLumis>().currentLumi().lumi() != INVALID_LUMI);
00582 return true;
00583 }
00584
00585 sc::result HandleNewInputFile3::react(Run const& run) {
00586 checkInvariant();
00587
00588 if(context<HandleRuns>().currentRun() == run) {
00589 return transit<ContinueRun2>();
00590 }
00591 return forward_event();
00592 }
00593
00594 sc::result HandleNewInputFile3::react(File const&) {
00595 checkInvariant();
00596 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00597 return transit<HandleNewInputFile3>();
00598 }
00599 return forward_event();
00600 }
00601
00602 ContinueRun2::ContinueRun2(my_context ctx) :
00603 my_base(ctx),
00604 ep_(context<Machine>().ep()) {
00605 ep_.readAndCacheRun(true);
00606 checkInvariant();
00607 }
00608
00609 ContinueRun2::~ContinueRun2() {
00610 checkInvariant();
00611 }
00612
00613 bool ContinueRun2::checkInvariant() {
00614 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00615 assert(context<HandleLumis>().currentLumi().processHistoryID() == context<HandleRuns>().currentRun().processHistoryID());
00616 assert(context<HandleLumis>().currentLumi().run() == context<HandleRuns>().currentRun().runNumber());
00617 assert(context<HandleLumis>().currentLumi().lumi() != INVALID_LUMI);
00618 return true;
00619 }
00620
00621 sc::result ContinueRun2::react(Run const& run) {
00622 checkInvariant();
00623 if(context<HandleRuns>().currentRun() != run) {
00624 return forward_event();
00625 } else {
00626 return transit<ContinueRun2>();
00627 }
00628 }
00629
00630 sc::result ContinueRun2::react(Lumi const& lumi) {
00631 checkInvariant();
00632
00633 if(context<HandleLumis>().currentLumi().lumi() != lumi.id()) {
00634 return transit<AnotherLumi>();
00635 } else {
00636 return transit<ContinueLumi>();
00637 }
00638 }
00639
00640 sc::result ContinueRun2::react(File const&) {
00641 checkInvariant();
00642 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00643 return transit<HandleNewInputFile3>();
00644 }
00645 return forward_event();
00646 }
00647
00648 ContinueLumi::ContinueLumi(my_context ctx) :
00649 my_base(ctx),
00650 ep_(context<Machine>().ep()) {
00651 ep_.readAndCacheLumi(true);
00652 checkInvariant();
00653 }
00654
00655 ContinueLumi::~ContinueLumi() {
00656 checkInvariant();
00657 }
00658
00659 bool ContinueLumi::checkInvariant() {
00660 assert(context<HandleRuns>().currentRun() != INVALID_RUN);
00661 assert(context<HandleLumis>().currentLumi().processHistoryID() == context<HandleRuns>().currentRun().processHistoryID());
00662 assert(context<HandleLumis>().currentLumi().run() == context<HandleRuns>().currentRun().runNumber());
00663 assert(context<HandleLumis>().currentLumi().lumi() != INVALID_LUMI);
00664 return true;
00665 }
00666
00667 sc::result ContinueLumi::react(Lumi const& lumi) {
00668 checkInvariant();
00669 if(context<HandleLumis>().currentLumi().lumi() != lumi.id()) {
00670 return transit<AnotherLumi>();
00671 } else {
00672 return transit<ContinueLumi>();
00673 }
00674 }
00675
00676 sc::result ContinueLumi::react(File const&) {
00677 checkInvariant();
00678 if(!context<HandleFiles>().shouldWeCloseOutput()) {
00679 return transit<HandleNewInputFile3>();
00680 }
00681 return forward_event();
00682 }
00683 }