]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/HOMER/AliHLTHOMERReader.cxx
bugfix: making distinct Swap functions; error code resolved in HOMER reader
[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         fShmDataSourceCnt++;
349         fDataSources[0].fNdx = 0;
350         }
351     }
352
353 AliHLTHOMERReader::~AliHLTHOMERReader()
354     {
355 // see header file for class documentation
356     ReleaseCurrentEvent();
357     FreeDataSources();
358     }
359
360 int  AliHLTHOMERReader::ReadNextEvent()
361     {
362 // see header file for class documentation
363 // Read in the next available event
364     return ReadNextEvent( false, 0 );
365     }
366
367 int AliHLTHOMERReader::ReadNextEvent( unsigned long timeout )
368     {
369 // see header file for class documentation
370 // Read in the next available event
371     return ReadNextEvent( true, timeout );
372     }
373
374 unsigned long AliHLTHOMERReader::GetBlockDataLength( unsigned long ndx ) const
375     {
376 // see header file for class documentation
377 // Return the size (in bytes) of the current event's data
378 // block with the given block index (starting at 0).
379     if ( ndx >= fBlockCnt )
380         return 0;
381     return fBlocks[ndx].fLength;
382     }
383
384 const void* AliHLTHOMERReader::GetBlockData( unsigned long ndx ) const
385     {
386 // see header file for class documentation
387 // Return a pointer to the start of the current event's data
388 // block with the given block index (starting at 0).
389     if ( ndx >= fBlockCnt )
390         return NULL;
391     return fBlocks[ndx].fData;
392     }
393
394 const char* AliHLTHOMERReader::GetBlockSendNodeID( unsigned long ndx ) const
395     {
396 // see header file for class documentation
397 // Return IP address or hostname of node which sent the 
398 // current event's data block with the given block index 
399 // (starting at 0).
400 // For HOMER this is the ID of the node on which the subscriber 
401 // that provided this data runs/ran.
402     if ( ndx >= fBlockCnt )
403         return NULL;
404 #ifdef DEBUG
405     if ( fBlocks[ndx].fSource >= fDataSourceCnt )
406         {
407         fprintf( stderr, "%s:%d: Internal Error: fBlocks[ndx].fSource (%lu) >= fDataSourceCnt (%lu)\n",
408                  __FILE__, __LINE__, fBlocks[ndx].fSource, fDataSourceCnt );
409         return NULL;
410         }
411 #endif
412     return fDataSources[ fBlocks[ndx].fSource ].fHostname;
413     //return fBlocks[ndx].fOriginatingNodeID;
414     }
415
416 homer_uint8 AliHLTHOMERReader::GetBlockByteOrder( unsigned long ndx ) const
417     {
418 // see header file for class documentation
419 // Return byte order of the data stored in the 
420 // current event's data block with the given block index (starting at 0). 
421 //         0 is unknown alignment, 
422 //         1 ist little endian, 
423 //         2 is big endian. */
424     if ( ndx >= fBlockCnt )
425         return 0;
426     //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
427     return *(((homer_uint8*)fBlocks[ndx].fMetaData)+kByteOrderAttribute_8b_Offset);
428     }
429
430 homer_uint8 AliHLTHOMERReader::GetBlockTypeAlignment( unsigned long ndx, homer_uint8 dataType ) const
431     {
432 // see header file for class documentation
433 // Return the alignment (in bytes) of the given datatype 
434 // in the data stored in the current event's data block
435 // with the given block index (starting at 0). 
436 // Possible values for the data type are
437 //         0: homer_uint64
438 //         1: homer_uint32
439 //         2: uin16
440 //         3: homer_uint8
441 //         4: double
442 //         5: float
443     if ( ndx >= fBlockCnt )
444         return 0;
445     if ( dataType > (kFloatAlignment_8b_Offset-kAlignment_8b_StartOffset) )
446         return 0;
447     //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
448     return *(((homer_uint8*)fBlocks[ndx].fMetaData)+kAlignment_8b_StartOffset+dataType);
449     }
450
451 homer_uint64 AliHLTHOMERReader::GetBlockStatusFlags( unsigned long ndx ) const
452     {
453 // see header file for class documentation
454     if ( ndx >= fBlockCnt )
455         return 0;
456     return *(((homer_uint64*)fBlocks[ndx].fMetaData)+kStatusFlags_64b_Offset);
457     }
458
459 /* HOMER specific */
460 /* Return the type of the data in the current event's data
461    block with the given block index (starting at 0). */
462 homer_uint64 AliHLTHOMERReader::GetBlockDataType( unsigned long ndx ) const
463     {
464 // see header file for class documentation
465     if ( ndx >= fBlockCnt )
466         return ~(homer_uint64)0;
467     //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
468     return *(((homer_uint64*)fBlocks[ndx].fMetaData)+kType_64b_Offset);
469     }
470
471 /* Return the origin of the data in the current event's data
472    block with the given block index (starting at 0). */
473 homer_uint32 AliHLTHOMERReader::GetBlockDataOrigin( unsigned long ndx ) const
474     {
475 // see header file for class documentation
476     if ( ndx >= fBlockCnt )
477         return ~(homer_uint32)0;
478     //return (homer_uint32)( ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fSubType1.fID );
479     return (homer_uint32)*(((homer_uint64*)fBlocks[ndx].fMetaData)+kSubType1_64b_Offset);
480     }
481
482 /* Return a specification of the data in the current event's data
483    block with the given block index (starting at 0). */
484 homer_uint32 AliHLTHOMERReader::GetBlockDataSpec( unsigned long ndx ) const
485     {
486 // see header file for class documentation
487     if ( ndx >= fBlockCnt )
488         return ~(homer_uint32)0;
489     //return (homer_uint32)( ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fSubType2.fID );
490     return (homer_uint32)*(((homer_uint64*)fBlocks[ndx].fMetaData)+kSubType2_64b_Offset);
491     }
492
493 /* Find the next data block in the current event with the given
494    data type, origin, and specification. Returns the block's 
495    index. */
496 unsigned long AliHLTHOMERReader::FindBlockNdx( homer_uint64 type, homer_uint32 origin, 
497                                          homer_uint32 spec, unsigned long startNdx ) const
498     {
499 // see header file for class documentation
500     for ( unsigned long n=startNdx; n < fBlockCnt; n++ )
501         {
502         if ( ( type == 0xFFFFFFFFFFFFFFFFULL || *(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset)==type ) &&
503              ( origin == 0xFFFFFFFF || (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset) )==origin ) &&
504              ( spec == 0xFFFFFFFF || (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset) )==spec ) )
505             return n;
506         }
507     return ~(unsigned long)0;
508     }
509
510 /* Find the next data block in the current event with the given
511    data type, origin, and specification. Returns the block's 
512    index. */
513 unsigned long AliHLTHOMERReader::FindBlockNdx( char type[8], char origin[4], 
514                                          homer_uint32 spec, unsigned long startNdx ) const
515     {
516 // see header file for class documentation
517     for ( unsigned long n=startNdx; n < fBlockCnt; n++ )
518         {
519         bool found1=true, found2=true;
520         for ( unsigned i = 0; i < 8; i++ )
521             {
522             if ( type[i] != (char)0xFF )
523                 {
524                 found1=false;
525                 break;
526                 }
527             }
528         if ( !found1 )
529             {
530             found1 = true;
531             for ( unsigned i = 0; i < 8; i++ )
532                 {
533                 //printf( "%u: Comparing type '%c' and '%c'\n", i, ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset))[i], type[i] );
534                 if ( ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset))[i] != type[i] )
535                     {
536                     found1=false;
537                     break;
538                     }
539                 }
540             }
541         for ( unsigned i = 0; i < 4; i++ )
542             {
543             if ( origin[i] != (char)0xFF )
544                 {
545                 found2 = false;
546                 break;
547                 }
548             }
549         if ( !found2 )
550             {
551             found2 = true;
552             for ( unsigned i = 0; i < 4; i++ )
553                 {
554                 //printf( "Comparing origin '%c' and '%c'\n", ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset))[i], origin[i] );
555                 if ( ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset))[i] != origin[i] )
556                     {
557                     found2=false;
558                     break;
559                     }
560                 }
561             }
562         //printf( "Comparing spec '0x%08lX' and '0x%08lX'\n", (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset) ), spec );
563         if ( found1 && found2 &&
564              ( spec == 0xFFFFFFFF || ((homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset)) )==spec ) )
565             return n;
566         }
567     return ~(unsigned long)0;
568     }
569
570 /* Return the ID of the node that actually produced this data block.
571    This may be different from the node which sent the data to this
572    monitoring object as returned by GetBlockSendNodeID. */
573 const char* AliHLTHOMERReader::GetBlockCreateNodeID( unsigned long ndx ) const
574     {
575 // see header file for class documentation
576     if ( ndx >= fBlockCnt )
577         return NULL;
578     return fBlocks[ndx].fOriginatingNodeID;
579     }
580
581
582 void AliHLTHOMERReader::Init()
583     {
584 // see header file for class documentation
585     fCurrentEventType = ~(homer_uint64)0;
586     fCurrentEventID = ~(homer_uint64)0;
587     fMaxBlockCnt = fBlockCnt = 0;
588     fBlocks = NULL;
589         
590     fDataSourceMaxCnt = fDataSourceCnt = fTCPDataSourceCnt = fShmDataSourceCnt = 0;
591     fDataSources = NULL;
592
593         
594     fConnectionStatus = 0;
595     fErrorConnection = ~(unsigned int)0;
596
597     fEventRequestAdvanceTime = 0;
598     }
599         
600 bool AliHLTHOMERReader::AllocDataSources( unsigned int sourceCnt )
601     {
602 // see header file for class documentation
603     fDataSources = new DataSource[ sourceCnt ];
604     if ( !fDataSources )
605         return false;
606     memset(fDataSources, 0, sizeof(DataSource)*sourceCnt);
607     fDataSourceCnt = 0;
608     fDataSourceMaxCnt = sourceCnt;
609     return true;
610     }
611
612 int AliHLTHOMERReader::AddDataSource( const char* hostname, unsigned short port, DataSource& source )
613     {
614 // see header file for class documentation
615     struct hostent* he;
616     he = gethostbyname( hostname );
617     if ( he == NULL )
618         {
619         //fprintf( stderr, "Unable to determine remote host address from '%s'.\n", hostname );
620         return EADDRNOTAVAIL;
621         }
622
623     struct sockaddr_in remoteAddr;
624     remoteAddr.sin_family = AF_INET;    // host byte order 
625     remoteAddr.sin_port = htons(port);  // short, network byte order 
626     remoteAddr.sin_addr = *((struct in_addr *)he->h_addr);
627     memset(&(remoteAddr.sin_zero), '\0', 8);  // zero the rest of the struct
628
629     // Create socket and connect to target program on remote node
630     source.fTCPConnection = socket( AF_INET, SOCK_STREAM, 0 );
631     if ( source.fTCPConnection == -1 )
632         {
633         return errno;
634         }
635
636     int ret;
637
638     ret = connect( source.fTCPConnection, (struct sockaddr *)&remoteAddr, sizeof(struct sockaddr) );
639     if ( ret == -1 )
640         {
641         ret=errno;
642         close( source.fTCPConnection );
643         return ret;
644         } 
645
646     ret = write( source.fTCPConnection, MOD_BIN, strlen(MOD_BIN) );
647     if ( ret != (int)strlen(MOD_BIN) )
648         {
649         ret=errno;
650         close( source.fTCPConnection );
651         return ret;
652         }
653
654     char* tmpchar = new char[ strlen( hostname )+1 ];
655     if ( !tmpchar )
656         {
657         close( source.fTCPConnection );
658         return ENOMEM;
659         }
660     strcpy( tmpchar, hostname );
661     source.fHostname = tmpchar;
662
663     source.fType = kTCP;
664     source.fTCPPort = port;
665     source.fData = NULL;
666     source.fDataSize = 0;
667     source.fDataRead = 0;
668     return 0;
669     }
670
671 int AliHLTHOMERReader::AddDataSource( key_t shmKey, int shmSize, DataSource& source )
672     {
673 // see header file for class documentation
674     int ret;
675     char* tmpchar = new char[ MAXHOSTNAMELEN+1 ];
676     if ( !tmpchar )
677         {
678         return ENOMEM;
679         }
680     gethostname( tmpchar, MAXHOSTNAMELEN );
681     tmpchar[MAXHOSTNAMELEN]=(char)0;
682     source.fHostname = tmpchar;
683
684     source.fShmID = shmget( shmKey, shmSize, 0660 );
685     if ( source.fShmID == -1 )
686         {
687         ret = errno;
688         delete [] source.fHostname;
689         return ret;
690         }
691     
692     source.fShmPtr = (void*)shmat( source.fShmID, NULL, 0 );
693
694     if ( !source.fShmPtr )
695         {
696         ret = errno;
697         shmctl( source.fShmID, IPC_RMID, NULL );
698         delete [] source.fHostname;
699         return ret;
700         }
701
702     source.fType = kShm;
703     source.fShmKey = shmKey;
704     source.fShmSize = shmSize;
705     source.fDataSize = 0;
706     source.fDataRead = 0;
707     return 0;
708     }
709
710 int AliHLTHOMERReader::AddDataSource( void* pBuffer, int size, DataSource& source )
711     {
712 // see header file for class documentation
713 // a buffer data source is like a shm source apart from the shm attach and detach
714 // procedure. Furthermore, the size indicator at the beginning of the buffer is not
715 // cleared right before sources are read but after the reading.
716     //int ret;
717     if ( !pBuffer || size<=0) return EINVAL;
718
719     char* tmpchar = new char[ MAXHOSTNAMELEN+1 ];
720     if ( !tmpchar )
721         {
722         return ENOMEM;
723         }
724     gethostname( tmpchar, MAXHOSTNAMELEN );
725     tmpchar[MAXHOSTNAMELEN]=(char)0;
726     source.fHostname = tmpchar;
727
728     source.fShmID = -1;
729     // the data buffer does not contain a size indicator in the first 4 bytes
730     // like the shm source buffer. Still we want to use the mechanism to invalidate/
731     // trigger by clearing the size indicator. Take the source.fShmSize variable.
732     source.fShmPtr = &source.fShmSize;
733     source.fType = kBuf;
734     source.fShmKey = 0;
735     source.fShmSize = size;
736     source.fData = pBuffer;
737     source.fDataSize = 0;
738     source.fDataRead = 0;
739     return 0;
740     }
741
742 void AliHLTHOMERReader::FreeDataSources()
743     {
744 // see header file for class documentation
745     for ( unsigned n=0; n < fDataSourceCnt; n++ )
746         {
747         if ( fDataSources[n].fType == kTCP )
748             FreeTCPDataSource( fDataSources[n] );
749         else if ( fDataSources[n].fType == kShm )
750             FreeShmDataSource( fDataSources[n] );
751         }
752     }
753
754 int AliHLTHOMERReader::FreeShmDataSource( DataSource& source )
755     {
756 // see header file for class documentation
757     if ( source.fShmPtr )
758         shmdt( source.fShmPtr );
759 //     if ( source.fShmID != -1 )
760 //      shmctl( source.fShmID, IPC_RMID, NULL );
761     if ( source.fHostname )
762         delete [] source.fHostname;
763     return 0;
764     }
765
766 int AliHLTHOMERReader::FreeTCPDataSource( DataSource& source )
767     {
768 // see header file for class documentation
769     if ( source.fTCPConnection )
770         close( source.fTCPConnection );
771     if ( source.fHostname )
772         delete [] source.fHostname;
773     return 0;
774     }
775
776 int AliHLTHOMERReader::ReadNextEvent( bool useTimeout, unsigned long timeout )
777     {
778 // see header file for class documentation
779     if ( fDataSourceCnt<=0 )
780         return ENXIO;
781     // Clean up currently active event.
782     ReleaseCurrentEvent();
783     int ret=0;
784     // Trigger all configured data sources
785     for ( unsigned n = 0; n<fDataSourceCnt; n++ )
786         {
787         if ( fDataSources[n].fType == kTCP )
788             ret = TriggerTCPSource( fDataSources[n], useTimeout, timeout );
789         else if ( fDataSources[n].fType == kShm )
790             ret = TriggerShmSource( fDataSources[n], useTimeout, timeout );
791         if ( ret )
792             {
793             fErrorConnection = n;
794             fConnectionStatus=ret;
795             return fConnectionStatus;
796             }
797         }
798     // Now read in data from the configured data source
799     ret = ReadDataFromTCPSources( fTCPDataSourceCnt, fDataSources, useTimeout, timeout );
800     if ( ret )
801         {
802         return ret;
803         }
804     ret = ReadDataFromShmSources( fShmDataSourceCnt, fDataSources+fTCPDataSourceCnt, useTimeout, timeout );
805     if ( ret )
806         {
807         return ret;
808         }
809 //     for ( unsigned n = 0; n<fDataSourceCnt; n++ )
810 //      {
811 //      if ( fDataSources[n].fType == kTCP )
812 //          ret = ReadDataFromTCPSource( fDataSources[n], useTimeout, timeout );
813 //      else
814 //          ret = ReadDataFromShmSource( fDataSources[n], useTimeout, timeout );
815 //      if ( ret )
816 //          {
817 //          fErrorConnection = n;
818 //          fConnectionStatus=ret;
819 //          return fConnectionStatus;
820 //          }
821 //      }
822     //Check to see that all sources contributed data for the same event
823     homer_uint64 eventID;
824     homer_uint64 eventType;
825     if (!fDataSources[0].fData)
826       {
827         fErrorConnection = 0;
828         fConnectionStatus=56;//ENOBUF;
829         return fConnectionStatus;
830       }
831     eventID = GetSourceEventID( fDataSources[0] );
832     eventType = GetSourceEventType( fDataSources[0] );
833     for ( unsigned n = 1; n < fDataSourceCnt; n++ )
834         {
835         if ( !fDataSources[n].fData || GetSourceEventID( fDataSources[n] ) != eventID || GetSourceEventType( fDataSources[n] ) != eventType )
836             {
837             fErrorConnection = n;
838             fConnectionStatus=56;//EBADRQC;
839             return fConnectionStatus;
840             }
841         }
842     // Find all the different data blocks contained in the data from all
843     // the sources.
844     for ( unsigned n = 0; n < fDataSourceCnt; n++ )
845         {
846         ret = ParseSourceData( fDataSources[n] );
847         if ( ret )
848             {
849             fErrorConnection = n;
850             fConnectionStatus=57;//EBADSLT;
851             return ret;
852             }
853         }
854     fCurrentEventID = eventID;
855     fCurrentEventType = eventType;
856     return 0;
857     }
858
859 void AliHLTHOMERReader::ReleaseCurrentEvent()
860     {
861 // see header file for class documentation
862     // sources.fDataRead = 0;
863     // fMaxBlockCnt
864     fCurrentEventID = ~(homer_uint64)0;
865     fCurrentEventType = ~(homer_uint64)0;
866     for ( unsigned n = 0; n < fDataSourceCnt; n++ )
867         {
868         if ( fDataSources[n].fData )
869             {
870             if ( fDataSources[n].fType == kTCP )
871                 delete [] (homer_uint8*)fDataSources[n].fData;
872             // do not reset the data pointer for kBuf sources since this
873             // can not be set again.
874             if ( fDataSources[n].fType != kBuf )
875               fDataSources[n].fData = NULL;
876             }
877         fDataSources[n].fDataSize = fDataSources[n].fDataRead = 0;
878         }
879     if ( fBlocks )
880         {
881         for ( unsigned n = 0; n < fMaxBlockCnt; n++ )
882             {
883             if ( fBlocks[n].fOriginatingNodeID )
884                 delete [] fBlocks[n].fOriginatingNodeID;
885             }
886         delete [] fBlocks;
887         fBlocks=0;
888         fMaxBlockCnt = 0;
889         fBlockCnt=0;
890         }
891     }
892
893 int AliHLTHOMERReader::TriggerTCPSource( DataSource& source, bool useTimeout, unsigned long timeoutUsec )
894     {
895 // see header file for class documentation
896     int ret;
897     struct timeval oldSndTO, newSndTO;
898     if ( useTimeout )
899         {
900         socklen_t optlen=sizeof(oldSndTO);
901         ret = getsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, &optlen );
902         if ( ret )
903             {
904             return errno;
905             }
906         if ( optlen!=sizeof(oldSndTO) )
907             {
908             return ENXIO;
909             }
910         newSndTO.tv_sec = timeoutUsec / 1000000;
911         newSndTO.tv_usec = timeoutUsec - (newSndTO.tv_sec*1000000);
912         ret = setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &newSndTO, sizeof(newSndTO) );
913         if ( ret )
914             {
915             return errno;
916             }
917         }
918     // Send one event request
919     if ( !fEventRequestAdvanceTime )
920         {
921         ret = write( source.fTCPConnection, GET_ONE, strlen(GET_ONE) );
922         
923         if ( ret != (int)strlen(GET_ONE) )
924             {
925             ret=errno;
926             setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
927             return ret;
928             }
929         }
930     else
931         {
932         char tmpCmd[ 128 ];
933
934         int len = snprintf( tmpCmd, 128, "FIRST ORBIT EVENT 0x%Lu\n", (unsigned long long)fEventRequestAdvanceTime );
935         if ( len>128 || len<0 )
936             {
937             ret=EMSGSIZE;
938             setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
939             return ret;
940             }
941         
942         ret = write( source.fTCPConnection, tmpCmd, strlen(tmpCmd) );
943         
944         if ( ret != (int)strlen(tmpCmd) )
945             {
946             ret=errno;
947             setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
948             return ret;
949             }
950         
951         }
952     return 0;
953     }
954
955 int AliHLTHOMERReader::TriggerShmSource( DataSource& source, bool, unsigned long ) const
956     {
957 // see header file for class documentation
958 // clear the size indicator in the first 4 bytes of the buffer to request data
959 // from the HOMER writer.
960     if ( source.fShmPtr )
961         {
962         *(homer_uint32*)( source.fShmPtr ) = 0;
963         return 0;
964         }
965     else
966         return EFAULT;
967     }
968
969 int AliHLTHOMERReader::ReadDataFromTCPSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout )
970     {
971 // see header file for class documentation
972     bool toRead = false;
973     do
974         {
975         fd_set conns;
976         FD_ZERO( &conns );
977         int highestConn=0;
978         toRead = false;
979         unsigned firstConnection=~(unsigned)0;
980         for ( unsigned long n = 0; n < sourceCnt; n++ )
981             {
982             if ( sources[n].fDataSize == 0 // size specifier not yet read
983                  || sources[n].fDataRead < sources[n].fDataSize ) // Data not yet read fully
984                 {
985                 toRead = true;
986                 FD_SET( sources[n].fTCPConnection, &conns );
987                 if ( sources[n].fTCPConnection > highestConn )
988                     highestConn = sources[n].fTCPConnection;
989                 fcntl( sources[n].fTCPConnection, F_SETFL, O_NONBLOCK );
990                 if ( firstConnection == ~(unsigned)0 )
991                     firstConnection = n;
992                 }
993             else
994                 {
995                 fcntl( sources[n].fTCPConnection, F_SETFL, 0 );
996                 }
997             }
998         if ( toRead )
999             {
1000             struct timeval tv, *ptv;
1001             if ( useTimeout )
1002                 {
1003                 tv.tv_sec = timeout / 1000000;
1004                 tv.tv_usec = timeout - (tv.tv_sec*1000000);
1005                 ptv = &tv;
1006                 }
1007             else
1008                 ptv = NULL;
1009             // wait until something is ready to be read
1010             // either for timeout usecs or until eternity
1011             int ret;
1012             ret = select( highestConn+1, &conns, NULL, NULL, ptv ); 
1013             if ( ret <=0 )
1014                 {
1015                 fErrorConnection = firstConnection;
1016                 if ( errno )
1017                     fConnectionStatus = errno;
1018                 else
1019                     fConnectionStatus = ETIMEDOUT;
1020                 return fConnectionStatus;
1021                 }
1022             for ( unsigned n = 0; n < sourceCnt; n++ )
1023                 {
1024                 if ( FD_ISSET( sources[n].fTCPConnection, &conns ) )
1025                     {
1026                     if ( sources[n].fDataSize == 0 )
1027                         {
1028                         ret=read( sources[n].fTCPConnection, &(sources[n].fDataSize), sizeof(homer_uint32) );
1029                         if ( ret != sizeof(homer_uint32) )
1030                             {
1031                             fErrorConnection = n;
1032                             if ( errno )
1033                                 fConnectionStatus = errno;
1034                             else
1035                                 fConnectionStatus = ENOMSG;
1036                             return fConnectionStatus;
1037                             }
1038                         sources[n].fDataSize = ntohl( sources[n].fDataSize );
1039                         sources[n].fDataRead = 0;
1040                         sources[n].fData = new homer_uint8[ sources[n].fDataSize ];
1041                         if ( !sources[n].fData )
1042                             {
1043                             fErrorConnection = n;
1044                             fConnectionStatus = ENOMEM;
1045                             return fConnectionStatus;
1046                             }
1047                         }
1048                     else if ( sources[n].fData && sources[n].fDataRead < sources[n].fDataSize)
1049                         {
1050                         ret=read( sources[n].fTCPConnection, ((homer_uint8*)sources[n].fData)+sources[n].fDataRead, sources[n].fDataSize-sources[n].fDataRead );
1051                         if ( ret>0 )
1052                             sources[n].fDataRead += ret;
1053                         else if ( ret == 0 )
1054                             {
1055                             fErrorConnection = n;
1056                             fConnectionStatus = ECONNRESET;
1057                             return fConnectionStatus;
1058                             }
1059                         else
1060                             {
1061                             fErrorConnection = n;
1062                             fConnectionStatus = errno;
1063                             return fConnectionStatus;
1064                             }
1065                         }
1066                     else
1067                         {
1068                         fErrorConnection = n;
1069                         fConnectionStatus = ENXIO;
1070                         return fConnectionStatus;
1071                         }
1072                     }
1073                 }
1074             }
1075         }
1076     while ( toRead );
1077     return 0;
1078     }
1079
1080 /*
1081 int AliHLTHOMERReader::ReadDataFromTCPSources( DataSource& source, bool useTimeout, unsigned long timeout )
1082     {
1083 #warning TODO If useTimeout: Set sockets to nonblocking, select + loop around GET_ONE write
1084     // Send one event request
1085     ret = write( source.fTCPConnection, GET_ONE, strlen(GET_ONE) );
1086     if ( ret != strlen(GET_ONE) )
1087         {
1088         return errno;
1089         }
1090     // wait for and read back size specifier
1091     unsigned sizeNBO;
1092     // The value transmitted is binary, in network byte order
1093     ret = read( source.fTCPConnection, &sizeNBO, sizeof(sizeNBO) );
1094     if ( ret != sizeof(sizeNBO) )
1095         {
1096         return errno;
1097         }
1098     // Convert back to host byte order
1099     source.fDataSize = ntohl( sizeNBO );
1100     source.fData = new homer_uint8[ source.fDataSize ];
1101     unsigned long dataRead=0, toRead;
1102     if ( !source.fData )
1103         {
1104         char buffer[1024];
1105         // Read in data into buffer in order not to block connection
1106         while ( dataRead < source.fDataSize )
1107             {
1108             if ( source.fDataSize-dataRead > 1024 )
1109                 toRead = 1024;
1110             else
1111                 toRead = source.fDataSize-dataRead;
1112             ret = read( source.fTCPConnection, buffer, toRead );
1113             if ( ret > 0 )
1114                 dataRead += ret;
1115             else
1116                 return errno;
1117             }
1118         return ENOMEM;
1119         }
1120     while ( dataRead < source.fDataSize )
1121         {
1122         toRead = source.fDataSize-dataRead;
1123         ret = read( source.fTCPConnection, source.fData+dataRead, toRead );
1124         if ( ret > 0 )
1125             dataRead += ret;
1126         else if ( ret == 0 && useTimeout )
1127             {
1128             struct timeval tv;
1129             tv.tv_sec = timeout / 1000000;
1130             tv.tv_usec = timeout - (tv.tv_sec*1000000);
1131             fd_set conns;
1132             FD_ZERO( &conns );
1133             FD_SET( source.fTCPConnection, &conns );
1134             ret = select( source.fTCPConnection+1, &conns, NULL, NULL );
1135             if ( ret <=0 )
1136                 return errno;
1137             }
1138         else if ( ret == 0 )
1139             {
1140             if ( errno == EOK )
1141                 return ECONNRESET;
1142             else
1143                 return errno;
1144             }
1145         else
1146             {
1147             return errno;
1148             }
1149         }
1150     return 0;
1151     }
1152 */
1153
1154 /*
1155 int AliHLTHOMERReader::ReadDataFromShmSource( DataSource& source, bool useTimeout, unsigned long timeout )
1156     {
1157     
1158     }
1159 */
1160
1161 int AliHLTHOMERReader::ReadDataFromShmSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout )
1162     {
1163 // see header file for class documentation
1164     struct timeval tv1, tv2;
1165     bool found=false;
1166     bool all=true;
1167     if ( useTimeout )
1168         gettimeofday( &tv1, NULL );
1169     do
1170         {
1171         found = false;
1172         all = true;
1173         for ( unsigned n = 0; n < sourceCnt; n++ )
1174             {
1175             if ( !sources[n].fDataSize )
1176                 all = false;
1177             if ( sources[n].fShmPtr && *(homer_uint32*)sources[n].fShmPtr>0 && !sources[n].fDataSize )
1178                 {
1179                 found = true;
1180                 sources[n].fDataSize = *(homer_uint32*)sources[n].fShmPtr;
1181                 if (sources[n].fType==kBuf)
1182                   {
1183                     // the data buffer is already set to fData, just need to set fDataSize member
1184                     // to invalidate after the first reading. Subsequent calls to ReadNextEvent return 0
1185                     TriggerShmSource( sources[n], 0, 0 );
1186                   } else 
1187                   {
1188                     sources[n].fData = ((homer_uint8*)sources[n].fShmPtr)+sizeof(homer_uint32);
1189                   }
1190                 }
1191             }
1192         if ( found && useTimeout )
1193             gettimeofday( &tv1, NULL );
1194         if ( !all && useTimeout )
1195             {
1196             gettimeofday( &tv2, NULL );
1197             unsigned long long tdiff;
1198             tdiff = tv2.tv_sec-tv1.tv_sec;
1199             tdiff *= 1000000;
1200             tdiff += tv2.tv_usec-tv1.tv_usec;
1201             if ( tdiff > timeout )
1202                 return ETIMEDOUT;
1203             }
1204         if ( !all )
1205             usleep( 0 );
1206         }
1207     while ( !all );
1208     return 0;
1209     }
1210
1211 int AliHLTHOMERReader::ParseSourceData( DataSource& source )
1212     {
1213 // see header file for class documentation
1214     if ( source.fData )
1215         {
1216         homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
1217         if (sourceByteOrder!=kHOMERLittleEndianByteOrder && sourceByteOrder!=kHOMERBigEndianByteOrder) return EBADMSG;
1218         homer_uint64 blockCnt = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kSubType2_64b_Offset ] );
1219         // block count is not related to size of the data in the way the
1220         // following condition implies. But we can at least limit the block
1221         // count for the case the data is corrupted
1222         if (blockCnt>source.fDataSize) return EBADMSG;
1223         int ret=ReAllocBlocks( fMaxBlockCnt+blockCnt );
1224         if ( ret )
1225             return ret;
1226         homer_uint64 descrOffset = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kOffset_64b_Offset ] );
1227         for ( homer_uint64 n = 0; n < blockCnt && fBlockCnt < fMaxBlockCnt; n++, fBlockCnt++ )
1228             {
1229             if (descrOffset+kLength_64b_Offset>=source.fDataSize) return EBADMSG;
1230             homer_uint8* descr = ((homer_uint8*)source.fData)+descrOffset;
1231             unsigned descrLen = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kLength_64b_Offset ] );
1232             if (descrOffset+descrLen>=source.fDataSize) return EBADMSG;
1233             if (Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kID_64b_Offset ] ) != HOMER_BLOCK_DESCRIPTOR_TYPEID) return 126/*ENOKEY*/;
1234             fBlocks[fBlockCnt].fSource = source.fNdx;
1235             fBlocks[fBlockCnt].fData = ((homer_uint8*)source.fData) + Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kOffset_64b_Offset ] );
1236             fBlocks[fBlockCnt].fLength = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kSize_64b_Offset ] );
1237             fBlocks[fBlockCnt].fMetaData = (homer_uint64*)descr;
1238             struct in_addr tmpA;
1239             tmpA.s_addr = (homer_uint32)( ((homer_uint64*)descr)[ kProducerNode_64b_Offset ] );
1240             char* addr = inet_ntoa( tmpA );
1241             char* tmpchar = new char[ strlen(addr)+1 ];
1242             if ( !tmpchar )
1243                 return ENOMEM;
1244             strcpy( tmpchar, addr );
1245             fBlocks[fBlockCnt].fOriginatingNodeID = tmpchar;
1246             descrOffset += descrLen;
1247             }
1248         return 0;
1249         }
1250     return EFAULT;
1251     }
1252         
1253 int AliHLTHOMERReader::ReAllocBlocks( unsigned long newCnt )
1254     {
1255 // see header file for class documentation
1256     DataBlock* newBlocks;
1257     newBlocks = new DataBlock[ newCnt ];
1258     if ( !newBlocks )
1259         return ENOMEM;
1260     unsigned long cpCnt = (newCnt > fMaxBlockCnt) ? fMaxBlockCnt : newCnt;
1261     memcpy( newBlocks, fBlocks, cpCnt*sizeof(DataBlock) );
1262     if ( newCnt > fMaxBlockCnt )
1263         memset( newBlocks+fMaxBlockCnt, 0, (newCnt-fMaxBlockCnt)*sizeof(DataBlock) );
1264     if ( fBlocks )
1265         delete [] fBlocks;
1266     fBlocks = newBlocks;
1267     fMaxBlockCnt = newCnt;
1268     return 0;
1269     }
1270
1271 homer_uint64 AliHLTHOMERReader::GetSourceEventID( DataSource& source )
1272     {
1273 // see header file for class documentation
1274     homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
1275     return Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kSubType1_64b_Offset ] );
1276     }
1277
1278 homer_uint64 AliHLTHOMERReader::GetSourceEventType( DataSource& source )
1279     {
1280 // see header file for class documentation
1281     homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
1282     return Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kType_64b_Offset ] );
1283     }
1284
1285 homer_uint64 AliHLTHOMERReader::Swap( homer_uint8 destFormat, homer_uint8 sourceFormat, homer_uint64 source ) const
1286     {
1287 // see header file for class documentation
1288     if ( destFormat == sourceFormat )
1289         return source;
1290     else
1291         return ((source & 0xFFULL) << 56) | 
1292         ((source & 0xFF00ULL) << 40) | 
1293         ((source & 0xFF0000ULL) << 24) | 
1294         ((source & 0xFF000000ULL) << 8) | 
1295         ((source & 0xFF00000000ULL) >> 8) | 
1296         ((source & 0xFF0000000000ULL) >> 24) | 
1297         ((source & 0xFF000000000000ULL) >>  40) | 
1298         ((source & 0xFF00000000000000ULL) >> 56);
1299     }
1300
1301 homer_uint32 AliHLTHOMERReader::Swap( homer_uint8 destFormat, homer_uint8 sourceFormat, homer_uint32 source ) const
1302     {
1303 // see header file for class documentation
1304     if ( destFormat == sourceFormat )
1305         return source;
1306     else
1307         return ((source & 0xFFUL) << 24) | 
1308         ((source & 0xFF00UL) << 8) | 
1309         ((source & 0xFF0000UL) >> 8) | 
1310         ((source & 0xFF000000UL) >> 24);
1311     }
1312
1313 AliHLTHOMERReader* AliHLTHOMERReaderCreateFromTCPPort(const char* hostname, unsigned short port )
1314     {
1315       // see header file for function documentation
1316       return new AliHLTHOMERReader(hostname, port);
1317     }
1318
1319 AliHLTHOMERReader* AliHLTHOMERReaderCreateFromTCPPorts(unsigned int tcpCnt, const char** hostnames, unsigned short* ports)
1320     {
1321       // see header file for function documentation
1322       return new AliHLTHOMERReader(tcpCnt, hostnames, ports);
1323     }
1324
1325 AliHLTHOMERReader* AliHLTHOMERReaderCreateFromBuffer(const void* pBuffer, int size)
1326     {
1327       // see header file for function documentation
1328       return new AliHLTHOMERReader(pBuffer, size);
1329     }
1330
1331 void AliHLTHOMERReaderDelete(AliHLTHOMERReader* pInstance)
1332     {
1333       // see header file for function documentation
1334       if (pInstance) delete pInstance;
1335     }
1336
1337 /*
1338 ***************************************************************************
1339 **
1340 ** $Author$ - Initial Version by Timm Morten Steinbeck
1341 **
1342 ** $Id$ 
1343 **
1344 ***************************************************************************
1345 */