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