1 #include "art/Framework/Core/ModuleMacros.h"
2 #include "art/Framework/Core/OutputModule.h"
3 #include "art/Framework/Core/RPManager.h"
4 #include "art/Framework/Core/ResultsProducer.h"
5 #include "art/Framework/IO/ClosingCriteria.h"
6 #include "art/Framework/IO/FileStatsCollector.h"
7 #include "art/Framework/IO/PostCloseFileRenamer.h"
8 #include "art/Framework/IO/Root/DropMetaData.h"
9 #include "art/Framework/IO/Root/RootFileBlock.h"
10 #include "art/Framework/IO/Root/detail/rootOutputConfigurationTools.h"
11 #include "art/Framework/IO/detail/logFileAction.h"
12 #include "art/Framework/IO/detail/validateFileNamePattern.h"
13 #include "art/Framework/Principal/Event.h"
14 #include "art/Framework/Principal/EventPrincipal.h"
15 #include "art/Framework/Principal/Results.h"
16 #include "art/Framework/Principal/ResultsPrincipal.h"
17 #include "art/Framework/Principal/Run.h"
18 #include "art/Framework/Principal/RunPrincipal.h"
19 #include "art/Framework/Principal/SubRun.h"
20 #include "art/Framework/Principal/SubRunPrincipal.h"
21 #include "art/Persistency/Provenance/ProductMetaData.h"
22 #include "art/Utilities/parent_path.h"
23 #include "art/Utilities/unique_filename.h"
24 #include "artdaq/ArtModules/RootDAQOutput-s85/RootDAQOutFile.h"
25 #include "artdaq/DAQdata/Globals.hh"
26 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
27 #include "canvas/Persistency/Provenance/ProductTables.h"
28 #include "canvas/Utilities/Exception.h"
29 #include "fhiclcpp/ParameterSet.h"
30 #include "fhiclcpp/types/Atom.h"
31 #include "fhiclcpp/types/ConfigurationTable.h"
32 #include "fhiclcpp/types/OptionalAtom.h"
33 #include "fhiclcpp/types/OptionalSequence.h"
34 #include "fhiclcpp/types/Table.h"
35 #include "messagefacility/MessageLogger/MessageLogger.h"
37 #define TRACE_NAME (app_name + "_RootDAQOut").c_str()
48 std::string
const dev_null{
"/dev/null"};
59 static constexpr
char const* default_tmpDir{
"<parent-path-of-filename>"};
63 using Name = fhicl::Name;
64 using Comment = fhicl::Comment;
66 using Atom = fhicl::Atom<T>;
68 using OptionalAtom = fhicl::OptionalAtom<T>;
70 fhicl::TableFragment<art::OutputModule::Config> omConfig;
71 Atom<std::string> catalog{Name(
"catalog"),
""};
72 OptionalAtom<bool> dropAllEvents{Name(
"dropAllEvents")};
73 Atom<bool> dropAllSubRuns{Name(
"dropAllSubRuns"),
false};
74 OptionalAtom<bool> fastCloning{Name(
"fastCloning")};
75 Atom<std::string> tmpDir{Name(
"tmpDir"), default_tmpDir};
76 Atom<int> compressionLevel{Name(
"compressionLevel"), 7};
77 Atom<unsigned> freePercent{Name(
"freePercent"), 0};
78 Atom<unsigned> freeMB{Name(
"freeMB"), 0};
79 Atom<int64_t> saveMemoryObjectThreshold{Name(
"saveMemoryObjectThreshold"),
81 Atom<int64_t> treeMaxVirtualSize{Name(
"treeMaxVirtualSize"), -1};
82 Atom<int> splitLevel{Name(
"splitLevel"), 99};
83 Atom<int> basketSize{Name(
"basketSize"), 16384};
84 Atom<bool> dropMetaDataForDroppedData{Name(
"dropMetaDataForDroppedData"),
86 Atom<std::string> dropMetaData{Name(
"dropMetaData"),
"NONE"};
87 Atom<bool> writeParameterSets{Name(
"writeParameterSets"),
true};
88 fhicl::Table<ClosingCriteria::Config> fileProperties{Name(
"fileProperties")};
89 Atom<int> firstLoggerRank{Name(
"firstLoggerRank"), -1};
93 fhicl::Atom<string> appName{fhicl::Name(
"appName")};
94 fhicl::Atom<string> newString{fhicl::Name(
"newString")};
98 fhicl::Atom<string> targetString{fhicl::Name(
"targetString")};
99 fhicl::Sequence<fhicl::Table<NewSubStringForApp>> replacementList{fhicl::Name(
"replacementList")};
101 fhicl::OptionalSequence<fhicl::Table<FileNameSubstitution>> fileNameSubstitutions{Name(
"fileNameSubstitutions")};
102 Atom<bool> enableLargeFileCatalogMetadata{
103 Name(
"enableLargeFileCatalogMetadata"),
113 using namespace fhicl::detail;
114 ParameterBase* adjustFilename{
115 const_cast<fhicl::Atom<std::string>*
>(&omConfig().fileName)};
116 adjustFilename->set_par_style(fhicl::par_style::REQUIRED);
121 std::set<std::string>
124 std::set<std::string> keys{
125 art::OutputModule::Config::KeysToIgnore::get()};
126 keys.insert(
"results");
132 using Parameters = fhicl::WrappedTable<Config, Config::KeysToIgnore>;
136 void postSelectProducts()
override;
138 void beginJob()
override;
139 void endJob()
override;
141 void event(EventPrincipal
const&)
override;
143 void beginSubRun(SubRunPrincipal
const&)
override;
144 void endSubRun(SubRunPrincipal
const&)
override;
146 void beginRun(RunPrincipal
const&)
override;
147 void endRun(RunPrincipal
const&)
override;
150 std::string fileNameAtOpen()
const;
151 std::string fileNameAtClose(std::string
const& currentFileName);
152 std::string
const& lastClosedFileName()
const override;
153 void openFile(FileBlock
const&)
override;
154 void respondToOpenInputFile(FileBlock
const&)
override;
155 void readResults(ResultsPrincipal
const& resp)
override;
156 void respondToCloseInputFile(FileBlock
const&)
override;
157 void incrementInputFileNumber()
override;
158 Granularity fileGranularity()
const override;
159 void write(EventPrincipal&)
override;
160 void writeSubRun(SubRunPrincipal&)
override;
161 void writeRun(RunPrincipal&)
override;
162 void setSubRunAuxiliaryRangeSetID(RangeSet
const&)
override;
163 void setRunAuxiliaryRangeSetID(RangeSet
const&)
override;
164 bool isFileOpen()
const override;
165 void setFileStatus(OutputFileStatus)
override;
166 bool requestsToCloseFile()
const override;
168 void startEndFile()
override;
169 void writeFileFormatVersion()
override;
170 void writeFileIndex()
override;
171 void writeEventHistory()
override;
172 void writeProcessConfigurationRegistry()
override;
173 void writeProcessHistoryRegistry()
override;
174 void writeParameterSetRegistry()
override;
175 void writeProductDescriptionRegistry()
override;
176 void writeParentageRegistry()
override;
177 void doWriteFileCatalogMetadata(
178 FileCatalogMetadata::collection_type
const& md,
179 FileCatalogMetadata::collection_type
const& ssmd)
override;
180 void writeProductDependencies()
override;
181 void finishEndFile()
override;
182 void doRegisterProducts(MasterProductRegistry& mpr,
183 ProductDescriptions& producedProducts,
184 ModuleDescription
const& md)
override;
185 std::string modifyFilePattern(std::string
const&,
Config const&);
188 std::string
const catalog_;
189 bool dropAllEvents_{
false};
190 bool dropAllSubRuns_;
191 std::string
const moduleLabel_;
192 bool enableLargeFileCatalogMetadata_{
true};
193 int inputFileCount_{0};
194 std::unique_ptr<RootDAQOutFile> rootOutputFile_{
nullptr};
195 FileStatsCollector fstats_;
196 PostCloseFileRenamer fRenamer_{fstats_};
197 std::string
const filePattern_;
199 std::string lastClosedFileName_{};
202 int const compressionLevel_;
203 unsigned freePercent_;
205 int64_t
const saveMemoryObjectThreshold_;
206 int64_t
const treeMaxVirtualSize_;
207 int const splitLevel_;
208 int const basketSize_;
209 DropMetaData dropMetaData_;
210 bool dropMetaDataForDroppedData_;
214 bool fastCloningEnabled_{
true};
219 bool writeParameterSets_;
220 ClosingCriteria fileProperties_;
223 ProductTable producedResultsProducts_{};
227 art::RootDAQOut::RootDAQOut(Parameters
const& config)
228 : OutputModule{config().omConfig, config.get_PSet()}
229 , catalog_{config().catalog()}
230 , dropAllSubRuns_{config().dropAllSubRuns()}
231 , moduleLabel_{config.get_PSet().get<
string>(
"module_label")}
232 , enableLargeFileCatalogMetadata_{config().enableLargeFileCatalogMetadata()}
233 , fstats_{moduleLabel_, processName(), enableLargeFileCatalogMetadata_}
234 , filePattern_{modifyFilePattern(config().omConfig().fileName(), config())}
235 , tmpDir_{config().tmpDir() == default_tmpDir ? parent_path(filePattern_) : config().tmpDir()}
236 , compressionLevel_{config().compressionLevel()}
237 , freePercent_{config().freePercent()}
238 , freeMB_{config().freeMB()}
239 , saveMemoryObjectThreshold_{config().saveMemoryObjectThreshold()}
240 , treeMaxVirtualSize_{config().treeMaxVirtualSize()}
241 , splitLevel_{config().splitLevel()}
242 , basketSize_{config().basketSize()}
243 , dropMetaData_{config().dropMetaData()}
244 , dropMetaDataForDroppedData_{config().dropMetaDataForDroppedData()}
245 , writeParameterSets_{config().writeParameterSets()}
247 detail::validateFileNamePattern(
248 config.get_PSet().has_key(config().fileProperties.name()),
250 config().fileProperties())}
251 , rpm_{config.get_PSet()}
253 bool const dropAllEventsSet{config().dropAllEvents(dropAllEvents_)};
255 detail::shouldDropEvents(dropAllEventsSet, dropAllEvents_, dropAllSubRuns_);
262 bool const fastCloningSet{config().fastCloning(fastCloningEnabled_)};
263 fastCloningEnabled_ = detail::shouldFastClone(
264 fastCloningSet, fastCloningEnabled_, wantAllEvents(), fileProperties_);
265 if (!writeParameterSets_)
267 mf::LogWarning(
"PROVENANCE")
268 <<
"Output module " << moduleLabel_
269 <<
" has parameter writeParameterSets set to false.\n"
270 <<
"Parameter set provenance will not be available in subsequent jobs.\n"
271 <<
"Check your experiment's policy on this issue to avoid future "
273 <<
"with analysis reproducibility.\n";
277 void art::RootDAQOut::openFile(FileBlock
const& fb)
285 respondToOpenInputFile(fb);
289 void art::RootDAQOut::postSelectProducts()
293 rootOutputFile_->selectProducts();
297 void art::RootDAQOut::respondToOpenInputFile(FileBlock
const& fb)
303 auto const* rfb =
dynamic_cast<RootFileBlock const*
>(&fb);
305 bool fastCloneThisOne = fastCloningEnabled_ && rfb &&
306 (rfb->tree() !=
nullptr) &&
307 ((remainingEvents() < 0) ||
308 (remainingEvents() >= rfb->tree()->GetEntries()));
309 if (fastCloningEnabled_ && !fastCloneThisOne)
311 mf::LogWarning(
"FastCloning")
312 <<
"Fast cloning deactivated for this input file due to "
313 <<
"empty event tree and/or event limits.";
315 if (fastCloneThisOne && !rfb->fastClonable())
317 mf::LogWarning(
"FastCloning")
318 <<
"Fast cloning deactivated for this input file due to "
319 <<
"information in FileBlock.";
320 fastCloneThisOne =
false;
322 rootOutputFile_->beginInputFile(rfb, fastCloneThisOne);
323 fstats_.recordInputFile(fb.fileName());
326 void art::RootDAQOut::readResults(ResultsPrincipal
const& resp)
328 rpm_.for_each_RPWorker([&resp](RPWorker& w) { w.rp().doReadResults(resp); });
331 void art::RootDAQOut::respondToCloseInputFile(FileBlock
const& fb)
335 rootOutputFile_->respondToCloseInputFile(fb);
339 void art::RootDAQOut::write(EventPrincipal& ep)
341 TLOG(10) << __func__ <<
": enter; dropAllEvents_=" << dropAllEvents_;
346 if (hasNewlyDroppedBranch()[InEvent])
348 ep.addToProcessHistory();
350 rootOutputFile_->writeOne(ep);
351 fstats_.recordEvent(ep.id());
352 TLOG(9) << __func__ <<
": return";
355 void art::RootDAQOut::setSubRunAuxiliaryRangeSetID(RangeSet
const& rs)
357 rootOutputFile_->setSubRunAuxiliaryRangeSetID(rs);
360 void art::RootDAQOut::writeSubRun(SubRunPrincipal& sr)
366 if (hasNewlyDroppedBranch()[InSubRun])
368 sr.addToProcessHistory();
370 rootOutputFile_->writeSubRun(sr);
371 fstats_.recordSubRun(sr.id());
374 void art::RootDAQOut::setRunAuxiliaryRangeSetID(RangeSet
const& rs)
376 rootOutputFile_->setRunAuxiliaryRangeSetID(rs);
379 void art::RootDAQOut::writeRun(RunPrincipal& r)
381 if (hasNewlyDroppedBranch()[InRun])
383 r.addToProcessHistory();
385 rootOutputFile_->writeRun(r);
386 fstats_.recordRun(r.id());
389 void art::RootDAQOut::startEndFile()
391 auto resp = std::make_unique<ResultsPrincipal>(
392 ResultsAuxiliary{}, description().processConfiguration(),
nullptr);
393 resp->setProducedProducts(producedResultsProducts_);
394 if (ProductMetaData::instance().productProduced(InResults) ||
395 hasNewlyDroppedBranch()[InResults])
397 resp->addToProcessHistory();
399 rpm_.for_each_RPWorker(
400 [&resp](RPWorker& w) { w.rp().doWriteResults(*resp); });
401 rootOutputFile_->writeResults(*resp);
404 void art::RootDAQOut::writeFileFormatVersion()
406 rootOutputFile_->writeFileFormatVersion();
409 void art::RootDAQOut::writeFileIndex()
411 rootOutputFile_->writeFileIndex();
414 void art::RootDAQOut::writeEventHistory()
416 rootOutputFile_->writeEventHistory();
419 void art::RootDAQOut::writeProcessConfigurationRegistry()
421 rootOutputFile_->writeProcessConfigurationRegistry();
424 void art::RootDAQOut::writeProcessHistoryRegistry()
426 rootOutputFile_->writeProcessHistoryRegistry();
429 void art::RootDAQOut::writeParameterSetRegistry()
431 if (writeParameterSets_)
433 rootOutputFile_->writeParameterSetRegistry();
437 void art::RootDAQOut::writeProductDescriptionRegistry()
439 rootOutputFile_->writeProductDescriptionRegistry();
442 void art::RootDAQOut::writeParentageRegistry()
444 rootOutputFile_->writeParentageRegistry();
447 void art::RootDAQOut::doWriteFileCatalogMetadata(
448 FileCatalogMetadata::collection_type
const& md,
449 FileCatalogMetadata::collection_type
const& ssmd)
451 rootOutputFile_->writeFileCatalogMetadata(fstats_, md, ssmd);
454 void art::RootDAQOut::writeProductDependencies()
456 rootOutputFile_->writeProductDependencies();
459 void art::RootDAQOut::finishEndFile()
461 std::string
const currentFileName{rootOutputFile_->currentFileName()};
462 rootOutputFile_->writeTTrees();
463 rootOutputFile_.reset();
464 fstats_.recordFileClose();
465 lastClosedFileName_ =
466 fRenamer_.maybeRenameFile(currentFileName, filePattern_);
467 TLOG(TLVL_INFO) << __func__ <<
": Closed output file \"" << lastClosedFileName_ <<
"\"";
468 rpm_.invoke(&ResultsProducer::doClear);
471 void art::RootDAQOut::doRegisterProducts(MasterProductRegistry& mpr,
472 ProductDescriptions& producedProducts,
473 ModuleDescription
const& md)
476 rpm_.for_each_RPWorker([&mpr, &producedProducts, &md](RPWorker& w) {
477 auto const& params = w.params();
478 w.setModuleDescription(
479 ModuleDescription{params.rpPSetID,
481 md.moduleLabel() +
'#' + params.rpLabel,
482 md.processConfiguration(),
483 md.parentageEnabled(),
486 ModuleDescription::invalidID()});
487 w.rp().registerProducts(mpr, producedProducts, w.moduleDescription());
493 producedResultsProducts_ = ProductTable{producedProducts, InResults};
496 void art::RootDAQOut::setFileStatus(OutputFileStatus
const ofs)
499 rootOutputFile_->setFileStatus(ofs);
502 bool art::RootDAQOut::isFileOpen()
const
504 return rootOutputFile_.get() !=
nullptr;
507 void art::RootDAQOut::incrementInputFileNumber()
510 rootOutputFile_->incrementInputFileNumber();
513 bool art::RootDAQOut::requestsToCloseFile()
const
515 return isFileOpen() ? rootOutputFile_->requestsToCloseFile() :
false;
519 art::RootDAQOut::fileGranularity()
const
521 return fileProperties_.granularity();
524 void art::RootDAQOut::doOpenFile()
526 if (inputFileCount_ == 0)
528 throw art::Exception(art::errors::LogicError)
529 <<
"Attempt to open output file before input file. "
530 <<
"Please report this to the core framework developers.\n";
533 std::make_unique<RootDAQOutFile>(
this,
539 saveMemoryObjectThreshold_,
544 dropMetaDataForDroppedData_,
546 description().parentageEnabled(),
547 description().rangesEnabled(),
548 description().dbEnabled());
549 fstats_.recordFileOpen();
550 TLOG(TLVL_INFO) << __func__ <<
": Opened output file with pattern \"" << filePattern_ <<
"\"";
554 art::RootDAQOut::fileNameAtOpen()
const
556 return filePattern_ == dev_null ? dev_null : unique_filename(tmpDir_ +
"/RootOutput");
560 art::RootDAQOut::fileNameAtClose(std::string
const& currentFileName)
562 return filePattern_ == dev_null ? dev_null : fRenamer_.maybeRenameFile(currentFileName, filePattern_);
566 art::RootDAQOut::lastClosedFileName()
const
568 if (lastClosedFileName_.empty())
570 throw Exception(errors::LogicError,
"RootDAQOut::currentFileName(): ")
571 <<
"called before meaningful.\n";
573 return lastClosedFileName_;
576 void art::RootDAQOut::beginJob()
578 rpm_.invoke(&ResultsProducer::doBeginJob);
581 void art::RootDAQOut::endJob()
583 rpm_.invoke(&ResultsProducer::doEndJob);
584 showMissingConsumes();
587 void art::RootDAQOut::event(EventPrincipal
const& ep)
589 rpm_.for_each_RPWorker([&ep](RPWorker& w) { w.rp().doEvent(ep); });
592 void art::RootDAQOut::beginSubRun(art::SubRunPrincipal
const& srp)
594 rpm_.for_each_RPWorker([&srp](RPWorker& w) {
595 SubRun
const sr{srp, w.moduleDescription(), Consumer::non_module_context()};
596 w.rp().doBeginSubRun(srp);
600 void art::RootDAQOut::endSubRun(art::SubRunPrincipal
const& srp)
602 rpm_.for_each_RPWorker([&srp](RPWorker& w) { w.rp().doEndSubRun(srp); });
605 void art::RootDAQOut::beginRun(art::RunPrincipal
const& rp)
607 rpm_.for_each_RPWorker([&rp](RPWorker& w) { w.rp().doBeginRun(rp); });
610 void art::RootDAQOut::endRun(art::RunPrincipal
const& rp)
612 rpm_.for_each_RPWorker([&rp](RPWorker& w) { w.rp().doEndRun(rp); });
616 art::RootDAQOut::modifyFilePattern(std::string
const& inputPattern, Config
const& config)
618 TLOG(TLVL_DEBUG) << __func__ <<
": inputPattern=\"" << inputPattern <<
"\"";
622 int firstLoggerRank = config.firstLoggerRank();
623 std::vector<Config::FileNameSubstitution> subs;
624 config.fileNameSubstitutions(subs);
625 TLOG(TLVL_TRACE) << __func__ <<
": firstLoggerRank=" << firstLoggerRank
626 <<
", numberOfSubstitutionsProvided=" << subs.size();
629 std::string modifiedPattern = inputPattern;
630 std::string searchString;
631 size_t targetLocation;
632 int zeroBasedRelativeRank = my_rank;
633 int oneBasedRelativeRank = my_rank + 1;
634 if (firstLoggerRank >= 0)
636 zeroBasedRelativeRank -= firstLoggerRank;
637 oneBasedRelativeRank -= firstLoggerRank;
639 TLOG(TLVL_TRACE) << __func__ <<
": my_rank=" << my_rank <<
", zeroBasedRelativeRank=" << zeroBasedRelativeRank
640 <<
", oneBasedRelativeRank=" << oneBasedRelativeRank;
644 searchString =
"${ZeroBasedRelativeRank}";
645 targetLocation = modifiedPattern.find(searchString);
646 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
647 while (targetLocation != std::string::npos)
649 std::ostringstream oss;
650 oss << zeroBasedRelativeRank;
651 modifiedPattern.replace(targetLocation, searchString.length(), oss.str());
652 targetLocation = modifiedPattern.find(searchString);
653 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
658 searchString =
"${OneBasedRelativeRank}";
659 targetLocation = modifiedPattern.find(searchString);
660 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
661 while (targetLocation != std::string::npos)
663 std::ostringstream oss;
664 oss << oneBasedRelativeRank;
665 modifiedPattern.replace(targetLocation, searchString.length(), oss.str());
666 targetLocation = modifiedPattern.find(searchString);
667 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
672 searchString =
"${Rank}";
673 targetLocation = modifiedPattern.find(searchString);
674 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
675 while (targetLocation != std::string::npos)
677 std::ostringstream oss;
679 modifiedPattern.replace(targetLocation, searchString.length(), oss.str());
680 targetLocation = modifiedPattern.find(searchString);
681 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
685 for (uint32_t subIdx = 0; subIdx < subs.size(); ++subIdx)
688 const std::string BLAH =
"none_provided";
689 std::string newString = BLAH;
690 std::vector<Config::NewSubStringForApp> replacementList = subs[subIdx].replacementList();
691 for (uint32_t rdx = 0; rdx < replacementList.size(); ++rdx)
695 newString = replacementList[rdx].newString();
700 if (newString != BLAH)
703 searchString =
"${" + subs[subIdx].targetString() +
"}";
704 targetLocation = modifiedPattern.find(searchString);
705 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
706 while (targetLocation != std::string::npos)
708 modifiedPattern.replace(targetLocation, searchString.length(), newString);
709 targetLocation = modifiedPattern.find(searchString);
710 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
715 searchString = subs[subIdx].targetString();
716 targetLocation = modifiedPattern.find(searchString);
717 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
718 while (targetLocation != std::string::npos)
720 modifiedPattern.replace(targetLocation, searchString.length(), newString);
721 targetLocation = modifiedPattern.find(searchString);
722 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
727 TLOG(TLVL_DEBUG) << __func__ <<
": modifiedPattern = \"" << modifiedPattern <<
"\"";
728 return modifiedPattern;
static std::string app_name_
The name of the current application, to be used in logging and metrics.
Required configuration for art processes started by artdaq, with artdaq-specific defaults where appli...