GetFileSources returns empty list in case of no files, but successful query
[u/mrichter/AliRoot.git] / SHUTTLE / AliShuttleConfig.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /*
17 $Log$
18 Revision 1.20  2007/04/04 10:33:36  jgrosseo
19 1) Storing of files to the Grid is now done _after_ your preprocessors succeeded. This is transparent, which means that you can still use the same functions (Store, StoreReferenceData) to store files to the Grid. However, the Shuttle first stores them locally and transfers them after the preprocessor finished. The return code of these two functions has changed from UInt_t to Bool_t which gives you the success of the storing.
20 In case of an error with the Grid, the Shuttle will retry the storing later, the preprocessor does not need to be run again.
21
22 2) The meaning of the return code of the preprocessor has changed. 0 is now success and any other value means failure. This value is stored in the log and you can use it to keep details about the error condition.
23
24 3) New function StoreReferenceFile to _directly_ store a file (without opening it) to the reference storage.
25
26 4) The memory usage of the preprocessor is monitored. If it exceeds 2 GB it is terminated.
27
28 5) New function AliPreprocessor::ProcessDCS(). If you do not need to have DCS data in all cases, you can skip the processing by implemting this function and returning kFALSE under certain conditions. E.g. if there is a certain run type.
29 If you always need DCS data (like before), you do not need to implement it.
30
31 6) The run type has been added to the monitoring page
32
33 Revision 1.19  2007/02/28 10:41:56  acolla
34 Run type field added in SHUTTLE framework. Run type is read from "run type" logbook and retrieved by
35 AliPreprocessor::GetRunType() function.
36 Added some ldap definition files.
37
38 Revision 1.18  2007/01/23 19:20:03  acolla
39 Removed old ldif files, added TOF, MCH ldif files. Added some options in
40 AliShuttleConfig::Print. Added in Ali Shuttle: SetShuttleTempDir and
41 SetShuttleLogDir
42
43 Revision 1.17  2007/01/18 11:17:47  jgrosseo
44 changing spaces to tabs ;-)
45
46 Revision 1.16  2007/01/18 11:10:35  jgrosseo
47 adding the possibility of defining DCS alias and data points with patterns
48 first pattern introduced: [N..M] to add all names between the two digits, this works also recursively.
49
50 Revision 1.15  2007/01/15 18:27:11  acolla
51 implementation of sending mail to subdetector expert in case the preprocessor fails.
52 shuttle.schema updated with expert's email entry
53
54 Revision 1.13  2006/12/07 08:51:26  jgrosseo
55 update (alberto):
56 table, db names in ldap configuration
57 added GRP preprocessor
58 DCS data can also be retrieved by data point
59
60 Revision 1.12  2006/11/16 16:16:48  jgrosseo
61 introducing strict run ordering flag
62 removed giving preprocessor name to preprocessor, they have to know their name themselves ;-)
63
64 Revision 1.11  2006/11/06 14:23:04  jgrosseo
65 major update (Alberto)
66 o) reading of run parameters from the logbook
67 o) online offline naming conversion
68 o) standalone DCSclient package
69
70 Revision 1.10  2006/10/20 15:22:59  jgrosseo
71 o) Adding time out to the execution of the preprocessors: The Shuttle forks and the parent process monitors the child
72 o) Merging Collect, CollectAll, CollectNew function
73 o) Removing implementation of empty copy constructors (declaration still there!)
74
75 Revision 1.9  2006/10/02 16:38:39  jgrosseo
76 update (alberto):
77 fixed memory leaks
78 storing of objects that failed to be stored to the grid before
79 interfacing of shuttle status table in daq system
80
81 Revision 1.8  2006/08/15 10:50:00  jgrosseo
82 effc++ corrections (alberto)
83
84 Revision 1.7  2006/07/20 09:54:40  jgrosseo
85 introducing status management: The processing per subdetector is divided into several steps,
86 after each step the status is stored on disk. If the system crashes in any of the steps the Shuttle
87 can keep track of the number of failures and skips further processing after a certain threshold is
88 exceeded. These thresholds can be configured in LDAP.
89
90 Revision 1.6  2006/07/19 10:09:55  jgrosseo
91 new configuration, accesst to DAQ FES (Alberto)
92
93 Revision 1.5  2006/07/10 13:01:41  jgrosseo
94 enhanced storing of last sucessfully processed run (alberto)
95
96 Revision 1.4  2006/06/12 09:11:16  jgrosseo
97 coding conventions (Alberto)
98
99 Revision 1.3  2006/06/06 14:26:40  jgrosseo
100 o) removed files that were moved to STEER
101 o) shuttle updated to follow the new interface (Alberto)
102
103 Revision 1.7  2006/05/12 09:07:16  colla
104 12/05/06
105 New configuration complete
106
107 Revision 1.2  2006/03/07 07:52:34  hristov
108 New version (B.Yordanov)
109
110 Revision 1.4  2005/11/19 14:20:31  byordano
111 logbook config added to AliShuttleConfig
112
113 Revision 1.3  2005/11/17 19:24:25  byordano
114 TList changed to TObjArray in AliShuttleConfig
115
116 Revision 1.2  2005/11/17 14:43:23  byordano
117 import to local CVS
118
119 Revision 1.1.1.1  2005/10/28 07:33:58  hristov
120 Initial import as subdirectory in AliRoot
121
122 Revision 1.1.1.1  2005/09/12 22:11:40  byordano
123 SHUTTLE package
124
125 Revision 1.3  2005/08/30 09:13:02  byordano
126 some docs added
127
128 */
129
130
131 //
132 // This class keeps the AliShuttle configuration.
133 // It reads the configuration for LDAP server.
134 // For every child entry in basedn which has schema type 'shuttleConfig'
135 // it creates a detector configuration. This configuration includes:
136 // DCS server host and port and the set of aliases for which data from
137 // will be retrieved (used by AliShuttle).
138 //
139
140
141 #include "AliShuttleConfig.h"
142 #include "AliShuttleInterface.h"
143
144 #include "AliLog.h"
145
146 #include <TSystem.h>
147 #include <TObjString.h>
148 #include <TLDAPResult.h>
149 #include <TLDAPEntry.h>
150 #include <TLDAPAttribute.h>
151
152
153 AliShuttleConfig::AliShuttleConfigHolder::AliShuttleConfigHolder(const TLDAPEntry* entry):
154 fDetector(""),
155 fDCSHost(""),
156 fDCSPort(0),
157 fDCSAliases(0),
158 fDCSDataPoints(0),
159 fDCSAliasesComp(0),
160 fDCSDataPointsComp(0),
161 fResponsibles(0),
162 fIsValid(kFALSE),
163 fSkipDCSQuery(kFALSE),
164 fStrictRunOrder(kFALSE)
165 {
166 // constructor of the shuttle configuration holder
167
168         TLDAPAttribute* anAttribute;
169         fDCSAliases = new TObjArray();
170         fDCSAliases->SetOwner(1);
171         fDCSDataPoints = new TObjArray();
172         fDCSDataPoints->SetOwner(1);
173         fDCSAliasesComp = new TObjArray();
174         fDCSAliasesComp->SetOwner(1);
175         fDCSDataPointsComp = new TObjArray();
176         fDCSDataPointsComp->SetOwner(1);
177         fResponsibles = new TObjArray();
178         fResponsibles->SetOwner(1);
179
180         anAttribute = entry->GetAttribute("det"); // MUST
181         if (!anAttribute)
182         {
183                 AliError(Form("Invalid configuration! No \"det\" attribute!"));
184                 return;
185         }
186         fDetector = anAttribute->GetValue();
187
188         anAttribute = entry->GetAttribute("StrictRunOrder"); // MAY
189         if (!anAttribute)
190         {
191                 AliWarning(Form("%s did not set StrictRunOrder flag - the default is FALSE",
192                                 fDetector.Data()));
193         } else {
194                 TString strictRunStr = anAttribute->GetValue();
195                 if (!(strictRunStr == "0" || strictRunStr == "1"))
196                 {
197                         AliError("Invalid configuration! StrictRunOrder flag must be 0 or 1!");
198                         return;
199                 }
200                 fStrictRunOrder = (Bool_t) strictRunStr.Atoi();
201         }
202
203         anAttribute = entry->GetAttribute("responsible"); // MAY
204         if (!anAttribute)
205         {
206                 AliDebug(2, "Warning! No \"responsible\" attribute!");
207         }
208         else
209         {
210                 const char* aResponsible;
211                 while ((aResponsible = anAttribute->GetValue()))
212                 {
213                         fResponsibles->AddLast(new TObjString(aResponsible));
214                 }
215         }
216         
217         anAttribute = entry->GetAttribute("DCSHost"); // MAY
218         if (!anAttribute)
219         {
220                 AliDebug(2,
221                         Form("%s has not DCS host entry - Shuttle will skip DCS data query!",
222                                 fDetector.Data()));
223                 fIsValid = kTRUE;
224                 fSkipDCSQuery = kTRUE;
225                 return;
226         }
227
228         fDCSHost = anAttribute->GetValue();
229
230         anAttribute = entry->GetAttribute("DCSPort"); // MAY
231         if (!anAttribute)
232         {
233                 AliError(Form("Invalid configuration! %s has DCS Host but no port number!",
234                                 fDetector.Data()));
235                 return;
236         }
237         TString portStr = anAttribute->GetValue();
238         fDCSPort = portStr.Atoi();
239
240         anAttribute = entry->GetAttribute("DCSalias"); // MAY
241         if (anAttribute)
242         {
243                 const char* anAlias;
244                 while ((anAlias = anAttribute->GetValue()))
245                 {
246                         fDCSAliasesComp->AddLast(new TObjString(anAlias));
247                         ExpandAndAdd(fDCSAliases, anAlias);
248                 }
249         }
250
251         anAttribute = entry->GetAttribute("DCSdatapoint"); // MAY
252         if (anAttribute)
253         {
254                 const char* aDataPoint;
255                 while ((aDataPoint = anAttribute->GetValue()))
256                 {
257                 fDCSDataPointsComp->AddLast(new TObjString(aDataPoint));
258                 ExpandAndAdd(fDCSDataPoints, aDataPoint);
259                 }
260         }
261
262         fIsValid = kTRUE;
263 }
264
265 //______________________________________________________________________________________________
266 void AliShuttleConfig::AliShuttleConfigHolder::ExpandAndAdd(TObjArray* target, const char* entry)
267 {
268         //
269         // adds <entry> to <target> applying expanding of the name
270         // [N..M] creates M-N+1 names with the corresponding digits
271         //
272
273         TString entryStr(entry);
274
275         Int_t begin = entryStr.Index("[");
276         Int_t end = entryStr.Index("]");
277         if (begin != -1 && end != -1 && end > begin)
278         {
279                 TString before(entryStr(0, begin));
280                 TString after(entryStr(end+1, entryStr.Length()));
281
282                 AliDebug(2, Form("Found [] pattern. Splitted input string %s %s", before.Data(), after.Data()));
283
284                 Int_t dotdot = entryStr.Index("..");
285
286                 TString nStr(entryStr(begin+1, dotdot-begin-1));
287                 TString mStr(entryStr(dotdot+2, end-dotdot-2));
288
289                 AliDebug(2, Form("Found [N..M] pattern. %s %s", nStr.Data(), mStr.Data()));
290
291                 if (nStr.IsDigit() && mStr.IsDigit())
292                 {
293                         Int_t n = nStr.Atoi();
294                         Int_t m = mStr.Atoi();
295
296                         Int_t nDigits = nStr.Length();
297                         TString formatStr;
298                         formatStr.Form("%%s%%0%dd%%s", nDigits);
299
300                         AliDebug(2, Form("Format string is %s", formatStr.Data()));
301
302                         for (Int_t current = n; current<=m; ++current)
303                         {
304                                 TString newEntry;
305                                 newEntry.Form(formatStr.Data(), before.Data(), current, after.Data());
306
307                                 AliDebug(2, Form("Calling recursive with %s", newEntry.Data()));
308
309                                 // and go recursive
310                                 ExpandAndAdd(target, newEntry);
311                         }
312
313                         // return here because we processed the entries already recursively.
314                         return;
315                 }
316         }
317
318         AliDebug(2, Form("Adding name %s", entry));
319         target->AddLast(new TObjString(entry));
320 }
321
322 //______________________________________________________________________________________________
323 AliShuttleConfig::AliShuttleConfigHolder::~AliShuttleConfigHolder()
324 {
325 // destructor of the shuttle configuration holder
326
327         delete fDCSAliases;
328         delete fDCSDataPoints;
329         delete fResponsibles;
330 }
331
332 ClassImp(AliShuttleConfig)
333
334 //______________________________________________________________________________________________
335 AliShuttleConfig::AliShuttleConfig(const char* host, Int_t port,
336         const char* binddn, const char* password, const char* basedn):
337         fIsValid(kFALSE), fConfigHost(host),
338         fDAQlbHost(""), fDAQlbPort(), fDAQlbUser(""), fDAQlbPass(""),
339         fDAQlbDB(""), fDAQlbTable(""), fShuttlelbTable(""), fRunTypelbTable(""),
340         fMaxRetries(0), fPPTimeOut(0), fPPMaxMem(0), fDetectorMap(), fDetectorList(),
341         fShuttleInstanceHost(""), fProcessedDetectors(), fProcessAll(kFALSE)
342 {
343         //
344         // host: ldap server host
345         // port: ldap server port
346         // binddn: binddn used for ldap binding (simple bind is used!).
347         // password: password for binddn
348         // basedn: this is basedn whose childeren entries which have
349         // (objectClass=shuttleConfig) will be used as detector configurations.
350         //
351
352         fDetectorMap.SetOwner();
353         fDetectorList.SetOwner(0); //fDetectorList and fDetectorMap share the same object!
354         fProcessedDetectors.SetOwner();
355
356         TLDAPServer aServer(host, port, binddn, password, 3);
357
358         if (!aServer.IsConnected()) {
359                 AliError(Form("Can't connect to ldap server %s:%d",
360                                 host, port));
361                 return;
362         }
363
364         // reads configuration for the shuttle running on this machine
365
366         fShuttleInstanceHost = gSystem->HostName();
367         TString queryFilter = Form("(ShuttleHost=%s)", fShuttleInstanceHost.Data());
368
369         TLDAPResult* aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL, queryFilter.Data());
370
371         if (!aResult) {
372                 AliError(Form("Can't find configuration with base DN: %s",
373                                 basedn));
374                 return;
375         }
376
377         if (aResult->GetCount() == 0) {
378                 AliError(Form("No Shuttle instance for host = %s!",
379                                         fShuttleInstanceHost.Data()));
380                 AliError(Form("All detectors will be processed."));
381                 fProcessAll=kTRUE;
382         }
383
384         if (aResult->GetCount() > 1) {
385                 AliError(Form("More than one Shuttle instance for host %s!",
386                                         fShuttleInstanceHost.Data()));
387                 delete aResult;
388                 return;
389         }
390
391         TLDAPEntry* anEntry = 0;
392         TLDAPAttribute* anAttribute = 0;
393
394         if(!fProcessAll){
395                 anEntry = aResult->GetNext();
396                 anAttribute = anEntry->GetAttribute("detectors");
397                 const char *detName;
398                 while((detName = anAttribute->GetValue())){
399                         TObjString *objDet= new TObjString(detName);
400                         fProcessedDetectors.Add(objDet);
401                 }
402         }
403
404         delete anEntry; delete aResult;
405
406         // Detector configuration (DCS Archive DB settings)
407
408         aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL, "(objectClass=AliShuttleDetector)");
409         if (!aResult) {
410                 AliError(Form("Can't find configuration with base DN: %s", basedn));
411                 return;
412         }
413
414
415         while ((anEntry = aResult->GetNext())) {
416                 AliShuttleConfigHolder* aHolder = new AliShuttleConfigHolder(anEntry);
417                 delete anEntry;
418
419                 if (!aHolder->IsValid()) {
420                         AliError("Detector configuration error!");
421                         delete aHolder;
422                         delete aResult;
423                         return;
424                 }
425
426                 TObjString* detStr = new TObjString(aHolder->GetDetector());
427                 fDetectorMap.Add(detStr, aHolder);
428                 fDetectorList.AddLast(detStr);
429         }
430
431         delete aResult;
432
433         // Global configuration (DAQ logbook)
434
435         aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL,
436                         "(objectClass=AliShuttleGlobalConfig)");
437         if (!aResult) {
438                 AliError(Form("Can't find configuration with base DN: %s",
439                                 basedn));
440                 return;
441         }
442
443         if (aResult->GetCount() == 0) {
444                 AliError("Can't find DAQ logbook configuration!");
445                 delete aResult;
446                 return;
447         }
448
449         if (aResult->GetCount() > 1) {
450                 AliError("More than one DAQ logbook configuration found!");
451                 delete aResult;
452                 return;
453         }
454
455         anEntry = aResult->GetNext();
456
457         anAttribute = anEntry->GetAttribute("DAQLogbookHost");
458         if (!anAttribute) {
459                 AliError("Can't find DAQLogbookHost attribute!");
460                 delete anEntry; delete aResult;
461                 return;
462         }
463         fDAQlbHost = anAttribute->GetValue();
464
465         anAttribute = anEntry->GetAttribute("DAQLogbookPort"); // MAY
466         if (anAttribute)
467         {
468                 fDAQlbPort = ((TString) anAttribute->GetValue()).Atoi();
469         } else {
470                 fDAQlbPort = 3306; // mysql
471         }
472
473         anAttribute = anEntry->GetAttribute("DAQLogbookUser");
474         if (!anAttribute) {
475                 AliError("Can't find DAQLogbookUser attribute!");
476                 delete aResult; delete anEntry;
477                 return;
478         }
479         fDAQlbUser = anAttribute->GetValue();
480
481         anAttribute = anEntry->GetAttribute("DAQLogbookPassword");
482         if (!anAttribute) {
483                 AliError("Can't find DAQLogbookPassword attribute!");
484                 delete aResult; delete anEntry;
485                 return;
486         }
487         fDAQlbPass = anAttribute->GetValue();
488
489         anAttribute = anEntry->GetAttribute("DAQLogbookDB");
490         if (!anAttribute) {
491                 AliError("Can't find DAQLogbookDB attribute!");
492                 delete aResult; delete anEntry;
493                 return;
494         }
495         fDAQlbDB = anAttribute->GetValue();
496
497         anAttribute = anEntry->GetAttribute("DAQLogbookTable");
498         if (!anAttribute) {
499                 AliError("Can't find DAQLogbookTable attribute!");
500                 delete aResult; delete anEntry;
501                 return;
502         }
503         fDAQlbTable = anAttribute->GetValue();
504
505         anAttribute = anEntry->GetAttribute("ShuttleLogbookTable");
506         if (!anAttribute) {
507                 AliError("Can't find ShuttleLogbookTable attribute!");
508                 delete aResult; delete anEntry;
509                 return;
510         }
511         fShuttlelbTable = anAttribute->GetValue();
512
513         anAttribute = anEntry->GetAttribute("RunTypeLogbookTable");
514         if (!anAttribute) {
515                 AliError("Can't find RunTypeLogbookTable attribute!");
516                 delete aResult; delete anEntry;
517                 return;
518         }
519         fRunTypelbTable = anAttribute->GetValue();
520
521         anAttribute = anEntry->GetAttribute("MaxRetries");
522         if (!anAttribute) {
523                 AliError("Can't find MaxRetries attribute!");
524                 delete aResult; delete anEntry;
525                 return;
526         }
527         TString tmpStr = anAttribute->GetValue();
528         fMaxRetries = tmpStr.Atoi();
529
530         anAttribute = anEntry->GetAttribute("PPTimeOut");
531         if (!anAttribute) {
532                 AliError("Can't find PPTimeOut attribute!");
533                 delete aResult; delete anEntry;
534                 return;
535         }
536         tmpStr = anAttribute->GetValue();
537         fPPTimeOut = tmpStr.Atoi();
538
539         anAttribute = anEntry->GetAttribute("PPMaxMem");
540         if (!anAttribute) {
541                 AliError("Can't find PPMaxMem attribute!");
542                 delete aResult; delete anEntry;
543                 return;
544         }
545         tmpStr = anAttribute->GetValue();
546         fPPMaxMem = tmpStr.Atoi();
547         
548         delete aResult; delete anEntry;
549
550         // FXS configuration (FXS logbook and hosts)
551
552         for(int iSys=0;iSys<3;iSys++){
553                 queryFilter = Form("(system=%s)", AliShuttleInterface::GetSystemName(iSys));
554                 aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL, queryFilter.Data());
555                 if (!aResult) {
556                         AliError(Form("Can't find configuration for system: %s",
557                                         AliShuttleInterface::GetSystemName(iSys)));
558                         return;
559                 }
560
561                 if (aResult->GetCount() != 1 ) {
562                         AliError("Error in FXS configuration!");
563                         delete aResult;
564                         return;
565                 }
566
567                 anEntry = aResult->GetNext();
568
569                 anAttribute = anEntry->GetAttribute("DBHost");
570                 if (!anAttribute) {
571                         AliError(Form ("Can't find DBHost attribute for %s!!",
572                                                 AliShuttleInterface::GetSystemName(iSys)));
573                         delete aResult; delete anEntry;
574                         return;
575                 }
576                 fFXSdbHost[iSys] = anAttribute->GetValue();
577
578                 anAttribute = anEntry->GetAttribute("DBPort"); // MAY
579                 if (anAttribute)
580                 {
581                         fFXSdbPort[iSys] = ((TString) anAttribute->GetValue()).Atoi();
582                 } else {
583                         fFXSdbPort[iSys] = 3306; // mysql
584                 }
585
586                 anAttribute = anEntry->GetAttribute("DBUser");
587                 if (!anAttribute) {
588                         AliError(Form ("Can't find DBUser attribute for %s!!",
589                                                 AliShuttleInterface::GetSystemName(iSys)));
590                         delete aResult; delete anEntry;
591                         return;
592                 }
593                 fFXSdbUser[iSys] = anAttribute->GetValue();
594
595                 anAttribute = anEntry->GetAttribute("DBPassword");
596                 if (!anAttribute) {
597                         AliError(Form ("Can't find DBPassword attribute for %s!!",
598                                                 AliShuttleInterface::GetSystemName(iSys)));
599                         delete aResult; delete anEntry;
600                         return;
601                 }
602                 fFXSdbPass[iSys] = anAttribute->GetValue();
603
604                 anAttribute = anEntry->GetAttribute("DBName");
605                 if (!anAttribute) {
606                         AliError(Form ("Can't find DBName attribute for %s!!",
607                                                 AliShuttleInterface::GetSystemName(iSys)));
608                         delete aResult; delete anEntry;
609                         return;
610                 }
611
612                 fFXSdbName[iSys] = anAttribute->GetValue();
613                 anAttribute = anEntry->GetAttribute("DBTable");
614                 if (!anAttribute) {
615                         AliError(Form ("Can't find DBTable attribute for %s!!",
616                                                 AliShuttleInterface::GetSystemName(iSys)));
617                         delete aResult; delete anEntry;
618                         return;
619                 }
620                 fFXSdbTable[iSys] = anAttribute->GetValue();
621
622                 anAttribute = anEntry->GetAttribute("FSHost");
623                 if (!anAttribute) {
624                         AliError(Form ("Can't find FSHost attribute for %s!!",
625                                                 AliShuttleInterface::GetSystemName(iSys)));
626                         delete aResult; delete anEntry;
627                         return;
628                 }
629                 fFXSHost[iSys] = anAttribute->GetValue();
630
631                 anAttribute = anEntry->GetAttribute("FSPort"); // MAY
632                 if (anAttribute)
633                 {
634                         fFXSPort[iSys] = ((TString) anAttribute->GetValue()).Atoi();
635                 } else {
636                         fFXSPort[iSys] = 22; // scp port number
637                 }
638
639                 anAttribute = anEntry->GetAttribute("FSUser");
640                 if (!anAttribute) {
641                         AliError(Form ("Can't find FSUser attribute for %s!!",
642                                                 AliShuttleInterface::GetSystemName(iSys)));
643                         delete aResult; delete anEntry;
644                         return;
645                 }
646                 fFXSUser[iSys] = anAttribute->GetValue();
647
648                 anAttribute = anEntry->GetAttribute("FSPassword");
649                 if (anAttribute) fFXSPass[iSys] = anAttribute->GetValue();
650
651                 delete aResult; delete anEntry;
652         }
653
654         fIsValid = kTRUE;
655 }
656
657 //______________________________________________________________________________________________
658 AliShuttleConfig::~AliShuttleConfig()
659 {
660 // destructor
661
662         fDetectorMap.DeleteAll();
663         fDetectorList.Clear();
664         fProcessedDetectors.Delete();
665 }
666
667 //______________________________________________________________________________________________
668 const TObjArray* AliShuttleConfig::GetDetectors() const
669 {
670         //
671         // returns collection of TObjString which contains the name
672         // of every detector which is in the configuration.
673         //
674
675         return &fDetectorList;
676 }
677
678 //______________________________________________________________________________________________
679 Bool_t AliShuttleConfig::HasDetector(const char* detector) const
680 {
681         //
682         // checks for paricular detector in the configuration.
683         //
684         return fDetectorMap.GetValue(detector) != NULL;
685 }
686
687 //______________________________________________________________________________________________
688 const char* AliShuttleConfig::GetDCSHost(const char* detector) const
689 {
690         //
691         // returns DCS server host used by particular detector
692         //
693         
694         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
695         if (!aHolder) {
696                 AliError(Form("There isn't configuration for detector: %s",
697                         detector));
698                 return NULL;
699         }
700
701         return aHolder->GetDCSHost();
702 }
703
704 //______________________________________________________________________________________________
705 Int_t AliShuttleConfig::GetDCSPort(const char* detector) const
706 {
707         //
708         // returns DCS server port used by particular detector
709         //
710
711
712         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
713         if (!aHolder) {
714                 AliError(Form("There isn't configuration for detector: %s",
715                         detector));
716                 return 0;
717         }
718
719         return aHolder->GetDCSPort();
720 }
721
722 //______________________________________________________________________________________________
723 const TObjArray* AliShuttleConfig::GetDCSAliases(const char* detector) const
724 {
725         //
726         // returns collection of TObjString which represents the set of aliases
727         // which used for data retrieval for particular detector
728         //
729
730         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
731         if (!aHolder) {
732                 AliError(Form("There isn't configuration for detector: %s",
733                         detector));
734                 return NULL;
735         }
736
737         return aHolder->GetDCSAliases();
738 }
739
740 //______________________________________________________________________________________________
741 const TObjArray* AliShuttleConfig::GetDCSDataPoints(const char* detector) const
742 {
743         //
744         // returns collection of TObjString which represents the set of aliases
745         // which used for data retrieval for particular detector
746         //
747
748         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
749         if (!aHolder) {
750                 AliError(Form("There isn't configuration for detector: %s",
751                         detector));
752                 return NULL;
753         }
754
755         return aHolder->GetDCSDataPoints();
756 }
757
758 //______________________________________________________________________________________________
759 const TObjArray* AliShuttleConfig::GetResponsibles(const char* detector) const
760 {
761         //
762         // returns collection of TObjString which represents the list of mail addresses
763         // of the detector's responsible(s)
764         //
765
766         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
767         if (!aHolder) {
768                 AliError(Form("There isn't configuration for detector: %s",
769                         detector));
770                 return NULL;
771         }
772
773         return aHolder->GetResponsibles();
774 }
775
776 //______________________________________________________________________________________________
777 Bool_t AliShuttleConfig::HostProcessDetector(const char* detector) const
778 {
779         // return TRUE if detector is handled by host or if fProcessAll is TRUE
780
781         if(fProcessAll) return kTRUE;
782         TIter iter(&fProcessedDetectors);
783         TObjString* detName;
784         while((detName = (TObjString*) iter.Next())){
785                 if(detName->String() == detector) return kTRUE;
786         }
787         return kFALSE;
788 }
789
790 //______________________________________________________________________________________________
791 Bool_t AliShuttleConfig::StrictRunOrder(const char* detector) const
792 {
793         // return TRUE if detector wants strict run ordering of stored data
794
795         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
796         if (!aHolder)
797         {
798                 AliError(Form("There isn't configuration for detector: %s",
799                         detector));
800                 return kTRUE;
801         }
802
803         return aHolder->StrictRunOrder();
804 }
805
806 //______________________________________________________________________________________________
807 void AliShuttleConfig::Print(Option_t* option) const
808 {
809 // print configuration
810 // options : "": print configuration for all detectors, aliases and DPs in compacted format
811 //           "uncompact": print configuration for all detectors, aliases and DPs in uncompacted format
812 //           "DET": print configuration for DET, aliases and DPs in compacted format
813 //           "DET, uncompact": print configuration for DET, aliases and DPs in uncompacted format
814
815         TString result;
816         result += '\n';
817
818         result += "####################################################\n";
819         result += Form(" Shuttle configuration from %s \n", fConfigHost.Data());
820         result += "####################################################\n";
821         result += Form("\nShuttle running on %s \n", fShuttleInstanceHost.Data());
822
823         if(fProcessAll) {
824                 result += Form("All detectors will be processed! \n");
825         } else {
826                 result += "Detectors processed by this host: ";
827                 TIter it(&fProcessedDetectors);
828                 TObjString* aDet;
829                 while ((aDet = (TObjString*) it.Next())) {
830                         result += Form("%s ", aDet->String().Data());
831                 }
832                 result += "\n";
833         }
834
835         result += Form("PP time out = %d - Max PP memsize = %d KB - Max total retries = %d\n\n", fPPTimeOut, fPPMaxMem, fMaxRetries);
836         result += "------------------------------------------------------\n";
837
838         result += Form("Logbook Configuration \n\n \tHost: %s:%d; \tUser: %s; ",
839                 fDAQlbHost.Data(), fDAQlbPort, fDAQlbUser.Data());
840
841 //      result += "Password: ";
842 //      result.Append('*', fDAQlbPass.Length());
843         result += Form("\tDB: %s; \tTables: %s, %s, %s",
844                 fDAQlbDB.Data(), fDAQlbTable.Data(), fShuttlelbTable.Data(), fRunTypelbTable.Data());
845
846         result += "\n\n";
847
848         result += "------------------------------------------------------\n";
849         result += "FXS configuration\n\n";
850
851         for(int iSys=0;iSys<3;iSys++){
852                 result += Form("*** %s ***\n", AliShuttleInterface::GetSystemName(iSys));
853                 result += Form("\tDB  host: %s:%d; \tUser: %s; \tName: %s; \tTable: %s\n",
854                                                 fFXSdbHost[iSys].Data(), fFXSdbPort[iSys], fFXSdbUser[iSys].Data(),
855                                                 fFXSdbName[iSys].Data(), fFXSdbTable[iSys].Data());
856                 // result += Form("DB Password:",fFXSdbPass[iSys].Data());
857                 result += Form("\tFXS host: %s:%d; \tUser: %s\n\n", fFXSHost[iSys].Data(), fFXSPort[iSys],
858                                                 fFXSUser[iSys].Data());
859                 // result += Form("FXS Password:",fFXSPass[iSys].Data());
860         }
861
862         TString optStr(option);
863
864         result += "------------------------------------------------------\n";
865         result += "Detector-specific configuration\n\n";
866         TIter iter(fDetectorMap.GetTable());
867         TPair* aPair;
868         while ((aPair = (TPair*) iter.Next())) {
869                 AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) aPair->Value();
870                 if (option != 0 && !optStr.Contains(aHolder->GetDetector()) && optStr.CompareTo("uncompact",TString::kIgnoreCase) != 0 )
871                                 continue;
872                 result += Form("*** %s *** \n", aHolder->GetDetector());
873
874                 const TObjArray* responsibles = aHolder->GetResponsibles();
875                 if (responsibles->GetEntries() != 0)
876                 {
877                         result += "\tDetector responsible(s): ";
878                         TIter it(responsibles);
879                         TObjString* aResponsible;
880                         while ((aResponsible = (TObjString*) it.Next()))
881                         {
882                                 result += Form("%s ", aResponsible->String().Data());
883                         }
884                         result += "\n";
885                 }
886
887                 result += Form("\tStrict run ordering: %s \n", aHolder->StrictRunOrder() ? "YES" : "NO");
888                 if(aHolder->SkipDCSQuery())
889                 {
890                         result += "\n";
891                         continue;
892                 }
893                 result += Form("\tAmanda server: %s:%d \n", aHolder->GetDCSHost(), aHolder->GetDCSPort());
894
895                 const TObjArray* aliases = 0;
896                 if (optStr.Contains("uncompact",TString::kIgnoreCase))
897                 {
898                         aliases = aHolder->GetDCSAliases();
899                 } else {
900                         aliases = aHolder->GetCompactDCSAliases();
901                 }
902
903                 if (aliases->GetEntries() != 0)
904                 {
905                         result += "\tDCS Aliases: ";
906                         TIter it(aliases);
907                         TObjString* anAlias;
908                         while ((anAlias = (TObjString*) it.Next()))
909                         {
910                                 result += Form("%s ", anAlias->String().Data());
911                         }
912                         result += "\n";
913                 }
914
915                 const TObjArray* dataPoints = 0;
916                 if (optStr.Contains("uncompact",TString::kIgnoreCase))
917                 {
918                         dataPoints = aHolder->GetDCSDataPoints();
919                 } else {
920                         dataPoints = aHolder->GetCompactDCSDataPoints();
921                 }
922                 if (dataPoints->GetEntries() != 0)
923                 {
924                         result += "\tDCS Data Points: ";
925                         TIter it(dataPoints);
926                         TObjString* aDataPoint;
927                         while ((aDataPoint = (TObjString*) it.Next())) {
928                                 result += Form("%s ", aDataPoint->String().Data());
929                         }
930                                 result += "\n";
931                 }
932                 result += "\n";
933         }
934
935         if(!fIsValid) result += "\n\n********** !!!!! Configuration is INVALID !!!!! **********\n";
936
937         AliInfo(result);
938 }