#include <iostream>
#include <sstream>
#include <cctype>
#include <cstring>
#include <sys/time.h>
#include <sys/resource.h>
#include <DAQ++/DAQmanager.h>
#include <DAQ++/Parameter.h>
#include <DAQ++/logger.h>
#include "../data/Analysis.h"
#include "../data/DataFormat.h"
#include "GenModule.h"
#include "Rmanager.h"
#include <config/Config.h>
#include <config/ParseOpt.h>
Rmanager::Rmanager(DAQpp::DAQid id, DAQpp::RunCommand *rc)
: DAQpp::RunManager(id, rc), DAQpp::ParameterCollection<Rmanager>(this), logger(0)
{
add_par("command", new_par<std::string>(&Rmanager::set_command,new DAQpp::Par<std::string>()) );
ConfigParser *cfg = ConfigParser::theConfig();
GeneralConfig *gnrl = dynamic_cast<GeneralConfig *>(cfg->get_handler("general"));
set_monitor( new MyMonitor(this, gnrl->get_monitor_buffer()) );
//get_monitor()->set_user_timeout(10000);
}
Rmanager::~Rmanager()
{
DAQpp::ostream os;
os << DAQpp::loglevel(DAQpp::Log::info) << "...destroying RunManager " << get_id() << std::endl;
}
void Rmanager::PrepareForRun()
{
ObserverList::iterator ip;
Observable &O = *(*this)();
for (ip=O.begin();ip!=O.end();ip++)
{
GenModule *m = dynamic_cast<GenModule *>( *ip );
if ( m )
{
m->set_run_type( get_run_type() );
}
}
DAQpp::RunManager::PrepareForRun();
}
void Rmanager::Start()
{
DAQpp::ostream os;
os << DAQpp::loglevel(DAQpp::Log::info) << "[RM." << get_id() << "] Starting the run" << std::endl;
event_number = 0;
DAQpp::RunManager::Start();
}
void Rmanager::Stop()
{
DAQpp::ostream os;
get_status().set_status( DAQpp::RunState::Stopping );
DAQpp::RunManager::Stop();
os << DAQpp::loglevel(DAQpp::Log::info) << "End of run" << std::endl;
stop_logging();
os << DAQpp::loglevel(DAQpp::Log::info) << "Quit Rmanager::Stop()" << std::endl;
}
int Rmanager::writeTail(const char **hdata, Rmanager *rm)
{
unsigned int *data = new unsigned int[4];
data[0] = DataHeader | EndOfRunRecord | 4;
data[1] = time(0);
data[2] = rm->get_run_number();
data[3] = 4;
*hdata = (char *)(data);
return 4*sizeof(unsigned int);
}
int Rmanager::writeHeader(const char **hdata, Rmanager *rm)
{
std::ostringstream oheader;
DAQpp::RunCommand *cmd = (*rm)();
int i = 0, n_modules = cmd->countObservers();
int size = 5 + n_modules;
unsigned int *data = reinterpret_cast<unsigned int *>(
DAQpp::Module::allocate_real(sizeof(unsigned int) * size));
// Start of Run block
data[i++] = DataHeader | StartOfRunRecord | size;
data[i++] = time(0);
data[i++] = rm->get_run_number();
data[i++] = n_modules;
ObserverList::iterator ip;
for (ip = cmd->begin();ip != cmd->end();++ip)
{
GenModule *m = dynamic_cast<GenModule *>( *ip );
m->set_header_description(data[i]);
i++;
}
data[i] = size;
oheader.write((char *)data, size*sizeof(unsigned int));
DAQpp::Module::deallocate_real((char *)data);
// Write pedestals
rm->writePedestals(oheader);
// Write Maps
rm->writeMaps(oheader);
// Write the configuration records
rm->writeConfig(oheader);
// Write any xtra section specific to the run manager
rm->writeHeaderXtra(oheader);
// write the block
int ss = oheader.str().size();
*hdata = new char[ss];
memcpy((void *)(*hdata), oheader.str().c_str(), ss);
return ss;
}
void Rmanager::writeMaps(std::ostream &oheader)
{
int size;
DAQpp::RunCommand *cmd = (*this)();
/** MAPs block
* The format of the data is the following
*
* \verbatim
* Word
* 0 0xCAFEibbb i= event type bbbb= size of data block
* 1 0xaaaaaaaa aaaaaaaa = module id
* 2 0xiiiijjjj iiii = nx, jjjj=ny
* 2 0xaaaabbbb aaaa= pix. no. of chan 0, bbbb=pix no. of chan 1
* . .
* bbbb bbbb size of data block
* \endverbatim
*
* where pixel numbers go like:
* pix. no. = y * nx + x
*/
unsigned int val;
int iword, i;
ObserverList::iterator ip;
for (ip = cmd->begin();ip != cmd->end();++ip)
{
GenModule *md = dynamic_cast<GenModule *>(*ip);
Analysis *a = md->get_analysis();
PadMap *m = a->get_map();
if (!m)
continue;
iword = 0;
size = 4 + a->Ntot() / 2;
val = 0xcafe0000 | MapRecord | size;
oheader.write((char *)&val, sizeof(unsigned int));
iword ++;
val = (unsigned int)md->get_id();
oheader.write((char *)&val, sizeof(unsigned int));
iword ++;
val = (m->nx()) << 16 | m->ny();
oheader.write((char *)&val, sizeof(unsigned int));
iword ++;
for (i = 0;i < a->Ntot();i += 2)
{
int ix, iy;
m->pad(i, ix, iy);
ix &= 0xff;
iy &= 0xff;
val = (ix << 24) | (iy << 16);
m->pad(i + 1, ix, iy);
ix &= 0xff;
iy &= 0xff;
val |= (ix << 8) | iy;
oheader.write((char *)&val, sizeof(unsigned int));
iword++;
}
val = ++iword;
oheader.write((char *)&val, sizeof(unsigned int));
}
}
void Rmanager::writePedestals(std::ostream &oheader)
{
int size;
unsigned int *data;
DAQpp::RunCommand *cmd = (*this)();
/** Pedestal block.
*
* The format of the data is the following
*
* \verbatim
* Word
* 0 0xCAFEibbb i= event type bbbb= size of data block
* 1 0xaaaaaaaa aaaaaaaa = module id
* 2 0xaaaabbbb aaaa= n chips bbbb= nchan
* 3 0xnnnnpppp nnnn = 50*noise, pppp=50*pedestal
* . .
* bbbb bbbb size of data block
* \endverbatim
*/
ObserverList::iterator ip;
for (ip = cmd->begin();ip != cmd->end();++ip)
{
GenModule *m = dynamic_cast<GenModule *>(*ip);
data = m->write_pedestals(size);
if (data)
{
oheader.write((char *)data, size*sizeof(unsigned int));
delete [] data;
}
}
}
void Rmanager::writeConfig(std::ostream &oheader)
{
/** Config block.
*
* There is one config block per module and only those
* modules providing the data will have their config
* block writen.
*
* The format of the block depends on the data provided
* by the module. The RunManager will only define the
* block header and the module identifier:
*
* \verbatim
* Word
* 0 0xCAFE8nnnn nnnn=size of data block
* 1 0xaaaaaaaa aaaaaaaa = module id
* .
* . data block provided by the module
* .
* bbbb bbbb size of data block
* \endverbatim
*/
int size;
unsigned int lsize, *data;
unsigned int val[3];
DAQpp::RunCommand *cmd = (*this)();
ObserverList::iterator ip;
for (ip = cmd->begin();ip != cmd->end();++ip)
{
GenModule *m = dynamic_cast<GenModule *>(*ip);
data = m->write_config(size);
if (data)
{
/** TODO: we need a way to sort out what happens if we need
* more that 12 bits to specify the block size
*/
lsize = (size+3) & 0xfff;
val[0] = DataHeader | ConfigRecord | lsize;
val[1] = (unsigned int)(m->get_id());
oheader.write((char *)val, 2*sizeof(unsigned int));
oheader.write((char *)data, size*sizeof(unsigned int));
oheader.write((char *)&lsize, sizeof(unsigned int));
delete [] data;
}
}
}
void Rmanager::log_data(const char *file, bool cmp, int sz)
{
if (file )
{
/*
* We create the logger here with the hook specified
* in the configuration file
*/
logger = create_logger(cmp, sz);
logger->open(file);
}
}
void Rmanager::stop_logging()
{
if ( logger )
{
DAQpp::ostream os;
os << DAQpp::loglevel(DAQpp::Log::info) << "Stopping data logger" << std::endl;
logger->close();
delete logger;
logger = 0;
}
}
int Rmanager::writeData(int size, const char *data)
{
int rc = size;
if ( get_logger() )
{
obuf.write(data, size);
}
return rc;
}
void Rmanager::EndOfEvent()
{
if ( get_logger() && obuf.str().size() )
{
// get_logger()->writeData(obuf.str().size(),obuf.str().c_str());
logger->write(obuf.str().c_str(), obuf.str().size());
}
// else
// GetStatus().new_written();
event_number++;
obuf.str("");
// Get a pointer to the configuration manager
ConfigParser *cfg = ConfigParser::theConfig();
PluginParser *plugin = dynamic_cast<PluginParser *>(cfg->get_handler("plugins"));
bool do_int = false;
try
{
do_int = get_par_value<bool>("doInterrupts");
}
catch ( DAQpp::Exception &ex )
{
do_int = false;
}
if (do_int)
plugin->reset_interrupts();
}
#include "DataRunManager.h"
#include "PedestalRunManager.h"
#include "PulseRunManager.h"
#include "IntTrgRunManager.h"
#include "ScanRunManager.h"
Rmanager *Rmanager::new_manager(const std::string &s, const DAQpp::DAQid &id)
{
if ( s == "data" )
return new DataRunManager(id);
if ( s == "pedestal" )
return new PedestalRunManager(id);
if ( s == "int_trg" )
return new IntTrgRunManager(id);
if ( s == "pulse" )
return new PulseRunManager(id);
if (s == "scan")
return new ScanRunManager(id);
std::cout << "*** Rmanager::new_manager: invalid run type " << s << std::endl;
return 0;
}
DAQpp::FileIOManager *Rmanager::create_logger(bool cmp, int sz)
{
ConfigParser *cfg = ConfigParser::theConfig();
PluginParser *plugin = dynamic_cast<PluginParser *>(cfg->get_handler("plugins"));
DAQpp::FileIOManager *fm = plugin->create_logger(cmp, sz);
if (!fm)
{
fm = new DAQpp::FileIOManager(cmp, sz);
fm->set_header_func((DAQpp::FileIOManager::HeaderFunc)writeHeader, (char *)this);
fm->set_tail_func((DAQpp::FileIOManager::HeaderFunc)writeTail, (char *)this);
}
return fm;
}
Rmanager *Rmanager::create_run_manager(const std::string &rm_type, const DAQpp::DAQid &name)
{
ConfigParser *cfg = ConfigParser::theConfig();
PluginParser *plugin = dynamic_cast<PluginParser *>(cfg->get_handler("plugins"));
Rmanager *rm =
dynamic_cast<Rmanager *>(
DAQpp::DAQmanager::theDAQmanager()->find_runmanager(name)
);
// The run manager already exist, so we will delete the old one
// and "transfer" the modules to the new one
std::vector<DAQpp::Module *> lm;
if ( rm ) {
lm = rm->deplete_run_manager();
delete rm;
}
// Create the new one
rm = dynamic_cast<Rmanager *>(plugin->create_run_manager(rm_type, name));
// ... and insert the modules
std::vector<DAQpp::Module *>::iterator ip;
for (ip = lm.begin();ip != lm.end();++ip)
rm->addModule( *ip );
return rm;
}
std::vector<DAQpp::Module *> Rmanager::deplete_run_manager()
{
std::vector<DAQpp::Module *> out;
ObserverList::iterator ip;
// fill the vector of modules first
for (ip = (*this)()->begin();ip != (*this)()->end();++ip)
{
DAQpp::Module *md = dynamic_cast<DAQpp::Module *>(*ip);
if ( md )
out.push_back(md);
}
std::vector<DAQpp::Module *>::iterator im;
for (im = out.begin();im != out.end();im++)
(*im)->UnRegisterDAQ();
return out;
}
void Rmanager::set_command(const std::string &cmmd)
{
ConfigParser *cfg = ConfigParser::theConfig();
SectionParser *sp = cfg->get_handler("IO");
IOConfig *io = dynamic_cast<IOConfig *>(sp);
/** Gives a linker problem in Linux
ParseOpt Opt(cmmd);
if (Opt.get_command()=="logData")
{
std::string ofile=Opt.find_opt("file");
if (!ofile.empty())
{
log_data(ofile.c_str(),
io->get_compression(),
io->get_max_size());
}
}
std::cout << "\n\n*** Received command " << Opt.get_command() << " -> " << cmmd << "\n*\n*\n\n" << std::endl;
*/
}