implementation of sending mail to subdetector expert in case the preprocessor fails.
[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.13  2006/12/07 08:51:26  jgrosseo
19 update (alberto):
20 table, db names in ldap configuration
21 added GRP preprocessor
22 DCS data can also be retrieved by data point
23
24 Revision 1.12  2006/11/16 16:16:48  jgrosseo
25 introducing strict run ordering flag
26 removed giving preprocessor name to preprocessor, they have to know their name themselves ;-)
27
28 Revision 1.11  2006/11/06 14:23:04  jgrosseo
29 major update (Alberto)
30 o) reading of run parameters from the logbook
31 o) online offline naming conversion
32 o) standalone DCSclient package
33
34 Revision 1.10  2006/10/20 15:22:59  jgrosseo
35 o) Adding time out to the execution of the preprocessors: The Shuttle forks and the parent process monitors the child
36 o) Merging Collect, CollectAll, CollectNew function
37 o) Removing implementation of empty copy constructors (declaration still there!)
38
39 Revision 1.9  2006/10/02 16:38:39  jgrosseo
40 update (alberto):
41 fixed memory leaks
42 storing of objects that failed to be stored to the grid before
43 interfacing of shuttle status table in daq system
44
45 Revision 1.8  2006/08/15 10:50:00  jgrosseo
46 effc++ corrections (alberto)
47
48 Revision 1.7  2006/07/20 09:54:40  jgrosseo
49 introducing status management: The processing per subdetector is divided into several steps,
50 after each step the status is stored on disk. If the system crashes in any of the steps the Shuttle
51 can keep track of the number of failures and skips further processing after a certain threshold is
52 exceeded. These thresholds can be configured in LDAP.
53
54 Revision 1.6  2006/07/19 10:09:55  jgrosseo
55 new configuration, accesst to DAQ FES (Alberto)
56
57 Revision 1.5  2006/07/10 13:01:41  jgrosseo
58 enhanced storing of last sucessfully processed run (alberto)
59
60 Revision 1.4  2006/06/12 09:11:16  jgrosseo
61 coding conventions (Alberto)
62
63 Revision 1.3  2006/06/06 14:26:40  jgrosseo
64 o) removed files that were moved to STEER
65 o) shuttle updated to follow the new interface (Alberto)
66
67 Revision 1.7  2006/05/12 09:07:16  colla
68 12/05/06
69 New configuration complete
70
71 Revision 1.2  2006/03/07 07:52:34  hristov
72 New version (B.Yordanov)
73
74 Revision 1.4  2005/11/19 14:20:31  byordano
75 logbook config added to AliShuttleConfig
76
77 Revision 1.3  2005/11/17 19:24:25  byordano
78 TList changed to TObjArray in AliShuttleConfig
79
80 Revision 1.2  2005/11/17 14:43:23  byordano
81 import to local CVS
82
83 Revision 1.1.1.1  2005/10/28 07:33:58  hristov
84 Initial import as subdirectory in AliRoot
85
86 Revision 1.1.1.1  2005/09/12 22:11:40  byordano
87 SHUTTLE package
88
89 Revision 1.3  2005/08/30 09:13:02  byordano
90 some docs added
91
92 */
93
94
95 //
96 // This class keeps the AliShuttle configuration.
97 // It reads the configuration for LDAP server.
98 // For every child entry in basedn which has schema type 'shuttleConfig'
99 // it creates a detector configuration. This configuration includes:
100 // DCS server host and port and the set of aliases for which data from
101 // will be retrieved (used by AliShuttle).
102 //
103
104
105 #include "AliShuttleConfig.h"
106 #include "AliShuttleInterface.h"
107
108 #include "AliLog.h"
109
110 #include <TSystem.h>
111 #include <TObjString.h>
112 #include <TLDAPResult.h>
113 #include <TLDAPEntry.h>
114 #include <TLDAPAttribute.h>
115
116
117 AliShuttleConfig::AliShuttleConfigHolder::AliShuttleConfigHolder(const TLDAPEntry* entry):
118 fDetector(""),
119 fDCSHost(""),
120 fDCSPort(0),
121 fDCSAliases(0),
122 fDCSDataPoints(0),
123 fResponsibles(0),
124 fIsValid(kFALSE),
125 fSkipDCSQuery(kFALSE),
126 fStrictRunOrder(kFALSE)
127 {
128 // constructor of the shuttle configuration holder
129
130         TLDAPAttribute* anAttribute;
131         fDCSAliases = new TObjArray();
132         fDCSAliases->SetOwner(1);
133         fDCSDataPoints = new TObjArray();
134         fDCSDataPoints->SetOwner(1);
135         fResponsibles = new TObjArray();
136         fResponsibles->SetOwner(1);
137
138         anAttribute = entry->GetAttribute("det"); // MUST
139         if (!anAttribute)
140         {
141                 AliError(Form("Invalid configuration! No \"det\" attribute!"));
142                 return;
143         }
144         fDetector = anAttribute->GetValue();
145
146         anAttribute = entry->GetAttribute("StrictRunOrder"); // MAY
147         if (!anAttribute)
148         {
149                 AliWarning(Form("%s did not set StrictRunOrder flag - the default is FALSE",
150                                 fDetector.Data()));
151         } else {
152                 TString strictRunStr = anAttribute->GetValue();
153                 if (!(strictRunStr == "0" || strictRunStr == "1"))
154                 {
155                         AliError("Invalid configuration! StrictRunOrder flag must be 0 or 1!");
156                         return;
157                 }
158                 fStrictRunOrder = (Bool_t) strictRunStr.Atoi();
159         }
160
161         anAttribute = entry->GetAttribute("responsible"); // MUST
162         if (!anAttribute)
163         {
164                 AliError(Form("Invalid configuration! No \"responsible\" attribute!"));
165                 return;
166         }
167         const char* aResponsible;
168         while ((aResponsible = anAttribute->GetValue()))
169         {
170                 fResponsibles->AddLast(new TObjString(aResponsible));
171         }
172
173         anAttribute = entry->GetAttribute("DCSHost"); // MAY
174         if (!anAttribute)
175         {
176                 AliDebug(2,
177                         Form("%s has not DCS host entry - Shuttle will skip DCS data query!",
178                                 fDetector.Data()));
179                 fIsValid = kTRUE;
180                 fSkipDCSQuery = kTRUE;
181                 return;
182         }
183
184         fDCSHost = anAttribute->GetValue();
185
186         anAttribute = entry->GetAttribute("DCSPort"); // MAY
187         if (!anAttribute)
188         {
189                 AliError(Form("Invalid configuration! %s has DCS Host but no port number!",
190                                 fDetector.Data()));
191                 return;
192         }
193         TString portStr = anAttribute->GetValue();
194         fDCSPort = portStr.Atoi();
195
196         anAttribute = entry->GetAttribute("DCSalias"); // MAY
197         if (anAttribute)
198         {
199                 const char* anAlias;
200                 while ((anAlias = anAttribute->GetValue()))
201                 {
202                         fDCSAliases->AddLast(new TObjString(anAlias));
203                 }
204         }
205
206         anAttribute = entry->GetAttribute("DCSdatapoint"); // MAY
207         if (anAttribute)
208         {
209                 const char* aDataPoint;
210                 while ((aDataPoint = anAttribute->GetValue()))
211                 {
212                         fDCSDataPoints->AddLast(new TObjString(aDataPoint));
213                 }
214         }
215
216         fIsValid = kTRUE;
217 }
218
219 //______________________________________________________________________________________________
220 AliShuttleConfig::AliShuttleConfigHolder::~AliShuttleConfigHolder()
221 {
222 // destructor of the shuttle configuration holder
223
224         delete fDCSAliases;
225         delete fDCSDataPoints;
226         delete fResponsibles;
227 }
228
229 ClassImp(AliShuttleConfig)
230
231 //______________________________________________________________________________________________
232 AliShuttleConfig::AliShuttleConfig(const char* host, Int_t port,
233         const char* binddn, const char* password, const char* basedn):
234         fIsValid(kFALSE), fConfigHost(host),
235         fDAQlbHost(""), fDAQlbPort(), fDAQlbUser(""), fDAQlbPass(""),
236         fDAQlbDB(""), fDAQlbTable(""),
237         fMaxRetries(0), fPPTimeOut(0), fDetectorMap(), fDetectorList(),
238         fShuttleInstanceHost(""), fProcessedDetectors(), fProcessAll(kFALSE)
239 {
240         //
241         // host: ldap server host
242         // port: ldap server port
243         // binddn: binddn used for ldap binding (simple bind is used!).
244         // password: password for binddn
245         // basedn: this is basedn whose childeren entries which have
246         // (objectClass=shuttleConfig) will be used as detector configurations.
247         //
248
249         fDetectorMap.SetOwner();
250         fDetectorList.SetOwner(0); //fDetectorList and fDetectorMap share the same object!
251         fProcessedDetectors.SetOwner();
252
253         TLDAPServer aServer(host, port, binddn, password, 3);
254
255         if (!aServer.IsConnected()) {
256                 AliError(Form("Can't connect to ldap server %s:%d",
257                                 host, port));
258                 return;
259         }
260
261         // reads configuration for the shuttle running on this machine
262
263         fShuttleInstanceHost = gSystem->HostName();
264         TString queryFilter = Form("(ShuttleHost=%s)", fShuttleInstanceHost.Data());
265
266         TLDAPResult* aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL, queryFilter.Data());
267
268         if (!aResult) {
269                 AliError(Form("Can't find configuration with base DN: %s",
270                                 basedn));
271                 return;
272         }
273
274         if (aResult->GetCount() == 0) {
275                 AliError(Form("No Shuttle instance for host = %s!",
276                                         fShuttleInstanceHost.Data()));
277                 AliError(Form("All detectors will be processed."));
278                 fProcessAll=kTRUE;
279         }
280
281         if (aResult->GetCount() > 1) {
282                 AliError(Form("More than one Shuttle instance for host %s!",
283                                         fShuttleInstanceHost.Data()));
284                 delete aResult;
285                 return;
286         }
287
288         TLDAPEntry* anEntry = 0;
289         TLDAPAttribute* anAttribute = 0;
290
291         if(!fProcessAll){
292                 anEntry = aResult->GetNext();
293                 anAttribute = anEntry->GetAttribute("detectors");
294                 const char *detName;
295                 while((detName = anAttribute->GetValue())){
296                         TObjString *objDet= new TObjString(detName);
297                         fProcessedDetectors.Add(objDet);
298                 }
299         }
300
301         delete anEntry; delete aResult;
302
303         // Detector configuration (DCS Archive DB settings)
304
305         aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL, "(objectClass=AliShuttleDetector)");
306         if (!aResult) {
307                 AliError(Form("Can't find configuration with base DN: %s", basedn));
308                 return;
309         }
310
311
312         while ((anEntry = aResult->GetNext())) {
313                 AliShuttleConfigHolder* aHolder = new AliShuttleConfigHolder(anEntry);
314                 delete anEntry;
315
316                 if (!aHolder->IsValid()) {
317                         AliError("Detector configuration error!");
318                         delete aHolder;
319                         delete aResult;
320                         return;
321                 }
322
323                 TObjString* detStr = new TObjString(aHolder->GetDetector());
324                 fDetectorMap.Add(detStr, aHolder);
325                 fDetectorList.AddLast(detStr);
326         }
327
328         delete aResult;
329
330         // Global configuration (DAQ logbook)
331
332         aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL,
333                         "(objectClass=AliShuttleGlobalConfig)");
334         if (!aResult) {
335                 AliError(Form("Can't find configuration with base DN: %s",
336                                 basedn));
337                 return;
338         }
339
340         if (aResult->GetCount() == 0) {
341                 AliError("Can't find DAQ logbook configuration!");
342                 delete aResult;
343                 return;
344         }
345
346         if (aResult->GetCount() > 1) {
347                 AliError("More than one DAQ logbook configuration found!");
348                 delete aResult;
349                 return;
350         }
351
352         anEntry = aResult->GetNext();
353
354         anAttribute = anEntry->GetAttribute("DAQLogbookHost");
355         if (!anAttribute) {
356                 AliError("Can't find DAQLogbookHost attribute!");
357                 delete anEntry; delete aResult;
358                 return;
359         }
360         fDAQlbHost = anAttribute->GetValue();
361
362         anAttribute = anEntry->GetAttribute("DAQLogbookPort"); // MAY
363         if (anAttribute)
364         {
365                 fDAQlbPort = ((TString) anAttribute->GetValue()).Atoi();
366         } else {
367                 fDAQlbPort = 3306; // mysql
368         }
369
370         anAttribute = anEntry->GetAttribute("DAQLogbookUser");
371         if (!anAttribute) {
372                 AliError("Can't find DAQLogbookUser attribute!");
373                 delete aResult; delete anEntry;
374                 return;
375         }
376         fDAQlbUser = anAttribute->GetValue();
377
378         anAttribute = anEntry->GetAttribute("DAQLogbookPassword");
379         if (!anAttribute) {
380                 AliError("Can't find DAQLogbookPassword attribute!");
381                 delete aResult; delete anEntry;
382                 return;
383         }
384         fDAQlbPass = anAttribute->GetValue();
385
386         anAttribute = anEntry->GetAttribute("DAQLogbookDB");
387         if (!anAttribute) {
388                 AliError("Can't find DAQLogbookDB attribute!");
389                 delete aResult; delete anEntry;
390                 return;
391         }
392         fDAQlbDB = anAttribute->GetValue();
393
394         anAttribute = anEntry->GetAttribute("DAQLogbookTable");
395         if (!anAttribute) {
396                 AliError("Can't find DAQLogbookTable attribute!");
397                 delete aResult; delete anEntry;
398                 return;
399         }
400         fDAQlbTable = anAttribute->GetValue();
401
402
403         anAttribute = anEntry->GetAttribute("MaxRetries");
404         if (!anAttribute) {
405                 AliError("Can't find MaxRetries attribute!");
406                 delete aResult; delete anEntry;
407                 return;
408         }
409         TString tmpStr = anAttribute->GetValue();
410         fMaxRetries = tmpStr.Atoi();
411
412         anAttribute = anEntry->GetAttribute("PPTimeOut");
413         if (!anAttribute) {
414                 AliError("Can't find PPTimeOut attribute!");
415                 delete aResult; delete anEntry;
416                 return;
417         }
418         tmpStr = anAttribute->GetValue();
419         fPPTimeOut = tmpStr.Atoi();
420
421         delete aResult; delete anEntry;
422
423         // FXS configuration (FXS logbook and hosts)
424
425         for(int iSys=0;iSys<3;iSys++){
426                 queryFilter = Form("(system=%s)", AliShuttleInterface::GetSystemName(iSys));
427                 aResult = aServer.Search(basedn, LDAP_SCOPE_ONELEVEL, queryFilter.Data());
428                 if (!aResult) {
429                         AliError(Form("Can't find configuration for system: %s",
430                                         AliShuttleInterface::GetSystemName(iSys)));
431                         return;
432                 }
433
434                 if (aResult->GetCount() != 1 ) {
435                         AliError("Error in FXS configuration!");
436                         delete aResult;
437                         return;
438                 }
439
440                 anEntry = aResult->GetNext();
441
442                 anAttribute = anEntry->GetAttribute("DBHost");
443                 if (!anAttribute) {
444                         AliError(Form ("Can't find DBHost attribute for %s!!",
445                                                 AliShuttleInterface::GetSystemName(iSys)));
446                         delete aResult; delete anEntry;
447                         return;
448                 }
449                 fFXSdbHost[iSys] = anAttribute->GetValue();
450
451                 anAttribute = anEntry->GetAttribute("DBPort"); // MAY
452                 if (anAttribute)
453                 {
454                         fFXSdbPort[iSys] = ((TString) anAttribute->GetValue()).Atoi();
455                 } else {
456                         fFXSdbPort[iSys] = 3306; // mysql
457                 }
458
459                 anAttribute = anEntry->GetAttribute("DBUser");
460                 if (!anAttribute) {
461                         AliError(Form ("Can't find DBUser attribute for %s!!",
462                                                 AliShuttleInterface::GetSystemName(iSys)));
463                         delete aResult; delete anEntry;
464                         return;
465                 }
466                 fFXSdbUser[iSys] = anAttribute->GetValue();
467
468                 anAttribute = anEntry->GetAttribute("DBPassword");
469                 if (!anAttribute) {
470                         AliError(Form ("Can't find DBPassword attribute for %s!!",
471                                                 AliShuttleInterface::GetSystemName(iSys)));
472                         delete aResult; delete anEntry;
473                         return;
474                 }
475                 fFXSdbPass[iSys] = anAttribute->GetValue();
476
477                 anAttribute = anEntry->GetAttribute("DBName");
478                 if (!anAttribute) {
479                         AliError(Form ("Can't find DBName attribute for %s!!",
480                                                 AliShuttleInterface::GetSystemName(iSys)));
481                         delete aResult; delete anEntry;
482                         return;
483                 }
484
485                 fFXSdbName[iSys] = anAttribute->GetValue();
486                 anAttribute = anEntry->GetAttribute("DBTable");
487                 if (!anAttribute) {
488                         AliError(Form ("Can't find DBTable attribute for %s!!",
489                                                 AliShuttleInterface::GetSystemName(iSys)));
490                         delete aResult; delete anEntry;
491                         return;
492                 }
493                 fFXSdbTable[iSys] = anAttribute->GetValue();
494
495                 anAttribute = anEntry->GetAttribute("FSHost");
496                 if (!anAttribute) {
497                         AliError(Form ("Can't find FSHost attribute for %s!!",
498                                                 AliShuttleInterface::GetSystemName(iSys)));
499                         delete aResult; delete anEntry;
500                         return;
501                 }
502                 fFXSHost[iSys] = anAttribute->GetValue();
503
504                 anAttribute = anEntry->GetAttribute("FSPort"); // MAY
505                 if (anAttribute)
506                 {
507                         fFXSPort[iSys] = ((TString) anAttribute->GetValue()).Atoi();
508                 } else {
509                         fFXSPort[iSys] = 22; // scp port number
510                 }
511
512                 anAttribute = anEntry->GetAttribute("FSUser");
513                 if (!anAttribute) {
514                         AliError(Form ("Can't find FSUser attribute for %s!!",
515                                                 AliShuttleInterface::GetSystemName(iSys)));
516                         delete aResult; delete anEntry;
517                         return;
518                 }
519                 fFXSUser[iSys] = anAttribute->GetValue();
520
521                 anAttribute = anEntry->GetAttribute("FSPassword");
522                 if (anAttribute) fFXSPass[iSys] = anAttribute->GetValue();
523
524                 delete aResult; delete anEntry;
525         }
526
527         fIsValid = kTRUE;
528 }
529
530 //______________________________________________________________________________________________
531 AliShuttleConfig::~AliShuttleConfig()
532 {
533 // destructor
534
535         fDetectorMap.DeleteAll();
536         fDetectorList.Clear();
537         fProcessedDetectors.Delete();
538 }
539
540 //______________________________________________________________________________________________
541 const TObjArray* AliShuttleConfig::GetDetectors() const
542 {
543         //
544         // returns collection of TObjString which contains the name
545         // of every detector which is in the configuration.
546         //
547
548         return &fDetectorList;
549 }
550
551 //______________________________________________________________________________________________
552 Bool_t AliShuttleConfig::HasDetector(const char* detector) const
553 {
554         //
555         // checks for paricular detector in the configuration.
556         //
557         return fDetectorMap.GetValue(detector) != NULL;
558 }
559
560 //______________________________________________________________________________________________
561 const char* AliShuttleConfig::GetDCSHost(const char* detector) const
562 {
563         //
564         // returns DCS server host used by particular detector
565         //
566         
567         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
568         if (!aHolder) {
569                 AliError(Form("There isn't configuration for detector: %s",
570                         detector));
571                 return NULL;
572         }
573
574         return aHolder->GetDCSHost();
575 }
576
577 //______________________________________________________________________________________________
578 Int_t AliShuttleConfig::GetDCSPort(const char* detector) const
579 {
580         //
581         // returns DCS server port used by particular detector
582         //
583
584
585         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
586         if (!aHolder) {
587                 AliError(Form("There isn't configuration for detector: %s",
588                         detector));
589                 return 0;
590         }
591
592         return aHolder->GetDCSPort();
593 }
594
595 //______________________________________________________________________________________________
596 const TObjArray* AliShuttleConfig::GetDCSAliases(const char* detector) const
597 {
598         //
599         // returns collection of TObjString which represents the set of aliases
600         // which used for data retrieval for particular detector
601         //
602
603         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
604         if (!aHolder) {
605                 AliError(Form("There isn't configuration for detector: %s",
606                         detector));
607                 return NULL;
608         }
609
610         return aHolder->GetDCSAliases();
611 }
612
613 //______________________________________________________________________________________________
614 const TObjArray* AliShuttleConfig::GetDCSDataPoints(const char* detector) const
615 {
616         //
617         // returns collection of TObjString which represents the set of aliases
618         // which used for data retrieval for particular detector
619         //
620
621         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
622         if (!aHolder) {
623                 AliError(Form("There isn't configuration for detector: %s",
624                         detector));
625                 return NULL;
626         }
627
628         return aHolder->GetDCSDataPoints();
629 }
630
631 //______________________________________________________________________________________________
632 const TObjArray* AliShuttleConfig::GetResponsibles(const char* detector) const
633 {
634         //
635         // returns collection of TObjString which represents the list of mail addresses
636         // of the detector's responsible(s)
637         //
638
639         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
640         if (!aHolder) {
641                 AliError(Form("There isn't configuration for detector: %s",
642                         detector));
643                 return NULL;
644         }
645
646         return aHolder->GetResponsibles();
647 }
648
649 //______________________________________________________________________________________________
650 Bool_t AliShuttleConfig::HostProcessDetector(const char* detector) const
651 {
652         // return TRUE if detector is handled by host or if fProcessAll is TRUE
653
654         if(fProcessAll) return kTRUE;
655         TIter iter(&fProcessedDetectors);
656         TObjString* detName;
657         while((detName = (TObjString*) iter.Next())){
658                 if(detName->String() == detector) return kTRUE;
659         }
660         return kFALSE;
661 }
662
663 //______________________________________________________________________________________________
664 Bool_t AliShuttleConfig::StrictRunOrder(const char* detector) const
665 {
666         // return TRUE if detector wants strict run ordering of stored data
667
668         AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) fDetectorMap.GetValue(detector);
669         if (!aHolder)
670         {
671                 AliError(Form("There isn't configuration for detector: %s",
672                         detector));
673                 return kTRUE;
674         }
675
676         return aHolder->StrictRunOrder();
677 }
678
679 //______________________________________________________________________________________________
680 void AliShuttleConfig::Print(Option_t* /*option*/) const
681 {
682 // print configuration
683         
684         TString result;
685         result += '\n';
686
687         result += "####################################################\n";
688         result += Form(" Shuttle configuration from %s \n", fConfigHost.Data());
689         result += "####################################################\n";
690         result += Form("\nShuttle running on %s \n", fShuttleInstanceHost.Data());
691
692         if(fProcessAll) {
693                 result += Form("All detectors will be processed! \n");
694         } else {
695                 result += "Detectors processed by this host: ";
696                 TIter it(&fProcessedDetectors);
697                 TObjString* aDet;
698                 while ((aDet = (TObjString*) it.Next())) {
699                         result += Form("%s ", aDet->String().Data());
700                 }
701                 result += "\n";
702         }
703
704         result += Form("PP time out = %d - Max total retries = %d\n\n", fPPTimeOut, fMaxRetries);
705         result += "------------------------------------------------------\n";
706
707         result += Form("Logbook Configuration \n\n \tHost: %s:%d; \tUser: %s; ",
708                 fDAQlbHost.Data(), fDAQlbPort, fDAQlbUser.Data());
709
710 //      result += "Password: ";
711 //      result.Append('*', fDAQlbPass.Length());
712         result += Form("\tDB: %s; \tTable: %s",
713                 fDAQlbDB.Data(), fDAQlbTable.Data());
714
715         result += "\n\n";
716
717         result += "------------------------------------------------------\n";
718         result += "FXS configuration\n\n";
719
720         for(int iSys=0;iSys<3;iSys++){
721                 result += Form("*** %s ***\n", AliShuttleInterface::GetSystemName(iSys));
722                 result += Form("\tDB  host: %s:%d; \tUser: %s; \tName: %s; \tTable: %s\n",
723                                                 fFXSdbHost[iSys].Data(), fFXSdbPort[iSys], fFXSdbUser[iSys].Data(),
724                                                 fFXSdbName[iSys].Data(), fFXSdbTable[iSys].Data());
725                 // result += Form("DB Password:",fFXSdbPass[iSys].Data());
726                 result += Form("\tFXS host: %s:%d; \tUser: %s\n\n", fFXSHost[iSys].Data(), fFXSPort[iSys],
727                                                 fFXSUser[iSys].Data());
728                 // result += Form("FXS Password:",fFXSPass[iSys].Data());
729         }
730
731         result += "------------------------------------------------------\n";
732         result += "Detector-specific configuration\n\n";
733         TIter iter(fDetectorMap.GetTable());
734         TPair* aPair;
735         while ((aPair = (TPair*) iter.Next())) {
736                 AliShuttleConfigHolder* aHolder = (AliShuttleConfigHolder*) aPair->Value();
737                 result += Form("*** %s *** \n", aHolder->GetDetector());
738
739                 const TObjArray* responsibles = aHolder->GetResponsibles();
740                 if (responsibles->GetEntries() != 0)
741                 {
742                         result += "\tDetector responsible(s): ";
743                         TIter it(responsibles);
744                         TObjString* aResponsible;
745                         while ((aResponsible = (TObjString*) it.Next()))
746                         {
747                                 result += Form("%s ", aResponsible->String().Data());
748                         }
749                         result += "\n";
750                 }
751
752                 result += Form("\tStrict run ordering: %s \n", aHolder->StrictRunOrder() ? "YES" : "NO");
753                 if(aHolder->SkipDCSQuery())
754                 {
755                         result += "\n";
756                         continue;
757                 }
758                 result += Form("\tAmanda server: %s:%d \n", aHolder->GetDCSHost(), aHolder->GetDCSPort());
759
760                 const TObjArray* aliases = aHolder->GetDCSAliases();
761                 if (aliases->GetEntries() != 0)
762                 {
763                         result += "\tDCS Aliases: ";
764                         TIter it(aliases);
765                         TObjString* anAlias;
766                         while ((anAlias = (TObjString*) it.Next()))
767                         {
768                                 result += Form("%s ", anAlias->String().Data());
769                         }
770                         result += "\n";
771                 }
772
773                 const TObjArray* dataPoints = aHolder->GetDCSDataPoints();
774                 if (dataPoints->GetEntries() != 0)
775                 {
776                         result += "\tDCS Data Points: ";
777                         TIter it(dataPoints);
778                         TObjString* aDataPoint;
779                         while ((aDataPoint = (TObjString*) it.Next())) {
780                                 result += Form("%s ", aDataPoint->String().Data());
781                         }
782                                 result += "\n";
783                 }
784                 result += "\n";
785         }
786
787         if(!fIsValid) result += "\n\n********** !!!!! Configuration is INVALID !!!!! **********\n";
788
789         AliInfo(result);
790 }