#include "AliHLTDimServer.h"
#include "TObjArray.h"
#include "TSystem.h"
#include "TThread.h"
ClassImp(AliHLTDimServer)
AliHLTDimServer::AliHLTDimServer()
: TNamed()
, fServices()
, fState(kStateOff)
, fpServerThread(NULL)
, fUpdatePeriod(10000)
{
}
AliHLTDimServer::AliHLTDimServer(const char* servername)
: TNamed(servername, "AliHLTDimServer")
, fServices()
, fState(kStateOff)
, fpServerThread(NULL)
, fUpdatePeriod(10000)
{
}
AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::fgpInterface=NULL;
AliHLTDimServer::~AliHLTDimServer()
{
}
int AliHLTDimServer::RegisterService(AliHLTDimService* pService)
{
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)
{
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)+5+digits;
char* name=(char*)malloc(namelen);
char* format=(char*)malloc(namelen);
if (name && format) {
memset(name, 0, namelen);
memset(format, 0, namelen);
const char* key=strchr(basename, '%');
strncpy(format, basename, namelen-1);
if (key && key[1]!=0) {
int iPos=(key-basename)+1;
if (key[1]=='d') {
snprintf(format+iPos, namelen-iPos, "0*d");
iPos+=3;
} else {
*(format+iPos++)='%';
*(format+iPos++)=key[1];
}
strncpy(format+iPos, &key[2], namelen-1-iPos);
} else {
snprintf(format+strlen(basename), namelen-strlen(basename), "_%%0*d");
}
for (i=0; i<count && iResult>=0; i++) {
snprintf(name, namelen, 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;
}
int AliHLTDimServer::UpdateServices()
{
return 0;
}
AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::Interface()
{
if (!fgpInterface) {
fgpInterface=new AliHLTDimInterface;
if (fgpInterface) {
if (fgpInterface->Init() != 0) {
delete fgpInterface;
fgpInterface = NULL;
}
}
}
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()
{
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()
{
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)
{
if (!param) return (void*)0;
AliHLTDimServer* server=reinterpret_cast<AliHLTDimServer*>(param);
return server->ServerLoop();
}
void* AliHLTDimServer::ServerLoop()
{
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;
TString name=GetName(); name+="_"; name+=pService->GetName();
const char* type="";
void* buffer=pService->GetLocation();
int size=0;
switch (pService->GetType()) {
case kDataTypeCustom:
case kDataTypeInt:
case kDataTypeFloat:
type=pService->GetTypeString();
size=pService->GetDataSize();
break;
case kDataTypeString:
log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: type 'string' not yet implemented", name.Data());
break;
default:
log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: unknown type %d", name.Data(), pService->GetType());
}
if (type[0]!=0) {
int id=Interface()->DisAddService(name.Data(), type, buffer, size);
if (id<0) {
log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to add dim service %s: error %d", name.Data(), id);
} else {
pService->SetId(id);
}
}
}
SetState(kStateRunning);
Interface()->DisStartServing(GetName());
while (GetState()==kStateRunning) {
gSystem->Sleep(fUpdatePeriod);
}
if (GetState()!=kStateStopping) return (void*)0;
Interface()->DisStopServing();
next.Reset();
while ((obj=next())!=NULL) {
const AliHLTDimService* pService=dynamic_cast<const AliHLTDimService*>(obj);
if (!pService || pService->GetId()<0) continue;
}
SetState(kStateOff);
return (void*)0;
}
AliHLTDimServer::AliHLTDimService::AliHLTDimService()
: TNamed()
, fData()
, fType(kDataTypeUnknown)
, fTypeString()
, fDataBuffer(NULL)
, fDataSize(0)
, fId(-1)
{
}
AliHLTDimServer::AliHLTDimService::AliHLTDimService(enum AliHLTDimServiceDataType type, const char* servicename)
: TNamed(servicename, "AliHLTDimService")
, fData()
, fType(type)
, fTypeString()
, fDataBuffer(NULL)
, fDataSize(0)
, fId(-1)
{
AliHLTLogging log;
switch (fType) {
case kDataTypeCustom:
log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "cannot use the kDataTypeCustom type with this method");
break;
case kDataTypeInt:
fTypeString="I";
fDataBuffer=&fData.iVal;
fDataSize=sizeof(int);
break;
case kDataTypeFloat:
fTypeString="F";
fDataBuffer=&fData.fVal;
fDataSize=sizeof(float);
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);
};
}
AliHLTDimServer::AliHLTDimService::AliHLTDimService(const char* type, void* data, int size, const char* servicename)
: TNamed(servicename, "AliHLTDimService")
, fData()
, fType(kDataTypeCustom)
, fTypeString(type)
, fDataBuffer(data)
, fDataSize(size)
, fId(-1)
{
}
void AliHLTDimServer::AliHLTDimService::Update()
{
static bool bWarning=true;
AliHLTLogging log;
switch (fType) {
case kDataTypeCustom: break;
default:
if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "The service %s must be a custom type (kDataTypeCustom) to use this form of Update", GetName());
bWarning=false;
};
AliHLTDimServer::Interface()->DisUpdateService(fId);
}
void AliHLTDimServer::AliHLTDimService::Update(const AliHLTDimServicePoint_t& sp)
{
static bool bWarning=true;
AliHLTLogging log;
switch (fType) {
case kDataTypeCustom:
if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Should not call this form of Update for custom type (kDataTypeCustom) service %s", GetName());
bWarning=false;
return;
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::Interface()->DisUpdateService(fId);
}
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()
{
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
{
TString tmp=symbol;
fctVoid fctptr=gSystem->DynFindSymbol(library, tmp.Data());
if (!fctptr) {
tmp+="_";
fctptr=gSystem->DynFindSymbol(library, tmp.Data());
}
if (fctptr) return fctptr;
HLTError("can not find symbol '%s' in %s", symbol, library);
return NULL;
}