* Added new Handler Classes for HOMER Proxy
[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   fProxyHandler(NULL),
55   fReader(NULL),
56   fSourceList(NULL),
57   fBlockList(NULL),
58   fNBlks(0),
59   fEventID(0),
60   fCurrentBlk(0),
61   fConnected(kFALSE),
62   fStateHasChanged(kTRUE) {
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("Initialize of ProxyHandler failed.");
109   }
110   else {
111     iResult = -1;
112     HLTError("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 ) {
139     HLTWarning("There have been errors, while creating the sources list.");
140   }
141   else {
142     HLTInfo("New sources list created.");
143
144     // -- New SourceList has been created 
145     // --> All Sources are new --> State has changed
146     fStateHasChanged = kTRUE;
147   }
148
149   return iResult;
150 }
151
152 //##################################################################################
153 void AliHLTHOMERManager::SetSourceState( AliHLTHOMERSourceDesc * source, Bool_t state ) {
154   // see header file for class documentation
155
156   if ( source->IsSelected() != state ) {
157     source->SetState( state );
158     fStateHasChanged = kTRUE;
159   }
160
161   return;
162 }
163
164 /*
165  * ---------------------------------------------------------------------------------
166  *                         Connection Handling -oublic
167  * ---------------------------------------------------------------------------------
168  */
169
170 //##################################################################################
171 Int_t AliHLTHOMERManager::ConnectHOMER(){
172   // see header file for class documentation
173
174   Int_t iResult = 0;
175
176   // -- Check if already connected and state has not changed
177   if ( fStateHasChanged == kFALSE && IsConnected() ) {
178     HLTInfo("No need for reconnection.");
179     return iResult;
180   }
181
182   // -- If already connected, disconnect before connect
183   if ( IsConnected() )
184     DisconnectHOMER();
185
186   // -- Create the Readoutlist
187   UShort_t* sourcePorts = new UShort_t [fSourceList->GetEntries()];
188   const char ** sourceHostnames = new const char* [fSourceList->GetEntries()];
189   UInt_t sourceCount = 0;
190
191   CreateReadoutList( sourceHostnames, sourcePorts, sourceCount );
192   if ( sourceCount == 0 ) {
193     HLTError("No sources selected, aborting.");
194     return -1;
195   }
196
197   // *** Connect to data sources
198   if ( !fReader && fLibManager )
199     fReader = fLibManager->OpenReader( sourceCount, sourceHostnames, sourcePorts );
200   else {
201     HLTError("No LibManager present.");
202     return -2;
203   }
204     
205   iResult = fReader->GetConnectionStatus();
206   if ( iResult ) {
207     // -- Connection failed
208
209     UInt_t ndx = fReader->GetErrorConnectionNdx();
210
211     if ( ndx < sourceCount ) {
212       HLTError("Error establishing connection to TCP source %s:%hu: %s (%d)",
213                sourceHostnames[ndx], sourcePorts[ndx], strerror(iResult), iResult);
214     }
215     else {
216       HLTError("Error establishing connection to unknown source with index %d: %s (%d)",
217                ndx, strerror(iResult), iResult);
218     }
219
220     if ( fReader )
221       fLibManager->DeleteReader( fReader );
222     fReader = NULL;
223   }
224   else {
225     // -- Connection ok - set reader
226     fConnected = kTRUE;
227
228     HLTInfo("Connection established.");
229   }
230
231   delete[] sourceHostnames;
232   delete[] sourcePorts;
233
234   return iResult;
235 }
236
237 //##################################################################################
238 void AliHLTHOMERManager::DisconnectHOMER(){
239   // see header file for class documentation
240
241   if ( ! IsConnected() )
242     return;
243
244   if ( fReader )
245     fLibManager->DeleteReader( fReader );
246   fReader = NULL;
247
248   fStateHasChanged = kTRUE;
249   fConnected = kFALSE;
250
251   HLTInfo("Connection closed.");
252
253   return;
254 }
255
256 //##################################################################################
257 Int_t AliHLTHOMERManager::ReconnectHOMER(){
258   // see header file for class documentation
259   
260   Int_t iResult = 0;
261
262   if ( IsConnected() )
263     DisconnectHOMER();
264
265   iResult = ConnectHOMER();
266   if ( iResult ) {
267     HLTError("Error reconnecting.");
268   }
269
270   return iResult;
271 }
272
273 /*
274  * ---------------------------------------------------------------------------------
275  *                            Event Handling - public
276  * ---------------------------------------------------------------------------------
277  */
278
279
280 //##################################################################################
281 Int_t AliHLTHOMERManager::NextEvent(){
282   // see header file for class documentation
283
284   Int_t iResult = 0;
285   Int_t iRetryCount = 0;
286
287   if ( !fReader || ! IsConnected() ) {
288     HLTWarning( "Not connected yet." );
289     return -1;
290   }
291
292   //  fReader->SetEventRequestAdvanceTime( 20000000 /*timeout in us*/ );
293
294   // -- Read next event data and error handling for HOMER (error codes and empty blocks)
295   while( 1 ) {
296     
297     iResult = fReader->ReadNextEvent( 40000000 /*timeout in us*/);
298
299     if ( iResult == 111 || iResult == 32 || iResult == 6 ) {
300       HLTError("No Connection to source %d: %s (%d)", 
301                fReader->GetErrorConnectionNdx(), strerror(iResult), iResult);
302       return -iResult;
303     }
304     else if ( iResult == 110 ) {
305       HLTError("Timout occured, reading event from source %d: %s (%d)", 
306                fReader->GetErrorConnectionNdx(), strerror(iResult), iResult);
307       return -iResult;
308     }
309     else if ( iResult == 56) {
310       ++iRetryCount;
311
312       if ( iRetryCount >= 20 ) {
313         HLTError("Retry Failed: Error reading event from source %d: %s (%d)", 
314                  fReader->GetErrorConnectionNdx(), strerror(iResult), iResult);
315         return -iResult;
316       }
317       else {
318         HLTError("Retry: Error reading event from source %d: %s (%d)", 
319                  fReader->GetErrorConnectionNdx(), strerror(iResult), iResult);
320         continue;
321       }
322     }
323     else if ( iResult ) {
324       HLTError("General Error reading event from source %d: %s (%d)", 
325                fReader->GetErrorConnectionNdx(), strerror(iResult), iResult);
326       fConnected = kFALSE;
327       return -iResult;
328     }
329     else {
330       break;
331     }
332   } // while( 1 ) {
333
334   // -- Get blockCnt and eventID
335   fNBlks = static_cast<ULong_t>(fReader->GetBlockCnt());
336   fEventID = static_cast<ULong64_t>(fReader->GetEventID());
337   fCurrentBlk = 0;
338
339   HLTInfo("Event 0x%016LX (%Lu) with %lu blocks", fEventID, fEventID, fNBlks);
340
341 #if EVE_DEBUG
342   // Loop for Debug only
343   for ( ULong_t ii = 0; ii < fNBlks; ii++ ) {
344     Char_t tmp1[9], tmp2[5];
345     memset( tmp1, 0, 9 );
346     memset( tmp2, 0, 5 );
347     void *tmp11 = tmp1;
348     ULong64_t* tmp12 = static_cast<ULong64_t*>(tmp11);
349     *tmp12 = fReader->GetBlockDataType( ii );
350     void *tmp21 = tmp2;
351     ULong_t* tmp22 = static_cast<ULong_t*>(tmp21);
352     *tmp22 = fReader->GetBlockDataOrigin( ii );
353     HLTInfo("Block %lu length: %lu - type: %s - origin: %s",
354             ii, fReader->GetBlockDataLength( ii ), tmp1, tmp2);
355   } // end for ( ULong_t ii = 0; ii < fNBlks; ii++ ) {
356 #endif
357
358   // -- Create BlockList
359   HLTInfo("Create Block List");
360   CreateBlockList();
361
362   return iResult;
363 }
364
365 /*
366  * ---------------------------------------------------------------------------------
367  *                            Connection Handling - private
368  * ---------------------------------------------------------------------------------
369  */
370
371 //##################################################################################
372 void AliHLTHOMERManager::CreateReadoutList( const char** sourceHostnames, 
373                                             UShort_t *sourcePorts, UInt_t &sourceCount ){
374   // see header file for class documentation
375
376   AliHLTHOMERSourceDesc * source= NULL;
377
378   // -- Read all sources and check if they should be read out
379   TIter next( fSourceList );
380   while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
381
382     if ( ! source->IsSelected() )
383       continue;
384     
385     Bool_t exists = kFALSE;
386     
387     // -- Loop over existing entries and check if entry is already in readout list
388     for ( UInt_t ii = 0; ii < sourceCount; ii++ ){
389       if ( !strcmp( sourceHostnames[ii], source->GetHostname().Data() ) 
390            && sourcePorts[ii] == source->GetPort() ) {
391         exists = kTRUE;
392         break;
393       }
394     }
395
396     // -- Add new entires to readout list
397     if ( ! exists ) {
398       sourcePorts[sourceCount] = source->GetPort();
399       sourceHostnames[sourceCount] = source->GetHostname().Data();
400       sourceCount++;
401     }
402
403   } // while ( ( source = (AliHLTHOMERSourceDesc*)next() ) ) {
404
405   fStateHasChanged = kFALSE;
406
407   return;
408 }
409
410 /*
411  * ---------------------------------------------------------------------------------
412  *                            Event Handling
413  * ---------------------------------------------------------------------------------
414  */
415
416
417 //##################################################################################
418 void AliHLTHOMERManager::CreateBlockList() {
419   // see header file for class documentation
420
421   // -- Initialize block list
422   if ( fBlockList != NULL )
423     delete fBlockList;
424   fBlockList = NULL;
425
426   fBlockList = new TList();
427   fBlockList->SetOwner(kTRUE);
428
429   GetFirstBlk();
430
431   // -- Fill block list
432   do {
433
434     // -- Create new block
435     AliHLTHOMERBlockDesc * block = new AliHLTHOMERBlockDesc();
436     block->SetBlock( GetBlk(), GetBlkSize(), GetBlkOrigin(),
437                      GetBlkType(), GetBlkSpecification() );
438     
439     // -- Check sources list if block is requested
440     if ( CheckIfRequested( block ) )
441       fBlockList->Add( block );
442     else {
443       delete block;
444       block = NULL;
445     }
446  
447   } while( GetNextBlk() );
448     
449   return;
450 }
451
452 /*
453  * ---------------------------------------------------------------------------------
454  *                            BlockHandling
455  * ---------------------------------------------------------------------------------
456  */
457
458 //##################################################################################
459 void* AliHLTHOMERManager::GetBlk( Int_t ndx ) {
460   // see header file for class documentation
461   // Get pointer to current block in current event
462    
463   if ( !fReader || !IsConnected() ) {
464     HLTError("Not connected yet.");
465     return NULL;
466   }
467   if ( ndx < static_cast<Int_t>(fNBlks) )
468     return  const_cast<void*> (fReader->GetBlockData(ndx));
469   else
470     return NULL;
471 }
472
473 //##################################################################################
474 ULong_t AliHLTHOMERManager::GetBlkSize( Int_t ndx ) {
475   // see header file for class documentation
476    
477   if ( !fReader || !IsConnected() ) {
478     HLTError("Not connected yet.");
479     return 0;
480   }
481   
482   if ( ndx < static_cast<Int_t>(fNBlks) )
483     return static_cast<ULong_t> (fReader->GetBlockDataLength(ndx));
484   else
485     return 0;
486 }
487
488 //##################################################################################
489 TString AliHLTHOMERManager::GetBlkOrigin( Int_t ndx ) {
490   // see header file for class documentation
491
492   TString origin = "";
493
494   // -- Check for Connection
495   if ( !fReader || ! IsConnected() ) {
496     HLTError("Not connected yet.");
497     return origin;
498   }
499
500   // -- Check block index
501   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
502     HLTError("Block index %d out of range.", ndx );
503     return origin;
504   }
505
506   // -- Get origin
507   union{
508     UInt_t data;
509     Char_t array[4];
510   } reverseOrigin;
511
512   reverseOrigin.data = static_cast<UInt_t>(fReader->GetBlockDataOrigin(ndx));
513
514   // -- Reverse the order
515   for (Int_t ii = 3; ii >= 0; ii-- )
516     if ( reverseOrigin.array[ii] != ' ')
517       origin.Append( reverseOrigin.array[ii] );
518
519   origin.Remove( TString::kTrailing, ' ' );
520
521   return origin;
522 }
523
524 //##################################################################################
525 TString AliHLTHOMERManager::GetBlkType( Int_t ndx ) {
526   // see header file for class documentation
527
528   TString type = "";
529
530   // -- Check for Connection
531   if ( !fReader || ! IsConnected() ) {
532     HLTError("Not connected yet.");
533     return type;
534   }
535
536   // -- Check block index
537   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
538     HLTError("Block index %d out of range.", ndx );
539     return type;
540   }
541
542   // -- Get type
543   union{
544     ULong64_t data;
545     Char_t array[8];
546   } reverseType;
547
548   reverseType.data = static_cast<ULong64_t> (fReader->GetBlockDataType(ndx));
549
550   // -- Reverse the order
551   for (Int_t ii = 7; ii >= 0; ii-- )
552     if ( reverseType.array[ii] != ' ')
553       type.Append( reverseType.array[ii] );
554   
555   type.Remove( TString::kTrailing, ' ' );
556
557   return type;
558 }
559
560 //##################################################################################
561 ULong_t AliHLTHOMERManager::GetBlkSpecification( Int_t ndx ) {
562   // see header file for class documentation
563
564   // -- Check for Connection
565   if ( !fReader || ! IsConnected() ) {
566     HLTError("Not connected yet.");
567     return 0;
568   }
569
570   // -- Check block index
571   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
572     HLTError("Block index %d out of range.", ndx );
573     return 0;
574   }
575
576   return static_cast<ULong_t>(fReader->GetBlockDataSpec(ndx));
577 }
578
579 //##################################################################################
580 Bool_t AliHLTHOMERManager::CheckIfRequested( AliHLTHOMERBlockDesc * block ) {
581   // see header file for class documentation
582
583   Bool_t requested = kFALSE;
584
585   AliHLTHOMERSourceDesc * source= NULL;
586
587   // -- Read all sources and check if they should be read out
588   TIter next( fSourceList );
589   while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
590     
591     // -- Check if source is selected
592     if ( ! source->IsSelected() )
593       continue;
594
595     // -- Check if detector matches
596     if ( source->GetSourceName().CompareTo( block->GetBlockName() ) )
597       continue;
598
599     requested = kTRUE;
600     break;
601
602   } // while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
603   
604 #if EVE_DEBUG
605   if ( requested ) {
606     HLTInfo ("Block requested : %s", block->GetBlockName().Data()); 
607   }
608   else {
609     HLTInfo("Block NOT requested : %s", block->GetBlockName().Data()); 
610   }
611 #endif
612
613   return requested;
614 }
615