added HOMER library from PubSub package HLT-stable-20070905.141318 (rev. 2375)
authorrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 14 Sep 2007 09:13:54 +0000 (09:13 +0000)
committerrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 14 Sep 2007 09:13:54 +0000 (09:13 +0000)
HLT/BASE/HOMER/AliHLTHOMERData.h [new file with mode: 0644]
HLT/BASE/HOMER/AliHLTHOMERLinkDef.h [new file with mode: 0644]
HLT/BASE/HOMER/AliHLTHOMERReader.cxx [new file with mode: 0644]
HLT/BASE/HOMER/AliHLTHOMERReader.h [new file with mode: 0644]
HLT/BASE/HOMER/AliHLTHOMERWriter.cxx [new file with mode: 0644]
HLT/BASE/HOMER/AliHLTHOMERWriter.h [new file with mode: 0644]
HLT/BASE/HOMER/HOMERReader.tex [new file with mode: 0644]
HLT/BASE/HOMER/Makefile.am [new file with mode: 0644]
HLT/BASE/Makefile.am
HLT/configure.ac
HLT/libAliHLTHOMER.pkg [new file with mode: 0644]

diff --git a/HLT/BASE/HOMER/AliHLTHOMERData.h b/HLT/BASE/HOMER/AliHLTHOMERData.h
new file mode 100644 (file)
index 0000000..1d6aec6
--- /dev/null
@@ -0,0 +1,374 @@
+// XEMacs -*-C++-*-
+#ifndef _HOMERDATA_HPP_
+#define _HOMERDATA_HPP_
+
+/************************************************************************
+**
+**
+** This file is property of and copyright by the Technical Computer
+** Science Group, Kirchhoff Institute for Physics, Ruprecht-Karls-
+** University, Heidelberg, Germany, 2001
+** This file has been written by Timm Morten Steinbeck, 
+** timm@kip.uni-heidelberg.de
+**
+**
+** See the file license.txt for details regarding usage, modification,
+** distribution and warranty.
+** Important: This file is provided without any warranty, including
+** fitness for any particular purpose.
+**
+**
+** Newer versions of this file's package will be made available from 
+** http://web.kip.uni-heidelberg.de/Hardwinf/L3/ 
+** or the corresponding page of the Heidelberg Alice Level 3 group.
+**
+*************************************************************************/
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
+
+#ifdef USE_ROOT
+#include "Rtypes.h"
+#endif
+#include <limits.h>
+
+
+// Determine the sizes of the different integer type
+// homer_uint32, homer_uint64
+#if !defined(USE_ROOT) && !defined(__CINT__)
+// First homer_uint32
+#if USHRT_MAX==4294967295
+typedef unsigned short homer_uint32;
+#else // USHRT_MAX==4294967295
+
+#if UINT_MAX==4294967295
+typedef unsigned int homer_uint32;
+#else // UINT_MAX==4294967295
+
+#if ULONG_MAX==4294967295l
+typedef unsigned long homer_uint32;
+#else // ULONG_MAX==4294967295l
+
+#error Could not typedef homer_uint32
+
+#endif // ULONG_MAX==4294967295l
+
+#endif // UINT_MAX==4294967295
+
+#endif // USHRT_MAX==4294967295
+
+// Then homer_uint16
+#if USHRT_MAX==65535
+typedef unsigned short homer_uint16;
+#else // USHRT_MAX==65535
+
+#if UINT_MAX==65535
+typedef unsigned int homer_uint16;
+#else // UINT_MAX==65535
+
+#if ULONG_MAX==65535
+typedef unsigned long homer_uint16;
+#else // ULONG_MAX==65535
+
+#error Could not typedef homer_uint16
+
+#endif // ULONG_MAX==65535
+
+#endif // UINT_MAX==65535
+
+#endif // USHRT_MAX==65535
+
+// Then homer_uint64
+#if ULONG_MAX==18446744073709551615ULL
+typedef unsigned long homer_uint64;
+#else // ULONG_MAX==18446744073709551615UL
+
+#if defined __GNUC__
+typedef unsigned long long homer_uint64;
+#else // defined __GNUC__
+
+#error Could not typedef homer_uint64
+
+#endif // defined __GNUC__
+
+#endif // ULONG_MAX==18446744073709551615UL
+
+typedef unsigned char homer_uint8;
+
+#else // !USE_ROOT && !CINT
+
+
+typedef UShort_t homer_uint16;
+typedef UInt_t homer_uint32;
+typedef ULong64_t homer_uint64;
+typedef Byte_t homer_uint8;
+
+#ifdef __CINT__
+typedef int key_t;
+#endif
+
+#endif // USE_ROOT
+
+//typedef homer_uint64 AliEventID_t;
+
+
+
+const unsigned kAttribute_8b_StartOffset = 0;
+const unsigned kByteOrderAttribute_8b_Offset = kAttribute_8b_StartOffset+0;
+const unsigned kVersionAttribute_8b_Offset = kAttribute_8b_StartOffset+1;
+const unsigned kAlignment_8b_StartOffset = 24;
+const unsigned kUInt64Alignment_8b_Offset = kAlignment_8b_StartOffset+0;
+const unsigned kUInt32Alignment_8b_Offset = kAlignment_8b_StartOffset+1;
+const unsigned kUInt16Alignment_8b_Offset = kAlignment_8b_StartOffset+2;
+const unsigned kUInt8Alignment_8b_Offset = kAlignment_8b_StartOffset+3;
+const unsigned kDoubleAlignment_8b_Offset = kAlignment_8b_StartOffset+4;
+const unsigned kFloatAlignment_8b_Offset = kAlignment_8b_StartOffset+5;
+
+
+const unsigned kID_64b_Offset = 1;
+const unsigned kLength_64b_Offset = 2;
+const unsigned kType_64b_Offset = 4;
+const unsigned kSubType1_64b_Offset = 5;
+const unsigned kSubType2_64b_Offset = 6;
+const unsigned kBirth_s_64b_Offset = 7;
+const unsigned kBirth_us_64b_Offset = 8;
+const unsigned kProducerNode_64b_Offset = 9;
+const unsigned kOffset_64b_Offset = 10;
+const unsigned kSize_64b_Offset = 11;
+const unsigned kStatusFlags_64b_Offset = 12;
+const unsigned kEnd_64b_Offset = 13;
+const unsigned kCount_64b_Words = kEnd_64b_Offset;
+
+
+// Possible values for fAttributes[kByteOrderAttribute]
+/* Keep this consistent with BCLNetworkData.hpp kLittleEndian/kBigEndian and AliHLTSubEventDataDescriptor.hpp */
+const homer_uint8 kHOMERUnknownByteOrder      = 0;
+const homer_uint8 kHOMERLittleEndianByteOrder = 1;
+const homer_uint8 kHOMERBigEndianByteOrder    = 2;
+#ifdef __i386__
+    const homer_uint8 kHOMERNativeByteOrder = kHOMERLittleEndianByteOrder;
+#else
+#ifdef __arm__
+    const homer_uint8 kHOMERNativeByteOrder = kHOMERLittleEndianByteOrder;
+#else
+#ifdef __x86_64__
+    const homer_uint8 kHOMERNativeByteOrder = kHOMERLittleEndianByteOrder;
+#else
+#if defined(__powerpc__)
+    const homer_uint8 kHOMERNativeByteOrder = kHOMERBigEndianByteOrder;
+#else
+#ifdef __CINT__
+    const homer_uint8 kHOMERNativeByteOrder = kHOMERLittleEndianByteOrder;
+#warning Assuming little endian format for __CINT__
+#else
+#error Byte format (little/big endian) currently not defined for platforms other than intel i386 compatible, x86-64 (AMD64) and arm...
+#endif
+#endif
+#endif
+#endif
+#endif
+
+
+//#define HOMER_BLOCK_DESCRIPTOR_TYPEID             (((homer_uint64)'HOBL')<<32 | 'KDES')
+#define HOMER_BLOCK_DESCRIPTOR_TYPEID               ( (((homer_uint64)'H')<<56)|(((homer_uint64)'O')<<48)|(((homer_uint64)'B')<<40)|(((homer_uint64)'L')<<32)|(((homer_uint64)'K')<<24)|(((homer_uint64)'D')<<16)|(((homer_uint64)'E')<<8)|(((homer_uint64)'S')<<0) )
+//#define HOMER_BLOCK_DESCRIPTOR_TYPEID            ( (((homer_uint64)'H')<<56)|(((homer_uint64)'O')<<48) )
+#define HOMER_HEADER_CURRENT_VERSION              2
+
+
+class HOMERBlockDescriptor
+    {
+    public:
+
+       static unsigned GetHOMERBlockDescriptorSize()
+               {
+               return sizeof(homer_uint64)*kCount_64b_Words;
+               }
+
+       HOMERBlockDescriptor( void* header = 0 )
+               {
+               fHeader = header;
+               }
+       void UseHeader( void* header )
+               {
+               fHeader = header;
+               }
+       void Initialize()
+               {
+               if ( fHeader )
+                   {
+                   for ( unsigned ii=0; ii<kCount_64b_Words; ii++ )
+                       ((homer_uint64*)fHeader)[ ii ] = (homer_uint64)0;
+                   ((homer_uint64*)fHeader)[ kID_64b_Offset ] = HOMER_BLOCK_DESCRIPTOR_TYPEID;
+                   ((homer_uint64*)fHeader)[ kLength_64b_Offset ] = GetHOMERBlockDescriptorSize();
+                   ((homer_uint8*)fHeader)[ kByteOrderAttribute_8b_Offset ] = kHOMERNativeByteOrder;
+                   ((homer_uint8*)fHeader)[ kVersionAttribute_8b_Offset ] = HOMER_HEADER_CURRENT_VERSION;
+                   }
+               }
+
+       void SetByteOrder( homer_uint8 bo )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kByteOrderAttribute_8b_Offset ] = bo;
+               }
+       homer_uint8 GetByteOrder() const 
+               {
+               if ( fHeader )
+                   return ((homer_uint8*)fHeader)[ kByteOrderAttribute_8b_Offset ];
+               else
+                   return 0xFF;
+               }
+       void SetVersion( homer_uint8 v )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kVersionAttribute_8b_Offset ] = v;
+               }
+       void SetID( homer_uint64 id  )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kID_64b_Offset ] = id;
+               }
+       void SetHeaderLength( homer_uint64 l  )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kLength_64b_Offset ] = l;
+               }
+       homer_uint64 GetHeaderLength()
+               {
+               if ( fHeader )
+                   return ((homer_uint64*)fHeader)[ kLength_64b_Offset ];
+               else
+                   return 0;
+               }
+       void SetAlignment( homer_uint8 type, homer_uint8 align )
+               {
+               if ( fHeader && type<6 )
+                   ((homer_uint8*)fHeader)[ kAlignment_8b_StartOffset+type ] = align;
+               }
+       void SetUInt64Alignment( homer_uint8 align )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kUInt64Alignment_8b_Offset ] = align;
+               }
+       void SetUInt32Alignment( homer_uint8 align )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kUInt32Alignment_8b_Offset ] = align;
+               }
+       void SetUInt16Alignment( homer_uint8 align )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kUInt16Alignment_8b_Offset ] = align;
+               }
+       void SetUInt8Alignment( homer_uint8 align )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kUInt8Alignment_8b_Offset ] = align;
+               }
+       void SetDoubleAlignment( homer_uint8 align )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kDoubleAlignment_8b_Offset ] = align;
+               }
+       void SetFloatAlignment( homer_uint8 align )
+               {
+               if ( fHeader )
+                   ((homer_uint8*)fHeader)[ kFloatAlignment_8b_Offset ] = align;
+               }
+       void SetType( homer_uint64 t )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kType_64b_Offset ] = t;
+               }
+       void SetSubType1( homer_uint64 st1 )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kSubType1_64b_Offset ] = st1;
+               }
+       void SetSubType2( homer_uint64 st2 )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kSubType2_64b_Offset ] = st2;
+               }
+       void SetBirth_s( homer_uint64 bs )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kBirth_s_64b_Offset ] = bs;
+               }
+       void SetBirth_us( homer_uint64 bus )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kBirth_us_64b_Offset ] = bus;
+               }
+       void SetProducerNode( homer_uint64 pn )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kProducerNode_64b_Offset ] = pn;
+               }
+       void SetBlockOffset( homer_uint64 bo )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kOffset_64b_Offset ] = bo;
+               }
+       homer_uint64 GetBlockOffset()
+               {
+               if ( fHeader )
+                   return ((homer_uint64*)fHeader)[ kOffset_64b_Offset ];
+               else
+                   return 0;
+               }
+       void SetBlockSize( homer_uint64 bs )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kSize_64b_Offset ] = bs;
+               }
+       homer_uint64 GetBlockSize()
+               {
+               if ( fHeader )
+                   return ((homer_uint64*)fHeader)[ kSize_64b_Offset ];
+               else
+                   return 0;
+               }
+       void SetStatusFlags( homer_uint64 bs )
+               {
+               if ( fHeader )
+                   ((homer_uint64*)fHeader)[ kStatusFlags_64b_Offset ] = bs;
+               }
+       homer_uint64 GetStatusFlags()
+               {
+               if ( fHeader )
+                   return ((homer_uint64*)fHeader)[ kStatusFlags_64b_Offset ];
+               else
+                   return 0;
+               }
+
+       void* GetHeader() const
+               {
+               return fHeader;
+               }
+               
+    protected:
+       void* fHeader;
+       
+
+    };
+
+
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
+
+#endif // _HOMERDATA_HPP_
diff --git a/HLT/BASE/HOMER/AliHLTHOMERLinkDef.h b/HLT/BASE/HOMER/AliHLTHOMERLinkDef.h
new file mode 100644 (file)
index 0000000..bbb425a
--- /dev/null
@@ -0,0 +1,15 @@
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class MonitoringReader;
+#pragma link C++ class HOMERReader;
+#pragma link C++ class HOMERWriter;
+
+
+#pragma link C++ global gROOT;
+#pragma link C++ global gEnv;
+
+#endif
diff --git a/HLT/BASE/HOMER/AliHLTHOMERReader.cxx b/HLT/BASE/HOMER/AliHLTHOMERReader.cxx
new file mode 100644 (file)
index 0000000..84ad5b7
--- /dev/null
@@ -0,0 +1,1057 @@
+/************************************************************************
+**
+**
+** This file is property of and copyright by the Technical Computer
+** Science Group, Kirchhoff Institute for Physics, Ruprecht-Karls-
+** University, Heidelberg, Germany, 2001
+** This file has been written by Timm Morten Steinbeck, 
+** timm@kip.uni-heidelberg.de
+**
+**
+** See the file license.txt for details regarding usage, modification,
+** distribution and warranty.
+** Important: This file is provided without any warranty, including
+** fitness for any particular purpose.
+**
+**
+** Newer versions of this file's package will be made available from 
+** http://web.kip.uni-heidelberg.de/Hardwinf/L3/ 
+** or the corresponding page of the Heidelberg Alice Level 3 group.
+**
+*************************************************************************/
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
+
+/** @file   AliHLTHomerReader.cxx
+    @author Timm Steinbeck
+    @date   Sep 14 2007
+    @brief  HLT Online Monitoring Environment including ROOT - Reader
+    @note   migrated from PubSub HLT-stable-20070905.141318 (rev 2375)    */
+
+// see below for class documentation
+// or
+// refer to README to build package
+// or
+// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+
+#include "AliHLTHOMERReader.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+extern int h_errno;
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+#include <rpc/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef USE_ROOT
+#include <Rtypes.h>
+#endif
+
+
+#define MOD_BIN "MOD BIN\n"
+#define MOD_ASC "MOD ASC\n"
+#define GET_ONE "GET ONE\n"
+#define GET_ALL "GET ALL\n"
+
+#ifdef USE_ROOT
+ClassImp(MonitoringReader);
+ClassImp(HOMERReader);
+#endif
+
+
+
+
+
+#ifdef USE_ROOT
+HOMERReader::HOMERReader()
+    {
+    Init();
+    }
+#endif
+
+
+/* For reading from a TCP port */
+HOMERReader::HOMERReader( const char* hostname, unsigned short port )
+    {
+    Init();
+    if ( !AllocDataSources(1) )
+       {
+       fErrorConnection = 0;
+       fConnectionStatus = ENOMEM;
+       return;
+       }
+    fConnectionStatus = AddDataSource( hostname, port, fDataSources[0] );
+    if ( fConnectionStatus )
+       fErrorConnection = 0;
+    else
+       {
+       fDataSourceCnt++;
+       fTCPDataSourceCnt++;
+       fDataSources[0].fNdx = 0;
+       }
+    }
+
+/* For reading from multiple TCP ports */
+HOMERReader::HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports )
+    {
+    Init();
+    if ( !AllocDataSources(tcpCnt) )
+       {
+       fErrorConnection = 0;
+       fConnectionStatus = ENOMEM;
+       return;
+       }
+    for ( unsigned int n = 0; n < tcpCnt; n++, fDataSourceCnt++, fTCPDataSourceCnt++ )
+       {
+       fConnectionStatus = AddDataSource( hostnames[n], ports[n], fDataSources[n] );
+       if ( fConnectionStatus )
+           {
+           fErrorConnection = n;
+           return;
+           }
+       fDataSources[n].fNdx = n;
+       }
+    }
+
+/* For reading from a System V shared memory segment */
+HOMERReader::HOMERReader( key_t shmKey, int shmSize )
+    {
+    Init();
+    if ( !AllocDataSources(1) )
+       {
+       fErrorConnection = 0;
+       fConnectionStatus = ENOMEM;
+       return;
+       }
+    fConnectionStatus = AddDataSource( shmKey, shmSize, fDataSources[0] );
+    if ( fConnectionStatus )
+       fErrorConnection = 0;
+    else
+       {
+       fDataSourceCnt++;
+       fShmDataSourceCnt++;
+       fDataSources[0].fNdx = 0;
+       }
+    }
+
+/* For reading from multiple System V shared memory segments */
+HOMERReader::HOMERReader( unsigned int shmCnt, key_t* shmKeys, int* shmSizes )
+    {
+    Init();
+    if ( !AllocDataSources(shmCnt) )
+       {
+       fErrorConnection = 0;
+       fConnectionStatus = ENOMEM;
+       return;
+       }
+    for ( unsigned int n = 0; n < shmCnt; n++, fDataSourceCnt++, fShmDataSourceCnt++ )
+       {
+       fConnectionStatus = AddDataSource( shmKeys[n], shmSizes[n], fDataSources[n] );
+       if ( fConnectionStatus )
+           {
+           fErrorConnection = n;
+           return;
+           }
+       fDataSources[n].fNdx = n;
+       }
+    }
+
+/* For reading from multiple TCP ports and multiple System V shared memory segments */
+HOMERReader::HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports, 
+                         unsigned int shmCnt, key_t* shmKeys, int* shmSizes )
+    {
+    Init();
+    if ( !AllocDataSources(tcpCnt+shmCnt) )
+       {
+       fErrorConnection = 0;
+       fConnectionStatus = ENOMEM;
+       return;
+       }
+    for ( unsigned int n = 0; n < tcpCnt; n++, fDataSourceCnt++, fTCPDataSourceCnt++ )
+       {
+       fConnectionStatus = AddDataSource( hostnames[n], ports[n], fDataSources[n] );
+       if ( fConnectionStatus )
+           {
+           fErrorConnection = n;
+           return;
+           }
+       fDataSources[n].fNdx = n;
+       }
+    for ( unsigned int n = 0; n < shmCnt; n++, fDataSourceCnt++, fShmDataSourceCnt++ )
+       {
+       fConnectionStatus = AddDataSource( shmKeys[n], shmSizes[n], fDataSources[tcpCnt+n] );
+       if ( fConnectionStatus )
+           {
+           fErrorConnection = tcpCnt+n;
+           return;
+           }
+       fDataSources[n].fNdx = n;
+       }
+    }
+HOMERReader::~HOMERReader()
+    {
+    ReleaseCurrentEvent();
+    FreeDataSources();
+    }
+
+/* Read in the next available event */
+int  HOMERReader::ReadNextEvent()
+    {
+    return ReadNextEvent( false, 0 );
+    }
+
+/* Read in the next available event */
+int HOMERReader::ReadNextEvent( unsigned long timeout )
+    {
+    return ReadNextEvent( true, timeout );
+    }
+
+/* Return the size (in bytes) of the current event's data
+   block with the given block index (starting at 0). */
+unsigned long HOMERReader::GetBlockDataLength( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return 0;
+    return fBlocks[ndx].fLength;
+    }
+
+    /* Return a pointer to the start of the current event's data
+       block with the given block index (starting at 0). */
+const void* HOMERReader::GetBlockData( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return NULL;
+    return fBlocks[ndx].fData;
+    }
+
+/* Return IP address or hostname of node which sent the 
+   current event's data block with the given block index 
+   (starting at 0).
+   For HOMER this is the ID of the node on which the subscriber 
+   that provided this data runs/ran. */
+const char* HOMERReader::GetBlockSendNodeID( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return NULL;
+#ifdef DEBUG
+    if ( fBlocks[ndx].fSource >= fDataSourceCnt )
+       {
+       fprintf( stderr, "%s:%d: Internal Error: fBlocks[ndx].fSource (%lu) >= fDataSourceCnt (%lu)\n",
+                __FILE__, __LINE__, fBlocks[ndx].fSource, fDataSourceCnt );
+       return NULL;
+       }
+#endif
+    return fDataSources[ fBlocks[ndx].fSource ].fHostname;
+    //return fBlocks[ndx].fOriginatingNodeID;
+    }
+
+       /* Return byte order of the data stored in the 
+          current event's data block with the given block 
+          index (starting at 0). 
+          0 is unknown alignment, 
+          1 ist little endian, 
+          2 is big endian. */
+homer_uint8 HOMERReader::GetBlockByteOrder( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return 0;
+    //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
+    return *(((homer_uint8*)fBlocks[ndx].fMetaData)+kByteOrderAttribute_8b_Offset);
+    }
+       /* Return the alignment (in bytes) of the given datatype 
+          in the data stored in the current event's data block
+          with the given block index (starting at 0). 
+          Possible values for the data type are
+          0: homer_uint64
+          1: homer_uint32
+          2: uin16
+          3: homer_uint8
+          4: double
+          5: float
+       */
+homer_uint8 HOMERReader::GetBlockTypeAlignment( unsigned long ndx, homer_uint8 dataType ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return 0;
+    if ( dataType > (kFloatAlignment_8b_Offset-kAlignment_8b_StartOffset) )
+       return 0;
+    //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
+    return *(((homer_uint8*)fBlocks[ndx].fMetaData)+kAlignment_8b_StartOffset+dataType);
+    }
+
+homer_uint64 HOMERReader::GetBlockStatusFlags( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return 0;
+    return *(((homer_uint64*)fBlocks[ndx].fMetaData)+kStatusFlags_64b_Offset);
+    }
+
+/* HOMER specific */
+/* Return the type of the data in the current event's data
+   block with the given block index (starting at 0). */
+homer_uint64 HOMERReader::GetBlockDataType( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return ~(homer_uint64)0;
+    //return ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fType.fID;
+    return *(((homer_uint64*)fBlocks[ndx].fMetaData)+kType_64b_Offset);
+    }
+
+/* Return the origin of the data in the current event's data
+   block with the given block index (starting at 0). */
+homer_uint32 HOMERReader::GetBlockDataOrigin( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return ~(homer_uint32)0;
+    //return (homer_uint32)( ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fSubType1.fID );
+    return (homer_uint32)*(((homer_uint64*)fBlocks[ndx].fMetaData)+kSubType1_64b_Offset);
+    }
+
+/* Return a specification of the data in the current event's data
+   block with the given block index (starting at 0). */
+homer_uint32 HOMERReader::GetBlockDataSpec( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return ~(homer_uint32)0;
+    //return (homer_uint32)( ((AliHLTRIBlockDescriptorV1*)fBlocks[ndx].fMetaData)->fSubType2.fID );
+    return (homer_uint32)*(((homer_uint64*)fBlocks[ndx].fMetaData)+kSubType2_64b_Offset);
+    }
+
+/* Find the next data block in the current event with the given
+   data type, origin, and specification. Returns the block's 
+   index. */
+unsigned long HOMERReader::FindBlockNdx( homer_uint64 type, homer_uint32 origin, 
+                                        homer_uint32 spec, unsigned long startNdx ) const
+    {
+    for ( unsigned long n=startNdx; n < fBlockCnt; n++ )
+       {
+       if ( ( type == 0xFFFFFFFFFFFFFFFFULL || *(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset)==type ) &&
+            ( origin == 0xFFFFFFFF || (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset) )==origin ) &&
+            ( spec == 0xFFFFFFFF || (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset) )==spec ) )
+           return n;
+       }
+    return ~(unsigned long)0;
+    }
+
+/* Find the next data block in the current event with the given
+   data type, origin, and specification. Returns the block's 
+   index. */
+unsigned long HOMERReader::FindBlockNdx( char type[8], char origin[4], 
+                                        homer_uint32 spec, unsigned long startNdx ) const
+    {
+    for ( unsigned long n=startNdx; n < fBlockCnt; n++ )
+       {
+       bool found1=true, found2=true;
+       for ( unsigned i = 0; i < 8; i++ )
+           {
+           if ( type[i] != (char)0xFF )
+               {
+               found1=false;
+               break;
+               }
+           }
+       if ( !found1 )
+           {
+           found1 = true;
+           for ( unsigned i = 0; i < 8; i++ )
+               {
+               //printf( "%u: Comparing type '%c' and '%c'\n", i, ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset))[i], type[i] );
+               if ( ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kType_64b_Offset))[i] != type[i] )
+                   {
+                   found1=false;
+                   break;
+                   }
+               }
+           }
+       for ( unsigned i = 0; i < 4; i++ )
+           {
+           if ( origin[i] != (char)0xFF )
+               {
+               found2 = false;
+               break;
+               }
+           }
+       if ( !found2 )
+           {
+           found2 = true;
+           for ( unsigned i = 0; i < 4; i++ )
+               {
+               //printf( "Comparing origin '%c' and '%c'\n", ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset))[i], origin[i] );
+               if ( ((char*)(((homer_uint64*)fBlocks[n].fMetaData)+kSubType1_64b_Offset))[i] != origin[i] )
+                   {
+                   found2=false;
+                   break;
+                   }
+               }
+           }
+       //printf( "Comparing spec '0x%08lX' and '0x%08lX'\n", (homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset) ), spec );
+       if ( found1 && found2 &&
+            ( spec == 0xFFFFFFFF || ((homer_uint32)( *(((homer_uint64*)fBlocks[n].fMetaData)+kSubType2_64b_Offset)) )==spec ) )
+           return n;
+       }
+    return ~(unsigned long)0;
+    }
+
+/* Return the ID of the node that actually produced this data block.
+   This may be different from the node which sent the data to this
+   monitoring object as returned by GetBlockSendNodeID. */
+const char* HOMERReader::GetBlockCreateNodeID( unsigned long ndx ) const
+    {
+    if ( ndx >= fBlockCnt )
+       return NULL;
+    return fBlocks[ndx].fOriginatingNodeID;
+    }
+
+
+void HOMERReader::Init()
+    {
+    fCurrentEventType = ~(homer_uint64)0;
+    fCurrentEventID = ~(homer_uint64)0;
+    fMaxBlockCnt = fBlockCnt = 0;
+    fBlocks = NULL;
+       
+    fDataSourceMaxCnt = fDataSourceCnt = fTCPDataSourceCnt = fShmDataSourceCnt = 0;
+    fDataSources = NULL;
+
+       
+    fConnectionStatus = 0;
+    fErrorConnection = ~(unsigned int)0;
+
+    fEventRequestAdvanceTime_us = 0;
+    }
+       
+bool HOMERReader::AllocDataSources( unsigned int sourceCnt )
+    {
+    fDataSources = new DataSource[ sourceCnt ];
+    if ( !fDataSources )
+       return false;
+    fDataSourceCnt = 0;
+    fDataSourceMaxCnt = sourceCnt;
+    return true;
+    }
+
+int HOMERReader::AddDataSource( const char* hostname, unsigned short port, DataSource& source )
+    {
+    struct hostent* he;
+    he = gethostbyname( hostname );
+    if ( he == NULL )
+       {
+       //fprintf( stderr, "Unable to determine remote host address from '%s'.\n", hostname );
+       return EADDRNOTAVAIL;
+       }
+
+    struct sockaddr_in remoteAddr;
+    remoteAddr.sin_family = AF_INET;    // host byte order 
+    remoteAddr.sin_port = htons(port);  // short, network byte order 
+    remoteAddr.sin_addr = *((struct in_addr *)he->h_addr);
+    memset(&(remoteAddr.sin_zero), '\0', 8);  // zero the rest of the struct
+
+    // Create socket and connect to target program on remote node
+    source.fTCPConnection = socket( AF_INET, SOCK_STREAM, 0 );
+    if ( source.fTCPConnection == -1 )
+       {
+       return errno;
+        }
+
+    int ret;
+
+    ret = connect( source.fTCPConnection, (struct sockaddr *)&remoteAddr, sizeof(struct sockaddr) );
+    if ( ret == -1 )
+       {
+       ret=errno;
+       close( source.fTCPConnection );
+       return ret;
+       } 
+
+    ret = write( source.fTCPConnection, MOD_BIN, strlen(MOD_BIN) );
+    if ( ret != (int)strlen(MOD_BIN) )
+       {
+       ret=errno;
+       close( source.fTCPConnection );
+       return ret;
+       }
+
+    char* tmpchar = new char[ strlen( hostname )+1 ];
+    if ( !tmpchar )
+       {
+       close( source.fTCPConnection );
+       return ENOMEM;
+       }
+    strcpy( tmpchar, hostname );
+    source.fHostname = tmpchar;
+
+    source.fType = kTCP;
+    source.fTCPPort = port;
+    source.fData = NULL;
+    source.fDataSize = 0;
+    source.fDataRead = 0;
+    return 0;
+    }
+
+int HOMERReader::AddDataSource( key_t shmKey, int shmSize, DataSource& source )
+    {
+    int ret;
+    char* tmpchar = new char[ MAXHOSTNAMELEN+1 ];
+    if ( !tmpchar )
+       {
+       return ENOMEM;
+       }
+    gethostname( tmpchar, MAXHOSTNAMELEN );
+    tmpchar[MAXHOSTNAMELEN]=(char)0;
+    source.fHostname = tmpchar;
+
+    source.fShmID = shmget( shmKey, shmSize, 0660 );
+    if ( source.fShmID == -1 )
+       {
+       ret = errno;
+       delete [] source.fHostname;
+       return ret;
+       }
+    
+    source.fShmPtr = (void*)shmat( source.fShmID, NULL, 0 );
+
+    if ( !source.fShmPtr )
+       {
+       ret = errno;
+       shmctl( source.fShmID, IPC_RMID, NULL );
+       delete [] source.fHostname;
+       return ret;
+       }
+
+    source.fType = kShm;
+    source.fShmKey = shmKey;
+    source.fShmSize = shmSize;
+    source.fDataSize = 0;
+    source.fDataRead = 0;
+    return 0;
+    }
+
+void HOMERReader::FreeDataSources()
+    {
+    for ( unsigned n=0; n < fDataSourceCnt; n++ )
+       {
+       if ( fDataSources[n].fType == kTCP )
+           FreeTCPDataSource( fDataSources[n] );
+       else
+           FreeShmDataSource( fDataSources[n] );
+       }
+    }
+
+int HOMERReader::FreeShmDataSource( DataSource& source )
+    {
+    if ( source.fShmPtr )
+       shmdt( source.fShmPtr );
+//     if ( source.fShmID != -1 )
+//     shmctl( source.fShmID, IPC_RMID, NULL );
+    if ( source.fHostname )
+       delete [] source.fHostname;
+    return 0;
+    }
+
+int HOMERReader::FreeTCPDataSource( DataSource& source )
+    {
+    if ( source.fTCPConnection )
+       close( source.fTCPConnection );
+    if ( source.fHostname )
+       delete [] source.fHostname;
+    return 0;
+    }
+
+int HOMERReader::ReadNextEvent( bool useTimeout, unsigned long timeout )
+    {
+    if ( fDataSourceCnt<=0 )
+       return ENXIO;
+    // Clean up currently active event.
+    ReleaseCurrentEvent();
+    int ret;
+    // Trigger all configured data sources
+    for ( unsigned n = 0; n<fDataSourceCnt; n++ )
+       {
+       if ( fDataSources[n].fType == kTCP )
+           ret = TriggerTCPSource( fDataSources[n], useTimeout, timeout );
+       else
+           ret = TriggerShmSource( fDataSources[n], useTimeout, timeout );
+       if ( ret )
+           {
+           fErrorConnection = n;
+           fConnectionStatus=ret;
+           return fConnectionStatus;
+           }
+       }
+    // Now read in data from the configured data source
+    ret = ReadDataFromTCPSources( fTCPDataSourceCnt, fDataSources, useTimeout, timeout );
+    if ( ret )
+       {
+       return ret;
+       }
+    ret = ReadDataFromShmSources( fShmDataSourceCnt, fDataSources+fTCPDataSourceCnt, useTimeout, timeout );
+    if ( ret )
+       {
+       return ret;
+       }
+//     for ( unsigned n = 0; n<fDataSourceCnt; n++ )
+//     {
+//     if ( fDataSources[n].fType == kTCP )
+//         ret = ReadDataFromTCPSource( fDataSources[n], useTimeout, timeout );
+//     else
+//         ret = ReadDataFromShmSource( fDataSources[n], useTimeout, timeout );
+//     if ( ret )
+//         {
+//         fErrorConnection = n;
+//         fConnectionStatus=ret;
+//         return fConnectionStatus;
+//         }
+//     }
+    //Check to see that all sources contributed data for the same event
+    homer_uint64 eventID;
+    homer_uint64 eventType;
+    eventID = GetSourceEventID( fDataSources[0] );
+    eventType = GetSourceEventType( fDataSources[0] );
+    for ( unsigned n = 1; n < fDataSourceCnt; n++ )
+       {
+       if ( GetSourceEventID( fDataSources[n] ) != eventID || GetSourceEventType( fDataSources[n] ) != eventType )
+           {
+           fErrorConnection = n;
+           fConnectionStatus=EBADRQC;
+           return fConnectionStatus;
+           }
+       }
+    // Find all the different data blocks contained in the data from all
+    // the sources.
+    for ( unsigned n = 0; n < fDataSourceCnt; n++ )
+       {
+       ret = ParseSourceData( fDataSources[n] );
+       if ( ret )
+           {
+           fErrorConnection = n;
+           fConnectionStatus=EBADSLT;
+           return fConnectionStatus;
+           }
+       }
+    fCurrentEventID = eventID;
+    fCurrentEventType = eventType;
+    return 0;
+    }
+
+void HOMERReader::ReleaseCurrentEvent()
+    {
+    // sources.fDataRead = 0;
+    // fMaxBlockCnt
+    fCurrentEventID = ~(homer_uint64)0;
+    fCurrentEventType = ~(homer_uint64)0;
+    for ( unsigned n = 0; n < fDataSourceCnt; n++ )
+       {
+       if ( fDataSources[n].fData )
+           {
+           if ( fDataSources[n].fType == kTCP )
+               delete [] (homer_uint8*)fDataSources[n].fData;
+           fDataSources[n].fData = NULL;
+           }
+       fDataSources[n].fDataSize = fDataSources[n].fDataRead = 0;
+       }
+    if ( fBlocks )
+       {
+       for ( unsigned n = 0; n < fMaxBlockCnt; n++ )
+           {
+           if ( fBlocks[n].fOriginatingNodeID )
+               delete [] fBlocks[n].fOriginatingNodeID;
+           }
+       delete [] fBlocks;
+       fBlocks=0;
+       fMaxBlockCnt = 0;
+       fBlockCnt=0;
+       }
+    }
+
+int HOMERReader::TriggerTCPSource( DataSource& source, bool useTimeout, unsigned long timeout_us )
+    {
+    int ret;
+    struct timeval oldSndTO, newSndTO;
+    if ( useTimeout )
+       {
+       socklen_t optlen=sizeof(oldSndTO);
+       ret = getsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, &optlen );
+       if ( ret )
+           {
+           return errno;
+           }
+       if ( optlen!=sizeof(oldSndTO) )
+           {
+           return ENXIO;
+           }
+       newSndTO.tv_sec = timeout_us / 1000000;
+       newSndTO.tv_usec = timeout_us - (newSndTO.tv_sec*1000000);
+       ret = setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &newSndTO, sizeof(newSndTO) );
+       if ( ret )
+           {
+           return errno;
+           }
+       }
+    // Send one event request
+    if ( !fEventRequestAdvanceTime_us )
+       {
+       ret = write( source.fTCPConnection, GET_ONE, strlen(GET_ONE) );
+       
+       if ( ret != (int)strlen(GET_ONE) )
+           {
+           ret=errno;
+           setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
+           return ret;
+           }
+       }
+    else
+       {
+       char tmpCmd[ 128 ];
+
+       int len = snprintf( tmpCmd, 128, "FIRST ORBIT EVENT 0x%Lu\n", (unsigned long long)fEventRequestAdvanceTime_us );
+       if ( len>128 || len<0 )
+           {
+           ret=EMSGSIZE;
+           setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
+           return ret;
+           }
+       
+       ret = write( source.fTCPConnection, tmpCmd, strlen(tmpCmd) );
+       
+       if ( ret != (int)strlen(tmpCmd) )
+           {
+           ret=errno;
+           setsockopt( source.fTCPConnection, SOL_SOCKET, SO_SNDTIMEO, &oldSndTO, sizeof(oldSndTO) );
+           return ret;
+           }
+       
+       }
+    return 0;
+    }
+
+int HOMERReader::TriggerShmSource( DataSource& source, bool, unsigned long )
+    {
+    if ( source.fShmPtr )
+       {
+       *(homer_uint32*)( source.fShmPtr ) = 0;
+       return 0;
+       }
+    else
+       return EFAULT;
+    }
+
+int HOMERReader::ReadDataFromTCPSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout )
+    {
+    bool toRead = false;
+    do
+       {
+       fd_set conns;
+       FD_ZERO( &conns );
+       int highestConn=0;
+       toRead = false;
+       unsigned firstConnection=~(unsigned)0;
+       for ( unsigned long n = 0; n < sourceCnt; n++ )
+           {
+           if ( sources[n].fDataSize == 0 // size specifier not yet read
+                || sources[n].fDataRead < sources[n].fDataSize ) // Data not yet read fully
+               {
+               toRead = true;
+               FD_SET( sources[n].fTCPConnection, &conns );
+               if ( sources[n].fTCPConnection > highestConn )
+                   highestConn = sources[n].fTCPConnection;
+               fcntl( sources[n].fTCPConnection, F_SETFL, O_NONBLOCK );
+               if ( firstConnection == ~(unsigned)0 )
+                   firstConnection = n;
+               }
+           else
+               {
+               fcntl( sources[n].fTCPConnection, F_SETFL, 0 );
+               }
+           }
+       if ( toRead )
+           {
+           struct timeval tv, *ptv;
+           if ( useTimeout )
+               {
+               tv.tv_sec = timeout / 1000000;
+               tv.tv_usec = timeout - (tv.tv_sec*1000000);
+               ptv = &tv;
+               }
+           else
+               ptv = NULL;
+           // wait until something is ready to be read
+           // either for timeout usecs or until eternity
+           int ret;
+           ret = select( highestConn+1, &conns, NULL, NULL, ptv ); 
+           if ( ret <=0 )
+               {
+               fErrorConnection = firstConnection;
+               if ( errno )
+                   fConnectionStatus = errno;
+               else
+                   fConnectionStatus = ETIMEDOUT;
+               return fConnectionStatus;
+               }
+           for ( unsigned n = 0; n < sourceCnt; n++ )
+               {
+               if ( FD_ISSET( sources[n].fTCPConnection, &conns ) )
+                   {
+                   if ( sources[n].fDataSize == 0 )
+                       {
+                       ret=read( sources[n].fTCPConnection, &(sources[n].fDataSize), sizeof(homer_uint32) );
+                       if ( ret != sizeof(homer_uint32) )
+                           {
+                           fErrorConnection = n;
+                           if ( errno )
+                               fConnectionStatus = errno;
+                           else
+                               fConnectionStatus = ENOMSG;
+                           return fConnectionStatus;
+                           }
+                       sources[n].fDataSize = ntohl( sources[n].fDataSize );
+                       sources[n].fDataRead = 0;
+                       sources[n].fData = new homer_uint8[ sources[n].fDataSize ];
+                       if ( !sources[n].fData )
+                           {
+                           fErrorConnection = n;
+                           fConnectionStatus = ENOMEM;
+                           return fConnectionStatus;
+                           }
+                       }
+                   else if ( sources[n].fData && sources[n].fDataRead < sources[n].fDataSize)
+                       {
+                       ret=read( sources[n].fTCPConnection, ((homer_uint8*)sources[n].fData)+sources[n].fDataRead, sources[n].fDataSize-sources[n].fDataRead );
+                       if ( ret>0 )
+                           sources[n].fDataRead += ret;
+                       else if ( ret == 0 )
+                           {
+                           fErrorConnection = n;
+                           fConnectionStatus = ECONNRESET;
+                           return fConnectionStatus;
+                           }
+                       else
+                           {
+                           fErrorConnection = n;
+                           fConnectionStatus = errno;
+                           return fConnectionStatus;
+                           }
+                       }
+                   else
+                       {
+                       fErrorConnection = n;
+                       fConnectionStatus = ENXIO;
+                       return fConnectionStatus;
+                       }
+                   }
+               }
+           }
+       }
+    while ( toRead );
+    return 0;
+    }
+
+/*
+int HOMERReader::ReadDataFromTCPSources( DataSource& source, bool useTimeout, unsigned long timeout )
+    {
+#warning TODO If useTimeout: Set sockets to nonblocking, select + loop around GET_ONE write
+    // Send one event request
+    ret = write( source.fTCPConnection, GET_ONE, strlen(GET_ONE) );
+    if ( ret != strlen(GET_ONE) )
+       {
+       return errno;
+       }
+    // wait for and read back size specifier
+    unsigned sizeNBO;
+    // The value transmitted is binary, in network byte order
+    ret = read( source.fTCPConnection, &sizeNBO, sizeof(sizeNBO) );
+    if ( ret != sizeof(sizeNBO) )
+       {
+       return errno;
+       }
+    // Convert back to host byte order
+    source.fDataSize = ntohl( sizeNBO );
+    source.fData = new homer_uint8[ source.fDataSize ];
+    unsigned long dataRead=0, toRead;
+    if ( !source.fData )
+       {
+       char buffer[1024];
+       // Read in data into buffer in order not to block connection
+       while ( dataRead < source.fDataSize )
+           {
+           if ( source.fDataSize-dataRead > 1024 )
+               toRead = 1024;
+           else
+               toRead = source.fDataSize-dataRead;
+           ret = read( source.fTCPConnection, buffer, toRead );
+           if ( ret > 0 )
+               dataRead += ret;
+           else
+               return errno;
+           }
+       return ENOMEM;
+       }
+    while ( dataRead < source.fDataSize )
+       {
+       toRead = source.fDataSize-dataRead;
+       ret = read( source.fTCPConnection, source.fData+dataRead, toRead );
+       if ( ret > 0 )
+           dataRead += ret;
+       else if ( ret == 0 && useTimeout )
+           {
+           struct timeval tv;
+           tv.tv_sec = timeout / 1000000;
+           tv.tv_usec = timeout - (tv.tv_sec*1000000);
+           fd_set conns;
+           FD_ZERO( &conns );
+           FD_SET( source.fTCPConnection, &conns );
+           ret = select( source.fTCPConnection+1, &conns, NULL, NULL );
+           if ( ret <=0 )
+               return errno;
+           }
+       else if ( ret == 0 )
+           {
+           if ( errno == EOK )
+               return ECONNRESET;
+           else
+               return errno;
+           }
+       else
+           {
+           return errno;
+           }
+       }
+    return 0;
+    }
+*/
+
+/*
+int HOMERReader::ReadDataFromShmSource( DataSource& source, bool useTimeout, unsigned long timeout )
+    {
+    
+    }
+*/
+
+int HOMERReader::ReadDataFromShmSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout )
+    {
+    struct timeval tv1, tv2;
+    bool found=false;
+    bool all=true;
+    if ( useTimeout )
+       gettimeofday( &tv1, NULL );
+    do
+       {
+       found = false;
+       all = true;
+       for ( unsigned n = 0; n < sourceCnt; n++ )
+           {
+           if ( !sources[n].fDataSize )
+               all = false;
+           if ( sources[n].fShmPtr && *(homer_uint32*)sources[n].fShmPtr>0 && !sources[n].fDataSize )
+               {
+               found = true;
+               sources[n].fDataSize = *(homer_uint32*)sources[n].fShmPtr;
+               sources[n].fData = ((homer_uint8*)sources[n].fShmPtr)+sizeof(homer_uint32);
+               }
+           }
+       if ( found && useTimeout )
+           gettimeofday( &tv1, NULL );
+       if ( !all && useTimeout )
+           {
+           gettimeofday( &tv2, NULL );
+           unsigned long long tdiff;
+           tdiff = tv2.tv_sec-tv1.tv_sec;
+           tdiff *= 1000000;
+           tdiff += tv2.tv_usec-tv1.tv_usec;
+           if ( tdiff > timeout )
+               return ETIMEDOUT;
+           }
+       if ( !all )
+           usleep( 0 );
+       }
+    while ( !all );
+    return 0;
+    }
+
+int HOMERReader::ParseSourceData( DataSource& source )
+    {
+    if ( source.fData )
+       {
+       homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
+       homer_uint64 blockCnt = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kSubType2_64b_Offset ] );
+       int ret=ReAllocBlocks( fMaxBlockCnt+blockCnt );
+       if ( ret )
+           return ret;
+       homer_uint64 descrOffset = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kOffset_64b_Offset ] );
+       for ( homer_uint64 n = 0; n < blockCnt && fBlockCnt < fMaxBlockCnt; n++, fBlockCnt++ )
+           {
+           homer_uint8* descr = ((homer_uint8*)source.fData)+descrOffset;
+           unsigned descrLen = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kLength_64b_Offset ] );
+           fBlocks[fBlockCnt].fSource = source.fNdx;
+           fBlocks[fBlockCnt].fData = ((homer_uint8*)source.fData) + Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kOffset_64b_Offset ] );
+           fBlocks[fBlockCnt].fLength = Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)descr)[ kSize_64b_Offset ] );
+           fBlocks[fBlockCnt].fMetaData = (homer_uint64*)descr;
+           struct in_addr tmpA;
+           tmpA.s_addr = (homer_uint32)( ((homer_uint64*)descr)[ kProducerNode_64b_Offset ] );
+           char* addr = inet_ntoa( tmpA );
+           char* tmpchar = new char[ strlen(addr)+1 ];
+           if ( !tmpchar )
+               return ENOMEM;
+           strcpy( tmpchar, addr );
+           fBlocks[fBlockCnt].fOriginatingNodeID = tmpchar;
+           descrOffset += descrLen;
+           }
+       return 0;
+       }
+    return EFAULT;
+    }
+       
+int HOMERReader::ReAllocBlocks( unsigned long newCnt )
+    {
+    DataBlock* newBlocks;
+    newBlocks = new DataBlock[ newCnt ];
+    if ( !newBlocks )
+       return ENOMEM;
+    unsigned long cpCnt = (newCnt > fMaxBlockCnt) ? fMaxBlockCnt : newCnt;
+    memcpy( newBlocks, fBlocks, cpCnt*sizeof(DataBlock) );
+    if ( newCnt > fMaxBlockCnt )
+       memset( newBlocks+fMaxBlockCnt, 0, (newCnt-fMaxBlockCnt)*sizeof(DataBlock) );
+    if ( fBlocks )
+       delete [] fBlocks;
+    fBlocks = newBlocks;
+    fMaxBlockCnt = newCnt;
+    return 0;
+    }
+
+homer_uint64 HOMERReader::GetSourceEventID( DataSource& source )
+    {
+    homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
+    return Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kSubType1_64b_Offset ] );
+    }
+
+homer_uint64 HOMERReader::GetSourceEventType( DataSource& source )
+    {
+    homer_uint8 sourceByteOrder = ((homer_uint8*)source.fData)[ kByteOrderAttribute_8b_Offset ];
+    return Swap( kHOMERNativeByteOrder, sourceByteOrder, ((homer_uint64*)source.fData)[ kType_64b_Offset ] );
+    }
+
+
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
diff --git a/HLT/BASE/HOMER/AliHLTHOMERReader.h b/HLT/BASE/HOMER/AliHLTHOMERReader.h
new file mode 100644 (file)
index 0000000..2cd8fe6
--- /dev/null
@@ -0,0 +1,310 @@
+// XEMacs -*-C++-*-
+#ifndef _HOMER_H_
+#define _HOMER_H_
+/* This file is property of and copyright by the ALICE HLT Project        * 
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ * See cxx source for full Copyright notice                               */
+
+/** @file   AliHLTHomerReader.h
+    @author Timm Steinbeck
+    @date   Sep 14 2007
+    @brief  HLT Online Monitoring Environment including ROOT - Reader
+    @note   migrated from PubSub HLT-stable-20070905.141318 (rev 2375)    */
+
+// see below for class documentation
+// or
+// refer to README to build package
+// or
+// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+
+#include <limits.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "AliHLTHOMERData.h"
+
+
+
+
+class MonitoringReader
+    {
+    public:
+
+       MonitoringReader() {};
+       virtual ~MonitoringReader() {};
+       
+       /* Read in the next available event */
+       virtual int ReadNextEvent() = 0;
+       /* Read in the next available event, wait max. timeout microsecs. */
+       virtual int ReadNextEvent( unsigned long timeout ) = 0;
+       
+       /* Return the type of the current event */
+       virtual homer_uint64 GetEventType() const = 0;
+
+       /* Return the ID of the current event */
+       virtual homer_uint64 GetEventID() const = 0;
+       
+       /* Return the number of data blocks in the current event */
+       virtual unsigned long GetBlockCnt() const = 0;
+       
+       /* Return the size (in bytes) of the current event's data
+          block with the given block index (starting at 0). */
+       virtual unsigned long GetBlockDataLength( unsigned long ndx ) const = 0;
+       /* Return a pointer to the start of the current event's data
+          block with the given block index (starting at 0). */
+       virtual const void* GetBlockData( unsigned long ndx ) const = 0;
+       /* Return IP address or hostname of node which sent the 
+          current event's data block with the given block index 
+          (starting at 0). */
+       virtual const char* GetBlockSendNodeID( unsigned long ndx ) const = 0;
+       /* Return byte order of the data stored in the 
+          current event's data block with the given block 
+          index (starting at 0). 
+          0 is unknown alignment, 
+          1 ist little endian, 
+          2 is big endian. */
+       virtual homer_uint8 GetBlockByteOrder( unsigned long ndx ) const = 0;
+       /* Return the alignment (in bytes) of the given datatype 
+          in the data stored in the current event's data block
+          with the given block index (starting at 0). 
+          Possible values for the data type are
+          0: homer_uint64
+          1: homer_uint32
+          2: uin16
+          3: homer_uint8
+          4: double
+          5: float
+       */
+       virtual homer_uint8 GetBlockTypeAlignment( unsigned long ndx, homer_uint8 dataType ) const = 0;
+
+       virtual homer_uint64 GetBlockStatusFlags( unsigned long ndx ) const = 0;
+
+#ifdef USE_ROOT
+        ClassDef(MonitoringReader,1);
+#endif
+    };
+
+
+
+class HOMERReader: public MonitoringReader
+    {
+    public:
+#ifdef USE_ROOT
+       HOMERReader();
+#endif
+
+       /* Constructors & destructors, HOMER specific */
+       /* For reading from a TCP port */
+       HOMERReader( const char* hostname, unsigned short port );
+       /* For reading from multiple TCP ports */
+       HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports );
+       /* For reading from a System V shared memory segment */
+       HOMERReader( key_t shmKey, int shmSize );
+       /* For reading from multiple System V shared memory segments */
+       HOMERReader( unsigned int shmCnt, key_t* shmKey, int* shmSize );
+       /* For reading from multiple TCP ports and multiple System V shared memory segments */
+       HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports, 
+                    unsigned int shmCnt, key_t* shmKey, int* shmSize );
+       virtual ~HOMERReader();
+
+       /* Return the status of the connection as established by one of the constructors.
+          0 means connection is ok, non-zero specifies the type of error that occured. */
+       int GetConnectionStatus() const
+               {
+               return fConnectionStatus;
+               }
+
+       /* Return the index of the connection for which an error given by the above
+          function occured. */
+       unsigned int GetErrorConnectionNdx() const
+               {
+               return fErrorConnection;
+               }
+
+       void SetEventRequestAdvanceTime( unsigned long time_us )
+               {
+               fEventRequestAdvanceTime_us = time_us;
+               }
+
+       /* Defined in MonitoringReader */
+       /* Read in the next available event */
+       virtual int  ReadNextEvent();
+       /* Read in the next available event */
+       virtual int ReadNextEvent( unsigned long timeout );
+
+       /* Return the type of the current event */
+       virtual homer_uint64 GetEventType() const
+               {
+               return fCurrentEventType;
+               }
+
+       /* Return the ID of the current event */
+       virtual homer_uint64 GetEventID() const
+               {
+               return fCurrentEventID;
+               }
+
+       /* Return the number of data blocks in the current event */
+       virtual unsigned long GetBlockCnt() const
+               {
+               return fBlockCnt;
+               }
+
+       /* Return the size (in bytes) of the current event's data
+          block with the given block index (starting at 0). */
+       virtual const void* GetBlockData( unsigned long ndx ) const;
+       /* Return a pointer to the start of the current event's data
+          block with the given block index (starting at 0). */
+       virtual unsigned long GetBlockDataLength( unsigned long ndx ) const;
+       /* Return IP address or hostname of node which sent the 
+          current event's data block with the given block index 
+          (starting at 0).
+          For HOMER this is the ID of the node on which the subscriber 
+          that provided this data runs/ran. */
+       virtual const char* GetBlockSendNodeID( unsigned long ndx ) const;
+       /* Return byte order of the data stored in the 
+          current event's data block with the given block 
+          index (starting at 0). 
+          0 is unknown alignment, 
+          1 ist little endian, 
+          2 is big endian. */
+       virtual homer_uint8 GetBlockByteOrder( unsigned long ndx ) const;
+       /* Return the alignment (in bytes) of the given datatype 
+          in the data stored in the current event's data block
+          with the given block index (starting at 0). 
+          Possible values for the data type are
+          0: homer_uint64
+          1: homer_uint32
+          2: uin16
+          3: homer_uint8
+          4: double
+          5: float
+       */
+       virtual homer_uint8 GetBlockTypeAlignment( unsigned long ndx, homer_uint8 dataType ) const;
+
+       virtual homer_uint64 GetBlockStatusFlags( unsigned long ndx ) const;
+
+       /* HOMER specific */
+       /* Return the type of the data in the current event's data
+          block with the given block index (starting at 0). */
+       homer_uint64 GetBlockDataType( unsigned long ndx ) const;
+       /* Return the origin of the data in the current event's data
+          block with the given block index (starting at 0). */
+       homer_uint32 GetBlockDataOrigin( unsigned long ndx ) const;
+       /* Return a specification of the data in the current event's data
+          block with the given block index (starting at 0). */
+       homer_uint32 GetBlockDataSpec( unsigned long ndx ) const;
+
+       /* Find the next data block in the current event with the given
+          data type, origin, and specification. Returns the block's 
+          index. */
+       unsigned long FindBlockNdx( homer_uint64 type, homer_uint32 origin, 
+                                   homer_uint32 spec, unsigned long startNdx=0 ) const;
+
+       /* Find the next data block in the current event with the given
+          data type, origin, and specification. Returns the block's 
+          index. */
+       unsigned long FindBlockNdx( char type[8], char origin[4], 
+                                   homer_uint32 spec, unsigned long startNdx=0 ) const;
+       
+       /* Return the ID of the node that actually produced this data block.
+          This may be different from the node which sent the data to this
+          monitoring object as returned by GetBlockSendNodeID. */
+       const char* GetBlockCreateNodeID( unsigned long ndx ) const;
+
+    protected:
+
+       enum DataSourceType { kUndef=0, kTCP, kShm };
+       struct DataSource
+           {
+               DataSource() { fType = kUndef; };
+               DataSourceType fType;
+               unsigned fNdx; // This source's index
+               const char* fHostname; // Filled for both Shm and TCP
+               unsigned short fTCPPort;
+               key_t fShmKey;
+               int fShmSize;
+               int fTCPConnection; // File descriptor for the TCP connection
+               int fShmID; // ID of the shared memory area
+               void* fShmPtr; // Pointer to shared memory area
+               void* fData; // Pointer to data read in for current event from this source
+               unsigned long fDataSize; // Size of data (to be) read in for current event from this source
+               unsigned long fDataRead; // Data actually read for current event
+           };
+
+       void Init();
+       
+       bool AllocDataSources( unsigned int sourceCnt );
+       int AddDataSource( const char* hostname, unsigned short port, DataSource& source );
+       int AddDataSource( key_t shmKey, int shmSize, DataSource& source );
+       void FreeDataSources();
+       int FreeShmDataSource( DataSource& source );
+       int FreeTCPDataSource( DataSource& source );
+       int ReadNextEvent( bool useTimeout, unsigned long timeout );
+       void ReleaseCurrentEvent();
+       int TriggerTCPSource( DataSource& source, bool useTimeout, unsigned long timeout );
+       int TriggerShmSource( DataSource& source, bool useTimeout, unsigned long timeout );
+       int ReadDataFromTCPSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout );
+       int ReadDataFromShmSources( unsigned sourceCnt, DataSource* sources, bool useTimeout, unsigned long timeout );
+       int ParseSourceData( DataSource& source );
+       int ReAllocBlocks( unsigned long newCnt );
+       homer_uint64 GetSourceEventID( DataSource& source );
+       homer_uint64 GetSourceEventType( DataSource& source );
+       homer_uint64 Swap( homer_uint8 destFormat, homer_uint8 sourceFormat, homer_uint64 source )
+               {
+               if ( destFormat == sourceFormat )
+                   return source;
+               else
+                   return ((source & 0xFFULL) << 56) | 
+                       ((source & 0xFF00ULL) << 40) | 
+                       ((source & 0xFF0000ULL) << 24) | 
+                       ((source & 0xFF000000ULL) << 8) | 
+                       ((source & 0xFF00000000ULL) >> 8) | 
+                       ((source & 0xFF0000000000ULL) >> 24) | 
+                       ((source & 0xFF000000000000ULL) >>  40) | 
+                       ((source & 0xFF00000000000000ULL) >> 56);
+               }
+       homer_uint32 Swap( homer_uint8 destFormat, homer_uint8 sourceFormat, homer_uint32 source )
+               {
+               if ( destFormat == sourceFormat )
+                   return source;
+               else
+                   return ((source & 0xFFUL) << 24) | 
+                       ((source & 0xFF00UL) << 8) | 
+                       ((source & 0xFF0000UL) >> 8) | 
+                       ((source & 0xFF000000UL) >> 24);
+               }
+
+
+       struct DataBlock
+           {
+               unsigned int fSource; // Index of originating data source
+               void* fData;
+               unsigned long fLength;
+               homer_uint64* fMetaData; // Pointer to meta data describing data itself.
+               const char* fOriginatingNodeID;
+           };
+
+       homer_uint64 fCurrentEventType;
+       homer_uint64 fCurrentEventID;
+       unsigned long fBlockCnt;
+       unsigned long fMaxBlockCnt;
+       DataBlock* fBlocks;
+       
+       unsigned int fDataSourceCnt;
+       unsigned int fTCPDataSourceCnt;
+       unsigned int fShmDataSourceCnt;
+       unsigned int fDataSourceMaxCnt;
+       DataSource* fDataSources;
+
+       
+       int fConnectionStatus;
+       unsigned fErrorConnection;
+
+       unsigned long fEventRequestAdvanceTime_us;
+
+#ifdef USE_ROOT
+        ClassDef(HOMERReader,2);
+#endif
+    };
+
+#endif /* _HOMER_H_ */
diff --git a/HLT/BASE/HOMER/AliHLTHOMERWriter.cxx b/HLT/BASE/HOMER/AliHLTHOMERWriter.cxx
new file mode 100644 (file)
index 0000000..c67a3d9
--- /dev/null
@@ -0,0 +1,382 @@
+/************************************************************************
+**
+**
+** This file is property of and copyright by the Technical Computer
+** Science Group, Kirchhoff Institute for Physics, Ruprecht-Karls-
+** University, Heidelberg, Germany, 2001
+** This file has been written by Timm Morten Steinbeck, 
+** timm@kip.uni-heidelberg.de
+**
+**
+** See the file license.txt for details regarding usage, modification,
+** distribution and warranty.
+** Important: This file is provided without any warranty, including
+** fitness for any particular purpose.
+**
+**
+** Newer versions of this file's package will be made available from 
+** http://web.kip.uni-heidelberg.de/Hardwinf/L3/ 
+** or the corresponding page of the Heidelberg Alice Level 3 group.
+**
+*************************************************************************/
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
+
+/** @file   AliHLTHomerWriter.cxx
+    @author Timm Steinbeck
+    @date   Sep 14 2007
+    @brief  HLT Online Monitoring Environment including ROOT - Writer   
+    @note   migrated from PubSub HLT-stable-20070905.141318 (rev 2375)    */
+
+// see below for class documentation
+// or
+// refer to README to build package
+// or
+// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+
+#include "AliHLTHOMERWriter.h"
+#include <sys/time.h>
+#include <time.h>
+
+
+HOMERWriter::HOMERWriter()
+    {
+    Clear();
+    }
+
+HOMERWriter::~HOMERWriter()
+    {
+    }
+
+void HOMERWriter::Clear()
+    {
+    fDataOffset = 0;
+    fBlocks.clear();
+    }
+
+void HOMERWriter::AddBlock( const void* descriptor, const void* data )
+    {
+    TBlockData bd;
+    memcpy( bd.fDescriptor, descriptor, HOMERBlockDescriptor::GetHOMERBlockDescriptorSize() );
+    bd.fData = data;
+    HOMERBlockDescriptor hbd( &bd.fDescriptor );
+    hbd.SetBlockOffset( fDataOffset );
+    fDataOffset += hbd.GetBlockSize();
+    fBlocks.push_back( bd );
+    }
+
+homer_uint32 HOMERWriter::GetTotalMemorySize( bool includeData )
+    {
+    if ( includeData )
+       return fDataOffset + HOMERBlockDescriptor::GetHOMERBlockDescriptorSize()*(fBlocks.size()+1);
+    else
+       return HOMERBlockDescriptor::GetHOMERBlockDescriptorSize()*(fBlocks.size()+1);
+    }
+
+void HOMERWriter::Copy( void* destination, homer_uint64 eventType, homer_uint64 eventNr, homer_uint64 statusFlags, homer_uint64 nodeID, bool includeData )
+    {
+    HOMERBlockDescriptor homerBlock;
+    homer_uint8* bd = reinterpret_cast<homer_uint8*>( destination );
+    struct timeval now;
+    gettimeofday( &now, NULL );
+    homerBlock.UseHeader( bd );
+    homerBlock.Initialize();
+    homerBlock.SetUInt64Alignment( HOMERWriter::DetermineUInt64Alignment() );
+    homerBlock.SetUInt32Alignment( HOMERWriter::DetermineUInt32Alignment() );
+    homerBlock.SetUInt16Alignment( HOMERWriter::DetermineUInt16Alignment() );
+    homerBlock.SetUInt8Alignment( HOMERWriter::DetermineUInt8Alignment() );
+    homerBlock.SetDoubleAlignment( HOMERWriter::DetermineDoubleAlignment() );
+    homerBlock.SetFloatAlignment( HOMERWriter::DetermineFloatAlignment() );
+    homerBlock.SetType( eventType );
+    homerBlock.SetSubType1( eventNr );
+    homerBlock.SetSubType2( fBlocks.size() );
+    homerBlock.SetBirth_s( now.tv_sec );
+    homerBlock.SetBirth_us( now.tv_usec );
+    homerBlock.SetProducerNode( nodeID );
+    homerBlock.SetBlockOffset( homerBlock.GetHeaderLength() );
+    homerBlock.SetBlockSize( HOMERBlockDescriptor::GetHOMERBlockDescriptorSize()*fBlocks.size() );
+    homerBlock.SetStatusFlags( statusFlags );
+    bd += homerBlock.GetHeaderLength();
+
+    //unsigned long dataOffset = HOMERBlockDescriptor::GetHOMERBlockDescriptorSize()*(fBlocks.size()+1);
+    unsigned long dataOffset = homerBlock.GetBlockOffset() + homerBlock.GetBlockSize();
+    std::vector<TBlockData>::iterator iter, end;
+    iter = fBlocks.begin();
+    end = fBlocks.end();
+    while ( iter != end )
+       {
+       homerBlock.UseHeader( iter->fDescriptor );
+       homerBlock.SetBlockOffset( homerBlock.GetBlockOffset()+dataOffset );
+       memcpy( bd, iter->fDescriptor, homerBlock.GetHeaderLength() );
+       bd += homerBlock.GetHeaderLength();
+       if ( includeData )
+           {
+           memcpy( ((homer_uint8*)destination)+homerBlock.GetBlockOffset(), iter->fData, homerBlock.GetBlockSize() );
+           }
+       iter++;
+       }
+    }
+       
+
+
+
+    struct HOMERWriterAlignment64TestStructure
+    {
+       homer_uint64 f64Fill;
+       homer_uint64 f64Test64;
+       homer_uint32 f32Fill;
+       homer_uint64 f64Test32;
+       homer_uint16 f16Fill;
+       homer_uint64 f64Test16;
+       homer_uint8  f8Fill;
+       homer_uint64 f64Test8;
+    };
+    struct HOMERWriterAlignment32TestStructure
+    {
+       homer_uint64 f64Fill;
+       homer_uint32 f32Test64;
+       homer_uint32 f32Fill;
+       homer_uint32 f32Test32;
+       homer_uint16 f16Fill;
+       homer_uint32 f32Test16;
+       homer_uint8  f8Fill;
+       homer_uint32 f32Test8;
+    };
+    struct HOMERWriterAlignment16TestStructure
+    {
+       homer_uint64 f64Fill;
+       homer_uint16 f16Test64;
+       homer_uint32 f32Fill;
+       homer_uint16 f16Test32;
+       homer_uint16 f16Fill;
+       homer_uint16 f16Test16;
+       homer_uint8  f8Fill;
+       homer_uint16 f16Test8;
+    };
+    struct HOMERWriterAlignment8TestStructure
+    {
+       homer_uint64 f64Fill;
+       homer_uint8 f8Test64;
+       homer_uint32 f32Fill;
+       homer_uint8 f8Test32;
+       homer_uint16 f16Fill;
+       homer_uint8 f8Test16;
+       homer_uint8  f8Fill;
+       homer_uint8 f8Test8;
+    };
+    struct HOMERWriterAlignmentDoubleTestStructure
+    {
+       homer_uint64 f64Fill;
+       double fDoubleTest64;
+       homer_uint32 f32Fill;
+       double fDoubleTest32;
+       homer_uint16 f16Fill;
+       double fDoubleTest16;
+       homer_uint8  f8Fill;
+       double fDoubleTest8;
+    };
+    struct HOMERWriterAlignmentFloatTestStructure
+    {
+       homer_uint64 f64Fill;
+       float fFloatTest64;
+       homer_uint32 f32Fill;
+       float fFloatTest32;
+       homer_uint16 f16Fill;
+       float fFloatTest16;
+       homer_uint8  f8Fill;
+       float fFloatTest8;
+    };
+
+homer_uint8 HOMERWriter::DetermineUInt64Alignment()
+    {
+    HOMERWriterAlignment64TestStructure test;
+    if ( (unsigned long)(&test.f64Test64) != ((unsigned long)(&test.f64Fill))+sizeof(test.f64Fill) )
+       {
+       // Alignment is beyond 64 bit, this is, to the best of my knowledge, currently unheard of.
+       return ~(homer_uint8)0;
+       }
+    if ( (unsigned long)(&test.f64Test32) != ((unsigned long)(&test.f32Fill))+sizeof(test.f32Fill) )
+       {
+       // The 64 bit element does not immedately follow the 32 bit element, 
+       // therefore the alignment has to be greater than 4.
+       return (homer_uint8)8;
+       }
+    if ( (unsigned long)(&test.f64Test16) != ((unsigned long)(&test.f16Fill))+sizeof(test.f16Fill) )
+       {
+       // The 64 bit element does not immedately follow the 16 bit element, 
+       // therefore the alignment has to be greater than 2.
+       return (homer_uint8)4;
+       }
+    if ( (unsigned long)(&test.f64Test8) != ((unsigned long)(&test.f8Fill))+sizeof(test.f8Fill) )
+       {
+       // The 64 bit element does not immedately follow the 8 bit element, 
+       // therefore the alignment has to be greater than 1.
+       return (homer_uint8)2;
+       }
+    return 1;
+    }
+
+homer_uint8 HOMERWriter::DetermineUInt32Alignment()
+    {
+    HOMERWriterAlignment32TestStructure test;
+    if ( (unsigned long)(&test.f32Test64) != ((unsigned long)(&test.f64Fill))+sizeof(test.f64Fill) )
+       {
+       // Alignment is beyond 64 bit, this is, to the best of my knowledge, currently unheard of.
+       return ~(homer_uint8)0;
+       }
+    if ( (unsigned long)(&test.f32Test32) != ((unsigned long)(&test.f32Fill))+sizeof(test.f32Fill) )
+       {
+       // The 32 bit element does not immedately follow the 32 bit element, 
+       // therefore the alignment has to be greater than 4.
+       return (homer_uint8)8;
+       }
+    if ( (unsigned long)(&test.f32Test16) != ((unsigned long)(&test.f16Fill))+sizeof(test.f16Fill) )
+       {
+       // The 32 bit element does not immedately follow the 16 bit element, 
+       // therefore the alignment has to be greater than 2.
+       return (homer_uint8)4;
+       }
+    if ( (unsigned long)(&test.f32Test8) != ((unsigned long)(&test.f8Fill))+sizeof(test.f8Fill) )
+       {
+       // The 32 bit element does not immedately follow the 8 bit element, 
+       // therefore the alignment has to be greater than 1.
+       return (homer_uint8)2;
+       }
+    return 1;
+    }
+
+homer_uint8 HOMERWriter::DetermineUInt16Alignment()
+    {
+    HOMERWriterAlignment16TestStructure test;
+    if ( (unsigned long)(&test.f16Test64) != ((unsigned long)(&test.f64Fill))+sizeof(test.f64Fill) )
+       {
+       // Alignment is beyond 64 bit, this is, to the best of my knowledge, currently unheard of.
+       return ~(homer_uint8)0;
+       }
+    if ( (unsigned long)(&test.f16Test32) != ((unsigned long)(&test.f32Fill))+sizeof(test.f32Fill) )
+       {
+       // The 16 bit element does not immedately follow the 32 bit element, 
+       // therefore the alignment has to be greater than 4.
+       return (homer_uint8)8;
+       }
+    if ( (unsigned long)(&test.f16Test16) != ((unsigned long)(&test.f16Fill))+sizeof(test.f16Fill) )
+       {
+       // The 16 bit element does not immedately follow the 16 bit element, 
+       // therefore the alignment has to be greater than 2.
+       return (homer_uint8)4;
+       }
+    if ( (unsigned long)(&test.f16Test8) != ((unsigned long)(&test.f8Fill))+sizeof(test.f8Fill) )
+       {
+       // The 16 bit element does not immedately follow the 8 bit element, 
+       // therefore the alignment has to be greater than 1.
+       return (homer_uint8)2;
+       }
+    return 1;
+    }
+
+homer_uint8 HOMERWriter::DetermineUInt8Alignment()
+    {
+    HOMERWriterAlignment8TestStructure test;
+    if ( (unsigned long)(&test.f8Test64) != ((unsigned long)(&test.f64Fill))+sizeof(test.f64Fill) )
+       {
+       // Alignment is beyond 64 bit, this is, to the best of my knowledge, currently unheard of.
+       return ~(homer_uint8)0;
+       }
+    if ( (unsigned long)(&test.f8Test32) != ((unsigned long)(&test.f32Fill))+sizeof(test.f32Fill) )
+       {
+       // The 8 bit element does not immedately follow the 32 bit element, 
+       // therefore the alignment has to be greater than 4.
+       return (homer_uint8)8;
+       }
+    if ( (unsigned long)(&test.f8Test16) != ((unsigned long)(&test.f16Fill))+sizeof(test.f16Fill) )
+       {
+       // The 8 bit element does not immedately follow the 16 bit element, 
+       // therefore the alignment has to be greater than 2.
+       return (homer_uint8)4;
+       }
+    if ( (unsigned long)(&test.f8Test8) != ((unsigned long)(&test.f8Fill))+sizeof(test.f8Fill) )
+       {
+       // The 8 bit element does not immedately follow the 8 bit element, 
+       // therefore the alignment has to be greater than 1.
+       return (homer_uint8)2;
+       }
+    return 1;
+    }
+
+homer_uint8 HOMERWriter::DetermineDoubleAlignment()
+    {
+    HOMERWriterAlignmentDoubleTestStructure test;
+    if ( (unsigned long)(&test.fDoubleTest64) != ((unsigned long)(&test.f64Fill))+sizeof(test.f64Fill) )
+       {
+       // Alignment is beyond 64 bit, this is, to the best of my knowledge, currently unheard of.
+       return ~(homer_uint8)0;
+       }
+    if ( (unsigned long)(&test.fDoubleTest32) != ((unsigned long)(&test.f32Fill))+sizeof(test.f32Fill) )
+       {
+       // The double element does not immedately follow the 32 bit element, 
+       // therefore the alignment has to be greater than 4.
+       return (homer_uint8)8;
+       }
+    if ( (unsigned long)(&test.fDoubleTest16) != ((unsigned long)(&test.f16Fill))+sizeof(test.f16Fill) )
+       {
+       // The double element does not immedately follow the 16 bit element, 
+       // therefore the alignment has to be greater than 2.
+       return (homer_uint8)4;
+       }
+    if ( (unsigned long)(&test.fDoubleTest8) != ((unsigned long)(&test.f8Fill))+sizeof(test.f8Fill) )
+       {
+       // The double element does not immedately follow the 8 bit element, 
+       // therefore the alignment has to be greater than 1.
+       return (homer_uint8)2;
+       }
+    return 1;
+    }
+
+homer_uint8 HOMERWriter::DetermineFloatAlignment()
+    {
+    HOMERWriterAlignmentFloatTestStructure test;
+    if ( (unsigned long)(&test.fFloatTest64) != ((unsigned long)(&test.f64Fill))+sizeof(test.f64Fill) )
+       {
+       // Alignment is beyond 64 bit, this is, to the best of my knowledge, currently unheard of.
+       return ~(homer_uint8)0;
+       }
+    if ( (unsigned long)(&test.fFloatTest32) != ((unsigned long)(&test.f32Fill))+sizeof(test.f32Fill) )
+       {
+       // The float element does not immedately follow the 32 bit element, 
+       // therefore the alignment has to be greater than 4.
+       return (homer_uint8)8;
+       }
+    if ( (unsigned long)(&test.fFloatTest16) != ((unsigned long)(&test.f16Fill))+sizeof(test.f16Fill) )
+       {
+       // The float element does not immedately follow the 16 bit element, 
+       // therefore the alignment has to be greater than 2.
+       return (homer_uint8)4;
+       }
+    if ( (unsigned long)(&test.fFloatTest8) != ((unsigned long)(&test.f8Fill))+sizeof(test.f8Fill) )
+       {
+       // The float element does not immedately follow the 8 bit element, 
+       // therefore the alignment has to be greater than 1.
+       return (homer_uint8)2;
+       }
+    return 1;
+    }
+
+
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
diff --git a/HLT/BASE/HOMER/AliHLTHOMERWriter.h b/HLT/BASE/HOMER/AliHLTHOMERWriter.h
new file mode 100644 (file)
index 0000000..5d954cf
--- /dev/null
@@ -0,0 +1,112 @@
+// XEMacs -*-C++-*-
+#ifndef _HOMERWRITER_HPP_
+#define _HOMERWRITER_HPP_
+/************************************************************************
+**
+**
+** This file is property of and copyright by the Technical Computer
+** Science Group, Kirchhoff Institute for Physics, Ruprecht-Karls-
+** University, Heidelberg, Germany, 2001
+** This file has been written by Timm Morten Steinbeck, 
+** timm@kip.uni-heidelberg.de
+**
+**
+** See the file license.txt for details regarding usage, modification,
+** distribution and warranty.
+** Important: This file is provided without any warranty, including
+** fitness for any particular purpose.
+**
+**
+** Newer versions of this file's package will be made available from 
+** http://web.kip.uni-heidelberg.de/Hardwinf/L3/ 
+** or the corresponding page of the Heidelberg Alice Level 3 group.
+**
+*************************************************************************/
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
+
+/** @file   AliHLTHomerWriter.h
+    @author Timm Steinbeck
+    @date   Sep 14 2007
+    @brief  HLT Online Monitoring Environment including ROOT - Writer   
+    @note   migrated from PubSub HLT-stable-20070905.141318 (rev 2375)    */
+
+// see below for class documentation
+// or
+// refer to README to build package
+// or
+// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+
+
+#include "AliHLTHOMERData.h"
+#include <vector>
+
+
+
+class HOMERWriter
+    {
+    public:
+
+       HOMERWriter();
+       virtual ~HOMERWriter();
+
+       void Clear();
+
+       void AddBlock( const void* descriptor, const void* data );
+       void AddBlock( const HOMERBlockDescriptor* descriptor, const void* data )
+               {
+               AddBlock( descriptor->GetHeader(), data );
+               }
+
+       homer_uint32 GetTotalMemorySize( bool includeData = true );
+       void Copy( void* destination, homer_uint64 eventType, homer_uint64 eventNr, homer_uint64 statusFlags, homer_uint64 nodeID, bool includeData = true );
+
+       static homer_uint8 DetermineUInt64Alignment();
+       static homer_uint8 DetermineUInt32Alignment();
+       static homer_uint8 DetermineUInt16Alignment();
+       static homer_uint8 DetermineUInt8Alignment();
+       static homer_uint8 DetermineDoubleAlignment();
+       static homer_uint8 DetermineFloatAlignment();
+
+
+    protected:
+
+
+
+       struct TBlockData
+           {
+               homer_uint64 fDescriptor[kCount_64b_Words];
+               const void* fData;
+           };
+
+       unsigned long fDataOffset;
+
+       std::vector<TBlockData> fBlocks;
+#ifdef USE_ROOT
+      ClassDef(HOMERWriter,0);
+#endif
+    };
+
+
+
+
+
+/*
+***************************************************************************
+**
+** $Author$ - Initial Version by Timm Morten Steinbeck
+**
+** $Id$ 
+**
+***************************************************************************
+*/
+
+#endif // _HOMERWRITER_HPP_
diff --git a/HLT/BASE/HOMER/HOMERReader.tex b/HLT/BASE/HOMER/HOMERReader.tex
new file mode 100644 (file)
index 0000000..5ed43b4
--- /dev/null
@@ -0,0 +1,846 @@
+
+\documentclass[a4paper,twoside]{article}
+
+%\sloppy
+
+%\renewcommand{\baselinestretch}{1.5}
+
+\usepackage{graphics}
+\usepackage{textcomp}
+\usepackage{times}
+%\usepackage[light]{draftcopy}
+\usepackage[english]{babel}
+
+%\usepackage[margin=20pt,head=20pt,headsep=20pt,foot=20pt]{geometry}
+%\usepackage[text={16.8cm,24.8cm}]{geometry}
+%\usepackage[text={16.9cm,24.8cm}]{geometry}
+\usepackage{geometry}
+
+
+
+
+\title{HLT Online Monitoring Environment including ROOT \\ --- \\ Reader Interface \\ --- \\ Version 0.2}
+\author{Timm M. Steinbeck, Heinz Tilsner}
+
+\begin{document}
+\maketitle
+
+\section{Preliminaries}
+\subsection{Disclaimer}
+This document is not complete. It is a design document describing an interface to be developed. We have tried to make it as complete as possible to the best of our knowledge but shortcomings of the defined subject may appear during its implementation or use.
+The document may therefore be subject to change as required, although we will try to minimize the impact of changes on existing code. 
+However, no guarantee about the described subject can be made.
+\subsection{Copyright}
+This document is copyright by the Computer Science/Computer Engineering group of the Kirchhoff Institute of Physics of the Ruprecht-Karls-University Heidelberg, Germany. It may be distributed 
+via any medium as a whole. Parts maybe quoted provided that the document with the original authors and their institute above are referenced properly. 
+\subsection{Terminology}
+As the whole interface described is a class API method, member function, and function will be used interchangeably.
+
+\section{Overview}
+
+This document defines an C++ class API to read data in an HLT Online Monitoring Environment including ROOT (HOMER). The API is structured into two parts:
+\begin{enumerate}
+\item An abstract base class defining an interface for reading via abstract functions. The functions defined here are kept generic so that they should be usable also with other monitoring environments. This class is called \texttt{Moni\-tor\-ing\-Read\-er}.
+\item A derived class with implementations for the defined abstract functions for HOMER. In addition, further functions are defined here that are considered to be too specific to the HOMER system to be included in the abstract interface definition. This class is called \texttt{HOMER\-Read\-er}.
+\end{enumerate}
+The purpose of splitting up the API into these two parts is to allow future additions in the form of other derived classes for further data sources in addition to HOMER. These classes, derived fromthe class MonitoringReader, could then read data from these other sources and provide them via an identical interface. This allows to add different data sources in to existing code (and support them in new code) with minimal code changes. Other possibilities for data sources could for example be the Mood DATE monitoring package or even offline data storage. 
+
+The purpose of the API as such is to provide an easy way to access the monitoring data from various taps in the HLT system (and as described above potentially other sources) in analysis packages and code.
+
+\section{MonitoringReader}
+
+The class \texttt{MonitoringReader} defines the abstract interface for monitoring data reader classes. It is shown in Fig. \ref{Fig:MonitoringReader}. 
+
+\begin{figure}[hbt]
+%\begin{center}
+{\footnotesize
+\begin{verbatim}
+
+class MonitoringReader
+    {
+    public:
+    MonitoringReader();
+    virtual ~MonitoringReader();
+    
+    /* Read in the next available event */
+    virtual int ReadNextEvent() = 0;
+    /* Read in the next available event, 
+       wait max. timeout microsecs. */
+    virtual int ReadNextEvent( unsigned long timeout_us ) = 0;
+
+    /* Return the ID of the current event */
+    virtual uint64 GetEventID() const = 0;
+
+    /* Return the number of data blocks in the 
+       current event */
+    virtual unsigned long GetBlockCnt() const = 0;
+
+    /* Return the size (in bytes) of the current 
+       event's data block with the given block 
+       index (starting at 0). */
+    virtual unsigned long GetBlockDataLength( unsigned long ndx ) const = 0;
+    /* Return a pointer to the start of the current
+       event's data block with the given block index
+       (starting at 0). */
+    virtual const void* GetBlockData( unsigned long ndx ) const = 0;
+    /* Return IP address or hostname of node which
+       received the current event's data block with
+       the given block index (starting at 0). */
+    virtual const char* GetBlockSendNodeID( unsigned long ndx ) const = 0;
+    /* Return byte order of the data stored in the 
+       current event's data block with the given block 
+       index (starting at 0). 
+       0 is unknown alignment, 
+       1 ist little endian, 
+       2 is big endian. */
+    virtual uint8 GetBlockByteOrder( unsigned long ndx ) const = 0;
+    /* Return the alignment (in bytes) of the given datatype 
+       in the data stored in the current event's data block
+       with the given block index (starting at 0). 
+       Possible values for the data type are
+       0: uint64
+       1: uint32
+       2: uin16
+       3: uint8
+       4: double
+       5: float
+     */
+    virtual uint8 GetBlockTypeAlignment( unsigned long ndx, uint8 dataType ) const = 0;
+    
+    };
+
+\end{verbatim}
+}
+\parbox{0.90\columnwidth}{
+\caption{\label{Fig:MonitoringReader}The API defined by the class \texttt{MonitoringReader}.}
+}
+%\end{center}
+\end{figure}
+
+The methods in the API will be discussed in the following subsections.
+
+
+\subsection{MonitoringReader()}
+
+\texttt{MonitoringReader()}
+
+The default constructor. Initializes anything required in the base class. Should not need to do much.
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] None
+\item[State after completion:] The object is created
+\end{description}
+
+
+\subsection{\~{ }MonitoringReader()}
+
+\texttt{virtual \~{ }MonitoringReader()}
+
+Destructor. Cleans up anything allocated/opened/initialized in the base class. Should not need to do much.
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] None
+\item[State after completion:] The object is destroyed
+\end{description}
+
+
+\subsection{ReadNextEvent()}
+\label{Subsec:MonitoringReader::ReadNextEvent}
+\texttt{virtual int ReadNextEvent()}
+
+This functions triggers reading in the next event from data sources defined by the derived class implementation. 
+The function will try indefinitely respectively until a permanent unresolvable error occurs. 
+Implementations of the function in derived classes may define an internal maximum timeout whose expiration is treated as a permanent error. After
+this function completes successfully the event's data is stored in the object and can be accessed by the class's other methods. It returns an 
+indicator signalling successful completion or the occurence of an error. 
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] An integer (\texttt{int}) signalling completion status. This is 0 on success or a non-zero integer value according to the values defined in the 
+include file \texttt{errno.h} to signal the type of error that occured. 
+\item[State after successful completion:] The event that was read in from the data sources is stored in the object and can be accessed by the class's other methods.
+\item[State after unsuccessful completion:] The state after an error occured during reading is undefined.
+\end{description}
+
+
+\subsection{ReadNextEvent( unsigned long )}
+\label{Subsec:MonitoringReader::ReadNextEvent:unsignedlong}
+\texttt{virtual int ReadNextEvent( unsigned long timeout\_us )}
+
+This function triggers reading in the next event from data sources defined by the derived class implementation. 
+The function will try until the given timeout expires or  permanent unresolvable error occurs. 
+In addition to the specified timeout implementations of the function in derived classes may 
+define an internal maximum timeout whose expiration is treated as a permanent error. After
+this function completes successfully the event's data is stored in the object and can be accessed by the class's other methods. It returns an 
+indicator signalling successful completion or the occurence of an error. 
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+       \item[\texttt{timeout\_us}:] An unsigned long integer (\texttt{unsigned long}) holding the timeout value in microseconds. When this timeout elapses the method will return 
+       even if no event has been received yet. Expiration of the timeout will be indicated by setting the return status to \texttt{ETIMEDOUT} as defined in the 
+       include file \texttt{errno.h}. 
+       \end{description}
+\item[Return value:] An integer (\texttt{int}) signalling completion status. This is 0 on success or a non-zero integer value according to the values defined in the 
+include file \texttt{errno.h} to signal the type of error that occured. \texttt{ETIMEDOUT} will be returned if the specified timeout expired before an event was received.
+\item[State after successful completion:] The event that was read in from the data sources is stored in the object and can be accessed by the class's other methods.
+\item[State after unsuccessful completion:] The state after an error occured during reading is undefined.
+\end{description}
+
+
+\subsection{GetEventID()}
+\label{Subsec:MonitoringReader::GetEventID}
+\texttt{virtual uint64 GetEventID() const}
+
+This function returns the ID of the event that was last successfully read in. If no event has yet been read in or if the last read attempt failed, 
+invalid event ID (\texttt{0xFF\-FF\-FF\-FF\-FF\-FF\-FF\-FF} / \texttt{\~{ }(uint64)0}) will be returned.
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] A 64~bit unsigned integer (\texttt{uint64}) that holds the ID of the last event that could be successfully read in. If no event has yet been read in or if the last read attempt failed, 
+invalid event ID (\texttt{0xFF\-FF\-FF\-FF\-FF\-FF\-FF\-FF} / \texttt{\~{ }(uint64)0}) will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockCnt()}
+\label{Subsec:MonitoringReader::GetBlockCnt}
+\texttt{virtual unsigned long GetBlockCnt() const}
+
+This function returns the number of data blocks in the current event. If no event has yet been read in or if the last read attempt failed 
+zero (\texttt{0}) data blocks will be reported.
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] An  unsigned long integer (\texttt{unsigned long}) that holds the number of data blocks contained in the last event that could be successfully read in. 
+If no event has yet been read in or if the last read attempt failed, zero (\texttt{0}) will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockDataLength( unsigned long )}
+\label{Subsec:MonitoringReader::GetBlockDataLength}
+\texttt{virtual unsigned long GetBlockDataLength( unsigned long ndx ) const}
+
+This function returns the size in bytes of the data block in the current event with the specified index. Indexing of data blocks starts at zero.
+If no event has yet been read in or if the last read attempt failed, a size of zero (\texttt{0}) bytes will be reported.
+If the block index is out of range (larger than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})) a size of 
+zero (\texttt{0}) bytes will be reported.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose size is 
+               to be reported. This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})
+       \end{description}
+\item[Return value:] An  unsigned long integer (\texttt{unsigned long}) that holds the size in bytes of the data block with the specified index 
+contained in the last event that could be successfully read in. 
+If no event has yet been read in or if the last read attempt failed, a size of zero (\texttt{0}) bytes will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt})) a size of 
+zero (\texttt{0}) bytes will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockData( unsigned long )}
+\label{Subsec:MonitoringReader::GetBlockData}
+\texttt{virtual const void* GetBlockData( unsigned long ndx ) const}
+
+This function returns a pointer to the beginning of data contained in the data block in the current event with the specified index. 
+Indexing of data blocks starts at zero.
+If no event has yet been read in or if the last read attempt failed, a \texttt{NULL} pointer will be returned.
+If the block index is out of range (larger than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a \texttt{NULL} pointer will be returned.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose data pointer is 
+               to be returned. This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})
+       \end{description}
+\item[Return value:] An  unsigned long integer (\texttt{unsigned long}) that holds a pointer to the beginning of the data block
+with the specified index contained in the last event that could be successfully read in. 
+If no event has yet been read in or if the last read attempt failed, a \texttt{NULL} pointer will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a \texttt{NULL} pointer will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockSendNodeID( unsigned long )}
+\label{Subsec:MonitoringReader::GetBlockSendNodeID}
+\texttt{virtual const char* GetBlockSendNodeID( unsigned long ndx ) const}
+
+This functions returns a pointer to a string holding an ID of the node which as sent the data block with the specified index. 
+Indexing of data blocks starts at zero. The node ID will be given in the string either as an IP address (e.g. ``\texttt{192.168.100.1}'')
+or as a hostname (e.g. ``\texttt{hlt42.alice.cern.ch}''). The string will be suitable as a parameter for the system call \texttt{gethostbyname}.
+If no event has yet been read in or if the last read attempt failed, a \texttt{NULL} pointer will be returned.
+If the block index is out of range (larger than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a \texttt{NULL} pointer will be returned.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose sending node's ID is 
+               to be returned. This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})
+       \end{description}
+\item[Return value:] A pointer to a string (\texttt{char*}) holding ID of the node that sent the data block
+with the specified index contained in the last event that could be successfully read in. 
+If no event has yet been read in or if the last read attempt failed, a \texttt{NULL} pointer will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a \texttt{NULL} pointer will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+\subsection{GetBlockByteOrder( unsigned long )}
+\label{Subsec:MonitoringReader::GetBlockByteOrder}
+\texttt{virtual uint8 GetBlockByteOrder( unsigned long ndx ) const}
+
+This function returns a character stating the byte order in which the data of the data block in the current event
+with the given index is stored. 
+
+The following values are returned:
+\begin{description}
+\item[0] specifies an unknown byte order
+\item[1] specifies little endian byte order
+\item[2] specifies big endian byte order
+\end{description}
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose sending node's ID is 
+               to be returned. This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})
+       \end{description}
+\item[Return value:] An unsigned character (\texttt{uint8}) specifying the byte order of the data stored in the current event's data block with the 
+specified index. Possible values are
+\begin{description}
+\item[0] for an unknown byte order
+\item[1] for little endian byte order
+\item[2] for big endian byte order
+\end{description}
+If no event has yet been read in or if the last read attempt failed, a value of zero specifying an unknown byte order will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a value of zero specifying an unknown byte order will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockTypeAlignment( unsigned long, uint8 )}
+\label{Subsec:MonitoringReader::GetBlockTypeAlignment}
+\texttt{virtual uint8 GetBlockTypeAlignment( unsigned long ndx, uint8 dataType ) const}
+
+This functions returns an indicator for the alignment in bytes of the given data type in the data of the data block in the current event
+with the given index. 
+
+Possible values for the data type are
+\begin{description}
+\item[0]: unsigned 64 bit integer (\texttt{uint64})
+\item[1]: unsigned 32 bit integer (\texttt{uint32})
+\item[2]: unsigned 16 bit integer (\texttt{uint16})
+\item[3]: unsigned 8 bit integer (\texttt{uint8})
+\item[4]: 64 bit floating point (\texttt{double})
+\item[5]: 32 bit floating point (\texttt{float})
+\end{description}
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose sending node's ID is 
+               to be returned. This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})
+       \end{description}
+       \begin{description}
+               \item[dataType:] An unsigned character (\texttt{uint8}) specifying the type of data whose alignment is queried. Possible values are
+                       \begin{description}
+                               \item[0] for unsigned 64 bit integer (\texttt{uint64})
+                               \item[1] for unsigned 32 bit integer (\texttt{uint32})
+                               \item[2] for unsigned 16 bit integer (\texttt{uint16})
+                               \item[3] for unsigned 8 bit integer (\texttt{uint8})
+                               \item[4] for 64 bit floating point (\texttt{double})
+                               \item[5] for 32 bit floating point (\texttt{float})
+                       \end{description}
+       \end{description}
+\item[Return value:] An unsigned character (\texttt{uint8}) specifying the alignment in bytes of the given data type in the data stored in the current event's data block with the 
+specified index. 
+If no event has yet been read in or if the last read attempt failed, a value of zero will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a value of zero will be returned. If an undefined value is specified for the data type (greater than 5) a value of zero will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+
+\section{HOMERReader}
+
+The class \texttt{HOMERReader} implements the abstract interface defined by the class \texttt{MonitoringReader} for the HLT Online Monitoring Environment. 
+It is shown in Fig. \ref{Fig:HOMERReader}. 
+
+\begin{figure}[hbt]
+%\begin{center}
+{\footnotesize
+\begin{verbatim}
+
+class HOMERReader: public MonitoringReader
+    {
+    public:
+    /* Constructors & destructors */
+    /* For reading from a TCP port */
+    HOMERReader( const char* hostname, unsigned short port );
+    /* For reading from multiple TCP ports */
+    HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports );
+    /* For reading from a System V shared memory segment */
+    HOMERReader( key_t shmKey, int shmSize );
+    /* For reading from multiple System V shared memory segments */
+    HOMERReader( unsigned int shmCnt, key_t* shmKey, int* shmSize );
+    /* For reading from multiple TCP ports and multiple System V shared memory segments */
+    HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports, 
+                 unsigned int shmCnt, key_t* shmKey, int* shmSize );
+    virtual ~HOMERReader();
+
+    /* Return the status of the connection as established by one of the constructors.
+     0 means connection is ok, non-zero specifies the type of error that occured. */
+    int GetConnectionStatus() const;
+
+    /* Return the index of the connection for which an error given by the above
+       function occured. */
+    unsigned int GetErrorConnectionNdx() const;
+
+    ...
+    Functions defined in MonitoringReader left out for clarity
+    ...
+
+    /* Return the type of the data in the current event's data
+       block with the given block index (starting at 0). */
+    uint64 GetBlockDataType( unsigned long ndx ) const;
+    /* Return the origin of the data in the current event's data
+       block with the given block index (starting at 0). */
+    uint32 GetBlockDataOrigin( unsigned long ndx ) const;
+    /* Return a specification of the data in the current event's data
+       block with the given block index (starting at 0). */
+    uint32 GetBlockDataSpec( unsigned long ndx ) const;
+
+    /* Find the next data block in the current event with the given
+       data type, origin, and specification. Returns the block's 
+       index. */
+    unsigned long FindBlockNdx( uint64 type, uint32 origin, 
+                         uint32 spec, unsigned long startNdx=0 ) const;
+
+    /* Return the ID of the node that actually produced this data block.
+       This may be different from the node which sent the data to this
+       monitoring object as returned by GetBlockSendNodeID. */
+    const char* GetBlockCreateNodeID( unsigned long ndx ) const;
+
+    };
+
+\end{verbatim}
+}
+\parbox{0.90\columnwidth}{
+\caption[The API defined by the class \texttt{HOMERReader}.]{\label{Fig:HOMERReader}The API defined by the class \texttt{HOMERReader}. Only those functions which are declared
+in addition to those inherited from the class \texttt{MonitoringReader} are shown. }
+}
+%\end{center}
+\end{figure}
+
+Objects of this class are able to read in events from one or more monitoring ``taps'' attached in a
+data flow constructed using the Publisher/Subscriber framework. These monitoring taps can provide the 
+data to be monitored either in System V Shared Memory segments or on TCP ports. The objects of the
+class \texttt{HOMERReader} can read data from both types. If multiple sources are specified for an object,
+it will only deliver events with matching event IDs for the blocks from the different sources. 
+
+The methods in the API will be discussed in the following subsections.
+
+\subsection{HOMERReader( const char*, unsigned short )}
+
+\texttt{HOMERReader( const char* hostname, unsigned short port )}
+
+This constructor connects the new object to one TCP data source specified by the given hostname and TCP port number. The status of the connection after object creation can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). 
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+       \item[hostname:] A string (\texttt{const char*}) holding a valid hostname on which the TCP monitoring source can be accessed. 
+       \item[port:] The port number (\texttt{unsigned short}) on which the TCP monitoring source waits for incoming connections/requests.
+       \end{description}
+\item[Return value:] None
+\item[State after completion:] The object is created. The connection status of the specified connection can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). 
+\end{description}
+
+
+\subsection{HOMERReader( unsigned int, const char**, unsigned short* )}
+
+\texttt{HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports )}
+
+This constructor connects the new object to multiple TCP data sources specified by the given hostnames and port numbers. The status of the connection after object creation can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). The object will only deliver events with matching event IDs for the blocks from the 
+different sources. 
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+       \item[tcpCnt:] The number of data sources specified. The number of hostnames and port numbers specified in the following
+       two parameters must be equal to this number.
+       \item[hostname:] An array of strings (\texttt{const char*}s)holding valid hostnames on which the TCP monitoring sources can be accessed. The number of hostnames
+       specified must be equal to the \texttt{tcpCnt} parameter. 
+       \item[port:] An array of port numbers (\texttt{unsigned short}s) on which the TCP monitoring sources wait for incoming connections/requests. The number of port numbers
+       specified must be equal to the \texttt{tcpCnt} parameter. 
+       \end{description}
+\item[Return value:] None
+\item[State after completion:] The object is created. The connection status of the specified connection can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). 
+\end{description}
+
+
+\subsection{HOMERReader( key\_t, int )}
+
+\texttt{HOMERReader( key\_t shmKey, int shmSize )}
+
+This constructor connects the new object to one System V shared memory segment. The status of the connection after object creation can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}).
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+       \item[shmKey:] A key (\texttt{key\_t} specifying the shared memory segment to which the object should attach.
+       \item[shmSize:] An integer (\texttt{int}) specifying the size of the shared memory segment to which the object should attach.
+       \end{description}
+\item[Return value:] None
+\item[State after completion:] The object is created. The connection status of the specified connection can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). 
+\end{description}
+
+
+\subsection{HOMERReader( unsigned int, key\_t*, int* )}
+
+\texttt{HOMERReader( unsigned int shmCnt, key\_t* shmKey, int* shmSize )}
+
+This constructor connects the new object to multiple System V shared memory segments. The status of the connection after object creation can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). The object will only deliver events with matching event IDs for the blocks from the 
+different sources. 
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+       \item[shmCnt:] The number of data sources specified. The number of shared memory keys and sizes specified in the following
+       two parameters must be equal to this number.
+       \item[shmKey:] An array of keys (\texttt{key\_t} specifying the shared memory segments to which the object should attach. The number of keys
+       specified must be equal to the \texttt{shmCnt} parameter. 
+       \item[shmSize:] An array of integers (\texttt{int}) specifying the sizes of the shared memory segments to which the object should attach. 
+       The number of sizes specified must be equal to the \texttt{shmCnt} parameter. 
+       \end{description}
+\item[Return value:] None
+\item[State after completion:] The object is created. The connection status of the specified connection can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). 
+\end{description}
+
+
+\subsection{HOMERReader( unsigned int, const char**, unsigned short*, unsigned int, key\_t*, int* )}
+
+\texttt{HOMERReader( unsigned int tcpCnt, const char** hostnames, unsigned short* ports, unsigned int shmCnt, key\_t* shmKey, int* shmSize )}
+
+This constructor connects the new object to multiple TCP data sources specified by the given hostnames and port numbers and 
+multiple System V shared memory segments. The status of the connection after object creation can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). The object will only deliver events with matching event IDs for the blocks from the 
+different sources. 
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+       \item[tcpCnt:] The number of TCP data sources specified. The number of hostnames and port numbers specified in the following
+       two parameters must be equal to this number.
+       \item[hostname:] An array of strings (\texttt{const char*}s)holding valid hostnames on which the TCP monitoring sources can be accessed. The number of hostnames
+       specified must be equal to the \texttt{tcpCnt} parameter. 
+       \item[port:] An array of port numbers (\texttt{unsigned short}s) on which the TCP monitoring sources wait for incoming connections/requests. The number of port numbers
+       specified must be equal to the \texttt{tcpCnt} parameter. 
+       \item[shmCnt:] The number of shared memory data sources specified. The number of shared memory keys and sizes specified in the following
+       two parameters must be equal to this number.
+       \item[shmKey:] An array of keys (\texttt{key\_t} specifying the shared memory segments to which the object should attach. The number of keys
+       specified must be equal to the \texttt{shmCnt} parameter. 
+       \item[shmSize:] An array of integers (\texttt{int}) specifying the sizes of the shared memory segments to which the object should attach. 
+       The number of sizes specified must be equal to the \texttt{shmCnt} parameter. 
+       \end{description}
+\item[Return value:] None
+\item[State after completion:] The object is created. The connection status of the specified connection can be queried
+using the function \texttt{GetConnectionStatus()} (\ref{Subsec:HOMERReader::GetConnectionStatus}). 
+\end{description}
+
+
+\subsection{\~{ }HOMERReader()}
+
+\texttt{virtual \~{ }HOMERReader()}
+
+The destructor. Cleans up anything from the established connections.
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] None
+\item[State after completion:] The object is destroyed.
+\end{description}
+
+
+\subsection{GetConnectionStatus()}
+\label{Subsec:HOMERReader::GetConnectionStatus}
+\texttt{int GetConnectionStatus() const}
+
+This functions returns the status of the connection to one or more data sources as specified in one of the class's constructors. 0 means the connection(s)
+could be successfully established, non-zero specified the error that occured, according to the definitions in the system include file \texttt{errno.h}.
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] An integer (\texttt{int}) given the status of the connection(s) specified to one of the constructors. A value of 0 signals no errors.
+Non-zero specifies the error that occured according to the constants defined in the system include file \texttt{errno.h}.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetErrorConnectionNdx()}
+
+\texttt{unsigned int GetErrorConnectionNdx() const}
+
+This functions returns the index of the connection that produced an error returned by the function \texttt{GetConnectionStatus()}
+(\ref{Subsec:HOMERReader::GetConnectionStatus}). If no error occured the value returned is \texttt{\~{ }(unsigned long)0} respectively \texttt{(unsigned long)-1}.
+
+Numbering is done as follows: TCP connections are numbered from zero up to the number of TCP sources minus 1. Shm connections are numbered
+starting at the number of TCP sources up to the number of TCP sources plus the number of Shm sources minus 1. If {\em tcpCnt} TCP sources and
+{\em shmCnt} shared memory sources are used then the indices for TCP and shared memory sources $ndx_{tcp}$ and $ndx_{shm}$ 
+respectively have ranges as follows:
+$$ 0 \le ndx_{tcp} < tcpCnt $$
+$$ tcpCnt \le ndx_{shm} < shmCnt $$
+For the constructors connecting only to TCP or shared memory sources the corresponding other count is assumed to be 0.
+
+\begin{description}
+\item[Parameters:] None
+\item[Return value:] An unsigned integer (\texttt{unsigned int}) given the index of the connection that produced an error reportedby the function \texttt{GetConnectionStatus()}
+(\ref{Subsec:HOMERReader::GetConnectionStatus}). If no error occured the value returned is \texttt{\~{ }(unsigned long)0} respectively \texttt{(unsigned long)-1}. The numbering scheme is defined above.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{ReadNextEvent()}
+
+\texttt{virtual int ReadNextEvent()}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::ReadNextEvent()} (\ref{Subsec:MonitoringReader::ReadNextEvent}).
+
+
+\subsection{ReadNextEvent( unsigned long )}
+
+\texttt{virtual int ReadNextEvent( unsigned long timeout\_us )}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::ReadNextEvent( unsigned long )} (\ref{Subsec:MonitoringReader::ReadNextEvent:unsignedlong}).
+
+
+\subsection{GetEventID()}
+
+\texttt{virtual uint64 GetEventID() const}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::GetEventID()} (\ref{Subsec:MonitoringReader::GetEventID}).
+
+
+\subsection{GetBlockCnt()}
+
+\texttt{virtual unsigned long GetBlockCnt() const}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}).
+
+
+\subsection{GetBlockDataLength( unsigned long )}
+
+\texttt{virtual unsigned long GetBlockDataLength( unsigned long ndx ) const}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::GetBlockDataLength()} (\ref{Subsec:MonitoringReader::GetBlockDataLength}).
+
+
+\subsection{GetBlockData( unsigned long )}
+
+\texttt{virtual const void* GetBlockData( unsigned long ndx ) const}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::GetBlockData()} (\ref{Subsec:MonitoringReader::GetBlockData}).
+
+
+\subsection{GetBlockSendNodeID( unsigned long )}
+
+\texttt{virtual const char* GetBlockSendNodeID( unsigned long ndx ) const}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::GetBlockSendNodeID} (\ref{Subsec:MonitoringReader::GetBlockSendNodeID}).
+
+
+\subsection{GetBlockByteOrder( unsigned long )}
+
+\texttt{virtual uint8 GetBlockByteOrder( unsigned long ndx ) const}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::GetBlockByteOrder} (\ref{Subsec:MonitoringReader::GetBlockByteOrder}).
+
+
+\subsection{GetBlockTypeAlignment( unsigned long, uint8 )}
+
+\texttt{virtual uint8 GetBlockTypeAlignment( unsigned long ndx, uint8 dataType ) const}
+
+This function is an implementation of the interface defined by \texttt{MonitoringReader::GetBlockTypeAlignment} (\ref{Subsec:MonitoringReader::GetBlockTypeAlignment}).
+
+
+\subsection{GetBlockDataType( unsigned long )}
+
+\texttt{uint64 GetBlockDataType( unsigned long ndx ) const}
+
+This function returns the data type of the data block in the current event with the specified index. The type of the data is returned as a 64~bit unsigned integer
+that is often also interpreted as an 8 character array. 
+Indexing of data blocks starts at zero.
+If no event has yet been read in or if the last read attempt failed, an invalid type of (\texttt{0xFF\-FF\-FF\-FF\-FF\-FF\-FF\-FF} / \texttt{\~{ }(uint64)0}) 
+will be returned.
+If the block index is out of range (larger than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})) an 
+invalid type of (\texttt{0xFF\-FF\-FF\-FF\-FF\-FF\-FF\-FF} / \texttt{\~{ }(uint64)0}) will be returned.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose data type is queried.
+               This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}).
+       \end{description}
+\item[Return value:] A 64~bit unsigned integer (\texttt{uint64}) holding the type of the data block with the specified index. The value is often also interpreted as an 8 
+character array.
+If no event has yet been read in or if the last read attempt failed, an invalid type of (\texttt{0xFF\-FF\-FF\-FF\-FF\-FF\-FF\-FF} / \texttt{\~{ }(uint64)0}) 
+will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+an invalid type of (\texttt{0xFF\-FF\-FF\-FF\-FF\-FF\-FF\-FF} / \texttt{\~{ }(uint64)0}) will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockDataOrigin( unsigned long )}
+
+\texttt{uint32 GetBlockDataOrigin( unsigned long ndx ) const}
+
+This function returns the origin of the data block in the current event with the specified index. The origin of the data is returned as a 32~bit unsigned integer
+that is often also interpreted as a 4 character array. 
+Indexing of data blocks starts at zero.
+If no event has yet been read in or if the last read attempt failed, an invalid value of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) 
+will be returned.
+If the block index is out of range (larger than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})) an 
+invalid value of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) will be returned.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose origin is queried.
+               This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}).
+       \end{description}
+\item[Return value:] A 32~bit unsigned integer (\texttt{uint32}) holding the origin of the data block with the specified index. The value is often also interpreted as a 4
+character array.
+If no event has yet been read in or if the last read attempt failed, an invalid value of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) 
+will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+an invalid value of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockDataSpec( unsigned long )}
+
+\texttt{uint32 GetBlockDataSpec( unsigned long ndx ) const}
+
+This function returns a specification of the data block in the current event with the specified index. This specification of the data is returned as a 32~bit unsigned integer
+that is often also interpreted as a 4 character array. 
+Indexing of data blocks starts at zero.
+If no event has yet been read in or if the last read attempt failed, an invalid value of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) 
+will be returned.
+If the block index is out of range (larger than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})) an 
+invalid value of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) will be returned.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose specification is queried.
+               This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}).
+       \end{description}
+\item[Return value:] A 32~bit unsigned integer (\texttt{uint32}) holding the specification of the data block with the specified index. The value is often also interpreted as a 4
+character array.
+If no event has yet been read in or if the last read attempt failed, an invalid type of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) 
+will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+an invalid type of (\texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{FindBlockNdx( uint64, uint32, uint32, unsigned long )}
+
+\texttt{unsigned long FindBlockNdx( uint64 type, uint32 origin, uint32 spec, unsigned long startNdx=0 ) const}
+
+This function searches for the next data block in the current event with the given data type, origin, and specification. Wildcards can be given
+for each of these parameters. An index at which the search is to be started can optionally also be specified. This parameter is 0 by default,
+starting the search at the beginning. By passing the result indices of previous searches increased by one as the start index all blocks can be searched.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[type:] A 64~bit unsigned integer (\texttt{uint64}) specifying the data type of the block to be searched. A value of
+               \texttt{0xFF\-FF\-FF\-FF\-FF\-FF\-FF\-FF} / \texttt{\~{ }(uint64)0}) is treated as a wildcard.
+               \item[origin:] A 32~bit unsigned integer (\texttt{uint32}) specifying the origin of the block to be searched. A value of
+               \texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) is treated as a wildcard.
+               \item[spec:] A 32~bit unsigned integer (\texttt{uint32}) specifying the data specification of the block to be searched. A value of
+               \texttt{0xFF\-FF\-FF\-FF} / \texttt{\~{ }(uint32)0}) is treated as a wildcard.
+               \item[startNdx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block where the search is to be started.
+               If this value is greater than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}) the 
+               search immediately terminates.
+       \end{description}
+\item[Return value:] An 32~bit unsigned long integer (\texttt{unsigned long}) holding the index of a block matching the specified criteria. If no block could be found 
+an invalid index of \texttt{\~{ }(unsigned long)0} / \texttt{(unsigned long)-1} is returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+
+\subsection{GetBlockCreateNodeID( unsigned long )}
+
+\texttt{const char* GetBlockCreateNodeID( unsigned long ndx ) const}
+
+This functions returns a pointer to a string holding an ID of the node which created the data block with the specified index. 
+Indexing of data blocks starts at zero. The node ID will be given in the string either as an IP address (e.g. ``\texttt{192.168.100.1}'')
+or as a hostname (e.g. ``\texttt{hlt42.alice.cern.ch}''). The string will be suitable as a parameter for the system call \texttt{gethostbyname}.
+If no event has yet been read in or if the last read attempt failed, a \texttt{NULL} pointer will be returned.
+If the block index is out of range (larger than or equal to the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a \texttt{NULL} pointer will be returned.
+
+This node ID can be different from the one returned by GetBlockSendNodeID() (\ref{Subsec:MonitoringReader::GetBlockSendNodeID}) if the Publisher/Subscriber
+framework component that produced or created the data is running on a different node than the one the monitoring component is running on.
+
+\begin{description}
+\item[Parameters:]
+       \begin{description}
+               \item[ndx:] An unsigned long integer (\texttt{unsigned long}) specifying the index of the block whose creator node's ID is 
+               to be returned. This value must be less than the value returned by \texttt{GetBlockCnt()} (\ref{Subsec:MonitoringReader::GetBlockCnt})
+       \end{description}
+\item[Return value:] A pointer to a string (\texttt{char*}) holding ID of the node that created the data block
+with the specified index contained in the last event that could be successfully read in. 
+If no event has yet been read in or if the last read attempt failed, a \texttt{NULL} pointer will be returned.
+If the block index is out of range (larger than the value returned by \texttt{GetBlockCnt} (\ref{Subsec:MonitoringReader::GetBlockCnt}))
+a \texttt{NULL} pointer will be returned.
+\item[State after successful completion:] No change
+\item[State after unsuccessful completion:] No change
+\end{description}
+
+\section{History}
+
+\begin{description}
+\item[0.1] Initial version
+\item[0.2] Added the \texttt{GetBlockByteOrder} and \texttt{GetBlockTypeAlignment} methods; tried to clarify the reason for splitting the API into two classes
+\end{description}
+
+
+\end{document}
\ No newline at end of file
diff --git a/HLT/BASE/HOMER/Makefile.am b/HLT/BASE/HOMER/Makefile.am
new file mode 100644 (file)
index 0000000..6dfa934
--- /dev/null
@@ -0,0 +1,122 @@
+# $Id$
+# Makefile template for the Alice HLT HOMER library
+# 
+# This is a ported version of the HOMER library of the HLT
+# PubSub package HLT-stable-20070905.141318 (rev 2375) on Sep 14 2007
+
+MODULE                         = HOMER
+
+ROOT_DEFS                      = USE_ROOT
+AM_CPPFLAGS                    = -DMODULE=$(MODULE) \
+                                 $(foreach i, $(ROOT_DEFS), -D$(i))
+
+# library definition
+# for now we only create the version with ROOT support
+# the build system is not completely ready yet, the approach with the copied
+# sources and replacement of USE_ROOT is not yet working. Send an email to
+# Matthias.Richter@ift.uib.no if you need this feature
+#lib_LTLIBRARIES                       =  libHOMER.la libAliHLTHOMER.la
+lib_LTLIBRARIES                        =  libAliHLTHOMER.la
+
+# version info for the library
+LIBRARY_VERSION                        = '0:0:0'
+
+# MODDIR is set by the AliRoot build system and denotes the topdir
+# of the module, we must set it since the package definition libAliHLTHOMER.pkg
+# includes another common configuration file
+MODDIR                         = $(top_srcdir)
+PKGDEF                         = $(MODDIR)/libAliHLTHOMER.pkg
+include $(top_srcdir)/libAliHLTHOMER.pkg
+
+NOROOT_SRC                     = $(MODULE_SRCS:.cxx=_noRoot.cxx)
+
+# ##########################################################
+# general settings for both libraries
+#
+HOMER_DOC                      = HOMERReader.tex
+
+EXTRA_DIST                     = $(MODULE_DHDR) \
+                                 $(HOMER_DOC)
+
+# automatic generation of data and time of library build
+COMPILE_INFO                   =  HOMERCompileInfo.cxx
+
+# library headers
+pkginclude_HEADERS             = $(MODULE_HDRS) $(MODULE_DHDR)
+
+# ##########################################################
+# library version with ROOT support
+#
+
+# library sources
+libAliHLTHOMER_la_SOURCES      = $(MODULE_SRCS)
+
+# linker flags
+libAliHLTHOMER_la_LDFLAGS      = -L@ROOTLIBDIR@ \
+                                 @ROOTLIBS@ \
+                                 -version-info $(LIBRARY_VERSION)
+
+# set the file name for the generated root dictionary
+DICTCPP                                =  HOMER-DICT.cxx
+nodist_libAliHLTHOMER_la_SOURCES = $(COMPILE_INFO) \
+                                  $(DICTCPP)
+
+# ##########################################################
+# library version w/o ROOT support
+#
+# enable this if library w/o ROOT support is build
+
+# # library sources (generated)
+# nodist_libHOMER_la_SOURCES   = $(COMPILE_INFO) \
+#                                 $(NOROOT_SRC)
+
+# # # linker flags
+# libHOMER_la_LDFLAGS          = -version-info $(LIBRARY_VERSION)
+
+# ##########################################################
+
+CLEANFILES                     =  $(COMPILE_INFO) \
+                                  $(NOROOT_SRC)
+
+DICTFILES                      =  $(DICTCPP) $(DICTCPP:.cxx=.h)
+DICTHEADERS                    =  $(CLASS_HDRS)
+
+CLEANFILES                     += $(DICTFILES)
+
+
+# as the first step of the migration of the HOMER library to
+# AliRoot we leave the class names as they are but change the
+# file names. Thats why the automatic generation of the ROOT
+# LinkDef file doesn't work for the moment
+$(DICTCPP:.cxx=.h): $(DICTCPP)
+       if test $@ ; then : ; else rm -f $< ; $(MAKE) $(MAKEFLAGS) $< ; fi 
+
+$(DICTCPP): $(DICTHEADERS:%=$(srcdir)/%) $(MODULE_DHDR)
+       if [ -x $(ROOTCINT) ]; then $(ROOTCINT) -f $@ -c $(CPPFLAGS) $(AM_CPPFLAGS) $(DEFS) $(foreach i, $(DICTINCLUDE), $(i)) $^ ; fi
+
+# include $(top_srcdir)/make.dict
+
+$(NOROOT_SRC): $(MODULE_SRCS)
+       cat $(srcdir)/$(@:_noRoot.cxx=.cxx) $(foreach i, $(ROOT_DEFS), | sed -e "s|$(i)|FALSE|") > $@
+
+$(COMPILE_INFO): $(libAliHLTHOMER_la_SOURCES) $(pkginclude_HEADERS) $(noinst_HEADERS) Makefile.am
+       @echo '//automatically generated compilation info' > $@
+       @echo '//!!! DO NOT EDIT THIS FILE !!!' >> $@
+       @echo '//add changes in Makefile.am' >> $@
+       @echo 'void $(MODULE)CompileInfo( char*& date, char*& time)' >> $@
+       @echo '{date=__DATE__; time=__TIME__; return;}' >> $@
+
+all-local: $(HOMER_DOC:.tex=.ps) $(HOMER_DOC:.tex=.pdf)
+
+clean-local:
+       rm -f $(HOMER_DOC:.tex=.pdf) $(HOMER_DOC:.tex=.ps) $(HOMER_DOC:.tex=.dvi) $(HOMER_DOC:.tex=.aux) $(HOMER_DOC:.tex=.log)
+
+$(HOMER_DOC:.tex=.pdf): $(HOMER_DOC:.tex=.ps)
+       ps2pdf13 -dEmebedAllFonts=true $^
+
+$(HOMER_DOC:.tex=.ps): $(HOMER_DOC:.tex=.dvi)
+       dvips -o $@ $^
+
+$(HOMER_DOC:.tex=.dvi): $(HOMER_DOC)
+       latex $^
+       latex $^
index c13ba24973db1b54f8473f32d7bd7f38c06a6570..b18f7706cd36bf1bf52cb2784287af214a066a1f 100644 (file)
@@ -12,7 +12,7 @@ if EN_HLT_UTIL
 UTIL_DIR=util
 endif
 
-SUBDIRS                        = . $(UTIL_DIR) interface
+SUBDIRS                        = . $(UTIL_DIR) interface HOMER
 
 EXTRA_DIST                     = HLTbaseLinkDef.h
 
index 3789c5a4bf07ae55b86402b46067b5472dea25c9..f67d1d2a45b60c79d68c9b47eed7f8f05d33df3e 100644 (file)
@@ -684,6 +684,7 @@ AC_CONFIG_FILES([Makefile
                 BASE/Makefile
                 BASE/setenv.sh
                 BASE/setenv.csh
+                BASE/HOMER/Makefile
                 BASE/util/Makefile
                 BASE/interface/Makefile
                 SampleLib/Makefile
diff --git a/HLT/libAliHLTHOMER.pkg b/HLT/libAliHLTHOMER.pkg
new file mode 100644 (file)
index 0000000..2503299
--- /dev/null
@@ -0,0 +1,32 @@
+#-*- Mode: Makefile -*-
+# $Id$
+
+include $(MODDIR)/hlt.conf
+
+MODULE_SRCS=   AliHLTHOMERReader.cxx \
+               AliHLTHOMERWriter.cxx
+
+CLASS_HDRS:=   AliHLTHOMERReader.h \
+               AliHLTHOMERWriter.h
+
+MODULE_HDRS:=  $(CLASS_HDRS) \
+               AliHLTHOMERData.h
+
+# as the first step of the migration of the HOMER library to
+# AliRoot we leave the class names as they are but change the
+# file names. Thats why the automatic generation of the ROOT
+# LinkDef file doesn't work for the moment
+MODULE_DHDR:=  AliHLTHOMERLinkDef.h
+#CINTAUTOLINK:=  1
+
+SRCS:=$(patsubst %,BASE/HOMER/%,$(MODULE_SRCS))
+CINTHDRS:=$(patsubst %,BASE/HOMER/%,$(CLASS_HDRS))
+HDRS:=$(patsubst %,BASE/HOMER/%,$(MODULE_HDRS))
+DHDR:=$(patsubst %,BASE/HOMER/%,$(MODULE_DHDR))
+
+EDEFINE      := ${HLTDEFS}
+PACKCXXFLAGS := ${HLTCXXFLAGS}
+PACKCFLAGS   := ${HLTCLFAGS}
+PACKDCXXFLAGS:= ${HLTDCXXFLAGS}
+
+EINCLUDE := BASE/HOMER