Commit 95ab1d76 authored by dino's avatar dino
Browse files

Refactoring


git-svn-id: svn://gal-serv.lnl.infn.it/agata/trunk/narval_emulator@1205 170316e4-aea8-4b27-aad4-0380ec0519c9
parent 3767d3f7
#include <iostream>
#include <fstream>
#include <iomanip>
#include "CycleServer.h"
#if OS_TYPE != OS_WINDOWS
# include <unistd.h>
#endif
using namespace std;
void CycleServer::Start(std::string name, unsigned int cycleMin, unsigned int cycleMax)
{
SetPrompt(name);
secMinStep = cycleMin;
secMaxStep = cycleMax;
mRate.reset();
mCount = sCount = 0;
tstStart = tstCheck = tstWrite = tstThis = 0;
lastWrite = time(NULL);
}
// check if it exists and remove if requested (and possible)
bool CycleServer::CheckComFile(bool remove)
{
if( comFile.empty() )
return false;
FILE *fp = fopen(comFile.c_str(), "r");
if(!fp)
return false;
fclose(fp);
if(remove)
RemoveComFile();
return true;
}
bool CycleServer::CheckComFile(bool &erase, bool remove)
{
erase = false;
if( comFile.empty() )
return false;
FILE *fp = fopen(comFile.c_str(), "rb");
if(!fp)
return false;
// At the moment just check if it has some data
// Should be developed to decode command lines
char cbuf[10];
size_t nr = fread(cbuf, 1, 1, fp);
erase = (nr==1);
fclose(fp);
if(remove)
RemoveComFile();
return true;
}
bool CycleServer::RemoveComFile()
{
#if OS_TYPE == OS_WINDOWS
int done = _unlink(comFile.c_str());
#else
int done = unlink(comFile.c_str());
#endif
return (done == 0);
}
void CycleServer::SetPrompt(std::string name)
{
myName = "-" + name + ":";
//size_t ln = myName.length();
//for(size_t nn = ln; nn < 24; nn++)
// myName += " " ;
//ln = myName.length();
}
unsigned int CycleServer::Prompt(int id, unsigned int nevs, unsigned int bsize, bool isAll)
{
//if(mCount > sCount) {
// Check(); // only if new events
//}
if(id >= 0)
cout << setw(3) << id;
else
cout << " ";
unsigned int irate = GetRate();
cout << left << setw(24) << myName << right
<< " " << setw(6) << nevs
<< " evts (" << setw(8) << bsize << ")"
<< " Tot = " << setw(8) << GetCounts()
<< " " << setw(5) << irate << "/s";
if(isAll)
cout << endl;
return irate;
}
unsigned int CycleServer::ExecLong(bool newStep)
{
unsigned int actions = 0;
#ifdef MULTIHIST_SPECTRA
if(!hGroup)
return actions;
#endif //MULTIHIST_SPECTRA
if(mCount <= sCount)
return actions; // to avoid re-writing if no new data
#ifdef MULTIHIST_SPECTRA
if( hGroup->write(false, true) ) {
actions |= 1;
if(newStep)
tstStepSet(2*tstStep); // increase writing interval
lastWrite = time(NULL);
}
bool erase = false;
if( CheckComFile(erase, true) ) {
if(erase) {
hGroup->erase(true);
actions |= 2;
tstStepSet(tst1second*60); // restart with smaller steps
}
}
#endif //MULTIHIST_SPECTRA
sCount = mCount;
tstCheck = tstThis + tst1second*secMinStep;
tstWrite = tstThis + tstStep;
return actions;
}
#ifndef CYCLESERVER_H_INCLUDED
#define CYCLESERVER_H_INCLUDED
// Class to mange all cyclic activities like
// saving spectra and measuring event-rates
#include <ctime>
#include "commonDefs.h"
#include "Misc.h"
#ifdef MULTIHIST_SPECTRA
# include "MultiHist.h"
#endif
class ratemeter
{
clock_t *tStart;
unsigned int *tCount;
unsigned int mod;
unsigned int pos;
public:
ratemeter(int imod = 5)
{
mod = imod > 2 ? imod : 5;
tStart = new clock_t [mod];
tCount = new unsigned int[mod];
reset();
}
void start() { reset(); }
void reset()
{
clock_t tstart = clock();
for(unsigned int nn = 0; nn < mod; nn++) {
tStart[nn] = tstart;
tCount[nn] = 0;
}
pos = 0;
}
// The problem with the rate estimate is that time() returns elapsed seconds (which
// is too rough) and there seems to be no portable solution with higher precision.
// To smooth the result, we keep a queue of calls so as to average over longer time intervals
// Now using clock() which has a higher resolution of 1/CLOCKS_PER_SEC (ms in Windows);
// but still using the queue of old values to get smoother rates.
unsigned int rate(unsigned int counts)
{
clock_t tNow = clock();
clock_t tOld = tStart[pos];
unsigned int cOld = tCount[pos];
float sdiff = (tNow - tOld)/(float)CLOCKS_PER_SEC;
if(sdiff < 0.1f) sdiff = 0.1f;
unsigned int srate = (counts>cOld) ? (unsigned int)((counts-cOld)/sdiff) : 0;
// update only if at least mod elapsed seconds since previous update
tOld = tStart[((pos+mod)-1)%mod];
if(sdiff > mod) {
tStart[pos] = tNow;
tCount[pos] = counts;
pos = (pos+1)%mod;
}
return srate;
}
};
class CycleServer
{
unsigned long long tstStart; // value of the first timestamp
unsigned long long tstCheck; // timestamp for the NEXT check == tstNow + tst1second*secMinStep;
unsigned long long tstWrite; // timestamp for the NEXT write == tstNow + tstStep
unsigned long long tstStep; // tst interval to write spectra; tst1second*secMinStep, 2*, 4*, ..., tst1second*secMaxStep
unsigned long long tstThis; // tst-seconds of the lat Exec() call
unsigned int mCount; // counter of Exec() calls
unsigned int sCount; // mCount of last ExecLong()
unsigned int secMinStep; // elapsed time between Check() calls
unsigned int secMaxStep; // max elapsed seconds of the write-spectra cycle
time_t lastWrite; // when last spectra have been written (in seconds since the epoch);
ratemeter mRate; // analysis-rate estimator
std::string myName; // name of the actor, used in Prompt()
std::string comFile; // where to look for commands write and/or erase spectra
#ifdef MULTIHIST_SPECTRA
MultiHistGroup *hGroup; // pointers of all defined MultiHist spectra
#endif //MULTIHIST_SPECTRA
unsigned int ExecLong(bool newStep = true); // actions performed when it is time dump spectra
bool CheckComFile(bool remove = false);
bool CheckComFile(bool &erase, bool remove = false);
bool RemoveComFile();
void tstStepSet(unsigned long long tst = tst1second*defaultMinCycleTime) {
tstStep = (tst>secMaxStep*tst1second) ? secMaxStep*tst1second : tst;
if(tstStep < tst1second) tstStep = tst1second;
}
public:
CycleServer(unsigned int cycleMin = defaultMinCycleTime, unsigned int cycleMax = defaultMaxCycleTime) :
mCount(0), sCount(0),
tstStart(0), tstCheck(0), tstWrite(0), tstThis(0), tstStep(0),
secMinStep(cycleMin), secMaxStep(cycleMax), lastWrite(0)
{
#ifdef MULTIHIST_SPECTRA
hGroup = NULL;
#endif //MULTIHIST_SPECTRA
}
void SetCommandFile(std::string name) {
comFile = name;
}
#ifdef MULTIHIST_SPECTRA
void SetHistGroup(MultiHistGroup *hg) {
hGroup = hg;
}
#endif //MULTIHIST_SPECTRA
void Start(std::string name, unsigned int cycleMin = defaultMinCycleTime, unsigned int cycleMax = defaultMaxCycleTime);
unsigned int Exec(unsigned long long tstNew) {
++mCount;
tstThis = tstNew;
if(!tstWrite) {
// first time only
tstStart = tstThis;
tstCheck = tstThis + tst1second*secMinStep;
tstStepSet(tst1second*secMinStep);
tstWrite = tstThis + tstStep;
lastWrite = time(NULL);
return 0;
}
// every tst-minute check if time to write or forced write
if(tstThis >= tstCheck) {
tstCheck = tstThis + tst1second*secMinStep; // set next check tstTime
return Check(); // if enough time passed, this will write the spectra
}
return 0;
}
unsigned int Check() {
if(CheckComFile()) {
// presence of comFile forces a write cycle
return ExecLong(false);
}
if(tstThis >= tstWrite) {
#if NRV_TYPE != NRV_ONLINE
// As offline analysis can run much faster than the "timestamp seconds" we require a minimum elapsed time
unsigned int elapsedSeconds = (unsigned int)(time(NULL)-lastWrite);
if(elapsedSeconds >= secMinStep)
#endif
return ExecLong(true);
}
return 0;
}
void Finish() {
ExecLong(false);
#ifdef MULTIHIST_SPECTRA
if(hGroup)
hGroup->remove();
#endif //MULTIHIST_SPECTRA
}
unsigned int GetCounts() { return mCount; }
unsigned int GetRate() { return mRate.rate(mCount); }
int GetRunTime(){ return int((tstThis-tstStart)/tst1second); }
void Reset() {}
void SetPrompt(std::string name);
unsigned int Prompt(int id, unsigned int nevs, unsigned int bsize, bool isAll = true);
};
#endif // CYCLESERVER_H_INCLUDED
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment