moved headers

This commit is contained in:
Erik Frojdh
2019-11-25 11:58:45 +01:00
parent eae1fb6609
commit 58050f72da
7 changed files with 86 additions and 2 deletions

View File

@ -1,52 +0,0 @@
/*
This class parses command line input or string input to extract the
multi_id, detector_id, command and arguments. It's used in the command
line binaries (sls_detector_get/put) to parse commands and in the
slsDetectorShared library to parse input from config files.
This class is fully internal to the project and NO guarantees are given
on the stability of the interface or implementation. This is also the
reason that the header file is not exposed.
*/
#ifndef CMD_LINE_PARSER_H
#define CMD_LINE_PARSER_H
#include <string>
#include <vector>
namespace sls {
class CmdLineParser {
public:
void Parse(int argc, const char *const argv[]);
void Parse(const std::string &s);
void Print();
int multi_id() const noexcept { return multi_id_; };
int detector_id() const noexcept { return detector_id_; };
int n_arguments() const noexcept { return arguments_.size(); }
const std::string &command() const noexcept{ return command_; }
void setCommand(std::string cmd) { command_ = cmd; }
bool isHelp() const noexcept { return help_; }
const std::string &executable() const noexcept{ return executable_; }
const std::vector<std::string> &arguments() const noexcept{ return arguments_; };
std::vector<const char *> argv() const;
std::string cli_line() const;
private:
void DecodeIdAndPosition(const char *c);
void Reset(); // reset all private variables
int multi_id_ = 0;
int detector_id_ = -1;
bool help_ = false;
std::string command_;
std::string executable_;
std::vector<std::string> arguments_;
};
} // namespace sls
#endif // CMD_LINE_PARSER_H

File diff suppressed because it is too large Load Diff

View File

@ -1,304 +0,0 @@
#pragma once
/************************************************
* @file SharedMemory.h
* @short functions basic implemenation of
* shared memory
***********************************************/
/**
*@short functions basic implemenation of shared memory
*/
#include "ansi.h"
#include "logger.h"
#include "sls_detector_exceptions.h"
#include "stdlib.h"
#include <cerrno> // errno
#include <cstring> // strerror
#include <fcntl.h> // O_CREAT, O_TRUNC..
#include <iostream>
#include <sstream>
#include <stdio.h> // printf
#include <sys/mman.h> // shared memory
#include <sys/stat.h> // fstat
#include <unistd.h>
#define SHM_MULTI_PREFIX "/slsDetectorPackage_multi_"
#define SHM_SLS_PREFIX "_sls_"
#define SHM_ENV_NAME "SLSDETNAME"
#include <iostream>
#include <string>
namespace sls {
template <typename T>
class SharedMemory {
public:
/**
* Constructor
* creates the single/multi detector shared memory name
* @param multiId multi detector id
* @param slsId sls detector id, -1 if a multi detector shared memory
*/
SharedMemory(int multiId, int slsId) {
name = ConstructSharedMemoryName(multiId, slsId);
}
/**
* Delete the copy constructor and copy assignment since we don't want two
* objects managing the same resource
*/
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;
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();
}
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();
}
}
/**
* Verify if it exists
* @param name of shared memory
* @return true if exists, else false
*/
bool IsExisting() {
bool ret = true;
int tempfd = shm_open(name.c_str(), O_RDWR, 0);
if ((tempfd < 0) && (errno == ENOENT)) {
ret = false;
}
close(tempfd);
return ret;
}
/**
* 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
* @param sz of shared memory
*/
void CreateSharedMemory() {
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);
FILE_LOG(logERROR) << msg;
throw SharedMemoryError(msg);
}
if (ftruncate(fd, sizeof(T)) < 0) {
std::string msg = "Create shared memory " + name + " failed at ftruncate: " + strerror(errno);
FILE_LOG(logERROR) << msg;
close(fd);
RemoveSharedMemory();
throw SharedMemoryError(msg);
}
shared_struct = MapSharedMemory();
FILE_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
* @param sz of shared memory
*/
void OpenSharedMemory() {
fd = shm_open(name.c_str(), O_RDWR, 0);
if (fd < 0) {
std::string msg = "Open existing shared memory " + name + " failed: " + strerror(errno);
FILE_LOG(logERROR) << msg;
throw SharedMemoryError(msg);
}
shared_struct = MapSharedMemory();
}
/**
* Unmap shared memory from an address
* throws a SharedMemoryError exception on failure
*/
void UnmapSharedMemory() {
if (shared_struct != nullptr) {
if (munmap(shared_struct, shmSize) < 0) {
std::string msg = "Unmapping shared memory " + name + " failed: " + strerror(errno);
FILE_LOG(logERROR) << msg;
close(fd);
throw SharedMemoryError(msg);
}
shared_struct = nullptr;
}
}
/**
* Remove existing Shared memory
*/
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);
FILE_LOG(logERROR) << msg;
throw SharedMemoryError(msg);
}
FILE_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 multiId multi detector id
* @param slsId sls detector id, -1 if a multi detector shared memory
* @returns shared memory name
*/
std::string ConstructSharedMemoryName(int multiId, int slsId) {
// using environment path
std::string sEnvPath = "";
char *envpath = getenv(SHM_ENV_NAME);
if (envpath != nullptr) {
sEnvPath.assign(envpath);
sEnvPath.insert(0, "_");
}
std::stringstream ss;
if (slsId < 0)
ss << SHM_MULTI_PREFIX << multiId << sEnvPath;
else
ss << SHM_MULTI_PREFIX << multiId << SHM_SLS_PREFIX << slsId << sEnvPath;
std::string temp = ss.str();
if (temp.length() > NAME_MAX_LENGTH) {
std::string msg = "Shared memory initialization failed. " + temp + " has " + std::to_string(temp.length()) + " characters. \n" + "Maximum is " + std::to_string(NAME_MAX_LENGTH) + ". Change the environment variable " + SHM_ENV_NAME;
FILE_LOG(logERROR) << msg;
throw SharedMemoryError(msg);
}
return temp;
}
/**
* Map shared memory to an address
* throws a SharedMemoryException exception on failure
* @param sz of shared memory
*/
T *MapSharedMemory() {
void *addr = mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
std::string msg = "Mapping shared memory " + name + " failed: " + strerror(errno);
FILE_LOG(logERROR) << msg;
close(fd);
throw SharedMemoryError(msg);
}
shmSize = sizeof(T);
close(fd);
return (T *)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) {
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);
FILE_LOG(logERROR) << msg;
close(fd);
throw SharedMemoryError(msg);
}
//size does not match
auto sz = static_cast<size_t>(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);
FILE_LOG(logERROR) << 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

