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