$treeview $search $mathjax $extrastylesheet
artdaq
v3_04_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "art/Framework/Core/FileBlock.h" 00002 #include "art/Framework/Core/InputSourceMacros.h" 00003 #include "art/Framework/Core/ProductRegistryHelper.h" 00004 #include "art/Framework/IO/Sources/Source.h" 00005 #include "art/Framework/IO/Sources/SourceHelper.h" 00006 #include "art/Framework/IO/Sources/SourceTraits.h" 00007 #include "art/Framework/Services/Registry/ServiceHandle.h" 00008 00009 #include "art/Persistency/Provenance/MasterProductRegistry.h" 00010 #include "art/Persistency/Provenance/ProcessHistoryRegistry.h" 00011 #include "art/Persistency/Provenance/ProductMetaData.h" 00012 00013 #include "canvas/Persistency/Common/EDProduct.h" 00014 #include "canvas/Persistency/Common/Wrapper.h" 00015 #include "canvas/Persistency/Provenance/BranchDescription.h" 00016 #include "canvas/Persistency/Provenance/BranchKey.h" 00017 #include "canvas/Persistency/Provenance/History.h" 00018 #include "canvas/Persistency/Provenance/ParentageRegistry.h" 00019 #include "canvas/Persistency/Provenance/ProcessConfiguration.h" 00020 #include "canvas/Persistency/Provenance/ProcessHistory.h" 00021 #include "canvas/Persistency/Provenance/ProcessHistoryID.h" 00022 #include "canvas/Persistency/Provenance/ProductList.h" 00023 #include "canvas/Persistency/Provenance/ProductProvenance.h" 00024 #include "canvas/Utilities/DebugMacros.h" 00025 00026 #include "fhiclcpp/ParameterSet.h" 00027 #include "fhiclcpp/ParameterSetID.h" 00028 #include "fhiclcpp/ParameterSetRegistry.h" 00029 #include "fhiclcpp/make_ParameterSet.h" 00030 00031 #include <TBufferFile.h> 00032 #include <TClass.h> 00033 #include <TMessage.h> 00034 00035 #include "artdaq-core/Data/detail/ParentageMap.hh" 00036 #include "artdaq-core/Utilities/ExceptionHandler.hh" 00037 #include "artdaq/ArtModules/InputUtilities.hh" 00038 #include "artdaq/DAQdata/Globals.hh" 00039 00040 #include <sys/time.h> 00041 #include <cstdio> 00042 #include <iomanip> 00043 #include <iostream> 00044 #include <memory> 00045 #include <sstream> 00046 #include <string> 00047 #include <vector> 00048 00049 namespace art { 00050 template <typename U> 00051 class ArtdaqInput; 00052 } 00053 00068 template <typename U> 00069 class art::ArtdaqInput { 00070 public: 00074 ArtdaqInput(const ArtdaqInput&) = delete; 00075 00080 ArtdaqInput& operator=(const ArtdaqInput&) = delete; 00081 00085 ~ArtdaqInput(); 00086 00093 ArtdaqInput(const fhicl::ParameterSet& ps, art::ProductRegistryHelper& helper, art::SourceHelper const& pm); 00094 00098 void closeCurrentFile(); 00099 00104 void readFile(const std::string&, art::FileBlock*& fb); 00105 00110 bool hasMoreData() const; 00111 00121 bool readNext(art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR, art::RunPrincipal*& outR, 00122 art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE); 00123 00124 private: 00125 void readAndConstructPrincipal(std::unique_ptr<TBufferFile>&, unsigned long, art::RunPrincipal* const, 00126 art::SubRunPrincipal* const, art::RunPrincipal*&, art::SubRunPrincipal*&, 00127 art::EventPrincipal*&); 00128 00129 template <class T> 00130 void readDataProducts(std::unique_ptr<TBufferFile>&, T*&); 00131 00132 void putInPrincipal(RunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&, 00133 std::unique_ptr<const ProductProvenance>&&); 00134 00135 void putInPrincipal(SubRunPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&, 00136 std::unique_ptr<const ProductProvenance>&&); 00137 00138 void putInPrincipal(EventPrincipal*&, std::unique_ptr<EDProduct>&&, const BranchDescription&, 00139 std::unique_ptr<const ProductProvenance>&&); 00140 00141 private: 00142 bool shutdownMsgReceived_; 00143 bool outputFileCloseNeeded_; 00144 art::SourceHelper const& pm_; 00145 U communicationWrapper_; 00146 }; 00147 00148 template <typename U> 00149 art::ArtdaqInput<U>::ArtdaqInput(const fhicl::ParameterSet& ps, art::ProductRegistryHelper& helper, 00150 art::SourceHelper const& pm) 00151 : shutdownMsgReceived_(false), outputFileCloseNeeded_(false), pm_(pm), communicationWrapper_(ps) { 00152 artdaq::configureMessageFacility("artdaqart"); 00153 00154 // JCF, May-27-2016 00155 00156 // Something will have to be done about the labeling of this class, 00157 // since it's just a template class- the user will care about the 00158 // specific instantiation when it comes to messages 00159 00160 TLOG_ARB(5, "ArtdaqInput") << "Begin: ArtdaqInput::ArtdaqInput(" 00161 << "const fhicl::ParameterSet& ps, " 00162 << "art::ProductRegistryHelper& helper, " 00163 << "const art::SourceHelper& pm)"; 00164 (void)helper; 00165 00166 TLOG_ARB(5, "ArtdaqInput") << "Going to receive init message"; 00167 std::unique_ptr<TBufferFile> msg(nullptr); 00168 communicationWrapper_.receiveInitMessage(msg); 00169 TLOG_ARB(5, "ArtdaqInput") << "Init message received"; 00170 00171 if (!msg) { 00172 throw art::Exception(art::errors::DataCorruption) << "ArtdaqInput: Could not receive init message!"; 00173 } 00174 00175 // This first unsigned long is the message type code, ignored here in the constructor 00176 unsigned long dummy = 0; 00177 msg->ReadULong(dummy); 00178 00179 // 00180 // Read the ParameterSetRegistry. 00181 // 00182 unsigned long ps_cnt = 0; 00183 msg->ReadULong(ps_cnt); 00184 TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: parameter set count: " << ps_cnt; 00185 TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: reading parameter sets ..."; 00186 for (unsigned long I = 0; I < ps_cnt; ++I) { 00187 std::string pset_str = ""; // = ReadObjectAny<std::string>(msg, "std::string", "ArtdaqInput::ArtdaqInput"); 00188 msg->ReadStdString(pset_str); 00189 00190 TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: parameter set: " << pset_str; 00191 00192 fhicl::ParameterSet pset; 00193 fhicl::make_ParameterSet(pset_str, pset); 00194 // Force id calculation. 00195 pset.id(); 00196 fhicl::ParameterSetRegistry::put(pset); 00197 } 00198 TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: finished reading parameter sets."; 00199 // 00200 // Read the MasterProductRegistry. 00201 // 00202 00203 art::ProductList* productlist = ReadObjectAny<art::ProductList>( 00204 msg, "std::map<art::BranchKey,art::BranchDescription>", "ArtdaqInput::ArtdaqInput"); 00205 helper.productList(productlist); 00206 TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: got product list"; 00207 00208 TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: Reading ProcessHistory"; 00209 art::ProcessHistoryMap* phm = ReadObjectAny<art::ProcessHistoryMap>( 00210 msg, "std::map<const art::Hash<2>,art::ProcessHistory>", "ArtdaqInput::ArtdaqInput"); 00211 printProcessMap(*phm, "ArtdaqInput's ProcessHistoryMap"); 00212 00213 ProcessHistoryRegistry::put(*phm); 00214 printProcessMap(ProcessHistoryRegistry::get(), "ArtdaqInput's ProcessHistoryRegistry"); 00215 00216 // 00217 // Read the ParentageRegistry. 00218 // 00219 TLOG_ARB(5, "ArtdaqInput") << "ArtdaqInput: Reading ParentageMap"; 00220 ParentageMap* parentageMap = ReadObjectAny<ParentageMap>(msg, "art::ParentageMap", "ArtdaqInput::ArtdaqInput"); 00221 ParentageRegistry::put(*parentageMap); 00222 00223 // 00224 // Finished with init message. 00225 // 00226 TLOG_ARB(5, "ArtdaqInput") << "End: ArtdaqInput::ArtdaqInput(" 00227 << "const fhicl::ParameterSet& ps, " 00228 << "art::ProductRegistryHelper& helper, " 00229 << "const art::SourceHelper& pm)"; 00230 } 00231 00232 template <typename U> 00233 art::ArtdaqInput<U>::~ArtdaqInput() {} 00234 00235 template <typename U> 00236 void art::ArtdaqInput<U>::closeCurrentFile() { 00237 TLOG_ARB(6, "ArtdaqInput") << "Begin/End: ArtdaqInput::closeCurrentFile()"; 00238 } 00239 00240 template <typename U> 00241 void art::ArtdaqInput<U>::readFile(const std::string&, art::FileBlock*& fb) { 00242 TLOG_ARB(7, "ArtdaqInput") << "Begin: ArtdaqInput::" 00243 "readFile(const std::string& name, art::FileBlock*& fb)"; 00244 fb = new art::FileBlock(art::FileFormatVersion(1, "ArtdaqInput2013"), "nothing"); 00245 TLOG_ARB(7, "ArtdaqInput") << "End: ArtdaqInput::" 00246 "readFile(const std::string& name, art::FileBlock*& fb)"; 00247 } 00248 00249 template <typename U> 00250 bool art::ArtdaqInput<U>::hasMoreData() const { 00251 TLOG_ARB(8, "ArtdaqInput") << "Begin: ArtdaqInput::hasMoreData()"; 00252 if (shutdownMsgReceived_) { 00253 TLOG_ARB(8, "ArtdaqInput") << "ArtdaqInput::hasMoreData(): " 00254 "returning false on shutdownMsgReceived_."; 00255 TLOG_ARB(8, "ArtdaqInput") << "End: ArtdaqInput::hasMoreData()"; 00256 return false; 00257 } 00258 TLOG_ARB(8, "ArtdaqInput") << "ArtdaqInput::hasMoreData(): " 00259 "returning true on not shutdownMsgReceived_."; 00260 TLOG_ARB(8, "ArtdaqInput") << "End: ArtdaqInput::hasMoreData()"; 00261 return true; 00262 } 00263 00264 template <typename U> 00265 void art::ArtdaqInput<U>::readAndConstructPrincipal(std::unique_ptr<TBufferFile>& msg, unsigned long msg_type_code, 00266 art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR, 00267 art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR, 00268 art::EventPrincipal*& outE) { 00269 // 00270 // Process the message. 00271 // 00272 std::unique_ptr<art::RunAuxiliary> run_aux; 00273 std::unique_ptr<art::SubRunAuxiliary> subrun_aux; 00274 std::unique_ptr<art::EventAuxiliary> event_aux; 00275 std::shared_ptr<History> history; 00276 00277 // Establish default 'results' 00278 outR = 0; 00279 outSR = 0; 00280 outE = 0; 00281 00282 if (msg_type_code == 2) { // EndRun message. 00283 00284 TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: " 00285 << "processing EndRun message ..."; 00286 00287 run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary", "ArtdaqInput::readAndConstructPrincipal")); 00288 printProcessHistoryID("readAndConstructPrincipal", run_aux.get()); 00289 00290 TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: " 00291 << "making flush RunPrincipal ..."; 00292 outR = pm_.makeRunPrincipal(RunID::flushRun(), run_aux->beginTime()); 00293 00294 TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: " 00295 << "making flush SubRunPrincipal ..."; 00296 outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(), run_aux->beginTime()); 00297 00298 TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: " 00299 << "making flush EventPrincipal ..."; 00300 outE = pm_.makeEventPrincipal(EventID::flushEvent(), run_aux->endTime(), true, EventAuxiliary::Any); 00301 00302 TLOG_ARB(9, "ArtdaqInput") << "readAndConstructPrincipal: " 00303 << "finished processing EndRun message."; 00304 } else if (msg_type_code == 3) { // EndSubRun message. 00305 00306 TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: " 00307 << "processing EndSubRun message ..."; 00308 00309 subrun_aux.reset( 00310 ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary", "ArtdaqInput::readAndConstructPrincipal")); 00311 printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get()); 00312 00313 TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: " 00314 << "making flush RunPrincipal ..."; 00315 outR = pm_.makeRunPrincipal(RunID::flushRun(), subrun_aux->beginTime()); 00316 00317 // 28-Feb-2014, KAB: added the setting of the end time in the *current* 00318 // run and subrun. This is how we set the endTime in the RunPrincipal 00319 // and SubRunPrincipal objects that are written to the disk file. 00320 // This needs to happen here because: 00321 // A) setting them in every event doesn't work because the RunPrincipal 00322 // only allows us to set an end time value once 00323 // B) setting them in the "outputFileCloseNeeded_" block in the readNext() 00324 // method below doesn't work because that is too late. When this 00325 // method returns an outR with a different run number (flushRun), 00326 // the art output system closes the current file then. 00327 // C) setting them in the EndRun message block immediately above this 00328 // block wouldn't work because a) we're not currently sending endRun 00329 // events from the EBs to the AG, and b) because presumably that would 00330 // be too late, also. 00331 00332 art::Timestamp currentTime = time(0); 00333 if (inR != nullptr) { 00334 inR->setEndTime(currentTime); 00335 } 00336 if (inSR != nullptr) { 00337 inSR->setEndTime(currentTime); 00338 } 00339 00340 TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: " 00341 << "making flush SubRunPrincipal ..."; 00342 outSR = pm_.makeSubRunPrincipal(SubRunID::flushSubRun(), subrun_aux->beginTime()); 00343 00344 TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: " 00345 << "making flush EventPrincipal ..."; 00346 outE = pm_.makeEventPrincipal(EventID::flushEvent(), subrun_aux->endTime(), true, EventAuxiliary::Any); 00347 00348 TLOG_ARB(10, "ArtdaqInput") << "readAndConstructPrincipal: " 00349 << "finished processing EndSubRun message."; 00350 } else if (msg_type_code == 4) { // Event message. 00351 00352 TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: " 00353 << "processing Event message ..."; 00354 00355 run_aux.reset(ReadObjectAny<art::RunAuxiliary>(msg, "art::RunAuxiliary", "ArtdaqInput::readAndConstructPrincipal")); 00356 printProcessHistoryID("readAndConstructPrincipal", run_aux.get()); 00357 00358 subrun_aux.reset( 00359 ReadObjectAny<art::SubRunAuxiliary>(msg, "art::SubRunAuxiliary", "ArtdaqInput::readAndConstructPrincipal")); 00360 printProcessHistoryID("readAndConstructPrincipal", subrun_aux.get()); 00361 00362 event_aux.reset( 00363 ReadObjectAny<art::EventAuxiliary>(msg, "art::EventAuxiliary", "ArtdaqInput::readAndConstructPrincipal")); 00364 00365 history.reset(ReadObjectAny<art::History>(msg, "art::History", "ArtdaqInput::readAndConstructPrincipal")); 00366 printProcessHistoryID("readAndConstructPrincipal", history.get()); 00367 00368 // Can probably improve on error choice of "art::errors:Unknown" 00369 if (!history->processHistoryID().isValid()) { 00370 throw art::Exception(art::errors::Unknown) 00371 << "readAndConstructPrincipal: processHistoryID of history in Event message is invalid!"; 00372 } 00373 00374 TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: " 00375 << "inR: " << (void*)inR << " run/expected " 00376 << (inR ? std::to_string(inR->run()) : "invalid") << "/" << event_aux->run(); 00377 TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: " 00378 << "inSR: " << (void*)inSR << " run/expected " 00379 << (inSR ? std::to_string(inSR->run()) : "invalid") << "/" << event_aux->run() 00380 << ", subrun/expected " << (inSR ? std::to_string(inSR->subRun()) : "invalid") << "/" 00381 << event_aux->subRun(); 00382 00383 if ((inR == nullptr) || !inR->id().isValid() || (inR->run() != event_aux->run())) { 00384 // New run, either we have no input RunPrincipal, or the 00385 // input run number does not match the event run number. 00386 TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: making RunPrincipal ..."; 00387 outR = pm_.makeRunPrincipal(*run_aux.get()); 00388 } 00389 art::SubRunID subrun_check(event_aux->run(), event_aux->subRun()); 00390 if (inSR == 0 || subrun_check != inSR->id()) { 00391 // New SubRun, either we have no input SubRunPrincipal, or the 00392 // input subRun number does not match the event subRun number. 00393 TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: " 00394 << "making SubRunPrincipal ..."; 00395 outSR = pm_.makeSubRunPrincipal(*subrun_aux.get()); 00396 } 00397 TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: making EventPrincipal ..."; 00398 outE = pm_.makeEventPrincipal(*event_aux.get(), std::move(history)); 00399 00400 TLOG_ARB(11, "ArtdaqInput") << "readAndConstructPrincipal: " 00401 << "finished processing Event message."; 00402 } 00403 } 00404 00405 template <typename U> 00406 template <class T> 00407 void art::ArtdaqInput<U>::readDataProducts(std::unique_ptr<TBufferFile>& msg, T*& outPrincipal) { 00408 unsigned long prd_cnt = 0; 00409 { 00410 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: reading data product count ..."; 00411 msg->ReadULong(prd_cnt); 00412 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: product count: " << prd_cnt; 00413 } 00414 // 00415 // Read the data products. 00416 // 00417 const ProductList& productList = ProductMetaData::instance().productList(); 00418 00419 for (unsigned long I = 0; I < prd_cnt; ++I) { 00420 std::unique_ptr<BranchKey> bk; 00421 00422 { 00423 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: Reading branch key."; 00424 bk.reset(ReadObjectAny<BranchKey>(msg, "art::BranchKey", "ArtdaqInput::readDataProducts")); 00425 } 00426 00427 if (art::debugit() >= 1) { 00428 TLOG_ARB(13, "ArtdaqInput") << "readDataProducts: got product class: '" << bk->friendlyClassName_ << "' modlbl: '" 00429 << bk->moduleLabel_ << "' instnm: '" << bk->productInstanceName_ << "' procnm: '" 00430 << bk->processName_; 00431 } 00432 ProductList::const_iterator iter; 00433 { 00434 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: looking up product ..."; 00435 iter = productList.find(*bk); 00436 if (iter == productList.end()) { 00437 throw art::Exception(art::errors::ProductNotFound) 00438 << "No product is registered for\n" 00439 << " process name: '" << bk->processName_ << "'\n" 00440 << " module label: '" << bk->moduleLabel_ << "'\n" 00441 << " product friendly class name: '" << bk->friendlyClassName_ << "'\n" 00442 << " product instance name: '" << bk->productInstanceName_ << "'\n"; 00443 } 00444 } 00445 // Note: This must be a reference to the unique copy in 00446 // the master product registry! 00447 const BranchDescription& bd = iter->second; 00448 std::unique_ptr<EDProduct> prd; 00449 { 00450 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: Reading product with wrapped name: " << bd.wrappedName() 00451 << ", TClass = " << (void*)TClass::GetClass(bd.wrappedName().c_str()); 00452 00453 // JCF, May-25-2016 00454 // Currently unclear why the templatized version of ReadObjectAny doesn't work here... 00455 00456 // prd.reset(ReadObjectAny<EDProduct>(msg, bd.wrappedName())); 00457 00458 void* p = msg->ReadObjectAny(TClass::GetClass(bd.wrappedName().c_str())); 00459 auto pp = reinterpret_cast<EDProduct*>(p); 00460 00461 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: After ReadObjectAny(prd): p=" << p 00462 << ", EDProduct::isPresent: " << pp->isPresent(); 00463 prd.reset(pp); 00464 p = nullptr; 00465 } 00466 std::unique_ptr<const ProductProvenance> prdprov; 00467 { 00468 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: Reading product provenance."; 00469 prdprov.reset(ReadObjectAny<ProductProvenance>(msg, "art::ProductProvenance", "ArtdaqInput::readDataProducts")); 00470 } 00471 { 00472 TLOG_ARB(12, "ArtdaqInput") << "readDataProducts: inserting product: class: '" << bd.friendlyClassName() 00473 << "' modlbl: '" << bd.moduleLabel() << "' instnm: '" << bd.productInstanceName() 00474 << "' procnm: '" << bd.processName(); 00475 putInPrincipal(outPrincipal, std::move(prd), bd, std::move(prdprov)); 00476 } 00477 } 00478 } 00479 00480 template <typename U> 00481 void art::ArtdaqInput<U>::putInPrincipal(RunPrincipal*& rp, std::unique_ptr<EDProduct>&& prd, 00482 const BranchDescription& bd, 00483 std::unique_ptr<const ProductProvenance>&& prdprov) { 00484 rp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forRun(rp->id())); 00485 } 00486 00487 template <typename U> 00488 void art::ArtdaqInput<U>::putInPrincipal(SubRunPrincipal*& srp, std::unique_ptr<EDProduct>&& prd, 00489 const BranchDescription& bd, 00490 std::unique_ptr<const ProductProvenance>&& prdprov) { 00491 srp->put(std::move(prd), bd, std::move(prdprov), RangeSet::forSubRun(srp->id())); 00492 } 00493 00494 template <typename U> 00495 void art::ArtdaqInput<U>::putInPrincipal(EventPrincipal*& ep, std::unique_ptr<EDProduct>&& prd, 00496 const BranchDescription& bd, 00497 std::unique_ptr<const ProductProvenance>&& prdprov) { 00498 TLOG_ARB(14, "ArtdaqInput") << "EventPrincipal size before put: " << ep->size(); 00499 ep->put(std::move(prd), bd, std::move(prdprov)); 00500 TLOG_ARB(14, "ArtdaqInput") << "EventPrincipal size after put: " << ep->size(); 00501 } 00502 00503 template <typename U> 00504 bool art::ArtdaqInput<U>::readNext(art::RunPrincipal* const inR, art::SubRunPrincipal* const inSR, 00505 art::RunPrincipal*& outR, art::SubRunPrincipal*& outSR, art::EventPrincipal*& outE) { 00506 TLOG_ARB(15, "ArtdaqInput") << "Begin: ArtdaqInput::readNext"; 00507 if (outputFileCloseNeeded_) { 00508 outputFileCloseNeeded_ = false; 00509 // Signal that we need the output file closed by returning false, 00510 // but answering true to the hasMoreData() query. 00511 TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext: " 00512 << "returning false on outputFileCloseNeeded_"; 00513 TLOG_ARB(15, "ArtdaqInput") << "End: ArtdaqInput::readNext"; 00514 return false; 00515 } 00516 00517 std::unique_ptr<TBufferFile> msg; 00518 communicationWrapper_.receiveMessage(msg); 00519 00520 if (!msg) { 00521 TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext got an empty message"; 00522 shutdownMsgReceived_ = true; 00523 return false; 00524 } 00525 00526 // 00527 // Read message type code. 00528 // 00529 unsigned long msg_type_code = 0; 00530 { 00531 TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext: " 00532 << "getting message type code ..."; 00533 msg->ReadULong(msg_type_code); 00534 TLOG_ARB(15, "ArtdaqInput") << "ArtdaqInput::readNext: " 00535 << "message type: " << msg_type_code; 00536 } 00537 if (msg_type_code == 5) { 00538 // Shutdown message. 00539 shutdownMsgReceived_ = true; 00540 TLOG_ARB(16, "ArtdaqInput") << "ArtdaqInput::readNext: " 00541 << "returning false on Shutdown message."; 00542 TLOG_ARB(16, "ArtdaqInput") << "End: ArtdaqInput::readNext"; 00543 return false; 00544 } 00545 00546 readAndConstructPrincipal(msg, msg_type_code, inR, inSR, outR, outSR, outE); 00547 // 00548 // Read per-event metadata needed to construct principal. 00549 // 00550 if (msg_type_code == 2) { 00551 // EndRun message. 00552 // FIXME: We need to merge these into the input RunPrincipal. 00553 readDataProducts(msg, outR); 00554 // Signal that we should close the input and output file. 00555 TLOG_ARB(17, "ArtdaqInput") << "ArtdaqInput::readNext: " 00556 << "returning false on EndRun message."; 00557 TLOG_ARB(17, "ArtdaqInput") << "End: ArtdaqInput::readNext"; 00558 return false; 00559 } else if (msg_type_code == 3) { 00560 // EndSubRun message. 00561 // From the code above, EndRun and EndSubRun messages cause 00562 // the construction of principals that have: 00563 // Run:Subrun:Event=flush:flush:flush. 00564 // This is a problem when you have two neighboring EndSubRuns 00565 // which are both associated with empty subruns because art will 00566 // complain that you a new subrun with a subrun number identical 00567 // to that of the previous subrun. So the solution is to not 00568 // return new principals. 00569 if (inR != 0 && inSR != 0 && outR != 0 && outSR != 0) { 00570 if (inR->id().isFlush() && inSR->id().isFlush() && outR->id().isFlush() && outSR->id().isFlush()) { 00571 outR = 0; 00572 outSR = 0; 00573 outputFileCloseNeeded_ = true; 00574 return true; 00575 } 00576 } 00577 // FIXME: We need to merge these into the input SubRunPrincipal. 00578 readDataProducts(msg, outSR); 00579 // Remember that we should ask for file close next time 00580 // we are called. 00581 outputFileCloseNeeded_ = true; 00582 TLOG_ARB(18, "ArtdaqInput") << "readNext: returning true on EndSubRun message."; 00583 TLOG_ARB(18, "ArtdaqInput") << "End: ArtdaqInput::readNext"; 00584 return true; 00585 } else if (msg_type_code == 4) { 00586 // Event message. 00587 readDataProducts(msg, outE); 00588 TLOG_ARB(19, "ArtdaqInput") << "readNext: returning true on Event message."; 00589 TLOG_ARB(19, "ArtdaqInput") << "End: ArtdaqInput::readNext"; 00590 return true; 00591 } 00592 // Unknown message. 00593 // FIXME: What do we throw here for invalid message code? 00594 TLOG_ARB(20, "ArtdaqInput") << "readNext: returning false on unknown msg_type_code!"; 00595 TLOG_ARB(20, "ArtdaqInput") << "End: ArtdaqInput::readNext"; 00596 return false; 00597 }