string.h instead of cstring on Solaris x86
[u/mrichter/AliRoot.git] / HLT / BASE / HOMER / AliHLTHOMERReader.cxx
1 /************************************************************************
2 **
3 **
4 ** This file is property of and copyright by the Technical Computer
5 ** Science Group, Kirchhoff Institute for Physics, Ruprecht-Karls-
6 ** University, Heidelberg, Germany, 2001
7 ** This file has been written by Timm Morten Steinbeck, 
8 ** timm@kip.uni-heidelberg.de
9 **
10 **
11 ** See the file license.txt for details regarding usage, modification,
12 ** distribution and warranty.
13 ** Important: This file is provided without any warranty, including
14 ** fitness for any particular purpose.
15 **
16 **
17 ** Newer versions of this file's package will be made available from 
18 ** http://web.kip.uni-heidelberg.de/Hardwinf/L3/ 
19 ** or the corresponding page of the Heidelberg Alice Level 3 group.
20 **
21 *************************************************************************/
22
23 /*
24 ***************************************************************************
25 **
26 ** $Author$ - Initial Version by Timm Morten Steinbeck
27 **
28 ** $Id$ 
29 **
30 ***************************************************************************
31 */
32
33 /** @file   AliHLTHOMERReader.cxx
34     @author Timm Steinbeck
35     @date   Sep 14 2007
36     @brief  HLT Online Monitoring Environment including ROOT - Reader
37     @note   migrated from PubSub HLT-stable-20070905.141318 (rev 2375)    */
38
39 // see header file for class documentation
40 // or
41 // refer to README to build package
42 // or
43 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
44
45 #include "AliHLTHOMERReader.h"
46 //#include <stdio.h>
47 #ifdef __SUNPRO_CC
48 #include <string.h>
49 #else
50 #include <cstring>
51 #endif
52 #include <cerrno>
53 #include <netdb.h>
54 extern int h_errno;
55 //#include <sys/types.h>
56 //#include <sys/socket.h>
57 //#include <netinet/in.h>
58 //#include <netinet/tcp.h>
59 #include <unistd.h>
60 #include <rpc/types.h>
61 #include <fcntl.h>
62 #include <sys/stat.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #ifdef USE_ROOT
66 #include <Rtypes.h>
67 #endif
68
69
70 #define MOD_BIN "MOD BIN\n"
71 #define MOD_ASC "MOD ASC\n"
72 #define GET_ONE "GET ONE\n"
73 #define GET_ALL "GET ALL\n"
74
75 // MAXHOSTNAMELEN not defined on macosx
76 // 686-apple-darwin9-gcc-4.0.1
77 #ifndef MAXHOSTNAMELEN
78 #define MAXHOSTNAMELEN 64
79 #endif
80
81 #ifdef USE_ROOT
82 ClassImp(AliHLTMonitoringReader);
83 ClassImp(AliHLTHOMERReader);
84 #endif
85
86
87
88
89
90 #ifdef USE_ROOT
91 AliHLTHOMERReader::AliHLTHOMERReader()
92   :
93   fCurrentEventType(~(homer_uint64)0),
94   fCurrentEventID(~(homer_uint64)0),
95   fBlockCnt(0),
96   fMaxBlockCnt(0),
97   fBlocks(NULL),
98   fDataSourceCnt(0),
99   fTCPDataSourceCnt(0),
100   fShmDataSourceCnt(0),
101   fDataSourceMaxCnt(0),
102   fDataSources(NULL),
103   fConnectionStatus(0),
104   fErrorConnection(~(unsigned int)0),
105   fEventRequestAdvanceTime(0)
106     {
107 // Reader implementation of the HOMER interface.
108 // The HLT Monitoring Environment including ROOT is
109 // a native interface to ship out data from the HLT chain.
110 // See pdf document shiped with the package
111 // for class documentation and tutorial.
112     Init();
113     }
114 #endif
115
116
117 AliHLTHOMERReader::AliHLTHOMERReader( const char* hostname, unsigned short port )
118   :
119   AliHLTMonitoringReader(),
120   fCurrentEventType(~(homer_uint64)0),
121   fCurrentEventID(~(homer_uint64)0),
122   fBlockCnt(0),
123   fMaxBlockCnt(0),
124   fBlocks(NULL),
125   fDataSourceCnt(0),
126   fTCPDataSourceCnt(0),
127   fShmDataSourceCnt(0),
128   fDataSourceMaxCnt(0),
129   fDataSources(NULL),
130   fConnectionStatus(0),
131   fErrorConnection(~(unsigned int)0),
132   fEventRequestAdvanceTime(0)
133     {
134 // see header file for class documentation
135 // For reading from a TCP port
136     Init();
137     if ( !AllocDataSources(1) )
138         {
139         fErrorConnection = 0;
140         fConnectionStatus = ENOMEM;
141         return;
142         }
143     fConnectionStatus = AddDataSource( hostname, port, fDataSources[0] );
144     if ( fConnectionStatus )
145         fErrorConnection = 0;
146     else
147         {
148         fDataSourceCnt++;
149         fTCPDataSourceCnt++;
150         fDataSources[0].fNdx = 0;
151         }
152     }
153
154 AliHLTHOMERReader::AliHLTHOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports )
155   :
156   AliHLTMonitoringReader(),
157   fCurrentEventType(~(homer_uint64)0),
158   fCurrentEventID(~(homer_uint64)0),
159   fBlockCnt(0),
160   fMaxBlockCnt(0),
161   fBlocks(NULL),
162   fDataSourceCnt(0),
163   fTCPDataSourceCnt(0),
164   fShmDataSourceCnt(0),
165   fDataSourceMaxCnt(0),
166   fDataSources(NULL),
167   fConnectionStatus(0),
168   fErrorConnection(~(unsigned int)0),
169   fEventRequestAdvanceTime(0)
170     {
171 // see header file for class documentation
172 // For reading from multiple TCP ports
173     Init();
174     if ( !AllocDataSources(tcpCnt) )
175         {
176         fErrorConnection = 0;
177         fConnectionStatus = ENOMEM;
178         return;
179         }
180     for ( unsigned int n = 0; n < tcpCnt; n++, fDataSourceCnt++, fTCPDataSourceCnt++ )
181         {
182         fConnectionStatus = AddDataSource( hostnames[n], ports[n], fDataSources[n] );
183         if ( fConnectionStatus )
184             {
185             fErrorConnection = n;
186             return;
187             }
188         fDataSources[n].fNdx = n;
189         }
190     }
191
192 AliHLTHOMERReader::AliHLTHOMERReader( key_t shmKey, int shmSize )
193   :
194   AliHLTMonitoringReader(),
195   fCurrentEventType(~(homer_uint64)0),
196   fCurrentEventID(~(homer_uint64)0),
197   fBlockCnt(0),
198   fMaxBlockCnt(0),
199   fBlocks(NULL),
200   fDataSourceCnt(0),
201   fTCPDataSourceCnt(0),
202   fShmDataSourceCnt(0),
203   fDataSourceMaxCnt(0),
204   fDataSources(NULL),
205   fConnectionStatus(0),
206   fErrorConnection(~(unsigned int)0),
207   fEventRequestAdvanceTime(0)
208     {
209 // see header file for class documentation
210 // For reading from a System V shared memory segment
211     Init();
212     if ( !AllocDataSources(1) )
213         {
214         fErrorConnection = 0;
215         fConnectionStatus = ENOMEM;
216         return;
217         }
218     fConnectionStatus = AddDataSource( shmKey, shmSize, fDataSources[0] );
219     if ( fConnectionStatus )
220         fErrorConnection = 0;
221     else
222         {
223         fDataSourceCnt++;
224         fShmDataSourceCnt++;
225         fDataSources[0].fNdx = 0;
226         }
227     }
228
229 AliHLTHOMERReader::AliHLTHOMERReader( unsigned int shmCnt, key_t* shmKeys, int* shmSizes )
230   :
231   AliHLTMonitoringReader(),
232   fCurrentEventType(~(homer_uint64)0),
233   fCurrentEventID(~(homer_uint64)0),
234   fBlockCnt(0),
235   fMaxBlockCnt(0),
236   fBlocks(NULL),
237   fDataSourceCnt(0),
238   fTCPDataSourceCnt(0),
239   fShmDataSourceCnt(0),
240   fDataSourceMaxCnt(0),
241   fDataSources(NULL),
242   fConnectionStatus(0),
243   fErrorConnection(~(unsigned int)0),
244   fEventRequestAdvanceTime(0)
245     {
246 // see header file for class documentation
247 // For reading from multiple System V shared memory segments
248     Init();
249     if ( !AllocDataSources(shmCnt) )
250         {
251         fErrorConnection = 0;
252         fConnectionStatus = ENOMEM;
253         return;
254         }
255     for ( unsigned int n = 0; n < shmCnt; n++, fDataSourceCnt++, fShmDataSourceCnt++ )
256         {
257         fConnectionStatus = AddDataSource( shmKeys[n], shmSizes[n], fDataSources[n] );
258         if ( fConnectionStatus )
259             {
260             fErrorConnection = n;
261             return;
262             }
263         fDataSources[n].fNdx = n;
264         }
265     }
266
267 AliHLTHOMERReader::AliHLTHOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports, 
268                           unsigned int shmCnt, key_t* shmKeys, int* shmSizes )
269   :
270   AliHLTMonitoringReader(),
271   fCurrentEventType(~(homer_uint64)0),
272   fCurrentEventID(~(homer_uint64)0),
273   fBlockCnt(0),
274   fMaxBlockCnt(0),
275   fBlocks(NULL),
276   fDataSourceCnt(0),
277   fTCPDataSourceCnt(0),
278   fShmDataSourceCnt(0),
279   fDataSourceMaxCnt(0),
280   fDataSources(NULL),
281   fConnectionStatus(0),
282   fErrorConnection(~(unsigned int)0),
283   fEventRequestAdvanceTime(0)
284     {
285 // see header file for class documentation
286 // For reading from multiple TCP ports and multiple System V shared memory segments
287     Init();
288     if ( !AllocDataSources(tcpCnt+shmCnt) )
289         {
290         fErrorConnection = 0;
291         fConnectionStatus = ENOMEM;
292         return;
293         }
294     for ( unsigned int n = 0; n < tcpCnt; n++, fDataSourceCnt++, fTCPDataSourceCnt++ )
295         {
296         fConnectionStatus = AddDataSource( hostnames[n], ports[n], fDataSources[n] );
297         if ( fConnectionStatus )
298             {
299             fErrorConnection = n;
300             return;
301             }
302         fDataSources[n].fNdx = n;
303         }
304     for ( unsigned int n = 0; n < shmCnt; n++, fDataSourceCnt++, fShmDataSourceCnt++ )
305         {
306         fConnectionStatus = AddDataSource( shmKeys[n], shmSizes[n], fDataSources[tcpCnt+n] );
307         if ( fConnectionStatus )
308             {
309             fErrorConnection = tcpCnt+n;
310             return;
311             }
312         fDataSources[n].fNdx = n;
313         }
314     }
315
316 AliHLTHOMERReader::AliHLTHOMERReader( const void* pBuffer, int size )
317   :
318   AliHLTMonitoringReader(),
319   fCurrentEventType(~(homer_uint64)0),
320   fCurrentEventID(~(homer_uint64)0),
321   fBlockCnt(0),
322   fMaxBlockCnt(0),
323   fBlocks(NULL),
324   fDataSourceCnt(0),
325   fTCPDataSourceCnt(0),
326   fShmDataSourceCnt(0),
327   fDataSourceMaxCnt(0),
328   fDataSources(NULL),
329   fConnectionStatus(0),
330   fErrorConnection(~(unsigned int)0),
331   fEventRequestAdvanceTime(0)
332     {
333 // see header file for class documentation
334 // For reading from a System V shared memory segment
335     Init();
336     if ( !AllocDataSources(1) )
337         {
338         fErrorConnection = 0;
339         fConnectionStatus = ENOMEM;
340         return;
341         }
342     fConnectionStatus = AddDataSource(const_cast<void*>(pBuffer), size, fDataSources[0] );
343     if ( fConnectionStatus )
344         fErrorConnection = 0;
345     else
346         {
347         fDataSourceCnt++;
348         fDataSources[0].fNdx = 0;
349         }
350     }
351
352 AliHLTHOMERReader::~AliHLTHOMERReader()
353     {
354 // see header file for class documentation
355     ReleaseCurrentEvent();
356     FreeDataSources();
357     }
358
359 int  AliHLTHOMERReader::ReadNextEvent()
360     {
361 // see header file for class documentation
362 // Read in the next available event
363     return ReadNextEvent( false, 0 );
364     }
365
366 int AliHLTHOMERReader::ReadNextEvent( unsigned long timeout )
367     {
368 // see header file for class documentation
369 // Read in the next available event
370     return ReadNextEvent( true, timeout );
371     }
372
373 unsigned long AliHLTHOMERReader::GetBlockDataLength( unsigned long ndx ) const
374     {
375 // see header file for class documentation
376 // Return the size (in bytes) of the current event's data
377 // block with the given block index (starting at 0).
378     if ( ndx >= fBlockCnt )
379         return 0;
380     return fBlocks[ndx].fLength;
381     }
382
383 const void* AliHLTHOMERReader::GetBlockData( unsigned long ndx ) const
384     {
385 // see header file for class documentation
386 // Return a pointer to the start of the current event's data
387 // block with the given block index (starting at 0).
388     if ( ndx >= fBlockCnt )
389         return NULL;
390     return fBlocks[ndx].fData;
391     }
392
393 const char* AliHLTHOMERReader::GetBlockSendNodeID( unsigned long ndx ) const
394     {
395 // see header file for class documentation
396 // Return IP address or hostname of node which sent the 
397 // current event's data block with the given block index 
398 // (starting at 0).
399 // For HOMER this is the ID of the node on which the subscriber 
400 // that provided this data runs/ran.
401     if ( ndx >= fBlockCnt )
402         return NULL;
403 #ifdef DEBUG
404     if ( fBlocks[ndx].fSource >= fDataSourceCnt )
405         {
406         fprintf( stderr, "%s:%d: Internal Error: fBlocks[ndx].fSource (%lu) >= fDataSourceCnt (%lu)\n",
407                  __FILE__, __LINE__, fBlocks[ndx].fSource, fDataSourceCnt );
408         return NULL;
409         }
410 #endif
411     return fDataSources[ fBlocks[ndx].fSource ].fHostname;
412     //return fBlocks[ndx].fOriginatingNodeID;
413     }
414
415 homer_uint8 AliHLTHOMERReader::GetBlockByteOrder( unsigned long ndx ) const
416     {
417 // see header file for class documentation
418 // Return byte order of the data stored in the 
419 // current event's data block with the given block index (starting at 0). 
420 //         0 is unknown alignment, 
421 //         1 ist little endian, 
422 //         2 is big endian. */
423     if ( ndx >= fBlockCnt )
424         return 0;
425     //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
426     return *(((homer_uint8*)fBlocks[ndx].fMetaData)+kByteOrderAttribute_8b_Offset);
427     }
428
429 homer_uint8 AliHLTHOMERReader::GetBlockTypeAlignment( unsigned long ndx, homer_uint8 dataType ) const
430     {
431 // see header file for class documentation
432 // Return the alignment (in bytes) of the given datatype 
433 // in the data stored in the current event's data block
434 // with the given block index (starting at 0). 
435 // Possible values for the data type are
436 //         0: homer_uint64
437 //         1: homer_uint32
438 //         2: uin16
439 //         3: homer_uint8
440 //         4: double
441 //         5: float
442     if ( ndx >= fBlockCnt )
443         return 0;
444     if ( dataType > (kFloatAlignment_8b_Offset-kAlignment_8b_StartOffset) )
445         return 0;
446     //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
447     return *(((homer_uint8*)fBlocks[ndx].fMetaData)+kAlignment_8b_StartOffset+dataType);
448     }
449
450 homer_uint64 AliHLTHOMERReader::GetBlockStatusFlags( unsigned long ndx ) const
451     {
452 // see header file for class documentation
453     if ( ndx >= fBlockCnt )
454         return 0;
455     return *(((homer_uint64*)fBlocks[ndx].fMetaData)+kStatusFlags_64b_Offset);
456     }
457
458 /* HOMER specific */
459 /* Return the type of the data in the current event's data
460    block with the given block index (starting at 0). */
461 homer_uint64 AliHLTHOMERReader::GetBlockDataType( unsigned long ndx ) const
462     {
463 // see header file for class documentation
464     if ( ndx >= fBlockCnt )
465         return ~(homer_uint64)0;
466     //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
467     return *(((homer_uint64*)fBlocks[ndx].fMetaData)+kType_64b_Offset);
468     }
469
470 /* Return the origin of the data in the current event's data
471    block with the given block index (starting at 0). */
472 homer_uint32 AliHLTHOMERReader::GetBlockDataOrigin( unsigned long ndx ) const
473     {
474 // see header file for class documentation
475     if ( ndx >= fBlockCnt )
476         return ~(homer_uint32)0;
477     //return (homer_uint32)( ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fSubType1.fID );
478     return (homer_uint32)*(((homer_uint64*)fBlocks[ndx].fMetaData)+kSubType1_64b_Offset);
479     }
480
481 /* Return a specification of the data in the current event's data
482    block with the given block index (starting at 0). */
483 homer_uint32 AliHLTHOMERReader::GetBlockDataSpec( unsigned long ndx ) const
484     {
485 // see header file for class documentation
486     if ( ndx >= fBlockCnt )
487         return ~(homer_uint32)0;
488     //return (homer_uint32)( ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fSubType2.fID );
489     return (homer_uint32)*(((homer_uint64*)fBlocks[ndx].fMetaData)+kSubType2_64b_Offset);
490     }
491
492 /* Find the next data block in the current event with the given
493    data type, origin, and specification. Returns the block's 
494    index. */
495 unsigned long AliHLTHOMERReader::FindBlockNdx( homer_uint64 type, homer_uint32 origin, 
496                                          homer_uint32 spec, unsigned long startNdx ) const
497     {
498 // see header file for class documentation
499     for ( unsigned long n=startNdx; n < fBlockCnt; n++ )
500         {
501         if ( ( type == 0xFFFFFFFFFFFFFFFFULL || *(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset)==type ) &&
502              ( origin == 0xFFFFFFFF || (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset) )==origin ) &&
503              ( spec == 0xFFFFFFFF || (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset) )==spec ) )
504             return n;
505         }
506     return ~(unsigned long)0;
507     }
508
509 /* Find the next data block in the current event with the given
510    data type, origin, and specification. Returns the block's 
511    index. */
512 unsigned long AliHLTHOMERReader::FindBlockNdx( char type[8], char origin[4], 
513                                          homer_uint32 spec, unsigned long startNdx ) const
514     {
515 // see header file for class documentation
516     for ( unsigned long n=startNdx; n < fBlockCnt; n++ )
517         {
518         bool found1=true, found2=true;
519         for ( unsigned i = 0; i < 8; i++ )
520             {
521             if ( type[i] != (char)0xFF )
522                 {
523                 found1=false;
524                 break;
525                 }
526             }
527         if ( !found1 )
528             {
529             found1 = true;
530             for ( unsigned i = 0; i < 8; i++ )
531                 {
532                 //printf( "%u: Comparing type '%c' and '%c'\n", i, ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset))[i], type[i] );
533                 if ( ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset))[i] != type[i] )
534                     {
535                     found1=false;
536                     break;
537                     }
538                 }
539             }
540         for ( unsigned i = 0; i < 4; i++ )
541             {
542             if ( origin[i] != (char)0xFF )
543                 {
544                 found2 = false;
545                 break;
546                 }
547             }
548         if ( !found2 )
549             {
550             found2 = true;
551             for ( unsigned i = 0; i < 4; i++ )
552                 {
553                 //printf( "Comparing origin '%c' and '%c'\n", ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset))[i], origin[i] );
554                 if ( ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset))[i] != origin[i] )
555                     {
556                     found2=false;
557                     break;
558                     }
559                 }
560             }
561         //printf( "Comparing spec '0x%08lX' and '0x%08lX'\n", (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset) ), spec );
562         if ( found1 && found2 &&
563              ( spec == 0xFFFFFFFF || ((homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset)) )==spec ) )
564             return n;
565         }
566     return ~(unsigned long)0;
567     }
568
569 /* Return the ID of the node that actually produced this data block.
570    This may be different from the node which sent the data to this
571    monitoring object as returned by GetBlockSendNodeID. */
572 const char* AliHLTHOMERReader::GetBlockCreateNodeID( unsigned long ndx ) const
573     {
574 // see header file for class documentation
575     if ( ndx >= fBlockCnt )
576         return NULL;
577     return fBlocks[ndx].fOriginatingNodeID;
578     }
579
580
581 void AliHLTHOMERReader::Init()
582     {
583 // see header file for class documentation
584     fCurrentEventType = ~(homer_uint64)0;
585     fCurrentEventID = ~(homer_uint64)0;
586     fMaxBlockCnt = fBlockCnt = 0;
587     fBlocks = NULL;
588         
589     fDataSourceMaxCnt = fDataSourceCnt = fTCPDataSourceCnt = fShmDataSourceCnt = 0;
590     fDataSources = NULL;
591
592         
593     fConnectionStatus = 0;
594     fErrorConnection = ~(unsigned int)0;
595
596     fEventRequestAdvanceTime = 0;
597     }
598         
599 bool AliHLTHOMERReader::AllocDataSources( unsigned int sourceCnt )
600     {
601 // see header file for class documentation
602     fDataSources = new DataSource[ sourceCnt ];
603     if ( !fDataSources )
604         return false;
605     memset(fDataSources, 0, sizeof(DataSource)*sourceCnt);
606     fDataSourceCnt = 0;
607     fDataSourceMaxCnt = sourceCnt;
608     return true;
609     }
610
611 int AliHLTHOMERReader::AddDataSource( const char* hostname, unsigned short port, DataSource& source )
612     {
613 // see header file for class documentation
614     struct hostent* he;
615     he = gethostbyname( hostname );
616     if ( he == NULL )
617         {
618         //fprintf( stderr, "Unable to determine remote host address from '%s'.\n", hostname );
619         return EADDRNOTAVAIL;
620         }
621
622     struct sockaddr_in remoteAddr;
623     remoteAddr.sin_family = AF_INET;    // host byte order 
624     remoteAddr.sin_port = htons(port);  // short, network byte order 
625     remoteAddr.sin_addr = *((struct in_addr *)he->h_addr);
626     memset(&(remoteAddr.sin_zero), '\0', 8);  // zero the rest of the struct
627
628     // Create socket and connect to target program on remote node
629     source.fTCPConnection = socket( AF_INET, SOCK_STREAM, 0 );
630     if ( source.fTCPConnection == -1 )
631         {
632         return errno;
633         }
634
635     int ret;
636
637     ret = connect( source.fTCPConnection, (struct sockaddr *)&remoteAddr, sizeof(struct sockaddr) );
638     if ( ret == -1 )
639         {
640         ret=errno;
641         close( source.fTCPConnection );
642         return ret;
643         } 
644
645     ret = write( source.fTCPConnection, MOD_BIN, strlen(MOD_BIN) );
646     if ( ret != (int)strlen(MOD_BIN) )
647         {
648         ret=errno;
649         close( source.fTCPConnection );
650         return ret;
651         }
652
653     char* tmpchar = new char[ strlen( hostname )+1 ];
654     if ( !tmpchar )
655         {
656         close( source.fTCPConnection );
657         return ENOMEM;
658         }
659     strcpy( tmpchar, hostname );
660     source.fHostname = tmpchar;
661
662     source.fType = kTCP;
663     source.fTCPPort = port;
664     source.fData = NULL;
665     source.fDataSize = 0;
666     source.fDataRead = 0;
667     return 0;
668     }
669
670 int AliHLTHOMERReader::AddDataSource( key_t shmKey, int shmSize, DataSource& source )
671     {
672 // see header file for class documentation
673     int ret;
674     char* tmpchar = new char[ MAXHOSTNAMELEN+1 ];
675     if ( !tmpchar )
676         {
677         return ENOMEM;
678         }
679     gethostname( tmpchar, MAXHOSTNAMELEN );
680     tmpchar[MAXHOSTNAMELEN]=(char)0;
681     source.fHostname = tmpchar;
682
683     source.fShmID = shmget( shmKey, shmSize, 0660 );
684     if ( source.fShmID == -1 )
685         {
686         ret = errno;
687         delete [] source.fHostname;
688         return ret;
689         }
690     
691     source.fShmPtr = (void*)shmat( source.fShmID, NULL, 0 );
692
693     if ( !source.fShmPtr )
694         {
695         ret = errno;
696         shmctl( source.fShmID, IPC_RMID, NULL );
697         delete [] source.fHostname;
698         return ret;
699         }
700
701     source.fType = kShm;
702     source.fShmKey = shmKey;
703     source.fShmSize = shmSize;
704     source.fDataSize = 0;
705     source.fDataRead = 0;
706     return 0;
707     }
708
709 int AliHLTHOMERReader::AddDataSource( void* pBuffer, int size, DataSource& source )
710     {
711 // see header file for class documentation
712 // a buffer data source is like a shm source apart from the shm attach and detach
713 // procedure. Furthermore, the size indicator at the beginning of the buffer is not
714 // cleared right before sources are read but after the reading.
715     //int ret;
716     if ( !pBuffer || size<=0) return EINVAL;
717
718     char* tmpchar = new char[ MAXHOSTNAMELEN+1 ];
719     if ( !tmpchar )
720         {
721         return ENOMEM;
722         }
723     gethostname( tmpchar, MAXHOSTNAMELEN );
724     tmpchar[MAXHOSTNAMELEN]=(char)0;
725     source.fHostname = tmpchar;
726
727     source.fShmID = -1;
728     // the data buffer does not contain a size indicator in the first 4 bytes
729     // like the shm source buffer. Still we want to use the mechanism to invalidate/
730     // trigger by clearing the size indicator. Take the source.fShmSize variable.
731     source.fShmPtr = &source.fShmSize;
732     source.fType = kBuf;
733     source.fShmKey = 0;
734     source.fShmSize = size;
735     source.fData = pBuffer;
736     source.fDataSize = 0;
737     source.fDataRead = 0;
738     return 0;
739     }
740
741 void AliHLTHOMERReader::FreeDataSources()
742     {
743 // see header file for class documentation
744     for ( unsigned n=0; n < fDataSourceCnt; n++ )
745         {
746         if ( fDataSources[n].fType == kTCP )
747             FreeTCPDataSource( fDataSources[n] );
748         else if ( fDataSources[n].fType == kShm )
749             FreeShmDataSource( fDataSources[n] );
750         }
751     }
752
753 int AliHLTHOMERReader::FreeShmDataSource( DataSource& source )
754     {
755 // see header file for class documentation
756     if ( source.fShmPtr )
757         shmdt( source.fShmPtr );
758 //     if ( source.fShmID != -1 )
759 //      shmctl( source.fShmID, IPC_RMID, NULL );
760     if ( source.fHostname )
761         delete [] source.fHostname;
762     return 0;
763     }
764
765 int AliHLTHOMERReader::FreeTCPDataSource( DataSource& source )
766     {
767 // see header file for class documentation
768     if ( source.fTCPConnection )
769         close( source.fTCPConnection );
770     if ( source.fHostname )
771         delete [] source.fHostname;
772     return 0;
773     }
774
775 int AliHLTHOMERReader::ReadNextEvent( bool useTimeout, unsigned long timeout )
776     {
777 // see header file for class documentation
778     if ( fDataSourceCnt<=0 )
779         return ENXIO;
780     // Clean up currently active event.
781     ReleaseCurrentEvent();
782     int ret=0;
783     // Trigger all configured data sources
784     for ( unsigned n = 0; n<fDataSourceCnt; n++ )
785         {
786         if ( fDataSources[n].fType == kTCP )
787             ret = TriggerTCPSource( fDataSources[n], useTimeout, timeout );
788         else if ( fDataSources[n].fType == kShm )
789             ret = TriggerShmSource( fDataSources[n], useTimeout, timeout );
790         if ( ret )
791             {
792             fErrorConnection = n;
793             fConnectionStatus=ret;
794             return fConnectionStatus;
795             }
796         }
797     // Now read in data from the configured data source
798     ret = ReadDataFromTCPSources( fTCPDataSourceCnt, fDataSources, useTimeout, timeout );
799     if ( ret )
800         {
801         return ret;
802         }
803     ret = ReadDataFromShmSources( fShmDataSourceCnt, fDataSources+fTCPDataSourceCnt, useTimeout, timeout );
804     if ( ret )
805         {
806         return ret;
807         }
808 //     for ( unsigned n = 0; n<fDataSourceCnt; n++ )
809 //      {
810 //      if ( fDataSources[n].fType == kTCP )
811 //          ret = ReadDataFromTCPSource( fDataSources[n], useTimeout, timeout );
812 //      else
813 //          ret = ReadDataFromShmSource( fDataSources[n], useTimeout, timeout );
814 //      if ( ret )
815 //          {
816 //          fErrorConnection = n;
817 //          fConnectionStatus=ret;
818 //          return fConnectionStatus;
819 //          }
820 //      }
821     //Check to see that all sources contributed data for the same event
822     homer_uint64 eventID;
823     homer_uint64 eventType;
824     if (!fDataSources[0].fData)
825       {
826         fErrorConnection = 0;
827         fConnectionStatus=56;//ENOBUF;
828         return fConnectionStatus;
829       }
830     eventID = GetSourceEventID( fDataSources[0] );
831     eventType = GetSourceEventType( fDataSources[0] );
832     for ( unsigned n = 1; n < fDataSourceCnt; n++ )
833         {
834         if ( !fDataSources[n].fData || GetSourceEventID( fDataSources[n] ) != eventID || GetSourceEventType( fDataSources[n] ) != eventType )
835             {
836             fErrorConnection = n;
837             fConnectionStatus=56;//EBADRQC;
838             return fConnectionStatus;
839             }
840         }
841     // Find all the different data blocks contained in the data from all
842     // the sources.
843     for ( unsigned n = 0; n < fDataSourceCnt; n++ )
844         {
845         ret = ParseSourceData( fDataSources[n] );
846         if ( ret )
847             {
848             fErrorConnection = n;
849             fConnectionStatus=57;//EBADSLT;
850             return fConnectionStatus;
851             }
852         }
853     fCurrentEventID = eventID;
854     fCurrentEventType = eventType;
855     return 0;
856     }
857
858 void AliHLTHOMERReader::ReleaseCurrentEvent()
859     {
860 // see header file for class documentation
861     // sources.fDataRead = 0;
862     // fMaxBlockCnt
863     fCurrentEventID = ~(homer_uint64)0;
864     fCurrentEventType = ~(homer_uint64)0;
865     for ( unsigned n = 0; n < fDataSourceCnt; n++ )
866         {
867         if ( fDataSources[n].fData )
868             {
869             if ( fDataSources[n].fType == kTCP )
870                 delete [] (homer_uint8*)fDataSources[n].fData;
871             // do not reset the data pointer for kBuf sources since this
872             // can not be set again.
873             if ( fDataSources[n].fType != kBuf )
874               fDataSources[n].fData = NULL;
875             }
876         fDataSources[n].fDataSize = fDataSources[n].fDataRead = 0;
877         }
878     if ( fBlocks )
879         {
880         for ( unsigned n = 0; n < fMaxBlockCnt; n++ )
881             {
882             if ( fBlocks[n].fOriginatingNodeID )
883                 delete [] fBlocks[n].fOriginatingNodeID;
884             }
885         delete [] fBlocks;
886         fBlocks=0;
887         fMaxBlockCnt = 0;
888         fBlockCnt=0;
889         }
890     }
891
892 int AliHLTHOMERReader::TriggerTCPSource( DataSource& source, bool useTimeout, unsigned long timeoutUsec )
893     {
894 // see header file for class documentation
895     int ret;
896     struct timeval oldSndTO, newSndTO;
897     if ( useTimeout )
898         {
899         socklen_t optlen=sizeof(oldSndTO);
900         ret = getsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, &optlen );
901         if ( ret )
902             {
903             return errno;
904             }
905         if ( optlen!=sizeof(oldSndTO) )
906             {
907             return ENXIO;
908             }
909         newSndTO.tv_sec = timeoutUsec / 1000000;
910         newSndTO.tv_usec = timeoutUsec - (newSndTO.tv_sec*1000000);
911         ret = setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &newSndTO, sizeof(newSndTO) );
912         if ( ret )
913             {
914             return errno;
915             }
916         }
917     // Send one event request
918     if ( !fEventRequestAdvanceTime )
919         {
920         ret = write( source.fTCPConnection, GET_ONE, strlen(GET_ONE) );
921         
922         if ( ret != (int)strlen(GET_ONE) )
923             {
924             ret=errno;
925             setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
926             return ret;
927             }
928         }
929     else
930         {
931         char tmpCmd[ 128 ];
932
933         int len = snprintf( tmpCmd, 128, "FIRST ORBIT EVENT 0x%Lu\n", (unsigned long long)fEventRequestAdvanceTime );
934         if ( len>128 || len<0 )
935             {
936             ret=EMSGSIZE;
937             setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
938             return ret;
939             }
940         
941         ret = write( source.fTCPConnection, tmpCmd, strlen(tmpCmd) );
942         
943         if ( ret != (int)strlen(tmpCmd) )
944             {
945             ret=errno;
946             setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
947             return ret;
948             }
949         
950         }
951     return 0;
952     }
953
954 int AliHLTHOMERReader::TriggerShmSource( DataSource& source, bool, unsigned long ) const
955     {
956 // see header file for class documentation
957 // clear the size indicator in the first 4 bytes of the buffer to request data
958 // from the HOMER writer.
959     if ( source.fShmPtr )
960         {
961         *(homer_uint32*)( source.fShmPtr ) = 0;
962         return 0;
963         }
964     else
965         return EFAULT;
966     }
967
968 int AliHLTHOMERReader::ReadDataFromTCPSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout )
969     {
970 // see header file for class documentation
971     bool toRead = false;
972     do
973         {
974         fd_set conns;
975         FD_ZERO( &conns );
976         int highestConn=0;
977         toRead = false;
978         unsigned firstConnection=~(unsigned)0;
979         for ( unsigned long n = 0; n < sourceCnt; n++ )
980             {
981             if ( sources[n].fDataSize == 0 // size specifier not yet read
982                  || sources[n].fDataRead < sources[n].fDataSize ) // Data not yet read fully
983                 {
984                 toRead = true;
985                 FD_SET( sources[n].fTCPConnection, &conns );
986                 if ( sources[n].fTCPConnection > highestConn )
987                     highestConn = sources[n].fTCPConnection;
988                 fcntl( sources[n].fTCPConnection, F_SETFL, O_NONBLOCK );
989                 if ( firstConnection == ~(unsigned)0 )
990                     firstConnection = n;
991                 }
992             else
993                 {
994                 fcntl( sources[n].fTCPConnection, F_SETFL, 0 );
995                 }
996             }
997         if ( toRead )
998             {
999             struct timeval tv, *ptv;
1000             if ( useTimeout )
1001                 {
1002                 tv.tv_sec = timeout / 1000000;
1003                 tv.tv_usec = timeout - (tv.tv_sec*1000000);
1004                 ptv = &tv;
1005                 }
1006             else
1007                 ptv = NULL;
1008             // wait until something is ready to be read
1009             // either for timeout usecs or until eternity
1010             int ret;
1011             ret = select( highestConn+1, &conns, NULL, NULL, ptv ); 
1012             if ( ret <=0 )
1013                 {
1014                 fErrorConnection = firstConnection;
1015                 if ( errno )
1016                     fConnectionStatus = errno;
1017                 else
1018                     fConnectionStatus = ETIMEDOUT;
1019                 return fConnectionStatus;
1020                 }
1021             for ( unsigned n = 0; n < sourceCnt; n++ )
1022                 {
1023                 if ( FD_ISSET( sources[n].fTCPConnection, &conns ) )
1024                     {
1025                     if ( sources[n].fDataSize == 0 )
1026                         {
1027                         ret=read( sources[n].fTCPConnection, &(sources[n].fDataSize), sizeof(homer_uint32) );
1028                         if ( ret != sizeof(homer_uint32) )
1029                             {
1030                             fErrorConnection = n;
1031                             if ( errno )
1032                                 fConnectionStatus = errno;
1033                             else
1034                                 fConnectionStatus = ENOMSG;
1035                             return fConnectionStatus;
1036                             }
1037                         sources[n].fDataSize = ntohl( sources[n].fDataSize );
1038                         sources[n].fDataRead = 0;
1039                         sources[n].fData = new homer_uint8[ sources[n].fDataSize ];
1040                         if ( !sources[n].fData )
1041                             {
1042                             fErrorConnection = n;
1043                             fConnectionStatus = ENOMEM;
1044                             return fConnectionStatus;
1045                             }
1046                         }
1047                     else if ( sources[n].fData && sources[n].fDataRead < sources[n].fDataSize)
1048                         {
1049                         ret=read( sources[n].fTCPConnection, ((homer_uint8*)sources[n].fData)+sources[n].fDataRead, sources[n].fDataSize-sources[n].fDataRead );
1050                         if ( ret>0 )
1051                             sources[n].fDataRead += ret;
1052                         else if ( ret == 0 )
1053                             {
1054                             fErrorConnection = n;
1055                             fConnectionStatus = ECONNRESET;
1056                             return fConnectionStatus;
1057                             }
1058                         else
1059                             {
1060                             fErrorConnection = n;
1061                             fConnectionStatus = errno;
1062                             return fConnectionStatus;
1063                             }
1064                         }
1065                     else
1066                         {
1067                         fErrorConnection = n;
1068                         fConnectionStatus = ENXIO;
1069                         return fConnectionStatus;
1070                         }
1071                     }
1072                 }
1073             }
1074         }
1075     while ( toRead );
1076     return 0;
1077     }
1078
1079 /*
1080 int AliHLTHOMERReader::ReadDataFromTCPSources( DataSource& source, bool useTimeout, unsigned long timeout )
1081     {
1082 #warning TODO If useTimeout: Set sockets to nonblocking, select + loop around GET_ONE write
1083     // Send one event request
1084     ret = write( source.fTCPConnection, GET_ONE, strlen(GET_ONE) );
1085     if ( ret != strlen(GET_ONE) )
1086         {
1087         return errno;
1088         }
1089     // wait for and read back size specifier
1090     unsigned sizeNBO;
1091     // The value transmitted is binary, in network byte order
1092     ret = read( source.fTCPConnection, &sizeNBO, sizeof(sizeNBO) );
1093     if ( ret != sizeof(sizeNBO) )
1094         {
1095         return errno;
1096         }
1097     // Convert back to host byte order
1098     source.fDataSize = ntohl( sizeNBO );
1099     source.fData = new homer_uint8[ source.fDataSize ];
1100     unsigned long dataRead=0, toRead;
1101     if ( !source.fData )
1102         {
1103         char buffer[1024];
1104         // Read in data into buffer in order not to block connection
1105         while ( dataRead < source.fDataSize )
1106             {
1107             if ( source.fDataSize-dataRead > 1024 )
1108                 toRead = 1024;
1109             else
1110                 toRead = source.fDataSize-dataRead;
1111             ret = read( source.fTCPConnection, buffer, toRead );
1112             if ( ret > 0 )
1113                 dataRead += ret;
1114             else
1115                 return errno;
1116             }
1117         return ENOMEM;
1118         }
1119     while ( dataRead < source.fDataSize )
1120         {
1121         toRead = source.fDataSize-dataRead;
1122         ret = read( source.fTCPConnection, source.fData+dataRead, toRead );
1123         if ( ret > 0 )
1124             dataRead += ret;
1125         else if ( ret == 0 && useTimeout )
1126             {
1127             struct timeval tv;
1128             tv.tv_sec = timeout / 1000000;
1129             tv.tv_usec = timeout - (tv.tv_sec*1000000);
1130             fd_set conns;
1131             FD_ZERO( &conns );
1132             FD_SET( source.fTCPConnection, &conns );
1133             ret = select( source.fTCPConnection+1, &conns, NULL, NULL );
1134             if ( ret <=0 )
1135                 return errno;
1136             }
1137         else if ( ret == 0 )
1138             {
1139             if ( errno == EOK )
1140                 return ECONNRESET;
1141             else
1142                 return errno;
1143             }
1144         else
1145             {
1146             return errno;
1147             }
1148         }
1149     return 0;
1150     }
1151 */
1152
1153 /*
1154 int AliHLTHOMERReader::ReadDataFromShmSource( DataSource& source, bool useTimeout, unsigned long timeout )
1155     {
1156     
1157     }
1158 */
1159
1160 int AliHLTHOMERReader::ReadDataFromShmSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout )
1161     {
1162 // see header file for class documentation
1163     struct timeval tv1, tv2;
1164     bool found=false;
1165     bool all=true;
1166     if ( useTimeout )
1167         gettimeofday( &tv1, NULL );
1168     do
1169         {
1170         found = false;
1171         all = true;
1172         for ( unsigned n = 0; n < sourceCnt; n++ )
1173             {
1174             if ( !sources[n].fDataSize )
1175                 all = false;
1176             if ( sources[n].fShmPtr && *(homer_uint32*)sources[n].fShmPtr>0 && !sources[n].fDataSize )
1177                 {
1178                 found = true;
1179                 sources[n].fDataSize = *(homer_uint32*)sources[n].fShmPtr;
1180                 if (sources[n].fType==kBuf)
1181                   {
1182                     // the data buffer is already set to fData, just need to set fDataSize member
1183                     // to invalidate after the first reading. Subsequent calls to ReadNextEvent return 0
1184                     TriggerShmSource( sources[n], 0, 0 );
1185                   } else 
1186                   {
1187                     sources[n].fData = ((homer_uint8*)sources[n].fShmPtr)+sizeof(homer_uint32);
1188                   }
1189                 }
1190             }
1191         if ( found && useTimeout )
1192             gettimeofday( &tv1, NULL );
1193         if ( !all && useTimeout )
1194             {
1195             gettimeofday( &tv2, NULL );
1196             unsigned long long tdiff;
1197             tdiff = tv2.tv_sec-tv1.tv_sec;
1198             tdiff *= 1000000;
1199             tdiff += tv2.tv_usec-tv1.tv_usec;
1200             if ( tdiff > timeout )
1201                 return ETIMEDOUT;
1202             }
1203         if ( !all )
1204             usleep( 0 );
1205         }
1206     while ( !all );
1207     return 0;
1208     }
1209
1210 int AliHLTHOMERReader::ParseSourceData( DataSource& source )
1211     {
1212 // see header file for class documentation
1213     if ( source.fData )
1214         {
1215         homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
1216         homer_uint64 blockCnt = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kSubType2_64b_Offset ] );
1217         int ret=ReAllocBlocks( fMaxBlockCnt+blockCnt );
1218         if ( ret )
1219             return ret;
1220         homer_uint64 descrOffset = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kOffset_64b_Offset ] );
1221         for ( homer_uint64 n = 0; n < blockCnt && fBlockCnt < fMaxBlockCnt; n++, fBlockCnt++ )
1222             {
1223             homer_uint8* descr = ((homer_uint8*)source.fData)+descrOffset;
1224             unsigned descrLen = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kLength_64b_Offset ] );
1225             fBlocks[fBlockCnt].fSource = source.fNdx;
1226             fBlocks[fBlockCnt].fData = ((homer_uint8*)source.fData) + Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kOffset_64b_Offset ] );
1227             fBlocks[fBlockCnt].fLength = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kSize_64b_Offset ] );
1228             fBlocks[fBlockCnt].fMetaData = (homer_uint64*)descr;
1229             struct in_addr tmpA;
1230             tmpA.s_addr = (homer_uint32)( ((homer_uint64*)descr)[ kProducerNode_64b_Offset ] );
1231             char* addr = inet_ntoa( tmpA );
1232             char* tmpchar = new char[ strlen(addr)+1 ];
1233             if ( !tmpchar )
1234                 return ENOMEM;
1235             strcpy( tmpchar, addr );
1236             fBlocks[fBlockCnt].fOriginatingNodeID = tmpchar;
1237             descrOffset += descrLen;
1238             }
1239         return 0;
1240         }
1241     return EFAULT;
1242     }
1243         
1244 int AliHLTHOMERReader::ReAllocBlocks( unsigned long newCnt )
1245     {
1246 // see header file for class documentation
1247     DataBlock* newBlocks;
1248     newBlocks = new DataBlock[ newCnt ];
1249     if ( !newBlocks )
1250         return ENOMEM;
1251     unsigned long cpCnt = (newCnt > fMaxBlockCnt) ? fMaxBlockCnt : newCnt;
1252     memcpy( newBlocks, fBlocks, cpCnt*sizeof(DataBlock) );
1253     if ( newCnt > fMaxBlockCnt )
1254         memset( newBlocks+fMaxBlockCnt, 0, (newCnt-fMaxBlockCnt)*sizeof(DataBlock) );
1255     if ( fBlocks )
1256         delete [] fBlocks;
1257     fBlocks = newBlocks;
1258     fMaxBlockCnt = newCnt;
1259     return 0;
1260     }
1261
1262 homer_uint64 AliHLTHOMERReader::GetSourceEventID( DataSource& source )
1263     {
1264 // see header file for class documentation
1265     homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
1266     return Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kSubType1_64b_Offset ] );
1267     }
1268
1269 homer_uint64 AliHLTHOMERReader::GetSourceEventType( DataSource& source )
1270     {
1271 // see header file for class documentation
1272     homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
1273     return Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kType_64b_Offset ] );
1274     }
1275
1276 homer_uint64 AliHLTHOMERReader::Swap( homer_uint8 destFormat, homer_uint8 sourceFormat, homer_uint64 source ) const
1277     {
1278 // see header file for class documentation
1279     if ( destFormat == sourceFormat )
1280         return source;
1281     else
1282         return ((source & 0xFFULL) << 56) | 
1283         ((source & 0xFF00ULL) << 40) | 
1284         ((source & 0xFF0000ULL) << 24) | 
1285         ((source & 0xFF000000ULL) << 8) | 
1286         ((source & 0xFF00000000ULL) >> 8) | 
1287         ((source & 0xFF0000000000ULL) >> 24) | 
1288         ((source & 0xFF000000000000ULL) >>  40) | 
1289         ((source & 0xFF00000000000000ULL) >> 56);
1290     }
1291
1292 homer_uint32 AliHLTHOMERReader::Swap( homer_uint8 destFormat, homer_uint8 sourceFormat, homer_uint32 source ) const
1293     {
1294 // see header file for class documentation
1295     if ( destFormat == sourceFormat )
1296         return source;
1297     else
1298         return ((source & 0xFFUL) << 24) | 
1299         ((source & 0xFF00UL) << 8) | 
1300         ((source & 0xFF0000UL) >> 8) | 
1301         ((source & 0xFF000000UL) >> 24);
1302     }
1303
1304 AliHLTHOMERReader* AliHLTHOMERReaderCreateFromTCPPort(const char* hostname, unsigned short port )
1305     {
1306       // see header file for function documentation
1307       return new AliHLTHOMERReader(hostname, port);
1308     }
1309
1310 AliHLTHOMERReader* AliHLTHOMERReaderCreateFromTCPPorts(unsigned int tcpCnt, const char** hostnames, unsigned short* ports)
1311     {
1312       // see header file for function documentation
1313       return new AliHLTHOMERReader(tcpCnt, hostnames, ports);
1314     }
1315
1316 AliHLTHOMERReader* AliHLTHOMERReaderCreateFromBuffer(const void* pBuffer, int size)
1317     {
1318       // see header file for function documentation
1319       return new AliHLTHOMERReader(pBuffer, size);
1320     }
1321
1322 void AliHLTHOMERReaderDelete(AliHLTHOMERReader* pInstance)
1323     {
1324       // see header file for function documentation
1325       if (pInstance) delete pInstance;
1326     }
1327
1328 /*
1329 ***************************************************************************
1330 **
1331 ** $Author$ - Initial Version by Timm Morten Steinbeck
1332 **
1333 ** $Id$ 
1334 **
1335 ***************************************************************************
1336 */