// Author: Egon Pavlica <http://www.p-ng.si/~pavlica/>
//________________________________________
// This is server class
// modified to conect to LClient
//
//
//
// Logs:
//
// $Log: LServer.cc,v $
// Revision 1.10 2004/03/12 14:52:33 cvs
// a bug was found and repaired, when data was saved over other one, so directories and jobID in data didnt matched!
//
// Revision 1.9 2004/02/11 11:23:47 cvs
// found and resolved some bugs in LServer.cc and hoppserv.cc
//
// Revision 1.8 2003/11/24 17:06:23 cvs
// a bug was corrected in LServer::GetLData and the error bars were corrected when drawing Draw(".tof.")
//
// Revision 1.7 2003/11/15 17:17:26 cvs
// new scheme is working...
// Clients (hoppclient) are connected as kLC_AMAX and free socket is given
// TLServer (lserver) is multithreading
// LServer (hoppserver) has a file which is always in memory - faster but needs more memory
//
// Revision 1.6 2003/11/11 17:33:03 cvs
// LServer upgraded
//
// Revision 1.5 2003/07/09 10:53:13 cvs
// added some verbosity and changed LContainer class. The LData isnt changed. Corrected daemon mode of hoppserv, since network connection is dependend on process pid. So the connection should be opened by child processes.
//
// Revision 1.4 2003/06/26 09:27:11 cvs
// added log fields...
//
#include "LServer.h"
#include <iostream>
#include <syslog.h>
#include <TCollection.h>
#include <TKey.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <TH1.h>
ClassImp(LServer)
LServer::LServer(TLClient* calling,const char* filename,int syslogd){
//and open (update) root file of name filename
fsocket=calling;
fname=new TString(filename); //ROOT filename
fdatabase=0;//dynamically open
fdata=0;//dynamically open
fheader=0;//dynamically open
if (syslogd) SetSysLog(); else fsyslog=0;
char message[80];
sprintf(message,"Database is ready (%s)",filename);
SendLog(message);
}
LServer::~LServer(){
//default destructor
if (fname) {
delete fname;
fname=0;
}
CloseDataBase();
}
void
LServer::SetSysLog(){
//set the server to send logs to syslogd -> e.g. /var/log/messages
fsyslog=1;
}
Int_t
LServer::SendLog(const char* message){
if(fverbose) std::cout<<message<<std::endl;
if (fsyslog) syslog(LOG_INFO,message);
if(!fsocket->IsConnected()) {
if(fverbose) std::cerr<<"Error:LServer no network connectionn";
return 0;
}
fsocket->SendTo(kLC_RC,kRC_NEW_MESSAGE);
fsocket->SendTo(kLC_RC,message);
return 1;
}
Bool_t
LServer::ReceiveString() {
//goes through all clients that thinks will talk to
//receive fStr from client fclient
//if something is wrong, then returns kFALSE
Int_t rc;
Bool_t wait=kFALSE;
fclient=kLC_MAX;
if ((rc=fsocket->RecvFrom(kLC_RC,fStr,wait)) && rc && (fclient=kLC_RC))
return kTRUE;
if ((rc=fsocket->RecvFrom(kLC_CLIENT,fStr,wait)) && rc && (fclient=kLC_CLIENT))
return kTRUE;
if ((rc=fsocket->RecvFrom(kLC_HDELIVER,fStr,wait)) && rc && (fclient=kLC_HDELIVER))
return kTRUE;
if ((rc=fsocket->RecvFrom(kLC_ANA1,fStr,wait)) && rc && (fclient=kLC_ANA1))
return kTRUE;
if ((rc=fsocket->RecvFrom(kLC_ANA2,fStr,wait)) && rc && (fclient=kLC_ANA2))
return kTRUE;
if ((rc=fsocket->RecvFrom(kLC_ANA3,fStr,wait)) && rc && (fclient=kLC_ANA3))
return kTRUE;
// if (fverbose) std::cout<<"rc:"<<rc<<"n";
if(rc==-4) {
return kFALSE;
}
if(rc==-1) {
fsocket->SetDisconnected();
return kFALSE;
}
return kFALSE;
}
int
LServer::WaitConnection(){
//this is only filter, which captures kRC_STOP_RUN
if (ReceiveString()){
// if (fverbose) std::cout<<"Something recived:"<<fStr<<"n";
if(!strcmp(fStr,kRC_STOP_RUN)) {
if (fverbose) std::cout<<"received stop run commandn";
return 0;
}
if(!strcmp(fStr,kRC_UPDATE_FILE)) {
if (fverbose) std::cout<<"received update file commandn";
CloseDataBase();
OpenDataBase();
return 1;
}
return 1;
}
sleep(1);//something goes wrong better to sleep for a while
return 1;//and continue to serving
}
void
LServer::Serving(){
char str[32];
TObject* obj=0;
fStr[0]='X';
while(WaitConnection()){
if(fclient!=kLC_MAX){//someone is connected
if(!strcmp(fStr,kRC_UPDATE_STATE)) {
//receive an object
fsocket->RecvFrom(fclient,obj);
sprintf(str,"%s",obj->ClassName());
if (fverbose>2) std::cout<<"RECV: "<<str<<"n";
if(!strcmp(str,"LData"))
DataTransfer((LData*)obj);
if(!strcmp(str,"LContainer"))
DataContainerTransfer((LContainer*)obj);
if(!strcmp(str,"LDataHeader"))
DataHeaderTransfer((LDataHeader*)obj);
//BUG HERE?
if (obj) delete obj;
obj=0;
//empty buffer string
fStr[0]='X';
}
}
}
if (obj) delete obj;
CloseDataBase();
return;
}
Int_t LServer::DataTransfer(LData* data){
//connection for data transfer is handled
if (fverbose>1) std::cout<<"data transfer...n";
char messag[256];
char* datum;
time_t t1;
time(&t1);datum=ctime(&t1);datum[strlen(datum)-1]='0';
if (!data->GetJobID()) {
sprintf(messag,"%s:Data without JobID - Ignored!",datum);
} else {
LData* old=GetLData(data->GetJobID());
if (!old)
sprintf(messag,"%s:Data ignored",datum);
else {
old->Add(data);//add new data
sprintf(messag,"%s:Data added",datum);
}
}
SendLog(messag);
return 1;
}
Int_t LServer::DataContainerTransfer(LContainer* data){
//connection for data container transfer is handled
if (fverbose>1) std::cout<<"data container transfer...n";
//create message
char messag[256];
char* datum;
time_t t1;
time(&t1);datum=ctime(&t1);datum[strlen(datum)-1]='0';
//open file for reading
if (!data->GetJobID()) {
//if container has no jobID so is useless!!
sprintf(messag,"%s:Data container without jobID:%s",datum,data->GetLog());
} else {
LData* old=GetLData(data->GetJobID());
if (!old)
sprintf(messag,"%s:Data ignored:%s",datum,data->GetLog());
else {
old->Add(data);//add new data from container
sprintf(messag,"%s:Data added:%s",datum,data->GetLog());
}
}
SendLog(messag);
return 1;
}
Int_t LServer::DataHeaderTransfer(LDataHeader* header){
//connection for data transfer is handled
if (fverbose>1) std::cout<<"data header transfer...n";
if (!header->GetJobID()) {
SendLog("Header without JobID!- Ignored");
return 1;
}
//check if already exists and is loaded
if (fheader && fheader->GetJobID()==header->GetJobID()) return 1;
//check the database
TFile* datoteka=OpenDataBase();
datoteka->cd();
MkDirectory(header);
LDataHeader* old=(LDataHeader*)gDirectory->Get("header");
if (old) {//header already exist
if (old->GetJobID()==header->GetJobID()){ //check
if (fheader) {
//fheader->Write("header",TObject::kOverwrite);
delete fheader;
}
fheader=old; return 1;
} else {
delete old; return 1;
}//end check
} else {//new one
header->Write("header"); return(1);
}
return 1;
}
TDirectory* LServer::MkDirectory(LDataHeader* header){
//this function cd fname to last directory regarding jobID it returns the pointer to created directory. if directory already exist 0 is returned
char jobid[256];
sprintf(jobid,"%ld",header->GetJobID());
TDirectory* created; created=0;
if (!gDirectory->cd(jobid)) {
created=gDirectory->mkdir(jobid);
gDirectory->cd(jobid);
char* datum;
time_t t1;
char message[256];
time(&t1);datum=ctime(&t1);datum[strlen(datum)-1]='0';
sprintf(message,"%s:Directory %s created",datum,jobid);
SendLog(message);
if (fverbose>1) std::cout<<"Directory "<<jobid<<" created!"<<std::endl;
}
return created;
}
TDirectory* LServer::CdDirectory(Long_t jobID){
//this function cd fname to last directory of specific jobID and returns the pointer to it
TFile* Rootfile=OpenDataBase();
Rootfile->cd();
char dirname[256];
sprintf(dirname,"%ld",jobID);
Rootfile->cd(dirname);
return gDirectory;//CORRECTION OF MEMORY LEAK
}
TFile* LServer::OpenDataBase(){
//open ROOT file for writing
if (!fdatabase)
fdatabase=new TFile((const char*)fname->Data(),(const char*)"update",(const char*)"",0);
return fdatabase;
}
void LServer::CloseDataBase(){
if (fdata){
CdDirectory(fdata->GetJobID());
fdata->Write("data",TObject::kOverwrite);
delete fdata; fdata=0;
}
if (fheader){
// fheader->Write("header",TObject::kOverwrite);
delete fheader;
fheader=0;
}
if (fdatabase) {
fdatabase->Close();
delete fdatabase;
fdatabase=0;
}
}
LData* LServer::GetLData(Long_t jobID){
//we suppose here, the file is already open
//this return pointer to data if already exists, or load new data from file
//or create new data from header in file (header must be there!)
if (fdata && fdata->GetJobID()==jobID) return fdata;
//new jobID has came searching directory with that name in database
CdDirectory(jobID);
int found=0;
TIter* next=new TIter(gDirectory->GetListOfKeys());
TKey* key;
while((key=(TKey*)(*next)()))
if (!strcmp("data",key->GetName())) {found=1;break;}
delete next;
if (found) {
//old data found - yuhu
if (fdata){
CdDirectory(fdata->GetJobID());
fdata->Write("data",TObject::kOverwrite);
delete fdata; fdata=0;
CdDirectory(jobID);
}
fdata=(LData*)gDirectory->Get("data");
return fdata;
} else {
//find header,make new data, add container
//header should be always presented before data arives
if (fheader && fheader->GetJobID()!=jobID) {delete fheader;fheader=0;}
if (!fheader) fheader=(LDataHeader*)gDirectory->Get("header");
if (!fheader) {
if (fverbose){
std::cerr<<"Error: adding container:no header with jobID:"<<jobID<<std::endl;
std::cerr<<"Received data ignored!"<<std::endl;
std::cerr<<"Hint: You have probably changed file name in hoppserv. So your header is stored in another file, while you want to store simulated data in another file. If this error repeates several times for the same JobID, you should worry about!"<<std::endl;
}
return 0;
}
fdata=new LData(fheader);//creating data
//delete oldh;
return fdata;
}
return 0;
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.