Minor bugfixes and extensions for the onlineDiplay Interface
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTHOMERManager.cxx
1 //-*- Mode: C++ -*-
2 // $Id: AliHLTHOMERManager.cxx  $
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Jochen Thaeder <thaeder@kip.uni-heidelberg.de>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /** @file   AliHLTHOMERManager.cxx
20     @author Jochen Thaeder
21     @date
22     @brief  Manger for HOMER in aliroot
23 */
24
25 // see header file for class documentation
26 // or
27 // refer to README to build package
28 // or
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
30
31 #if __GNUC__>= 3
32    using namespace std;
33 #endif
34
35 #define EVE_DEBUG 1
36
37 #include "AliHLTHOMERManager.h"
38 // -- -- -- -- -- -- -- 
39 #include "AliHLTHOMERLibManager.h"
40 #include "AliHLTHOMERSourceDesc.h"
41 #include "AliHLTHOMERBlockDesc.h"
42 // -- -- -- -- -- -- -- 
43 ClassImp(AliHLTHOMERManager)
44
45 /*
46  * ---------------------------------------------------------------------------------
47  *                            Constructor / Destructor
48  * ---------------------------------------------------------------------------------
49  */
50
51 //##################################################################################
52   AliHLTHOMERManager::AliHLTHOMERManager() :
53   fLibManager(new AliHLTHOMERLibManager),
54   fStateHasChanged(kTRUE),
55   fProxyHandler(NULL),
56   fReader(NULL),
57   fSourceList(NULL),
58   fBlockList(NULL),
59   fNBlks(0),
60   fEventID(0),
61   fCurrentBlk(0),
62   fConnected(kFALSE) {
63   // see header file for class documentation
64   // or
65   // refer to README to build package
66   // or
67   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
68
69 }
70
71 //##################################################################################
72 AliHLTHOMERManager::~AliHLTHOMERManager() {
73   // see header file for class documentation
74
75   if ( fLibManager ) {
76     if ( fReader )
77       fLibManager->DeleteReader(fReader);
78     delete fLibManager;
79     fLibManager = NULL;
80     fReader = NULL;
81   }
82
83   if ( fProxyHandler != NULL )
84     delete fProxyHandler;
85   fProxyHandler = NULL;
86
87   if ( fSourceList != NULL )
88     delete fSourceList;
89   fSourceList = NULL;
90
91   if ( fBlockList != NULL )
92     delete fBlockList;
93   fBlockList = NULL;
94 }
95
96 //##################################################################################
97 Int_t AliHLTHOMERManager::Initialize() {
98   // see header file for class documentation
99
100   Int_t iResult = 0;
101
102   if ( !fProxyHandler )
103     fProxyHandler = new AliHLTHOMERProxyHandler();
104   
105   if ( fProxyHandler ) {
106     iResult = fProxyHandler->Initialize();
107     if (iResult)
108       HLTError(Form("Initialize of ProxyHandler failed."));
109   }
110   else {
111     iResult = -1;
112     HLTError(Form("Creating of ProxyHandler failed."));
113   }
114  
115   return iResult;
116 }
117
118 /*
119  * ---------------------------------------------------------------------------------
120  *                                 Source Handling
121  * ---------------------------------------------------------------------------------
122  */
123
124 //##################################################################################
125 Int_t AliHLTHOMERManager::CreateSourcesList() {
126   // see header file for class documentation
127
128   Int_t iResult = 0;
129   
130   if ( fSourceList != NULL )
131     delete fSourceList;
132   fSourceList = NULL;
133
134   fSourceList = new TList();
135   fSourceList->SetOwner( kTRUE );
136
137   iResult = fProxyHandler->FillSourceList( fSourceList );
138   if ( iResult < 0 ) {
139     HLTWarning(Form("There have been errors, while creating the sources list."));
140   }
141   else if ( iResult > 0 ) {
142     HLTWarning(Form("No active services found."));
143   }
144   else if ( fSourceList->IsEmpty() ) {
145     HLTWarning(Form("No active services in the list."));
146     iResult = 2;
147   }
148   else {
149      HLTInfo(Form("New sources list created."));
150
151     // -- New SourceList has been created 
152     // --> All Sources are new --> State has changed
153     fStateHasChanged = kTRUE;
154   }
155
156   return iResult;
157 }
158
159 //##################################################################################
160 void AliHLTHOMERManager::SetSourceState( AliHLTHOMERSourceDesc * source, Bool_t state ) {
161   // see header file for class documentation
162
163   if ( source->IsSelected() != state ) {
164     source->SetState( state );
165     fStateHasChanged = kTRUE;
166   }
167
168   return;
169 }
170
171 /*
172  * ---------------------------------------------------------------------------------
173  *                         Connection Handling -oublic
174  * ---------------------------------------------------------------------------------
175  */
176
177 //##################################################################################
178 Int_t AliHLTHOMERManager::ConnectHOMER( TString detector ){
179   // see header file for class documentation
180
181   Int_t iResult = 0;
182
183   // -- Check if LibManager is present
184   if ( ! fLibManager ) {
185     HLTError(Form("No LibManager present."));
186     return -1;
187   }
188   
189   // -- Check if already connected and state has not changed
190   if ( fStateHasChanged == kFALSE && IsConnected() ) {
191     HLTInfo(Form("No need for reconnection."));
192     return iResult;
193   }
194   
195   // -- If already connected, disconnect before connect
196   if ( IsConnected() )
197     DisconnectHOMER();
198   
199   // -- Create the Readoutlist
200   UShort_t* sourcePorts = new UShort_t [fSourceList->GetEntries()];
201   const char ** sourceHostnames = new const char* [fSourceList->GetEntries()];
202   UInt_t sourceCount = 0;
203   
204   CreateReadoutList( sourceHostnames, sourcePorts, sourceCount, detector );
205   if ( sourceCount == 0 ) {
206     HLTError(Form("No sources selected, aborting."));
207     return -2;
208   }
209
210   // *** Connect to data sources
211   if ( !fReader )
212     fReader = fLibManager->OpenReader( sourceCount, sourceHostnames, sourcePorts );
213   
214   iResult = fReader->GetConnectionStatus();
215   if ( iResult ) {
216     // -- Connection failed
217
218     UInt_t ndx = fReader->GetErrorConnectionNdx();
219
220     if ( ndx < sourceCount ) {
221       HLTError(Form("Error establishing connection to TCP source %s:%hu: %s (%d)",
222                     sourceHostnames[ndx], sourcePorts[ndx], strerror(iResult), iResult));
223     }
224     else {
225       HLTError(Form("Error establishing connection to unknown source with index %d: %s (%d)",
226                     ndx, strerror(iResult), iResult));
227     }
228
229     if ( fReader )
230       fLibManager->DeleteReader( fReader );
231     fReader = NULL;
232   }
233   else {
234     // -- Connection ok - set reader
235     fConnected = kTRUE;
236
237     HLTInfo(Form("Connection established."));
238   }
239
240   delete[] sourceHostnames;
241   delete[] sourcePorts;
242
243   return iResult;
244 }
245
246 //##################################################################################
247 void AliHLTHOMERManager::DisconnectHOMER(){
248   // see header file for class documentation
249
250   if ( ! IsConnected() )
251     return;
252
253   if ( fReader )
254     fLibManager->DeleteReader( fReader );
255   fReader = NULL;
256
257   fStateHasChanged = kTRUE;
258   fConnected = kFALSE;
259
260   HLTInfo(Form("Connection closed."));
261
262   return;
263 }
264
265 //##################################################################################
266 Int_t AliHLTHOMERManager::ReconnectHOMER( TString detector="" ){
267   // see header file for class documentation
268   
269   Int_t iResult = 0;
270
271   if ( IsConnected() )
272     DisconnectHOMER();
273
274   iResult = ConnectHOMER(detector);
275   if ( iResult ) {
276     HLTError(Form("Error reconnecting."));
277   }
278
279   return iResult;
280 }
281
282 /*
283  * ---------------------------------------------------------------------------------
284  *                            Event Handling - public
285  * ---------------------------------------------------------------------------------
286  */
287
288 //##################################################################################
289 Int_t AliHLTHOMERManager::NextEvent(){
290   // see header file for class documentation
291
292   Int_t iResult = 0;
293   Int_t iRetryCount = 0;
294   
295   if ( !IsConnected() || fStateHasChanged )
296     ConnectHOMER();
297   
298   if ( !fReader || !IsConnected() ) {
299     HLTWarning(Form( "Not connected yet." ));
300     return -1;
301   }
302
303   //  fReader->SetEventRequestAdvanceTime( 20000000 /*timeout in us*/ );
304
305   // -- Read next event data and error handling for HOMER (error codes and empty blocks)
306   while( 1 ) {
307     
308     iResult = fReader->ReadNextEvent( 40000000 /*timeout in us*/);
309
310     if ( iResult == 111 || iResult == 32 || iResult == 6 ) {
311       HLTError(Form("No Connection to source %d: %s (%d)", 
312                     fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
313       return -iResult;
314     }
315     else if ( iResult == 110 ) {
316       HLTError(Form("Timeout occured, reading event from source %d: %s (%d)", 
317                     fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
318       return -iResult;
319     }
320     else if ( iResult == 56) {
321       ++iRetryCount;
322
323       if ( iRetryCount >= 20 ) {
324         HLTError(Form("Retry Failed: Error reading event from source %d: %s (%d)", 
325                       fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
326         return -iResult;
327       }
328       else {
329         HLTError(Form("Retry: Error reading event from source %d: %s (%d)", 
330                       fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
331         continue;
332       }
333     }
334     else if ( iResult ) {
335       HLTError(Form("General Error reading event from source %d: %s (%d)", 
336                     fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
337       fConnected = kFALSE;
338       return -iResult;
339     }
340     else {
341       break;
342     }
343   } // while( 1 ) {
344
345   // -- Get blockCnt and eventID
346   fNBlks = static_cast<ULong_t>(fReader->GetBlockCnt());
347   fEventID = static_cast<ULong64_t>(fReader->GetEventID());
348   fCurrentBlk = 0;
349
350   HLTInfo(Form("Event 0x%016LX (%Lu) with %lu blocks", fEventID, fEventID, fNBlks));
351
352 #if EVE_DEBUG
353   // Loop for Debug only
354   for ( ULong_t ii = 0; ii < fNBlks; ii++ ) {
355     Char_t tmp1[9], tmp2[5];
356     memset( tmp1, 0, 9 );
357     memset( tmp2, 0, 5 );
358     void *tmp11 = tmp1;
359     ULong64_t* tmp12 = static_cast<ULong64_t*>(tmp11);
360     *tmp12 = fReader->GetBlockDataType(ii);
361     void *tmp21 = tmp2;
362     ULong_t* tmp22 = static_cast<ULong_t*>(tmp21);
363     *tmp22 = fReader->GetBlockDataOrigin(ii);
364     HLTInfo(Form( "Block %lu length: %lu - type: %s - origin: %s - spec 0x%08X",
365                   ii, fReader->GetBlockDataLength(ii), tmp1, tmp2, fReader->GetBlockDataSpec(ii) ));
366   } // end for ( ULong_t ii = 0; ii < fNBlks; ii++ ) {
367 #endif
368
369   // -- Create BlockList
370   if ( fNBlks > 0 ) {
371     HLTInfo(Form("Create Block List"));
372     CreateBlockList();
373   }
374   else {
375     HLTWarning(Form("Event 0x%016LX (%Lu) with %lu blocks", fEventID, fEventID, fNBlks));
376   }
377     
378   return iResult;
379 }
380
381 /*
382  * ---------------------------------------------------------------------------------
383  *                            Connection Handling - private
384  * ---------------------------------------------------------------------------------
385  */
386
387 //##################################################################################
388 void AliHLTHOMERManager::CreateReadoutList( const char** sourceHostnames, UShort_t *sourcePorts, 
389                                             UInt_t &sourceCount, TString detector ){
390   // see header file for class documentation
391
392   AliHLTHOMERSourceDesc * source= NULL;
393
394   // -- Read all sources and check if they should be read out
395   TIter next( fSourceList );
396   while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
397
398     // -- If detector NO detector name given
399     if ( ! detector.CompareTo("ALL") ) {
400       // -- Continue if source is not selected
401       if ( ! source->IsSelected() )
402         continue;
403     }
404     // -- DetectorName given
405     else {
406       // -- Continue if detector name doesn't match
407       if ( detector.CompareTo(source->GetDetector()) )
408         continue;
409       else
410         source->Select();
411     }
412     
413     Bool_t exists = kFALSE;
414     
415     // -- Loop over existing entries and check if entry is already in readout list
416     for ( UInt_t ii = 0; ii < sourceCount; ii++ ){
417       if ( !strcmp( sourceHostnames[ii], source->GetHostname().Data() ) 
418            && sourcePorts[ii] == source->GetPort() ) {
419         exists = kTRUE;
420         break;
421       }
422     }
423
424     // -- Add new entires to readout list
425     if ( ! exists ) {
426       sourcePorts[sourceCount] = source->GetPort();
427       sourceHostnames[sourceCount] = source->GetHostname().Data();
428       sourceCount++;
429     }
430
431   } // while ( ( source = (AliHLTHOMERSourceDesc*)next() ) ) {
432
433   fStateHasChanged = kFALSE;
434
435   return;
436 }
437
438 /*
439  * ---------------------------------------------------------------------------------
440  *                            Event Handling
441  * ---------------------------------------------------------------------------------
442  */
443
444
445 //##################################################################################
446 void AliHLTHOMERManager::CreateBlockList() {
447   // see header file for class documentation
448
449   // -- Initialize block list
450   if ( fBlockList != NULL )
451     delete fBlockList;
452   fBlockList = NULL;
453
454   fBlockList = new TList();
455   fBlockList->SetOwner(kTRUE);
456
457   GetFirstBlk();
458
459   // -- Fill block list
460   do {
461
462     // -- Create new block
463     AliHLTHOMERBlockDesc * block = new AliHLTHOMERBlockDesc();
464     block->SetBlock( GetBlk(), GetBlkSize(), GetBlkOrigin(),
465                      GetBlkType(), GetBlkSpecification() );
466     
467     // -- Check sources list if block is requested
468     if ( CheckIfRequested( block ) ) {
469       fBlockList->Add( block );
470     }
471     else {
472       // XXX HACK Jochen
473       fBlockList->Add( block );
474       //      delete block;
475       //      block = NULL;
476     }
477  
478   } while( GetNextBlk() );
479     
480   return;
481 }
482
483 /*
484  * ---------------------------------------------------------------------------------
485  *                            BlockHandling
486  * ---------------------------------------------------------------------------------
487  */
488
489 //##################################################################################
490 void* AliHLTHOMERManager::GetBlk( Int_t ndx ) {
491   // see header file for class documentation
492   // Get pointer to current block in current event
493    
494   if ( !fReader || !IsConnected() ) {
495     HLTError(Form("Not connected yet."));
496     return NULL;
497   }
498   if ( ndx < static_cast<Int_t>(fNBlks) )
499     return  const_cast<void*> (fReader->GetBlockData(ndx));
500   else
501     return NULL;
502 }
503
504 //##################################################################################
505 ULong_t AliHLTHOMERManager::GetBlkSize( Int_t ndx ) {
506   // see header file for class documentation
507    
508   if ( !fReader || !IsConnected() ) {
509     HLTError(Form("Not connected yet."));
510     return 0;
511   }
512   
513   if ( ndx < static_cast<Int_t>(fNBlks) )
514     return static_cast<ULong_t> (fReader->GetBlockDataLength(ndx));
515   else
516     return 0;
517 }
518
519 //##################################################################################
520 TString AliHLTHOMERManager::GetBlkOrigin( Int_t ndx ) {
521   // see header file for class documentation
522
523   TString origin = "";
524
525   // -- Check for Connection
526   if ( !fReader || ! IsConnected() ) {
527     HLTError(Form("Not connected yet."));
528     return origin;
529   }
530
531   // -- Check block index
532   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
533     HLTError(Form("Block index %d out of range.", ndx ));
534     return origin;
535   }
536
537   // -- Get origin
538   union{
539     UInt_t data;
540     Char_t array[4];
541   } reverseOrigin;
542
543   reverseOrigin.data = static_cast<UInt_t>(fReader->GetBlockDataOrigin(ndx));
544
545   // -- Reverse the order
546   for (Int_t ii = 3; ii >= 0; ii-- )
547     if ( reverseOrigin.array[ii] != ' ')
548       origin.Append( reverseOrigin.array[ii] );
549
550   origin.Remove( TString::kTrailing, ' ' );
551
552   return origin;
553 }
554
555 //##################################################################################
556 TString AliHLTHOMERManager::GetBlkType( Int_t ndx ) {
557   // see header file for class documentation
558
559   TString type = "";
560
561   // -- Check for Connection
562   if ( !fReader || ! IsConnected() ) {
563     HLTError(Form("Not connected yet."));
564     return type;
565   }
566
567   // -- Check block index
568   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
569     HLTError(Form("Block index %d out of range.", ndx ));
570     return type;
571   }
572
573   // -- Get type
574   union{
575     ULong64_t data;
576     Char_t array[8];
577   } reverseType;
578
579   reverseType.data = static_cast<ULong64_t> (fReader->GetBlockDataType(ndx));
580
581   // -- Reverse the order
582   for (Int_t ii = 7; ii >= 0; ii-- )
583     if ( reverseType.array[ii] != ' ')
584       type.Append( reverseType.array[ii] );
585   
586   type.Remove( TString::kTrailing, ' ' );
587
588   return type;
589 }
590
591 //##################################################################################
592 ULong_t AliHLTHOMERManager::GetBlkSpecification( Int_t ndx ) {
593   // see header file for class documentation
594
595   // -- Check for Connection
596   if ( !fReader || ! IsConnected() ) {
597     HLTError(Form("Not connected yet."));
598     return 0;
599   }
600
601   // -- Check block index
602   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
603     HLTError(Form("Block index %d out of range.", ndx ));
604     return 0;
605   }
606
607   return static_cast<ULong_t>(fReader->GetBlockDataSpec(ndx));
608 }
609
610 //##################################################################################
611 Bool_t AliHLTHOMERManager::CheckIfRequested( AliHLTHOMERBlockDesc * block ) {
612   // see header file for class documentation
613
614   Bool_t requested = kFALSE;
615
616   AliHLTHOMERSourceDesc * source= NULL;
617
618   // -- Read all sources and check if they should be read out
619   TIter next( fSourceList );
620   while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
621     
622     // -- Check if source is selected
623     if ( ! source->IsSelected() )
624       continue;
625     
626     // -- Check if detector matches
627     if ( source->GetSourceName().CompareTo( block->GetBlockName() ) )
628       continue;
629
630     requested = kTRUE;
631     break;
632
633   } // while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
634   
635 #if EVE_DEBUG
636   if ( requested ) {
637     HLTInfo(Form("Block requested : %s", block->GetBlockName().Data())); 
638   }
639   else {
640     HLTInfo(Form("Block NOT requested : %s", block->GetBlockName().Data())); 
641   }
642 #endif
643
644   return requested;
645 }
646