@@ -488,116 +488,84 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext
488488 extraSpecs.push_back (timePipeline (aodReader, ctx.options ().get <int64_t >(" readers" )));
489489 }
490490
491- ConcreteDataMatcher dstf{" FLP" , " DISTSUBTIMEFRAME" , 0xccdb };
492- if (ccdbBackend.outputs .empty () == false ) {
493- ccdbBackend.outputs .push_back (OutputSpec{" CTP" , " OrbitReset" , 0 });
494- InputSpec matcher{" dstf" , " FLP" , " DISTSUBTIMEFRAME" , 0xccdb };
495- bool providesDISTSTF = false ;
496- // Check if any of the provided outputs is a DISTSTF
497- // Check if any of the requested inputs is for a 0xccdb message
498- for (auto & dp : workflow) {
499- for (auto & output : dp.outputs ) {
500- if (DataSpecUtils::match (matcher, output)) {
501- providesDISTSTF = true ;
502- dstf = DataSpecUtils::asConcreteDataMatcher (output);
503- break ;
504- }
505- }
506- if (providesDISTSTF) {
507- break ;
508- }
491+ // ConcreteDataMatcher dstf{"FLP", "DISTSUBTIMEFRAME", 0xccdb};
492+ InputSpec matcher{" dstf" , " FLP" , " DISTSUBTIMEFRAME" , 0xccdb };
493+ auto & dstf = std::get<ConcreteDataMatcher>(matcher.matcher );
494+ // Check if any of the provided outputs is a DISTSTF
495+ // Check if any of the requested inputs is for a 0xccdb message
496+ bool providesDISTSTF = std::any_of (workflow.begin (), workflow.end (),
497+ [&matcher](auto const & dp) {
498+ return std::any_of (dp.outputs .begin (), dp.outputs .end (), [&matcher](auto const & output){
499+ return DataSpecUtils::match (matcher, output);
500+ });
501+ });
502+
503+ // If there is no CCDB requested, but we still ask for a FLP/DISTSUBTIMEFRAME/0xccdb
504+ // we add to the first data processor which has no inputs (apart from
505+ // enumerations / timers) the responsibility to provide the DISTSUBTIMEFRAME
506+ bool requiresDISTSUBTIMEFRAME = std::any_of (workflow.begin (), workflow.end (),
507+ [&dstf](auto const & dp) {
508+ return std::any_of (dp.inputs .begin (), dp.inputs .end (), [&dstf](auto const & input){
509+ return DataSpecUtils::match (input, dstf);
510+ });
511+ });
512+
513+ // We find the first device which has either just enumerations or
514+ // just timers, and we will add the DISTSUBTIMEFRAME to it.
515+ // Notice how we do so in a stable manner by sorting the devices
516+ // by name.
517+ int enumCandidate = -1 ;
518+ int timerCandidate = -1 ;
519+ for (auto wi = 0U ; wi < workflow.size (); ++wi) {
520+ auto & dp = workflow[wi];
521+ if (dp.inputs .size () != 1 ) {
522+ continue ;
523+ }
524+ auto lifetime = dp.inputs [0 ].lifetime ;
525+ if (lifetime == Lifetime::Enumeration && (enumCandidate == -1 || workflow[enumCandidate].name > dp.name )) {
526+ enumCandidate = wi;
509527 }
510- // * If there are AOD outputs we use TFNumber as the CCDB clock
511- // * If one device provides a DISTSTF we use that as the CCDB clock
512- // * If one of the devices provides a timer we use that as the CCDB clock
513- // * If none of the above apply add to the first data processor
514- // which has no inputs apart from enumerations the responsibility
515- // to provide the DISTSUBTIMEFRAME.
528+ if (lifetime == Lifetime::Timer && (timerCandidate == -1 || workflow[timerCandidate].name > dp.name )) {
529+ timerCandidate = wi;
530+ }
531+ }
532+
533+ // * If there are AOD outputs we use TFNumber as the CCDB clock
534+ // * If one device provides a DISTSTF we use that as the CCDB clock
535+ // * If one of the devices provides a timer we use that as the CCDB clock
536+ // * If none of the above apply, add to the first data processor
537+ // which has no inputs apart from enumerations the responsibility
538+ // to provide the DISTSUBTIMEFRAME.
539+ if (ccdbBackend.outputs .empty () == false ) {
516540 if (aodReader.outputs .empty () == false ) {
541+ // fetcher clock follows AOD source (TFNumber)
517542 ccdbBackend.inputs .push_back (InputSpec{" tfn" , " TFN" , " TFNumber" });
518543 } else if (providesDISTSTF) {
544+ // fetcher clock follows DSTF/ccdb source (DISTSUBTIMEFRAME)
519545 ccdbBackend.inputs .push_back (InputSpec{" tfn" , dstf, Lifetime::Timeframe});
520546 } else {
521- // We find the first device which has either just enumerations or
522- // just timers, and we add the DISTSUBTIMEFRAME to it.
523- // Notice how we do so in a stable manner by sorting the devices
524- // by name.
525- int enumCandidate = -1 ;
526- int timerCandidate = -1 ;
527- for (size_t wi = 0 ; wi < workflow.size (); wi++) {
528- auto & dp = workflow[wi];
529- if (dp.inputs .size () != 1 ) {
530- continue ;
531- }
532- auto lifetime = dp.inputs [0 ].lifetime ;
533- if (lifetime == Lifetime::Enumeration && (enumCandidate == -1 || workflow[enumCandidate].name > dp.name )) {
534- enumCandidate = wi;
535- }
536- if (lifetime == Lifetime::Timer && (timerCandidate == -1 || workflow[timerCandidate].name > dp.name )) {
537- timerCandidate = wi;
538- }
539- }
540547 if (enumCandidate != -1 ) {
541- auto & dp = workflow[enumCandidate];
542- DataSpecUtils::updateOutputList (dp.outputs , OutputSpec{{" ccdb-diststf" }, dstf, Lifetime::Timeframe});
548+ // add DSTF/ccdb source to the enumeration-driven source explicitly
549+ // fetcher clock is provided by enumeration-driven source (DISTSUBTIMEFRAME)
550+ DataSpecUtils::updateOutputList (workflow[enumCandidate].outputs , OutputSpec{{" ccdb-diststf" }, dstf, Lifetime::Timeframe});
543551 ccdbBackend.inputs .push_back (InputSpec{" tfn" , dstf, Lifetime::Timeframe});
544552 } else if (timerCandidate != -1 ) {
545- auto & dp = workflow[timerCandidate];
546- dstf = DataSpecUtils::asConcreteDataMatcher (dp .outputs [0 ]);
547- ccdbBackend.inputs .push_back (InputSpec{{ " tfn" }, dstf , Lifetime::Timeframe});
553+ // fetcher clock is proived by timer source
554+ auto timer_dstf = DataSpecUtils::asConcreteDataMatcher (workflow[timerCandidate] .outputs [0 ]);
555+ ccdbBackend.inputs .push_back (InputSpec{" tfn" , timer_dstf , Lifetime::Timeframe});
548556 }
549557 }
550558
559+ ccdbBackend.outputs .push_back (OutputSpec{" CTP" , " OrbitReset" , 0 });
551560 // Load the CCDB backend from the plugin
552561 ccdbBackend.algorithm = PluginManager::loadAlgorithmFromPlugin (" O2FrameworkCCDBSupport" , " CCDBFetcherPlugin" , ctx);
553562 extraSpecs.push_back (ccdbBackend);
554- } else {
555- // If there is no CCDB requested, but we still ask for a FLP/DISTSUBTIMEFRAME/0xccdb
556- // we add to the first data processor which has no inputs (apart from
557- // enumerations / timers) the responsibility to provide the DISTSUBTIMEFRAME
558- bool requiresDISTSUBTIMEFRAME = false ;
559- for (auto & dp : workflow) {
560- for (auto & input : dp.inputs ) {
561- if (DataSpecUtils::match (input, dstf)) {
562- requiresDISTSUBTIMEFRAME = true ;
563- break ;
564- }
565- }
566- }
567- if (requiresDISTSUBTIMEFRAME) {
568- // We find the first device which has either just enumerations or
569- // just timers, and we add the DISTSUBTIMEFRAME to it.
570- // Notice how we do so in a stable manner by sorting the devices
571- // by name.
572- int enumCandidate = -1 ;
573- int timerCandidate = -1 ;
574- for (size_t wi = 0 ; wi < workflow.size (); wi++) {
575- auto & dp = workflow[wi];
576- if (dp.inputs .size () != 1 ) {
577- continue ;
578- }
579- auto lifetime = dp.inputs [0 ].lifetime ;
580- if (lifetime == Lifetime::Enumeration && (enumCandidate == -1 || workflow[enumCandidate].name > dp.name )) {
581- enumCandidate = wi;
582- }
583- if (lifetime == Lifetime::Timer && (timerCandidate == -1 || workflow[timerCandidate].name > dp.name )) {
584- timerCandidate = wi;
585- }
586- }
587- if (enumCandidate != -1 ) {
588- auto & dp = workflow[enumCandidate];
589- DataSpecUtils::updateOutputList (dp.outputs , OutputSpec{{" ccdb-diststf" }, dstf, Lifetime::Timeframe});
590- ccdbBackend.inputs .push_back (InputSpec{" tfn" , dstf, Lifetime::Timeframe});
591- } else if (timerCandidate != -1 ) {
592- auto & dp = workflow[timerCandidate];
593- dstf = DataSpecUtils::asConcreteDataMatcher (dp.outputs [0 ]);
594- ccdbBackend.inputs .push_back (InputSpec{{" tfn" }, dstf, Lifetime::Timeframe});
595- }
596- }
563+ } else if (requiresDISTSUBTIMEFRAME && enumCandidate != -1 ) {
564+ // add DSTF/ccdb source to the enumeration-driven source explicitly if it is required in the workflow
565+ DataSpecUtils::updateOutputList (workflow[enumCandidate].outputs , OutputSpec{{" ccdb-diststf" }, dstf, Lifetime::Timeframe});
597566 }
598567
599- // add the Analysys CCDB backend which reads CCDB objects using a provided
600- // table
568+ // add the Analysys CCDB backend which reads CCDB objects using a provided table
601569 if (analysisCCDBBackend.outputs .empty () == false ) {
602570 // add normal reader
603571 auto && algo = PluginManager::loadAlgorithmFromPlugin (" O2FrameworkCCDBSupport" , " AnalysisCCDBFetcherPlugin" , ctx);
0 commit comments