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 "artdaq/ArtModules/RootDAQOutput-s85/RootDAQOutFile.h"
11 #include "art/Framework/IO/Root/detail/rootOutputConfigurationTools.h"
12 #include "art/Framework/IO/detail/logFileAction.h"
13 #include "art/Framework/IO/detail/validateFileNamePattern.h"
14 #include "art/Framework/Principal/Event.h"
15 #include "art/Framework/Principal/EventPrincipal.h"
16 #include "art/Framework/Principal/Results.h"
17 #include "art/Framework/Principal/ResultsPrincipal.h"
18 #include "art/Framework/Principal/Run.h"
19 #include "art/Framework/Principal/RunPrincipal.h"
20 #include "art/Framework/Principal/SubRun.h"
21 #include "art/Framework/Principal/SubRunPrincipal.h"
22 #include "art/Persistency/Provenance/ProductMetaData.h"
23 #include "art/Utilities/parent_path.h"
24 #include "art/Utilities/unique_filename.h"
25 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
26 #include "canvas/Persistency/Provenance/ProductTables.h"
27 #include "canvas/Utilities/Exception.h"
28 #include "fhiclcpp/ParameterSet.h"
29 #include "fhiclcpp/types/Atom.h"
30 #include "fhiclcpp/types/ConfigurationTable.h"
31 #include "fhiclcpp/types/OptionalAtom.h"
32 #include "fhiclcpp/types/OptionalSequence.h"
33 #include "fhiclcpp/types/Table.h"
34 #include "messagefacility/MessageLogger/MessageLogger.h"
35 #include "artdaq/DAQdata/Globals.hh"
37 #define TRACE_NAME (app_name + "_RootDAQOut").c_str()
48 std::string
const dev_null{
"/dev/null"};
58 static constexpr
char const* default_tmpDir{
"<parent-path-of-filename>"};
62 using Name = fhicl::Name;
63 using Comment = fhicl::Comment;
65 using Atom = fhicl::Atom<T>;
67 using OptionalAtom = fhicl::OptionalAtom<T>;
69 fhicl::TableFragment<art::OutputModule::Config> omConfig;
70 Atom<std::string> catalog{Name(
"catalog"),
""};
71 OptionalAtom<bool> dropAllEvents{Name(
"dropAllEvents")};
72 Atom<bool> dropAllSubRuns{Name(
"dropAllSubRuns"),
false};
73 OptionalAtom<bool> fastCloning{Name(
"fastCloning")};
74 Atom<std::string> tmpDir{Name(
"tmpDir"), default_tmpDir};
75 Atom<int> compressionLevel{Name(
"compressionLevel"), 7};
76 Atom<unsigned> freePercent{Name(
"freePercent"), 0};
77 Atom<unsigned> freeMB{Name(
"freeMB"), 0};
78 Atom<int64_t> saveMemoryObjectThreshold{Name(
"saveMemoryObjectThreshold"),
80 Atom<int64_t> treeMaxVirtualSize{Name(
"treeMaxVirtualSize"), -1};
81 Atom<int> splitLevel{Name(
"splitLevel"), 99};
82 Atom<int> basketSize{Name(
"basketSize"), 16384};
83 Atom<bool> dropMetaDataForDroppedData{Name(
"dropMetaDataForDroppedData"),
85 Atom<std::string> dropMetaData{Name(
"dropMetaData"),
"NONE"};
86 Atom<bool> writeParameterSets{Name(
"writeParameterSets"),
true};
87 fhicl::Table<ClosingCriteria::Config> fileProperties{Name(
"fileProperties")};
88 Atom<int> firstLoggerRank{Name(
"firstLoggerRank"), -1};
91 fhicl::Atom<string> appName { fhicl::Name(
"appName") };
92 fhicl::Atom<string> newString { fhicl::Name(
"newString") };
95 fhicl::Atom<string> targetString { fhicl::Name(
"targetString") };
96 fhicl::Sequence<fhicl::Table<NewSubStringForApp>> replacementList { fhicl::Name(
"replacementList") };
98 fhicl::OptionalSequence<fhicl::Table<FileNameSubstitution>> fileNameSubstitutions{Name(
"fileNameSubstitutions")};
99 Atom<bool> enableLargeFileCatalogMetadata{
100 Name(
"enableLargeFileCatalogMetadata"),
110 using namespace fhicl::detail;
111 ParameterBase* adjustFilename{
112 const_cast<fhicl::Atom<std::string>*
>(&omConfig().fileName)};
113 adjustFilename->set_par_style(fhicl::par_style::REQUIRED);
117 std::set<std::string>
120 std::set<std::string> keys{
121 art::OutputModule::Config::KeysToIgnore::get()};
122 keys.insert(
"results");
128 using Parameters = fhicl::WrappedTable<Config, Config::KeysToIgnore>;
132 void postSelectProducts()
override;
134 void beginJob()
override;
135 void endJob()
override;
137 void event(EventPrincipal
const&)
override;
139 void beginSubRun(SubRunPrincipal
const&)
override;
140 void endSubRun(SubRunPrincipal
const&)
override;
142 void beginRun(RunPrincipal
const&)
override;
143 void endRun(RunPrincipal
const&)
override;
146 std::string fileNameAtOpen()
const;
147 std::string fileNameAtClose(std::string
const& currentFileName);
148 std::string
const& lastClosedFileName()
const override;
149 void openFile(FileBlock
const&)
override;
150 void respondToOpenInputFile(FileBlock
const&)
override;
151 void readResults(ResultsPrincipal
const& resp)
override;
152 void respondToCloseInputFile(FileBlock
const&)
override;
153 void incrementInputFileNumber()
override;
154 Granularity fileGranularity()
const override;
155 void write(EventPrincipal&)
override;
156 void writeSubRun(SubRunPrincipal&)
override;
157 void writeRun(RunPrincipal&)
override;
158 void setSubRunAuxiliaryRangeSetID(RangeSet
const&)
override;
159 void setRunAuxiliaryRangeSetID(RangeSet
const&)
override;
160 bool isFileOpen()
const override;
161 void setFileStatus(OutputFileStatus)
override;
162 bool requestsToCloseFile()
const override;
164 void startEndFile()
override;
165 void writeFileFormatVersion()
override;
166 void writeFileIndex()
override;
167 void writeEventHistory()
override;
168 void writeProcessConfigurationRegistry()
override;
169 void writeProcessHistoryRegistry()
override;
170 void writeParameterSetRegistry()
override;
171 void writeProductDescriptionRegistry()
override;
172 void writeParentageRegistry()
override;
173 void doWriteFileCatalogMetadata(
174 FileCatalogMetadata::collection_type
const& md,
175 FileCatalogMetadata::collection_type
const& ssmd)
override;
176 void writeProductDependencies()
override;
177 void finishEndFile()
override;
178 void doRegisterProducts(MasterProductRegistry& mpr,
179 ProductDescriptions& producedProducts,
180 ModuleDescription
const& md)
override;
181 std::string modifyFilePattern(std::string
const&,
Config const&);
184 std::string
const catalog_;
185 bool dropAllEvents_{
false};
186 bool dropAllSubRuns_;
187 std::string
const moduleLabel_;
188 bool enableLargeFileCatalogMetadata_{
true};
189 int inputFileCount_{0};
190 std::unique_ptr<RootDAQOutFile> rootOutputFile_{
nullptr};
191 FileStatsCollector fstats_;
192 PostCloseFileRenamer fRenamer_{fstats_};
193 std::string
const filePattern_;
195 std::string lastClosedFileName_{};
198 int const compressionLevel_;
199 unsigned freePercent_;
201 int64_t
const saveMemoryObjectThreshold_;
202 int64_t
const treeMaxVirtualSize_;
203 int const splitLevel_;
204 int const basketSize_;
205 DropMetaData dropMetaData_;
206 bool dropMetaDataForDroppedData_;
210 bool fastCloningEnabled_{
true};
215 bool writeParameterSets_;
216 ClosingCriteria fileProperties_;
219 ProductTable producedResultsProducts_{};
223 art::RootDAQOut::RootDAQOut(Parameters
const& config)
224 : OutputModule{config().omConfig, config.get_PSet()}
225 , catalog_{config().catalog()}
226 , dropAllSubRuns_{config().dropAllSubRuns()}
227 , moduleLabel_{config.get_PSet().get<
string>(
"module_label")}
228 , enableLargeFileCatalogMetadata_{config().enableLargeFileCatalogMetadata()}
229 , fstats_{moduleLabel_, processName(), enableLargeFileCatalogMetadata_}
230 , filePattern_{modifyFilePattern(config().omConfig().fileName(), config())}
231 , tmpDir_{config().tmpDir() == default_tmpDir ? parent_path(filePattern_) :
233 , compressionLevel_{config().compressionLevel()}
234 , freePercent_{config().freePercent()}
235 , freeMB_{config().freeMB()}
236 , saveMemoryObjectThreshold_{config().saveMemoryObjectThreshold()}
237 , treeMaxVirtualSize_{config().treeMaxVirtualSize()}
238 , splitLevel_{config().splitLevel()}
239 , basketSize_{config().basketSize()}
240 , dropMetaData_{config().dropMetaData()}
241 , dropMetaDataForDroppedData_{config().dropMetaDataForDroppedData()}
242 , writeParameterSets_{config().writeParameterSets()}
244 detail::validateFileNamePattern(
245 config.get_PSet().has_key(config().fileProperties.name()),
247 config().fileProperties())}
248 , rpm_{config.get_PSet()}
250 bool const dropAllEventsSet{config().dropAllEvents(dropAllEvents_)};
252 detail::shouldDropEvents(dropAllEventsSet, dropAllEvents_, dropAllSubRuns_);
259 bool const fastCloningSet{config().fastCloning(fastCloningEnabled_)};
260 fastCloningEnabled_ = detail::shouldFastClone(
261 fastCloningSet, fastCloningEnabled_, wantAllEvents(), fileProperties_);
262 if (!writeParameterSets_) {
263 mf::LogWarning(
"PROVENANCE")
264 <<
"Output module " << moduleLabel_
265 <<
" has parameter writeParameterSets set to false.\n"
266 <<
"Parameter set provenance will not be available in subsequent jobs.\n"
267 <<
"Check your experiment's policy on this issue to avoid future "
269 <<
"with analysis reproducibility.\n";
274 art::RootDAQOut::openFile(FileBlock
const& fb)
281 respondToOpenInputFile(fb);
286 art::RootDAQOut::postSelectProducts()
289 rootOutputFile_->selectProducts();
294 art::RootDAQOut::respondToOpenInputFile(FileBlock
const& fb)
300 auto const* rfb =
dynamic_cast<RootFileBlock const*
>(&fb);
302 bool fastCloneThisOne = fastCloningEnabled_ && rfb &&
303 (rfb->tree() !=
nullptr) &&
304 ((remainingEvents() < 0) ||
305 (remainingEvents() >= rfb->tree()->GetEntries()));
306 if (fastCloningEnabled_ && !fastCloneThisOne) {
307 mf::LogWarning(
"FastCloning")
308 <<
"Fast cloning deactivated for this input file due to "
309 <<
"empty event tree and/or event limits.";
311 if (fastCloneThisOne && !rfb->fastClonable()) {
312 mf::LogWarning(
"FastCloning")
313 <<
"Fast cloning deactivated for this input file due to "
314 <<
"information in FileBlock.";
315 fastCloneThisOne =
false;
317 rootOutputFile_->beginInputFile(rfb, fastCloneThisOne);
318 fstats_.recordInputFile(fb.fileName());
322 art::RootDAQOut::readResults(ResultsPrincipal
const& resp)
324 rpm_.for_each_RPWorker([&resp](RPWorker& w) { w.rp().doReadResults(resp); });
328 art::RootDAQOut::respondToCloseInputFile(FileBlock
const& fb)
331 rootOutputFile_->respondToCloseInputFile(fb);
336 art::RootDAQOut::write(EventPrincipal& ep)
338 TLOG(10) << __func__ <<
": enter; dropAllEvents_=" << dropAllEvents_;
339 if (dropAllEvents_) {
342 if (hasNewlyDroppedBranch()[InEvent]) {
343 ep.addToProcessHistory();
345 rootOutputFile_->writeOne(ep);
346 fstats_.recordEvent(ep.id());
347 TLOG(9) << __func__ <<
": return";
351 art::RootDAQOut::setSubRunAuxiliaryRangeSetID(RangeSet
const& rs)
353 rootOutputFile_->setSubRunAuxiliaryRangeSetID(rs);
357 art::RootDAQOut::writeSubRun(SubRunPrincipal& sr)
359 if (dropAllSubRuns_) {
362 if (hasNewlyDroppedBranch()[InSubRun]) {
363 sr.addToProcessHistory();
365 rootOutputFile_->writeSubRun(sr);
366 fstats_.recordSubRun(sr.id());
370 art::RootDAQOut::setRunAuxiliaryRangeSetID(RangeSet
const& rs)
372 rootOutputFile_->setRunAuxiliaryRangeSetID(rs);
376 art::RootDAQOut::writeRun(RunPrincipal& r)
378 if (hasNewlyDroppedBranch()[InRun]) {
379 r.addToProcessHistory();
381 rootOutputFile_->writeRun(r);
382 fstats_.recordRun(r.id());
386 art::RootDAQOut::startEndFile()
388 auto resp = std::make_unique<ResultsPrincipal>(
389 ResultsAuxiliary{}, description().processConfiguration(),
nullptr);
390 resp->setProducedProducts(producedResultsProducts_);
391 if (ProductMetaData::instance().productProduced(InResults) ||
392 hasNewlyDroppedBranch()[InResults]) {
393 resp->addToProcessHistory();
395 rpm_.for_each_RPWorker(
396 [&resp](RPWorker& w) { w.rp().doWriteResults(*resp); });
397 rootOutputFile_->writeResults(*resp);
401 art::RootDAQOut::writeFileFormatVersion()
403 rootOutputFile_->writeFileFormatVersion();
407 art::RootDAQOut::writeFileIndex()
409 rootOutputFile_->writeFileIndex();
413 art::RootDAQOut::writeEventHistory()
415 rootOutputFile_->writeEventHistory();
419 art::RootDAQOut::writeProcessConfigurationRegistry()
421 rootOutputFile_->writeProcessConfigurationRegistry();
425 art::RootDAQOut::writeProcessHistoryRegistry()
427 rootOutputFile_->writeProcessHistoryRegistry();
431 art::RootDAQOut::writeParameterSetRegistry()
433 if (writeParameterSets_) {
434 rootOutputFile_->writeParameterSetRegistry();
439 art::RootDAQOut::writeProductDescriptionRegistry()
441 rootOutputFile_->writeProductDescriptionRegistry();
445 art::RootDAQOut::writeParentageRegistry()
447 rootOutputFile_->writeParentageRegistry();
451 art::RootDAQOut::doWriteFileCatalogMetadata(
452 FileCatalogMetadata::collection_type
const& md,
453 FileCatalogMetadata::collection_type
const& ssmd)
455 rootOutputFile_->writeFileCatalogMetadata(fstats_, md, ssmd);
459 art::RootDAQOut::writeProductDependencies()
461 rootOutputFile_->writeProductDependencies();
465 art::RootDAQOut::finishEndFile()
467 std::string
const currentFileName{rootOutputFile_->currentFileName()};
468 rootOutputFile_->writeTTrees();
469 rootOutputFile_.reset();
470 fstats_.recordFileClose();
471 lastClosedFileName_ =
472 fRenamer_.maybeRenameFile(currentFileName, filePattern_);
473 TLOG(TLVL_INFO) << __func__ <<
": Closed output file \"" << lastClosedFileName_ <<
"\"";
474 rpm_.invoke(&ResultsProducer::doClear);
478 art::RootDAQOut::doRegisterProducts(MasterProductRegistry& mpr,
479 ProductDescriptions& producedProducts,
480 ModuleDescription
const& md)
483 rpm_.for_each_RPWorker([&mpr, &producedProducts, &md](RPWorker& w) {
484 auto const& params = w.params();
485 w.setModuleDescription(
486 ModuleDescription{params.rpPSetID,
488 md.moduleLabel() +
'#' + params.rpLabel,
489 md.processConfiguration(),
490 md.parentageEnabled(),
493 ModuleDescription::invalidID()});
494 w.rp().registerProducts(mpr, producedProducts, w.moduleDescription());
500 producedResultsProducts_ = ProductTable{producedProducts, InResults};
504 art::RootDAQOut::setFileStatus(OutputFileStatus
const ofs)
507 rootOutputFile_->setFileStatus(ofs);
511 art::RootDAQOut::isFileOpen()
const
513 return rootOutputFile_.get() !=
nullptr;
517 art::RootDAQOut::incrementInputFileNumber()
520 rootOutputFile_->incrementInputFileNumber();
524 art::RootDAQOut::requestsToCloseFile()
const
526 return isFileOpen() ? rootOutputFile_->requestsToCloseFile() :
false;
530 art::RootDAQOut::fileGranularity()
const
532 return fileProperties_.granularity();
536 art::RootDAQOut::doOpenFile()
538 if (inputFileCount_ == 0) {
539 throw art::Exception(art::errors::LogicError)
540 <<
"Attempt to open output file before input file. "
541 <<
"Please report this to the core framework developers.\n";
544 std::make_unique<RootDAQOutFile>(
this,
550 saveMemoryObjectThreshold_,
555 dropMetaDataForDroppedData_,
557 description().parentageEnabled(),
558 description().rangesEnabled(),
559 description().dbEnabled());
560 fstats_.recordFileOpen();
561 TLOG(TLVL_INFO) << __func__ <<
": Opened output file with pattern \"" << filePattern_ <<
"\"";
565 art::RootDAQOut::fileNameAtOpen()
const
567 return filePattern_ == dev_null ? dev_null :
568 unique_filename(tmpDir_ +
"/RootOutput");
572 art::RootDAQOut::fileNameAtClose(std::string
const& currentFileName)
574 return filePattern_ == dev_null ?
576 fRenamer_.maybeRenameFile(currentFileName, filePattern_);
580 art::RootDAQOut::lastClosedFileName()
const
582 if (lastClosedFileName_.empty()) {
583 throw Exception(errors::LogicError,
"RootDAQOut::currentFileName(): ")
584 <<
"called before meaningful.\n";
586 return lastClosedFileName_;
590 art::RootDAQOut::beginJob()
592 rpm_.invoke(&ResultsProducer::doBeginJob);
596 art::RootDAQOut::endJob()
598 rpm_.invoke(&ResultsProducer::doEndJob);
599 showMissingConsumes();
603 art::RootDAQOut::event(EventPrincipal
const& ep)
605 rpm_.for_each_RPWorker([&ep](RPWorker& w) { w.rp().doEvent(ep); });
609 art::RootDAQOut::beginSubRun(art::SubRunPrincipal
const& srp)
611 rpm_.for_each_RPWorker([&srp](RPWorker& w) {
612 SubRun
const sr{srp, w.moduleDescription(), Consumer::non_module_context()};
613 w.rp().doBeginSubRun(srp);
618 art::RootDAQOut::endSubRun(art::SubRunPrincipal
const& srp)
620 rpm_.for_each_RPWorker([&srp](RPWorker& w) { w.rp().doEndSubRun(srp); });
624 art::RootDAQOut::beginRun(art::RunPrincipal
const& rp)
626 rpm_.for_each_RPWorker([&rp](RPWorker& w) { w.rp().doBeginRun(rp); });
630 art::RootDAQOut::endRun(art::RunPrincipal
const& rp)
632 rpm_.for_each_RPWorker([&rp](RPWorker& w) { w.rp().doEndRun(rp); });
636 art::RootDAQOut::modifyFilePattern(std::string
const& inputPattern, Config
const& config)
638 TLOG(TLVL_DEBUG) << __func__ <<
": inputPattern=\"" << inputPattern <<
"\"";
642 int firstLoggerRank = config.firstLoggerRank();
643 std::vector<Config::FileNameSubstitution> subs;
644 config.fileNameSubstitutions(subs);
645 TLOG(TLVL_TRACE) << __func__ <<
": firstLoggerRank=" << firstLoggerRank
646 <<
", numberOfSubstitutionsProvided=" << subs.size();
649 std::string modifiedPattern = inputPattern;
650 std::string searchString;
651 size_t targetLocation;
652 int zeroBasedRelativeRank = my_rank;
653 int oneBasedRelativeRank = my_rank + 1;
654 if (firstLoggerRank >= 0)
656 zeroBasedRelativeRank -= firstLoggerRank;
657 oneBasedRelativeRank -= firstLoggerRank;
659 TLOG(TLVL_TRACE) << __func__ <<
": my_rank=" << my_rank <<
", zeroBasedRelativeRank=" << zeroBasedRelativeRank
660 <<
", oneBasedRelativeRank=" << oneBasedRelativeRank;
664 searchString =
"${ZeroBasedRelativeRank}";
665 targetLocation = modifiedPattern.find(searchString);
666 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
667 while (targetLocation != std::string::npos)
669 std::ostringstream oss;
670 oss << zeroBasedRelativeRank;
671 modifiedPattern.replace(targetLocation, searchString.length(), oss.str());
672 targetLocation = modifiedPattern.find(searchString);
673 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
678 searchString =
"${OneBasedRelativeRank}";
679 targetLocation = modifiedPattern.find(searchString);
680 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
681 while (targetLocation != std::string::npos)
683 std::ostringstream oss;
684 oss << oneBasedRelativeRank;
685 modifiedPattern.replace(targetLocation, searchString.length(), oss.str());
686 targetLocation = modifiedPattern.find(searchString);
687 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
692 searchString =
"${Rank}";
693 targetLocation = modifiedPattern.find(searchString);
694 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
695 while (targetLocation != std::string::npos)
697 std::ostringstream oss;
699 modifiedPattern.replace(targetLocation, searchString.length(), oss.str());
700 targetLocation = modifiedPattern.find(searchString);
701 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
705 for (uint32_t subIdx = 0; subIdx < subs.size(); ++subIdx)
708 const std::string BLAH =
"none_provided";
709 std::string newString = BLAH;
710 std::vector<Config::NewSubStringForApp> replacementList = subs[subIdx].replacementList();
711 for (uint32_t rdx = 0; rdx < replacementList.size(); ++rdx)
715 newString = replacementList[rdx].newString();
720 if (newString != BLAH)
723 searchString =
"${" + subs[subIdx].targetString() +
"}";
724 targetLocation = modifiedPattern.find(searchString);
725 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
726 while (targetLocation != std::string::npos)
728 modifiedPattern.replace(targetLocation, searchString.length(), newString);
729 targetLocation = modifiedPattern.find(searchString);
730 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
735 searchString = subs[subIdx].targetString();
736 targetLocation = modifiedPattern.find(searchString);
737 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
738 while (targetLocation != std::string::npos)
740 modifiedPattern.replace(targetLocation, searchString.length(), newString);
741 targetLocation = modifiedPattern.find(searchString);
742 TLOG(TLVL_TRACE) << __func__ <<
":" << __LINE__ <<
" searchString=" << searchString <<
", targetLocation=" << targetLocation;
747 TLOG(TLVL_DEBUG) << __func__ <<
": modifiedPattern = \"" << modifiedPattern <<
"\"";
748 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...