Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:16:11

0001 #include "Fun4AllSyncManager.h"
0002 
0003 #include "Fun4AllInputManager.h"
0004 #include "Fun4AllReturnCodes.h"  // for EVENT_OK, RESET_NODE_TREE
0005 #include "Fun4AllServer.h"
0006 
0007 #include <ffaobjects/SyncObject.h>
0008 
0009 #include <phool/phool.h>  // for PHWHERE
0010 
0011 #include <TSystem.h>
0012 
0013 #include <cstdlib>
0014 #include <iostream>  // for operator<<, endl, basic_ostream
0015 #include <list>      // for list<>::const_iterator, _List_con...
0016 #include <string>
0017 #include <utility>  // for pair
0018 #include <vector>
0019 
0020 Fun4AllSyncManager::Fun4AllSyncManager(const std::string &name)
0021   : Fun4AllBase(name)
0022 {
0023   return;
0024 }
0025 
0026 Fun4AllSyncManager::~Fun4AllSyncManager()
0027 {
0028   delete m_MasterSync;
0029   while (m_InManager.begin() != m_InManager.end())
0030   {
0031     if (Verbosity())
0032     {
0033       m_InManager.back()->Verbosity(Verbosity());
0034     }
0035     delete m_InManager.back();
0036     m_InManager.pop_back();
0037   }
0038   return;
0039 }
0040 
0041 int Fun4AllSyncManager::registerInputManager(Fun4AllInputManager *InputManager)
0042 {
0043   for (Fun4AllInputManager *inman : m_InManager)
0044   {
0045     if (inman->Name() == InputManager->Name())
0046     {
0047       std::cout << "InputManager " << InputManager->Name() << " allready in list" << std::endl;
0048       return -1;
0049     }
0050   }
0051 
0052   if (Verbosity() > 0)
0053   {
0054     std::cout << "Registering InputManager " << InputManager->Name() << std::endl;
0055   }
0056   m_InManager.push_back(InputManager);
0057   m_iretInManager.push_back(0);
0058   InputManager->setSyncManager(this);
0059   return 0;
0060 }
0061 
0062 Fun4AllInputManager *
0063 Fun4AllSyncManager::getInputManager(const std::string &name)
0064 {
0065   for (Fun4AllInputManager *inman : m_InManager)
0066   {
0067     if (name == inman->Name())
0068     {
0069       return inman;
0070     }
0071   }
0072   std::cout << Name() << ": Could not find InputManager" << name << std::endl;
0073   return nullptr;
0074 }
0075 
0076 //_________________________________________________________________
0077 int Fun4AllSyncManager::run(const int nevnts)
0078 {
0079   int iret = 0;
0080   int icnt = 0;
0081   int iretsync = 0;
0082   int resetnodetree = 0;
0083   // on read errors (assumed to be caused that a file is empty and we need to open the next one)
0084   // we have to go through this 3 times
0085   // 1st pass: The error is detected (for all input mgrs), for the failed input manager(s) a fileclose(), fileopen() is executed, if this fails control goes back to Fun4All since we are done. For input managers without errors, the event is pushed back, so it is read again in the next pass
0086   // 2nd pass: Events are read from all input managers. If no errors all input managers are pushed back
0087   // The reason for this is that we opened a new files with maybe different content and we need to clean
0088   // the node tree so we do not propagate old objects from the previous event
0089   // The node tree reset is done by the Fun4AllServer so we give control back and signal via resetnodetree return code
0090   // 3rd pass: read from every input manager and go back to Fun4All
0091 
0092   while (!iret)
0093   {
0094     unsigned iman = 0;
0095     int ifirst = 0;
0096     int hassync = 0;
0097     for (auto &iter : m_InManager)
0098     {
0099       m_iretInManager[iman] = iter->run(1);
0100       iret += m_iretInManager[iman];
0101       // one can run DSTs without sync object via the DST input manager
0102       // this only poses a problem if one runs two of them and expects the syncing to work
0103       // or mix DSTs with sync object and without
0104       if (!hassync && iter->HasSyncObject())  // only update if hassync is 0 and input mgr is non zero
0105       {
0106         hassync = iter->HasSyncObject();
0107       }
0108       else
0109       {
0110         if (iter->HasSyncObject())  // if zero (no syncing) no need to go further
0111         {
0112           if (hassync != iter->HasSyncObject())  // we have sync and no sync mixed
0113           // NOLINTNEXTLINE(bugprone-branch-clone)
0114           {
0115             PrintSyncProblem();
0116             gSystem->Exit(1);
0117             exit(1);
0118           }
0119           else if (hassync < 0)  // we have more than one nosync input
0120           {
0121             PrintSyncProblem();
0122             gSystem->Exit(1);
0123             exit(1);
0124           }
0125         }
0126       }
0127       if (!ifirst)
0128       {
0129         if (!m_iretInManager[iman])
0130         {
0131           if (!(iter->GetSyncObject(&m_MasterSync)))  // NoSync managers return non zero
0132           {
0133             ifirst = 1;
0134           }
0135         }
0136       }
0137       else
0138       {
0139         iretsync = CheckSync(iman);
0140         if (iretsync)
0141         {
0142           break;
0143         }
0144       }
0145       iman++;
0146     }
0147 
0148     // check event reading, syncronisation
0149     if (iret || iretsync)
0150     {
0151       // tell the server to reset the node tree
0152       resetnodetree = Fun4AllReturnCodes::RESET_NODE_TREE;
0153 
0154       // if there was an io error (file exhausted) we nee to push back
0155       // the events from files which are not exhausted yet into the root files
0156       // here we check the return codes for each input manager and if the
0157       // read was successful (iret = 0) we push the event back
0158       if (iret)
0159       {
0160         unsigned inputmgr_cnt = 0;
0161         std::vector<Fun4AllInputManager *>::const_iterator InIter;
0162         // set in the macro for Sync Manager. Permanently enabled (default when using syncman->Repeat(),
0163         // m_Repeat = -1 so the m_Repeat--; is not called, this is used when you give it a positive number of
0164         // repetitions
0165         if (m_Repeat)
0166         {
0167           for (InIter = m_InManager.begin(); InIter != m_InManager.end(); ++InIter)
0168           {
0169             if (m_iretInManager[inputmgr_cnt] == Fun4AllReturnCodes::EVENT_OK)
0170             {
0171               (*InIter)->PushBackEvents(1);
0172             }
0173             else
0174             {
0175               if ((*InIter)->IsOpen())
0176               {
0177                 (*InIter)->fileclose();
0178               }
0179               int ireset = (*InIter)->ResetFileList();
0180               if (ireset)
0181               {
0182                 std::cout << "Resetting input manager " << (*InIter)->Name() << " failed during Repeat" << std::endl;
0183                 exit(1);
0184               }
0185               inputmgr_cnt++;
0186             }
0187           }
0188           if (m_Repeat > 0)
0189           {
0190             m_Repeat--;
0191           }
0192           iret = 0;
0193           continue;  // got back and run again
0194         }
0195         // push back events where the Imanager did not report an error
0196         InIter = m_InManager.begin();
0197         for (int iter : m_iretInManager)
0198         {
0199           if (Verbosity() > 0)
0200           {
0201             std::cout << (*InIter)->Name() << ": return code: " << iter << std::endl;
0202           }
0203           if (!iter)
0204           {
0205             (*InIter)->PushBackEvents(1);
0206             if (Verbosity() > 0)
0207             {
0208               std::cout << (*InIter)->Name() << ": push evts: " << iter << std::endl;
0209             }
0210           }
0211           ++InIter;
0212         }
0213         // NOLINTNEXTLINE(hicpp-avoid-goto)
0214         goto readerror;
0215       }
0216       else
0217       {
0218         // just read the next event and hope it syncs
0219         // this won't update the event counter
0220         for (unsigned nman = 0; nman < iman; nman++)
0221         {
0222           m_InManager[nman]->NoSyncPushBackEvents(1);
0223         }
0224         continue;
0225       }
0226     }
0227     if (!resetnodetree)
0228     {
0229       m_EventsTotal++;
0230     }
0231     // this check is meaningless nowadays since we call this method with 1 event every time
0232     // so we can just break here but maybe this changes in the future
0233     if (nevnts > 0 && ++icnt >= nevnts)
0234     {
0235       break;
0236     }
0237   }
0238 
0239 readerror:
0240   if (!iret)
0241   {
0242     if (!resetnodetree)  // all syncing is done and no read errors --> we have a good event in memory
0243     {
0244       m_CurrentRun = 0;  // reset current run to 0
0245       for (auto &iter : m_InManager)
0246       {
0247         int runno = iter->RunNumber();
0248         if (Verbosity() > 2)
0249         {
0250           std::cout << Name() << " input mgr " << iter->Name() << " run: " << runno << std::endl;
0251         }
0252         if (runno != 0)
0253         {
0254           if (m_CurrentRun == 0)
0255           {
0256             m_CurrentRun = runno;
0257             continue;
0258           }
0259 
0260           if (m_CurrentRun != runno && !m_MixRunsOkFlag)
0261           {
0262             std::cout << PHWHERE << "Mixing run numbers (except runnumber=0 which means no valid runnumber) is not supported" << std::endl;
0263             std::cout << "Here are the list of input managers and runnumbers:" << std::endl;
0264             for (Fun4AllInputManager *inman : m_InManager)
0265             {
0266               std::cout << inman->Name() << " runno: " << inman->RunNumber() << std::endl;
0267             }
0268             std::cout << "Exiting now" << std::endl;
0269             exit(1);
0270           }
0271         }
0272       }
0273     }
0274     return resetnodetree;
0275   }
0276   return iret;
0277 }
0278 
0279 //_________________________________________________________________
0280 int Fun4AllSyncManager::skip(const int nevnts)
0281 {
0282   if (!m_InManager.empty())
0283   {
0284     int Npushback = -nevnts;
0285     // the PushBackEvents(const int nevents) "pushes back" events events into the root file
0286     // (technically it just decrements the local counter in the PHNodeIOManager)
0287     // giving it a negative argument will skip events
0288     // this is much faster than actually reading the events in
0289     int iret = 0;
0290     bool first = true;
0291     for (auto &iman : m_InManager)
0292     {
0293       if (iman->HasSyncObject())
0294       {
0295         if (first)
0296         {
0297           iret += iman->PushBackEvents(Npushback);
0298           first = false;
0299         }
0300       }
0301       else
0302       {
0303         iret += iman->SkipForThisManager(nevnts);
0304       }
0305     }
0306     if (!iret)
0307     {
0308       return 0;
0309     }
0310 
0311     std::cout << PHWHERE << " Error during skipping events" << std::endl;
0312     return iret;
0313   }
0314   std::cout << PHWHERE << " Cannot skip events: No Input Managers registered?" << std::endl;
0315   Print("INPUTMANAGER");
0316   std::cout << "If there are Input Managers in this list, send mail with this" << std::endl;
0317   std::cout << "error message to off-l" << std::endl;
0318   std::cout << "and include the macro you used" << std::endl;
0319   return -1;
0320 }
0321 
0322 //_________________________________________________________________
0323 int Fun4AllSyncManager::fileopen(const std::string &managername, const std::string &filename)
0324 {
0325   for (Fun4AllInputManager *inman : m_InManager)
0326   {
0327     if (managername == inman->Name())
0328     {
0329       int iret = inman->fileopen(filename);
0330       return iret;
0331     }
0332   }
0333   std::cout << "No Input Manager " << managername << " registered" << std::endl;
0334   return -1;
0335 }
0336 
0337 int Fun4AllSyncManager::BranchSelect(const std::string &managername, const std::string &branch, const int iflag)
0338 {
0339   for (Fun4AllInputManager *inman : m_InManager)
0340   {
0341     if (managername == inman->Name())
0342     {
0343       int iret = inman->BranchSelect(branch, iflag);
0344       return iret;
0345     }
0346   }
0347   std::cout << "No Input Manager " << managername << " registered" << std::endl;
0348   return -1;
0349 }
0350 
0351 int Fun4AllSyncManager::BranchSelect(const std::string &branch, const int iflag)
0352 {
0353   int iret = 0;
0354   for (Fun4AllInputManager *inman : m_InManager)
0355   {
0356     iret += inman->BranchSelect(branch, iflag);
0357   }
0358   return iret;
0359 }
0360 
0361 int Fun4AllSyncManager::setBranches(const std::string &managername)
0362 {
0363   for (Fun4AllInputManager *inman : m_InManager)
0364   {
0365     if (managername == inman->Name())
0366     {
0367       int iret = inman->setBranches();
0368       return iret;
0369     }
0370   }
0371   std::cout << "No Input Manager " << managername << " registered" << std::endl;
0372   return -1;
0373 }
0374 
0375 int Fun4AllSyncManager::setBranches()
0376 {
0377   int iret = 0;
0378   for (Fun4AllInputManager *inman : m_InManager)
0379   {
0380     iret += inman->setBranches();
0381   }
0382   return iret;
0383 }
0384 
0385 int Fun4AllSyncManager::fileclose(const std::string &managername)
0386 {
0387   int foundIt = 0;
0388   for (Fun4AllInputManager *inman : m_InManager)
0389   {
0390     if (managername == inman->Name() || managername.empty())
0391     {
0392       inman->fileclose();
0393       foundIt = 1;
0394     }
0395   }
0396   if (foundIt)
0397   {
0398     return 0;
0399   }
0400   std::cout << "No Input Manager " << managername << " registered" << std::endl;
0401   return -1;
0402 }
0403 
0404 void Fun4AllSyncManager::Print(const std::string &what) const
0405 {
0406   if (what == "ALL" || what == "INPUTMANAGER")
0407   {
0408     // loop over the map and print out the content (name and location in memory)
0409     std::cout << "--------------------------------------" << std::endl
0410               << std::endl;
0411     std::cout << "List of InputManagers in Fun4AllSyncManager "
0412               << Name() << ":" << std::endl;
0413 
0414     for (Fun4AllInputManager *inman : m_InManager)
0415     {
0416       std::cout << inman->Name() << std::endl;
0417     }
0418     std::cout << std::endl;
0419   }
0420   return;
0421 }
0422 
0423 int Fun4AllSyncManager::CheckSync(const unsigned i)
0424 {
0425   int iret;
0426   iret = m_InManager[i]->SyncIt(m_MasterSync);
0427   return iret;
0428 }
0429 
0430 void Fun4AllSyncManager::GetInputFullFileList(std::vector<std::string> &fnames) const
0431 {
0432   for (Fun4AllInputManager *InMan : m_InManager)
0433   {
0434     std::pair<std::list<std::string>::const_iterator, std::list<std::string>::const_iterator> beginend = InMan->FileOpenListBeginEnd();
0435     for (auto iter = beginend.first; iter != beginend.second; ++iter)
0436     {
0437       fnames.push_back(*iter);
0438     }
0439   }
0440   return;
0441 }
0442 
0443 void Fun4AllSyncManager::PushBackInputMgrsEvents(const int i)
0444 {
0445   for (Fun4AllInputManager *inman : m_InManager)
0446   {
0447     inman->PushBackEvents(i);
0448   }
0449   return;
0450 }
0451 
0452 int Fun4AllSyncManager::ResetEvent()
0453 {
0454   int iret = 0;
0455   for (Fun4AllInputManager *inman : m_InManager)
0456   {
0457     if (Verbosity() > 0)
0458     {
0459       std::cout << "Resetting Event for Input Manager " << inman->Name() << std::endl;
0460     }
0461     iret += inman->ResetEvent();
0462   }
0463   return iret;
0464 }
0465 
0466 void Fun4AllSyncManager::CurrentEvent(const int evt)
0467 {
0468   m_CurrentEvent = evt;
0469   Fun4AllServer *se = Fun4AllServer::instance();
0470   se->EventNumber(evt);
0471   return;
0472 }
0473 
0474 void Fun4AllSyncManager::PrintSyncProblem() const
0475 {
0476   std::cout << "Bad use of Fun4AllDstInputManager for file(s) which do not have a synchronization object" << std::endl;
0477   std::cout << "This works for single streams but if you run with multiple input streams this might lead to event mixing" << std::endl;
0478   std::cout << "If you insist to run this (you take full responsibility), change the following in your macro: " << std::endl;
0479   for (auto *iter : m_InManager)
0480   {
0481     if (iter->HasSyncObject() < 0)
0482     {
0483       std::cout << "File " << iter->FileName() << " does not contain a sync object" << std::endl;
0484       std::cout << "Change its Fun4AllDstInputManager with name " << iter->Name() << " from Fun4AllDstInputManager to Fun4AllNoSyncDstInputManager" << std::endl;
0485     }
0486   }
0487   return;
0488 }