Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Fun4AllSyncManager.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Fun4AllSyncManager.cc
1 #include "Fun4AllSyncManager.h"
2 
3 #include "Fun4AllInputManager.h"
4 #include "Fun4AllReturnCodes.h" // for EVENT_OK, RESET_NODE_TREE
5 #include "Fun4AllServer.h"
6 
8 
9 #include <phool/phool.h> // for PHWHERE
10 
11 #include <TSystem.h>
12 
13 #include <cstdlib>
14 #include <iostream> // for operator<<, endl, basic_ostream
15 #include <list> // for list<>::const_iterator, _List_con...
16 #include <string>
17 #include <utility> // for pair
18 #include <vector>
19 
21  : Fun4AllBase(name)
22 {
23  return;
24 }
25 
27 {
28  delete m_MasterSync;
29  while (m_InManager.begin() != m_InManager.end())
30  {
31  if (Verbosity())
32  {
33  m_InManager.back()->Verbosity(Verbosity());
34  }
35  delete m_InManager.back();
36  m_InManager.pop_back();
37  }
38  return;
39 }
40 
42 {
43  for (Fun4AllInputManager *inman : m_InManager)
44  {
45  if (inman->Name() == InputManager->Name())
46  {
47  std::cout << "InputManager " << InputManager->Name() << " allready in list" << std::endl;
48  return -1;
49  }
50  }
51 
52  if (Verbosity() > 0)
53  {
54  std::cout << "Registering InputManager " << InputManager->Name() << std::endl;
55  }
56  m_InManager.push_back(InputManager);
57  m_iretInManager.push_back(0);
58  InputManager->setSyncManager(this);
59  return 0;
60 }
61 
64 {
65  for (Fun4AllInputManager *inman : m_InManager)
66  {
67  if (name == inman->Name())
68  {
69  return inman;
70  }
71  }
72  std::cout << Name() << ": Could not find InputManager" << name << std::endl;
73  return nullptr;
74 }
75 
76 //_________________________________________________________________
77 int Fun4AllSyncManager::run(const int nevnts)
78 {
79  int iret = 0;
80  int icnt = 0;
81  int iretsync = 0;
82  int resetnodetree = 0;
83  // on read errors (assumed to be caused that a file is empty and we need to open the next one)
84  // we have to go through this 3 times
85  // 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
86  // 2nd pass: Events are read from all input managers. If no errors all input managers are pushed back
87  // The reason for this is that we opened a new files with maybe different content and we need to clean
88  // the node tree so we do not propagate old objects from the previous event
89  // The node tree reset is done by the Fun4AllServer so we give control back and signal via resetnodetree return code
90  // 3rd pass: read from every input manager and go back to Fun4All
91 
92  while (!iret)
93  {
94  unsigned iman = 0;
95  int ifirst = 0;
96  int hassync = 0;
97  for (auto &iter : m_InManager)
98  {
99  m_iretInManager[iman] = iter->run(1);
100  iret += m_iretInManager[iman];
101  // one can run DSTs without sync object via the DST input manager
102  // this only poses a problem if one runs two of them and expects the syncing to work
103  // or mix DSTs with sync object and without
104  if (!hassync && iter->HasSyncObject()) // only update if hassync is 0 and input mgr is non zero
105  {
106  hassync = iter->HasSyncObject();
107  }
108  else
109  {
110  if (iter->HasSyncObject()) // if zero (no syncing) no need to go further
111  {
112  if (hassync != iter->HasSyncObject()) // we have sync and no sync mixed
113  // NOLINTNEXTLINE(bugprone-branch-clone)
114  {
116  gSystem->Exit(1);
117  exit(1);
118  }
119  else if (hassync < 0) // we have more than one nosync input
120  {
122  gSystem->Exit(1);
123  exit(1);
124  }
125  }
126  }
127  if (!ifirst)
128  {
129  if (!m_iretInManager[iman])
130  {
131  if (!(iter->GetSyncObject(&m_MasterSync))) // NoSync managers return non zero
132  {
133  ifirst = 1;
134  }
135  }
136  }
137  else
138  {
139  iretsync = CheckSync(iman);
140  if (iretsync)
141  {
142  break;
143  }
144  }
145  iman++;
146  }
147 
148  // check event reading, syncronisation
149  if (iret || iretsync)
150  {
151  // tell the server to reset the node tree
152  resetnodetree = Fun4AllReturnCodes::RESET_NODE_TREE;
153 
154  // if there was an io error (file exhausted) we nee to push back
155  // the events from files which are not exhausted yet into the root files
156  // here we check the return codes for each input manager and if the
157  // read was successful (iret = 0) we push the event back
158  if (iret)
159  {
160  unsigned inputmgr_cnt = 0;
161  std::vector<Fun4AllInputManager *>::const_iterator InIter;
162  // set in the macro for Sync Manager. Permanently enabled (default when using syncman->Repeat(),
163  // m_Repeat = -1 so the m_Repeat--; is not called, this is used when you give it a positive number of
164  // repetitions
165  if (m_Repeat)
166  {
167  for (InIter = m_InManager.begin(); InIter != m_InManager.end(); ++InIter)
168  {
169  if (m_iretInManager[inputmgr_cnt] == Fun4AllReturnCodes::EVENT_OK)
170  {
171  (*InIter)->PushBackEvents(1);
172  }
173  else
174  {
175  if ((*InIter)->IsOpen())
176  {
177  (*InIter)->fileclose();
178  }
179  int ireset = (*InIter)->ResetFileList();
180  if (ireset)
181  {
182  std::cout << "Resetting input manager " << (*InIter)->Name() << " failed during Repeat" << std::endl;
183  exit(1);
184  }
185  inputmgr_cnt++;
186  }
187  }
188  if (m_Repeat > 0)
189  {
190  m_Repeat--;
191  }
192  iret = 0;
193  continue; // got back and run again
194  }
195  // push back events where the Imanager did not report an error
196  InIter = m_InManager.begin();
197  for (int iter : m_iretInManager)
198  {
199  if (Verbosity() > 0)
200  {
201  std::cout << (*InIter)->Name() << ": return code: " << iter << std::endl;
202  }
203  if (!iter)
204  {
205  (*InIter)->PushBackEvents(1);
206  if (Verbosity() > 0)
207  {
208  std::cout << (*InIter)->Name() << ": push evts: " << iter << std::endl;
209  }
210  }
211  ++InIter;
212  }
213  // NOLINTNEXTLINE(hicpp-avoid-goto)
214  goto readerror;
215  }
216  else
217  {
218  // just read the next event and hope it syncs
219  // this won't update the event counter
220  for (unsigned nman = 0; nman < iman; nman++)
221  {
222  m_InManager[nman]->NoSyncPushBackEvents(1);
223  }
224  continue;
225  }
226  }
227  if (!resetnodetree)
228  {
229  m_EventsTotal++;
230  }
231  // this check is meaningless nowadays since we call this method with 1 event every time
232  // so we can just break here but maybe this changes in the future
233  if (nevnts > 0 && ++icnt >= nevnts)
234  {
235  break;
236  }
237  }
238 
239 readerror:
240  if (!iret)
241  {
242  if (!resetnodetree) // all syncing is done and no read errors --> we have a good event in memory
243  {
244  m_CurrentRun = 0; // reset current run to 0
245  for (auto &iter : m_InManager)
246  {
247  int runno = iter->RunNumber();
248  if (Verbosity() > 2)
249  {
250  std::cout << Name() << " input mgr " << iter->Name() << " run: " << runno << std::endl;
251  }
252  if (runno != 0)
253  {
254  if (m_CurrentRun == 0)
255  {
256  m_CurrentRun = runno;
257  continue;
258  }
259  else
260  {
261  if (m_CurrentRun != runno && !m_MixRunsOkFlag)
262  {
263  std::cout << PHWHERE << "Mixing run numbers (except runnumber=0 which means no valid runnumber) is not supported" << std::endl;
264  std::cout << "Here are the list of input managers and runnumbers:" << std::endl;
265  for (Fun4AllInputManager *inman : m_InManager)
266  {
267  std::cout << inman->Name() << " runno: " << inman->RunNumber() << std::endl;
268  }
269  std::cout << "Exiting now" << std::endl;
270  exit(1);
271  }
272  }
273  }
274  }
275  }
276  return resetnodetree;
277  }
278  return iret;
279 }
280 
281 //_________________________________________________________________
282 int Fun4AllSyncManager::skip(const int nevnts)
283 {
284  if (!m_InManager.empty())
285  {
286  int Npushback = -nevnts;
287  // the PushBackEvents(const int nevents) "pushes back" events events into the root file
288  // (technically it just decrements the local counter in the PHNodeIOManager)
289  // giving it a negative argument will skip events
290  // this is much faster than actually reading the events in
291  int iret = m_InManager[0]->PushBackEvents(Npushback);
292  for (unsigned int i = 1; i < m_InManager.size(); ++i)
293  {
294  iret += m_InManager[i]->SkipForThisManager(nevnts);
295  }
296  if (!iret)
297  {
298  return 0;
299  }
300  else
301  {
302  std::cout << PHWHERE << " Error during skipping events" << std::endl;
303  return iret;
304  }
305  }
306  std::cout << PHWHERE << " Cannot skip events: No Input Managers registered?" << std::endl;
307  Print("INPUTMANAGER");
308  std::cout << "If there are Input Managers in this list, send mail with this" << std::endl;
309  std::cout << "error message to off-l" << std::endl;
310  std::cout << "and include the macro you used" << std::endl;
311  return -1;
312 }
313 
314 //_________________________________________________________________
316 {
317  for (Fun4AllInputManager *inman : m_InManager)
318  {
319  if (managername == inman->Name())
320  {
321  int iret = inman->fileopen(filename);
322  return iret;
323  }
324  }
325  std::cout << "No Input Manager " << managername << " registered" << std::endl;
326  return -1;
327 }
328 
329 int Fun4AllSyncManager::BranchSelect(const std::string &managername, const std::string &branch, const int iflag)
330 {
331  for (Fun4AllInputManager *inman : m_InManager)
332  {
333  if (managername == inman->Name())
334  {
335  int iret = inman->BranchSelect(branch, iflag);
336  return iret;
337  }
338  }
339  std::cout << "No Input Manager " << managername << " registered" << std::endl;
340  return -1;
341 }
342 
343 int Fun4AllSyncManager::BranchSelect(const std::string &branch, const int iflag)
344 {
345  int iret = 0;
346  for (Fun4AllInputManager *inman : m_InManager)
347  {
348  iret += inman->BranchSelect(branch, iflag);
349  }
350  return iret;
351 }
352 
354 {
355  for (Fun4AllInputManager *inman : m_InManager)
356  {
357  if (managername == inman->Name())
358  {
359  int iret = inman->setBranches();
360  return iret;
361  }
362  }
363  std::cout << "No Input Manager " << managername << " registered" << std::endl;
364  return -1;
365 }
366 
368 {
369  int iret = 0;
370  for (Fun4AllInputManager *inman : m_InManager)
371  {
372  iret += inman->setBranches();
373  }
374  return iret;
375 }
376 
378 {
379  int foundIt = 0;
380  for (Fun4AllInputManager *inman : m_InManager)
381  {
382  if (managername == inman->Name() || managername.empty())
383  {
384  inman->fileclose();
385  foundIt = 1;
386  }
387  }
388  if (foundIt)
389  {
390  return 0;
391  }
392  std::cout << "No Input Manager " << managername << " registered" << std::endl;
393  return -1;
394 }
395 
396 void Fun4AllSyncManager::Print(const std::string &what) const
397 {
398  if (what == "ALL" || what == "INPUTMANAGER")
399  {
400  // loop over the map and print out the content (name and location in memory)
401  std::cout << "--------------------------------------" << std::endl
402  << std::endl;
403  std::cout << "List of InputManagers in Fun4AllSyncManager "
404  << Name() << ":" << std::endl;
405 
406  for (Fun4AllInputManager *inman : m_InManager)
407  {
408  std::cout << inman->Name() << std::endl;
409  }
410  std::cout << std::endl;
411  }
412  return;
413 }
414 
415 int Fun4AllSyncManager::CheckSync(const unsigned i)
416 {
417  int iret;
418  iret = m_InManager[i]->SyncIt(m_MasterSync);
419  return iret;
420 }
421 
422 void Fun4AllSyncManager::GetInputFullFileList(std::vector<std::string> &fnames) const
423 {
424  for (Fun4AllInputManager *InMan : m_InManager)
425  {
426  std::pair<std::list<std::string>::const_iterator, std::list<std::string>::const_iterator> beginend = InMan->FileOpenListBeginEnd();
427  for (auto iter = beginend.first; iter != beginend.second; ++iter)
428  {
429  fnames.push_back(*iter);
430  }
431  }
432  return;
433 }
434 
436 {
437  for (Fun4AllInputManager *inman : m_InManager)
438  {
439  inman->PushBackEvents(i);
440  }
441  return;
442 }
443 
445 {
446  int iret = 0;
447  for (Fun4AllInputManager *inman : m_InManager)
448  {
449  if (Verbosity() > 0)
450  {
451  std::cout << "Resetting Event for Input Manager " << inman->Name() << std::endl;
452  }
453  iret += inman->ResetEvent();
454  }
455  return iret;
456 }
457 
459 {
460  m_CurrentEvent = evt;
462  se->EventNumber(evt);
463  return;
464 }
465 
467 {
468  std::cout << "Bad use of Fun4AllDstInputManager for file(s) which do not have a synchronization object" << std::endl;
469  std::cout << "This works for single streams but if you run with multiple input streams this might lead to event mixing" << std::endl;
470  std::cout << "If you insist to run this (you take full responsibility), change the following in your macro: " << std::endl;
471  for (auto iter : m_InManager)
472  {
473  if (iter->HasSyncObject() < 0)
474  {
475  std::cout << "File " << iter->FileName() << " does not contain a sync object" << std::endl;
476  std::cout << "Change its Fun4AllDstInputManager with name " << iter->Name() << " from Fun4AllDstInputManager to Fun4AllNoSyncDstInputManager" << std::endl;
477  }
478  }
479  return;
480 }