Skip to content
Snippets Groups Projects
Commit 9f3fdf68 authored by Chao1009's avatar Chao1009
Browse files

add the et channel class

parent 9cbecff2
No related branches found
No related tags found
No related merge requests found
......@@ -65,6 +65,7 @@ target_include_directories(${LIBNAME}
$<BUILD_INTERFACE:${SPDLOG_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${SPDLOG_INCLUDE_DIR}>
$<BUILD_INTERFACE:${FMT_INCLUDE_DIR}>
/site/coda/3.10/Linux-x86_64/include
)
target_compile_options(${LIBNAME}
......@@ -77,10 +78,16 @@ if(WITH_DEBUG)
target_compile_definitions(${LIBNAME} PUBLIC WITH_DEBUG)
endif()
target_link_directories(${LIBNAME}
PUBLIC
"/site/coda/3.10/Linux-x86_64/lib"
)
target_link_libraries(${LIBNAME}
PUBLIC
Podd::Podd
Podd::Decode
et
)
set_target_properties(${LIBNAME} PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
......@@ -111,6 +118,7 @@ build_root_dictionary(${LIBNAME} ${headers}
-I${CMAKE_CURRENT_SOURCE_DIR}/include/hcana
-I${Podd_DIR}/../../include
-I${Podd_DIR}/../../include/podd2
-I/site/coda/3.10/Linux-x86_64/include
TARGETS ${LIBNAME}
LINKDEF include/HallC_LinkDef.h
)
......
//============================================================================//
// A C++ wrapper class for C based ET //
// //
// Chao Peng //
// 02/27/2016 //
//============================================================================//
#include "PRadETChannel.h"
#include "PRadETStation.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
using namespace std;
PRadETChannel::PRadETChannel(size_t size)
: curr_stat(nullptr), et_id(nullptr), bufferSize(size)
{
buffer = new uint32_t[bufferSize];
}
PRadETChannel::~PRadETChannel()
{
if(buffer != nullptr)
delete[](buffer), buffer = nullptr;
// force close ET
ForceClose();
}
// Close ET connection
void PRadETChannel::ForceClose()
{
if(et_id != nullptr && et_alive(et_id))
{
et_forcedclose(et_id);
et_id = nullptr;
}
}
// Open ET
void PRadETChannel::Open(const char* ipAddr, int tcpPort, const char* etFile)
{
// Use a direct connection to the ET system
config.SetCast(ET_DIRECT);
// Set the ip address and tcp port
config.SetHost(ipAddr);
config.SetServerPort(tcpPort);
int charSize = strlen(etFile)+1;
char *fileName = new char[charSize];
strncpy(fileName, etFile, charSize);
// Open et client
int status = et_open(&et_id, fileName, config.Get());
delete fileName;
if(status != ET_OK) {
throw(PRadException(PRadException::ET_CONNECT_ERROR, "et_client: cannot open et client!"));
}
/* set level of debug output */
et_system_setdebug(et_id, ET_DEBUG_INFO);
}
void PRadETChannel::NewStation(const string &name)
{
auto it = stations.find(name);
if(it == stations.end()) {
curr_stat = new PRadETStation(this, name);
stations[string(name)] = curr_stat;
}
}
void PRadETChannel::SwitchStation(const string &name)
{
auto it = stations.find(name);
if(it != stations.end()) {
curr_stat = it->second;
} else {
cout << "ET Channel Warning: station " << name << " does not exist!" << endl;
}
}
void PRadETChannel::RemoveStation(const string &name)
{
try {
if(et_id != nullptr && et_alive(et_id)) {
auto it = stations.find(name);
if(it != stations.end()) {
it->second->Remove();
stations.erase(it);
} else {
cout << "ET Channel Warning: station " << name << " does not exist!" << endl;
}
} else {
cout << "ET Channel Warning: cannot remove station while disconnected from ET!" << endl;
}
} catch (PRadException e) {
throw e;
}
}
PRadETStation* PRadETChannel::GetStation(const string &name)
{
auto it = stations.find(name);
if(it != stations.end()) {
return it->second;
} else {
return nullptr;
}
}
// Attach station
void PRadETChannel::AttachStation()
{
try {
curr_stat->Create();
curr_stat->Attach();
} catch (PRadException e) {
throw(e);
}
cout << "Successfully attached to ET!" << endl;
}
// Read one event from ET station, return true if success
bool PRadETChannel::Read()
{
// check if et is opened or alive
if(et_id == nullptr || !et_alive(et_id))
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is not opened or dead!"));
et_att_id att = curr_stat->GetAttachID();
// get the event
int status = et_event_get(et_id, att, &etEvent, ET_ASYNC, nullptr);
switch(status)
{
case ET_OK:
break;
case ET_ERROR_EMPTY:
return false;
case ET_ERROR_DEAD:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is dead!"));
case ET_ERROR_TIMEOUT:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: got timeout!!"));
case ET_ERROR_BUSY:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: station is busy!"));
case ET_ERROR_WAKEUP:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: someone told me to wake up."));
default:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: unkown error!"));
}
// copy the data buffer
copyEvent();
// put back the event
status = et_event_put(et_id, att, etEvent);
switch(status)
{
case ET_OK:
break;
case ET_ERROR_DEAD:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is dead!"));
default:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: unkown error!"));
}
return true;
}
void PRadETChannel::copyEvent()
{
void *data;
et_event_getdata(etEvent, &data);
et_event_getlength(etEvent, &bufferSize);
bufferSize /= 4; // from byte to int32 words
uint32_t *data_buffer = (uint32_t*) data;
size_t index = 0;
// check if it is a block header
if(bufferSize >= 8 && data_buffer[7] == 0xc0da0100) {
index += 8;
bufferSize -= 8;
}
for(size_t i = 0; i < bufferSize; ++i)
{
buffer[i] = data_buffer[index+i];
}
}
// nested config classes
// et_openconfig
PRadETChannel::Configuration::Configuration()
{
Initialize();
}
PRadETChannel::Configuration::~Configuration()
{
et_open_config_destroy(config);
}
// wrapper functions
void PRadETChannel::Configuration::Initialize()
{
et_open_config_init(&config);
}
void PRadETChannel::Configuration::SetWait(int val)
{
et_open_config_setwait(config, val);
}
void PRadETChannel::Configuration::SetTimeOut(struct timespec val)
{
et_open_config_settimeout(config, val);
}
void PRadETChannel::Configuration::SetHost(const char *val)
{
et_open_config_sethost(config, val);
}
void PRadETChannel::Configuration::SetCast(int val)
{
et_open_config_setcast(config, val);
}
void PRadETChannel::Configuration::SetTTL(int val)
{
et_open_config_setTTL(config, val);
}
void PRadETChannel::Configuration::SetPort(unsigned short val)
{
et_open_config_setport(config, val);
}
void PRadETChannel::Configuration::SetServerPort(unsigned short val)
{
et_open_config_setserverport(config, val);
}
void PRadETChannel::Configuration::AddBroadCast(const char *val)
{
et_open_config_addbroadcast(config, val);
}
void PRadETChannel::Configuration::RemoveBroadCast(const char *val)
{
et_open_config_removebroadcast(config, val);
}
void PRadETChannel::Configuration::AddMultiCast(const char *val)
{
et_open_config_addmulticast(config, val);
}
void PRadETChannel::Configuration::RemoveMultiCast(const char *val)
{
et_open_config_removemulticast(config, val);
}
void PRadETChannel::Configuration::SetPolicy(int val)
{
et_open_config_setpolicy(config, val);
}
void PRadETChannel::Configuration::SetMode(int val)
{
et_open_config_setmode(config, val);
}
void PRadETChannel::Configuration::SetDebugDefault(int val)
{
et_open_config_setdebugdefault(config, val);
}
void PRadETChannel::Configuration::SetInterface(const char *val)
{
et_open_config_setinterface(config, val);
}
void PRadETChannel::Configuration::SetTCP(int rBufSize, int sBufSize, int noDelay)
{
et_open_config_settcp(config, rBufSize, sBufSize, noDelay);
}
#ifndef PRAD_ET_CHANNEL_H
#define PRAD_ET_CHANNEL_H
#include <unordered_map>
#include <string>
#include <stdint.h>
#include "et.h"
#include "PRadException.h"
#include "PRadETStation.h"
#define ET_CHUNK_SIZE 500
class PRadETChannel
{
public:
class Configuration
{
public:
Configuration();
virtual ~Configuration();
et_openconfig &Get() {return config;}
// wrapper functions
void Initialize();
void SetWait(int val);
void SetTimeOut(struct timespec val);
void SetHost(const char *val);
void SetCast(int val);
void SetTTL(int val);
void SetPort(unsigned short val);
void SetServerPort(unsigned short val);
void AddBroadCast(const char *val);
void RemoveBroadCast(const char *val);
void AddMultiCast(const char *val);
void RemoveMultiCast(const char *val);
void SetPolicy(int val);
void SetMode(int val);
void SetDebugDefault(int val);
void SetInterface(const char *val);
void SetTCP(int rBufSize, int sBufSize, int noDelay);
private:
et_openconfig config;
};
public:
PRadETChannel(size_t size = 1048576);
virtual ~PRadETChannel();
void Open(const char *ipAddr, int tcpPort, const char *etFile);
void NewStation(const std::string &name);
void SwitchStation(const std::string &name);
void RemoveStation(const std::string &name);
void AttachStation();
void DetachStation();
void ForceClose();
bool Read();
void *GetBuffer() {return (void*) buffer;}
size_t GetBufferLength() {return bufferSize;}
Configuration &GetConfig() {return config;}
et_sys_id &GetID() {return et_id;}
PRadETStation *GetCurrentStation() {return curr_stat;}
PRadETStation *GetStation(const std::string &name);
private:
Configuration config;
PRadETStation *curr_stat;
std::unordered_map<std::string, PRadETStation*> stations;
et_sys_id et_id;
et_event *etEvent;
uint32_t *buffer;
size_t bufferSize;
void copyEvent();
};
#endif
//============================================================================//
// A C++ wrapper class for C based ET station //
// //
// Chao Peng //
// 04/01/2016 //
//============================================================================//
#include "PRadETStation.h"
#include "PRadETChannel.h"
PRadETStation::PRadETStation(PRadETChannel *p, std::string n, int mode)
: et_system(p), name(n)
{
PreSetting(mode);
}
PRadETStation::~PRadETStation()
{
Remove();
}
void PRadETStation::PreSetting(int mode)
{
// Generic settings
config.SetUser(ET_STATION_USER_MULTI);
config.SetRestore(ET_STATION_RESTORE_OUT);
config.SetPrescale(1);
config.SetCUE(ET_CHUNK_SIZE);
// TODO, change to meaningful settings
int selections[] = {17,15,-1,-1};
char fName[] = "et_my_function";
char libName[] = "libet_user.so";
// some pre-defined settings
// TODO, make these settings selectable
switch(mode)
{
case 1:
config.SetSelect(ET_STATION_SELECT_ALL);
config.SetBlock(ET_STATION_BLOCKING);
break;
case 2:
config.SetSelect(ET_STATION_SELECT_ALL);
config.SetBlock(ET_STATION_NONBLOCKING);
break;
case 3:
config.SetSelect(ET_STATION_SELECT_MATCH);
config.SetBlock(ET_STATION_BLOCKING);
config.SetSelectWords(selections);
break;
case 4:
config.SetSelect(ET_STATION_SELECT_MATCH);
config.SetBlock(ET_STATION_NONBLOCKING);
config.SetSelectWords(selections);
break;
case 5:
config.SetSelect(ET_STATION_SELECT_USER);
config.SetBlock(ET_STATION_BLOCKING);
config.SetSelectWords(selections);
config.SetFunction(fName);
config.SetLib(libName);
break;
case 6:
config.SetSelect(ET_STATION_SELECT_USER);
config.SetBlock(ET_STATION_NONBLOCKING);
config.SetSelectWords(selections);
config.SetFunction(fName);
config.SetLib(libName);
break;
}
}
// Create station
void PRadETStation::Create()
{
char s_name[256];
strcpy(s_name, name.c_str());
/* create the station */
int status = et_station_create(et_system->GetID(), &station_id, s_name, config.Get());
if(status < ET_OK) {
if(status == ET_ERROR_EXISTS) {
/* station_id contains pointer to existing station */;
throw(PRadException(PRadException::ET_STATION_CREATE_ERROR, "et_client: station already exists!"));
} else if(status == ET_ERROR_TOOMANY) {
throw(PRadException(PRadException::ET_STATION_CREATE_ERROR, "et_client: too many stations created!"));
} else {
throw(PRadException(PRadException::ET_STATION_CREATE_ERROR, "et_client: error in station creation!"));
}
}
}
void PRadETStation::Attach()
{
if(et_station_attach(et_system->GetID(), station_id, &attach_id) < ET_OK) {
throw(PRadException(PRadException::ET_STATION_ATTACH_ERROR, "et_client: error in station attach!"));
}
}
void PRadETStation::Detach()
{
if(et_station_detach(et_system->GetID(), attach_id) < ET_OK) {
throw(PRadException(PRadException::ET_STATION_ATTACH_ERROR, "et_client: error in station dettach!"));
}
}
void PRadETStation::Remove()
{
if(et_station_remove(et_system->GetID(), station_id) < ET_OK) {
throw(PRadException(PRadException::ET_STATION_ATTACH_ERROR, "et_client: error in station remove!"));
}
}
// et_station_config
PRadETStation::Configuration::Configuration()
{
Initialize();
}
PRadETStation::Configuration::~Configuration()
{
et_station_config_destroy(config);
}
// wrapper functions
void PRadETStation::Configuration::Initialize()
{
et_station_config_init(&config);
}
void PRadETStation::Configuration::SetBlock(int val)
{
et_station_config_setblock(config, val);
}
void PRadETStation::Configuration::SetFlow(int val)
{
et_station_config_setflow(config, val);
}
void PRadETStation::Configuration::SetSelect(int val)
{
et_station_config_setselect(config, val);
}
void PRadETStation::Configuration::SetUser(int val)
{
et_station_config_setuser(config, val);
}
void PRadETStation::Configuration::SetRestore(int val)
{
et_station_config_setrestore(config, val);
}
void PRadETStation::Configuration::SetCUE(int val)
{
et_station_config_setcue(config, val);
}
void PRadETStation::Configuration::SetPrescale(int val)
{
et_station_config_setprescale(config, val);
}
void PRadETStation::Configuration::SetSelectWords(int val[])
{
et_station_config_setselectwords(config, val);
}
void PRadETStation::Configuration::SetFunction(const char *val)
{
et_station_config_setfunction(config, val);
}
void PRadETStation::Configuration::SetLib(const char *val)
{
et_station_config_setlib(config, val);
}
void PRadETStation::Configuration::SetClass(const char *val)
{
et_station_config_setclass(config, val);
}
#ifndef PRAD_ET_STATION_H
#define PRAD_ET_STATION_H
#include "et.h"
#include "PRadException.h"
#include <string>
class PRadETChannel;
class PRadETStation
{
public:
class Configuration
{
public:
Configuration();
virtual ~Configuration();
et_statconfig &Get() {return config;}
//wrapper functions
void Initialize();
void SetBlock(int val);
void SetFlow(int val);
void SetSelect(int val);
void SetUser(int val);
void SetRestore(int val);
void SetCUE(int val);
void SetPrescale(int val);
void SetSelectWords(int val[]);
void SetFunction(const char *val);
void SetLib(const char *val);
void SetClass(const char *val);
private:
et_statconfig config;
};
public:
PRadETStation(PRadETChannel *p, std::string n, int mode = 2);
virtual ~PRadETStation();
Configuration &GetConfig() {return config;}
et_stat_id &GetID() {return station_id;}
et_att_id &GetAttachID() {return attach_id;}
std::string GetName() {return name;}
void PreSetting(int mode);
void Create();
void Attach();
void Detach();
void Remove();
private:
PRadETChannel *et_system;
std::string name;
et_att_id attach_id;
et_stat_id station_id;
Configuration config;
};
#endif
//============================================================================//
// A exception class for PRad Event Viewer //
// //
// Chao Peng //
// 02/27/2016 //
//============================================================================//
#include "PRadException.h"
using namespace std;
PRadException::PRadException(const string &typ, const string &txt, const string &aux)
: title(typ), text(txt), auxText(aux)
{
}
PRadException::PRadException(PRadExceptionType typ, const string &txt, const string &aux)
: type(typ), text(txt), auxText(aux)
{
}
PRadException::PRadException(PRadExceptionType typ, const string &txt, const string &file, const string &func, int line)
: type(typ), text(txt)
{
ostringstream oss;
oss << " evioException occured in file " << file << ", function " << func << ", line " << line;
auxText=oss.str();
}
string PRadException::FailureDesc(void) const
{
ostringstream oss;
oss << text << endl
<< auxText;
return(oss.str());
}
string PRadException::FailureType(void) const
{
if(!title.empty())
return title;
string oss;
switch(type)
{
case ET_CONNECT_ERROR:
oss = "ET CONNECT ERROR";
break;
case ET_CONFIG_ERROR:
oss = "ET CONFIG ERROR";
break;
case ET_STATION_CONFIG_ERROR:
oss = "ET STATION CONFIG ERROR";
break;
case ET_STATION_CREATE_ERROR:
oss = "ET STATION CREATE ERROR";
break;
case ET_STATION_ATTACH_ERROR:
oss = "ET ATTACH ERROR";
break;
case ET_READ_ERROR:
oss = "ET READ ERROR";
break;
case ET_PUT_ERROR:
oss = "ET PUT ERROR";
break;
case HIGH_VOLTAGE_ERROR:
oss = "HIGH VOLTAGE SYSTEM ERROR";
break;
default:
oss = "UNKNOWN ERROR";
break;
}
return(oss);
}
const char* PRadException::what() const noexcept
{
string failure = FailureType() + ": " + FailureDesc();
return failure.c_str();
}
#ifndef PRAD_EXCEPTION_H
#define PRAD_EXCEPTION_H
#include <stdlib.h>
#include <string.h>
#include <exception>
#include <string>
#include <sstream>
class PRadException : public std::exception
{
public:
enum PRadExceptionType
{
UNKNOWN_ERROR,
ET_CONNECT_ERROR,
ET_CONFIG_ERROR,
ET_STATION_CONFIG_ERROR,
ET_STATION_CREATE_ERROR,
ET_STATION_ATTACH_ERROR,
ET_READ_ERROR,
ET_PUT_ERROR,
HIGH_VOLTAGE_ERROR,
};
PRadException(const std::string &typ, const std::string &txt = "", const std::string &aux = "");
PRadException(PRadExceptionType typ = UNKNOWN_ERROR, const std::string &txt = "", const std::string &aux = "");
PRadException(PRadExceptionType typ, const std::string &txt, const std::string &file, const std::string &func, int line);
virtual ~PRadException(void) {}
virtual std::string FailureDesc(void) const;
virtual std::string FailureType(void) const;
const char *what() const noexcept;
public:
PRadExceptionType type; // exception type
std::string title;
std::string text; // primary text
std::string auxText; // auxiliary text
};
#endif
......@@ -3,6 +3,7 @@
#include "THaBenchmark.h"
#include "THcAnalyzer.h"
#include "PRadETChannel.h"
#include <iostream>
......@@ -16,9 +17,13 @@ namespace hcana {
virtual Int_t Process(THaRunBase* run = nullptr);
virtual Int_t ReadOneEvent();
//Int_t GoToEndOfCodaFile();
void SetETChannel(PRadETChannel *ch) { online_ch = ch; }
PRadETChannel *GetETChannel() { return online_ch; }
int _skip_events = 0;
PRadETChannel *online_ch;
ClassDef(Scandalizer, 0) // Hall C Analyzer Standard Event Loop
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment