Dev/verify shm (#1276)
Some checks failed
Build on RHEL9 / build (push) Failing after 3m41s
Build on RHEL8 / build (push) Failing after 5m10s

* removed verify, update, fixed getUser to be a free function, generated commands, python bindings yet to do

* python bindings

* fixed tests

* minor

* minor

* format
This commit is contained in:
2025-08-23 10:23:27 +02:00
committed by GitHub
parent 15cbaa509e
commit fff5fa73be
18 changed files with 198 additions and 209 deletions

View File

@@ -15,7 +15,7 @@ from .gaincaps import Mythen3GainCapsWrapper
from .PatternGenerator import PatternGenerator
from . import _slsdet
from ._slsdet import freeSharedMemory
from ._slsdet import freeSharedMemory, getUserDetails
xy = _slsdet.xy
defs = _slsdet.slsDetectorDefs

View File

@@ -15,7 +15,7 @@ defs = slsDetectorDefs
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
from ._slsdet import xy, freeSharedMemory
from ._slsdet import xy, freeSharedMemory, getUserDetails
from .gaincaps import Mythen3GainCapsWrapper
from . import utils as ut
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
@@ -1537,7 +1537,7 @@ class Detector(CppDetectorApi):
"""
Retrieve user details from shared memory (hostname, type, PID, User, Date)
"""
return self.getUserDetails()
return getUserDetails(self.getShmId())
@property
@element

View File

@@ -25,6 +25,9 @@ void init_det(py::module &m) {
(void (*)(const int, const int)) & sls::freeSharedMemory,
py::arg() = 0, py::arg() = -1);
m.def("getUserDetails", (std::string(*)(const int)) & sls::getUserDetails,
py::arg() = 0);
py::class_<Detector> CppDetectorApi(m, "CppDetectorApi");
CppDetectorApi.def(py::init<int>());
@@ -2063,7 +2066,5 @@ void init_det(py::module &m) {
(Result<sls::ns>(Detector::*)(sls::Positions) const) &
Detector::getMeasurementTime,
py::arg() = Positions{});
CppDetectorApi.def("getUserDetails", (std::string(Detector::*)() const) &
Detector::getUserDetails);
;
}

View File

