2993f2b9134062937669a5c97de953b7e96420a5
[u/mrichter/AliRoot.git] / EVE / EveHLT / AliEveHOMERManager.cxx
1 // $Id$
2 // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3 // Author: Jochen Thaeder <thaeder@kip.uni-heidelberg.de>                *
4 //         for The ALICE HLT Project.                                    *
5
6 //-*- Mode: C++ -*-
7
8 /** @file   AliEveHOMERManager.cxx
9     @author Jochen Thaeder
10     @date
11     @brief  Manger for HOMER in offline
12 */
13
14 #if __GNUC__>= 3
15    using namespace std;
16 #endif
17
18 #include "AliEveHOMERManager.h"
19
20 #define EVE_DEBUG 1
21 // -- -- -- -- -- -- -- 
22 #include "AliHLTHOMERLibManager.h"
23 #include "AliHLTHOMERSourceDesc.h"
24 #include "AliHLTHOMERBlockDesc.h"
25 // -- -- -- -- -- -- -- 
26 #include "AliEveHOMERSource.h"
27 // -- -- -- -- -- -- -- 
28 #include "TString.h"
29 #include <TApplication.h>
30 #include "Riostream.h"
31 #include "TXMLAttr.h"
32 #include "TCollection.h"
33 #include "TList.h"
34 #include "TObjString.h"
35 #include "TObjArray.h"
36 // -- -- -- -- -- -- -- 
37 #include "AliLog.h"
38
39 //______________________________________________________________________________
40 //
41 // Manage connections to HLT data-sources.
42
43 ClassImp(AliEveHOMERManager)
44
45 /*
46  * ---------------------------------------------------------------------------------
47  *                            Constructor / Destructor
48  * ---------------------------------------------------------------------------------
49  */
50
51 //##################################################################################
52 AliEveHOMERManager::AliEveHOMERManager( TString xmlFile ) :
53   TEveElementList("AliEveHOMERManager"),
54   fLibManager(new AliHLTHOMERLibManager),
55   fXMLHandler( new AliEveHOMERXMLHandler( xmlFile ) ),
56   fSourceList(NULL),
57   fReader(NULL),
58   fBlockList(NULL),
59   fNBlks(0),
60   fEventID(0),
61   fCurrentBlk(0),
62   fConnected(kFALSE),
63   fStateHasChanged(kTRUE),
64   fSrcList(NULL) {
65   // This Class should handle the communication
66   // from the HLT to AliEVE. The HLT sends data via 
67   // the HOMER interface on several TCP ports of nodes 
68   // in the CERN GPN and DCS network.
69   // All this communication is hidden from the user.
70   // 
71   // Right now, a xml file ( SCC1 ) is used to get the
72   // configuration, this will/ has to change to a proxy
73   // running on dedicated nodes.
74
75 }
76
77 //##################################################################################
78 AliEveHOMERManager::~AliEveHOMERManager() {
79   // The destructor
80
81   if ( fLibManager ) {
82     if ( fReader )
83       fLibManager->DeleteReader(fReader);
84     delete fLibManager;
85     fLibManager = NULL;
86     fReader = NULL;
87   }
88
89   if ( fXMLHandler != NULL )
90     delete fXMLHandler;
91   fXMLHandler = NULL;
92
93   if ( fSourceList != NULL )
94     delete fSourceList;
95   fSourceList = NULL;
96
97   if ( fBlockList != NULL )
98     delete fBlockList;
99   fBlockList = NULL;
100
101  if ( fSrcList != NULL )
102     delete fSrcList;
103   fSrcList = NULL;
104 }
105
106 /*
107  * ---------------------------------------------------------------------------------
108  *                                 Source Handling
109  * ---------------------------------------------------------------------------------
110  */
111
112 //##################################################################################
113 Int_t AliEveHOMERManager::CreateHOMERSourcesList() {
114   // Create Sources List from HOMER-Proxy
115
116   Int_t iResult = 0;
117
118   // -- Initialize sources list
119   DestroyElements();
120   if ( fSourceList != NULL )
121     delete fSourceList;
122   fSourceList = NULL;
123
124   fSourceList = new TList();
125   fSourceList->SetOwner( kTRUE );
126
127   iResult = fXMLHandler->FillSourceList( fSourceList );
128
129   if ( iResult ) {
130     AliWarning( Form("There have been errors, while creating the sources list.") );
131   }
132   else {
133     AliInfo( Form("New sources list created.") );
134
135     // -- New SourceList has been created --> All Sources are new --> State has changed
136     fStateHasChanged = kTRUE;
137  
138     if ( fSrcList ) 
139       delete fSrcList;
140
141     // -- Create new AliEVE sources list 
142     fSrcList = new AliEveHOMERSourceList("HLT Sources");
143     fSrcList->SetManager(this);
144     
145     AddElement(fSrcList);
146     fSrcList->CreateByType();
147   }
148
149   return iResult;
150 }
151
152 //##################################################################################
153 void AliEveHOMERManager::SetSourceState( AliHLTHOMERSourceDesc * source, Bool_t state ) {
154   // Set state of a source
155   // * param source      Pointer to AliHLTHOMERSourceDesc object.
156   // * param state       New (selected/not selected) state.
157   
158   if ( source->IsSelected() != state ) {
159     source->SetState( state );
160     fStateHasChanged = kTRUE;
161   }
162
163   return;
164 }
165
166 /*
167  * ---------------------------------------------------------------------------------
168  *                            Connection Handling
169  * ---------------------------------------------------------------------------------
170  */
171
172 //##################################################################################
173 Int_t AliEveHOMERManager::ConnectHOMER(){
174   // Connect to HOMER sources, out of Readout List, which gets created when state has changed
175   // * return            0 on sucess, "HOMER" errors on error
176
177   Int_t iResult = 0;
178
179   fStateHasChanged = fSrcList->GetSelectedSources();
180
181   // -- Check if already connected and state has not changed
182   if ( fStateHasChanged == kFALSE && IsConnected() ) {
183     AliInfo( Form("No need for reconnection.") );
184     return iResult;
185   }
186
187   // -- If already connected, disconnect before connect
188   if ( IsConnected() )
189     DisconnectHOMER();
190
191   // *** Create the Readoutlist
192
193   UShort_t* sourcePorts = new UShort_t [fSourceList->GetEntries()];
194   const char ** sourceHostnames = new const char* [fSourceList->GetEntries()];
195   UInt_t sourceCount = 0;
196
197   CreateReadoutList( sourceHostnames, sourcePorts, sourceCount );
198
199   if ( sourceCount == 0 ) {
200     AliError(Form("No sources selected, aborting.") );
201     return iResult;
202   }
203
204   // *** Connect to data sources
205
206   if ( !fReader ) {
207     if ( fLibManager )
208       fReader = fLibManager->OpenReader( sourceCount, sourceHostnames, sourcePorts );
209   }
210
211   iResult = fReader->GetConnectionStatus();
212
213   if ( iResult ) {
214     // -- Connection failed
215
216     UInt_t ndx = fReader->GetErrorConnectionNdx();
217
218     if ( ndx < sourceCount ) {
219       AliError( Form("Error : Error establishing connection to TCP source %s:%hu: %s (%d)",
220                      sourceHostnames[ndx], sourcePorts[ndx], strerror(iResult), iResult) );
221     }
222     else {
223       AliError( Form("Error : Error establishing connection to unknown source with index %d: %s (%d)",
224                      ndx, strerror(iResult), iResult) );
225     }
226
227     if ( fReader )
228       fLibManager->DeleteReader( fReader );
229     fReader = NULL;
230
231   }
232   else {
233     // -- Connection ok - set reader
234     fConnected = kTRUE;
235
236     AliInfo( Form("Connection established") );
237   }
238
239   delete[] sourceHostnames;
240   delete[] sourcePorts;
241
242   return iResult;
243 }
244
245 //##################################################################################
246 void AliEveHOMERManager::DisconnectHOMER(){
247   // Disconnect from HOMER sources
248
249   if ( ! IsConnected() )
250     return;
251
252   if ( fReader )
253     fLibManager->DeleteReader( fReader );
254   fReader = NULL;
255
256   fStateHasChanged = kTRUE;
257   fConnected = kFALSE;
258
259   AliInfo( Form("Connection closed") );
260
261   return;
262 }
263
264 //##################################################################################
265 Int_t AliEveHOMERManager::ReconnectHOMER(){
266   // Reconnect from HOMER sources
267   // * return            0 on sucess, "ConnectHOMER()" errors on error
268
269   Int_t iResult = 0;
270
271   if ( IsConnected() )
272     DisconnectHOMER();
273
274   iResult = ConnectHOMER();
275   if ( iResult ) {
276     AliError( Form("Error connecting.") );
277   }
278
279   return iResult;
280 }
281
282 //##################################################################################
283 void AliEveHOMERManager::CreateReadoutList( const char** sourceHostnames, UShort_t *sourcePorts, UInt_t &sourceCount ){
284   //  Create a readout list for Hostname and ports
285   // * param socurceHostnames   Array of selected hostnames
286   // * param socurcePorts       Array of selected ports
287   // * param socurceCount       Number of selected hostname:port
288
289   AliHLTHOMERSourceDesc * source= NULL;
290
291   // -- Read all sources and check if they should be read out
292   TIter next( fSourceList );
293   while ( ( source = (AliHLTHOMERSourceDesc*)next() ) ) {
294
295     if ( ! source->IsSelected() )
296       continue;
297
298     Bool_t exists = kFALSE;
299
300     // -- Loop over existing entries and check if entry is already in readout list
301     for ( UInt_t ii = 0; ii < sourceCount; ii++ ){
302       if ( !strcmp( sourceHostnames[ii], source->GetHostname().Data() ) &&  sourcePorts[ii] == source->GetPort() ) {
303         exists = kTRUE;
304         break;
305       }
306     }
307
308     // -- Add new entires to readout list
309     if ( ! exists ) {
310       sourcePorts[sourceCount] = source->GetPort();
311       sourceHostnames[sourceCount] = source->GetHostname().Data();
312       sourceCount++;
313     }
314
315   } // while ( ( source = (AliHLTHOMERSourceDesc*)next() ) ) {
316
317   fStateHasChanged = kFALSE;
318
319   return;
320 }
321
322 /*
323  * ---------------------------------------------------------------------------------
324  *                            Event Handling
325  * ---------------------------------------------------------------------------------
326  */
327
328 //##################################################################################
329 Int_t AliEveHOMERManager::NextEvent(){
330   // Loads the next Event, after being connected
331   // * return            0 on sucess, "HOMER" errors on error
332
333   Int_t iResult = 0;
334   Int_t iRetryCount = 0;
335
336   if ( !fReader || ! IsConnected() ) {
337     AliWarning( Form( "Not connected yet." ) );
338     return 1;
339   }
340
341   //  fReader->SetEventRequestAdvanceTime( 20000000 /*timeout in us*/ );
342
343   // -- Read next event data and error handling for HOMER (error codes and empty blocks)
344   while( 1 ) {
345
346     iResult = fReader->ReadNextEvent( 40000000 /*timeout in us*/);
347
348     if ( iResult == 111 || iResult == 32 || iResult == 6 ) {
349       Int_t ndx = fReader->GetErrorConnectionNdx();
350       AliError( Form("Error, No Connection to source %d: %s (%d)", 
351                      ndx, strerror(iResult), iResult) );
352       return 2;
353     }
354     else if ( iResult == 110 ) {
355       Int_t ndx = fReader->GetErrorConnectionNdx();
356       AliError( Form("Timout occured, reading event from source %d: %s (%d)", 
357                      ndx, strerror(iResult), iResult) );
358       return 3;
359     }
360     else if ( iResult == 56) {
361       Int_t ndx = fReader->GetErrorConnectionNdx();
362
363       ++iRetryCount;
364
365       if ( iRetryCount >= 20 ) {
366         AliError( Form("Retry Failed: Error reading event from source %d: %s (%d)", 
367                        ndx, strerror(iResult), iResult) );
368         return 4;
369       }
370       else {
371         AliError( Form("Retry: Error reading event from source %d: %s (%d)", 
372                        ndx, strerror(iResult), iResult) );
373         continue;
374       }
375     }
376     else if ( iResult ) {
377       Int_t ndx = fReader->GetErrorConnectionNdx();
378       AliError( Form("General Error reading event from source %d: %s (%d)", 
379                      ndx, strerror(iResult), iResult) );
380       fConnected = kFALSE;
381       return 2;
382     }
383     else {
384       break;
385     }
386   } // while( 1 ) {
387
388   if ( iResult )
389     return iResult;
390   
391   // -- Get blockCnt and eventID
392   fNBlks = (ULong_t) fReader->GetBlockCnt();
393   fEventID = (ULong64_t) fReader->GetEventID();
394   fCurrentBlk = 0;
395
396   AliInfo( Form("Event 0x%016LX (%Lu) with %lu blocks", fEventID, fEventID, fNBlks) );
397
398 #if EVE_DEBUG
399   // Loop for Debug only
400   for ( ULong_t i = 0; i < fNBlks; i++ ) {
401     Char_t tmp1[9], tmp2[5];
402     memset( tmp1, 0, 9 );
403     memset( tmp2, 0, 5 );
404     void *tmp11 = tmp1;
405     ULong64_t* tmp12 = (ULong64_t*)tmp11;
406     *tmp12 = fReader->GetBlockDataType( i );
407     void *tmp21 = tmp2;
408     ULong_t* tmp22 = (ULong_t*)tmp21;
409     *tmp22 = fReader->GetBlockDataOrigin( i );
410     AliInfo( Form("Block %lu length: %lu - type: %s - origin: %s",
411                   i, fReader->GetBlockDataLength( i ), tmp1, tmp2) );
412   } // end for ( ULong_t i = 0; i < fNBlks; i++ ) {
413 #endif
414
415   // -- Create BlockList
416   AliInfo( Form("Create Block List") );
417   iResult = CreateBlockList();
418
419   return iResult;
420 }
421
422 //##################################################################################
423 Int_t AliEveHOMERManager::CreateBlockList() {
424   // Create a TList of blocks, which have been readout
425
426
427   Int_t iResult = 0;
428 #if 0
429   // -- Initialize block list
430   if ( fBlockList != NULL )
431     delete fBlockList;
432   fBlockList = NULL;
433
434   fBlockList = new TList();
435   fBlockList->SetOwner( kTRUE );
436
437   void* iter = GetFirstBlk();
438
439   // -- Fill block list
440   while ( iter != NULL ){
441
442     // -- Create new block
443     AliHLTHOMERBlockDesc * block = new AliHLTHOMERBlockDesc( GetBlk(), GetBlkSize(), GetBlkOrigin(),
444                                                              GetBlkType(), GetBlkSpecification() );
445
446     // -- Check sources list if block is requested
447     if ( CheckIfRequested( block ) )
448       fBlockList->Add( block );
449     else {
450       //The Following 2 line commented out and the previous is added.
451       //       delete block;
452       //       block = NULL;
453       fBlockList->Add( block );
454     }
455     iter = GetNextBlk();
456
457   } // while ( iter != NULL ){
458 #endif
459   return iResult;
460 }
461
462 /*
463  * ---------------------------------------------------------------------------------
464  *                            BlockHandling
465  * ---------------------------------------------------------------------------------
466  */
467
468 //##################################################################################
469 void* AliEveHOMERManager::GetBlk( Int_t ndx ) {
470   // Get pointer to current block in current event
471   // * param ndx        Block index
472   // * return           returns pointer to blk, NULL if no block present
473    
474   void* data = NULL;
475
476   if ( !fReader || ! IsConnected() ) {
477     AliError( Form("Not connected yet.") );
478   }
479   else {
480     if ( ( ndx ) < (Int_t) fNBlks )
481       data = (void*) fReader->GetBlockData( ndx );
482   }
483
484   return data;
485 }
486
487 //##################################################################################
488 ULong_t AliEveHOMERManager::GetBlkSize( Int_t ndx ) {
489   // Get size of block ndx
490   // * param ndx        Block index
491   // * return           returns pointer to blk, 0 if no block present
492    
493   ULong_t length = 0;
494
495   if ( !fReader || ! IsConnected() ) {
496     AliError( Form("Not connected yet.") );
497   }
498   else {
499     if ( ( ndx ) < (Int_t) fNBlks )
500       length = (ULong_t) fReader->GetBlockDataLength( ndx );
501   }
502
503   return length;
504 }
505
506 //##################################################################################
507 TString AliEveHOMERManager::GetBlkOrigin( Int_t ndx ) {
508   // Get origin of block ndx
509   // * param ndx        Block index
510   // * return           origin of block
511
512   TString origin = "";
513
514   // -- Check for Connection
515   if ( !fReader || ! IsConnected() ) {
516     AliError( Form("Not connected yet.") );
517     return origin;
518   }
519
520   // -- Check block index
521   if ( ( ndx ) >= (Int_t) fNBlks ) {
522     AliError( Form("Block index %d out of range.", ndx ) );
523     return origin;
524   }
525
526   // -- Get origin
527   union{
528     UInt_t data;
529     Char_t array[4];
530   } reverseOrigin;
531
532   reverseOrigin.data = (UInt_t) fReader->GetBlockDataOrigin( ndx );
533
534   // -- Reverse the order
535   for (Int_t ii = 3; ii >= 0; ii-- )
536     if ( reverseOrigin.array[ii] != ' ')
537       origin.Append( reverseOrigin.array[ii] );
538
539   return origin;
540 }
541
542 //##################################################################################
543 TString AliEveHOMERManager::GetBlkType( Int_t ndx ) {
544   // Get type of block ndx
545   // * param ndx        Block index
546   // * return           type of block
547
548   TString type = "";
549
550   // -- Check for Connection
551   if ( !fReader || ! IsConnected() ) {
552     AliError( Form("Not connected yet.") );
553     return type;
554   }
555
556   // -- Check blockk index
557   if ( ( ndx ) >= (Int_t) fNBlks ) {
558     AliError( Form("Block index %d out of range.", ndx ) );
559     return type;
560   }
561
562   // -- Get type
563   union{
564     ULong64_t data;
565     Char_t array[8];
566   } reverseType;
567
568   reverseType.data = (ULong64_t) fReader->GetBlockDataType( ndx );
569
570   // -- Reverse the order
571   for (Int_t ii = 7; ii >= 0; ii-- )
572     if ( reverseType.array[ii] != ' ')
573       type.Append( reverseType.array[ii] );
574
575   return type;
576 }
577
578 //##################################################################################
579 ULong_t AliEveHOMERManager::GetBlkSpecification( Int_t ndx ) {
580   // Get specification of block ndx
581   // * param ndx        Block index
582   // * return           specification of block
583
584   ULong_t spec = 0;
585
586   // -- Check for Connection
587   if ( !fReader || ! IsConnected() ) {
588     AliError( Form("Not connected yet.") );
589     return spec;
590   }
591
592   // -- Check blockk index
593   if ( ( ndx ) >= (Int_t) fNBlks ) {
594     AliError( Form("Block index %d out of range.", ndx ) );
595     return spec;
596   }
597
598   spec = (ULong_t) fReader->GetBlockDataSpec( ndx );
599
600   return spec;
601 }
602
603 //##################################################################################
604 Bool_t AliEveHOMERManager::CheckIfRequested( AliHLTHOMERBlockDesc */* block*/ ) {
605   // Checks if current Block should was requested
606   // * return           returns kTRUE, if block should was requested
607
608   Bool_t requested = kFALSE;
609 #if 0
610   AliHLTHOMERSourceDesc * source= NULL;
611
612   // -- Read all sources and check if they should be read out
613   TIter next( fSourceList );
614   while ( ( source = (AliHLTHOMERSourceDesc*)next() ) ) {
615     
616     if ( ! source->IsSelected() )
617       continue;
618
619     if ( !( block->GetDetector().CompareTo( "*** " ) && block->GetDetector().CompareTo( "***" ) ) ) {
620       // if not any detector
621       if ( source->GetDetector().CompareTo( block->GetDetector() ) )
622         continue;
623     }
624
625     if ( ! ( block->GetDataType().CompareTo( "******* " ) && block->GetDataType().CompareTo( "******* " ) ) ) {
626       if ( source->GetDataType().CompareTo( block->GetDataType() ) )
627         continue;
628     }
629
630     if ( ! block->HasSubDetectorRange() ) {
631       if ( source->GetSubDetector().Atoi() != block->GetSubDetector().Atoi() )
632         continue;
633
634       if ( ! block->HasSubSubDetectorRange() ) {
635
636         if ( source->GetSubSubDetector().Atoi() != block->GetSubSubDetector().Atoi() )
637           continue;
638
639       } // if ( ! block->HasSubSubDetectorRange ) {
640     } //  if ( ! block->HasSubDetectorRange ) {
641
642     requested = kTRUE;
643     break;
644
645   } // while ( ( source = (AliHLTHOMERSourceDesc*)next() ) ) {
646   
647 #if EVE_DEBUG
648
649   if ( block->GetDataType().CompareTo("CLUSTERS") ) {
650   if ( requested ) {
651     AliError( Form("Block requested : %s - %s : %s/%s -> %s ", block->GetDetector().Data(), block->GetDataType().Data(),
652                    block->GetSubDetector().Data(), block->GetSubSubDetector().Data(), block->GetClassName().Data() ) );
653   }
654   else {
655     AliError( Form("Block NOT requested : %s - %s : %s/%s -> %s ", block->GetDetector().Data(), block->GetDataType().Data(),
656                    block->GetSubDetector().Data(), block->GetSubSubDetector().Data(), block->GetClassName().Data() ) );
657   }
658
659   }
660 #endif
661 #endif
662   return requested;
663 }
664