ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Fun4AllDstInputManager.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Fun4AllDstInputManager.cc
2 
3 #include "Fun4AllReturnCodes.h"
4 #include "Fun4AllServer.h"
5 
6 #include <ffaobjects/RunHeader.h>
7 #include <ffaobjects/SyncDefs.h>
9 
10 #include <frog/FROG.h>
11 
12 #include <phool/PHCompositeNode.h>
13 #include <phool/PHNodeIOManager.h>
14 #include <phool/PHNodeIntegrate.h>
15 #include <phool/PHNodeIterator.h> // for PHNodeIterator
16 #include <phool/PHObject.h> // for PHObject
17 #include <phool/getClass.h>
18 #include <phool/phool.h> // for PHWHERE, PHReadOnly, PHRunTree
19 #include <phool/phooldefs.h>
20 
21 #include <TSystem.h>
22 
23 #include <boost/algorithm/string.hpp>
24 
25 #include <cassert>
26 #include <cstdlib>
27 #include <iostream> // for operator<<, basic_ostream, endl
28 #include <utility> // for pair
29 #include <vector> // for vector
30 
31 class TBranch;
32 
33 using namespace std;
34 
35 Fun4AllDstInputManager::Fun4AllDstInputManager(const string &name, const string &nodename, const string &topnodename)
36  : Fun4AllInputManager(name, nodename, topnodename)
37 {
38  return;
39 }
40 
42 {
43  delete IManager;
44  delete runNodeSum;
45  return;
46 }
47 
48 int Fun4AllDstInputManager::fileopen(const string &filenam)
49 {
51  if (IsOpen())
52  {
53  cout << "Closing currently open file "
54  << FileName()
55  << " and opening " << filenam << endl;
56  fileclose();
57  }
58  FileName(filenam);
59  FROG frog;
60  fullfilename = frog.location(FileName());
61  if (Verbosity() > 0)
62  {
63  cout << Name() << ": opening file " << fullfilename << endl;
64  }
65  // sanity check - the IManager must be nullptr when this method is executed
66  // if not something is very very wrong and we must not continue
67  if (IManager)
68  {
69  cout << PHWHERE << " IManager pointer is not nullptr but " << IManager
70  << endl;
71  cout << "Send mail to off-l with this printout and the macro you used"
72  << endl;
73  cout << "Trying to execute IManager->print() to display more info"
74  << endl;
75  cout << "Code will probably segfault now" << endl;
76  IManager->print();
77  cout << "Have someone look into this problem - Exiting now" << endl;
78  exit(1);
79  }
80  // first read the runnode if not disabled
81  if (m_ReadRunTTree)
82  {
84  if (IManager->isFunctional())
85  {
88  // get the current run number
89  RunHeader *runheader = findNode::getClass<RunHeader>(runNode, "RunHeader");
90  if (runheader)
91  {
92  SetRunNumber(runheader->get_RunNumber());
93  }
94  // delete our internal copy of the runnode when opening subsequent files
95  if (runNodeCopy)
96  {
97  cout << PHWHERE
98  << " The impossible happened, we have a valid copy of the run node "
99  << runNodeCopy->getName() << " which should be a nullptr"
100  << endl;
101  gSystem->Exit(1);
102  }
103  runNodeCopy = new PHCompositeNode("RUNNODECOPY");
104  if (!runNodeSum)
105  {
106  runNodeSum = new PHCompositeNode("RUNNODESUM");
107  }
109  tmpIman->read(runNodeCopy);
110  delete tmpIman;
111 
112  PHNodeIntegrate integrate;
113  integrate.RunNode(runNode);
114  integrate.RunSumNode(runNodeSum);
115  // run recursively over internal run node copy and integrate objects
116  PHNodeIterator mainIter(runNodeCopy);
117  mainIter.forEach(integrate);
118  // we do not need to keep the internal copy, keeping it would crate
119  // problems in case a subsequent file does not contain all the
120  // runwise objects from the previous file. Keeping this copy would then
121  // integrate the missing object again with the old copy
122  delete runNodeCopy;
123  runNodeCopy = nullptr;
124  }
125  // DLW: move the delete outside the if block to cover the case where isFunctional() fails
126  delete IManager;
127  }
128  // now open the dst node
129  dstNode = se->getNode(InputNode(), TopNodeName());
131  if (IManager->isFunctional())
132  {
133  IsOpen(1);
134  events_thisfile = 0;
135  setBranches(); // set branch selections
136  AddToFileOpened(FileName()); // add file to the list of files which were opened
137  // check if our input file has a sync object or not
138  if (IManager->NodeExist(syncdefs::SYNCNODENAME))
139  {
140  m_HaveSyncObject = 1;
141  }
142  else
143  {
144  m_HaveSyncObject = -1;
145  }
146 
147  return 0;
148  }
149  else
150  {
151  cout << PHWHERE << ": " << Name() << " Could not open file "
152  << FileName() << endl;
153  delete IManager;
154  IManager = nullptr;
155  return -1;
156  }
157 }
158 
159 int Fun4AllDstInputManager::run(const int nevents)
160 {
161  if (!IsOpen())
162  {
163  if (FileListEmpty())
164  {
165  if (Verbosity() > 0)
166  {
167  cout << Name() << ": No Input file open" << endl;
168  }
169  return -1;
170  }
171  else
172  {
173  if (OpenNextFile())
174  {
175  cout << Name() << ": No Input file from filelist opened" << endl;
176  return -1;
177  }
178  }
179  }
180  if (Verbosity() > 3)
181  {
182  cout << "Getting Event from " << Name() << endl;
183  }
184 readagain:
185  PHCompositeNode *dummy;
186  int ncount = 0;
187  dummy = IManager->read(dstNode);
188  while (dummy)
189  {
190  ncount++;
191  if (nevents > 0 && ncount >= nevents)
192  {
193  break;
194  }
195  dummy = IManager->read(dstNode);
196  }
197  if (!dummy)
198  {
199  fileclose();
200  if (!OpenNextFile())
201  {
202  goto readagain;
203  }
204  return -1;
205  }
206  events_total += ncount;
207  events_thisfile += ncount;
208  // check if the local SubsysReco discards this event
210  {
211  goto readagain;
212  }
213  syncobject = findNode::getClass<SyncObject>(dstNode, syncdefs::SYNCNODENAME);
214  return 0;
215 }
216 
218 {
219  if (!IsOpen())
220  {
221  cout << Name() << ": fileclose: No Input file open" << endl;
222  return -1;
223  }
224  delete IManager;
225  IManager = nullptr;
226  IsOpen(0);
227  UpdateFileList();
228  m_HaveSyncObject = 0;
229  return 0;
230 }
231 
233 {
234  // here we copy the sync object from the current file to the
235  // location pointed to by mastersync. If mastersync is a 0 pointer
236  // the syncobject is cloned. If mastersync allready exists the content
237  // of syncobject is copied
238  if (!(*mastersync))
239  {
240  if (syncobject)
241  {
242  *mastersync = dynamic_cast<SyncObject *>(syncobject->CloneMe());
243  assert(*mastersync);
244  }
245  }
246  else
247  {
248  *(*mastersync) = *syncobject; // copy syncobject content
249  }
251 }
252 
254 {
255  if (!mastersync)
256  {
257  cout << PHWHERE << Name() << " No MasterSync object, cannot perform synchronization" << endl;
258  cout << "Most likely your first file does not contain a SyncObject and the file" << endl;
259  cout << "opened by the Fun4AllDstInputManager with Name " << Name() << " has one" << endl;
260  cout << "Change your macro and use the file opened by this input manager as first input" << endl;
261  cout << "and you will be okay. Fun4All will not process the current configuration" << endl
262  << endl;
264  }
265  int iret = syncobject->Different(mastersync);
266  if (iret) // what to do if files are not in sync
267  {
268  if (mastersync->EventNumber() == -999999) // first file does not contain sync object
269  {
270  cout << PHWHERE << " Mastersync not filled, your first file does not contain a SyncObject" << endl;
271  cout << "This Event will not be processed further" << endl;
272  }
273  else // okay try to resync here
274  {
275  if (Verbosity() > 3)
276  {
277  cout << "Need to Resync, mastersync evt no: " << mastersync->EventNumber()
278  << ", this Event no: " << syncobject->EventNumber() << endl;
279  cout << "mastersync evt counter: " << mastersync->EventCounter()
280  << ", this Event counter: " << syncobject->EventCounter() << endl;
281  cout << "mastersync run number: " << mastersync->RunNumber()
282  << ", this run number: " << syncobject->RunNumber() << endl;
283  }
284  while (syncobject->RunNumber() < mastersync->RunNumber())
285 
286  {
288  if (Verbosity() > 2)
289  {
290  cout << Name() << " Run Number: " << syncobject->RunNumber()
291  << ", master: " << mastersync->RunNumber()
292  << endl;
293  }
294  int iret = ReadNextEventSyncObject();
295  if (iret)
296  {
297  return iret;
298  }
299  }
300  int igood = 0;
301  if (syncobject->RunNumber() == mastersync->RunNumber())
302  {
303  igood = 1;
304  }
305  // only run up the Segment Number if run numbers are identical
306  while (syncobject->SegmentNumber() < mastersync->SegmentNumber() && igood)
307  {
309  if (Verbosity() > 2)
310  {
311  cout << Name() << " Segment Number: " << syncobject->SegmentNumber()
312  << ", master: " << mastersync->SegmentNumber()
313  << endl;
314  }
315  int iret = ReadNextEventSyncObject();
316  if (iret)
317  {
318  return iret;
319  }
320  }
321  // only run up the Event Counter if run number and segment number are identical
322  if (syncobject->SegmentNumber() == mastersync->SegmentNumber() && syncobject->RunNumber() == mastersync->RunNumber())
323  {
324  igood = 1;
325  }
326  else
327  {
328  igood = 0;
329  }
330  while (syncobject->EventCounter() < mastersync->EventCounter() && igood)
331  {
333  if (Verbosity() > 2)
334  {
335  cout << Name()
336  << ", EventCounter: " << syncobject->EventCounter()
337  << ", master: " << mastersync->EventCounter()
338  << endl;
339  }
340  int iret = ReadNextEventSyncObject();
341  if (iret)
342  {
343  return iret;
344  }
345  }
346  // Since up to here we only read the sync object we need to push
347  // the current event back inot the root file (subtract one from the
348  // local root file event counter) so we can read the full event
349  // if it syncs, if it does not sync we also read one event too many
350  // (otherwise we cannot determine that we are "too far")
351  // and also have to push this one back
352  PushBackEvents(1);
353  if (syncobject->RunNumber() > mastersync->RunNumber() || // check if run number too large
354  syncobject->EventCounter() > mastersync->EventCounter() || // check if event counter too large
355  syncobject->SegmentNumber() > mastersync->SegmentNumber()) // check segment number too large
356  {
357  // the event from first file which determines the mastersync
358  // and which we are trying to find on this file does not exist on this file
359  // so: return failure. This will cause the input managers to read
360  // the next event from the input files file
362  }
363  // Here the event counter and segment number and run number do agree - we found the right match
364  // now read the full event (previously we only read the sync object)
365  PHCompositeNode *dummy;
366  dummy = IManager->read(dstNode);
367  if (!dummy)
368  {
369  cout << PHWHERE << " " << Name() << " Could not read full Event" << endl;
370  cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << endl;
371  fileclose();
373  }
374  int iret = syncobject->Different(mastersync); // final check if they really agree
375  if (iret) // if not things are severely wrong
376  {
377  cout << PHWHERE << " MasterSync and SyncObject of " << Name() << " are different" << endl;
378  cout << "This Event will not be processed further, here is some debugging info:" << endl;
379  cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << endl;
380  cout << "MasterSync->identify:" << endl;
381  mastersync->identify();
382  cout << Name() << ": SyncObject->identify:" << endl;
383  syncobject->identify();
385  }
386  else if (Verbosity() > 3)
387  {
388  cout << PHWHERE << " Resynchronization successfull for " << Name() << endl;
389  cout << "MasterSync->identify:" << endl;
390  mastersync->identify();
391  cout << Name() << ": SyncObject->identify:" << endl;
392  syncobject->identify();
393  }
394  }
395  }
396  // else
397  // {
398  // cout << "No Need to Resync" << endl;
399  // }
401 }
402 
404 {
405 readnextsync:
406  static int readfull = 0; // for some reason all the input managers need to see the same (I think, should look at this at some point)
407  if (!IManager) // in case the old file was exhausted and there is no new file opened
408  {
410  }
411  if (syncbranchname.empty())
412  {
413  readfull = 1; // we need to read a full event to set the root branches to phool nodes right when a new file has been opened
414  map<string, TBranch *>::const_iterator bIter;
415  for (bIter = IManager->GetBranchMap()->begin(); bIter != IManager->GetBranchMap()->end(); ++bIter)
416  {
417  if (Verbosity() > 2)
418  {
419  cout << Name() << ": branch: " << bIter->first << endl;
420  }
421  string delimeters = phooldefs::branchpathdelim; // + phooldefs::legacypathdelims;
422  vector<string> splitvec;
423  boost::split(splitvec, bIter->first, boost::is_any_of(delimeters));
424  for (size_t ia = 0; ia < splitvec.size(); ia++) // -1 so we skip the node name
425  {
426  if (splitvec[ia] == syncdefs::SYNCNODENAME)
427  {
428  syncbranchname = bIter->first;
429  break;
430  }
431  }
432  if (!syncbranchname.empty())
433  {
434  break;
435  }
436  }
437  if (syncbranchname.empty())
438  {
439  cout << PHWHERE << "Could not locate Sync Branch" << endl;
440  cout << "Please check for it in the following list of branch names and" << endl;
441  cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << endl;
442  for (bIter = IManager->GetBranchMap()->begin(); bIter != IManager->GetBranchMap()->end(); ++bIter)
443  {
444  cout << bIter->first << endl;
445  }
447  }
448  }
449  size_t EventOnDst = 0;
450  int itest = 0;
451  if (!readfull)
452  {
453  // if all files are exhausted, the IManager is deleted and set to nullptr
454  // so check if IManager is valid before getting a new event
455  if (IManager)
456  {
457  EventOnDst = IManager->getEventNumber(); // this returns the next number of the event
458  itest = IManager->readSpecific(EventOnDst, syncbranchname.c_str());
459  }
460  else
461  {
462  if (Verbosity() > 2)
463  {
464  cout << Name() << ": File exhausted while resyncing" << endl;
465  }
467  }
468  }
469  else
470  {
471  if (IManager->read(dstNode))
472  {
473  itest = 1;
474  }
475  else
476  {
477  itest = 0;
478  }
479  }
480  if (!itest)
481  {
482  if (Verbosity() > 2)
483  {
484  cout << Name() << ": File exhausted while resyncing" << endl;
485  }
486  fileclose();
487  if (OpenNextFile())
488  {
490  }
491  syncbranchname.clear(); // clear the sync branch name, who knows - it might be different on new file
492  goto readnextsync;
493  }
494  if (!readfull)
495  {
496  EventOnDst++;
497  IManager->setEventNumber(EventOnDst); // update event number in phool io manager
498  }
499  else
500  {
501  readfull = 0;
502  }
503  return 0;
504 }
505 
506 int Fun4AllDstInputManager::BranchSelect(const string &branch, const int iflag)
507 {
508  if (IsOpen())
509  {
510  cout << "BranchSelect(\"" << branch << "\", " << iflag
511  << ") : Input branches can only selected for reading before fileopen is called proceeding without input branch selection" << endl;
512  return -1;
513  }
514  // if iflag > 0 the branch is set to read
515  // if iflag = 0, the branch is set to NOT read
516  // if iflag < 0 the branchname is erased from our internal branch read map
517  // this does not have any effect on phool yet
518  if (iflag < 0)
519  {
520  map<const string, int>::iterator branchiter;
521  branchiter = branchread.find(branch);
522  if (branchiter != branchread.end())
523  {
524  branchread.erase(branchiter);
525  }
526  return 0;
527  }
528  int readit = 0;
529  if (iflag > 0)
530  {
531  if (Verbosity() > 1)
532  {
533  cout << "Setting Root Tree Branch: " << branch << " to read" << endl;
534  }
535  readit = 1;
536  }
537  else
538  {
539  if (Verbosity() > 1)
540  {
541  cout << "Setting Root Tree Branch: " << branch << " to NOT read" << endl;
542  }
543  }
544  branchread[branch] = readit;
545  return 0;
546 }
547 
549 {
550  if (IManager)
551  {
552  if (!branchread.empty())
553  {
554  map<const string, int>::const_iterator branchiter;
555  for (branchiter = branchread.begin(); branchiter != branchread.end(); ++branchiter)
556  {
557  IManager->selectObjectToRead(branchiter->first.c_str(), branchiter->second);
558  if (Verbosity() > 0)
559  {
560  cout << branchiter->first << " set to " << branchiter->second << endl;
561  }
562  }
563  // protection against switching off the sync variables
564  // only implemented in the Sync Manager
566  }
567  }
568  else
569  {
570  cout << PHWHERE << " " << Name() << ": You can only call this function after a file has been opened" << endl;
571  cout << "Do not worry, the branches will be set as soon as you open a file" << endl;
572  return -1;
573  }
574  return 0;
575 }
576 
578 {
579  // protection against switching off the sync variables
580  for (int i = 0; i < syncdefs::NUM_SYNC_VARS; i++)
581  {
582  IManager->selectObjectToRead(syncdefs::SYNCVARS[i], 1);
583  }
584  return 0;
585 }
586 
587 void Fun4AllDstInputManager::Print(const string &what) const
588 {
589  if (what == "ALL" || what == "BRANCH")
590  {
591  // loop over the map and print out the content (name and location in memory)
592  cout << "--------------------------------------" << endl
593  << endl;
594  cout << "List of selected branches in Fun4AllDstInputManager " << Name() << ":" << endl;
595 
596  map<const string, int>::const_iterator iter;
597  for (iter = branchread.begin(); iter != branchread.end(); ++iter)
598  {
599  cout << iter->first << " is switched ";
600  if (iter->second)
601  {
602  cout << "ON";
603  }
604  else
605  {
606  cout << "OFF";
607  }
608  cout << endl;
609  }
610  }
611  if ((what == "ALL" || what == "PHOOL") && IManager)
612  {
613  // loop over the map and print out the content (name and location in memory)
614  cout << "--------------------------------------" << endl
615  << endl;
616  cout << "PHNodeIOManager print in Fun4AllDstInputManager " << Name() << ":" << endl;
617  IManager->print();
618  }
620  return;
621 }
622 
624 {
625  if (IManager)
626  {
627  unsigned EventOnDst = IManager->getEventNumber();
628  EventOnDst -= static_cast<unsigned>(i);
629  IManager->setEventNumber(EventOnDst);
630  return 0;
631  }
632  cout << PHWHERE << Name() << ": could not push back events, Imanager is NULL"
633  << " probably the dst is not open yet (you need to call fileopen or run 1 event for lists)" << endl;
634  return -1;
635 }
636 
638 {
639  if (m_HaveSyncObject)
640  {
641  return m_HaveSyncObject;
642  }
643  if (IsOpen())
644  {
645  cout << PHWHERE << "HasSyncObject() not initialized check the calling order" << endl;
646  gSystem->Exit(1);
647  exit(1);
648  }
649  return 0;
650 }