Merge branch 'developer' into jsonmaster

This commit is contained in:
maliakal_d 2022-03-29 16:29:55 +02:00
commit e68499bb09
21 changed files with 616 additions and 273 deletions

View File

@ -54,7 +54,7 @@ This document describes the differences between v7.0.0 and v6.x.x
- added geometry to metadata - added geometry to metadata
- 10g eiger nextframenumber get fixed. - 10g eiger nextframenumber get fixed.
- stop, able to set nextframenumber to a consistent (max + 1) for all modules if different (eiger/ctb/jungfrau/moench) - stop, able to set nextframenumber to a consistent (max + 1) for all modules if different (eiger/ctb/jungfrau/moench)
- fpga/kernel programming, checks if drive is a special file and not a normal file - ctb: can set names for all the dacs
- fpga/kernel programming, checks if drive is a special file and not a normal file - fpga/kernel programming, checks if drive is a special file and not a normal file
- gotthard 25 um image reconstructed in gui and virtual hdf5 (firmware updated for slave to reverse channels) - gotthard 25 um image reconstructed in gui and virtual hdf5 (firmware updated for slave to reverse channels)

View File

@ -1,43 +1,45 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
from .detector import Detector from .detector import Detector, freeze
from .utils import element_if_equal from .utils import element_if_equal
from .dacs import DetectorDacs from .dacs import DetectorDacs, NamedDacs
import _slsdet import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty
class CtbDacs(DetectorDacs): # class CtbDacs(DetectorDacs):
""" # """
Ctb dacs # Ctb dacs
""" # """
_dacs = [('dac0', dacIndex(0), 0, 4000, 1400), # _dacs = [('dac0', dacIndex(0), 0, 4000, 1400),
('dac1', dacIndex(1), 0, 4000, 1200), # ('dac1', dacIndex(1), 0, 4000, 1200),
('dac2', dacIndex(2), 0, 4000, 900), # ('dac2', dacIndex(2), 0, 4000, 900),
('dac3', dacIndex(3), 0, 4000, 1050), # ('dac3', dacIndex(3), 0, 4000, 1050),
('dac4', dacIndex(4), 0, 4000, 1400), # ('dac4', dacIndex(4), 0, 4000, 1400),
('dac5', dacIndex(5), 0, 4000, 655), # ('dac5', dacIndex(5), 0, 4000, 655),
('dac6', dacIndex(6), 0, 4000, 2000), # ('dac6', dacIndex(6), 0, 4000, 2000),
('dac7', dacIndex(7), 0, 4000, 1400), # ('dac7', dacIndex(7), 0, 4000, 1400),
('dac8', dacIndex(8), 0, 4000, 850), # ('dac8', dacIndex(8), 0, 4000, 850),
('dac9', dacIndex(9), 0, 4000, 2000), # ('dac9', dacIndex(9), 0, 4000, 2000),
('dac10', dacIndex(10), 0, 4000, 2294), # ('dac10', dacIndex(10), 0, 4000, 2294),
('dac11', dacIndex(11), 0, 4000, 983), # ('dac11', dacIndex(11), 0, 4000, 983),
('dac12', dacIndex(12), 0, 4000, 1475), # ('dac12', dacIndex(12), 0, 4000, 1475),
('dac13', dacIndex(13), 0, 4000, 1200), # ('dac13', dacIndex(13), 0, 4000, 1200),
('dac14', dacIndex(14), 0, 4000, 1600), # ('dac14', dacIndex(14), 0, 4000, 1600),
('dac15', dacIndex(15), 0, 4000, 1455), # ('dac15', dacIndex(15), 0, 4000, 1455),
('dac16', dacIndex(16), 0, 4000, 0), # ('dac16', dacIndex(16), 0, 4000, 0),
('dac17', dacIndex(17), 0, 4000, 1000), # ('dac17', dacIndex(17), 0, 4000, 1000),
] # ]
_dacnames = [_d[0] for _d in _dacs] # _dacnames = [_d[0] for _d in _dacs]
from .utils import element from .utils import element
@freeze
class Ctb(Detector): class Ctb(Detector):
def __init__(self, id = 0): def __init__(self, id = 0):
super().__init__(id) super().__init__(id)
self._frozen = False self._frozen = False
self._dacs = CtbDacs(self) # self._dacs = CtbDacs(self)
self._dacs = NamedDacs(self)
@property @property
def dacs(self): def dacs(self):

View File

@ -36,6 +36,79 @@ class Dac(DetectorProperty):
dacstr = ''.join([f'{item:5d}' for item in self.get()]) dacstr = ''.join([f'{item:5d}' for item in self.get()])
return f'{self.__name__:15s}:{dacstr}' return f'{self.__name__:15s}:{dacstr}'
class NamedDacs:
"""
New implementation of the detector dacs. Used at the momen for
Ctb but should replace the old one for all detectors
"""
_frozen = False
_direct_access = ['_detector', '_current', '_dacnames']
def __init__(self, detector):
self._detector = detector
self._current = 0
self._dacnames = [n.replace(" ", "") for n in detector.getDacNames()]
# # Populate the dacs
for i,name in enumerate(self._dacnames):
#name, enum, low, high, default, detector
setattr(self, name, Dac(name, dacIndex(i), 0, 4000, 1000, detector))
self._frozen = True
# def __getattr__(self, name):
# return self.__getattribute__('_' + name)
def __setattr__(self, name, value):
if not self._frozen:
#durining init we need to be able to set up the class
super().__setattr__(name, value)
else:
#Later we restrict us to manipulate dacs and a few fields
if name in self._direct_access:
super().__setattr__(name, value)
elif name in self._dacnames:
return self.__getattribute__(name).__setitem__(slice(None, None, None), value)
else:
raise AttributeError(f'Dac not found: {name}')
def __next__(self):
if self._current >= len(self._dacnames):
self._current = 0
raise StopIteration
else:
self._current += 1
return self.__getattribute__(self._dacnames[self._current-1])
# return self.__getattr__(self._dacnames[self._current-1])
def __iter__(self):
return self
def __repr__(self):
r_str = ['========== DACS =========']
r_str += [repr(dac) for dac in self]
return '\n'.join(r_str)
def get_asarray(self):
"""
Read the dacs into a numpy array with dimensions [ndacs, nmodules]
"""
dac_array = np.zeros((len(self._dacnames), len(self._detector)))
for i, _d in enumerate(self):
dac_array[i,:] = _d[:]
return dac_array
def to_array(self):
return self.get_asarray()
def set_from_array(self, dac_array):
"""
Set the dacs from an numpy array with dac values. [ndacs, nmodules]
"""
dac_array = dac_array.astype(np.int)
for i, _d in enumerate(self):
_d[:] = dac_array[i]
def from_array(self, dac_array):
self.set_from_array(dac_array)
class DetectorDacs: class DetectorDacs:
_dacs = [] _dacs = []
@ -50,7 +123,7 @@ class DetectorDacs:
# Index to support iteration # Index to support iteration
self._current = 0 self._current = 0
# Populate the dacs # Name the attributes?
for _d in self._dacs: for _d in self._dacs:
setattr(self, '_'+_d[0], Dac(*_d, detector)) setattr(self, '_'+_d[0], Dac(*_d, detector))
@ -59,6 +132,9 @@ class DetectorDacs:
def __getattr__(self, name): def __getattr__(self, name):
return self.__getattribute__('_' + name) return self.__getattribute__('_' + name)
@property
def dacnames(self):
return [_d[0] for _d in _dacs]
def __setattr__(self, name, value): def __setattr__(self, name, value):
if name in self._dacnames: if name in self._dacnames:

