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