* AliHLTHOMERBlockDesc holds now a copy of the data
[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 0
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   fNBlks(0),
59   fEventID(),
60   fCurrentBlk(0),
61   fEventBuffer(NULL),
62   fBufferTopIdx(-1),
63   fBufferLowIdx(-1),
64   fCurrentBufferIdx(-1),
65   fNavigateBufferIdx(-1),
66   fConnected(kFALSE) {
67   // see header file for class documentation
68   // or
69   // refer to README to build package
70   // or
71   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
72
73 }
74
75 //##################################################################################
76 AliHLTHOMERManager::~AliHLTHOMERManager() {
77   // see header file for class documentation
78
79   if ( fLibManager ) {
80     if ( fReader )
81       fLibManager->DeleteReader(fReader);
82     delete fLibManager;
83     fLibManager = NULL;
84     fReader = NULL;
85   }
86
87   if ( fProxyHandler != NULL )
88     delete fProxyHandler;
89   fProxyHandler = NULL;
90
91   if ( fSourceList != NULL )
92     delete fSourceList;
93   fSourceList = NULL;
94
95   if ( fEventBuffer ) {
96     fEventBuffer->Clear();
97     delete fEventBuffer;
98   }
99
100 }
101
102 //##################################################################################
103 Int_t AliHLTHOMERManager::Initialize() {
104   // see header file for class documentation
105
106   Int_t iResult = 0;
107
108   if ( !fProxyHandler )
109     fProxyHandler = new AliHLTHOMERProxyHandler();
110   
111   if ( fProxyHandler ) {
112     iResult = fProxyHandler->Initialize();
113     if (iResult)
114       HLTError(Form("Initialize of ProxyHandler failed."));
115   }
116   else {
117     iResult = -1;
118     HLTError(Form("Creating of ProxyHandler failed."));
119   }
120  
121   // -- Initialize Event Buffer
122   if ( !fEventBuffer ) {
123     fEventBuffer = new TClonesArray( "TList", BUFFERSIZE );
124   }
125
126   for ( Int_t idx; idx < BUFFERSIZE; ++idx ) {
127     new ((*fEventBuffer)[idx]) TList();
128     (reinterpret_cast<TList*>((*fEventBuffer)[idx]))->SetOwner(kTRUE);
129
130     fEventID[idx] = 0;
131   }
132
133   return iResult;
134 }
135
136 /*
137  * ---------------------------------------------------------------------------------
138  *                                 Source Handling
139  * ---------------------------------------------------------------------------------
140  */
141
142 //##################################################################################
143 Int_t AliHLTHOMERManager::CreateSourcesList() {
144   // see header file for class documentation
145
146   Int_t iResult = 0;
147   
148   if ( fSourceList != NULL )
149     delete fSourceList;
150   fSourceList = NULL;
151
152   fSourceList = new TList();
153   fSourceList->SetOwner( kTRUE );
154
155   iResult = fProxyHandler->FillSourceList( fSourceList );
156   if ( iResult < 0 ) {
157     HLTWarning(Form("There have been errors, while creating the sources list."));
158   }
159   else if ( iResult > 0 ) {
160     HLTWarning(Form("No active services found."));
161   }
162   else if ( fSourceList->IsEmpty() ) {
163     HLTWarning(Form("No active services in the list."));
164     iResult = 2;
165   }
166   else {
167      HLTInfo(Form("New sources list created."));
168
169     // -- New SourceList has been created 
170     // --> All Sources are new --> State has changed
171     fStateHasChanged = kTRUE;
172   }
173
174   return iResult;
175 }
176
177 //##################################################################################
178 void AliHLTHOMERManager::SetSourceState( AliHLTHOMERSourceDesc * source, Bool_t state ) {
179   // see header file for class documentation
180
181   if ( source->IsSelected() != state ) {
182     source->SetState( state );
183     fStateHasChanged = kTRUE;
184   }
185
186   return;
187 }
188
189 /*
190  * ---------------------------------------------------------------------------------
191  *                         Connection Handling - public
192  * ---------------------------------------------------------------------------------
193  */
194
195 //##################################################################################
196 Int_t AliHLTHOMERManager::ConnectHOMER( TString detector ){
197   // see header file for class documentation
198
199   Int_t iResult = 0;
200
201   // -- Check if LibManager is present
202   if ( ! fLibManager ) {
203     HLTError(Form("No LibManager present."));
204     return -1;
205   }
206   
207   // -- Check if already connected and state has not changed
208   if ( fStateHasChanged == kFALSE && IsConnected() ) {
209     HLTInfo(Form("No need for reconnection."));
210     return iResult;
211   }
212   
213   // -- If already connected, disconnect before connect
214   if ( IsConnected() )
215     DisconnectHOMER();
216   
217   // -- Create the Readoutlist
218   UShort_t* sourcePorts = new UShort_t [fSourceList->GetEntries()];
219   const char ** sourceHostnames = new const char* [fSourceList->GetEntries()];
220   UInt_t sourceCount = 0;
221   
222   CreateReadoutList( sourceHostnames, sourcePorts, sourceCount, detector );
223   if ( sourceCount == 0 ) {
224     HLTError(Form("No sources selected, aborting."));
225     return -2;
226   }
227
228   // *** Connect to data sources
229   if ( !fReader )
230     fReader = fLibManager->OpenReader( sourceCount, sourceHostnames, sourcePorts );
231   
232   iResult = fReader->GetConnectionStatus();
233   if ( iResult ) {
234     // -- Connection failed
235
236     UInt_t ndx = fReader->GetErrorConnectionNdx();
237
238     if ( ndx < sourceCount ) {
239       HLTError(Form("Error establishing connection to TCP source %s:%hu: %s (%d)",
240                     sourceHostnames[ndx], sourcePorts[ndx], strerror(iResult), iResult));
241     }
242     else {
243       HLTError(Form("Error establishing connection to unknown source with index %d: %s (%d)",
244                     ndx, strerror(iResult), iResult));
245     }
246
247     if ( fReader )
248       fLibManager->DeleteReader( fReader );
249     fReader = NULL;
250   }
251   else {
252     // -- Connection ok - set reader
253     fConnected = kTRUE;
254
255     HLTInfo(Form("Connection established."));
256   }
257
258   delete[] sourceHostnames;
259   delete[] sourcePorts;
260
261   return iResult;
262 }
263
264 //##################################################################################
265 void AliHLTHOMERManager::DisconnectHOMER(){
266   // see header file for class documentation
267
268   if ( ! IsConnected() )
269     return;
270
271   if ( fReader )
272     fLibManager->DeleteReader( fReader );
273   fReader = NULL;
274
275   fStateHasChanged = kTRUE;
276   fConnected = kFALSE;
277
278   HLTInfo(Form("Connection closed."));
279
280   return;
281 }
282
283 //##################################################################################
284 Int_t AliHLTHOMERManager::ReconnectHOMER( TString detector="" ){
285   // see header file for class documentation
286   
287   Int_t iResult = 0;
288
289   if ( IsConnected() )
290     DisconnectHOMER();
291
292   iResult = ConnectHOMER(detector);
293   if ( iResult ) {
294     HLTError(Form("Error reconnecting."));
295   }
296
297   return iResult;
298 }
299
300 /*
301  * ---------------------------------------------------------------------------------
302  *                            Event Handling - public
303  * ---------------------------------------------------------------------------------
304  */
305
306 //##################################################################################
307 Int_t AliHLTHOMERManager::NextEvent(){
308   // see header file for class documentation
309
310   Int_t iResult = 0;
311   Int_t iRetryCount = 0;
312   
313   if ( !IsConnected() || fStateHasChanged )
314     ConnectHOMER();
315   
316   if ( !fReader || !IsConnected() ) {
317     HLTWarning(Form( "Not connected yet." ));
318     return -1;
319   }
320
321   //  fReader->SetEventRequestAdvanceTime( 20000000 /*timeout in us*/ );
322
323   // -- Read next event data and error handling for HOMER (error codes and empty blocks)
324   while( 1 ) {
325     
326     iResult = fReader->ReadNextEvent( 40000000 /*timeout in us*/);
327
328     if ( iResult == 111 || iResult == 32 || iResult == 6 ) {
329       HLTError(Form("No Connection to source %d: %s (%d)", 
330                     fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
331       return -iResult;
332     }
333     else if ( iResult == 110 ) {
334       HLTError(Form("Timeout occured, reading event from source %d: %s (%d)", 
335                     fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
336       return -iResult;
337     }
338     else if ( iResult == 56) {
339       ++iRetryCount;
340
341       if ( iRetryCount >= 20 ) {
342         HLTError(Form("Retry Failed: Error reading event from source %d: %s (%d)", 
343                       fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
344         return -iResult;
345       }
346       else {
347         HLTError(Form("Retry: Error reading event from source %d: %s (%d)", 
348                       fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
349         continue;
350       }
351     }
352     else if ( iResult ) {
353       HLTError(Form("General Error reading event from source %d: %s (%d)", 
354                     fReader->GetErrorConnectionNdx(), strerror(iResult), iResult));
355       fConnected = kFALSE;
356       return -iResult;
357     }
358     else {
359       break;
360     }
361   } // while( 1 ) {
362
363   // -- Get blockCnt and eventID
364   fNBlks = static_cast<ULong_t>(fReader->GetBlockCnt());
365   ULong_t eventID = static_cast<ULong64_t>(fReader->GetEventID());  
366   fCurrentBlk = 0;
367
368   HLTInfo(Form("Event 0x%016LX (%Lu) with %lu blocks", eventID,eventID, fNBlks));
369
370 #if EVE_DEBUG
371   // Loop for Debug only
372   for ( ULong_t ii = 0; ii < fNBlks; ii++ ) {
373     Char_t tmp1[9], tmp2[5];
374     memset( tmp1, 0, 9 );
375     memset( tmp2, 0, 5 );
376     void *tmp11 = tmp1;
377     ULong64_t* tmp12 = static_cast<ULong64_t*>(tmp11);
378     *tmp12 = fReader->GetBlockDataType(ii);
379     void *tmp21 = tmp2;
380     ULong_t* tmp22 = static_cast<ULong_t*>(tmp21);
381     *tmp22 = fReader->GetBlockDataOrigin(ii);
382     HLTInfo(Form( "Block %lu length: %lu - type: %s - origin: %s - spec 0x%08X",
383                   ii, fReader->GetBlockDataLength(ii), tmp1, tmp2, fReader->GetBlockDataSpec(ii) ));
384   } // end for ( ULong_t ii = 0; ii < fNBlks; ii++ ) {
385 #endif
386
387   // -- Create BlockList
388   if ( fNBlks > 0 ) {
389     HLTInfo(Form("Add Block List to buffer"));
390     AddBlockListToBuffer();
391   }
392   else {
393     HLTWarning(Form("Event 0x%016LX (%Lu) with %lu blocks", eventID, eventID, fNBlks));
394   }
395     
396   return iResult;
397 }
398
399 /* ---------------------------------------------------------------------------------
400  *                           Buffer Handling - public
401  * ---------------------------------------------------------------------------------
402  */
403
404 //##################################################################################
405 Int_t AliHLTHOMERManager::NavigateEventBufferBack() { 
406   // see header file for class documentation
407
408   // -- reached the end of the buffer
409   if ( fNavigateBufferIdx == fBufferLowIdx )
410     return -1;
411
412   Int_t newIdx = fNavigateBufferIdx - 1;
413   if ( newIdx == -1 )
414     newIdx = BUFFERSIZE-1;
415
416   fCurrentBufferIdx = fNavigateBufferIdx = newIdx;
417
418   return newIdx;
419 }
420
421 //##################################################################################
422 Int_t AliHLTHOMERManager::NavigateEventBufferFwd() {
423   // see header file for class documentation
424
425   // -- reached the top of the buffer
426   if ( fNavigateBufferIdx == fBufferTopIdx )
427     return -1;
428
429   Int_t newIdx = fNavigateBufferIdx + 1;
430   if ( newIdx == BUFFERSIZE )
431     newIdx = 0;
432   
433   fCurrentBufferIdx = fNavigateBufferIdx = newIdx;
434
435   return newIdx;
436 }
437
438  ///////////////////////////////////////////////////////////////////////////////////
439
440 /*
441  * ---------------------------------------------------------------------------------
442  *                            Connection Handling - private
443  * ---------------------------------------------------------------------------------
444  */
445
446 //##################################################################################
447 void AliHLTHOMERManager::CreateReadoutList( const char** sourceHostnames, UShort_t *sourcePorts, 
448                                             UInt_t &sourceCount, TString detector ){
449   // see header file for class documentation
450
451   AliHLTHOMERSourceDesc * source= NULL;
452
453   // -- Read all sources and check if they should be read out
454   TIter next( fSourceList );
455   while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
456
457     // -- If detector NO detector name given
458     if ( ! detector.CompareTo("ALL") ) {
459       // -- Continue if source is not selected
460       if ( ! source->IsSelected() )
461         continue;
462     }
463     // -- DetectorName given
464     else {
465       // -- Continue if detector name doesn't match
466       if ( detector.CompareTo(source->GetDetector()) )
467         continue;
468       else
469         source->Select();
470     }
471     
472     Bool_t exists = kFALSE;
473     
474     // -- Loop over existing entries and check if entry is already in readout list
475     for ( UInt_t ii = 0; ii < sourceCount; ii++ ){
476       if ( !strcmp( sourceHostnames[ii], source->GetHostname().Data() ) 
477            && sourcePorts[ii] == source->GetPort() ) {
478         exists = kTRUE;
479         break;
480       }
481     }
482
483     // -- Add new entires to readout list
484     if ( ! exists ) {
485       sourcePorts[sourceCount] = source->GetPort();
486       sourceHostnames[sourceCount] = source->GetHostname().Data();
487       sourceCount++;
488     }
489
490   } // while ( ( source = (AliHLTHOMERSourceDesc*)next() ) ) {
491
492   fStateHasChanged = kFALSE;
493
494   return;
495 }
496
497 /*
498  * ---------------------------------------------------------------------------------
499  *                          Buffer Handling - private
500  * ---------------------------------------------------------------------------------
501  */
502
503 //##################################################################################
504 void AliHLTHOMERManager::AddBlockListToBuffer() {
505   // see header file for class documentation
506
507   // -- Set Top mark 
508   ++fBufferTopIdx;
509   if ( fBufferTopIdx == BUFFERSIZE )
510     fBufferTopIdx = 0;
511
512   // -- Change the low mark if necessary
513   if ( fBufferLowIdx == -1 )
514     fBufferLowIdx = 0;
515   else if ( fBufferTopIdx == fBufferLowIdx ) {
516     ++fBufferLowIdx;
517     if ( fBufferLowIdx == BUFFERSIZE )
518       fBufferLowIdx = 0;
519   }
520
521   fNavigateBufferIdx = fCurrentBufferIdx = fBufferTopIdx;    
522
523   // -- Fill EventID
524   fEventID[fBufferTopIdx] = static_cast<ULong64_t>(fReader->GetEventID());
525
526   // -- Clear Buffer slot
527   (reinterpret_cast<TList*>((*fEventBuffer)[fBufferTopIdx]))->Clear();
528
529   GetFirstBlk();
530
531   // -- Fill block list
532   do {
533
534     // -- Create new block
535     AliHLTHOMERBlockDesc * block = new AliHLTHOMERBlockDesc();
536     block->SetBlock( GetBlk(), GetBlkSize(), GetBlkOrigin(),
537                      GetBlkType(), GetBlkSpecification() );
538     
539     // -- Check sources list if block is requested
540     if ( CheckIfRequested( block ) ) {
541       (reinterpret_cast<TList*>((*fEventBuffer)[fBufferTopIdx]))->Add( block );
542     }
543     else {
544       // XXX HACK Jochen
545       (reinterpret_cast<TList*>((*fEventBuffer)[fBufferTopIdx]))->Add( block );
546       //      delete block;
547       //      block = NULL;
548     }
549  
550   } while( GetNextBlk() );
551
552   return;
553 }
554
555 //##################################################################################
556 TList* AliHLTHOMERManager::GetBlockListEventBuffer( Int_t idx ) {
557   // see header file for class documentation
558   
559   if ( idx == -1 )
560     return NULL;
561
562   return reinterpret_cast<TList*>((*fEventBuffer)[idx]);
563 }
564
565 /*
566  * ---------------------------------------------------------------------------------
567  *                          Block Handling - private
568  * ---------------------------------------------------------------------------------
569  */
570
571 //##################################################################################
572 void* AliHLTHOMERManager::GetBlk( Int_t ndx ) {
573   // see header file for class documentation
574   // Get pointer to current block in current event
575    
576   if ( !fReader || !IsConnected() ) {
577     HLTError(Form("Not connected yet."));
578     return NULL;
579   }
580   if ( ndx < static_cast<Int_t>(fNBlks) )
581     return  const_cast<void*> (fReader->GetBlockData(ndx));
582   else
583     return NULL;
584 }
585
586 //##################################################################################
587 ULong_t AliHLTHOMERManager::GetBlkSize( Int_t ndx ) {
588   // see header file for class documentation
589    
590   if ( !fReader || !IsConnected() ) {
591     HLTError(Form("Not connected yet."));
592     return 0;
593   }
594   
595   if ( ndx < static_cast<Int_t>(fNBlks) )
596     return static_cast<ULong_t> (fReader->GetBlockDataLength(ndx));
597   else
598     return 0;
599 }
600
601 //##################################################################################
602 TString AliHLTHOMERManager::GetBlkOrigin( Int_t ndx ) {
603   // see header file for class documentation
604
605   TString origin = "";
606
607   // -- Check for Connection
608   if ( !fReader || ! IsConnected() ) {
609     HLTError(Form("Not connected yet."));
610     return origin;
611   }
612
613   // -- Check block index
614   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
615     HLTError(Form("Block index %d out of range.", ndx ));
616     return origin;
617   }
618
619   // -- Get origin
620   union{
621     UInt_t data;
622     Char_t array[4];
623   } reverseOrigin;
624
625   reverseOrigin.data = static_cast<UInt_t>(fReader->GetBlockDataOrigin(ndx));
626
627   // -- Reverse the order
628   for (Int_t ii = 3; ii >= 0; ii-- )
629     if ( reverseOrigin.array[ii] != ' ')
630       origin.Append( reverseOrigin.array[ii] );
631
632   origin.Remove( TString::kTrailing, ' ' );
633
634   return origin;
635 }
636
637 //##################################################################################
638 TString AliHLTHOMERManager::GetBlkType( Int_t ndx ) {
639   // see header file for class documentation
640
641   TString type = "";
642
643   // -- Check for Connection
644   if ( !fReader || ! IsConnected() ) {
645     HLTError(Form("Not connected yet."));
646     return type;
647   }
648
649   // -- Check block index
650   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
651     HLTError(Form("Block index %d out of range.", ndx ));
652     return type;
653   }
654
655   // -- Get type
656   union{
657     ULong64_t data;
658     Char_t array[8];
659   } reverseType;
660
661   reverseType.data = static_cast<ULong64_t> (fReader->GetBlockDataType(ndx));
662
663   // -- Reverse the order
664   for (Int_t ii = 7; ii >= 0; ii-- )
665     if ( reverseType.array[ii] != ' ')
666       type.Append( reverseType.array[ii] );
667   
668   type.Remove( TString::kTrailing, ' ' );
669
670   return type;
671 }
672
673 //##################################################################################
674 ULong_t AliHLTHOMERManager::GetBlkSpecification( Int_t ndx ) {
675   // see header file for class documentation
676
677   // -- Check for Connection
678   if ( !fReader || ! IsConnected() ) {
679     HLTError(Form("Not connected yet."));
680     return 0;
681   }
682
683   // -- Check block index
684   if ( ndx >= static_cast<Int_t>(fNBlks) ) {
685     HLTError(Form("Block index %d out of range.", ndx ));
686     return 0;
687   }
688
689   return static_cast<ULong_t>(fReader->GetBlockDataSpec(ndx));
690 }
691
692 //##################################################################################
693 Bool_t AliHLTHOMERManager::CheckIfRequested( AliHLTHOMERBlockDesc * block ) {
694   // see header file for class documentation
695
696   Bool_t requested = kFALSE;
697
698   AliHLTHOMERSourceDesc * source= NULL;
699
700   // -- Read all sources and check if they should be read out
701   TIter next( fSourceList );
702   while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
703     
704     // -- Check if source is selected
705     if ( ! source->IsSelected() )
706       continue;
707     
708     // -- Check if detector matches
709     if ( source->GetSourceName().CompareTo( block->GetBlockName() ) )
710       continue;
711
712     requested = kTRUE;
713     break;
714
715   } // while ( ( source = dynamic_cast<AliHLTHOMERSourceDesc*>(next()) ) ) {
716   
717 #if EVE_DEBUG
718   if ( requested ) {
719     HLTInfo(Form("Block requested : %s", block->GetBlockName().Data())); 
720   }
721   else {
722     HLTInfo(Form("Block NOT requested : %s", block->GetBlockName().Data())); 
723   }
724 #endif
725
726   return requested;
727 }
728