Back to home page

sPhenix code displayed by LXR

 
 

    


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

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 (!striprunnodes.empty())
0256     {
0257       for (const auto &nodename : striprunnodes)
0258       {
0259         PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0260         if (ChosenNode)
0261         {
0262           ChosenNode->makeTransient();
0263         }
0264         else
0265         {
0266           if (Verbosity() > 0)
0267           {
0268             std::cout << PHWHERE << Name() << ": Node " << nodename
0269                       << " does not exist" << std::endl;
0270           }
0271         }
0272       }
0273     }
0274   }
0275   else
0276   {
0277     for (const auto &nodename : saverunnodes)
0278     {
0279       PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0280       if (ChosenNode)
0281       {
0282         ChosenNode->makePersistent();
0283       }
0284       else
0285       {
0286         if (Verbosity() > 0)
0287         {
0288           std::cout << PHWHERE << Name() << ": Node " << nodename
0289                     << " does not exist" << std::endl;
0290         }
0291       }
0292     }
0293   }
0294   dstOut->write(thisNode);
0295   se->MakeNodesTransient(thisNode);
0296   delete dstOut;
0297   dstOut = nullptr;
0298   return 0;
0299 }
0300 
0301 int Fun4AllDstOutputManager::outfile_open_first_write()
0302 {
0303   delete dstOut;
0304   SetEventsWritten(1);  // this is the first event we write, need to set the number to 1
0305   std::filesystem::path p = OutFileName();
0306   if (m_FileNameStem.empty())
0307   {
0308     m_FileNameStem = p.stem();
0309   }
0310   if (ApplyFileRule())
0311   {
0312     recoConsts *rc = recoConsts::instance();
0313     int runnumber = 0;
0314     if (rc->FlagExist("RUNNUMBER"))
0315     {
0316       runnumber = rc->get_IntFlag("RUNNUMBER");
0317     }
0318     std::string fullpath = ".";
0319     if (p.has_parent_path())
0320     {
0321       fullpath = p.parent_path();
0322     }
0323     std::string runseg = std::format("-{:08}-{:05}",runnumber,m_CurrentSegment);
0324     std::string newfile = fullpath + std::string("/") + m_FileNameStem + runseg + std::string(p.extension());
0325     OutFileName(newfile);
0326     m_CurrentSegment++;
0327   }
0328   m_UsedOutFileName = OutFileName() + std::string("?reproducible=") + std::string(p.filename());
0329   dstOut = new PHNodeIOManager(UsedOutFileName(), PHWrite);
0330   if (SplitLevel() != std::numeric_limits<int>::min())
0331   {
0332     dstOut->SplitLevel(SplitLevel());
0333   }
0334   if (BufferSize() != std::numeric_limits<int>::min())
0335   {
0336     dstOut->BufferSize(BufferSize());
0337   }
0338   if (!dstOut->isFunctional())
0339   {
0340     delete dstOut;
0341     dstOut = nullptr;
0342     std::cout << PHWHERE << " Could not open " << OutFileName() << std::endl;
0343     return -1;
0344   }
0345 
0346   dstOut->SetCompressionSetting(m_CompressionSetting);
0347   return 0;
0348 }