--- /dev/null
+// $Id$
+
+//**************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project *
+//* ALICE Experiment at CERN, All rights reserved. *
+//* *
+//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
+//* for The ALICE HLT Project. *
+//* *
+//* Permission to use, copy, modify and distribute this software and its *
+//* documentation strictly for non-commercial purposes is hereby granted *
+//* without fee, provided that the above copyright notice appears in all *
+//* copies and that both the copyright notice and this permission notice *
+//* appear in the supporting documentation. The authors make no claims *
+//* about the suitability of this software for any purpose. It is *
+//* provided "as is" without express or implied warranty. *
+//**************************************************************************
+
+/** @file AliHLTDimServer.cxx
+ @author Matthias Richter
+ @date 2010-03-10
+ @brief HLT DIM server implementation
+*/
+
+#include "AliHLTDimServer.h"
+#include "TObjArray.h"
+#include "TSystem.h"
+#include "TThread.h"
+
+/** ROOT macro for the implementation of ROOT specific class methods */
+ClassImp(AliHLTDimServer)
+
+AliHLTDimServer::AliHLTDimServer()
+ : TNamed()
+ , fServices()
+ , fState(kStateOff)
+ , fpServerThread(NULL)
+ , fUpdatePeriod(10000)
+{
+ // see header file for class documentation
+ // or
+ // refer to README to build package
+ // or
+ // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+}
+
+AliHLTDimServer::AliHLTDimServer(const char* servername)
+ : TNamed(servername, "AliHLTDimServer")
+ , fServices()
+ , fState(kStateOff)
+ , fpServerThread(NULL)
+ , fUpdatePeriod(10000)
+{
+ // see header file for class documentation
+}
+
+AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::fgpInterface=NULL;
+
+AliHLTDimServer::~AliHLTDimServer()
+{
+ // see header file for class documentation
+}
+
+int AliHLTDimServer::RegisterService(AliHLTDimService* pService)
+{
+ // see header file for class documentation
+ if (!pService) return -EINVAL;
+ if (fServices.FindObject(pService)) {
+ AliHLTLogging log;
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "RegisterService" , __FILE__ , __LINE__ , "duplicate service name %s, skip ...", pService->GetName());
+ return -EEXIST;
+ }
+ fServices.Add(pService);
+ return 0;
+}
+
+AliHLTDimServer::AliHLTDimService* AliHLTDimServer::CreateService(enum AliHLTDimServer::AliHLTDimServiceDataType type, const char* name)
+{
+ // see header file for class documentation
+ AliHLTDimService* service=new AliHLTDimService(type, name);
+ int iResult=RegisterService(service);
+ if (iResult<0) {
+ AliHLTLogging log;
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "CreateService" , __FILE__ , __LINE__ , "failed to register service %s: %d", name, iResult);
+ if (service) delete service;
+ return NULL;
+ }
+ return service;
+}
+
+TObjArray* AliHLTDimServer::CreateServiceGroup(enum AliHLTDimServer::AliHLTDimServiceDataType type, const char* basename, int count)
+{
+ int iResult=0;
+ TObjArray* pServices=new TObjArray;
+ AliHLTLogging log;
+ if (pServices) {
+ if (basename && count>0) {
+ int digits=1;
+ int i=count;
+ while ((i/=10)>0) digits++;
+ if (digits<9) {
+ log.LoggingVarargs(kHLTLogDebug, "AliHLTDimServer", "CreateServiceGroup" , __FILE__ , __LINE__ , "basename=%s count=%d digits=%d\n", basename, count, digits);
+ int namelen=strlen(basename)+2+digits;
+ char* name=(char*)malloc(namelen);
+ char* format=(char*)malloc(namelen); // this has actually only indirect to do with namelen but its appropriate
+ if (name && format) {
+ const char* key=strchr(basename, '%');
+ strcpy(format, basename);
+ if (key) {
+ int iPos=(key-basename)+1;
+ if (key[1]=='d') {
+ sprintf(format+iPos, "0*d");
+ iPos+=3;
+ } else {
+ *(format+iPos++)='%';
+ *(format+iPos++)=key[1];
+ }
+ strcpy(format+iPos, &key[2]);
+ } else {
+ sprintf(format+strlen(basename), "_%%0*d");
+ }
+ for (i=0; i<count && iResult>=0; i++) {
+ sprintf(name, format, digits, i);
+ AliHLTDimService* service=new AliHLTDimService(type, name);
+ iResult=RegisterService(service);
+ }
+ } else {
+ iResult=-ENOMEM;
+ }
+ if (name) free(name);
+ if (format) free(format);
+ }
+ }
+ }
+ return pServices;
+}
+
+AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::Interface()
+{
+ if (!fgpInterface) {
+ fgpInterface=new AliHLTDimInterface;
+ if (fgpInterface) {
+ fgpInterface->Init();
+ }
+ }
+ return fgpInterface;
+}
+
+int AliHLTDimServer::Init(const char* dimNameServer)
+{
+ AliHLTLogging log;
+ const char* myname=GetName();
+ if (myname==NULL || myname[0]==0) {
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Init" , __FILE__ , __LINE__ , "can not start without a server name, skipping initialization ...");
+ return -EINVAL;
+ }
+
+ if (Interface()==NULL) return -ENODEV;
+
+ Interface()->DisSetDnsNode(dimNameServer);
+ return 0;
+}
+
+int AliHLTDimServer::Reset()
+{
+ return 0;
+}
+
+int AliHLTDimServer::Start()
+{
+ // start the server in a separate thread
+ int iResult=0;
+ AliHLTLogging log;
+ if (GetState()!=kStateOff) {
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "server is not off, currently in state %d", GetState());
+ return -ENOENT;
+ }
+ fpServerThread=new TThread(ServerLoop, (void*)this);
+ if (!fpServerThread) {
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "unable to create server thread");
+ return -ENOMEM;
+ }
+ SetState(kStateStarting);
+ fpServerThread->Run();
+
+ int count=0;
+ const int maxcount=100;
+ const int maxsleepms=1000;
+ while (GetState()==kStateStarting) {
+ if (count++==maxcount) break;
+ gSystem->Sleep(maxsleepms/maxcount);
+ }
+
+ if (GetState()!=kStateRunning) {
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "could not start server, currently in state %d", GetState());
+ Reset();
+ iResult=-EFAULT;
+ }
+ return iResult;
+}
+
+int AliHLTDimServer::Stop()
+{
+ // stop the server thread
+ int iResult=0;
+ AliHLTLogging log;
+ if (GetState()!=kStateRunning) {
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "server is not running, currently in state %d", GetState());
+ return -ENOENT;
+ }
+ SetState(kStateStopping);
+ int count=0;
+ const int maxcount=100;
+ const int maxsleepms=2*fUpdatePeriod;
+ while (GetState()==kStateStopping) {
+ if (count++==maxcount) break;
+ gSystem->Sleep(maxsleepms/maxcount);
+ }
+
+ if (GetState()!=kStateOff) {
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "could not stop server, currently in state %d", GetState());
+ Reset();
+ iResult=-EFAULT;
+ }
+ return iResult;
+}
+
+void* AliHLTDimServer::ServerLoop(void* param)
+{
+ // see header file for class documentation
+ if (!param) return (void*)0;
+ AliHLTDimServer* server=reinterpret_cast<AliHLTDimServer*>(param);
+ return server->ServerLoop();
+}
+
+void* AliHLTDimServer::ServerLoop()
+{
+ // see header file for class documentation
+ if (!Interface()) return (void*)-ENODEV;
+
+ AliHLTLogging log;
+ TIter next(&fServices);
+ TObject* obj=NULL;
+ while ((obj=next())!=NULL) {
+ AliHLTDimService* pService=dynamic_cast<AliHLTDimService*>(obj);
+ if (!pService) continue;
+ const char* name=pService->GetName();
+ const char* type="";
+ void* buffer=pService->GetLocation();
+ int size=0;
+ switch (pService->GetType()) {
+ case kDataTypeInt:
+ type="I";
+ size=sizeof(int);
+ break;
+ case kDataTypeFloat:
+ type="F";
+ size=sizeof(float);
+ break;
+ case kDataTypeString:
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: type 'string' not yet implemented", name);
+ break;
+ default:
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: unknown type %d", name, pService->GetType());
+ }
+ if (type[0]!=0) {
+ int id=Interface()->DisAddService(name, type, buffer, size);
+ if (id<0) {
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to add dim service %s: error %d", name, id);
+ } else {
+ pService->SetId(id);
+ }
+ }
+ }
+
+ SetState(kStateRunning);
+ while (GetState()==kStateRunning) {
+ cout << "test" << endl;
+ gSystem->Sleep(fUpdatePeriod);
+ }
+
+ if (GetState()!=kStateStopping) return (void*)0;
+
+ // cleanup
+ Interface()->DisStopServing();
+ next.Reset();
+ while ((obj=next())!=NULL) {
+ const AliHLTDimService* pService=dynamic_cast<const AliHLTDimService*>(obj);
+ if (!pService || pService->GetId()<0) continue;
+ // int iResult=Interface()->DisRemoveService(pService->GetId());
+ // if (iResult<0) {
+ // log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to remove dim service %s: error %d", pService->GetName(), iResult);
+ // }
+ }
+
+ SetState(kStateOff);
+
+ return (void*)0;
+}
+
+AliHLTDimServer::AliHLTDimService::AliHLTDimService()
+ : TNamed()
+ , fData()
+ , fType(kDataTypeUnknown)
+ , fId(-1)
+{
+ // see header file for class documentation
+}
+
+AliHLTDimServer::AliHLTDimService::AliHLTDimService(enum AliHLTDimServiceDataType type, const char* servicename)
+ : TNamed(servicename, "AliHLTDimService")
+ , fData()
+ , fType(type)
+ , fId(-1)
+{
+ // see header file for class documentation
+ AliHLTLogging log;
+ switch (fType) {
+ case kDataTypeInt: break;
+ case kDataTypeFloat: break;
+ case kDataTypeString:
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "dim service type 'string' not yet implemented");
+ break;
+ default:
+ log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "Unknown dim service type %d", fType);
+ };
+}
+
+void AliHLTDimServer::AliHLTDimService::Update(AliHLTDimServicePoint_t& sp)
+{
+ // see header file for class documentation
+ static bool bWarning=true;
+ AliHLTLogging log;
+ switch (fType) {
+ case kDataTypeInt: fData.iVal=sp.iVal; break;
+ case kDataTypeFloat: fData.fVal=sp.fVal; break;
+ case kDataTypeString:
+ if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: 'string' not yet implemented", GetName());
+ bWarning=false;
+ break;
+ default:
+ if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: unknown type %d", GetName(), fType);
+ bWarning=false;
+ };
+}
+
+AliHLTDimServer::AliHLTDimInterface::AliHLTDimInterface()
+ : AliHLTLogging()
+ , fpDisAddService(NULL)
+ , fpDisRemoveService(NULL)
+ , fpDisUpdateService(NULL)
+ , fpDisStartServing(NULL)
+ , fpDisStopServing(NULL)
+ , fpDisSetDnsNode(NULL)
+{
+}
+
+AliHLTDimServer::AliHLTDimInterface::~AliHLTDimInterface()
+{
+}
+
+
+const char* AliHLTDimServer::AliHLTDimInterface::fgkDimLibraryName="libdim.so";
+const char* AliHLTDimServer::AliHLTDimInterface::fgkDisAddServiceSymbol="dis_add_service";
+const char* AliHLTDimServer::AliHLTDimInterface::fgkDisRemoveServiceSymbol="dis_remove_service";
+const char* AliHLTDimServer::AliHLTDimInterface::fgkDisUpdateServiceSymbol="dis_update_service";
+const char* AliHLTDimServer::AliHLTDimInterface::fgkDisStartServingSymbol="dis_start_serving";
+const char* AliHLTDimServer::AliHLTDimInterface::fgkDisStopServingSymbol="dis_stop_serving";
+const char* AliHLTDimServer::AliHLTDimInterface::fgkDisSetDnsNodeSymbol="dis_set_dns_node";
+
+int AliHLTDimServer::AliHLTDimInterface::Init()
+{
+ /// load the dim library and function pointers
+ if (gSystem->Load(fgkDimLibraryName)) {
+ HLTFatal("failed to load dim library: %s", fgkDimLibraryName);
+ return -ENODEV;
+ }
+
+ fpDisAddService=(fctDisAddService)FindSymbol(fgkDimLibraryName, fgkDisAddServiceSymbol);
+ if (!fpDisAddService) return -ENODEV;
+
+ fpDisRemoveService=(fctDisRemoveService)FindSymbol(fgkDimLibraryName, fgkDisRemoveServiceSymbol);
+ if (!fpDisRemoveService) return -ENODEV;
+
+ fpDisUpdateService=(fctDisUpdateService)FindSymbol(fgkDimLibraryName, fgkDisUpdateServiceSymbol);
+ if (!fpDisUpdateService) return -ENODEV;
+
+ fpDisStartServing=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisStartServingSymbol);
+ if (!fpDisStartServing) return -ENODEV;
+
+ fpDisStopServing=(fctDisNoArg)FindSymbol(fgkDimLibraryName, fgkDisStopServingSymbol);
+ if (!fpDisStopServing) return -ENODEV;
+
+ fpDisSetDnsNode=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisSetDnsNodeSymbol);
+ if (!fpDisSetDnsNode) return -ENODEV;
+
+ return 0;
+}
+
+AliHLTDimServer::fctVoid AliHLTDimServer::AliHLTDimInterface::FindSymbol(const char* library, const char* symbol) const
+{
+ /// Find symbol in the dim library
+ TString tmp=symbol;
+ fctVoid fctptr=gSystem->DynFindSymbol(library, tmp.Data());
+ if (!fctptr) {
+ // do a 2nd try with appended '_'
+ tmp+="_";
+ fctptr=gSystem->DynFindSymbol(library, tmp.Data());
+ }
+ if (fctptr) return fctptr;
+
+ HLTError("can not find symbol '%s' in %s", symbol, library);
+ return NULL;
+}
--- /dev/null
+//-*- Mode: C++ -*-
+// $Id$
+
+#ifndef ALIHLTDIMSERVER_H
+#define ALIHLTDIMSERVER_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 AliHLTDimServer.h
+ @author Matthias Richter
+ @date 20010-03-10
+ @brief HLT DIM server
+*/
+#include "AliHLTLogging.h"
+#include "TNamed.h"
+#include "TObjArray.h"
+
+class TThread;
+
+/**
+ * @class AliHLTDimServer
+ * Implementation of a DIM server for HLT and the dynamic access to the
+ * DIM library.
+ */
+class AliHLTDimServer : public TNamed {
+public:
+ AliHLTDimServer();
+ AliHLTDimServer(const char* servername);
+ ~AliHLTDimServer();
+
+ /// Data type identifiers for services.
+ enum AliHLTDimServiceDataType{
+ kDataTypeUnknown = 0, /// initializer
+ kDataTypeInt, /// Integer type
+ kDataTypeFloat, /// Float type
+ kDataTypeString, /// String type
+ };
+
+ /// The service data field.
+ struct AliHLTDimServicePoint_t {
+ union {
+ int iVal; /// integer value
+ float fVal; /// float value
+ void* strVal; /// string value, casted to string* before use
+ };
+ };
+
+ /** @class AliHLTDimService
+ * Base class for DIM services
+ */
+ class AliHLTDimService : public TNamed {
+ public:
+ AliHLTDimService();
+ AliHLTDimService(AliHLTDimServiceDataType type, const char* servicename);
+
+ void Update(AliHLTDimServicePoint_t& sp);
+ AliHLTDimServiceDataType GetType() const {return fType;}
+ void* GetLocation() {return &fData.iVal;}
+ int GetId() const {return fId;}
+ int SetId(int id) {fId=id;return id;}
+
+ private:
+ AliHLTDimServicePoint_t fData; /// the data point
+ AliHLTDimServiceDataType fType; /// type of this service
+ int fId; /// id of the service
+ };
+
+ /** @class AliHLTDimServiceFloat
+ * DIM service for a float value
+ */
+ class AliHLTDimServiceFloat : public AliHLTDimService {
+ public:
+ AliHLTDimServiceFloat();
+ ~AliHLTDimServiceFloat();
+
+ void Update(float f) {
+ AliHLTDimServicePoint_t sp; sp.fVal=f; AliHLTDimService::Update(sp);
+ }
+ };
+
+ /**
+ * Register a service.
+ * @param pService the service to be registered
+ * @ingroup rcu_ce_base_services
+ */
+ int RegisterService(AliHLTDimService* pService);
+
+ /**
+ * Create a service.
+ * @param type type of the channel, see @ref ceServiceDataType
+ * @param name unique name of the service
+ * @return dim service object, needs to be cleaned by the caller
+ * @ingroup rcu_ce_base_services
+ */
+ AliHLTDimService* CreateService(AliHLTDimServiceDataType type, const char* name);
+
+ /**
+ * Create a group of services.
+ * The names are built from the basename and the number of services.
+ * @param type type of the channel
+ * @param basename base name of the services, the name might contain a '%d' sequence which is then
+ * replaced by the number, number is appended if no '%d' provided
+ * @param count number of services in this group, passed to the <i>update</i> and <i>set</i> function as parameter major
+ * @return TObjArray of AliHLTDimService objects, the array needs to be cleaned by the caller
+ * @ingroup rcu_ce_base_services
+ */
+ TObjArray* CreateServiceGroup(AliHLTDimServiceDataType type, const char* basename, int count);
+
+ /// Update all services via the Dim channel
+ int UpdateServices();
+
+ /// init the server
+ /// load the dim library and function pointers
+ /// init dim (DNS and server name)
+ int Init(const char* dimNameServer);
+
+ /// Reset
+ int Reset();
+
+ /// start the server
+ int Start();
+
+ /// stop the server
+ int Stop();
+
+protected:
+ enum AliHLTDimServerState_t {
+ // server is not started
+ kStateOff = 0,
+ // starting, will be changed by the server thread to kStateRunning
+ kStateStarting,
+ // server running
+ kStateRunning,
+ // set by the main thread and changed by the server thread before it terminates
+ kStateStopping,
+ // error
+ kStateError
+ };
+
+ int SetState(int state) {fState=state; return fState;}
+
+ int GetState() {return fState;}
+
+ typedef void (*fctVoid)();
+ typedef int (*fctDisServiceCallback)( const char*);
+ typedef int (*fctDisAddService) ( const char* service,
+ const char* type,
+ void* buffer,
+ int size,
+ fctDisServiceCallback cb,
+ long int tag);
+ typedef int (*fctDisRemoveService) ( unsigned int id);
+ typedef int (*fctDisUpdateService) ( unsigned int id);
+ typedef int (*fctDisCharArg) ( const char*);
+ typedef int (*fctDisNoArg) ( );
+
+ /// @class AliHLTDimInterface Interface to the dim library
+ class AliHLTDimInterface : public AliHLTLogging {
+ public:
+ AliHLTDimInterface();
+ ~AliHLTDimInterface();
+
+ /// load the dim library and function pointers
+ int Init();
+
+ int DisAddService(const char* service, const char* type, void* buffer,
+ int size, fctDisServiceCallback cb, long int tag) {
+ if (fpDisAddService) return (*fpDisAddService)(service, type, buffer, size, cb, tag);
+ return -ENODEV;
+ }
+
+ int DisAddService(const char* service, const char* type, void* buffer, int size) {
+ if (fpDisAddService) return (*fpDisAddService)(service, type, buffer, size, NULL, 0);
+ return -ENODEV;
+ }
+
+ int DisRemoveService(unsigned int id) {
+ if (fpDisRemoveService) return (*fpDisRemoveService)(id);
+ return -ENODEV;
+ }
+
+ int DisUpdateService(unsigned int id) {
+ if (fpDisUpdateService) return (*fpDisUpdateService)(id);
+ return -ENODEV;
+ }
+
+ int DisStartServing(const char *server) {
+ if (fpDisStartServing) return (*fpDisStartServing)(server);
+ return -ENODEV;
+ }
+
+ int DisStopServing() {
+ if (fpDisStopServing) return (*fpDisStopServing)();
+ return -ENODEV;
+ }
+
+ int DisSetDnsNode(const char *server) {
+ if (fpDisSetDnsNode) return (*fpDisSetDnsNode)(server);
+ return -ENODEV;
+ }
+
+ private:
+ fctVoid FindSymbol(const char* library, const char* symbol) const;
+
+ fctDisAddService fpDisAddService; //! transient
+ fctDisRemoveService fpDisRemoveService; //! transient
+ fctDisUpdateService fpDisUpdateService; //! transient
+ fctDisCharArg fpDisStartServing; //! transient
+ fctDisNoArg fpDisStopServing; //! transient
+ fctDisCharArg fpDisSetDnsNode; //! transient
+ static const char* fgkDimLibraryName ; //!
+ static const char* fgkDisAddServiceSymbol; //!
+ static const char* fgkDisRemoveServiceSymbol; //!
+ static const char* fgkDisUpdateServiceSymbol; //!
+ static const char* fgkDisStartServingSymbol; //!
+ static const char* fgkDisStopServingSymbol; //!
+ static const char* fgkDisSetDnsNodeSymbol; //!
+ };
+
+ static AliHLTDimInterface* Interface();
+
+private:
+ /// copy constructor not permitted
+ AliHLTDimServer(const AliHLTDimServer&);
+ /// assignment operator not permitted
+ AliHLTDimServer& operator=(const AliHLTDimServer&);
+
+ /// entry point for the thread, param is pointer to object
+ static void* ServerLoop(void* param);
+
+ /// the server loop
+ void* ServerLoop();
+
+ TObjArray fServices; //! list of services
+ int fState; //! state of the server
+ TThread* fpServerThread; //! thread
+ int fUpdatePeriod; //! update period for the DIM loop in ms
+
+ static AliHLTDimInterface* fgpInterface; //! the dim interface
+
+ ClassDef(AliHLTDimServer, 0)
+};
+#endif