Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:19:34

0001 #include "Fun4AllDstOutputManager.h"
0002 
0003 #include "Fun4AllServer.h"
0004 
0005 #include <phool/PHCompositeNode.h>
0006 #include <phool/PHNode.h>
0007 #include <phool/PHNodeIOManager.h>
0008 #include <phool/PHNodeIterator.h>
0009 #include <phool/phool.h>  // for PHWHERE, PHReadOnly, PHRunTree
0010 #include <phool/recoConsts.h>
0011 
0012 #include <TSystem.h>
0013 
0014 #include <cstdlib>
0015 #include <filesystem>
0016 #include <format>
0017 #include <iostream>
0018 #include <string>
0019 
0020 Fun4AllDstOutputManager::Fun4AllDstOutputManager(const std::string &myname, const std::string &filename)
0021   : Fun4AllOutputManager(myname, filename)
0022 {
0023   return;
0024 }
0025 
0026 Fun4AllDstOutputManager::~Fun4AllDstOutputManager()
0027 {
0028   delete dstOut;
0029   return;
0030 }
0031 
0032 int Fun4AllDstOutputManager::AddNode(const std::string &nodename)
0033 {
0034   savenodes.insert(nodename);
0035   return 0;
0036 }
0037 
0038 int Fun4AllDstOutputManager::AddRunNode(const std::string &nodename)
0039 {
0040   saverunnodes.insert(nodename);
0041   return 0;
0042 }
0043 
0044 int Fun4AllDstOutputManager::StripCompositeNode(const std::string &nodename)
0045 {
0046   m_StripCompositeNodes.insert(nodename);
0047   return 0;
0048 }
0049 
0050 int Fun4AllDstOutputManager::StripNode(const std::string &nodename)
0051 {
0052   stripnodes.insert(nodename);
0053   return 0;
0054 }
0055 
0056 int Fun4AllDstOutputManager::StripRunNode(const std::string &nodename)
0057 {
0058   striprunnodes.insert(nodename);
0059   return 0;
0060 }
0061 
0062 int Fun4AllDstOutputManager::outfileopen(const std::string &fname)
0063 {
0064   OutFileName(fname);
0065   return 0;
0066 }
0067 
0068 void Fun4AllDstOutputManager::Print(const std::string &what) const
0069 {
0070   if (what == "ALL" || what == "WRITENODES")
0071   {
0072     std::cout << Name() << " writes " << OutFileName() << std::endl;
0073     if (savenodes.empty())
0074     {
0075       if (stripnodes.empty())
0076       {
0077         std::cout << Name() << ": All Nodes will be written out" << std::endl;
0078       }
0079       else
0080       {
0081         for (const auto &nodename : stripnodes)
0082         {
0083           std::cout << Name() << ": Node " << nodename << " will be stripped" << std::endl;
0084         }
0085       }
0086     }
0087     else
0088     {
0089       for (const auto &nodename : savenodes)
0090       {
0091         std::cout << Name() << ": Node " << nodename << " is written out" << std::endl;
0092       }
0093     }
0094   }
0095   // base class print method
0096   Fun4AllOutputManager::Print(what);
0097 
0098   return;
0099 }
0100 
0101 // All nodes are set to transient by the framework
0102 // here we first change the nodes we want to write out
0103 // to persistent and then call the write method
0104 // of the io manager
0105 // afterwards the nodes we just wrote out are changed back
0106 // to transient
0107 // if we want to strip nodes (only meaningful if we take the default
0108 // that everything is written out), those nodes are declared transient
0109 int Fun4AllDstOutputManager::Write(PHCompositeNode *startNode)
0110 {
0111   if (!m_SaveDstNodeFlag)
0112   {
0113     return 0;
0114   }
0115   if (!dstOut)
0116   {
0117     outfile_open_first_write();  //    outfileopen(OutFileName());
0118   }
0119   PHNodeIterator nodeiter(startNode);
0120   if (savenodes.empty())
0121   {
0122     Fun4AllServer *se = Fun4AllServer::instance();
0123     se->MakeNodesPersistent(startNode);
0124     if (!m_StripCompositeNodes.empty())
0125     {
0126       for (const auto &compnodename : m_StripCompositeNodes)
0127       {
0128         PHCompositeNode *stripcomp = dynamic_cast<PHCompositeNode *>(nodeiter.findFirst("PHCompositeNode", compnodename));
0129         if (stripcomp)
0130         {
0131           se->MakeNodesTransient(stripcomp);
0132         }
0133       }
0134     }
0135     if (!stripnodes.empty())
0136     {
0137       for (const auto &nodename : stripnodes)
0138       {
0139         PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0140         if (ChosenNode)
0141         {
0142           ChosenNode->makeTransient();
0143         }
0144         else
0145         {
0146           if (Verbosity() > 0)
0147           {
0148             std::cout << PHWHERE << Name() << ": Node " << nodename
0149                       << " does not exist" << std::endl;
0150           }
0151         }
0152       }
0153     }
0154   }
0155   else
0156   {
0157     for (const auto &nodename : savenodes)
0158     {
0159       PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0160       if (ChosenNode)
0161       {
0162         ChosenNode->makePersistent();
0163       }
0164       else
0165       {
0166         if (Verbosity() > 0)
0167         {
0168           std::cout << PHWHERE << Name() << ": Node " << nodename
0169                     << " does not exist" << std::endl;
0170         }
0171       }
0172     }
0173   }
0174   dstOut->write(startNode);
0175   // to save some cpu cycles we only make it globally transient if
0176   // all nodes have been written (savenodes set is empty)
0177   // else we only make the nodes transient which we have written (all
0178   // others are transient by construction)
0179   if (savenodes.empty())
0180   {
0181     Fun4AllServer *se = Fun4AllServer::instance();
0182     se->MakeNodesTransient(startNode);
0183   }
0184   else
0185   {
0186     for (const auto &nodename : savenodes)
0187     {
0188       PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0189       if (ChosenNode)
0190       {
0191         ChosenNode->makeTransient();
0192       }
0193     }
0194   }
0195   return 0;
0196 }
0197 
0198 int Fun4AllDstOutputManager::WriteNode(PHCompositeNode *thisNode)
0199 {
0200   if (!m_SaveRunNodeFlag)
0201   {
0202     dstOut = nullptr;
0203     return 0;
0204   }
0205   PHAccessType access_type = PHUpdate;
0206   if (!m_SaveDstNodeFlag)
0207   {
0208     access_type = PHWrite;
0209   }
0210   else
0211   {
0212     // This construct prevents a race condition:
0213     // files are written every n events, Fun4All closes them and saves the run node but leaves it
0214     // up to the DST Output Manager to open the next file on the first write.
0215     // The last files is typically closed during the End() which then saves the Run Node. If
0216     // the total number of events is a multiple of the number of requested events,
0217     // no DST is open (since no events were processed since the last file was closed). Then the End()
0218     // will open the last filename again and save the RunNode here. By checking if dstOut is not null
0219     // we check if a DST is actually open, but only when m_SaveDstNodeFlag is set (meanes we save the
0220     // event wise DST content
0221     if (!dstOut)
0222     {
0223       if (Verbosity() > 0)
0224       {
0225         std::cout << PHWHERE << " DST file has not been written to yet, not saving the RunNode by itself" << std::endl;
0226       }
0227       return 0;
0228     }
0229   }
0230   delete dstOut;
0231 
0232   if (UsedOutFileName().empty())
0233   {
0234     std::filesystem::path p = OutFileName();
0235     if (m_FileNameStem.empty())
0236     {
0237       m_FileNameStem = p.stem();
0238     }
0239     m_UsedOutFileName = OutFileName() + std::string("?reproducible=") + std::string(p.filename());
0240   }
0241   dstOut = new PHNodeIOManager(UsedOutFileName(), access_type, PHRunTree);
0242   if (SplitLevel() != std::numeric_limits<int>::min())
0243   {
0244     dstOut->SplitLevel(SplitLevel());
0245   }
0246   if (BufferSize() != std::numeric_limits<int>::min())
0247   {
0248     dstOut->BufferSize(BufferSize());
0249   }
0250   Fun4AllServer *se = Fun4AllServer::instance();
0251   PHNodeIterator nodeiter(thisNode);
0252   if (saverunnodes.empty())
0253   {
0254     se->MakeNodesPersistent(thisNode);
0255     if (!m_StripCompositeNodes.empty())
0256     {
0257       for (const auto &compnodename : m_StripCompositeNodes)
0258       {
0259         PHCompositeNode *stripcomp = dynamic_cast<PHCompositeNode *>(nodeiter.findFirst("PHCompositeNode", compnodename));
0260         if (stripcomp)
0261         {
0262           se->MakeNodesTransient(stripcomp);
0263         }
0264       }
0265     }
0266     if (!striprunnodes.empty())
0267     {
0268       for (const auto &nodename : striprunnodes)
0269       {
0270         PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0271         if (ChosenNode)
0272         {
0273           ChosenNode->makeTransient();
0274         }
0275         else
0276         {
0277           if (Verbosity() > 0)
0278           {
0279             std::cout << PHWHERE << Name() << ": Node " << nodename
0280                       << " does not exist" << std::endl;
0281           }
0282         }
0283       }
0284     }
0285   }
0286   else
0287   {
0288     for (const auto &nodename : saverunnodes)
0289     {
0290       PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0291       if (ChosenNode)
0292       {
0293         ChosenNode->makePersistent();
0294       }
0295       else
0296       {
0297         if (Verbosity() > 0)
0298         {
0299           std::cout << PHWHERE << Name() << ": Node " << nodename
0300                     << " does not exist" << std::endl;
0301         }
0302       }
0303     }
0304   }
0305   dstOut->write(thisNode);
0306   se->MakeNodesTransient(thisNode);
0307   delete dstOut;
0308   dstOut = nullptr;
0309   return 0;
0310 }
0311 
0312 int Fun4AllDstOutputManager::outfile_open_first_write()
0313 {
0314   delete dstOut;
0315   SetEventsWritten(1);  // this is the first event we write, need to set the number to 1
0316   std::filesystem::path p = OutFileName();
0317   if (m_FileNameStem.empty())
0318   {
0319     m_FileNameStem = p.stem();
0320   }
0321   if (ApplyFileRule())
0322   {
0323     recoConsts *rc = recoConsts::instance();
0324     int runnumber = 0;
0325     if (rc->FlagExist("RUNNUMBER"))
0326     {
0327       runnumber = rc->get_IntFlag("RUNNUMBER");
0328     }
0329     std::string fullpath = ".";
0330     if (p.has_parent_path())
0331     {
0332       fullpath = p.parent_path();
0333     }
0334     std::string runseg = std::format("-{:08}-{:05}", runnumber, m_CurrentSegment);
0335     std::string newfile = fullpath + std::string("/") + m_FileNameStem + runseg + std::string(p.extension());
0336     OutFileName(newfile);
0337     m_CurrentSegment++;
0338   }
0339   m_UsedOutFileName = OutFileName() + std::string("?reproducible=") + std::string(p.filename());
0340   dstOut = new PHNodeIOManager(UsedOutFileName(), PHWrite);
0341   if (SplitLevel() != std::numeric_limits<int>::min())
0342   {
0343     dstOut->SplitLevel(SplitLevel());
0344   }
0345   if (BufferSize() != std::numeric_limits<int>::min())
0346   {
0347     dstOut->BufferSize(BufferSize());
0348   }
0349   if (!dstOut->isFunctional())
0350   {
0351     delete dstOut;
0352     dstOut = nullptr;
0353     std::cout << PHWHERE << " Could not open " << OutFileName() << std::endl;
0354     return -1;
0355   }
0356 
0357   dstOut->SetCompressionSetting(m_CompressionSetting);
0358   return 0;
0359 }
0360 
0361 // this method figures out the last event number to be saved before rolling over
0362 // an integer div of the current event by the number of events gives the first event we can expect
0363 // in this process (this is not needed), then adding the number of events we want gives us the last event
0364 // since want ranges like 1-99999, 100,000 - 199,999 we need to subtract 1
0365 // from the calculated range.
0366 // This is just run for the first event - later we just add the number of events to the last event number
0367 void Fun4AllDstOutputManager::InitializeLastEvent(int eventnumber)
0368 {
0369   if (GetEventNumberRollover() == 0 || m_LastEventInitialized || eventnumber < 0)
0370   {
0371     return;
0372   }
0373   m_LastEventInitialized = true;
0374   unsigned int firstevent = eventnumber / GetEventNumberRollover();
0375   unsigned int newlastevent = firstevent * GetEventNumberRollover() + GetEventNumberRollover() - 1;
0376   if (Verbosity() > 1)
0377   {
0378     std::cout << "event number: " << eventnumber << ", rollover: " << GetEventNumberRollover() << ", multiple: "
0379               << eventnumber / GetEventNumberRollover() << ", new last event number "
0380               << newlastevent << std::endl;
0381   }
0382   SetLastEventNumber(firstevent * GetEventNumberRollover() + GetEventNumberRollover() - 1);
0383   return;
0384 }