View File

@ -1,476 +0,0 @@
#pragma once
#include "Result.h"
#include "SharedMemory.h"
#include "logger.h"
#include "sls_detector_defs.h"
class slsDetector;
class ZmqSocket;
class detectorData;
#include <memory>
#include <mutex>
#include <semaphore.h>
#include <string>
#include <thread>
#include <vector>
#define MULTI_SHMAPIVERSION 0x190809
#define MULTI_SHMVERSION 0x190814
#define SHORT_STRING_LENGTH 50
#define DATE_LENGTH 30
#include <future>
#include <numeric>
/**
* @short structure allocated in shared memory to store detector settings
* for IPC and cache
*/
struct sharedMultiSlsDetector {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND
* ------*/
/** shared memory version */
int shmversion;
/** last process id accessing the shared memory */
pid_t lastPID;
/** last user name accessing the shared memory */
char lastUser[SHORT_STRING_LENGTH];
/** last time stamp when accessing the shared memory */
char lastDate[SHORT_STRING_LENGTH];
/** number of sls detectors in shared memory */
int numberOfDetectors;
/** multi detector type */
slsDetectorDefs::detectorType multiDetectorType;
/** END OF FIXED PATTERN
* -----------------------------------------------*/
/** Number of detectors operated at once */
slsDetectorDefs::xy numberOfDetector;
/** max number of channels for complete detector*/
slsDetectorDefs::xy numberOfChannels;
/** flag for acquiring */
bool acquiringFlag;
/** data streaming (up stream) enable in receiver */
bool receiver_upstream;
};
class multiSlsDetector : public virtual slsDetectorDefs {
public:
/**
* Constructor
* @param id multi detector id
* @param verify true to verify if shared memory version matches existing
* one
* @param update true to update last user pid, date etc
*/
explicit multiSlsDetector(int multi_id = 0, bool verify = true,
bool update = true);
/**
* Destructor
*/
virtual ~multiSlsDetector();
template <class CT> struct NonDeduced { using type = CT; };
template <typename RT, typename... CT>
sls::Result<RT> Parallel(RT (slsDetector::*somefunc)(CT...),
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
std::iota(begin(positions), end(positions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(positions.size());
for (size_t i : positions) {
if (i >= detectors.size())
throw sls::RuntimeError("Detector out of range");
futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...));
}
sls::Result<RT> result;
result.reserve(positions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel(RT (slsDetector::*somefunc)(CT...) const,
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) const {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
std::iota(begin(positions), end(positions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(positions.size());
for (size_t i : positions) {
if (i >= detectors.size())
throw sls::RuntimeError("Detector out of range");
futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...));
}
sls::Result<RT> result;
result.reserve(positions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename... CT>
void Parallel(void (slsDetector::*somefunc)(CT...),
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
std::iota(begin(positions), end(positions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(positions.size());
for (size_t i : positions) {
if (i >= detectors.size())
throw sls::RuntimeError("Detector out of range");
futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...));
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT>
void Parallel(void (slsDetector::*somefunc)(CT...) const,
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) const {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
std::iota(begin(positions), end(positions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(positions.size());
for (size_t i : positions) {
if (i >= detectors.size())
throw sls::RuntimeError("Detector out of range");
futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...));
}
for (auto &i : futures) {
i.get();
}
}
/**
* Loop through the detectors serially and return the result as a vector
*/
template <typename RT, typename... CT>
std::vector<RT> serialCall(RT (slsDetector::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args);
/**
* Loop through the detectors serially and return the result as a vector
* Const qualified version
*/
template <typename RT, typename... CT>
std::vector<RT> serialCall(RT (slsDetector::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const;
/**
* Loop through the detectors in parallel and return the result as a vector
*/
template <typename RT, typename... CT>
std::vector<RT> parallelCall(RT (slsDetector::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args);
/**
* Loop through the detectors in parallel and return the result as a vector
* Const qualified version
*/
template <typename RT, typename... CT>
std::vector<RT> parallelCall(RT (slsDetector::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const;
template <typename... CT>
void parallelCall(void (slsDetector::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args);
template <typename... CT>
void parallelCall(void (slsDetector::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const;
/** set acquiring flag in shared memory */
void setAcquiringFlag(bool flag);
/** return multi detector shared memory ID */
int getMultiId() const;
std::string getPackageVersion() const;
int64_t getClientSoftwareVersion() const;
/** Free specific shared memory from the command line without creating object */
static void freeSharedMemory(int multiId, int detPos = -1);
/** Free all modules from current multi Id shared memory and delete members */
void freeSharedMemory();
/** Get user details of shared memory */
std::string getUserDetails();
/**
* Connect to Virtual Detector Servers at local host
* @param ndet number of detectors
* @param port starting port number
*/
void setVirtualDetectorServers(const int numdet, const int port);
/** Sets the hostname of all sls detectors in shared memory and updates local cache */
void setHostname(const std::vector<std::string> &name);
/** Gets the total number of detectors */
int size() const;
slsDetectorDefs::xy getNumberOfDetectors() const;
slsDetectorDefs::xy getNumberOfChannels() const;
/** Must be set before setting hostname
* Sets maximum number of channels of all sls detectors */
void setNumberOfChannels(const slsDetectorDefs::xy c);
/**
* Enable gap pixels, only for Eiger and for 8,16 and 32 bit mode. (Eiger)
* 4 bit mode gap pixels only in gui call back
*/
void setGapPixelsinReceiver(bool enable);
/**
* Enable data streaming to client
* @param enable 0 to disable, 1 to enable, -1 to get the value
* @returns data streaming to client enable
*/
bool enableDataStreamingToClient(int enable = -1);
void savePattern(const std::string &fname);
/**
* register callback for accessing acquisition final data
* @param func function to be called at the end of the acquisition.
* gets detector status and progress index as arguments
* @param pArg argument
*/
void registerAcquisitionFinishedCallback(void (*func)(double, int, void *),
void *pArg);
/**
* register calbback for accessing detector final data,
* also enables data streaming in client and receiver
* @param userCallback function for plotting/analyzing the data.
* Its arguments are
* the data structure d and the frame number f,
* s is for subframe number for eiger for 32 bit mode
* @param pArg argument
*/
void registerDataCallback(void (*userCallback)(detectorData *, uint64_t,
uint32_t, void *),
void *pArg);
/**
* Performs a complete acquisition
* resets frames caught in receiver, starts receiver, starts detector,
* blocks till detector finished acquisition, stop receiver, increments file
* index, loops for measurements, calls required call backs.
* @returns OK or FAIL depending on if it already started
*/
int acquire();
/**
* Combines data from all readouts and gives it to the gui
* or just gives progress of acquisition by polling receivers
*/
void processData();
/**
* Convert raw file
* @param fname name of pof file
* @param fpgasrc pointer in memory to read pof to
* @returns file size
*/
std::vector<char> readPofFile(const std::string &fname);
private:
/**
* 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 setupMultiDetector(bool verify = true, bool update = true);
/**
* Creates shm and initializes shm structure OR
* Open shm and maps to structure
* @param verify true to verify if shm size matches existing one
* @param update true to update last user pid, date etc
*/
void initSharedMemory(bool verify = true);
/** Initialize detector structure for the shared memory just created */
void initializeDetectorStructure();
/** Initialize members (eg. slsDetectors from shm, zmqsockets)
* @param verify true to verify if shm size matches existing one
*/
void initializeMembers(bool verify = true);
/** Update in shm */
void updateUserdetails();
bool isAcquireReady();
/** Execute command in terminal and return result */
std::string exec(const char *cmd);
void addSlsDetector(const std::string &hostname);
void updateDetectorSize();
/**
* Create Receiving Data Sockets
* @param destroy is true to destroy all the sockets
* @returns OK or FAIL
*/
int createReceivingDataSockets(const bool destroy = false);
/**
* Reads frames from receiver through a constant socket
* Called during acquire() when call back registered or when using gui
*/
void readFrameFromReceiver();
/**
* add gap pixels to the image (only for Eiger in 4 bit mode)
* @param image pointer to image without gap pixels
* @param gpImage poiner to image with gap pixels, if NULL, allocated
* inside function
* quadEnable quad enabled
* @returns number of data bytes of image with gap pixels
*/
int processImageWithGapPixels(char *image, char *&gpImage, bool quadEnable);
double setTotalProgress();
double getCurrentProgress();
void incrementProgress();
void setCurrentProgress(int64_t i = 0);
void startProcessingThread();
/**
* Check if processing thread is ready to join main thread
* @returns true if ready, else false
*/
bool getJoinThreadFlag() const;
/**
* Main thread sets if the processing thread should join it
* @param v true if it should join, else false
*/
void setJoinThreadFlag(bool value);
/**
* Listen to key event to stop acquiring
* when using acquire command
*/
int kbhit();
/**
* Convert a double holding time in seconds to an int64_t with nano seconds
* Used for conversion when sending time to detector
* @param t time in seconds
* @returns time in nano seconds
*/
int64_t secondsToNanoSeconds(double t);
/** Multi detector Id */
const int multiId{0};
/** Shared Memory object */
sls::SharedMemory<sharedMultiSlsDetector> multi_shm{0, -1};
/** pointers to the slsDetector structures */
std::vector<std::unique_ptr<slsDetector>> detectors;
/** data streaming (down stream) enabled in client (zmq sckets created) */
bool client_downstream{false};
/** ZMQ Socket - Receiver to Client */
std::vector<std::unique_ptr<ZmqSocket>> zmqSocket;
/** semaphore to let postprocessing thread continue for next
* scan/measurement */
sem_t sem_newRTAcquisition;
/** semaphore to let main thread know it got all the dummy packets (also
* from ext. process) */
sem_t sem_endRTAcquisition;
/** Total number of frames/images for next acquisition */
double totalProgress{0};
/** Current progress or frames/images processed in current acquisition */
double progressIndex{0};
/** mutex to synchronize main and data processing threads */
mutable std::mutex mp;
/** sets when the acquisition is finished */
bool jointhread{false};
/** the data processing thread */
// pthread_t dataProcessingThread;
std::thread dataProcessingThread;
/** detector data packed for the gui */
detectorData *thisData{nullptr};
void (*acquisition_finished)(double, int, void *){nullptr};
void *acqFinished_p{nullptr};
void (*dataReady)(detectorData *, uint64_t, uint32_t, void *){nullptr};
void *pCallbackArg{nullptr};
};

File diff suppressed because it is too large Load Diff