GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
MainUserAnalysis.cxx
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include <cstring>
15 #include <cstdlib>
16 #include <cstdio>
17 #include <iostream>
18 
19 #include "TROOT.h"
20 #include "TClass.h"
21 #include "TClassTable.h"
22 #include "TDataType.h"
23 #include "TMethod.h"
24 #include "TMethodArg.h"
25 #include "TRint.h"
26 #include "TSystem.h"
27 #include "TObjString.h"
28 #include "TInterpreter.h"
29 #include "TStyle.h"
30 
31 #include "TGo4Version.h"
32 #include "TGo4Log.h"
33 #include "TGo4StepFactory.h"
34 #include "TGo4AnalysisStep.h"
35 #include "TGo4AnalysisImp.h"
36 #include "TGo4AnalysisClient.h"
37 #include "Go4EventServer.h"
38 #include "Go4EventServerTypes.h"
39 
40 #ifdef __GO4HDF5__
42 #include "TGo4HDF5StoreParameter.h"
43 #endif
44 
45 #include "TGo4FileStore.h"
46 
47 #define PROCESSLOOPDELAY 20
48 // milliseconds
49 #define TERMCOUNTS 10000
50 // x PROCESSLOOPDELAY termination wait time
51 
52 void showerror(const TString &msg)
53 {
54  std::cerr << "Error: " << msg << std::endl;
55  std::cerr << "Call 'go4analysis -help' to see list of available arguments" << std::endl;
56  exit(1);
57 }
58 
60 {
61  std::cout << " -file filename : use file filename (lmd or lml) as MBS event source (short: -f)" << std::endl;
62  std::cout << " -transport server : connect to MBS transport server (short: -tr)" << std::endl;
63  std::cout << " -stream server : connect to MBS stream server (short: -st)" << std::endl;
64  std::cout << " -evserv server : connect to MBS event server (short: -ev)" << std::endl;
65  std::cout << " -revserv server [port] : connect to remote event server (short: -rev)" << std::endl;
66  std::cout << " -random : use random generator as source (short: -rnd)" << std::endl;
67 #ifdef __GO4HDF5__
68  std::cout << " -hdf5 name : use HDF5 formatted file (h5) as event source" << std::endl;
69 #endif
70  std::cout << " -user name : create user-defined event source" << std::endl;
71  std::cout << " -timeout tm : specify timeout parameter for event source" << std::endl;
72  std::cout << " -skip num : skip num first events in mbs event source" << std::endl;
73  std::cout << " -mbs-select first last step : select events interval from mbs source " << std::endl;
74  std::cout << " first: sequence number of the first event (starts from 0)" << std::endl;
75  std::cout << " last: sequence number of the last event" << std::endl;
76  std::cout << " step: step over several events, 1 means all events are used" << std::endl;
77 
78 }
79 
80 void usage(const char *subtopic = nullptr)
81 {
82  std::cout << std::endl;
83  std::cout << "GO4 analysis runnable " << __GO4RELEASE__ << std::endl;
84  std::cout << "S. Linev, GSI, Darmstadt" << std::endl;
85 
86  if (subtopic && (strlen(subtopic) > 0)) {
87  const char *sub = subtopic;
88  if (*sub == '-') sub++;
89 
90  if ((strcmp(subtopic, "sources") == 0) || (strcmp(subtopic, "src") == 0) || (strcmp(subtopic, "src") == 0)) {
91  std::cout << "These are arguments of go4analysis which allows to specify event source" << std::endl;
92  printsources();
93  return;
94  } else
95  if ((strcmp(sub, "print") == 0) || (strcmp(sub, "pr") == 0) ||
96  (strcmp(sub, "type") == 0) || (strcmp(sub, "ty") == 0)) {
97  std::cout << "Usage of go4analysis -print command." << std::endl;
98  std::cout << std::endl;
99  std::cout << " go4analysis -print|-pr|-type|-ty [PROPT] [SOURCE] [MISC]" << std::endl;
100  std::cout << std::endl;
101  std::cout << "PROPT: print options, right after -print command" << std::endl;
102  std::cout << " hex : print data in hexadecimal format" << std::endl;
103  std::cout << " dec : print data in decimal format" << std::endl;
104  std::cout << " long : print data in long (4 bytes) form (default)" << std::endl;
105  std::cout << " short : print data in short (2 bytes) form" << std::endl;
106  std::cout << " sub=N : select subevent id N (default all subevents are shown)" << std::endl;
107  std::cout << " fhead : print current lmd file header" << std::endl;
108  std::cout << " bhead : print current buffer header" << std::endl;
109  std::cout << "SOURCE: event source print options" << std::endl;
110  printsources();
111  std::cout << "MISC: other options, which may be relevant for \"print\" command" << std::endl;
112  std::cout << " -number M : print M events, default is 1 (short: -num)" << std::endl;
113  std::cout << " -lib name : load library, may be required for user-defined sources" << std::endl;
114  std::cout << " -v : enable verbose mode to see some debug output (default: -v2)" << std::endl;
115  std::cout << std::endl;
116  std::cout << " Print event header from MBS stream server" << std::endl;
117  std::cout << " go4analysis -stream r4-4 -print " << std::endl;
118  std::cout << std::endl;
119  std::cout << " Print event data in hexadecimal form from MBS event server" << std::endl;
120  std::cout << " go4analysis -ev r2-1 -pr hex" << std::endl;
121  std::cout << std::endl;
122  std::cout << " Print 5 events with subevent id=1 in decimal form from MBS transport server" << std::endl;
123  std::cout << " go4analysis -tr r2-2 -num 5 -ty dec sub=1 " << std::endl;
124  std::cout << std::endl;
125  return;
126  } else {
127  std::cout << "No help for topic: \""<< subtopic << "\"" << std::endl;
128  std::cout << "Available: print, sources" << std::endl;
129  return;
130  }
131  }
132 
133  std::cout << "calling: " << std::endl;
134  std::cout << "" << std::endl;
135  std::cout << " go4analysis [RUN] [ANALYSIS] [STEP1] [STEP2] ... [USER]" << std::endl;
136  std::cout << "" << std::endl;
137  std::cout << "RUN: configuration, relevant for application run mode" << std::endl;
138  std::cout << " -lib name : user library to load (default: libGo4UserLibrary)" << std::endl;
139  std::cout << " -server [name] : run analysis in server mode, name - optional analysis name" << std::endl;
140  std::cout << " -gui name guihost guiport : run analysis in gui mode, used by GUI launch analysis" << std::endl;
141 #ifdef WITH_HTTP
142  std::cout << " -http [port] : run analysis with web-server running, " << std::endl;
143  std::cout << " optionally port can be specified, default 8080" << std::endl;
144  std::cout << " -auth [filename] : use authentication file to restrict access to http server " << std::endl;
145  std::cout << " file should contain 'controller' and 'admin' accounts for 'go4' domain" << std::endl;
146  std::cout << " Could be generated with htdigets utility, by default '$GO4SYS/etc/.htdigest' filename is used" << std::endl;
147  std::cout << " -fastcgi port : run analysis with fastcgi server running, "<< std::endl;
148  std::cout << " which can deliver data to normal webserver (see mod_proxy_fcgi for Apache)" << std::endl;
149  std::cout << " -jsroot location : use JSROOT from other location like https://root.cern.ch/js/latest/" << std::endl;
150 #ifdef WITH_DABC
151  std::cout << " -dabc master_host:port : run analysis with optional connection to dabc application, "<< std::endl;
152  std::cout << " which could receive objects from running analysis" << std::endl;
153 #endif
154 #endif
155  std::cout << " -run : run analysis in server mode (default only run if source specified)" << std::endl;
156  std::cout << " -norun : exclude automatical run" << std::endl;
157  std::cout << " -number NUMBER : process NUMBER events in batch mode" << std::endl;
158  std::cout << " -hserver [name [passwd]] : start histogram server with optional name and password" << std::endl;
159  std::cout << " -log [filename] : enable log output into filename (default:go4logfile.txt)" << std::endl;
160  std::cout << " -v -v0 -v1 -v2 -v3 : change log output verbosity (0 - maximum, 1 - info, 2 - warn, 3 - errors)" << std::endl;
161  std::cout << " -gdebug [lvl] : set ROOT gDebug value, default 1" << std::endl;
162  std::cout << " -rate : display rate information during run" << std::endl;
163  std::cout << " -print [sub=N] [hex|dec] : print events, see -help print for more info" << std::endl;
164  std::cout << " -help [topic] : show this help or for selected topic" << std::endl;
165  std::cout << " -version : print only go4 version" << std::endl;
166  std::cout << " -graphics : enable graphics in the analysis" << std::endl;
167  std::cout << "" << std::endl;
168  std::cout << "ANALYSIS: common analysis configurations" << std::endl;
169  std::cout << " -name name : specify analysis instance name" << std::endl;
170  std::cout << " -asf [filename] : enable store autosave file and set autosave filename (default <Name>ASF.root)" << std::endl;
171  std::cout << " -enable-asf [interval] : enable store of autosave file, optionally interval in seconds" << std::endl;
172  std::cout << " -disable-asf : disable usage of asf" << std::endl;
173  std::cout << " -prefs [filename] : load preferences (analysis configuration) from specified file (default Go4AnalysisPrefs.root)" << std::endl;
174  std::cout << " -no-prefs : disable preferences loading" << std::endl;
175  std::cout << " -maxtreesize value : define maximum tree size, value can be: 2g, 1900m, 1900000000" << std::endl;
176  std::cout << "" << std::endl;
177  std::cout << "STEP: individual step configurations" << std::endl;
178  std::cout << " -step name : select step by it's name, if not found, first step will be used" << std::endl;
179  std::cout << " -step number : select step by it's number (first step has number 0)" << std::endl;
180  std::cout << " -enable-step : enable step processing" << std::endl;
181  std::cout << " -disable-step : disable step processing" << std::endl;
182  std::cout << " -file filename : use file filename (lmd or lml) as MBS event source" << std::endl;
183  std::cout << " -transport server : connect to MBS transport server" << std::endl;
184  std::cout << " -stream server : connect to MBS stream server" << std::endl;
185  std::cout << " -evserv server : connect to MBS event server" << std::endl;
186  std::cout << " -revserv server [port] : connect to remote event server" << std::endl;
187  std::cout << " -port number : select custom port number for event source" << std::endl;
188  std::cout << " -retry number : select number of retries when connection to source was lost" << std::endl;
189  std::cout << " -random : use random generator as source" << std::endl;
190  std::cout << " -user name : create user-defined event source" << std::endl;
191  std::cout << " -source filename : read step input from the root file" << std::endl;
192 #ifdef __GO4HDF5__
193  std::cout << " -hdf5 filename : read step input from hdf5 file (.h5)" << std::endl;
194 #endif
195  std::cout << " -skip num : skip num first events in mbs event source" << std::endl;
196  std::cout << " -mbs-select first last step : select events interval from mbs source" << std::endl;
197  std::cout << " -timeout tm : specify timeout parameter for event source" << std::endl;
198  std::cout << " -enable-source : enable step source" << std::endl;
199  std::cout << " -disable-source : disable step source" << std::endl;
200  std::cout << " -store filename [split buffersize compression] : write step output into the root file" << std::endl;
201  std::cout << " -overwrite-store : overwrite file, when store output" << std::endl;
202  std::cout << " -append-store : append to file, when store output" << std::endl;
203  std::cout << " -backstore name : create backstore for online tree draw" << std::endl;
204 #ifdef __GO4HDF5__
205  std::cout << " -hdf5store filename : write step output into hdf5 file (.h5)" << std::endl;
206 #endif
207  std::cout << " -userstore name : create user-defined store for output data" << std::endl;
208  std::cout << " -enable-store : enable step store" << std::endl;
209  std::cout << " -disable-store : disable step store" << std::endl;
210  std::cout << " -enable-errstop : enable stop-on-error mode" << std::endl;
211  std::cout << " -disable-errstop : disable stop-on-error mode" << std::endl;
212  std::cout << " -inpevt-class name : (re)define class name of input event" << std::endl;
213  std::cout << " -outevt-class name : (re)define class name of output event" << std::endl;
214  std::cout << std::endl;
215  std::cout << "USER: user-defined arguments" << std::endl;
216  std::cout << " -args [userargs] : create user analysis with constructor (int argc, char **argv) signature" << std::endl;
217  std::cout << " all following arguments will be provided as array of strings, first argument - analysis name" << std::endl;
218  std::cout << std::endl;
219 }
220 
222  public:
223  TGo4PrintProcessor(const char *name) : TGo4EventProcessor(name) {}
224 
225  static Int_t fSubId;
226  static Bool_t fHex;
227  static Bool_t fLong;
228  static Bool_t fData;
229  static Bool_t fFileHead;
230  static Bool_t fBufHead;
231 
232  Bool_t BuildEvent(TGo4EventElement *dest) override
233  {
235 
236  auto mbs = dynamic_cast<TGo4MbsEvent *> (evnt);
237  if (mbs) mbs->PrintMbsEvent(fSubId, fLong, fHex, fData, fBufHead, fFileHead);
238  else evnt->PrintEvent();
239 
240  return kTRUE;
241  }
242 };
243 
244 Int_t TGo4PrintProcessor::fSubId = -1;
245 Bool_t TGo4PrintProcessor::fHex = kTRUE;
246 Bool_t TGo4PrintProcessor::fLong = kTRUE;
247 Bool_t TGo4PrintProcessor::fData = kFALSE;
248 Bool_t TGo4PrintProcessor::fFileHead = kFALSE;
249 Bool_t TGo4PrintProcessor::fBufHead = kFALSE;
250 
252  public:
253  TGo4PrintFactory(const char *name) : TGo4StepFactory(name) {}
255  {
256  return new TGo4PrintProcessor("PrintProc");
257  }
258 };
259 
260 
261 typedef TGo4Analysis *(UserCreateFunc)(const char *name);
262 
263 int FindArg(int argc, char **argv, const char *argname)
264 {
265  if (!argname || (strlen(argname) == 0))
266  return -1;
267  for (int n = 0; n < argc; n++)
268  if (strcmp(argv[n], argname) == 0)
269  return n;
270  return -1;
271 }
272 
273 const char *GetArgValue(int argc, char **argv, const char *argname, int* pos = nullptr, bool incomplete = false)
274 {
275  int n = pos ? *pos : 0;
276 
277  while (++n<argc)
278  if (strcmp(argv[n], argname) == 0) {
279  if ((n+1<argc) && (argv[n+1][0]!='-')) {
280  if (pos) *pos = n+1;
281  return argv[n+1];
282  } else
283  if (incomplete) {
284  if (pos) *pos = n+1;
285  return "";
286  }
287  }
288 
289  if (pos) *pos = 0;
290  return nullptr;
291 }
292 
293 TList *GetClassesList(TList *prev = nullptr)
294 {
295  TClassTable::Init();
296  char *name = nullptr;
297 
298  TList *lst = new TList;
299  lst->SetOwner(kTRUE);
300 
301  if (prev) TGo4Log::Debug("Search user classes in loaded library");
302 
303  while ((name = TClassTable::Next()) != nullptr) {
304  if (prev && prev->FindObject(name)) continue;
305 
306  TNamed *obj = new TNamed(name, name);
307  lst->Add(obj);
308 
309  if (prev) TGo4Log::Debug("New class %s", name);
310  }
311  return lst;
312 }
313 
314 TGo4Analysis *CreateDefaultAnalysis(TList *lst, const char *name, int user_argc, char **user_argv, bool doprint)
315 {
316  TIter iter(lst);
317 
318  TObjArray evnt_classes; // list of found event classes
319 
320  TClass *proc_cl = nullptr, *an_cl = nullptr, *evsrc_cl = nullptr, *evstore_cl = nullptr;
321 
322  while (auto obj = iter()) {
323  TClass *cl = TClass::GetClass(obj->GetName());
324 
325  // all relevant go4 classes inherited from TObject
326  if (!cl || !cl->IsStartingWithTObject()) continue;
327 
328  if (cl->InheritsFrom(TGo4EventProcessor::Class())) {
329  // if several processor classes are existing, take higher in hierarchy
330  if ((cl != TGo4EventProcessor::Class()) && (!proc_cl || cl->InheritsFrom(proc_cl)))
331  proc_cl = cl;
332  } else if (cl->InheritsFrom(TGo4EventSource::Class())) {
333  if ((cl != TGo4EventSource::Class()) && !evsrc_cl)
334  evsrc_cl = cl;
335  } else if (cl->InheritsFrom(TGo4EventStore::Class())) {
336  if ((cl != TGo4EventStore::Class()) && !evstore_cl)
337  evstore_cl = cl;
338  } else if (cl->InheritsFrom(TGo4EventElement::Class())) {
339  if (cl != TGo4EventElement::Class())
340  evnt_classes.Add(cl);
341  } else if (cl->InheritsFrom(TGo4Analysis::Class())) {
342  if ((cl != TGo4Analysis::Class()) && !an_cl)
343  an_cl = cl;
344  }
345  }
346 
347  if (doprint) {
348  an_cl = nullptr;
349  }
350 
351  if (an_cl) {
352 
353  TGo4Log::Info("Find user analysis class %s", an_cl->GetName());
354 
355  TMethod* meth = an_cl->GetMethodWithPrototype(an_cl->GetName(), "int,char**");
356  if (meth) {
357  TGo4Log::Info("!!! Find constructor with prototype %s::%s(int, char **)", an_cl->GetName(), an_cl->GetName());
358 
359  if ((user_argc > 0) && user_argv) {
360  user_argv[0] = (char*) name;
361  } else {
362  user_argc = 1;
363  user_argv = (char **) &name;
364  }
365 
366  #ifdef _MSC_VER
367  TString cmd = TString::Format("new %s(%d, (char **)0x%x)", an_cl->GetName(), user_argc, user_argv);
368  #else
369  TString cmd = TString::Format("new %s(%d, (char **)%p)", an_cl->GetName(), user_argc, user_argv);
370  #endif
371  Int_t err = 0;
372 
373  TGo4Log::Info("Process: %s", cmd.Data());
374 
375  TGo4Analysis *analysis = (TGo4Analysis*) gROOT->ProcessLineFast(cmd.Data(), &err);
376 
377  if (analysis && (err == 0)) return analysis;
378 
379  TGo4Log::Error("Cannot create analysis class %s instance with (int, char **) prototype", an_cl->GetName());
380  TGo4Log::Error("Implement correct analysis constructor with such signature in user library");
381  exit(1);
382  }
383 
384 
385  meth = an_cl->GetMethodWithPrototype(an_cl->GetName(), "const char*");
386  if (meth) {
387  TGo4Log::Info("!!! Find constructor with prototype %s::%s(const char *)", an_cl->GetName(), an_cl->GetName());
388 
389  TString cmd = TString::Format("new %s(\"%s\")", an_cl->GetName(), name);
390  Int_t err = 0;
391 
392  TGo4Log::Info("Process: %s", cmd.Data());
393 
394  TGo4Analysis *analysis = (TGo4Analysis*) gROOT->ProcessLineFast(cmd.Data(), &err);
395 
396  if (analysis && (err == 0)) return analysis;
397 
398  TGo4Log::Error("Cannot create analysis class %s instance with (const char *) prototype", an_cl->GetName());
399  TGo4Log::Error("Implement correct analysis constructor with such signature in user library");
400  exit(1);
401  }
402 
403  // search for non-default analysis constructor
404  TIter iter(an_cl->GetListOfMethods());
405  while ((meth = (TMethod*) iter()) != nullptr) {
406  if (strcmp(meth->GetName(), an_cl->GetName()) != 0) continue;
407  if (meth->GetListOfMethodArgs()->GetSize() == 0) continue;
408  break;
409  }
410 
411  if (!meth) {
412  TGo4Log::Error("Cannot find non-default constructor for class %s", an_cl->GetName());
413  TGo4Log::Error("Implement analysis constructor with (const char *) or (int, char **) signature");
414  TGo4Log::Error("Or define TGo4Analysis *CreateUserAnalysis(const char *) function in user library");
415  exit(1);
416  }
417 
418  TGo4Log::Info("Find constructor with %d arguments", meth->GetListOfMethodArgs()->GetSize());
419 
420  TIter next(meth->GetListOfMethodArgs());
421 
422  TString cmd = TString::Format("new %s(", an_cl->GetName());
423 
424  int counter = 0;
425 
426  while (auto argument = (TMethodArg *) next()) {
427 
428  if (counter > 0) cmd+=", ";
429  counter++;
430 
431  TDataType *datatype = gROOT->GetType(argument->GetTypeName());
432 
433  TString basictype = !datatype ? "int" : datatype->GetTypeName();
434 
435  TGo4Log::Debug("Argument %s type %s basictype %s", argument->GetName(), argument->GetTitle(), basictype.Data());
436 
437  TString argDflt = argument->GetDefault() ? argument->GetDefault() : "";
438  if (argDflt.Length()>0) {
439  cmd += argDflt;
440  continue;
441  }
442 
443  bool isptr = strchr(argument->GetTitle(), '*') != nullptr;
444 
445  if (!datatype && !isptr) {
446  TGo4Log::Error("Cannot specify any value for argument %s of class %s constructor", argument->GetName(), an_cl->GetName());
447  TGo4Log::Error("Add CreateUserAnalysis(const char *) function in user library");
448  exit(1);
449  }
450 
451  if (isptr) {
452  if ((basictype == "char") || (basictype == "Text_t")) cmd += "\"\"";
453  else cmd += "0";
454  } else {
455  if ((counter==2) && (basictype=="int")) {
456  TGo4Log::Info("Special treatment for second integer argument, suppose MBS input type");
457  cmd += TString::Format("%d", GO4EV_MBS_FILE);
458  } else
459  if (basictype=="bool") {
460  cmd += "false";
461  } else
462  cmd += "0";
463  }
464  }
465 
466  cmd += ")";
467 
468  Int_t err = 0;
469  TGo4Log::Info("Process: %s", cmd.Data());
470  TGo4Analysis *analysis = (TGo4Analysis*) gROOT->ProcessLineFast(cmd.Data(), &err);
471  if (analysis && (err == 0)) return analysis;
472 
473  TGo4Log::Error("Cannot create analysis class %s instance", an_cl->GetName());
474  TGo4Log::Error("Add CreateUserAnalysis(const char *) function in user library");
475 
476  exit(1);
477  }
478 
479  TClass *outev_cl = nullptr, *inpev_cl = nullptr;
480 
481  const char *inp_evnt_classname = GetArgValue(user_argc, user_argv, "-inpevt-class");
482  const char *out_evnt_classname = GetArgValue(user_argc, user_argv, "-outevt-class");
483 
484  if (inp_evnt_classname) {
485  inpev_cl = gROOT->GetClass(inp_evnt_classname);
486  if (!inpev_cl) {
487  TGo4Log::Error("Class %s not exists", inp_evnt_classname);
488  exit(1);
489  }
490 
491  if (!inpev_cl->InheritsFrom(TGo4EventElement::Class())) {
492  TGo4Log::Error("Class %s cannot be used as input event", inp_evnt_classname);
493  exit(1);
494  }
495 
496  evnt_classes.Remove(inpev_cl);
497  evnt_classes.Compress();
498  }
499 
500  if (out_evnt_classname) {
501  outev_cl = gROOT->GetClass(out_evnt_classname);
502  if (!outev_cl) {
503  TGo4Log::Error("Class %s not exists", out_evnt_classname);
504  exit(1);
505  }
506 
507  if (!outev_cl->InheritsFrom(TGo4EventElement::Class())) {
508  TGo4Log::Error("Class %s cannot be used as output event", out_evnt_classname);
509  exit(1);
510  }
511 
512  evnt_classes.Remove(outev_cl);
513  evnt_classes.Compress();
514  }
515 
516  // check if user event source requires special event class
517  // create instance only if we have something to check
518  if (evsrc_cl && !inpev_cl && (evnt_classes.GetLast() >= 0)) {
519  TGo4EventSource *src = (TGo4EventSource*) evsrc_cl->New();
520 
521  // if special input event is required, try to detect it
522  if (src && !src->CheckEventClass(TGo4MbsEvent::Class())) {
523  for (int n = 0; n <= evnt_classes.GetLast(); n++) {
524  TClass *cl = (TClass *) evnt_classes.At(n);
525  if (!src->CheckEventClass(cl)) continue;
526 
527  // if more than two classes are suited - ignore any of them
528  if (inpev_cl) { inpev_cl = nullptr; break; }
529 
530  inpev_cl = cl;
531  }
532  }
533 
534  delete src;
535 
536  if (inpev_cl) {
537  evnt_classes.Remove(inpev_cl);
538  evnt_classes.Compress();
539  }
540  }
541 
542  // as very last, try to define best-suitable output event
543  if (!outev_cl)
544  for (int n = 0; n <= evnt_classes.GetLast(); n++) {
545  TClass *cl = (TClass *)evnt_classes.At(n);
546  if (!outev_cl || cl->InheritsFrom(outev_cl)) outev_cl = cl;
547  }
548 
549  if (doprint) {
550  TGo4Log::Info("Create default analysis with print-processor class");
551  outev_cl = nullptr;
552  } else {
553  if (!proc_cl) return nullptr;
554  TGo4Log::Info("Create default analysis with processor class %s", proc_cl->GetName());
555  if (outev_cl)
556  TGo4Log::Info("Use class %s as output event", outev_cl->GetName());
557  }
558 
559 
560  if (inpev_cl)
561  TGo4Log::Info("Use class %s as input event", inpev_cl->GetName());
562 
563  TGo4Analysis *analysis = TGo4Analysis::Instance();
564  analysis->SetAnalysisName(name);
565 
566  TGo4StepFactory* factory = nullptr;
567 
568  if (doprint) {
569  factory = new TGo4PrintFactory("Factory");
570  } else {
571  factory = new TGo4StepFactory("Factory");
572  factory->DefEventProcessor("Processor", proc_cl->GetName());// object name, class name
573  }
574 
575  if (inpev_cl)
576  factory->DefInputEvent("InputEvent", inpev_cl->GetName()); // object name, class name
577 
578  if (outev_cl)
579  factory->DefOutputEvent("OutputEvent", outev_cl->GetName()); // object name, class name
580  else
581  factory->DefOutputEvent("OutputEvent", "TGo4EventElement"); // object name, class name
582 
583  if (evsrc_cl)
584  factory->DefUserEventSource(evsrc_cl->GetName());
585 
586  if (evstore_cl)
587  factory->DefUserEventStore(evstore_cl->GetName());
588 
589  TGo4MbsFileParameter* sourcepar = new TGo4MbsFileParameter(analysis->GetDefaultTestFileName());
590 
591  TGo4AnalysisStep *step = new TGo4AnalysisStep("Analysis", factory, sourcepar);
592 
593  step->SetSourceEnabled(kTRUE);
594  step->SetStoreEnabled(evstore_cl != nullptr);
595  step->SetProcessEnabled(kTRUE);
596  step->SetErrorStopEnabled(kTRUE);
597 
598  // Now the first analysis step is set up.
599  // Other steps could be created here
600  analysis->AddAnalysisStep(step);
601 
602  return analysis;
603 }
604 
605 //================== analysis main program ============================
606 int main(int argc, char **argv)
607 {
609  std::cerr << "Please check your system configuration and restart analysis again" << std::endl;
610  return -1;
611  }
612 
613  if (argc == 1) {
614  usage();
615  return 0;
616  }
617 
618  if ((FindArg(argc, argv, "-version") > 0) || (FindArg(argc, argv, "--version") > 0)) {
619  std::cout << __GO4RELEASE__ << std::endl;
620  return 0;
621  }
622 
623  int phelp = FindArg(argc, argv, "-help");
624  if (phelp < 0) phelp = FindArg(argc, argv, "-h") > 0;
625  if (phelp > 0) {
626  usage(phelp < argc-1 ? argv[phelp+1] : 0);
627  return 0;
628  }
629 
630  int user_argc = 0;
631  char **user_argv = nullptr;
632 
633  int userargspos = FindArg(argc, argv, "-args");
634  if (userargspos<0) userargspos = FindArg(argc, argv, "-x");
635  if (userargspos>0) {
636  user_argc = argc - userargspos;
637  user_argv = argv + userargspos;
638  // hide user-defined arguments
639  argc = userargspos;
640  }
641 
642  bool doprint = (FindArg(argc, argv, "-print") > 0) || (FindArg(argc, argv, "-type") > 0) ||
643  (FindArg(argc, argv, "-pr") > 0) || (FindArg(argc, argv, "-ty") > 0);
644  if (doprint) TGo4Log::SetIgnoreLevel(2);
645 
646  const char *logfile = GetArgValue(argc, argv, "-log", 0, true);
647  if (logfile) {
649 
650  TGo4Log::LogfileEnable(kTRUE);
651  if (strlen(logfile) == 0) logfile = TGo4Log::GetDefaultLogname();
652  TGo4Log::OpenLogfile(logfile, 0, kTRUE);
653 
654  TString info = "go4analysis";
655  for (int n = 1; n < argc; n++) { info += " "; info += argv[n]; }
656 
657  TGo4Log::WriteLogfile(info.Data(), true);
658  }
659 
660  if ((FindArg(argc, argv, "-v") > 0) || (FindArg(argc, argv, "-verbose") > 0))
662  else if (FindArg(argc, argv, "-v0") > 0)
664  else if (FindArg(argc, argv, "-v1") > 0)
666  else if (FindArg(argc, argv, "-v2") > 0)
668  else if (FindArg(argc, argv, "-v3") > 0)
670 
672  if (FindArg(argc, argv, "-gui") > 0)
674  else if (FindArg(argc, argv, "-server") > 0)
676 
677  // disable cint locking when called via process line
678  // makes problem in multi-threaded environment, where CINT lock
679  // also used for object streaming
680  gInterpreter->SetProcessLineLock(kFALSE);
681 
682  // add main go4 include path for the case if scripts are called from inside analysis, required for ROOT6
683  TString go4inc = TGo4Log::GO4INCPATH();
684  if (go4inc.IsNull())
685  go4inc = TGo4Log::subGO4SYS("include");
686  if (go4inc.Length() > 0)
687  gInterpreter->AddIncludePath(go4inc.Data());
688 
689  const char *extra_incl = gSystem->Getenv("GO4EXTRAINCLUDE");
690  if (extra_incl && *extra_incl)
691  gInterpreter->AddIncludePath(extra_incl);
692 
693  const char *analysis_name = GetArgValue(argc, argv, "-server");
694  if (!analysis_name) analysis_name = GetArgValue(argc, argv, "-gui");
695  if (!analysis_name) analysis_name = GetArgValue(argc, argv, "-name");
696  if (!analysis_name) analysis_name = "Go4Analysis";
697 
698  TList *lst0 = GetClassesList();
699 
700  int argpos = 0;
701  bool isanylib = false;
702  const char *libname = nullptr;
703  while ((libname = GetArgValue(argc, argv, "-lib", &argpos)) != nullptr) {
704  TGo4Log::Info("Reading library: %s", libname);
705  if (gSystem->Load(libname)<0) return -1;
706  isanylib = true;
707  }
708 
709  // we should try to load library if for printing -user argument specified - means user input
710  if (!isanylib && (!doprint || GetArgValue(argc, argv, "-user"))) {
711  libname = "libGo4UserAnalysis";
712  TGo4Log::Info("Reading library: %s", libname);
713  if (gSystem->Load(libname)<0) return -1;
714  }
715 
716  TList *lst1 = GetClassesList(lst0);
717 
718  TGo4Analysis *analysis = nullptr;
719 
720  UserCreateFunc* crfunc = (UserCreateFunc*) gSystem->DynFindSymbol("*", "CreateUserAnalysis");
721  if (crfunc) analysis = crfunc(analysis_name);
722  else analysis = CreateDefaultAnalysis(lst1, analysis_name, user_argc, user_argv, doprint);
723 
724  if (!analysis) {
725  std::cerr << "!!! Analysis instance cannot be created" << std::endl;
726  std::cerr << "!!! PLEASE check your analysis library " << libname << std::endl;
727  std::cerr << "!!! One requires user subclass for TGo4Analysis class in user library" << std::endl;
728  std::cerr << "!!! Alternatively, CreateUserAnalysis(const char *) function can be implemented" << std::endl;
729  std::cerr << "!!! See Go4ExampleSimple, Go4Example1Step or Go4Example2Step for details" << std::endl;
730  return -1;
731  }
732 
733  delete lst0; lst0 = nullptr;
734  delete lst1; lst1 = nullptr;
735 
736  TGo4AnalysisStep *step = analysis->GetAnalysisStep(nullptr);
737  if (!step) {
738  std::cerr << "No active step in analysis found" << std::endl;
739  return -1;
740  }
741 
742  int app_argc = 1;
743  // char *app_argv[] = { argv[0], (char *) "-l" };
744  // TApplication theApp("Go4App", &app_argc, argv);
745 
746  gROOT->SetBatch(kTRUE);
747 
748  TObjArray http_args; // all arguments for http server
749  http_args.SetOwner(kTRUE);
750  TString auth_file; // authentication file for http server
751  const char *auth_domain = "go4"; // default authentication domain http server
752  (void) auth_domain; // prevent compiler warning
753 
754  Bool_t batchMode = kTRUE; // GUI or Batch
755  Bool_t servermode = kFALSE; // run analysis as server task
756  Bool_t httpmode = kFALSE; // run analysis with web server
757  Bool_t hserver = kFALSE; // enable histogram server
758  Bool_t loadprefs = kTRUE; // loading preferences by client
759  Bool_t showrate = kFALSE; // display event rate
760  Double_t process_interv = -1.; // interval how often system events will be processed by analysis
761  const char *hname = ""; // namebase for histogram server
762  const char *hpasswd = ""; // password for histogram server
763  const char *hostname = "localhost"; // gui host name
764  Int_t iport = 5000; // port number used by GUI
765 
766  bool autorun = false; // immediately run analysis on start
767  long maxevents = -1; // number of events (batch mode)
768  Int_t canrun = 0; // -1 cannot run, 0 - only if source specified, 1 - always
769 
770  if (doprint) {
771  maxevents = 1;
772  analysis->SetAutoSave(kFALSE);
773  }
774 
775  //------ process arguments -------------------------
776 
777  int narg = 1;
778 
779  while (narg < argc) {
780  if (strcmp(argv[narg], "-server") == 0) {
781  narg++;
782  batchMode = kFALSE;
783  servermode = kTRUE;
784  // skip name, if specified
785  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-')) narg++;
786  } else
787  if(strcmp(argv[narg], "-gui") == 0) {
788  batchMode = kFALSE;
789  if (argc <= narg + 3) showerror("Not all -gui arguments specified");
790  narg++; // -gui
791  narg++; // name
792  hostname = argv[narg++];
793  iport = atoi(argv[narg++]); // port of GUI server
794  } else
795 #ifdef WITH_HTTP
796  if (strcmp(argv[narg], "-http") == 0) {
797  narg++;
798  httpmode = kTRUE;
799  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
800  http_args.Add(new TObjString(TString::Format("http:%s?top=Go4", argv[narg++])));
801  else
802  http_args.Add(new TObjString("http:8080?top=Go4"));
803  } else
804  if (strcmp(argv[narg], "-fastcgi") == 0) {
805  narg++;
806  httpmode = kTRUE;
807  if (narg >= argc) showerror("fastcgi options not specified");
808  http_args.Add(new TObjString(TString::Format("fastcgi:%s?top=Go4", argv[narg++])));
809  } else
810  if (strcmp(argv[narg], "-jsroot") == 0) {
811  narg++;
812  if (narg >= argc) showerror("jsroot location not specified");
813  http_args.Add(new TObjString(TString::Format("jsroot:%s", argv[narg++])));
814  } else
815  if (strcmp(argv[narg], "-auth") == 0) {
816  narg++;
817  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
818  auth_file = argv[narg++];
819  else
820  auth_file = TGo4Log::subGO4SYS("etc/htdigest.txt");
821  } else
822  if (strcmp(argv[narg], "-domain") == 0) {
823  narg++;
824  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
825  auth_domain = argv[narg++];
826  else
827  auth_domain = "go4";
828  } else
829 #ifdef WITH_DABC
830  if (strcmp(argv[narg], "-dabc") == 0) {
831  narg++;
832  if (narg >= argc) showerror("Master dabc node not specified");
833  const char *hostname = gSystem->HostName();
834  if (!hostname || (*hostname == 0)) hostname = "localhost";
835  http_args.Add(new TObjString(TString::Format("dabc:%s?top=Go4/%s_pid%d", argv[narg++],hostname,gSystem->GetPid())));
836  } else
837 #endif
838 #endif
839  if(strcmp(argv[narg], "-lib") == 0) {
840  // skip library name
841  if (++narg >= argc) showerror("library name not specified");
842  narg++;
843  } else
844  if(strcmp(argv[narg], "-name") == 0) {
845  // skip analysis name
846  if (++narg >= argc) showerror("analysis name not specified");
847  narg++;
848  } else
849  if (strcmp(argv[narg],"-step") == 0) {
850  if (++narg < argc) {
851  const char *step_name = argv[narg++];
852  int step_number = -1;
853  step = nullptr;
854  if (sscanf(step_name, "%d", &step_number) == 1)
855  if (step_number >= 0) step = analysis->GetAnalysisStepNum(step_number);
856  if (!step) step = analysis->GetAnalysisStep(step_name);
857  if (!step) showerror("step not found");
858  } else
859  showerror("step name not specified");
860  } else
861  if(strcmp(argv[narg],"-enable-step") == 0) {
862  narg++;
863  step->SetProcessEnabled(kTRUE);
864  } else
865  if(strcmp(argv[narg],"-disable-step") == 0) {
866  narg++;
867  step->SetProcessEnabled(kFALSE);
868  } else
869  if ((strcmp(argv[narg],"-file") == 0) || (strcmp(argv[narg],"-f") == 0)) {
870  if (++narg < argc) {
871  TGo4MbsFileParameter sourcepar(argv[narg++]);
872  // this is case when many files are specified at once
873  while ((narg<argc) && (argv[narg][0]!='-'))
874  sourcepar.AddMoreFile(argv[narg++]);
875  step->SetEventSource(&sourcepar);
876  step->SetSourceEnabled(kTRUE);
877  autorun = true;
878  } else
879  showerror("LMD/LML file name not specified");
880  } else
881  if (strcmp(argv[narg],"-source") == 0) {
882  if (++narg < argc) {
883  TGo4FileSourceParameter sourcepar(argv[narg++]);
884  step->SetEventSource(&sourcepar);
885  step->SetSourceEnabled(kTRUE);
886  autorun = true;
887  } else
888  showerror("Input file name not specified");
889  } else
890  if ((strcmp(argv[narg],"-transport") == 0) || (strcmp(argv[narg],"-tr") == 0)) {
891  if (++narg < argc) {
892  TGo4MbsTransportParameter sourcepar(argv[narg++]);
893  step->SetEventSource(&sourcepar);
894  step->SetSourceEnabled(kTRUE);
895  autorun = true;
896  } else
897  showerror("MBS Transport server name not specified");
898  } else
899  if ((strcmp(argv[narg],"-stream") == 0) || (strcmp(argv[narg],"-st") == 0)) {
900  if (++narg < argc) {
901  TGo4MbsStreamParameter sourcepar(argv[narg++]);
902  step->SetEventSource(&sourcepar);
903  step->SetSourceEnabled(kTRUE);
904  autorun = true;
905  } else
906  showerror("MBS Stream server name not specified");
907  } else
908  if ((strcmp(argv[narg],"-evserv") == 0) || (strcmp(argv[narg],"-ev") == 0)) {
909  if (++narg < argc) {
910  TGo4MbsEventServerParameter sourcepar(argv[narg++]);
911  step->SetEventSource(&sourcepar);
912  step->SetSourceEnabled(kTRUE);
913  autorun = true;
914  } else
915  showerror("MBS Event server name not specified");
916  } else
917  if ((strcmp(argv[narg],"-random") == 0) || (strcmp(argv[narg],"-rnd") == 0)) {
918  narg++;
919  TGo4MbsRandomParameter sourcepar("Random");
920  step->SetEventSource(&sourcepar);
921  step->SetSourceEnabled(kTRUE);
922  autorun = true;
923  } else
924  if (strcmp(argv[narg],"-user") == 0) {
925  if (++narg < argc) {
926  TGo4UserSourceParameter sourcepar(argv[narg++]);
927  step->SetEventSource(&sourcepar);
928  step->SetSourceEnabled(kTRUE);
929  autorun = true;
930  } else
931  showerror("User source name not specified");
932  }
933 #ifdef __GO4HDF5__
934  else
935  if (strcmp(argv[narg],"-hdf5") == 0) {
936  if (++narg < argc) {
937  TGo4HDF5SourceParameter sourcepar(argv[narg++]);
938  step->SetEventSource(&sourcepar);
939  step->SetSourceEnabled(kTRUE);
940  autorun = true;
941  } else
942  showerror("HDF5 file name not specified");
943  }
944 #endif
945 
946  else
947  if ((strcmp(argv[narg],"-revserv") == 0) || (strcmp(argv[narg],"-rev") == 0)) {
948  if (++narg < argc) {
949  const char *serv_name = argv[narg++];
950  int serv_port = 0;
951  if ((narg < argc) && (argv[narg][0] != '-'))
952  serv_port = atoi(argv[narg++]);
953  TGo4RevServParameter sourcepar(serv_name, serv_port);
954  step->SetEventSource(&sourcepar);
955  step->SetSourceEnabled(kTRUE);
956  autorun = true;
957  } else
958  showerror("Remote event server name or port are not specified");
959  } else
960  if (strcmp(argv[narg],"-skip") == 0) {
961  narg++;
962  TGo4MbsSourceParameter* param = dynamic_cast<TGo4MbsSourceParameter*> (step->GetEventSource());
963  if (!param) showerror("only in MBS source events can be skipped");
964  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-')) {
965  unsigned value = 0;
966  if (sscanf(argv[narg],"%u",&value)!=1)
967  showerror(TString::Format("Value error %s", argv[narg]));
968  param->SetStartEvent(value);
969  narg++;
970  }
971  } else
972  if (strcmp(argv[narg],"-port") == 0) {
973  narg++;
974  int port = 0;
975  if ((narg < argc) && (argv[narg][0] != '-')) {
976  if (sscanf(argv[narg],"%d",&port)!=1)
977  showerror(TString::Format("Value error %s", argv[narg]));
978  narg++;
979  }
980  TGo4MbsSourceParameter* param = dynamic_cast<TGo4MbsSourceParameter*> (step->GetEventSource());
981  if (param) param->SetPort(port);
982 
983  TGo4UserSourceParameter* user = dynamic_cast<TGo4UserSourceParameter*> (step->GetEventSource());
984  if (user) user->SetPort(port);
985  } else
986  if (strcmp(argv[narg],"-retry") == 0) {
987  narg++;
988  int nretry = 0;
989  if ((narg < argc) && (argv[narg][0]!='-')) {
990  if (sscanf(argv[narg],"%d",&nretry)!=1)
991  showerror(TString::Format("Value error %s", argv[narg]));
992  narg++;
993  }
994  TGo4MbsSourceParameter* param = dynamic_cast<TGo4MbsSourceParameter*> (step->GetEventSource());
995  if (param) param->SetRetryCnt(nretry);
996  } else
997  if (strcmp(argv[narg],"-mbs-select") == 0) {
998  narg++;
999  TGo4MbsSourceParameter* param = dynamic_cast<TGo4MbsSourceParameter*> (step->GetEventSource());
1000  if (!param) showerror("only in MBS source events can be selected");
1001  unsigned cnt = 0;
1002  while ((cnt < 3) && (narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0] != '-')) {
1003  unsigned value = 0;
1004  if ((cnt==1) && (strcmp(argv[narg],"all") == 0)) value = 0; else
1005  if (sscanf(argv[narg],"%u",&value)!=1)
1006  showerror(TString::Format("Value error %s", argv[narg]));
1007  if (cnt == 0) param->SetStartEvent(value); else
1008  if (cnt==1) param->SetStopEvent(value); else
1009  if (cnt==2) param->SetEventInterval(value);
1010  narg++; cnt++;
1011  }
1012  } else
1013  if(strcmp(argv[narg],"-store") == 0) {
1014  if (++narg >= argc) showerror("Store name not specified");
1015 
1016  const char *sourcename = argv[narg++];
1017  int splitlevel = 1;
1018  int buffersize = 64000;
1019  int compression = 5;
1020 
1021  unsigned cnt = 0;
1022  while ((cnt < 3) && (narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0] != '-')) {
1023  int value = 0;
1024  if (sscanf(argv[narg],"%d",&value)!=1)
1025  showerror(TString::Format("Value error %s", argv[narg]));
1026  if (cnt == 0) splitlevel = value; else
1027  if (cnt==1) buffersize = value; else
1028  if (cnt==2) compression = value;
1029  narg++; cnt++;
1030  }
1031 
1032  TGo4FileStoreParameter storepar(sourcename, splitlevel, buffersize, compression);
1033  step->SetEventStore(&storepar);
1034  step->SetStoreEnabled(kTRUE);
1035  } else
1036  if (strcmp(argv[narg], "-timeout") == 0) {
1037  if (++narg >= argc) showerror("Timeout value not specified");
1038  if (!step->GetEventSource()) showerror("No source parameter configured");
1039  int value = 0;
1040  if (sscanf(argv[narg],"%d",&value)!=1)
1041  showerror(TString::Format("Timeout value error %s", argv[narg]));
1042  narg++;
1043  step->GetEventSource()->SetTimeout(value);
1044  } else
1045  if (strcmp(argv[narg],"-overwrite-store") == 0) {
1046  narg++;
1047  TGo4FileStoreParameter* par = dynamic_cast<TGo4FileStoreParameter*> (step->GetEventStore());
1048  if (par) par->SetOverwriteMode(kTRUE);
1049  else showerror("No file-store parameter available");
1050  } else
1051  if (strcmp(argv[narg],"-append-store") == 0) {
1052  narg++;
1053  TGo4FileStoreParameter* par = dynamic_cast<TGo4FileStoreParameter*> (step->GetEventStore());
1054  if (par) par->SetOverwriteMode(kFALSE);
1055  else showerror("No file-store parameter available");
1056  } else
1057  if(strcmp(argv[narg],"-backstore") == 0) {
1058  if (++narg < argc) {
1059  TGo4BackStoreParameter storepar(argv[narg++]);
1060  step->SetEventStore(&storepar);
1061  step->SetStoreEnabled(kTRUE);
1062  } else
1063  showerror("Backstore name not specified");
1064  } else
1065  if(strcmp(argv[narg],"-userstore") == 0) {
1066  if (++narg < argc) {
1067  TGo4UserStoreParameter storepar(argv[narg++]);
1068  step->SetEventStore(&storepar);
1069  step->SetStoreEnabled(kTRUE);
1070  } else
1071  showerror("User store name not specified");
1072  } else
1073 #ifdef __GO4HDF5__
1074  if(strcmp(argv[narg],"-hdf5store") == 0) {
1075  if (++narg < argc) {
1076  TGo4HDF5StoreParameter storepar(argv[narg++]);
1077  step->SetEventStore(&storepar);
1078  step->SetStoreEnabled(kTRUE);
1079  } else
1080  showerror("HDF5 store name not specified");
1081  } else
1082 #endif
1083  if ((strcmp(argv[narg],"-events") == 0) || (strcmp(argv[narg],"-number") == 0) || (strcmp(argv[narg],"-num") == 0)) {
1084  if (++narg < argc) {
1085  if (sscanf(argv[narg++],"%ld",&maxevents)!=1) maxevents = -1;
1086  } else
1087  showerror("number of events to process not specified");
1088  } else
1089  if (strcmp(argv[narg],"-asf") == 0) {
1090  narg++;
1091  analysis->SetAutoSave(kTRUE);
1092  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
1093  analysis->SetAutoSaveFile(argv[narg++]);
1094  } else
1095  if (strcmp(argv[narg],"-enable-asf") == 0) {
1096  narg++;
1097  analysis->SetAutoSave(kTRUE);
1098  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
1099  analysis->SetAutoSaveInterval(atoi(argv[narg++]));
1100  } else
1101  if (strcmp(argv[narg],"-disable-asf") == 0) {
1102  narg++;
1103  analysis->SetAutoSave(kFALSE);
1104  } else
1105  if (strcmp(argv[narg],"-prefs") == 0) {
1106  narg++;
1107  const char *fname = nullptr;
1108  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
1109  fname = argv[narg++];
1110  analysis->LoadStatus(fname);
1111  loadprefs = kFALSE;
1112  } else
1113  if (strcmp(argv[narg],"-no-prefs") == 0) {
1114  narg++;
1115  loadprefs = kFALSE;
1116  } else
1117  if(strcmp(argv[narg],"-log") == 0) {
1118  narg++;
1119  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-')) narg++;
1120  } else
1121  if(strcmp(argv[narg],"-gdebug") == 0) {
1122  narg++;
1123  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
1124  gDebug = TString(argv[narg++]).Atoi();
1125  else
1126  gDebug = 1;
1127  } else
1128  if((strcmp(argv[narg],"-v") == 0) || (strcmp(argv[narg],"-v0") == 0) || (strcmp(argv[narg],"-v1") == 0) || (strcmp(argv[narg],"-v2") == 0) || (strcmp(argv[narg],"-v3") == 0)) {
1129  narg++;
1130  } else
1131  if((strcmp(argv[narg],"-graphics") == 0) || (strcmp(argv[narg],"-gr") == 0)) {
1132  narg++;
1133  gROOT->SetBatch(kFALSE);
1134  process_interv = 0.1; // allow system events processing
1135  new TApplication("Go4App", &app_argc, argv);
1136  TStyle::BuildStyles();
1137  gROOT->SetStyle();
1138  } else
1139  if(strcmp(argv[narg],"-run") == 0) {
1140  narg++;
1141  autorun = true;
1142  } else
1143  if(strcmp(argv[narg],"-norun") == 0) {
1144  narg++;
1145  canrun = -1;
1146  } else
1147  if(strcmp(argv[narg],"-maxtreesize") == 0) {
1148  narg++;
1149  long long maxtreesize = 1900000000;
1150  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-')) {
1151  char sbuf[1000];
1152  strncpy(sbuf, argv[narg], sizeof(sbuf)-1);
1153  long long mult = 1, val = 1;
1154  int len = strlen(sbuf);
1155  if ((sbuf[len-1]=='g') || (sbuf[len-1]=='G')) { mult = 1000000000; sbuf[len-1] = 0; } else
1156  if ((sbuf[len-1]=='m') || (sbuf[len-1]=='M')) { mult = 1000000; sbuf[len-1] = 0; } else
1157  if ((sbuf[len-1]=='k') || (sbuf[len-1]=='K')) { mult = 1000; sbuf[len-1] = 0; }
1158  if (sscanf(sbuf, "%lld", &val)==1) maxtreesize = val*mult;
1159  narg++;
1160  }
1161  TGo4Log::Info("Set tree file size limit to %lld bytes", maxtreesize);
1162  TGo4FileStore::SetMaxTreeSize(maxtreesize);
1163  } else
1164  if ((strcmp(argv[narg],"-print") == 0) || (strcmp(argv[narg],"-type") == 0) || (strcmp(argv[narg],"-ty") == 0) || (strcmp(argv[narg],"-pr") == 0)) {
1165  narg++;
1166  while ((narg<argc) && (argv[narg][0]!='-')) {
1167  if (strncmp(argv[narg],"sub=",4) == 0) {
1168  TGo4PrintProcessor::fSubId = atoi(argv[narg] + 4);
1169  } else
1170  if (strcmp(argv[narg],"hex") == 0) {
1171  TGo4PrintProcessor::fHex = kTRUE;
1172  TGo4PrintProcessor::fData = kTRUE;
1173  } else
1174  if (strcmp(argv[narg],"dec") == 0) {
1175  TGo4PrintProcessor::fHex = kFALSE;
1176  TGo4PrintProcessor::fData = kTRUE;
1177  } else
1178  if (strcmp(argv[narg],"long") == 0) {
1179  TGo4PrintProcessor::fLong = kTRUE;
1180  TGo4PrintProcessor::fData = kTRUE;
1181  } else
1182  if (strcmp(argv[narg],"short") == 0) {
1183  TGo4PrintProcessor::fLong = kFALSE;
1184  TGo4PrintProcessor::fData = kTRUE;
1185  } else
1186  if (strcmp(argv[narg],"data") == 0) {
1187  TGo4PrintProcessor::fData = kTRUE;
1188  } else
1189  if (strcmp(argv[narg],"nodata") == 0) {
1190  TGo4PrintProcessor::fData = kFALSE;
1191  } else
1192  if (strcmp(argv[narg],"fhead") == 0) {
1194  } else
1195  if (strcmp(argv[narg],"bhead") == 0) {
1197  }
1198  narg++;
1199  }
1200  } else
1201  if(strcmp(argv[narg],"-enable-store") == 0) {
1202  narg++;
1203  step->SetStoreEnabled(kTRUE);
1204  } else
1205  if(strcmp(argv[narg],"-disable-store") == 0) {
1206  narg++;
1207  step->SetStoreEnabled(kFALSE);
1208  } else
1209  if(strcmp(argv[narg],"-enable-source") == 0) {
1210  narg++;
1211  step->SetSourceEnabled(kTRUE);
1212  } else
1213  if(strcmp(argv[narg],"-disable-source") == 0) {
1214  narg++;
1215  step->SetSourceEnabled(kFALSE);
1216  } else
1217  if(strcmp(argv[narg],"-disable-errstop") == 0) {
1218  narg++;
1219  step->SetErrorStopEnabled(kFALSE);
1220  } else
1221  if(strcmp(argv[narg],"-enable-errstop") == 0) {
1222  narg++;
1223  step->SetErrorStopEnabled(kTRUE);
1224  } else
1225  if(strcmp(argv[narg],"-rate") == 0) {
1226  narg++;
1227  showrate = kTRUE;
1228  } else
1229  if(strcmp(argv[narg],"-norate") == 0) {
1230  narg++;
1231  showrate = kFALSE;
1232  } else
1233  if(strcmp(argv[narg],"-inpevt-class") == 0) {
1234  // these arguments used only in simple analysis with single step and
1235  // processed when analysis created
1236  narg++;
1237  if (narg < argc) narg++;
1238  } else
1239  if(strcmp(argv[narg],"-outevt-class") == 0) {
1240  // these arguments used only in simple analysis with single step and
1241  // processed when analysis created
1242  narg++;
1243  if (narg < argc) narg++;
1244  } else
1245  if(strcmp(argv[narg],"-hserver") == 0) {
1246  narg++;
1247  hserver = true;
1248  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
1249  hname = argv[narg++];
1250  if ((narg < argc) && (strlen(argv[narg]) > 0) && (argv[narg][0]!='-'))
1251  hpasswd = argv[narg++];
1252  } else
1253  showerror(TString::Format("Unknown argument %d %s", narg, argv[narg]));
1254  }
1255 
1256  #ifdef WITH_HTTP
1257  if (http_args.GetLast() >= 0) {
1258  if (gSystem->Load("libGo4Http") != 0)
1259  showerror("Fail to load libGo4Http.so library");
1260 
1261  TGo4Log::EnableRedirection(); // one sniff complete std out
1262 
1263  TGo4MbsSource::SetPollingMode(kTRUE); // allow to process http requests when no events are coming
1264 
1265  TString cmd;
1266  for (Int_t n = 0; n <= http_args.GetLast(); n++) {
1267  TString engine = http_args[n]->GetName();
1268  if ((engine.Index("http:") == 0) && (auth_file.Length() > 0))
1269  engine.Append(TString::Format("&auth_file=%s&auth_domain=%s", auth_file.Data(), auth_domain));
1270 
1271  cmd.Form("TGo4Sniffer::CreateEngine(\"%s\");", engine.Data());
1272  Int_t err = 0;
1273  auto res = gROOT->ProcessLineFast(cmd.Data(), &err);
1274  if ((res <= 0) || (err != 0)) {
1275  printf("Fail to start %s", engine.Data());
1276  return 1;
1277  }
1278  }
1279 
1280  process_interv = 0.1;
1281  }
1282  #endif
1283 
1284  //------ start the analysis -------------------------
1285  if(batchMode) {
1286  TGo4Log::Info("Main: starting analysis in batch mode ... ");
1287 
1288  Bool_t enter_loop = kTRUE;
1289  if ((canrun >= 0) || autorun) {
1290  // initialize event classes also with -norun option if any source was specified
1291  if (!analysis->InitEventClasses()) {
1292  TGo4Log::Error("Main: Init event classes failed, aborting!");
1293  enter_loop = kFALSE;
1294  } else {
1295  if (canrun >= 0) analysis->StartAnalysis();
1296  }
1297  }
1298 
1299  if (enter_loop) {
1300  analysis->RunImplicitLoop(maxevents, showrate, process_interv, httpmode);
1301  delete analysis;
1302  TGo4Log::Info("Main: analysis batch done");
1303  }
1304  } else {
1305  if (!hostname) hostname = "localhost";
1306 
1307  if(servermode) TGo4Log::Info("Main: starting analysis in server mode ...");
1308  else TGo4Log::Info("Main: starting analysis in slave mode ...");
1309 
1310  if (canrun < 0) autorun = false;
1311 
1312  TGo4AnalysisClient *client = new TGo4AnalysisClient("UserClient", analysis, hostname, iport, hserver, hname, hpasswd, servermode, autorun, kFALSE, loadprefs, showrate);
1313 
1314  TGo4Log::Info("Main: created AnalysisClient instance: %s", client->GetName());
1315  TGo4Log::Info("Main: Run application loop");
1316 
1317  int termcounter = 0;
1318 
1319  while (TGo4Analysis::Exists()) {
1320  // add this check while at some moments ROOT could reset this pointer
1321  if (!gSystem) {
1322  // printf("ROOT feature - gSystem == 0, break execution\n");
1323 
1324  // exit call exit handler and produces even more problems
1325  // we trying to close application as soon as possible - anyway many
1326  // items already cleaned up
1327  abort();
1328  //exit(5);
1329  }
1330 
1331  gSystem->ProcessEvents();
1332  gSystem->Sleep(PROCESSLOOPDELAY);
1333  if(client->IsBeingQuit()) {
1334  if(termcounter == 0) {
1335  termcounter = TERMCOUNTS;
1336  TGo4Log::Info("Found Quit state: starting termination counter with %d s", PROCESSLOOPDELAY * TERMCOUNTS / 1000);
1337  } else
1338  if (termcounter>0) {
1339  termcounter--;
1340  if (termcounter == 0) {
1341  TGo4Log::Info("Reached end of termination counter after %d s, terminating.", PROCESSLOOPDELAY * TERMCOUNTS / 1000);
1342  break;
1343  }
1344  if ((termcounter % (10000 / PROCESSLOOPDELAY)) == 0)
1345  TGo4Log::Info("Counting termination counter down, remains %d s", PROCESSLOOPDELAY * termcounter / 1000);
1346  }
1347  }
1348  }
1349 
1350  }
1351 
1352  TGo4Log::Info("Main: THE END");
1354 
1355  return 0;
1356 }
const char * GetName() const
void SetStartEvent(UInt_t firstindex)
static TGo4Log * Instance()
Definition: TGo4Log.cxx:85
TGo4EventStoreParameter * GetEventStore() const
void SetStopEvent(UInt_t lastindex)
void printsources()
static Bool_t CheckVersion(Int_t version)
Definition: TGo4Version.cxx:42
static void Info(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:294
static void SetMaxTreeSize(Long64_t sz)
virtual Bool_t CheckEventClass(TClass *cl)
void DefUserEventSource(const char *Sclass)
void SetEventStore(TGo4EventStoreParameter *kind)
static void WriteLogfile(const char *text, Bool_t withtime=kTRUE)
Definition: TGo4Log.cxx:420
#define TERMCOUNTS
void DefEventProcessor(const char *Pname, const char *Pclass)
static void CloseLogfile()
Definition: TGo4Log.cxx:444
void SetAutoSaveFile(const char *filename=nullptr, Bool_t overwrite=kFALSE, Int_t compression=5)
static void OpenLogfile(const char *name=nullptr, const char *headercomment=nullptr, Bool_t appendmode=kFALSE)
Definition: TGo4Log.cxx:383
static const char * GetDefaultLogname()
Definition: TGo4Log.cxx:348
static void SetIgnoreLevel(Int_t level)
Definition: TGo4Log.cxx:332
TGo4PrintFactory(const char *name)
TGo4EventProcessor * CreateEventProcessor(TGo4EventProcessorParameter *par)
virtual void PrintEvent()
TGo4Analysis *() UserCreateFunc(const char *name)
int main(int argc, char **argv)
TGo4AnalysisStep * GetAnalysisStep(const char *name)
void SetSourceEnabled(Bool_t on=kTRUE)
TList * GetClassesList(TList *prev=nullptr)
static void Debug(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:281
void SetOverwriteMode(Bool_t over=kTRUE)
#define __GO4RELEASE__
Definition: TGo4Version.h:25
Int_t RunImplicitLoop(Int_t times, Bool_t showrate=kFALSE, Double_t process_event_interval=-1., Bool_t iswebserver=kFALSE)
static const char * GO4INCPATH()
Definition: TGo4Log.cxx:179
void SetAutoSave(Bool_t on=kTRUE)
static void EnableRedirection()
Definition: TGo4Log.cxx:93
static void SetPollingMode(Bool_t on=kTRUE)
#define PROCESSLOOPDELAY
int FindArg(int argc, char **argv, const char *argname)
void DefOutputEvent(const char *Oname, const char *Oclass)
void SetEventInterval(UInt_t skipinterval)
#define __GO4BUILDVERSION__
Definition: TGo4Version.h:24
void PrintMbsEvent(Int_t subid=-1, Bool_t longw=kTRUE, Bool_t hexw=kTRUE, Bool_t dataw=kTRUE, Bool_t bufhead=kFALSE, Bool_t filhead=kFALSE)
void SetStoreEnabled(Bool_t on=kTRUE)
void AddMoreFile(const char *more)
static void Error(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:320
TGo4EventElement * GetInputEvent()
virtual Bool_t InitEventClasses()
void showerror(const TString &msg)
void SetProcessEnabled(Bool_t on=kTRUE)
void SetEventSource(TGo4EventSourceParameter *kind)
TGo4AnalysisStep * GetAnalysisStepNum(Int_t number)
TGo4EventSourceParameter * GetEventSource() const
static TString subGO4SYS(const char *subdir)
Definition: TGo4Log.cxx:189
void DefUserEventStore(const char *Sclass)
void SetErrorStopEnabled(Bool_t on)
TGo4PrintProcessor(const char *name)
const char * GetArgValue(int argc, char **argv, const char *argname, int *pos=nullptr, bool incomplete=false)
Bool_t BuildEvent(TGo4EventElement *dest) override
static Bool_t Exists()
void DefInputEvent(const char *Iname, const char *Iclass)
Bool_t LoadStatus(const char *filename=nullptr)
static void SetRunningMode(int mode)
static TGo4Analysis * Instance()
Bool_t IsBeingQuit()
TGo4Analysis * CreateDefaultAnalysis(TList *lst, const char *name, int user_argc, char **user_argv, bool doprint)
void SetAutoSaveInterval(Int_t interval=0)
void usage(const char *subtopic=nullptr)
string msg
Definition: go4init.py:11
static void LogfileEnable(Bool_t on=kTRUE)
Definition: TGo4Log.cxx:363