View File

@ -1571,8 +1571,16 @@ class Detector(CppDetectorApi):
@property @property
def daclist(self): def daclist(self):
"""Gets the list of enums for every dac for this detector.""" """
return self.getDacList() List of enums for every dac for this detector.
:setter: Only implemented for Chiptestboard
"""
return self.getDacNames()
@daclist.setter
def daclist(self, value):
self.setDacNames(value)
@property @property
def dacvalues(self): def dacvalues(self):

View File

@ -1427,6 +1427,19 @@ void init_det(py::module &m) {
(void (Detector::*)(bool, sls::Positions)) & (void (Detector::*)(bool, sls::Positions)) &
Detector::setLEDEnable, Detector::setLEDEnable,
py::arg(), py::arg() = Positions{}) py::arg(), py::arg() = Positions{})
.def("setDacNames",
(void (Detector::*)(const std::vector<std::string>)) &
Detector::setDacNames,
py::arg())
.def("getDacNames", (std::vector<std::string>(Detector::*)() const) &
Detector::getDacNames)
.def("getDacIndex",
(defs::dacIndex(Detector::*)(const std::string &)) &
Detector::getDacIndex,
py::arg())
.def("getDacName",
(std::string(Detector::*)(defs::dacIndex)) & Detector::getDacName,
py::arg())
.def("setPattern", .def("setPattern",
(void (Detector::*)(const std::string &, sls::Positions)) & (void (Detector::*)(const std::string &, sls::Positions)) &
Detector::setPattern, Detector::setPattern,

View File

@ -7,6 +7,7 @@ set(SOURCES
src/CmdProxy.cpp src/CmdProxy.cpp
src/CmdParser.cpp src/CmdParser.cpp
src/Pattern.cpp src/Pattern.cpp
src/CtbConfig.cpp
) )
add_library(slsDetectorObject OBJECT add_library(slsDetectorObject OBJECT

View File

@ -1613,6 +1613,14 @@ class Detector {
/** [CTB] Default is enabled. */ /** [CTB] Default is enabled. */
void setLEDEnable(bool enable, Positions pos = {}); void setLEDEnable(bool enable, Positions pos = {});
void setDacNames(const std::vector<std::string> names);
std::vector<std::string> getDacNames() const;
defs::dacIndex getDacIndex(const std::string& name);
std::string getDacName(defs::dacIndex i);
///@} ///@}
/** @name Pattern */ /** @name Pattern */

View File

@ -1056,11 +1056,10 @@ std::string CmdProxy::TemperatureValues(int action) {
std::string CmdProxy::Dac(int action) { std::string CmdProxy::Dac(int action) {
std::ostringstream os; std::ostringstream os;
os << cmd << ' '; os << cmd << ' ';
auto type = det->getDetectorType().squash();
// dac indices only for ctb // dac indices only for ctb
if (args.size() > 0 && action != defs::HELP_ACTION) { if (args.size() > 0 && action != defs::HELP_ACTION) {
if (is_int(args[0]) && if (is_int(args[0]) && type != defs::CHIPTESTBOARD) {
det->getDetectorType().squash() != defs::CHIPTESTBOARD) {
throw sls::RuntimeError( throw sls::RuntimeError(
"Dac indices can only be used for chip test board. Use daclist " "Dac indices can only be used for chip test board. Use daclist "
"to get list of dac names for current detector."); "to get list of dac names for current detector.");
@ -1077,7 +1076,14 @@ std::string CmdProxy::Dac(int action) {
if (args.empty()) if (args.empty())
WrongNumberOfParameters(1); // This prints slightly wrong WrongNumberOfParameters(1); // This prints slightly wrong
defs::dacIndex dacIndex = StringTo<defs::dacIndex>(args[0]); defs::dacIndex dacIndex{};
//TODO! Remove if
if (type == defs::CHIPTESTBOARD && !is_int(args[0])) {
dacIndex = det->getDacIndex(args[0]);
} else {
dacIndex = StringTo<defs::dacIndex>(args[0]);
}
bool mV = false; bool mV = false;
if (args.size() == 2) { if (args.size() == 2) {
@ -1095,7 +1101,11 @@ std::string CmdProxy::Dac(int action) {
if (args.empty()) if (args.empty())
WrongNumberOfParameters(1); // This prints slightly wrong WrongNumberOfParameters(1); // This prints slightly wrong
defs::dacIndex dacIndex = StringTo<defs::dacIndex>(args[0]); defs::dacIndex dacIndex{};
if (type == defs::CHIPTESTBOARD && !is_int(args[0]))
dacIndex = det->getDacIndex(args[0]);
else
dacIndex = StringTo<defs::dacIndex>(args[0]);
bool mV = false; bool mV = false;
if (args.size() == 3) { if (args.size() == 3) {
if ((args[2] != "mv") && (args[2] != "mV")) { if ((args[2] != "mv") && (args[2] != "mV")) {
@ -1115,6 +1125,41 @@ std::string CmdProxy::Dac(int action) {
return os.str(); return os.str();
} }
std::string CmdProxy::DacList(const int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == slsDetectorDefs::HELP_ACTION) {
os << "\n\t[dacname1 dacname2 .. dacname18] \n\t\t[ChipTestBoard] Set "
"the list of dac names for this detector.\n\t\t[All] Gets the "
"list "
"of "
"dac names for every dac for this detector."
<< '\n';
} else if (action == slsDetectorDefs::GET_ACTION) {
if (!args.empty()) {
WrongNumberOfParameters(0);
}
auto t = det->getDacNames();
os << sls::ToString(t) << '\n';
} else if (action == slsDetectorDefs::PUT_ACTION) {
if (det->getDetectorType().squash() != defs::CHIPTESTBOARD) {
throw sls::RuntimeError("This detector already has fixed dac "
"names. Cannot change them.");
}
if (det_id != -1) {
throw sls::RuntimeError("Cannot configure dacnames at module level");
}
if (args.size() != 18) {
WrongNumberOfParameters(18);
}
det->setDacNames(args);
os << ToString(args) << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::DacValues(int action) { std::string CmdProxy::DacValues(int action) {
std::ostringstream os; std::ostringstream os;
os << cmd << ' '; os << cmd << ' ';
@ -1134,13 +1179,15 @@ std::string CmdProxy::DacValues(int action) {
WrongNumberOfParameters(1); WrongNumberOfParameters(1);
} }
auto t = det->getDacList(); auto t = det->getDacList();
auto names = det->getDacNames();
auto name_it = names.begin();
os << '['; os << '[';
auto it = t.cbegin(); auto it = t.cbegin();
os << ToString(*it) << ' '; os << ToString(*name_it++) << ' ';
os << OutString(det->getDAC(*it++, mv, std::vector<int>{det_id})) os << OutString(det->getDAC(*it++, mv, std::vector<int>{det_id}))
<< (!args.empty() ? " mV" : ""); << (!args.empty() ? " mV" : "");
while (it != t.cend()) { while (it != t.cend()) {
os << ", " << ToString(*it) << ' '; os << ", " << ToString(*name_it++) << ' ';
os << OutString(det->getDAC(*it++, mv, std::vector<int>{det_id})) os << OutString(det->getDAC(*it++, mv, std::vector<int>{det_id}))
<< (!args.empty() ? " mV" : ""); << (!args.empty() ? " mV" : "");
} }

View File

@ -837,7 +837,7 @@ class CmdProxy {
/* dacs */ /* dacs */
{"dac", &CmdProxy::Dac}, {"dac", &CmdProxy::Dac},
{"daclist", &CmdProxy::daclist}, {"daclist", &CmdProxy::DacList},
{"dacvalues", &CmdProxy::DacValues}, {"dacvalues", &CmdProxy::DacValues},
{"resetdacs", &CmdProxy::ResetDacs}, {"resetdacs", &CmdProxy::ResetDacs},
{"defaultdac", &CmdProxy::DefaultDac}, {"defaultdac", &CmdProxy::DefaultDac},
@ -1124,6 +1124,7 @@ class CmdProxy {
std::string TemperatureValues(int action); std::string TemperatureValues(int action);
/* dacs */ /* dacs */
std::string Dac(int action); std::string Dac(int action);
std::string DacList(int action);
std::string DacValues(int action); std::string DacValues(int action);
std::string ResetDacs(int action); std::string ResetDacs(int action);
std::string DefaultDac(int action); std::string DefaultDac(int action);
@ -1465,10 +1466,6 @@ class CmdProxy {
/* dacs */ /* dacs */
GET_COMMAND_NOID(
daclist, getDacList,
"\n\tGets the list of commands for every dac for this detector.");
/* on chip dacs */ /* on chip dacs */
INTEGER_USER_IND_COMMAND( INTEGER_USER_IND_COMMAND(
vchip_comp_fe, getOnChipDAC, setOnChipDAC, StringTo<int>, vchip_comp_fe, getOnChipDAC, setOnChipDAC, StringTo<int>,

View File

@ -0,0 +1,72 @@
#include "CtbConfig.h"
#include "SharedMemory.h"
#include "sls/ToString.h"
#include "sls/string_utils.h"
#include <algorithm>
#include <fstream>
#include <sstream>
namespace sls {
CtbConfig::CtbConfig(){
for (size_t i=0; i!=num_dacs; ++i){
setDacName(i, "dac"+ToString(i));
}
}
void CtbConfig::check_index(size_t i) const {
if (!(i < num_dacs)) {
std::ostringstream oss;
oss << "DAC index is too large needs to be below " << num_dacs;
throw RuntimeError(oss.str());
}
}
void CtbConfig::check_size(const std::string &name) const {
if (name.empty())
throw RuntimeError("Name needs to be at least one character");
// dacname_length -1 to account for \0 termination
if (!(name.size() < (name_length - 1))) {
std::ostringstream oss;
oss << "Length of name needs to be less than " << name_length - 1
<< " chars";
throw RuntimeError(oss.str());
}
}
void CtbConfig::setDacName(size_t index, const std::string &name) {
check_index(index);
check_size(name);
char *dst = &dacnames[index * name_length];
memset(dst, '\0', name_length);
memcpy(dst, &name[0], name.size());
}
void CtbConfig::setDacNames(const std::vector<std::string>& names){
for (size_t i = 0; i!=num_dacs; ++i){
setDacName(i, names[i]);
}
}
std::string CtbConfig::getDacName(size_t index) const {
return dacnames + index * name_length;
}
std::vector<std::string> CtbConfig::getDacNames() const {
std::vector<std::string> names;
for (size_t i = 0; i != num_dacs; ++i)
names.push_back(getDacName(i));
return names;
}
const char* CtbConfig::shm_tag(){
return shm_tag_;
}
} // namespace sls

View File

@ -0,0 +1,31 @@
#pragma once
#include <string>
#include <vector>
namespace sls {
class CtbConfig {
static constexpr size_t name_length = 20;
static constexpr size_t num_dacs = 18;
static constexpr const char* shm_tag_ = "ctbdacs";
char dacnames[name_length * num_dacs]{};
void check_index(size_t i) const;
void check_size(const std::string &name) const;
public:
CtbConfig();
CtbConfig(const CtbConfig&) = default;
CtbConfig(CtbConfig&&) = default;
CtbConfig& operator=(const CtbConfig&) = default;
~CtbConfig() = default;
void setDacNames(const std::vector<std::string> &names);
void setDacName(size_t index, const std::string &name);
std::string getDacName(size_t index) const;
std::vector<std::string> getDacNames() const;
static const char* shm_tag();
};
} // namespace sls

View File

@ -7,6 +7,7 @@
#include "CmdProxy.h" #include "CmdProxy.h"
#include "DetectorImpl.h" #include "DetectorImpl.h"
#include "Module.h" #include "Module.h"
#include "CtbConfig.h"
#include "sls/Pattern.h" #include "sls/Pattern.h"
#include "sls/container_utils.h" #include "sls/container_utils.h"
#include "sls/file_utils.h" #include "sls/file_utils.h"
@ -21,11 +22,12 @@
namespace sls { namespace sls {
void freeSharedMemory(int detectorIndex, int moduleIndex) { void freeSharedMemory(int detectorIndex, int moduleIndex) {
// single module // single module
if (moduleIndex >= 0) { if (moduleIndex >= 0) {
SharedMemory<sharedModule> moduleShm(detectorIndex, moduleIndex); SharedMemory<sharedModule> moduleShm(detectorIndex, moduleIndex);
if (moduleShm.IsExisting()) { if (moduleShm.exists()) {
moduleShm.RemoveSharedMemory(); moduleShm.removeSharedMemory();
} }
return; return;
} }
@ -34,16 +36,21 @@ void freeSharedMemory(int detectorIndex, int moduleIndex) {
SharedMemory<sharedDetector> detectorShm(detectorIndex, -1); SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
int numDetectors = 0; int numDetectors = 0;
if (detectorShm.IsExisting()) { if (detectorShm.exists()) {
detectorShm.OpenSharedMemory(); detectorShm.openSharedMemory();
numDetectors = detectorShm()->numberOfModules; numDetectors = detectorShm()->numberOfModules;
detectorShm.RemoveSharedMemory(); detectorShm.removeSharedMemory();
} }
for (int i = 0; i < numDetectors; ++i) { for (int i = 0; i < numDetectors; ++i) {
SharedMemory<sharedModule> moduleShm(detectorIndex, i); SharedMemory<sharedModule> moduleShm(detectorIndex, i);
moduleShm.RemoveSharedMemory(); moduleShm.removeSharedMemory();
} }
// Ctb configuration
SharedMemory<CtbConfig> ctbShm(detectorIndex, -1, CtbConfig::shm_tag());
if (ctbShm.exists())
ctbShm.removeSharedMemory();
} }
using defs = slsDetectorDefs; using defs = slsDetectorDefs;
@ -2067,6 +2074,42 @@ void Detector::setLEDEnable(bool enable, Positions pos) {
pimpl->Parallel(&Module::setLEDEnable, pos, enable); pimpl->Parallel(&Module::setLEDEnable, pos, enable);
} }
void Detector::setDacNames(const std::vector<std::string> names) {
if (getDetectorType().squash() != defs::CHIPTESTBOARD)
throw RuntimeError("Named dacs only for CTB");
pimpl->setCtbDacNames(names);
}
std::vector<std::string> Detector::getDacNames() const {
std::vector<std::string> names;
auto type = getDetectorType().squash();
if (type == defs::CHIPTESTBOARD)
return pimpl->getCtbDacNames();
for (const auto &index : getDacList())
names.push_back(ToString(index));
return names;
}
defs::dacIndex Detector::getDacIndex(const std::string &name) {
auto type = getDetectorType().squash();
if (type == defs::CHIPTESTBOARD) {
auto names = getDacNames();
auto it = std::find(names.begin(), names.end(), name);
if (it == names.end())
throw RuntimeError("Dacname not found");
return static_cast<defs::dacIndex>(it - names.begin());
}
return StringTo<defs::dacIndex>(name);
}
std::string Detector::getDacName(defs::dacIndex i) {
auto type = getDetectorType().squash();
if (type == defs::CHIPTESTBOARD)
return pimpl->getCtbDacName(i);
return ToString(i);
}
// Pattern // Pattern
void Detector::setPattern(const std::string &fname, Positions pos) { void Detector::setPattern(const std::string &fname, Positions pos) {

View File

@ -32,7 +32,8 @@
namespace sls { namespace sls {
DetectorImpl::DetectorImpl(int detector_index, bool verify, bool update) DetectorImpl::DetectorImpl(int detector_index, bool verify, bool update)
: detectorIndex(detector_index), shm(detector_index, -1) { : detectorIndex(detector_index), shm(detector_index, -1),
ctb_shm(detector_index, -1, CtbConfig::shm_tag()) {
setupDetector(verify, update); setupDetector(verify, update);
} }
@ -44,6 +45,9 @@ void DetectorImpl::setupDetector(bool verify, bool update) {
if (update) { if (update) {
updateUserdetails(); updateUserdetails();
} }
if (ctb_shm.exists())
ctb_shm.openSharedMemory();
} }
void DetectorImpl::setAcquiringFlag(bool flag) { shm()->acquiringFlag = flag; } void DetectorImpl::setAcquiringFlag(bool flag) { shm()->acquiringFlag = flag; }
@ -54,8 +58,8 @@ void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) {
// single // single
if (detPos >= 0) { if (detPos >= 0) {
SharedMemory<sharedModule> moduleShm(detectorIndex, detPos); SharedMemory<sharedModule> moduleShm(detectorIndex, detPos);
if (moduleShm.IsExisting()) { if (moduleShm.exists()) {
moduleShm.RemoveSharedMemory(); moduleShm.removeSharedMemory();
} }
return; return;
} }
@ -64,16 +68,20 @@ void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) {
SharedMemory<sharedDetector> detectorShm(detectorIndex, -1); SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
int numModules = 0; int numModules = 0;
if (detectorShm.IsExisting()) { if (detectorShm.exists()) {
detectorShm.OpenSharedMemory(); detectorShm.openSharedMemory();
numModules = detectorShm()->numberOfModules; numModules = detectorShm()->numberOfModules;
detectorShm.RemoveSharedMemory(); detectorShm.removeSharedMemory();
} }
for (int i = 0; i < numModules; ++i) { for (int i = 0; i < numModules; ++i) {
SharedMemory<sharedModule> moduleShm(detectorIndex, i); SharedMemory<sharedModule> moduleShm(detectorIndex, i);
moduleShm.RemoveSharedMemory(); moduleShm.removeSharedMemory();
} }
SharedMemory<CtbConfig> ctbShm(detectorIndex, -1, CtbConfig::shm_tag());
if (ctbShm.exists())
ctbShm.removeSharedMemory();
} }
void DetectorImpl::freeSharedMemory() { void DetectorImpl::freeSharedMemory() {
@ -84,8 +92,11 @@ void DetectorImpl::freeSharedMemory() {
modules.clear(); modules.clear();
// clear detector shm // clear detector shm
shm.RemoveSharedMemory(); shm.removeSharedMemory();
client_downstream = false; client_downstream = false;
if (ctb_shm.exists())
ctb_shm.removeSharedMemory();
} }
std::string DetectorImpl::getUserDetails() { std::string DetectorImpl::getUserDetails() {
@ -129,11 +140,11 @@ void DetectorImpl::setInitialChecks(const bool value) {
} }
void DetectorImpl::initSharedMemory(bool verify) { void DetectorImpl::initSharedMemory(bool verify) {
if (!shm.IsExisting()) { if (!shm.exists()) {
shm.CreateSharedMemory(); shm.createSharedMemory();
initializeDetectorStructure(); initializeDetectorStructure();
} else { } else {
shm.OpenSharedMemory(); shm.openSharedMemory();
if (verify && shm()->shmversion != DETECTOR_SHMVERSION) { if (verify && shm()->shmversion != DETECTOR_SHMVERSION) {
LOG(logERROR) << "Detector shared memory (" << detectorIndex LOG(logERROR) << "Detector shared memory (" << detectorIndex
<< ") version mismatch " << ") version mismatch "
@ -144,6 +155,8 @@ void DetectorImpl::initSharedMemory(bool verify) {
throw SharedMemoryError("Shared memory version mismatch!"); throw SharedMemoryError("Shared memory version mismatch!");
} }
} }
// std::cout <<
} }
void DetectorImpl::initializeDetectorStructure() { void DetectorImpl::initializeDetectorStructure() {
@ -245,6 +258,16 @@ void DetectorImpl::setHostname(const std::vector<std::string> &name) {
addModule(hostname); addModule(hostname);
} }
updateDetectorSize(); updateDetectorSize();
// Here we know the detector type and can add ctb shared memory
// if needed, CTB dac names are only on detector level
if (shm()->detType == defs::CHIPTESTBOARD) {
if (ctb_shm.exists())
ctb_shm.openSharedMemory();
else
ctb_shm.createSharedMemory();
}
} }
void DetectorImpl::addModule(const std::string &hostname) { void DetectorImpl::addModule(const std::string &hostname) {
@ -1379,4 +1402,16 @@ void DetectorImpl::setDefaultDac(defs::dacIndex index, int defaultValue,
Parallel(&Module::setDefaultDac, pos, index, defaultValue, sett); Parallel(&Module::setDefaultDac, pos, index, defaultValue, sett);
} }
std::vector<std::string> DetectorImpl::getCtbDacNames() const {
return ctb_shm()->getDacNames();
}
void DetectorImpl::setCtbDacNames(const std::vector<std::string> &names) {
ctb_shm()->setDacNames(names);
}
std::string DetectorImpl::getCtbDacName(defs::dacIndex i) const {
return ctb_shm()->getDacName(static_cast<int>(i));
}
} // namespace sls } // namespace sls

View File

@ -7,6 +7,8 @@
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#include "CtbConfig.h"
class ZmqSocket; class ZmqSocket;
class detectorData; class detectorData;
@ -298,6 +300,11 @@ class DetectorImpl : public virtual slsDetectorDefs {
void setDefaultDac(defs::dacIndex index, int defaultValue, void setDefaultDac(defs::dacIndex index, int defaultValue,
defs::detectorSettings sett, Positions pos); defs::detectorSettings sett, Positions pos);
std::vector<std::string> getCtbDacNames() const;
std::string getCtbDacName(defs::dacIndex i) const;
void setCtbDacNames(const std::vector<std::string>& names);
private: private:
/** /**
* Creates/open shared memory, initializes detector structure and members * Creates/open shared memory, initializes detector structure and members
@ -381,6 +388,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
const int detectorIndex{0}; const int detectorIndex{0};
sls::SharedMemory<sharedDetector> shm{0, -1}; sls::SharedMemory<sharedDetector> shm{0, -1};
sls::SharedMemory<CtbConfig> ctb_shm{0, -1, CtbConfig::shm_tag()};
std::vector<std::unique_ptr<sls::Module>> modules; std::vector<std::unique_ptr<sls::Module>> modules;
/** data streaming (down stream) enabled in client (zmq sckets created) */ /** data streaming (down stream) enabled in client (zmq sckets created) */

View File

@ -33,11 +33,11 @@ Module::Module(detectorType type, int det_id, int module_index, bool verify)
: moduleIndex(module_index), shm(det_id, module_index) { : moduleIndex(module_index), shm(det_id, module_index) {
// ensure shared memory was not created before // ensure shared memory was not created before
if (shm.IsExisting()) { if (shm.exists()) {
LOG(logWARNING) << "This shared memory should have been " LOG(logWARNING) << "This shared memory should have been "
"deleted before! " "deleted before! "
<< shm.GetName() << ". Freeing it again"; << shm.getName() << ". Freeing it again";
shm.RemoveSharedMemory(); shm.removeSharedMemory();
} }
initSharedMemory(type, det_id, verify); initSharedMemory(type, det_id, verify);
@ -55,8 +55,8 @@ Module::Module(int det_id, int module_index, bool verify)
Module::~Module() = default; Module::~Module() = default;
void Module::freeSharedMemory() { void Module::freeSharedMemory() {
if (shm.IsExisting()) { if (shm.exists()) {
shm.RemoveSharedMemory(); shm.removeSharedMemory();
} }
} }
@ -3171,20 +3171,20 @@ Ret Module::sendToReceiver(int fnum, const Arg &args) {
slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id, slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id,
bool verify) { bool verify) {
if (!shm.IsExisting()) { if (!shm.exists()) {
throw SharedMemoryError("Shared memory " + shm.GetName() + throw SharedMemoryError("Shared memory " + shm.getName() +
"does not exist.\n Corrupted Multi Shared " "does not exist.\n Corrupted Multi Shared "
"memory. Please free shared memory."); "memory. Please free shared memory.");
} }
shm.OpenSharedMemory(); shm.openSharedMemory();
if (verify && shm()->shmversion != MODULE_SHMVERSION) { if (verify && shm()->shmversion != MODULE_SHMVERSION) {
std::ostringstream ss; std::ostringstream ss;
ss << "Single shared memory (" << det_id << "-" << moduleIndex ss << "Single shared memory (" << det_id << "-" << moduleIndex
<< ":)version mismatch (expected 0x" << std::hex << MODULE_SHMVERSION << ":)version mismatch (expected 0x" << std::hex << MODULE_SHMVERSION
<< " but got 0x" << shm()->shmversion << ")" << std::dec << " but got 0x" << shm()->shmversion << ")" << std::dec
<< ". Clear Shared memory to continue."; << ". Clear Shared memory to continue.";
shm.UnmapSharedMemory(); shm.unmapSharedMemory();
throw SharedMemoryError(ss.str()); throw SharedMemoryError(ss.str());
} }
return shm()->detType; return shm()->detType;
@ -3192,11 +3192,11 @@ slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id,
void Module::initSharedMemory(detectorType type, int det_id, bool verify) { void Module::initSharedMemory(detectorType type, int det_id, bool verify) {
shm = SharedMemory<sharedModule>(det_id, moduleIndex); shm = SharedMemory<sharedModule>(det_id, moduleIndex);
if (!shm.IsExisting()) { if (!shm.exists()) {
shm.CreateSharedMemory(); shm.createSharedMemory();
initializeModuleStructure(type); initializeModuleStructure(type);
} else { } else {
shm.OpenSharedMemory(); shm.openSharedMemory();
if (verify && shm()->shmversion != MODULE_SHMVERSION) { if (verify && shm()->shmversion != MODULE_SHMVERSION) {
std::ostringstream ss; std::ostringstream ss;
ss << "Single shared memory (" << det_id << "-" << moduleIndex ss << "Single shared memory (" << det_id << "-" << moduleIndex

View File

@ -13,13 +13,13 @@
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_exceptions.h" #include "sls/sls_detector_exceptions.h"
#include "stdlib.h" // #include "stdlib.h"
#include <cstdlib>
#include <cerrno> // errno #include <cerrno> // errno
#include <cstring> // strerror #include <cstring> // strerror
#include <fcntl.h> // O_CREAT, O_TRUNC.. #include <fcntl.h> // O_CREAT, O_TRUNC..
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
// #include <stdio.h> // printf
#include <sys/mman.h> // shared memory #include <sys/mman.h> // shared memory
#include <sys/stat.h> // fstat #include <sys/stat.h> // fstat
#include <unistd.h> #include <unistd.h>
@ -34,275 +34,178 @@
namespace sls { namespace sls {
template <typename T> class SharedMemory { template <typename T> class SharedMemory {
static constexpr int NAME_MAX_LENGTH = 255;
std::string name;
T *shared_struct{};
public: public:
/** // moduleid of -1 creates a detector only shared memory
* moduleid of -1 creates a detector only shared memory SharedMemory(int detectorId, int moduleIndex, const std::string &tag = "") {
*/ name = constructSharedMemoryName(detectorId, moduleIndex, tag);
SharedMemory(int detectorId, int moduleIndex) {
name = ConstructSharedMemoryName(detectorId, moduleIndex);
} }
/** // Disable copy, since we refer to a unique location
* Delete the copy constructor and copy assignment since we don't want two
* objects managing the same resource
*/
SharedMemory(const SharedMemory &) = delete; SharedMemory(const SharedMemory &) = delete;
SharedMemory &operator=(const SharedMemory &other) = delete; SharedMemory &operator=(const SharedMemory &other) = delete;
// Move constructor
SharedMemory(SharedMemory &&other) SharedMemory(SharedMemory &&other)
: name(other.name), fd(other.fd), shmSize(other.shmSize), : name(other.name), shared_struct(other.shared_struct) {
shared_struct(other.shared_struct) {
other.fd = -1;
other.shared_struct = nullptr; other.shared_struct = nullptr;
other.shmSize = 0;
} }
// Move assignment
SharedMemory &operator=(SharedMemory &&other) { SharedMemory &operator=(SharedMemory &&other) {
name = other.name; name = other.name;
if (fd) { if (shared_struct != nullptr)
close(fd); unmapSharedMemory();
}
fd = other.fd;
other.fd = -1;
if (shared_struct != nullptr) {
UnmapSharedMemory();
}
shared_struct = other.shared_struct; shared_struct = other.shared_struct;
other.shared_struct = nullptr; other.shared_struct = nullptr;
shmSize = other.shmSize;
other.shmSize = 0;
return *this; return *this;
} }
~SharedMemory() { ~SharedMemory() {
if (fd >= 0) if (shared_struct)
close(fd); unmapSharedMemory();
if (shared_struct) {
UnmapSharedMemory();
}
} }
/** T *operator()() { return shared_struct; }
* Verify if it exists const T *operator()() const { return shared_struct; }
* @return true if exists, else false std::string getName() const { return name; }
*/
bool IsExisting() { bool exists() {
bool ret = true;
int tempfd = shm_open(name.c_str(), O_RDWR, 0); int tempfd = shm_open(name.c_str(), O_RDWR, 0);
if ((tempfd < 0) && (errno == ENOENT)) { if ((tempfd < 0) && (errno == ENOENT)) {
ret = false; return false;
} }
close(tempfd); close(tempfd);
return ret; return true;
} }
/** void createSharedMemory() {
* Get shared memory name int fd = shm_open(name.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_RDWR,
*/
std::string GetName() const { return name; }
size_t size() const { return shmSize; }
/**
* Create Shared memory and call MapSharedMemory to map it to an address
* throws a SharedMemoryError exception on failure to create, ftruncate or
* map
*/
void CreateSharedMemory() {
fd = shm_open(name.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_RDWR,
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
if (fd < 0) { if (fd < 0) {
std::string msg = std::string msg =
"Create shared memory " + name + " failed: " + strerror(errno); "Create shared memory " + name + " failed: " + strerror(errno);
LOG(logERROR) << msg;
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
if (ftruncate(fd, sizeof(T)) < 0) { if (ftruncate(fd, sizeof(T)) < 0) {
std::string msg = "Create shared memory " + name + std::string msg = "Create shared memory " + name +
" failed at ftruncate: " + strerror(errno); " failed at ftruncate: " + strerror(errno);
LOG(logERROR) << msg;
close(fd); close(fd);
RemoveSharedMemory(); removeSharedMemory();
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
shared_struct = mapSharedMemory(fd);
shared_struct = MapSharedMemory(); new (shared_struct) T{};
LOG(logINFO) << "Shared memory created " << name; LOG(logINFO) << "Shared memory created " << name;
} }
/** void openSharedMemory() {
* Open existing Shared memory and call MapSharedMemory to map it to an int fd = shm_open(name.c_str(), O_RDWR, 0);
* address throws a SharedMemoryError exception on failure to open or map
*/
void OpenSharedMemory() {
fd = shm_open(name.c_str(), O_RDWR, 0);
if (fd < 0) { if (fd < 0) {
std::string msg = "Open existing shared memory " + name + std::string msg = "Open existing shared memory " + name +
" failed: " + strerror(errno); " failed: " + strerror(errno);
LOG(logERROR) << msg;
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
checkSize(fd);
shared_struct = MapSharedMemory(); shared_struct = mapSharedMemory(fd);
} }
/** void unmapSharedMemory() {
* Unmap shared memory from an address
* throws a SharedMemoryError exception on failure
*/
void UnmapSharedMemory() {
if (shared_struct != nullptr) { if (shared_struct != nullptr) {
if (munmap(shared_struct, shmSize) < 0) { if (munmap(shared_struct, sizeof(T)) < 0) {
std::string msg = "Unmapping shared memory " + name + std::string msg = "Unmapping shared memory " + name +
" failed: " + strerror(errno); " failed: " + strerror(errno);
LOG(logERROR) << msg;
close(fd);
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
shared_struct = nullptr; shared_struct = nullptr;
} }
} }
/** void removeSharedMemory() {
* Remove existing Shared memory unmapSharedMemory();
*/
void RemoveSharedMemory() {
UnmapSharedMemory();
if (shm_unlink(name.c_str()) < 0) { if (shm_unlink(name.c_str()) < 0) {
// silent exit if shm did not exist anyway // silent exit if shm did not exist anyway
if (errno == ENOENT) if (errno == ENOENT)
return; return;
std::string msg = std::string msg =
"Free Shared Memory " + name + " Failed: " + strerror(errno); "Free Shared Memory " + name + " Failed: " + strerror(errno);
LOG(logERROR) << msg;
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
LOG(logINFO) << "Shared memory deleted " << name; LOG(logINFO) << "Shared memory deleted " << name;
} }
/**
* Maximum length of name as from man pages
*/
static const int NAME_MAX_LENGTH = 255;
/**
*Using the call operator to access the pointer
*/
T *operator()() { return shared_struct; }
/**
*Using the call operator to access the pointer, const overload
*/
const T *operator()() const { return shared_struct; }
private: private:
/** std::string constructSharedMemoryName(int detectorId, int moduleIndex,
* Create Shared memory name const std::string &tag) {
* throws exception if name created is longer than required 255(manpages)
* @param detectorId detector id
* @param moduleIndex module id, -1 if a detector shared memory
* @returns shared memory name
*/
std::string ConstructSharedMemoryName(int detectorId, int moduleIndex) {
// using environment path // using environment variable
std::string sEnvPath; std::string slsdetname;
char *envpath = getenv(SHM_ENV_NAME); char *envpath = getenv(SHM_ENV_NAME);
if (envpath != nullptr) { if (envpath != nullptr) {
sEnvPath.assign(envpath); slsdetname = envpath;
sEnvPath.insert(0, "_"); slsdetname.insert(0, "_");
} }
std::stringstream ss; std::stringstream ss;
if (moduleIndex < 0) if (moduleIndex < 0) {
ss << SHM_DETECTOR_PREFIX << detectorId << sEnvPath; ss << SHM_DETECTOR_PREFIX << detectorId << slsdetname;
else if (!tag.empty())
ss << "_" << tag;
} else {
ss << SHM_DETECTOR_PREFIX << detectorId << SHM_MODULE_PREFIX ss << SHM_DETECTOR_PREFIX << detectorId << SHM_MODULE_PREFIX
<< moduleIndex << sEnvPath; << moduleIndex << slsdetname;
}
std::string temp = ss.str(); std::string shm_name = ss.str();
if (temp.length() > NAME_MAX_LENGTH) { if (shm_name.length() > NAME_MAX_LENGTH) {
std::string msg = std::string msg =
"Shared memory initialization failed. " + temp + " has " + "Shared memory initialization failed. " + shm_name + " has " +
std::to_string(temp.length()) + " characters. \n" + std::to_string(shm_name.length()) + " characters. \n" +
"Maximum is " + std::to_string(NAME_MAX_LENGTH) + "Maximum is " + std::to_string(NAME_MAX_LENGTH) +
". Change the environment variable " + SHM_ENV_NAME; ". Change the environment variable " + SHM_ENV_NAME;
LOG(logERROR) << msg;
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
return temp; return shm_name;
} }
/** // from the Linux manual:
* Map shared memory to an address // After the mmap() call has returned, the file descriptor, fd, can
* throws a SharedMemoryException exception on failure // be closed immediately without invalidating the mapping.
*/ T *mapSharedMemory(int fd) {
T *MapSharedMemory() {
void *addr = void *addr =
mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (addr == MAP_FAILED) { if (addr == MAP_FAILED) {
std::string msg = std::string msg =
"Mapping shared memory " + name + " failed: " + strerror(errno); "Mapping shared memory " + name + " failed: " + strerror(errno);
LOG(logERROR) << msg;
close(fd);
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
shmSize = sizeof(T); return static_cast<T *>(addr);
close(fd);
return (T *)addr;
} }
/** void checkSize(int fd) {
* Verify if existing shared memory size matches expected size
* @param expectedSize expected size of shared memory, replaced with smaller
* size if size does not match
* @return 0 for success, 1 for fail
*/
int VerifySizeMatch(size_t expectedSize) {
struct stat sb; struct stat sb;
// could not fstat
if (fstat(fd, &sb) < 0) { if (fstat(fd, &sb) < 0) {
std::string msg = "Could not verify existing shared memory " + std::string msg = "Could not verify existing shared memory " +
name + " size match " + name + " size match " +
"(could not fstat): " + strerror(errno); "(could not fstat): " + strerror(errno);
LOG(logERROR) << msg;
close(fd); close(fd);
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
// size does not match auto actual_size = static_cast<size_t>(sb.st_size);
auto sz = static_cast<size_t>(sb.st_size); auto expected_size = sizeof(T);
if (sz != expectedSize) { if (actual_size != expected_size) {
std::string msg = "Existing shared memory " + name + std::string msg =
" size does not match" + "Expected " + "Existing shared memory " + name + " size does not match. " +
std::to_string(expectedSize) + ", found " + "Expected " + std::to_string(expected_size) + ", found " +
std::to_string(sz); std::to_string(actual_size) +
LOG(logERROR) << msg; ". Detector software mismatch? Try freeing shared memory.";
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
return 1;
} }
return 0;
} }
/** Shared memory name */
std::string name;
/** File descriptor */
int fd{-1};
/** shm size */
size_t shmSize{0};
T *shared_struct{nullptr};
}; };
} // namespace sls } // namespace sls

View File

@ -18,6 +18,7 @@ target_sources(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Module.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Pattern.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Pattern.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-CtbConfig.cpp
) )
target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>") target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>")

View File

@ -590,13 +590,13 @@ TEST_CASE("master", "[.cmd]") {
} }
{ {
std::ostringstream oss1; std::ostringstream oss1;
proxy.Call("master", {"0"}, 0, PUT, oss3); proxy.Call("master", {"0"}, 0, PUT, oss1);
REQUIRE(oss3.str() == "master 0\n"); REQUIRE(oss1.str() == "master 0\n");
} }
{ {
std::ostringstream oss1; std::ostringstream oss1;
proxy.Call("master", {"1"}, 0, PUT, oss3); proxy.Call("master", {"1"}, 0, PUT, oss1);
REQUIRE(oss3.str() == "master 1\n"); REQUIRE(oss1.str() == "master 1\n");
} }
REQUIRE_THROWS(proxy.Call("master", {"1"}, -1, PUT)); REQUIRE_THROWS(proxy.Call("master", {"1"}, -1, PUT));
// set all to slaves, and then master // set all to slaves, and then master

View File

@ -0,0 +1,59 @@
#include "catch.hpp"
#include <string>
#include <stdlib.h>
#include "SharedMemory.h"
#include "CtbConfig.h"
using namespace sls;
#include <fstream>
TEST_CASE("Default construction"){
static_assert(sizeof(CtbConfig) == 360); // 18*20
CtbConfig c;
auto names = c.getDacNames();
REQUIRE(names.size() == 18);
REQUIRE(names[0] == "dac0");
REQUIRE(names[1] == "dac1");
REQUIRE(names[2] == "dac2");
REQUIRE(names[3] == "dac3");
}
TEST_CASE("Set and get a single dac name"){
CtbConfig c;
c.setDacName(3, "vrf");
auto names = c.getDacNames();
REQUIRE(c.getDacName(3) == "vrf");
REQUIRE(names[3] == "vrf");
}
TEST_CASE("Set a name that is too large throws"){
CtbConfig c;
REQUIRE_THROWS(c.setDacName(3, "somestringthatisreallytolongforadatac"));
}
TEST_CASE("Length of dac name cannot be 0"){
CtbConfig c;
REQUIRE_THROWS(c.setDacName(1, ""));
}
TEST_CASE("Copy a CTB config"){
CtbConfig c1;
c1.setDacName(5, "somename");
auto c2 = c1;
//change the name on the first object
//to detecto shallow copy
c1.setDacName(5, "someothername");
REQUIRE(c2.getDacName(5) == "somename");
}
TEST_CASE("Move CtbConfig "){
CtbConfig c1;
c1.setDacName(3, "yetanothername");
CtbConfig c2(std::move(c1));
REQUIRE(c2.getDacName(3) == "yetanothername");
}

View File

@ -32,8 +32,8 @@ TEST_CASE("Is shm fixed pattern shm compatible") {
// Set shm version to 0 // Set shm version to 0
sls::SharedMemory<sls::sharedModule> shm(0, 0); sls::SharedMemory<sls::sharedModule> shm(0, 0);
REQUIRE(shm.IsExisting() == true); REQUIRE(shm.exists() == true);
shm.OpenSharedMemory(); shm.openSharedMemory();
shm()->shmversion = 0; shm()->shmversion = 0;
// Should fail since version is set to 0 // Should fail since version is set to 0

View File

@ -20,8 +20,8 @@ constexpr int shm_id = 10;
TEST_CASE("Create SharedMemory read and write", "[detector]") { TEST_CASE("Create SharedMemory read and write", "[detector]") {
SharedMemory<Data> shm(shm_id, -1); SharedMemory<Data> shm(shm_id, -1);
shm.CreateSharedMemory(); shm.createSharedMemory();
CHECK(shm.GetName() == std::string("/slsDetectorPackage_detector_") + CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
std::to_string(shm_id)); std::to_string(shm_id));
shm()->x = 3; shm()->x = 3;
@ -32,25 +32,25 @@ TEST_CASE("Create SharedMemory read and write", "[detector]") {
CHECK(shm()->y == 5.7); CHECK(shm()->y == 5.7);
CHECK(std::string(shm()->mess) == "Some string"); CHECK(std::string(shm()->mess) == "Some string");
shm.UnmapSharedMemory(); shm.unmapSharedMemory();
shm.RemoveSharedMemory(); shm.removeSharedMemory();
CHECK(shm.IsExisting() == false); CHECK(shm.exists() == false);
} }
TEST_CASE("Open existing SharedMemory and read", "[detector]") { TEST_CASE("Open existing SharedMemory and read", "[detector]") {
{ {
SharedMemory<double> shm(shm_id, -1); SharedMemory<double> shm(shm_id, -1);
shm.CreateSharedMemory(); shm.createSharedMemory();
*shm() = 5.3; *shm() = 5.3;
} }
SharedMemory<double> shm2(shm_id, -1); SharedMemory<double> shm2(shm_id, -1);
shm2.OpenSharedMemory(); shm2.openSharedMemory();
CHECK(*shm2() == 5.3); CHECK(*shm2() == 5.3);
shm2.RemoveSharedMemory(); shm2.removeSharedMemory();
} }
TEST_CASE("Creating a second shared memory with the same name throws", TEST_CASE("Creating a second shared memory with the same name throws",
@ -59,24 +59,24 @@ TEST_CASE("Creating a second shared memory with the same name throws",
SharedMemory<double> shm0(shm_id, -1); SharedMemory<double> shm0(shm_id, -1);
SharedMemory<double> shm1(shm_id, -1); SharedMemory<double> shm1(shm_id, -1);
shm0.CreateSharedMemory(); shm0.createSharedMemory();
CHECK_THROWS(shm1.CreateSharedMemory()); CHECK_THROWS(shm1.createSharedMemory());
shm0.RemoveSharedMemory(); shm0.removeSharedMemory();
} }
TEST_CASE("Open two shared memories to the same place", "[detector]") { TEST_CASE("Open two shared memories to the same place", "[detector]") {
// Create the first shared memory // Create the first shared memory
SharedMemory<Data> shm(shm_id, -1); SharedMemory<Data> shm(shm_id, -1);
shm.CreateSharedMemory(); shm.createSharedMemory();
shm()->x = 5; shm()->x = 5;
CHECK(shm()->x == 5); CHECK(shm()->x == 5);
// Open the second shared memory with the same name // Open the second shared memory with the same name
SharedMemory<Data> shm2(shm_id, -1); SharedMemory<Data> shm2(shm_id, -1);
shm2.OpenSharedMemory(); shm2.openSharedMemory();
CHECK(shm2()->x == 5); CHECK(shm2()->x == 5);
CHECK(shm.GetName() == shm2.GetName()); CHECK(shm.getName() == shm2.getName());
// Check that they still point to the same place // Check that they still point to the same place
shm2()->x = 7; shm2()->x = 7;
@ -84,31 +84,28 @@ TEST_CASE("Open two shared memories to the same place", "[detector]") {
// Remove only needs to be done once since they refer // Remove only needs to be done once since they refer
// to the same memory // to the same memory
shm2.RemoveSharedMemory(); shm2.removeSharedMemory();
CHECK(shm.IsExisting() == false); CHECK(shm.exists() == false);
CHECK(shm2.IsExisting() == false); CHECK(shm2.exists() == false);
} }
TEST_CASE("Move SharedMemory", "[detector]") { TEST_CASE("Move SharedMemory", "[detector]") {
SharedMemory<Data> shm(shm_id, -1); SharedMemory<Data> shm(shm_id, -1);
CHECK(shm.GetName() == std::string("/slsDetectorPackage_detector_") + CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
std::to_string(shm_id)); std::to_string(shm_id));
shm.CreateSharedMemory(); shm.createSharedMemory();
shm()->x = 9; shm()->x = 9;
CHECK(shm.size() == sizeof(Data));
SharedMemory<Data> shm2(shm_id + 1, -1); SharedMemory<Data> shm2(shm_id + 1, -1);
shm2 = std::move(shm); // shm is now a moved from object! shm2 = std::move(shm); // shm is now a moved from object!
CHECK(shm2()->x == 9); CHECK(shm2()->x == 9);
CHECK(shm() == nullptr); CHECK(shm() == nullptr);
CHECK(shm.size() == 0); CHECK(shm2.getName() == std::string("/slsDetectorPackage_detector_") +
CHECK(shm2.GetName() == std::string("/slsDetectorPackage_detector_") +
std::to_string(shm_id)); std::to_string(shm_id));
shm2.RemoveSharedMemory(); shm2.removeSharedMemory();
} }
TEST_CASE("Create several shared memories", "[detector]") { TEST_CASE("Create several shared memories", "[detector]") {
@ -117,20 +114,62 @@ TEST_CASE("Create several shared memories", "[detector]") {
v.reserve(N); v.reserve(N);
for (int i = 0; i != N; ++i) { for (int i = 0; i != N; ++i) {
v.emplace_back(shm_id + i, -1); v.emplace_back(shm_id + i, -1);
CHECK(v[i].IsExisting() == false); CHECK(v[i].exists() == false);
v[i].CreateSharedMemory(); v[i].createSharedMemory();
*v[i]() = i; *v[i]() = i;
CHECK(*v[i]() == i); CHECK(*v[i]() == i);
} }
for (int i = 0; i != N; ++i) { for (int i = 0; i != N; ++i) {
CHECK(*v[i]() == i); CHECK(*v[i]() == i);
CHECK(v[i].GetName() == std::string("/slsDetectorPackage_detector_") + CHECK(v[i].getName() == std::string("/slsDetectorPackage_detector_") +
std::to_string(i + shm_id)); std::to_string(i + shm_id));
} }
for (int i = 0; i != N; ++i) { for (int i = 0; i != N; ++i) {
v[i].RemoveSharedMemory(); v[i].removeSharedMemory();
CHECK(v[i].IsExisting() == false); CHECK(v[i].exists() == false);
} }
} }
TEST_CASE("Create create a shared memory with a tag"){
SharedMemory<int> shm(0, -1, "ctbdacs");
REQUIRE(shm.getName() == "/slsDetectorPackage_detector_0_ctbdacs");
}
TEST_CASE("Create create a shared memory with a tag when SLSDETNAME is set"){
// if SLSDETNAME is already set we unset it but
// save the value
std::string old_slsdetname;
if (getenv(SHM_ENV_NAME))
old_slsdetname = getenv(SHM_ENV_NAME);
unsetenv(SHM_ENV_NAME);
setenv(SHM_ENV_NAME, "myprefix", 1);
SharedMemory<int> shm(0, -1, "ctbdacs");
REQUIRE(shm.getName() == "/slsDetectorPackage_detector_0_myprefix_ctbdacs");
// Clean up after us
if (old_slsdetname.empty())
unsetenv(SHM_ENV_NAME);
else
setenv(SHM_ENV_NAME, old_slsdetname.c_str(), 1);
}
TEST_CASE("map int64 to int32 throws"){
SharedMemory<int32_t> shm(shm_id, -1);
shm.createSharedMemory();
*shm() = 7;
SharedMemory<int64_t> shm2(shm_id, -1);
REQUIRE_THROWS(shm2.openSharedMemory());
shm.removeSharedMemory();
}