@@ -19,6 +19,8 @@ void init_det(py::module &m) {
using sls::Result;
m.def("freeSharedMemory", (void (*)(const int, const int)) &sls::freeSharedMemory, py::arg() = 0, py::arg() = -1);
m.def("getUserDetails", (std::string (*)(const int)) &sls::getUserDetails, py::arg() = 0);
py::class_<Detector> CppDetectorApi(m, "CppDetectorApi");
CppDetectorApi.def(py::init<int>());

View File

@@ -2466,6 +2466,15 @@ free:
PUT:
argc: 0
user:
is_description: true
actions:
GET:
argc: 0
PUT:
argc: 0
hostname:
is_description: true
actions:
@@ -4279,14 +4288,6 @@ initialchecks:
cast_input: [ true ]
output: [ args.front() ]
user:
help: "\n\tUser details from shared memory (hostname, type, PID, User, Date)."
actions:
GET:
argc: 0
check_det_id: true
function: getUserDetails
output: [ t ]

View File

@@ -12590,19 +12590,32 @@ user:
- arg_types: []
argc: 0
cast_input: []
check_det_id: true
check_det_id: false
convert_det_id: true
function: getUserDetails
function: ''
input: []
input_types: []
output:
- t
output: []
require_det_id: false
store_result_in_t: true
PUT:
args:
- arg_types: []
argc: 0
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
command_name: user
function_alias: user
help: "\n\tUser details from shared memory (hostname, type, PID, User, Date)."
help: ''
infer_action: true
is_description: true
v_a:
actions:
GET:

View File

@@ -22,6 +22,10 @@ class IpAddr;
// shm by mistake
void freeSharedMemory(const int detectorIndex = 0, const int moduleIndex = -1);
// Free function to avoid dependence on class
// and get user details directly from shm
std::string getUserDetails(const int detectorIndex = 0);
/**
* \class Detector
*/
@@ -2137,10 +2141,6 @@ class Detector {
* start [Gotthard2] not in burst and auto mode */
Result<ns> getMeasurementTime(Positions pos = {}) const;
/** get user details from shared memory (hostname, type, PID, User, Date)
*/
std::string getUserDetails() const;
///@}
private:

View File

@@ -16316,48 +16316,6 @@ std::string Caller::updatemode(int action) {
return os.str();
}
std::string Caller::user(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N(
User details from shared memory (hostname, type, PID, User, Date). )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
if (1 && args.size() != 0) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
}
else {
throw RuntimeError(
"INTERNAL ERROR: Invalid action: supported actions are ['GET']");
}
// generate code for each action
if (action == slsDetectorDefs::GET_ACTION) {
if (args.size() == 0) {
if (det_id != -1) {
throw RuntimeError("Cannot execute user at module level");
}
auto t = det->getUserDetails();
os << t << '\n';
}
}
return os.str();
}
std::string Caller::v_a(int action) {
std::ostringstream os;

View File

@@ -73,6 +73,7 @@ std::string Caller::list(int action) {
}
if (args.empty()) {
std::string ret = "free\n";
ret += "user\n";
for (auto &f : functions) {
ret += f.first + "\n";
}
@@ -188,6 +189,12 @@ std::string Caller::free(int action) {
return "free\n\tFree detector shared memory\n";
}
std::string Caller::user(int action) {
// This function is purely for help, actual functionality is in the caller
return "user\n\tUser details from shared memory (hostname, type, PID, "
"User, Date).\n";
}
std::string Caller::hostname(int action) {
std::ostringstream os;
if (action == defs::HELP_ACTION) {

View File

@@ -50,14 +50,27 @@ int main(int argc, char *argv[]) {
action = slsDetectorDefs::HELP_ACTION;
else {
// Free shared memory should work also without a detector
// if we have an option for verify in the detector constructor
// we could avoid this but clutter the code
if (parser.command() == "free") {
if (parser.detector_id() != -1)
std::cout << "Cannot free shared memory of sub-detector\n";
else
sls::freeSharedMemory(parser.multi_id());
return 0;
return EXIT_SUCCESS;
}
// Get user details from shared memory should work also without a
// detector
if (parser.command() == "user") {
if (action == slsDetectorDefs::PUT_ACTION) {
std::cout << "Cannot set user details\n";
return EXIT_FAILURE;
}
if (parser.detector_id() != -1)
std::cout << "Cannot get user details of only a sub-detector\n";
else
std::cout << sls::getUserDetails(parser.multi_id())
<< std::endl;
return EXIT_SUCCESS;
}
}

View File

@@ -61,6 +61,54 @@ void freeSharedMemory(const int detectorIndex, const int moduleIndex) {
}
}
std::string getUserDetails(const int detectorIndex) {
int numModules = 0;
defs::detectorType type = defs::GENERIC;
pid_t pid = -1;
std::string hostname = "Unknown";
std::string user = "Unknown";
std::string date = "Unknown";
SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
if (detectorShm.exists()) {
detectorShm.openSharedMemory(false);
if (detectorShm()->shmversion < DETECTOR_SHMAPIVERSION) {
detectorShm.unmapSharedMemory();
throw SharedMemoryError(
"Detector Shared memory version too old to get user details!");
}
numModules = detectorShm()->totalNumberOfModules;
type = detectorShm()->detType;
pid = detectorShm()->lastPID;
user = detectorShm()->lastUser;
date = detectorShm()->lastDate;
detectorShm.unmapSharedMemory();
}
for (int imod = 0; imod != numModules; ++imod) {
SharedMemory<sharedModule> moduleShm(detectorIndex, imod);
moduleShm.openSharedMemory(false);
if (moduleShm()->shmversion < MODULE_SHMAPIVERSION) {
LOG(logWARNING) << "Module Shared Memory too old to get hostname";
} else {
hostname = moduleShm()->hostname;
}
moduleShm.unmapSharedMemory();
}
std::ostringstream userDetails;
userDetails << "Detector Index: " << detectorIndex << "\n"
<< "Number of Modules: " << numModules << "\n"
<< "Type: " << type << "\n"
<< "PID: " << pid << "\n"
<< "User: " << user << "\n"
<< "Date: " << date << "\n"
<< "Hostname: " << hostname << "\n";
return userDetails.str();
}
using defs = slsDetectorDefs;
Detector::Detector(int shm_id) : pimpl(make_unique<DetectorImpl>(shm_id)) {}
@@ -2828,8 +2876,6 @@ Result<ns> Detector::getMeasurementTime(Positions pos) const {
return pimpl->Parallel(&Module::getMeasurementTime, pos);
}
std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); }
std::vector<uint16_t> Detector::getValidPortNumbers(uint16_t start_port) {
int num_sockets_per_detector = getNumberofUDPInterfaces({}).tsquash(
"Number of UDP Interfaces is not consistent among modules");

View File

@@ -31,21 +31,16 @@
namespace sls {
DetectorImpl::DetectorImpl(int detector_index, bool verify, bool update)
DetectorImpl::DetectorImpl(int detector_index)
: detectorIndex(detector_index), shm(detector_index, -1),
ctb_shm(detector_index, -1, CtbConfig::shm_tag()) {
setupDetector(verify, update);
setupDetector();
}
void DetectorImpl::setupDetector(bool verify, bool update) {
initSharedMemory(verify);
initializeMembers(verify);
if (update) {
updateUserdetails();
}
if (ctb_shm.exists())
ctb_shm.openSharedMemory(verify);
void DetectorImpl::setupDetector() {
initSharedMemory();
initializeMembers();
updateUserdetails();
}
bool DetectorImpl::isAllPositions(Positions pos) const {
@@ -57,64 +52,45 @@ void DetectorImpl::setAcquiringFlag(bool flag) { shm()->acquiringFlag = flag; }
int DetectorImpl::getDetectorIndex() const { return detectorIndex; }
std::string DetectorImpl::getUserDetails() {
if (modules.empty()) {
return std::string("none");
}
std::ostringstream sstream;
sstream << "\nHostname: ";
for (auto &module : modules) {
sstream << (module->isFixedPatternSharedMemoryCompatible()
? module->getHostname()
: "Unknown")
<< "+";
}
sstream << "\nType: ";
// get type from detector version shm
if (shm()->shmversion >= DETECTOR_SHMAPIVERSION) {
sstream << ToString(shm()->detType);
}
// get type from module shm
else {
for (auto &module : modules) {
sstream << (module->isFixedPatternSharedMemoryCompatible()
? ToString(module->getDetectorType())
: "Unknown")
<< "+";
}
}
sstream << "\nPID: " << shm()->lastPID << "\nUser: " << shm()->lastUser
<< "\nDate: " << shm()->lastDate << std::endl;
return sstream.str();
}
bool DetectorImpl::getInitialChecks() const { return shm()->initialChecks; }
void DetectorImpl::setInitialChecks(const bool value) {
shm()->initialChecks = value;
}
void DetectorImpl::initSharedMemory(bool verify) {
void DetectorImpl::initSharedMemory() {
// creating new shm
if (!shm.exists()) {
shm.createSharedMemory();
initializeDetectorStructure();
} else {
shm.openSharedMemory(verify);
if (verify && shm()->shmversion != DETECTOR_SHMVERSION) {
}
// opening existing shm
else {
shm.openSharedMemory(true);
if (shm()->shmversion != DETECTOR_SHMVERSION) {
LOG(logERROR) << "Detector shared memory (" << detectorIndex
<< ") version mismatch "
"(expected 0x"
<< std::hex << DETECTOR_SHMVERSION << " but got 0x"
<< shm()->shmversion << std::dec
<< ". Clear Shared memory to continue.";
throw SharedMemoryError("Shared memory version mismatch!");
<< ". Free Shared memory to continue.";
shm.unmapSharedMemory();
throw SharedMemoryError("Detector Shared memory version mismatch!");
}
if (ctb_shm.exists()) {
ctb_shm.openSharedMemory(true);
if (ctb_shm()->shmversion != CTB_SHMVERSION) {
LOG(logERROR)
<< "CTB shared memory version mismatch (expected 0x"
<< std::hex << CTB_SHMVERSION << " but got 0x"
<< ctb_shm()->shmversion << std::dec
<< ". Free Shared memory to continue.";
ctb_shm.unmapSharedMemory();
throw SharedMemoryError("Ctb Shared memory version mismatch!");
}
}
}
// std::cout <<
}
void DetectorImpl::initializeDetectorStructure() {
@@ -132,14 +108,14 @@ void DetectorImpl::initializeDetectorStructure() {
shm()->zmqHwm = -1;
}
void DetectorImpl::initializeMembers(bool verify) {
void DetectorImpl::initializeMembers() {
// DetectorImpl
zmqSocket.clear();
// get objects from single det shared memory (open)
for (int i = 0; i < shm()->totalNumberOfModules; i++) {
try {
modules.push_back(make_unique<Module>(detectorIndex, i, verify));
modules.push_back(make_unique<Module>(detectorIndex, i));
} catch (...) {
modules.clear();
throw;
@@ -210,10 +186,12 @@ void DetectorImpl::setHostname(const std::vector<std::string> &name) {
if (shm()->detType == defs::CHIPTESTBOARD ||
shm()->detType == defs::XILINX_CHIPTESTBOARD) {
if (ctb_shm.exists())
ctb_shm.openSharedMemory(true);
else
ctb_shm.createSharedMemory();
if (ctb_shm.exists()) {
throw SharedMemoryError(
"This shared memory " + ctb_shm.getName() +
" should have been deleted before! Free it to continue.");
}
ctb_shm.createSharedMemory();
}
}
@@ -233,7 +211,7 @@ void DetectorImpl::addModule(const std::string &name) {
}
auto pos = modules.size();
modules.emplace_back(make_unique<Module>(type, detectorIndex, pos, false));
modules.emplace_back(make_unique<Module>(type, detectorIndex, pos));
shm()->totalNumberOfModules = modules.size();
modules[pos]->setControlPort(port);
modules[pos]->setStopPort(port + 1);

View File

@@ -71,13 +71,7 @@ struct sharedDetector {
class DetectorImpl : public virtual slsDetectorDefs {
public:
/**
* @param verify true to verify if shared memory version matches existing
* one
* @param update true to update last user pid, date etc
*/
explicit DetectorImpl(int detector_index = 0, bool verify = true,
bool update = true);
explicit DetectorImpl(int detector_index = 0);
template <class CT> struct NonDeduced {
using type = CT;
@@ -195,9 +189,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** return detector index in shared memory */
int getDetectorIndex() const;
/** Get user details of shared memory */
std::string getUserDetails();
bool getInitialChecks() const;
/** initial compaibility and other server start up checks
@@ -341,26 +332,20 @@ class DetectorImpl : public virtual slsDetectorDefs {
/**
* Creates/open shared memory, initializes detector structure and members
* Called by constructor/ set hostname / read config file
* @param verify true to verify if shared memory version matches existing
* one
* @param update true to update last user pid, date etc
*/
void setupDetector(bool verify = true, bool update = true);
void setupDetector();
/**
* Creates shm and initializes shm structure OR
* Open shm and maps to structure
* @param verify true to verify if shm size matches existing one
*/
void initSharedMemory(bool verify = true);
void initSharedMemory();
/** Initialize detector structure for the shared memory just created */
void initializeDetectorStructure();
/** Initialize members (eg. modules from shm, zmqsockets)
* @param verify true to verify if shm size matches existing one
*/
void initializeMembers(bool verify = true);
/** Initialize members (eg. modules from shm, zmqsockets) */
void initializeMembers();
/** Update in shm */
void updateUserdetails();

View File

@@ -30,27 +30,15 @@
namespace sls {
// creating new shm
Module::Module(detectorType type, int det_id, int module_index, bool verify)
Module::Module(detectorType type, int det_id, int module_index)
: moduleIndex(module_index), shm(det_id, module_index) {
// ensure shared memory was not created before
if (shm.exists()) {
LOG(logWARNING) << "This shared memory should have been "
"deleted before! "
<< shm.getName() << ". Freeing it again";
shm.removeSharedMemory();
}
initSharedMemory(type, det_id, verify);
createSharedMemory(type, det_id);
}
// opening existing shm
Module::Module(int det_id, int module_index, bool verify)
Module::Module(int det_id, int module_index)
: moduleIndex(module_index), shm(det_id, module_index) {
// getDetectorType From shm will check if existing
detectorType type = getDetectorTypeFromShm(det_id, verify);
initSharedMemory(type, det_id, verify);
openSharedMemory(det_id);
}
bool Module::isFixedPatternSharedMemoryCompatible() const {
@@ -3403,43 +3391,39 @@ Ret Module::sendToReceiver(int fnum, const Arg &args) {
return static_cast<const Module &>(*this).sendToReceiver<Ret>(fnum, args);
}
slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id,
bool verify) {
void Module::createSharedMemory(detectorType type, int det_id) {
shm = SharedMemory<sharedModule>(det_id, moduleIndex);
// ensure shared memory was not created before
if (shm.exists()) {
throw SharedMemoryError(
"This shared memory " + shm.getName() +
" should have been deleted before! Free it to continue.");
}
shm.createSharedMemory();
initializeModuleStructure(type);
}
void Module::openSharedMemory(int det_id) {
shm = SharedMemory<sharedModule>(det_id, moduleIndex);
if (!shm.exists()) {
throw SharedMemoryError("Shared memory " + shm.getName() +
" does not exist.\n Corrupted Multi Shared "
"memory. Please free shared memory.");
}
shm.openSharedMemory(verify);
if (verify && shm()->shmversion != MODULE_SHMVERSION) {
shm.openSharedMemory(true);
if (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.";
ss << "Module 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();
throw SharedMemoryError(ss.str());
}
return shm()->detType;
}
void Module::initSharedMemory(detectorType type, int det_id, bool verify) {
shm = SharedMemory<sharedModule>(det_id, moduleIndex);
if (!shm.exists()) {
shm.createSharedMemory();
initializeModuleStructure(type);
} else {
shm.openSharedMemory(verify);
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.";
throw SharedMemoryError(ss.str());
}
}
}
void Module::initializeModuleStructure(detectorType type) {

View File

@@ -67,14 +67,11 @@ class Module : public virtual slsDetectorDefs {
* *
* ************************************************/
/** creating new shared memory
verify is if shared memory version matches existing one */
explicit Module(detectorType type, int det_id = 0, int module_index = 0,
bool verify = true);
/** creating new shared memory */
explicit Module(detectorType type, int det_id = 0, int module_index = 0);
/** opening existing shared memory
verify is if shared memory version matches existing one */
explicit Module(int det_id = 0, int module_index = 0, bool verify = true);
/** opening existing shared memory */
explicit Module(int det_id = 0, int module_index = 0);
bool isFixedPatternSharedMemoryCompatible() const;
std::string getHostname() const;
@@ -738,13 +735,8 @@ class Module : public virtual slsDetectorDefs {
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args) const;
/** Get Detector Type from Shared Memory
verify is if shm size matches existing one */
detectorType getDetectorTypeFromShm(int det_id, bool verify = true);
/** Initialize shared memory
verify is if shm size matches existing one */
void initSharedMemory(detectorType type, int det_id, bool verify = true);
void createSharedMemory(detectorType type, int det_id);
void openSharedMemory(int det_id);
/** Initialize module structure to defaults,
Called when new shared memory is created */

View File

@@ -4158,7 +4158,9 @@ int InferAction::updatemode() {
int InferAction::user() {
if (args.size() == 0) {
return slsDetectorDefs::GET_ACTION;
throw RuntimeError(
"sls_detector is disabled for command: user with number of "
"arguments 0. Use sls_detector_get or sls_detector_put");
}
else {

View File

@@ -3592,10 +3592,16 @@ TEST_CASE("frametime", "[.cmdcall]") {
TEST_CASE("user", "[.cmdcall]") {
Detector det;
Caller caller(&det);
caller.call("user", {}, -1, GET);
// stays the same across calls
std::ostringstream oss1, oss2, oss3;
caller.call("user", {}, -1, GET, oss1);
caller.call("user", {}, -1, GET, oss2);
caller.call("user", {}, -1, GET, oss3);
REQUIRE(oss1.str() == oss2.str());
REQUIRE(oss2.str() == oss3.str());
// This is a get only command
REQUIRE_THROWS(caller.call("user", {}, -1, PUT));
// REQUIRE_THROWS(caller.call("user", {}, -1, PUT)); exit with failure
REQUIRE_NOTHROW(caller.call("user", {}, -1, GET));
}

View File

@@ -9,6 +9,7 @@ namespace sls {
using dt = slsDetectorDefs::detectorType;
TEST_CASE("Construction with a defined detector type") {
freeSharedMemory(0, 0); // clean up to start test
Module m(dt::EIGER);
REQUIRE(m.getDetectorType() == dt::EIGER);
freeSharedMemory(0, 0); // clean up