#include #include #include #include #include #include "RamBuffer.hpp" #include "buffer_config.hpp" #include "date.h" #include #include using namespace std; using namespace buffer_config; RamBuffer::RamBuffer( const string &detector_name, const int n_modules, const int n_slots) : detector_name_(detector_name), n_modules_(n_modules), n_slots_(n_slots), meta_bytes_(sizeof(ModuleFrame) * n_modules_), image_bytes_(MODULE_N_BYTES * n_modules_), buffer_bytes_((meta_bytes_ + image_bytes_) * n_slots_) { shm_fd_ = shm_open(detector_name_.c_str(), O_RDWR | O_CREAT, 0777); if (shm_fd_ < 0) { throw runtime_error(strerror(errno)); } if ((ftruncate(shm_fd_, buffer_bytes_)) == -1) { throw runtime_error(strerror(errno)); } // TODO: Test with MAP_HUGETLB buffer_ = mmap(NULL, buffer_bytes_, PROT_WRITE, MAP_SHARED, shm_fd_, 0); if (buffer_ == MAP_FAILED) { throw runtime_error(strerror(errno)); } // Metadata buffer is located at the start of the memory region. meta_buffer_ = (ModuleFrame *) buffer_; // Image buffer start right after metadata buffer. image_buffer_ = (char*)buffer_ + (meta_bytes_ * n_slots_); #ifdef DEBUG_OUTPUT using namespace date; cout << " [" << std::chrono::system_clock::now(); cout << "] [RamBuffer::RamBuffer] :"; cout << " Details of rambuffer:"; cout << "n_modules: " << n_modules_; cout << " || meta_bytes: " << meta_bytes_; cout << " || image_bytes: " << image_bytes_; cout << " || buffer_bytes: " << buffer_bytes_; cout << " || n_slots: " << n_slots_; cout << endl; #endif } RamBuffer::~RamBuffer() { munmap(buffer_, buffer_bytes_); close(shm_fd_); shm_unlink(detector_name_.c_str()); } void RamBuffer::write_frame( const ModuleFrame& src_meta, const char *src_data) const { const int slot_n = src_meta.frame_index % n_slots_; ModuleFrame *dst_meta = meta_buffer_ + (n_modules_ * slot_n) + src_meta.module_id; char *dst_data = image_buffer_ + (image_bytes_ * slot_n) + (MODULE_N_BYTES * src_meta.module_id); #ifdef DEBUG_OUTPUT using namespace date; cout << " [" << std::chrono::system_clock::now(); cout << "] [RamBuffer::write_frame] :"; cout << " || src_meta.frame_index " << src_meta.frame_index; cout << " || src_meta.n_recv_packets " << src_meta.n_recv_packets; cout << " || src_meta.daq_rec " << src_meta.daq_rec; cout << " || src_meta.module_id " << src_meta.module_id; cout << " || dst_data " << dst_data; cout << endl; #endif memcpy(dst_meta, &src_meta, sizeof(ModuleFrame)); memcpy(dst_data, src_data, MODULE_N_BYTES); } void RamBuffer::read_frame( const uint64_t pulse_id, const uint64_t module_id, ModuleFrame& dst_meta, char* dst_data) const { const size_t slot_n = pulse_id % n_slots_; ModuleFrame *src_meta = meta_buffer_ + (n_modules_ * slot_n) + module_id; char *src_data = image_buffer_ + (image_bytes_ * slot_n) + (MODULE_N_BYTES * module_id); memcpy(&dst_meta, src_meta, sizeof(ModuleFrame)); memcpy(dst_data, src_data, MODULE_N_BYTES); } char* RamBuffer::read_image(const uint64_t pulse_id, ImageMetadata &image_meta) const { const size_t slot_n = pulse_id % n_slots_; ModuleFrame *src_meta = meta_buffer_ + (n_modules_ * slot_n); char *src_data = image_buffer_ + (image_bytes_ * slot_n); auto is_pulse_init = false; auto is_good_image = true; for (int i_module=0; i_module < n_modules_; i_module++) { ModuleFrame *frame_meta = src_meta + i_module; auto is_good_frame = frame_meta->n_recv_packets == N_PACKETS_PER_FRAME; if (!is_good_frame) { is_good_image = false; continue; } if (!is_pulse_init) { if (frame_meta->pulse_id != pulse_id) { throw runtime_error("Wrong pulse_id in ram buffer slot."); } image_meta.pulse_id = frame_meta->pulse_id; image_meta.frame_index = frame_meta->frame_index; image_meta.daq_rec = frame_meta->daq_rec; is_pulse_init = 1; } if (is_good_image) { if (frame_meta->pulse_id != image_meta.pulse_id) { is_good_image = false; // TODO: Add some diagnostics in case this happens. } if (frame_meta->frame_index != image_meta.frame_index) { is_good_image = false; } if (frame_meta->daq_rec != image_meta.daq_rec) { is_good_image = false; } } } image_meta.is_good_image = is_good_image; if (!is_pulse_init) { image_meta.pulse_id = 0; image_meta.frame_index = 0; image_meta.daq_rec = 0; } return src_data; }