diff --git a/RELEASE.txt b/RELEASE.txt index 5d1bbf6cf..7eff077d3 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -54,7 +54,7 @@ This document describes the differences between v7.0.0 and v6.x.x - added geometry to metadata - 10g eiger nextframenumber get fixed. - 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 - gotthard 25 um image reconstructed in gui and virtual hdf5 (firmware updated for slave to reverse channels) diff --git a/python/slsdet/ctb.py b/python/slsdet/ctb.py index 10afd3ae3..53ba8e8d7 100644 --- a/python/slsdet/ctb.py +++ b/python/slsdet/ctb.py @@ -1,43 +1,45 @@ # SPDX-License-Identifier: LGPL-3.0-or-other # 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 .dacs import DetectorDacs +from .dacs import DetectorDacs, NamedDacs import _slsdet dacIndex = _slsdet.slsDetectorDefs.dacIndex from .detector_property import DetectorProperty -class CtbDacs(DetectorDacs): - """ - Ctb dacs - """ - _dacs = [('dac0', dacIndex(0), 0, 4000, 1400), - ('dac1', dacIndex(1), 0, 4000, 1200), - ('dac2', dacIndex(2), 0, 4000, 900), - ('dac3', dacIndex(3), 0, 4000, 1050), - ('dac4', dacIndex(4), 0, 4000, 1400), - ('dac5', dacIndex(5), 0, 4000, 655), - ('dac6', dacIndex(6), 0, 4000, 2000), - ('dac7', dacIndex(7), 0, 4000, 1400), - ('dac8', dacIndex(8), 0, 4000, 850), - ('dac9', dacIndex(9), 0, 4000, 2000), - ('dac10', dacIndex(10), 0, 4000, 2294), - ('dac11', dacIndex(11), 0, 4000, 983), - ('dac12', dacIndex(12), 0, 4000, 1475), - ('dac13', dacIndex(13), 0, 4000, 1200), - ('dac14', dacIndex(14), 0, 4000, 1600), - ('dac15', dacIndex(15), 0, 4000, 1455), - ('dac16', dacIndex(16), 0, 4000, 0), - ('dac17', dacIndex(17), 0, 4000, 1000), - ] - _dacnames = [_d[0] for _d in _dacs] +# class CtbDacs(DetectorDacs): +# """ +# Ctb dacs +# """ +# _dacs = [('dac0', dacIndex(0), 0, 4000, 1400), +# ('dac1', dacIndex(1), 0, 4000, 1200), +# ('dac2', dacIndex(2), 0, 4000, 900), +# ('dac3', dacIndex(3), 0, 4000, 1050), +# ('dac4', dacIndex(4), 0, 4000, 1400), +# ('dac5', dacIndex(5), 0, 4000, 655), +# ('dac6', dacIndex(6), 0, 4000, 2000), +# ('dac7', dacIndex(7), 0, 4000, 1400), +# ('dac8', dacIndex(8), 0, 4000, 850), +# ('dac9', dacIndex(9), 0, 4000, 2000), +# ('dac10', dacIndex(10), 0, 4000, 2294), +# ('dac11', dacIndex(11), 0, 4000, 983), +# ('dac12', dacIndex(12), 0, 4000, 1475), +# ('dac13', dacIndex(13), 0, 4000, 1200), +# ('dac14', dacIndex(14), 0, 4000, 1600), +# ('dac15', dacIndex(15), 0, 4000, 1455), +# ('dac16', dacIndex(16), 0, 4000, 0), +# ('dac17', dacIndex(17), 0, 4000, 1000), +# ] +# _dacnames = [_d[0] for _d in _dacs] from .utils import element +@freeze class Ctb(Detector): def __init__(self, id = 0): super().__init__(id) self._frozen = False - self._dacs = CtbDacs(self) + # self._dacs = CtbDacs(self) + self._dacs = NamedDacs(self) @property def dacs(self): diff --git a/python/slsdet/dacs.py b/python/slsdet/dacs.py index 5628eb3a6..0321c24dc 100755 --- a/python/slsdet/dacs.py +++ b/python/slsdet/dacs.py @@ -36,6 +36,79 @@ class Dac(DetectorProperty): dacstr = ''.join([f'{item:5d}' for item in self.get()]) 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: _dacs = [] @@ -50,7 +123,7 @@ class DetectorDacs: # Index to support iteration self._current = 0 - # Populate the dacs + # Name the attributes? for _d in self._dacs: setattr(self, '_'+_d[0], Dac(*_d, detector)) @@ -59,7 +132,10 @@ class DetectorDacs: def __getattr__(self, name): return self.__getattribute__('_' + name) - + @property + def dacnames(self): + return [_d[0] for _d in _dacs] + def __setattr__(self, name, value): if name in self._dacnames: return self.__getattribute__('_' + name).__setitem__(slice(None, None, None), value) diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index d60dd05e8..d94d82995 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -1571,8 +1571,16 @@ class Detector(CppDetectorApi): @property 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 def dacvalues(self): diff --git a/python/src/detector.cpp b/python/src/detector.cpp index 024d08ddb..2323a0e1d 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -1427,6 +1427,19 @@ void init_det(py::module &m) { (void (Detector::*)(bool, sls::Positions)) & Detector::setLEDEnable, py::arg(), py::arg() = Positions{}) + .def("setDacNames", + (void (Detector::*)(const std::vector)) & + Detector::setDacNames, + py::arg()) + .def("getDacNames", (std::vector(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", (void (Detector::*)(const std::string &, sls::Positions)) & Detector::setPattern, diff --git a/slsDetectorSoftware/CMakeLists.txt b/slsDetectorSoftware/CMakeLists.txt index ce88e0ca8..33bfc8432 100755 --- a/slsDetectorSoftware/CMakeLists.txt +++ b/slsDetectorSoftware/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES src/CmdProxy.cpp src/CmdParser.cpp src/Pattern.cpp + src/CtbConfig.cpp ) add_library(slsDetectorObject OBJECT diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index e359d49a5..68ccbd2a9 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1613,6 +1613,14 @@ class Detector { /** [CTB] Default is enabled. */ void setLEDEnable(bool enable, Positions pos = {}); + + + void setDacNames(const std::vector names); + + std::vector getDacNames() const; + + defs::dacIndex getDacIndex(const std::string& name); + std::string getDacName(defs::dacIndex i); ///@} /** @name Pattern */ diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index ddd2e1d5f..dc61cc538 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -1056,11 +1056,10 @@ std::string CmdProxy::TemperatureValues(int action) { std::string CmdProxy::Dac(int action) { std::ostringstream os; os << cmd << ' '; - + auto type = det->getDetectorType().squash(); // dac indices only for ctb if (args.size() > 0 && action != defs::HELP_ACTION) { - if (is_int(args[0]) && - det->getDetectorType().squash() != defs::CHIPTESTBOARD) { + if (is_int(args[0]) && type != defs::CHIPTESTBOARD) { throw sls::RuntimeError( "Dac indices can only be used for chip test board. Use daclist " "to get list of dac names for current detector."); @@ -1077,7 +1076,14 @@ std::string CmdProxy::Dac(int action) { if (args.empty()) WrongNumberOfParameters(1); // This prints slightly wrong - defs::dacIndex dacIndex = StringTo(args[0]); + defs::dacIndex dacIndex{}; + //TODO! Remove if + if (type == defs::CHIPTESTBOARD && !is_int(args[0])) { + dacIndex = det->getDacIndex(args[0]); + } else { + dacIndex = StringTo(args[0]); + } + bool mV = false; if (args.size() == 2) { @@ -1095,7 +1101,11 @@ std::string CmdProxy::Dac(int action) { if (args.empty()) WrongNumberOfParameters(1); // This prints slightly wrong - defs::dacIndex dacIndex = StringTo(args[0]); + defs::dacIndex dacIndex{}; + if (type == defs::CHIPTESTBOARD && !is_int(args[0])) + dacIndex = det->getDacIndex(args[0]); + else + dacIndex = StringTo(args[0]); bool mV = false; if (args.size() == 3) { if ((args[2] != "mv") && (args[2] != "mV")) { @@ -1115,6 +1125,41 @@ std::string CmdProxy::Dac(int action) { 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::ostringstream os; os << cmd << ' '; @@ -1134,13 +1179,15 @@ std::string CmdProxy::DacValues(int action) { WrongNumberOfParameters(1); } auto t = det->getDacList(); + auto names = det->getDacNames(); + auto name_it = names.begin(); os << '['; auto it = t.cbegin(); - os << ToString(*it) << ' '; + os << ToString(*name_it++) << ' '; os << OutString(det->getDAC(*it++, mv, std::vector{det_id})) << (!args.empty() ? " mV" : ""); while (it != t.cend()) { - os << ", " << ToString(*it) << ' '; + os << ", " << ToString(*name_it++) << ' '; os << OutString(det->getDAC(*it++, mv, std::vector{det_id})) << (!args.empty() ? " mV" : ""); } diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index 0f8952c91..293bda371 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -837,7 +837,7 @@ class CmdProxy { /* dacs */ {"dac", &CmdProxy::Dac}, - {"daclist", &CmdProxy::daclist}, + {"daclist", &CmdProxy::DacList}, {"dacvalues", &CmdProxy::DacValues}, {"resetdacs", &CmdProxy::ResetDacs}, {"defaultdac", &CmdProxy::DefaultDac}, @@ -1124,6 +1124,7 @@ class CmdProxy { std::string TemperatureValues(int action); /* dacs */ std::string Dac(int action); + std::string DacList(int action); std::string DacValues(int action); std::string ResetDacs(int action); std::string DefaultDac(int action); @@ -1465,10 +1466,6 @@ class CmdProxy { /* dacs */ - GET_COMMAND_NOID( - daclist, getDacList, - "\n\tGets the list of commands for every dac for this detector."); - /* on chip dacs */ INTEGER_USER_IND_COMMAND( vchip_comp_fe, getOnChipDAC, setOnChipDAC, StringTo, diff --git a/slsDetectorSoftware/src/CtbConfig.cpp b/slsDetectorSoftware/src/CtbConfig.cpp new file mode 100644 index 000000000..d450ac5e6 --- /dev/null +++ b/slsDetectorSoftware/src/CtbConfig.cpp @@ -0,0 +1,72 @@ + +#include "CtbConfig.h" +#include "SharedMemory.h" +#include "sls/ToString.h" +#include "sls/string_utils.h" + +#include +#include +#include + +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& 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 CtbConfig::getDacNames() const { + std::vector 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 \ No newline at end of file diff --git a/slsDetectorSoftware/src/CtbConfig.h b/slsDetectorSoftware/src/CtbConfig.h new file mode 100644 index 000000000..6c17fadbf --- /dev/null +++ b/slsDetectorSoftware/src/CtbConfig.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +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 &names); + void setDacName(size_t index, const std::string &name); + std::string getDacName(size_t index) const; + std::vector getDacNames() const; + static const char* shm_tag(); +}; + + +} // namespace sls diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 98108cf43..31720a1ec 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -7,6 +7,7 @@ #include "CmdProxy.h" #include "DetectorImpl.h" #include "Module.h" +#include "CtbConfig.h" #include "sls/Pattern.h" #include "sls/container_utils.h" #include "sls/file_utils.h" @@ -21,11 +22,12 @@ namespace sls { void freeSharedMemory(int detectorIndex, int moduleIndex) { + // single module if (moduleIndex >= 0) { SharedMemory moduleShm(detectorIndex, moduleIndex); - if (moduleShm.IsExisting()) { - moduleShm.RemoveSharedMemory(); + if (moduleShm.exists()) { + moduleShm.removeSharedMemory(); } return; } @@ -34,16 +36,21 @@ void freeSharedMemory(int detectorIndex, int moduleIndex) { SharedMemory detectorShm(detectorIndex, -1); int numDetectors = 0; - if (detectorShm.IsExisting()) { - detectorShm.OpenSharedMemory(); + if (detectorShm.exists()) { + detectorShm.openSharedMemory(); numDetectors = detectorShm()->numberOfModules; - detectorShm.RemoveSharedMemory(); + detectorShm.removeSharedMemory(); } for (int i = 0; i < numDetectors; ++i) { SharedMemory moduleShm(detectorIndex, i); - moduleShm.RemoveSharedMemory(); + moduleShm.removeSharedMemory(); } + + // Ctb configuration + SharedMemory ctbShm(detectorIndex, -1, CtbConfig::shm_tag()); + if (ctbShm.exists()) + ctbShm.removeSharedMemory(); } using defs = slsDetectorDefs; @@ -2067,6 +2074,42 @@ void Detector::setLEDEnable(bool enable, Positions pos) { pimpl->Parallel(&Module::setLEDEnable, pos, enable); } +void Detector::setDacNames(const std::vector names) { + if (getDetectorType().squash() != defs::CHIPTESTBOARD) + throw RuntimeError("Named dacs only for CTB"); + pimpl->setCtbDacNames(names); +} + +std::vector Detector::getDacNames() const { + std::vector 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(it - names.begin()); + } + return StringTo(name); +} + +std::string Detector::getDacName(defs::dacIndex i) { + auto type = getDetectorType().squash(); + if (type == defs::CHIPTESTBOARD) + return pimpl->getCtbDacName(i); + return ToString(i); +} + // Pattern void Detector::setPattern(const std::string &fname, Positions pos) { diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index 6b5e84db7..de4b45609 100644 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -32,7 +32,8 @@ namespace sls { 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); } @@ -44,6 +45,9 @@ void DetectorImpl::setupDetector(bool verify, bool update) { if (update) { updateUserdetails(); } + + if (ctb_shm.exists()) + ctb_shm.openSharedMemory(); } void DetectorImpl::setAcquiringFlag(bool flag) { shm()->acquiringFlag = flag; } @@ -54,8 +58,8 @@ void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) { // single if (detPos >= 0) { SharedMemory moduleShm(detectorIndex, detPos); - if (moduleShm.IsExisting()) { - moduleShm.RemoveSharedMemory(); + if (moduleShm.exists()) { + moduleShm.removeSharedMemory(); } return; } @@ -64,16 +68,20 @@ void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) { SharedMemory detectorShm(detectorIndex, -1); int numModules = 0; - if (detectorShm.IsExisting()) { - detectorShm.OpenSharedMemory(); + if (detectorShm.exists()) { + detectorShm.openSharedMemory(); numModules = detectorShm()->numberOfModules; - detectorShm.RemoveSharedMemory(); + detectorShm.removeSharedMemory(); } for (int i = 0; i < numModules; ++i) { SharedMemory moduleShm(detectorIndex, i); - moduleShm.RemoveSharedMemory(); + moduleShm.removeSharedMemory(); } + + SharedMemory ctbShm(detectorIndex, -1, CtbConfig::shm_tag()); + if (ctbShm.exists()) + ctbShm.removeSharedMemory(); } void DetectorImpl::freeSharedMemory() { @@ -84,8 +92,11 @@ void DetectorImpl::freeSharedMemory() { modules.clear(); // clear detector shm - shm.RemoveSharedMemory(); + shm.removeSharedMemory(); client_downstream = false; + + if (ctb_shm.exists()) + ctb_shm.removeSharedMemory(); } std::string DetectorImpl::getUserDetails() { @@ -129,11 +140,11 @@ void DetectorImpl::setInitialChecks(const bool value) { } void DetectorImpl::initSharedMemory(bool verify) { - if (!shm.IsExisting()) { - shm.CreateSharedMemory(); + if (!shm.exists()) { + shm.createSharedMemory(); initializeDetectorStructure(); } else { - shm.OpenSharedMemory(); + shm.openSharedMemory(); if (verify && shm()->shmversion != DETECTOR_SHMVERSION) { LOG(logERROR) << "Detector shared memory (" << detectorIndex << ") version mismatch " @@ -144,6 +155,8 @@ void DetectorImpl::initSharedMemory(bool verify) { throw SharedMemoryError("Shared memory version mismatch!"); } } + + // std::cout << } void DetectorImpl::initializeDetectorStructure() { @@ -245,6 +258,16 @@ void DetectorImpl::setHostname(const std::vector &name) { addModule(hostname); } 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) { @@ -1379,4 +1402,16 @@ void DetectorImpl::setDefaultDac(defs::dacIndex index, int defaultValue, Parallel(&Module::setDefaultDac, pos, index, defaultValue, sett); } +std::vector DetectorImpl::getCtbDacNames() const { + return ctb_shm()->getDacNames(); +} + +void DetectorImpl::setCtbDacNames(const std::vector &names) { + ctb_shm()->setDacNames(names); +} + +std::string DetectorImpl::getCtbDacName(defs::dacIndex i) const { + return ctb_shm()->getDacName(static_cast(i)); +} + } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/DetectorImpl.h b/slsDetectorSoftware/src/DetectorImpl.h index e3b0ab985..af1ec71ac 100644 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -7,6 +7,8 @@ #include "sls/logger.h" #include "sls/sls_detector_defs.h" + +#include "CtbConfig.h" class ZmqSocket; class detectorData; @@ -298,6 +300,11 @@ class DetectorImpl : public virtual slsDetectorDefs { void setDefaultDac(defs::dacIndex index, int defaultValue, defs::detectorSettings sett, Positions pos); + + std::vector getCtbDacNames() const; + std::string getCtbDacName(defs::dacIndex i) const; + void setCtbDacNames(const std::vector& names); + private: /** * Creates/open shared memory, initializes detector structure and members @@ -381,6 +388,7 @@ class DetectorImpl : public virtual slsDetectorDefs { const int detectorIndex{0}; sls::SharedMemory shm{0, -1}; + sls::SharedMemory ctb_shm{0, -1, CtbConfig::shm_tag()}; std::vector> modules; /** data streaming (down stream) enabled in client (zmq sckets created) */ diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 5555ec71f..7178e75f1 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -33,11 +33,11 @@ Module::Module(detectorType type, int det_id, int module_index, bool verify) : moduleIndex(module_index), shm(det_id, module_index) { // ensure shared memory was not created before - if (shm.IsExisting()) { + if (shm.exists()) { LOG(logWARNING) << "This shared memory should have been " "deleted before! " - << shm.GetName() << ". Freeing it again"; - shm.RemoveSharedMemory(); + << shm.getName() << ". Freeing it again"; + shm.removeSharedMemory(); } initSharedMemory(type, det_id, verify); @@ -55,8 +55,8 @@ Module::Module(int det_id, int module_index, bool verify) Module::~Module() = default; void Module::freeSharedMemory() { - if (shm.IsExisting()) { - shm.RemoveSharedMemory(); + if (shm.exists()) { + shm.removeSharedMemory(); } } @@ -3171,20 +3171,20 @@ Ret Module::sendToReceiver(int fnum, const Arg &args) { slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id, bool verify) { - if (!shm.IsExisting()) { - throw SharedMemoryError("Shared memory " + shm.GetName() + + if (!shm.exists()) { + throw SharedMemoryError("Shared memory " + shm.getName() + "does not exist.\n Corrupted Multi Shared " "memory. Please free shared memory."); } - shm.OpenSharedMemory(); + shm.openSharedMemory(); if (verify && shm()->shmversion != MODULE_SHMVERSION) { std::ostringstream ss; ss << "Single shared memory (" << det_id << "-" << moduleIndex << ":)version mismatch (expected 0x" << std::hex << MODULE_SHMVERSION << " but got 0x" << shm()->shmversion << ")" << std::dec << ". Clear Shared memory to continue."; - shm.UnmapSharedMemory(); + shm.unmapSharedMemory(); throw SharedMemoryError(ss.str()); } return shm()->detType; @@ -3192,11 +3192,11 @@ slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id, void Module::initSharedMemory(detectorType type, int det_id, bool verify) { shm = SharedMemory(det_id, moduleIndex); - if (!shm.IsExisting()) { - shm.CreateSharedMemory(); + if (!shm.exists()) { + shm.createSharedMemory(); initializeModuleStructure(type); } else { - shm.OpenSharedMemory(); + shm.openSharedMemory(); if (verify && shm()->shmversion != MODULE_SHMVERSION) { std::ostringstream ss; ss << "Single shared memory (" << det_id << "-" << moduleIndex diff --git a/slsDetectorSoftware/src/SharedMemory.h b/slsDetectorSoftware/src/SharedMemory.h index e50662487..5693a541f 100644 --- a/slsDetectorSoftware/src/SharedMemory.h +++ b/slsDetectorSoftware/src/SharedMemory.h @@ -13,13 +13,13 @@ #include "sls/logger.h" #include "sls/sls_detector_exceptions.h" -#include "stdlib.h" +// #include "stdlib.h" +#include #include // errno #include // strerror #include // O_CREAT, O_TRUNC.. #include #include -// #include // printf #include // shared memory #include // fstat #include @@ -34,275 +34,178 @@ namespace sls { template class SharedMemory { + static constexpr int NAME_MAX_LENGTH = 255; + std::string name; + T *shared_struct{}; public: - /** - * moduleid of -1 creates a detector only shared memory - */ - SharedMemory(int detectorId, int moduleIndex) { - name = ConstructSharedMemoryName(detectorId, moduleIndex); + // moduleid of -1 creates a detector only shared memory + SharedMemory(int detectorId, int moduleIndex, const std::string &tag = "") { + name = constructSharedMemoryName(detectorId, moduleIndex, tag); } - /** - * Delete the copy constructor and copy assignment since we don't want two - * objects managing the same resource - */ + // Disable copy, since we refer to a unique location SharedMemory(const SharedMemory &) = delete; SharedMemory &operator=(const SharedMemory &other) = delete; - // Move constructor SharedMemory(SharedMemory &&other) - : name(other.name), fd(other.fd), shmSize(other.shmSize), - shared_struct(other.shared_struct) { - - other.fd = -1; + : name(other.name), shared_struct(other.shared_struct) { other.shared_struct = nullptr; - other.shmSize = 0; } - // Move assignment SharedMemory &operator=(SharedMemory &&other) { name = other.name; - if (fd) { - close(fd); - } - fd = other.fd; - other.fd = -1; - - if (shared_struct != nullptr) { - UnmapSharedMemory(); - } + if (shared_struct != nullptr) + unmapSharedMemory(); shared_struct = other.shared_struct; other.shared_struct = nullptr; - - shmSize = other.shmSize; - other.shmSize = 0; return *this; } ~SharedMemory() { - if (fd >= 0) - close(fd); - - if (shared_struct) { - UnmapSharedMemory(); - } + if (shared_struct) + unmapSharedMemory(); } - /** - * Verify if it exists - * @return true if exists, else false - */ - bool IsExisting() { - bool ret = true; + T *operator()() { return shared_struct; } + const T *operator()() const { return shared_struct; } + std::string getName() const { return name; } + + bool exists() { int tempfd = shm_open(name.c_str(), O_RDWR, 0); if ((tempfd < 0) && (errno == ENOENT)) { - ret = false; + return false; } close(tempfd); - return ret; + return true; } - /** - * Get shared memory name - */ - 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); + void createSharedMemory() { + int fd = shm_open(name.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_RDWR, + S_IRUSR | S_IWUSR); if (fd < 0) { std::string msg = "Create shared memory " + name + " failed: " + strerror(errno); - LOG(logERROR) << msg; throw SharedMemoryError(msg); } if (ftruncate(fd, sizeof(T)) < 0) { std::string msg = "Create shared memory " + name + " failed at ftruncate: " + strerror(errno); - LOG(logERROR) << msg; close(fd); - RemoveSharedMemory(); + removeSharedMemory(); throw SharedMemoryError(msg); } - - shared_struct = MapSharedMemory(); + shared_struct = mapSharedMemory(fd); + new (shared_struct) T{}; LOG(logINFO) << "Shared memory created " << name; } - /** - * Open existing Shared memory and call MapSharedMemory to map it to an - * address throws a SharedMemoryError exception on failure to open or map - */ - void OpenSharedMemory() { - fd = shm_open(name.c_str(), O_RDWR, 0); + void openSharedMemory() { + int fd = shm_open(name.c_str(), O_RDWR, 0); if (fd < 0) { std::string msg = "Open existing shared memory " + name + " failed: " + strerror(errno); - LOG(logERROR) << msg; throw SharedMemoryError(msg); } - - shared_struct = MapSharedMemory(); + checkSize(fd); + shared_struct = mapSharedMemory(fd); } - /** - * Unmap shared memory from an address - * throws a SharedMemoryError exception on failure - */ - void UnmapSharedMemory() { + void unmapSharedMemory() { if (shared_struct != nullptr) { - if (munmap(shared_struct, shmSize) < 0) { + if (munmap(shared_struct, sizeof(T)) < 0) { std::string msg = "Unmapping shared memory " + name + " failed: " + strerror(errno); - LOG(logERROR) << msg; - close(fd); throw SharedMemoryError(msg); } shared_struct = nullptr; } } - /** - * Remove existing Shared memory - */ - void RemoveSharedMemory() { - UnmapSharedMemory(); + void removeSharedMemory() { + unmapSharedMemory(); if (shm_unlink(name.c_str()) < 0) { // silent exit if shm did not exist anyway if (errno == ENOENT) return; std::string msg = "Free Shared Memory " + name + " Failed: " + strerror(errno); - LOG(logERROR) << msg; throw SharedMemoryError(msg); } 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: - /** - * Create Shared memory name - * 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) { + std::string constructSharedMemoryName(int detectorId, int moduleIndex, + const std::string &tag) { - // using environment path - std::string sEnvPath; + // using environment variable + std::string slsdetname; char *envpath = getenv(SHM_ENV_NAME); if (envpath != nullptr) { - sEnvPath.assign(envpath); - sEnvPath.insert(0, "_"); + slsdetname = envpath; + slsdetname.insert(0, "_"); } std::stringstream ss; - if (moduleIndex < 0) - ss << SHM_DETECTOR_PREFIX << detectorId << sEnvPath; - else + if (moduleIndex < 0) { + ss << SHM_DETECTOR_PREFIX << detectorId << slsdetname; + if (!tag.empty()) + ss << "_" << tag; + } else { ss << SHM_DETECTOR_PREFIX << detectorId << SHM_MODULE_PREFIX - << moduleIndex << sEnvPath; + << moduleIndex << slsdetname; + } - std::string temp = ss.str(); - if (temp.length() > NAME_MAX_LENGTH) { + std::string shm_name = ss.str(); + if (shm_name.length() > NAME_MAX_LENGTH) { std::string msg = - "Shared memory initialization failed. " + temp + " has " + - std::to_string(temp.length()) + " characters. \n" + + "Shared memory initialization failed. " + shm_name + " has " + + std::to_string(shm_name.length()) + " characters. \n" + "Maximum is " + std::to_string(NAME_MAX_LENGTH) + ". Change the environment variable " + SHM_ENV_NAME; - LOG(logERROR) << msg; throw SharedMemoryError(msg); } - return temp; + return shm_name; } - /** - * Map shared memory to an address - * throws a SharedMemoryException exception on failure - */ - - T *MapSharedMemory() { + // from the Linux manual: + // After the mmap() call has returned, the file descriptor, fd, can + // be closed immediately without invalidating the mapping. + T *mapSharedMemory(int fd) { void *addr = mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + close(fd); if (addr == MAP_FAILED) { std::string msg = "Mapping shared memory " + name + " failed: " + strerror(errno); - LOG(logERROR) << msg; - close(fd); throw SharedMemoryError(msg); } - shmSize = sizeof(T); - close(fd); - return (T *)addr; + return static_cast(addr); } - /** - * 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) { + void checkSize(int fd) { struct stat sb; - // could not fstat if (fstat(fd, &sb) < 0) { std::string msg = "Could not verify existing shared memory " + name + " size match " + "(could not fstat): " + strerror(errno); - LOG(logERROR) << msg; close(fd); throw SharedMemoryError(msg); } - // size does not match - auto sz = static_cast(sb.st_size); - if (sz != expectedSize) { - std::string msg = "Existing shared memory " + name + - " size does not match" + "Expected " + - std::to_string(expectedSize) + ", found " + - std::to_string(sz); - LOG(logERROR) << msg; + auto actual_size = static_cast(sb.st_size); + auto expected_size = sizeof(T); + if (actual_size != expected_size) { + std::string msg = + "Existing shared memory " + name + " size does not match. " + + "Expected " + std::to_string(expected_size) + ", found " + + std::to_string(actual_size) + + ". Detector software mismatch? Try freeing shared memory."; 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 diff --git a/slsDetectorSoftware/tests/CMakeLists.txt b/slsDetectorSoftware/tests/CMakeLists.txt index bc65a73e9..5a39e615e 100755 --- a/slsDetectorSoftware/tests/CMakeLists.txt +++ b/slsDetectorSoftware/tests/CMakeLists.txt @@ -18,6 +18,7 @@ target_sources(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Pattern.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test-CtbConfig.cpp ) target_include_directories(tests PUBLIC "$") \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index 06b95c48f..ff451bff5 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -590,13 +590,13 @@ TEST_CASE("master", "[.cmd]") { } { std::ostringstream oss1; - proxy.Call("master", {"0"}, 0, PUT, oss3); - REQUIRE(oss3.str() == "master 0\n"); + proxy.Call("master", {"0"}, 0, PUT, oss1); + REQUIRE(oss1.str() == "master 0\n"); } { std::ostringstream oss1; - proxy.Call("master", {"1"}, 0, PUT, oss3); - REQUIRE(oss3.str() == "master 1\n"); + proxy.Call("master", {"1"}, 0, PUT, oss1); + REQUIRE(oss1.str() == "master 1\n"); } REQUIRE_THROWS(proxy.Call("master", {"1"}, -1, PUT)); // set all to slaves, and then master diff --git a/slsDetectorSoftware/tests/test-CtbConfig.cpp b/slsDetectorSoftware/tests/test-CtbConfig.cpp new file mode 100644 index 000000000..15a22e852 --- /dev/null +++ b/slsDetectorSoftware/tests/test-CtbConfig.cpp @@ -0,0 +1,59 @@ +#include "catch.hpp" +#include + +#include + +#include "SharedMemory.h" +#include "CtbConfig.h" +using namespace sls; +#include + + +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"); +} \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-Module.cpp b/slsDetectorSoftware/tests/test-Module.cpp index 667aea4e9..52805939b 100644 --- a/slsDetectorSoftware/tests/test-Module.cpp +++ b/slsDetectorSoftware/tests/test-Module.cpp @@ -32,8 +32,8 @@ TEST_CASE("Is shm fixed pattern shm compatible") { // Set shm version to 0 sls::SharedMemory shm(0, 0); - REQUIRE(shm.IsExisting() == true); - shm.OpenSharedMemory(); + REQUIRE(shm.exists() == true); + shm.openSharedMemory(); shm()->shmversion = 0; // Should fail since version is set to 0 diff --git a/slsDetectorSoftware/tests/test-SharedMemory.cpp b/slsDetectorSoftware/tests/test-SharedMemory.cpp index fb1248653..051100663 100644 --- a/slsDetectorSoftware/tests/test-SharedMemory.cpp +++ b/slsDetectorSoftware/tests/test-SharedMemory.cpp @@ -20,8 +20,8 @@ constexpr int shm_id = 10; TEST_CASE("Create SharedMemory read and write", "[detector]") { SharedMemory shm(shm_id, -1); - shm.CreateSharedMemory(); - CHECK(shm.GetName() == std::string("/slsDetectorPackage_detector_") + + shm.createSharedMemory(); + CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") + std::to_string(shm_id)); shm()->x = 3; @@ -32,25 +32,25 @@ TEST_CASE("Create SharedMemory read and write", "[detector]") { CHECK(shm()->y == 5.7); CHECK(std::string(shm()->mess) == "Some string"); - shm.UnmapSharedMemory(); - shm.RemoveSharedMemory(); + shm.unmapSharedMemory(); + shm.removeSharedMemory(); - CHECK(shm.IsExisting() == false); + CHECK(shm.exists() == false); } TEST_CASE("Open existing SharedMemory and read", "[detector]") { { SharedMemory shm(shm_id, -1); - shm.CreateSharedMemory(); + shm.createSharedMemory(); *shm() = 5.3; } SharedMemory shm2(shm_id, -1); - shm2.OpenSharedMemory(); + shm2.openSharedMemory(); CHECK(*shm2() == 5.3); - shm2.RemoveSharedMemory(); + shm2.removeSharedMemory(); } 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 shm0(shm_id, -1); SharedMemory shm1(shm_id, -1); - shm0.CreateSharedMemory(); - CHECK_THROWS(shm1.CreateSharedMemory()); - shm0.RemoveSharedMemory(); + shm0.createSharedMemory(); + CHECK_THROWS(shm1.createSharedMemory()); + shm0.removeSharedMemory(); } TEST_CASE("Open two shared memories to the same place", "[detector]") { // Create the first shared memory SharedMemory shm(shm_id, -1); - shm.CreateSharedMemory(); + shm.createSharedMemory(); shm()->x = 5; CHECK(shm()->x == 5); // Open the second shared memory with the same name SharedMemory shm2(shm_id, -1); - shm2.OpenSharedMemory(); + shm2.openSharedMemory(); CHECK(shm2()->x == 5); - CHECK(shm.GetName() == shm2.GetName()); + CHECK(shm.getName() == shm2.getName()); // Check that they still point to the same place 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 // to the same memory - shm2.RemoveSharedMemory(); - CHECK(shm.IsExisting() == false); - CHECK(shm2.IsExisting() == false); + shm2.removeSharedMemory(); + CHECK(shm.exists() == false); + CHECK(shm2.exists() == false); } TEST_CASE("Move SharedMemory", "[detector]") { SharedMemory shm(shm_id, -1); - CHECK(shm.GetName() == std::string("/slsDetectorPackage_detector_") + + CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") + std::to_string(shm_id)); - shm.CreateSharedMemory(); + shm.createSharedMemory(); shm()->x = 9; - CHECK(shm.size() == sizeof(Data)); SharedMemory shm2(shm_id + 1, -1); shm2 = std::move(shm); // shm is now a moved from object! CHECK(shm2()->x == 9); 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)); - shm2.RemoveSharedMemory(); + shm2.removeSharedMemory(); } TEST_CASE("Create several shared memories", "[detector]") { @@ -117,20 +114,62 @@ TEST_CASE("Create several shared memories", "[detector]") { v.reserve(N); for (int i = 0; i != N; ++i) { v.emplace_back(shm_id + i, -1); - CHECK(v[i].IsExisting() == false); - v[i].CreateSharedMemory(); + CHECK(v[i].exists() == false); + v[i].createSharedMemory(); *v[i]() = i; CHECK(*v[i]() == i); } for (int i = 0; i != N; ++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)); } for (int i = 0; i != N; ++i) { - v[i].RemoveSharedMemory(); - CHECK(v[i].IsExisting() == false); + v[i].removeSharedMemory(); + CHECK(v[i].exists() == false); } } + +TEST_CASE("Create create a shared memory with a tag"){ + SharedMemory 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 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 shm(shm_id, -1); + shm.createSharedMemory(); + *shm() = 7; + + SharedMemory shm2(shm_id, -1); + REQUIRE_THROWS(shm2.openSharedMemory()); + + shm.removeSharedMemory(); + + + + +} \ No newline at end of file