From 01d54a7a4caf74b8384082e6a64e9bc086bf2a42 Mon Sep 17 00:00:00 2001 From: Dhanya Maliakal Date: Fri, 27 Jan 2017 15:40:36 +0100 Subject: [PATCH] Complete rewrite of receiver, with new changes --- slsReceiverSoftware/Makefile | 5 +- .../include/BinaryFileWriter.h | 34 + slsReceiverSoftware/include/DataProcessor.h | 104 + slsReceiverSoftware/include/DataStreamer.h | 90 + slsReceiverSoftware/include/Fifo.h | 88 + slsReceiverSoftware/include/FileReader.h | 32 + slsReceiverSoftware/include/FileWriter.h | 45 + slsReceiverSoftware/include/GeneralData.h | 364 ++ slsReceiverSoftware/include/HDF5FileWriter.h | 34 + slsReceiverSoftware/include/Listener.h | 108 + slsReceiverSoftware/include/ThreadObject.h | 111 + .../include/UDPBaseImplementation.h | 13 +- slsReceiverSoftware/include/UDPInterface.h | 11 +- .../include/UDPStandardImplementation.h | 828 +--- .../include/UDPStandardImplementation_copy.h | 873 ++++ slsReceiverSoftware/include/logger.h | 6 +- slsReceiverSoftware/include/receiver_defs.h | 261 +- slsReceiverSoftware/src/BinaryFileWriter.cpp | 22 + slsReceiverSoftware/src/DataProcessor.cpp | 112 + slsReceiverSoftware/src/DataStreamer.cpp | 94 + slsReceiverSoftware/src/Fifo.cpp | 100 + slsReceiverSoftware/src/FileReader.cpp | 19 + slsReceiverSoftware/src/FileWriter.cpp | 24 + slsReceiverSoftware/src/HDF5FileWriter.cpp | 23 + slsReceiverSoftware/src/Listener.cpp | 118 + slsReceiverSoftware/src/ThreadObject.cpp | 113 + .../src/UDPBaseImplementation.cpp | 8 +- .../src/UDPStandardImplementation.cpp | 4100 +---------------- .../src/UDPStandardImplementation_copy.cpp | 4026 ++++++++++++++++ slsReceiverSoftware/src/main.cpp | 4 +- slsReceiverSoftware/src/slsReceiver.cpp | 1 + .../src/slsReceiverTCPIPInterface.cpp | 12 +- 32 files changed, 6986 insertions(+), 4797 deletions(-) create mode 100644 slsReceiverSoftware/include/BinaryFileWriter.h create mode 100644 slsReceiverSoftware/include/DataProcessor.h create mode 100644 slsReceiverSoftware/include/DataStreamer.h create mode 100644 slsReceiverSoftware/include/Fifo.h create mode 100644 slsReceiverSoftware/include/FileReader.h create mode 100644 slsReceiverSoftware/include/FileWriter.h create mode 100644 slsReceiverSoftware/include/GeneralData.h create mode 100644 slsReceiverSoftware/include/HDF5FileWriter.h create mode 100644 slsReceiverSoftware/include/Listener.h create mode 100644 slsReceiverSoftware/include/ThreadObject.h create mode 100644 slsReceiverSoftware/include/UDPStandardImplementation_copy.h create mode 100644 slsReceiverSoftware/src/BinaryFileWriter.cpp create mode 100644 slsReceiverSoftware/src/DataProcessor.cpp create mode 100644 slsReceiverSoftware/src/DataStreamer.cpp create mode 100644 slsReceiverSoftware/src/Fifo.cpp create mode 100644 slsReceiverSoftware/src/FileReader.cpp create mode 100644 slsReceiverSoftware/src/FileWriter.cpp create mode 100644 slsReceiverSoftware/src/HDF5FileWriter.cpp create mode 100644 slsReceiverSoftware/src/Listener.cpp create mode 100644 slsReceiverSoftware/src/ThreadObject.cpp create mode 100644 slsReceiverSoftware/src/UDPStandardImplementation_copy.cpp diff --git a/slsReceiverSoftware/Makefile b/slsReceiverSoftware/Makefile index d94ac77a0..1d486fb02 100644 --- a/slsReceiverSoftware/Makefile +++ b/slsReceiverSoftware/Makefile @@ -21,7 +21,10 @@ LIBZMQ = -L$(LIBZMQDIR) -Wl,-rpath=$(LIBZMQDIR) -lzmq #-Iinclude -I../slsDetectorCalibration -I$(ASM) -SRC_CLNT = MySocketTCP.cpp UDPInterface.cpp UDPBaseImplementation.cpp UDPStandardImplementation.cpp slsReceiverTCPIPInterface.cpp slsReceiver.cpp slsReceiverUsers.cpp utilities.cpp +SRC_CLNT = MySocketTCP.cpp ThreadObject.cpp Listener.cpp DataProcessor.cpp DataStreamer.cpp Fifo.cpp FileWriter.cpp BinaryFileWriter.cpp UDPInterface.cpp UDPBaseImplementation.cpp UDPStandardImplementation.cpp slsReceiverTCPIPInterface.cpp slsReceiver.cpp slsReceiverUsers.cpp utilities.cpp +ifeq ($(HDF5),yes) + SRC_CLNT += HDF5FileWriter.cpp +endif ifeq ($(REST), yes) SRC_CLNT += UDPRESTImplementation.cpp diff --git a/slsReceiverSoftware/include/BinaryFileWriter.h b/slsReceiverSoftware/include/BinaryFileWriter.h new file mode 100644 index 000000000..b47ec08b2 --- /dev/null +++ b/slsReceiverSoftware/include/BinaryFileWriter.h @@ -0,0 +1,34 @@ +/************************************************ + * @file BinaryFileWriter.h + * @short sets/gets properties for the binary file, + * creates/closes the file and writes data to it + ***********************************************/ +#ifndef BINARY_FILE_WRITER_H +#define BINARY_FILE_WRITER_H + +#include "FileWriter.h" + +/** + *@short sets/gets properties for the binary file, creates/closes the file and writes data to it + */ + +class BinaryFileWriter : private virtual slsReceiverDefs, public FileWriter { + + public: + /** + * Constructor + * creates the File Writer + * @fname pointer to file name prefix + */ + BinaryFileWriter(char* fname); + + /** + * Destructor + */ + ~BinaryFileWriter(); + + private: + +}; + +#endif diff --git a/slsReceiverSoftware/include/DataProcessor.h b/slsReceiverSoftware/include/DataProcessor.h new file mode 100644 index 000000000..1e18616c5 --- /dev/null +++ b/slsReceiverSoftware/include/DataProcessor.h @@ -0,0 +1,104 @@ +/************************************************ + * @file DataProcessor.h + * @short creates data processor thread that + * pulls pointers to memory addresses from fifos + * and processes data stored in them & writes them to file + ***********************************************/ +#ifndef DATAPROCESSOR_H +#define DATAPROCESSOR_H +/** + *@short creates & manages a data processor thread each + */ + +#include "ThreadObject.h" + +class Fifo; + +class DataProcessor : private virtual slsReceiverDefs, public ThreadObject { + + public: + /** + * Constructor + * Calls Base Class CreateThread(), sets ErrorMask if error and increments NumberofDataProcessors + * @param f address of Fifo pointer + */ + DataProcessor(Fifo*& f); + + /** + * Destructor + * Calls Base Class DestroyThread() and decrements NumberofDataProcessors + */ + ~DataProcessor(); + + + /** + * Get RunningMask + * @return RunningMask + */ + static uint64_t GetErrorMask(); + + /** + * Reset RunningMask + */ + static void ResetRunningMask(); + + + /** + * Set bit in RunningMask to allow thread to run + */ + void StartRunning(); + + /** + * Reset bit in RunningMask to prevent thread from running + */ + void StopRunning(); + + /** + * Set Fifo pointer to the one given + * @param f address of Fifo pointer + */ + void SetFifo(Fifo*& f); + + private: + + /** + * Get Type + * @return type + */ + std::string GetType(); + + /** + * Returns if the thread is currently running + * @returns true if thread is running, else false + */ + bool IsRunning(); + + /** + * Thread Exeution for DataProcessor Class + * Pop bound addresses, process them, + * write to file if needed & free the address + */ + void ThreadExecution(); + + + + /** type of thread */ + static const std::string TypeName; + + /** Total Number of DataProcessor Objects */ + static int NumberofDataProcessors; + + /** Mask of errors on any object eg.thread creation */ + static uint64_t ErrorMask; + + /** Mask of all listener objects running */ + static uint64_t RunningMask; + + /** mutex to update static items among objects (threads)*/ + static pthread_mutex_t Mutex; + + /** Fifo structure */ + Fifo* fifo; +}; + +#endif diff --git a/slsReceiverSoftware/include/DataStreamer.h b/slsReceiverSoftware/include/DataStreamer.h new file mode 100644 index 000000000..ef1936e04 --- /dev/null +++ b/slsReceiverSoftware/include/DataStreamer.h @@ -0,0 +1,90 @@ +/************************************************ + * @file DataStreamer.h + * @short streams data from receiver via ZMQ + ***********************************************/ +#ifndef DATASTREAMER_H +#define DATASTREAMER_H +/** + *@short creates & manages a data streamer thread each + */ + +#include "ThreadObject.h" + +class DataStreamer : private virtual slsReceiverDefs, public ThreadObject { + + public: + /** + * Constructor + * Calls Base Class CreateThread(), sets ErrorMask if error and increments NumberofDataStreamers + */ + DataStreamer(); + + /** + * Destructor + * Calls Base Class DestroyThread() and decrements NumberofDataStreamers + */ + ~DataStreamer(); + + + /** + * Get RunningMask + * @return RunningMask + */ + static uint64_t GetErrorMask(); + + /** + * Reset RunningMask + */ + static void ResetRunningMask(); + + + /** + * Set bit in RunningMask to allow thread to run + */ + void StartRunning(); + + /** + * Reset bit in RunningMask to prevent thread from running + */ + void StopRunning(); + + + private: + + /** + * Get Type + * @return type + */ + std::string GetType(); + + /** + * Returns if the thread is currently running + * @returns true if thread is running, else false + */ + bool IsRunning(); + + /** + * Thread Exeution for DataStreamer Class + * Stream an image via zmq + */ + void ThreadExecution(); + + + + /** type of thread */ + static const std::string TypeName; + + /** Total Number of DataStreamer Objects */ + static int NumberofDataStreamers; + + /** Mask of errors on any object eg.thread creation */ + static uint64_t ErrorMask; + + /** Mask of all listener objects running */ + static uint64_t RunningMask; + + /** mutex to update static items among objects (threads)*/ + static pthread_mutex_t Mutex; +}; + +#endif diff --git a/slsReceiverSoftware/include/Fifo.h b/slsReceiverSoftware/include/Fifo.h new file mode 100644 index 000000000..180aaa6b9 --- /dev/null +++ b/slsReceiverSoftware/include/Fifo.h @@ -0,0 +1,88 @@ +/************************************************ + * @file Fifo.h + * @short constructs the fifo structure + * which is a circular buffer with pointers to + * parts of allocated memory + ***********************************************/ +#ifndef FIFO_H +#define FIFO_H +/** + *@short constructs the fifo structure + */ + +#include "sls_receiver_defs.h" +#include "logger.h" + +#include "circularFifo.h" + +class Fifo : private virtual slsReceiverDefs { + + public: + /** + * Constructor + * Calls CreateFifos that creates fifos and allocates memory + * @param fifoItemSize size of each fifo item + * @param fifoDepth fifo depth + * @param success true if successful, else false + */ + Fifo(uint32_t fifoItemSize, uint32_t fifoDepth, bool &success); + + /** + * Destructor + */ + ~Fifo(); + + /** + * Pops free address from fifoFree + */ + void GetNewAddress(char*& address); + + /** + * Frees the bound address by pushing into fifoFree + */ + void FreeAddress(char*& address); + + /** + * Pushes bound address into fifoBound + */ + void PushAddress(char*& address); + + /** + * Pops bound address from fifoBound to process data + */ + void PopAddress(char*& address); + + private: + + /** + * Create Fifos, allocate memory & push addresses into fifo + * @param fifoItemSize size of each fifo item + * @param fifoDepth fifo depth + * @return OK if successful, else FAIL + */ + int CreateFifos(uint32_t fifoItemSize, uint32_t fifoDepth); + + /** + * Destroy Fifos and deallocate memory + */ + void DestroyFifos(); + + + /** Total Number of Fifo Class Objects */ + static int NumberofFifoClassObjects; + + /** Self Index */ + int index; + + /** Memory allocated, whose addresses are pushed into the fifos */ + char* memory; + + /** Circular Fifo pointing to addresses of bound data in memory */ + CircularFifo* fifoBound; + + /** Circular Fifo pointing to addresses of freed data in memory */ + CircularFifo* fifoFree; + +}; + +#endif diff --git a/slsReceiverSoftware/include/FileReader.h b/slsReceiverSoftware/include/FileReader.h new file mode 100644 index 000000000..7638ec327 --- /dev/null +++ b/slsReceiverSoftware/include/FileReader.h @@ -0,0 +1,32 @@ +/********************************************//** + * @file FileWriter.h + * @short sets/gets properties for the file, creates/closes the file and writes data to it + ***********************************************/ +#ifndef FILE_WRITER_H +#define FILE_WRITER_H + + + +/** + *@short sets/gets properties for the file, creates/closes the file and writes data to it + */ + +class FileWriter : private virtual slsReceiverDefs { + + public: + /** + * Constructor + * creates the File Writer + */ + FileWriter(); + + /** + * Destructor + */ + ~FileWriter(); + + private: + +}; + +#endif diff --git a/slsReceiverSoftware/include/FileWriter.h b/slsReceiverSoftware/include/FileWriter.h new file mode 100644 index 000000000..a25748f28 --- /dev/null +++ b/slsReceiverSoftware/include/FileWriter.h @@ -0,0 +1,45 @@ +/************************************************ + * @file FileWriter.h + * @short sets/gets properties for the file, + * creates/closes the file and writes data to it + ***********************************************/ +#ifndef FILE_WRITER_H +#define FILE_WRITER_H +/** + *@short sets/gets properties for the file, creates/closes the file and writes data to it + */ + +#include "sls_receiver_defs.h" +#include "logger.h" + + +class FileWriter : private virtual slsReceiverDefs { + + public: + /** + * Constructor + * creates the File Writer + * @fname pointer to file name prefix + */ + FileWriter(char* fname); + + /** + * Destructor + */ + ~FileWriter(); + + /** + * Get File Name prefix + * @returns file name prefix + */ + char* GetFileName(); + + protected: + + char* fileName; + + + +}; + +#endif diff --git a/slsReceiverSoftware/include/GeneralData.h b/slsReceiverSoftware/include/GeneralData.h new file mode 100644 index 000000000..5a38e8095 --- /dev/null +++ b/slsReceiverSoftware/include/GeneralData.h @@ -0,0 +1,364 @@ +/************************************************ + * @file GeneralData.h + * @short abstract for setting/getting properties of detector data + ***********************************************/ +#ifndef GENERAL_DATA_H +#define GENERAL_DATA_H +/** + *@short abstract for setting/getting properties of detector data + */ + + +typedef double double32_t; +typedef float float32_t; +typedef int int32_t; + + +class GeneralData { + +public: + + /** Number of Pixels in x axis */ + uint32_t nPixelsX; + + /** Number of Pixels in y axis */ + uint32_t nPixelsY; + + /** Size of just data in 1 packet (in bytes) */ + uint32_t dataSize; + + /** Size of 1 packet (in bytes) */ + uint32_t packetSize; + + /** Number of packets in an image (for each listening UDP port) */ + uint32_t packetsPerFrame; + + /** Image size (in bytes, for each listening UDP port) */ + uint32_t imageSize; + + /** Frame Number Mask */ + uint64_t frameIndexMask; + + /** Frame Index Offset */ + uint32_t frameIndexOffset; + + /** Packet Index Mask */ + uint32_t packetIndexMask; + + /** Packet Index Offset */ + uint32_t packetIndexOffset; + + /** Max Frames per binary file */ + uint32_t maxFramesPerFile; + + /** Data size that is saved into the fifo buffer at a time*/ + uint32_t fifoBufferSize; + + /** Header size of data saved into fifo buffer at a time*/ + uint32_t fifoBufferHeaderSize; + + /** Default Fifo depth */ + uint32_t defaultFifoDepth; + + /** Cosntructor */ + GeneralData(){}; + + /** Destructor */ + virtual ~GeneralData(){}; + + /** + * Get Header Infomation (frame number, packet number) + * @param index thread index for debugging purposes + * @param packetData pointer to data + * @param dynamicRange dynamic range to assign subframenumber if 32 bit mode + * @param frameNumber frame number + * @param packetNumber packet number + * @param subFrameNumber sub frame number if applicable + * @param bunchId bunch id + */ + void GetHeaderInfo(int index, char* packetData, uint32_t dynamicRange, + uint64_t& frameNumber, uint32_t& packetNumber, uint32_t& subFrameNumber, uint64_t bunchId) { + subFrameNumber = 0; + bunchId = 0; + frameNumber = ((uint32_t)(*((uint32_t*)(packetData)))); + frameNumber++; + packetNumber = frameNumber&packetIndexMask; + frameNumber = (frameNumber & frameIndexMask) >> frameIndexOffset; + } +}; + + +class GotthardData : public GeneralData { + + public: + + /** Constructor */ + GotthardData(){ + nPixelsX = 1280; + nPixelsY = 1; + dataSize = 1280; + packetSize = 1286; + packetsPerFrame = 2; + imageSize = dataSize*packetsPerFrame; + frameIndexMask = 0xFFFFFFFE; + frameIndexOffset = 1; + packetIndexMask = 1; + maxFramesPerFile = MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS; + defaultFifoDepth = 25000; + }; +}; + + +class ShortGotthardData : public GeneralData { + + public: + + /** Constructor */ + ShortGotthardData(){ + nPixelsX = 256; + nPixelsY = 1; + dataSize = 512; + packetSize = 518; + packetsPerFrame = 1; + imageSize = dataSize*packetsPerFrame; + frameIndexMask = 0xFFFFFFFF; + maxFramesPerFile = SHORT_MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS; + defaultFifoDepth = 25000; + }; +}; + + +class PropixData : public GeneralData { + + private: + + /** dynamic range for calculating image size */ + const static uint32_t dynamicRange = 16; + + public: + + /** Constructor */ + PropixData(){ + nPixelsX = 22; + nPixelsY = 22; + dataSize = 1280; + packetSize = 1286; + packetsPerFrame = 2; //not really + imageSize = nPixelsX*nPixelsY*dynamicRange; + frameIndexMask = 0xFFFFFFFE; + frameIndexOffset = 1; + packetIndexMask = 1; + maxFramesPerFile = MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS; + defaultFifoDepth = 25000; + }; +}; + + +class Moench02Data : public GeneralData { + + public: + + /** Bytes Per Adc */ + const static uint32_t bytesPerAdc = (40*2); + + /** Constructor */ + Moench02Data(){ + nPixelsX = 160; + nPixelsY = 160; + dataSize = 1280; + packetSize = 1286; + packetsPerFrame = 40; + imageSize = dataSize*packetsPerFrame; + frameIndexMask = 0xFFFFFF00; + frameIndexOffset = 8; + packetIndexMask = 0xFF; + maxFramesPerFile = MOENCH_MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS + FILE_FRAME_HEADER_LENGTH; + defaultFifoDepth = 2500; + }; +}; + + +class Moench03Data : public GeneralData { + + public: + + /** Size of packet header */ + const static uint32_t packetHeaderSize = 22; + + /** Constructor */ + Moench03Data(){ + nPixelsX = 400; + nPixelsY = 400; + dataSize = 8192; + packetSize = packetHeaderSize + dataSize; + packetsPerFrame = 40; + imageSize = dataSize*packetsPerFrame; + frameIndexMask = 0xFFFFFFFF; + frameIndexOffset = (6+8); + packetIndexMask = 0xFFFFFFFF; + maxFramesPerFile = JFRAU_MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS + FILE_FRAME_HEADER_LENGTH; + defaultFifoDepth = 2500; + }; +}; + + +class JCTBData : public GeneralData { + + public: + + /** Bytes Per Adc */ + const static uint32_t bytesPerAdc = 2; + + /** Constructor */ + JCTBData(){ + nPixelsX = 32; + nPixelsY = 128; + dataSize = 8192; + packetSize = 8224; + packetsPerFrame = 1; + imageSize = dataSize*packetsPerFrame; + maxFramesPerFile = JFCTB_MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS + FILE_FRAME_HEADER_LENGTH; + defaultFifoDepth = 2500; + }; +}; + + +class JungfrauData : public GeneralData { + +private: + + /** Structure of an jungfrau packet header */ + typedef struct { + unsigned char emptyHeader[6]; + unsigned char reserved[4]; + unsigned char packetNumber[1]; + unsigned char frameNumber[3]; + unsigned char bunchid[8]; + } jfrau_packet_header_t; + + public: + + /** Size of packet header */ + const static uint32_t packetHeaderSize = 22; + + /** Constructor */ + JungfrauData(){ + nPixelsX = (256*4); + nPixelsY = 256; + dataSize = 8192; + packetSize = packetHeaderSize + dataSize; + packetsPerFrame = 128; + imageSize = dataSize*packetsPerFrame; + frameIndexMask = 0xffffff; + frameIndexOffset = 0; + packetIndexMask = 0; + packetIndexOffset = 0; + maxFramesPerFile = JFRAU_MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS + FILE_FRAME_HEADER_LENGTH; + defaultFifoDepth = 2500; + }; + + /** + * Get Header Infomation (frame number, packet number) + * @param index thread index for debugging purposes + * @param packetData pointer to data + * @param dynamicRange dynamic range to assign subframenumber if 32 bit mode + * @param frameNumber frame number + * @param packetNumber packet number + * @param subFrameNumber sub frame number if applicable + * @param bunchId bunch id + */ + void GetHeaderInfo(int index, char* packetData, uint32_t dynamicRange, + uint64_t& frameNumber, uint32_t& packetNumber, uint32_t& subFrameNumber, uint64_t bunchId) { + subFrameNumber = 0; + jfrau_packet_header_t* header = (jfrau_packet_header_t*)(packetData); + frameNumber = (*( (uint32_t*) header->frameNumber))&frameIndexMask; + packetNumber = (uint32_t)(*( (uint8_t*) header->packetNumber)); + bunchId = (*((uint64_t*) header->bunchid)); + } +}; + + +class EigerData : public GeneralData { + +private: + /** Structure of an eiger packet header */ + typedef struct { + unsigned char subFrameNumber[4]; + unsigned char missingPacket[2]; + unsigned char portIndex[1]; + unsigned char dynamicRange[1]; + } eiger_packet_header_t; + + /** Structure of an eiger packet footer */ + typedef struct { + unsigned char frameNumber[6]; + unsigned char packetNumber[2]; + } eiger_packet_footer_t; + + public: + + /** Size of packet header */ + const static uint32_t packetHeaderSize = 8; + + /** Footer offset */ + uint32_t footerOffset; + + /** Constructor */ + EigerData(){ + nPixelsX = (256*2); + nPixelsY = 256; + dataSize = 1024; + packetSize = 1040; + packetsPerFrame = 1; + imageSize = dataSize*packetsPerFrame; + frameIndexMask = 0xFFFFFFFF; + frameIndexOffset = 0; + packetIndexMask = 0; + packetIndexOffset = 0; + maxFramesPerFile = EIGER_MAX_FRAMES_PER_FILE; + fifoBufferSize = packetSize*packetsPerFrame; + fifoBufferHeaderSize= HEADER_SIZE_NUM_TOT_PACKETS + FILE_FRAME_HEADER_LENGTH; + defaultFifoDepth = 100; + footerOffset = packetHeaderSize+dataSize; + }; + + /** + * Get Header Infomation (frame number, packet number) + * @param index thread index for debugging purposes + * @param packetData pointer to data + * @param dynamicRange dynamic range to assign subframenumber if 32 bit mode + * @param frameNumber frame number + * @param packetNumber packet number + * @param subFrameNumber sub frame number if applicable + * @param bunchId bunch id + */ + void GetHeaderInfo(int index, char* packetData, uint32_t dynamicRange, + uint64_t& frameNumber, uint32_t& packetNumber, uint32_t& subFrameNumber, uint64_t bunchId) { + bunchId = 0; + subFrameNumber = 0; + eiger_packet_footer_t* footer = (eiger_packet_footer_t*)(packetData + footerOffset); + frameNumber = (uint64_t)(*( (uint64_t*) footer)); + packetNumber = (*( (uint16_t*) footer->packetNumber))-1; + if (dynamicRange == 32) { + eiger_packet_header_t* header = (eiger_packet_header_t*) (packetData); + subFrameNumber = *( (uint32_t*) header->subFrameNumber); + } + } +}; + + +#endif diff --git a/slsReceiverSoftware/include/HDF5FileWriter.h b/slsReceiverSoftware/include/HDF5FileWriter.h new file mode 100644 index 000000000..4f26116f2 --- /dev/null +++ b/slsReceiverSoftware/include/HDF5FileWriter.h @@ -0,0 +1,34 @@ +/************************************************ + * @file HDF5FileWriter.h + * @short sets/gets properties for the HDF5 file, + * creates/closes the file and writes data to it + ***********************************************/ +#ifndef HDF5_FILE_WRITER_H +#define HDF5_FILE_WRITER_H + +#include "FileWriter.h" + +/** + *@short sets/gets properties for the HDF5 file, creates/closes the file and writes data to it + */ + +class HDF5FileWriter : private virtual slsReceiverDefs, public FileWriter { + + public: + /** + * Constructor + * creates the File Writer + * @fname pointer to file name prefix + */ + HDF5FileWriter(char* fname); + + /** + * Destructor + */ + ~HDF5FileWriter(); + + private: + +}; + +#endif diff --git a/slsReceiverSoftware/include/Listener.h b/slsReceiverSoftware/include/Listener.h new file mode 100644 index 000000000..88e381f16 --- /dev/null +++ b/slsReceiverSoftware/include/Listener.h @@ -0,0 +1,108 @@ +/************************************************ + * @file Listener.h + * @short creates the listener thread that + * listens to udp sockets, writes data to memory + * & puts pointers to their memory addresses into fifos + ***********************************************/ +#ifndef LISTENER_H +#define LISTENER_H +/** + *@short creates & manages a listener thread each + */ + +#include "ThreadObject.h" + +class Fifo; + +class Listener : private virtual slsReceiverDefs, public ThreadObject { + + public: + /** + * Constructor + * Calls Base Class CreateThread(), sets ErrorMask if error and increments NumberofListerners + * @param f address of Fifo pointer + */ + Listener(Fifo*& f); + + /** + * Destructor + * Calls Base Class DestroyThread() and decrements NumberofListerners + */ + ~Listener(); + + + /** + * Get RunningMask + * @return RunningMask + */ + static uint64_t GetErrorMask(); + + /** + * Reset RunningMask + */ + static void ResetRunningMask(); + + + /** + * Set bit in RunningMask to allow thread to run + */ + void StartRunning(); + + /** + * Reset bit in RunningMask to prevent thread from running + */ + void StopRunning(); + + /** + * Set Fifo pointer to the one given + * @param f address of Fifo pointer + */ + void SetFifo(Fifo*& f); + + + private: + + /** + * Get Type + * @return type + */ + std::string GetType(); + + /** + * Returns if the thread is currently running + * @returns true if thread is running, else false + */ + bool IsRunning(); + + /** + * Thread Exeution for Listener Class + * Pop free addresses, listen to udp socket, + * write to memory & push the address into fifo + */ + void ThreadExecution(); + + + + /** type of thread */ + static const std::string TypeName; + + /** Total Number of Listener Objects */ + static int NumberofListeners; + + /** Mask of errors on any object eg.thread creation */ + static uint64_t ErrorMask; + + /** Mask of all listener objects running */ + static uint64_t RunningMask; + + /** Mutex to update static items among objects (threads)*/ + static pthread_mutex_t Mutex; + + /** Fifo structure */ + Fifo* fifo; + + int count; + +}; + +#endif diff --git a/slsReceiverSoftware/include/ThreadObject.h b/slsReceiverSoftware/include/ThreadObject.h new file mode 100644 index 000000000..d6b0d9813 --- /dev/null +++ b/slsReceiverSoftware/include/ThreadObject.h @@ -0,0 +1,111 @@ +/************************************************ + * @file ThreadObject.h + * @short creates/destroys a thread + ***********************************************/ +#ifndef THREADOBJECT_H +#define THREADOBJECT_H +/** + *@short creates/destroys a thread + */ + +#include "sls_receiver_defs.h" +#include "logger.h" + +#include +#include +#include + +class ThreadObject : private virtual slsReceiverDefs { + + public: + /** + * Constructor + * @param ind self index + */ + ThreadObject(int ind); + + /** + * Destructor + * if alive, destroys thread + */ + virtual ~ThreadObject(); + + /** + * Print all member values + */ + void PrintMembers(); + + + /** + * Get Type + * @return type + */ + virtual std::string GetType() = 0; + + /** + * Returns if the thread is currently running + * @returns true if thread is running, else false + */ + virtual bool IsRunning() = 0; + + /** + * What is really being executed in the thread + */ + virtual void ThreadExecution() = 0; + + /** + * Post semaphore so thread can continue & start an acquisition + */ + void Continue(); + + protected: + + /** + * Destroy thread, semaphore and resets alive and killThread + */ + void DestroyThread(); + + /** + * Create Thread, sets semaphore, alive and killThread + * @return OK if successful, else FAIL + */ + int CreateThread(); + + + private: + + /** + * Static function using pointer from argument to call RunningThread() + * @param thisPointer pointer to an object of ThreadObject + */ + static void* StartThread(void *thisPointer); + + /** + * Actual Thread called: An infinite while loop in which, + * semaphore starts executing its contents as long RunningMask is satisfied + * Then it exits the thread on its own if killThread is true + */ + void RunningThread(); + + + protected: + /** Self Index */ + int index; + + /** Thread is alive/dead */ + bool alive; + + /** Variable monitored by thread to kills itself */ + bool killThread; + + /** Thread variable */ + pthread_t thread; + + /** Semaphore to synchonize starting of each run */ + sem_t semaphore; + + + +}; + +#endif diff --git a/slsReceiverSoftware/include/UDPBaseImplementation.h b/slsReceiverSoftware/include/UDPBaseImplementation.h index 34f60bc2c..fdd8e5886 100644 --- a/slsReceiverSoftware/include/UDPBaseImplementation.h +++ b/slsReceiverSoftware/include/UDPBaseImplementation.h @@ -173,9 +173,9 @@ class UDPBaseImplementation : protected virtual slsReceiverDefs, public UDPInter /** * Get the data stream enable - * @return 1 to send via zmq, else 0 + * @return data stream enable */ - uint32_t getDataStreamEnable() const; + bool getDataStreamEnable() const; /** @@ -336,8 +336,9 @@ class UDPBaseImplementation : protected virtual slsReceiverDefs, public UDPInter /** * Set Short Frame Enabled, later will be moved to getROI (so far only for gotthard) * @param i index of adc enabled, else -1 if all enabled + * @return OK or FAIL */ - void setShortFrameEnable(const int i); + int setShortFrameEnable(const int i); /** * Set the Frequency of Frames Sent to GUI @@ -354,10 +355,10 @@ class UDPBaseImplementation : protected virtual slsReceiverDefs, public UDPInter /** * Set the data stream enable - * @param enable 0 to disable, 1 to enable + * @param enable data stream enable * @return OK or FAIL */ - uint32_t setDataStreamEnable(const uint32_t enable); + int setDataStreamEnable(const bool enable); /** * Set Acquisition Period @@ -604,7 +605,7 @@ class UDPBaseImplementation : protected virtual slsReceiverDefs, public UDPInter /** Timer of Frames sent to GUI when frequency is 0 */ uint32_t frameToGuiTimerinMS; /** Data Stream Enable from Receiver */ - int32_t dataStreamEnable; + bool dataStreamEnable; static const int DEFAULT_STREAMING_TIMER = 500; diff --git a/slsReceiverSoftware/include/UDPInterface.h b/slsReceiverSoftware/include/UDPInterface.h index ec38b0a9f..315f12bec 100644 --- a/slsReceiverSoftware/include/UDPInterface.h +++ b/slsReceiverSoftware/include/UDPInterface.h @@ -235,9 +235,9 @@ class UDPInterface { /** * Get the data stream enable - * @return 1 to send via zmq, else 0 + * @return data stream enable */ - virtual uint32_t getDataStreamEnable() const = 0; + virtual bool getDataStreamEnable() const = 0; /** * Get Acquisition Period @@ -393,8 +393,9 @@ class UDPInterface { /** * Set Short Frame Enabled, later will be moved to getROI (so far only for gotthard) * @param i index of adc enabled, else -1 if all enabled + * @return OK or FAIL */ - virtual void setShortFrameEnable(const int i) = 0; + virtual int setShortFrameEnable(const int i) = 0; /** * Set the Frequency of Frames Sent to GUI @@ -411,10 +412,10 @@ class UDPInterface { /** * Set the data stream enable - * @param enable 0 to disable, 1 to enable + * @param enable data stream enable * @return OK or FAIL */ - virtual uint32_t setDataStreamEnable(const uint32_t enable) = 0; + virtual int setDataStreamEnable(const bool enable) = 0; /** * Set Acquisition Period diff --git a/slsReceiverSoftware/include/UDPStandardImplementation.h b/slsReceiverSoftware/include/UDPStandardImplementation.h index 9451fa6bb..c4fc66faf 100644 --- a/slsReceiverSoftware/include/UDPStandardImplementation.h +++ b/slsReceiverSoftware/include/UDPStandardImplementation.h @@ -5,45 +5,26 @@ * @file UDPBaseImplementation.h * @short does all the functions for a receiver, set/get parameters, start/stop etc. ***********************************************/ - -#include "UDPBaseImplementation.h" - -#include "genericSocket.h" -#include "circularFifo.h" -#include "singlePhotonDetector.h" -#include "slsReceiverData.h" -#include "moenchCommonMode.h" - - -#ifdef MYROOT1 -#include -#include -#endif - -#include -#include -#include -#include - -#ifdef HDF5C -#include "H5Cpp.h" -#ifndef H5_NO_NAMESPACE - using namespace H5; -#endif -#endif - /** * @short does all the functions for a receiver, set/get parameters, start/stop etc. */ +#include "UDPBaseImplementation.h" + +class GeneralData; +class Listener; +class DataProcessor; +class DataStreamer; +class Fifo; +class FileWriter; + +#include class UDPStandardImplementation: private virtual slsReceiverDefs, public UDPBaseImplementation { public: - /************************************************************************* - * Constructor & Destructor ********************************************** - *************************************************************************/ + //*** cosntructor & destructor *** /** * Constructor */ @@ -54,36 +35,17 @@ class UDPStandardImplementation: private virtual slsReceiverDefs, public UDPBase */ virtual ~UDPStandardImplementation(); - - /************************************************************************* - * Getters *************************************************************** - * They access local cache of configuration or detector parameters ******* - *************************************************************************/ - - - /************************************************************************* - * Setters *************************************************************** - * They modify the local cache of configuration or detector parameters *** - *************************************************************************/ - - //**initial parameters*** - //*** file parameters*** + //*** initial parameters (behavioral)*** /** - * Set File Name Prefix (without frame index, file index and extension (_d0_f000000000000_8.raw)) - * Does not check for file existence since it is created only at startReceiver - * @param c file name (max of 1000 characters) - */ - void setFileName(const char c[]); - - /** - * Overridden method - * Set data compression, by saving only hits (so far implemented only for Moench and Gotthard) - * @param b true for data compression enable, else false + * Set receiver type (and corresponding detector variables in derived STANDARD class) + * It is the first function called by the client when connecting to receiver + * @param d detector type * @return OK or FAIL */ - int setDataCompressionEnable(const bool b); + int setDetectorType(const detectorType d); - //***acquisition count parameters*** + + //*** Getters *** /** * Get Total Frames Caught for an entire acquisition (including all scans) * @return total number of frames caught for entire acquisition @@ -96,13 +58,25 @@ class UDPStandardImplementation: private virtual slsReceiverDefs, public UDPBase */ uint64_t getFramesCaught() const; - //***acquisition parameters*** + + + //*** Setters *** + + //*** file parameters *** + /** + * Set File Name Prefix (without frame index, file index and extension (_f000000000000_8.raw)) + * Does not check for file existence since it is created only at startReceiver + * @param c file name (max of 1000 characters) + */ + void setFileName(const char c[]); + + //*** acquisition parameters *** /** - * Overridden method * Set Short Frame Enabled, later will be moved to getROI (so far only for gotthard) * @param i index of adc enabled, else -1 if all enabled + * @return OK or FAIL */ - void setShortFrameEnable(const int i); + int setShortFrameEnable(const int i); /** * Set the Frequency of Frames Sent to GUI @@ -113,758 +87,80 @@ class UDPStandardImplementation: private virtual slsReceiverDefs, public UDPBase /** * Set the data stream enable - * @param enable 0 to disable, 1 to enable + * @param enable data stream enable * @return OK or FAIL */ - uint32_t setDataStreamEnable(const uint32_t enable); + int setDataStreamEnable(const bool enable); /** - * Overridden method * Set Acquisition Period * @param i acquisition period * @return OK or FAIL */ int setAcquisitionPeriod(const uint64_t i); - /** - * Set Acquisition Time - * @param i acquisition time - * @return OK or FAIL - */ - int setAcquisitionTime(const uint64_t i); - - /** - * Overridden method - * Set Number of Frames expected by receiver from detector - * The data receiver status will change from running to idle when it gets this number of frames - * @param i number of frames expected - * @return OK or FAIL - */ - int setNumberOfFrames(const uint64_t i); - - /** - * Overridden method - * Set Dynamic Range or Number of Bits Per Pixel - * @param i dynamic range that is 4, 8, 16 or 32 - * @return OK or FAIL - */ - int setDynamicRange(const uint32_t i); - - /** - * Overridden method - * Set Ten Giga Enable - * @param b true if 10Giga enabled, else false (1G enabled) - * @return OK or FAIL - */ - int setTenGigaEnable(const bool b); + //*** Behavioral functions *** - /** - * Overridden method - * Set Fifo Depth - * @param i fifo depth value - * @return OK or FAIL - */ - int setFifoDepth(const uint32_t i); - - /************************************************************************* - * Behavioral functions*************************************************** - * They may modify the status of the receiver **************************** - *************************************************************************/ - - //***initial functions*** - /** - * Overridden method - * Set receiver type (and corresponding detector variables in derived STANDARD class) - * It is the first function called by the client when connecting to receiver - * @param d detector type - * @return OK or FAIL - */ - int setDetectorType(const detectorType d); - - //***acquisition functions*** - /** - * Overridden method - * Reset acquisition parameters such as total frames caught for an entire acquisition (including all scans) - */ - void resetAcquisitionCount(); - - /** - * Overridden method - * Start Listening for Packets by activating all configuration settings to receiver - * When this function returns, it has status RUNNING(upon SUCCESS) or IDLE (upon failure) - * @param c error message if FAIL - * @return OK or FAIL - */ - int startReceiver(char *c=NULL); - - /** - * Overridden method - * Stop Listening for Packets - * Calls startReadout(), which stops listening and sets status to Transmitting - * When it has read every frame in buffer, the status changes to Run_Finished - * When this function returns, receiver has status IDLE - * Pre: status is running, semaphores have been instantiated, - * Post: udp sockets shut down, status is idle, semaphores destroyed - */ - void stopReceiver(); - - /** - * Overridden method - * Stop Listening to Packets - * and sets status to Transmitting - * Next step would be to get all data and stop receiver completely and return with idle state - * Pre: status is running, udp sockets have been initialized, stop receiver initiated - * Post:udp sockets closed, status is transmitting - */ - void startReadout(); - - /** - * Overridden method - * Shuts down and deletes UDP Sockets - * TCPIPInterface can also call this in case of illegal shutdown of receiver - * @return OK or FAIL - */ - int shutDownUDPSockets(); - - /** - * Overridden method - * Get the buffer-current frame read by receiver - * @param ithread writer thread - * @param c pointer to current file name - * @param raw address of pointer, pointing to current frame to send to gui - * @param startAcq start index of the acquisition - * @param startFrame start index of the scan - */ - void readFrame(int ithread, char* c,char** raw, int64_t &startAcq, int64_t &startFrame); - - - void resetGuiPointer(int ithread); - /** - * Overridden method - * Closes file / all files(data compression involves multiple files) - * TCPIPInterface can also call this in case of illegal shutdown of receiver - * @param ithread writer thread index - */ - void closeFile(int ithread = 0); - - /** - * Activate / Deactivate Receiver - * If deactivated, receiver will write dummy packets 0xFF - * (as it will receive nothing from detector) - */ - int setActivate(int enable = -1); private: - /************************************************************************* - * Getters *************************************************************** - * They access local cache of configuration or detector parameters ******* - *************************************************************************/ - -/* - uint64_t (*getFrameNumber)(); - uint64_t eigerGetFrameNumber(); - uint64_t generalGetFrameNumber(); - getframenumber = &generalgetframenumber; - if(dettpe == eiger) getframenumber = &eigerGerFramenumber; - - call using getframenumber(); -*/ - - //**initial parameters*** /** * Delete and free member parameters */ - void deleteMembers(); - - /** - * Deletes all the filter objects for single photon data - * Deals with data compression - */ - void deleteFilter(); - - /** - * Initialize base member parameters - */ - void initializeBaseMembers(); + void DeleteMembers(); /** * Initialize member parameters */ - void initializeMembers(); + void InitializeMembers(); /** - * Sets up all the filter objects for single photon data - * Deals with data compression + * Sets local network parameters, but requires permissions */ - void initializeFilter(); + void SetLocalNetworkParameters(); /** * Set up the Fifo Structure for processing buffers - * between listening and writer threads - * When the parameters ahve been determined and if fifostructure needs to be changes, - * the listerning and writing threads are also destroyed together with this + * between listening and dataprocessor threads * @return OK or FAIL */ - int setupFifoStructure(); + int SetupFifoStructure(); - - /************************************************************************* - * Listening and Writing Threads ***************************************** - *************************************************************************/ - /** - * Create Data Call Back Threads - * @param destroy is true to destroy all the threads - * @return OK or FAIL - */ - int createDataCallbackThreads(bool destroy = false); - - /** - * Create Listening Threads - * @param destroy is true to destroy all the threads - */ - int createListeningThreads(bool destroy = false); - - /** - * Create Writer Threads - * @param destroy is true to destroy all the threads - * @return OK or FAIL - */ - int createWriterThreads(bool destroy = false); + //*** Class Members *** - - - /** - * Set Thread Priorities - */ - void setThreadPriorities(); - - /** - * Creates UDP Sockets - * @return OK or FAIL - */ - int createUDPSockets(); - - /** - * Initializes writer variables and creates the first file - * also does the startAcquisitionCallBack - * @return OK or FAIL - */ - int setupWriter(); - - /** - * Creates new file and reset some parameters - * @param ithread writer thread index - * @return OK or FAIL - */ - int createNewFile(int ithread); - - /** - * Creates new tree and file for compression - * @param ithread thread number - * @param iframe frame number - * @return OK or FAIL - */ - int createCompressionFile(int ithread, int iframe); - - /** - * Static function - Starts Data Callback Thread of this object - * @param this_pointer pointer to this object - */ - static void* startDataCallbackThread(void *this_pointer); - - /** - * Static function - Starts Listening Thread of this object - * @param this_pointer pointer to this object - */ - static void* startListeningThread(void *this_pointer); - - /** - * Static function - Starts Writing Thread of this object - * @param this_pointer pointer to this object - */ - static void* startWritingThread(void *this_pointer); - - /** - * Thread that sends data packets to client - */ - void startDataCallback(); - - /** - * Thread that listens to packets - * It pops the fifofree for free addresses, listens to packets and pushes them into the fifo - * This is continuously looped for each buffer in a nested loop, which is again looped for each acquisition - * Exits only for changing dynamic range, 10G parameters etc and recreated - * - */ - void startListening(); - - /** - * Called by startListening - * Listens to buffer, until packet(s) received or shutdownUDPsocket called by client - * Also copies carryovers from previous frame in front of buffer (gotthard and moench) - * For eiger, it ignores packets less than onePacketSize - * @param ithread listening thread index - * @param cSize number of bytes carried on from previous buffer - * @param temp temporary storage of previous buffer - * @return the number of bytes actually received - */ - int prepareAndListenBuffer(int ithread, int cSize, char* temp); - - /** - * Called by startListening - * Creates the packets - * @param ithread listening thread index - * @return the number of bytes actually received - */ - int prepareAndListenBufferDeactivated(int ithread); - - - /** - * Called by startListening - * Listens to each packet and copies only complete frames - * until all receiver or shutdownUDPsocket called by client - * @param ithread listening thread index - * @return the number of bytes copied to buffer - */ - int prepareAndListenBufferCompleteFrames(int ithread); - - /** - * Called by startListening - * Its called for the first packet of a scan or acquistion - * Sets the startframeindices and the variables to know if acquisition started - * @param ithread listening thread number - */ - void startFrameIndices(int ithread); - - /** - * Called by prepareAndListenBuffer - * This is called when udp socket is shut down by client - * It pushes ffff instead of packet number into fifo - * to inform writers about the end of listening session - * Then sets the listening mask so that it stops listening and wait for next acquisition trigger - * @param ithread listening thread number - * @param numbytes number of bytes received - */ - void stopListening(int ithread, int numbytes); - - /* - * Called by startListening for gotthard and moench to handle split frames - * It processes listening thread buffers by ensuring split frames are in the same buffer - * @param ithread listening thread index - * @param cSize number of bytes carried over to the next buffer to reunite with split frame - * @param temp temporary buffer to store the split frame - * @param rc number of bytes received - * @return packet count - */ - uint32_t processListeningBuffer(int ithread, int &cSize,char* temp, int rc); - - /** - * Thread started which writes packets to file. - * It calls popAndCheckEndofAcquisition to pop fifo and check if it is a dummy end buffer - * It then calls a function to process and write packets to file and pushes the addresses into the fifoFree - * This is continuously looped for each buffer in a nested loop, which is again looped for each acquisition - * Exits only for changing dynamic range, 10G parameters etc and recreated - * - */ - void startWriting(); - - /** - * Called by processWritingBuffer and processWritingBufferPacketByPacket - * When dummy-end buffers are popped from all FIFOs (acquisition over), this is called - * It frees the FIFO addresses, closes all files - * For data compression, it waits for all threads to be done - * Changes the status to RUN_FINISHED and prints statistics - * @param ithread writing thread index - * @param wbuffer writing buffer popped out from FIFO - */ - void stopWriting(int ithread, char* wbuffer); - - /** - * Called by processWritingBuffer and processWritingBufferPacketByPacket - * Updates parameters, (writes headers for eiger) and writes to file when not a dummy frame - * Copies data for gui display and frees addresses popped from FIFOs - * @param ithread writing thread index - * @param wbuffer writing buffer popped out from FIFO - * @param npackets number of packets - */ - void handleWithoutDataCompression(int ithread, char* wbuffer,uint32_t npackets); - - /** - * Called by startWriting for jungfrau and eiger - * writes complete frames to file - * Copies data for gui display and frees addresses popped from FIFOs - * @param ithread writing thread index - * @param wbuffer writing buffer popped out from FIFO - */ - void handleCompleteFramesOnly(int ithread, char* wbuffer); - - /** - * Calle by handleWithoutDataCompression - * Creating headers Writing to file without compression - * @param ithread writer thread index - * @param wbuffer is the address of buffer popped out of FIFO - * @param numpackets is the number of packets - */ - void writeFileWithoutCompression(int ithread, char* wbuffer,uint32_t numpackets); - - /** - * Called by writeToFileWithoutCompression - * Create headers for file writing (at the moment, this is eiger specific) - * @param wbuffer writing buffer popped from FIFOs - */ - void createHeaders(char* wbuffer); - - /** - * Updates the file header char aray, each time the corresp parameter is changed - * @param ithread writer thread index - */ - void updateFileHeader(int ithread); - - /** - * Called by handleWithoutDataCompression and handleWithCompression after writing to file - * Copy frames for GUI and updates appropriate parameters for frequency frames to gui - * Uses semaphore for nth frame mode - * @param ithread writer thread index - * @param buffer buffer to copy - * @param numpackets number of packets to copy - */ - void copyFrameToGui(int ithread, char* buffer, uint32_t numpackets); - - void waitWritingBufferForNextAcquisition(int ithread); - - /** - * Called by processWritingBuffer - * Processing fifo popped buffers for data compression - * Updates parameters and writes to file - * Copies data for gui display and frees addresses popped from FIFOs - * @param ithread writing thread number - * @param wbuffer writer buffer - * @param nf number of frames - */ - void handleDataCompression(int ithread, char* wbuffer, uint64_t &nf); - - - /** - * Get Frame Number - * @param ithread writer thread index - * @param wbuffer writer buffer - * @param framenumber reference to the frame number - * @param packetnumber reference to the packet number - * @param subframenumber reference to the subframe number - * @oaram bunchid reference to the bunch id - * @return OK or FAIL - */ - int getFrameandPacketNumber(int ithread, char* wbuffer, uint64_t &framenumber, uint32_t &packetnumber, uint32_t &subframenumber, uint64_t &bunchid); - - /** - * Find offset upto this frame number and write it to file - * @param ithread writer thread index - * @param wbuffer writer buffer - * @param offset reference of offset to look from and replaces offset to starting of nextframenumber - * @param nextFrameNumber frame number up to which data written - * @param numpackets number of packets in buffer - * @param numPacketsWritten number of packets written to file - */ - int writeUptoFrameNumber(int ithread, char* wbuffer, int &offset, uint64_t nextFrameNumber, uint32_t numpackets, int &numPacketsWritten); - - /** function that returns the name variable from the receiver complete file name prefix - @param fname complete file name prefix - @returns file name - */ - string getNameFromReceiverFilePrefix(string fname); - - /************************************************************************* - * Class Members ********************************************************* - *************************************************************************/ - - /** Maximum Number of Writer Threads */ - -#ifdef DCOMPRESS - /**** most likely not used ***/ - const static int MAX_NUMBER_OF_WRITER_THREADS = 15; -#else - const static int MAX_NUMBER_OF_WRITER_THREADS = 2; -#endif - - //**detector parameters*** + //*** detector parameters *** /*Detector Readout ID*/ int detID; - /** Size of 1 buffer processed at a time */ - int bufferSize; + //*** receiver parameters *** + /** Number of Threads */ + int numThreads; - /** One Packet Size including headers */ - int onePacketSize; + /** Number of Jobs */ + int numberofJobs; - /** One Packet Size without headers */ - int oneDataSize; - /** Frame Index Mask */ - uint64_t frameIndexMask; + //** class objects *** + /** General Data Properties */ + GeneralData* generalData; - /** Frame Index Offset */ - int frameIndexOffset; + /** Listener Objects that listen to UDP and push into fifo */ + std::vector listener; - /** Packet Index Mask */ - uint64_t packetIndexMask; + /** DataProcessor Objects that pull from fifo and process data */ + std::vector dataProcessor; - /** Footer offset from start of Packet*/ - int footerOffset; + /** DataStreamer Objects that stream data via ZMQ */ + std::vector dataStreamer; - /** variable to exclude missing packet */ - bool excludeMissingPackets; - - - //***File parameters*** -#ifdef MYROOT1 - /** Tree where the hits are stored */ - TTree *myTree[MAX_NUMBER_OF_WRITER_THREADS]; - - /** File where the tree is saved */ - TFile *myFile[MAX_NUMBER_OF_WRITER_THREADS]; -#endif - - /** Complete File name */ - char completeFileName[MAX_NUMBER_OF_WRITER_THREADS][MAX_STR_LENGTH]; - - /** File Name without frame index, file index and extension (_d0_f000000000000_8.raw)*/ - char fileNamePerThread[MAX_NUMBER_OF_WRITER_THREADS][MAX_STR_LENGTH]; - - /** Maximum Frames Per File **/ - uint64_t maxFramesPerFile; - const static int progressFrequency = 10; - - /** If file created successfully for all Writer Threads */ - bool fileCreateSuccess; - - /** File header */ - const static unsigned int FILE_HEADER_SIZE = 500; - char fileHeader[MAX_NUMBER_OF_WRITER_THREADS][FILE_HEADER_SIZE]; - - /** File Descriptor */ - FILE *sfilefd[MAX_NUMBER_OF_WRITER_THREADS]; -#ifdef HDF5C - DataSpace *hdf5_dataspaceId[MAX_NUMBER_OF_WRITER_THREADS]; - DataSet *hdf5_datasetId[MAX_NUMBER_OF_WRITER_THREADS]; - H5File *hdf5_fileId[MAX_NUMBER_OF_WRITER_THREADS]; - H5File* hdf5_masterFileId; - H5File* hdf5_virtualFileId; - DataType hdf5_datatype; -#endif - //***acquisition indices/count parameters*** - /** Frame Number of First Frame of an entire Acquisition (including all scans) */ - uint64_t startAcquisitionIndex; - - /** Frame index at start of each real time acquisition (eg. for each scan) */ - uint64_t startFrameIndex; - - /** Actual current frame index of each time acquisition (eg. for each scan) */ - uint64_t frameIndex[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Current Frame Number */ - uint64_t currentFrameNumber[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Previous Frame number from buffer to calculate loss */ - int64_t frameNumberInPreviousFile[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Previous Frame number from last check to calculate loss */ - int64_t frameNumberInPreviousCheck[MAX_NUMBER_OF_WRITER_THREADS]; - - /** total packet count from last check */ - int64_t totalWritingPacketCountFromLastCheck[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Pckets currently in current file, starts new file when it reaches max */ - int64_t lastFrameNumberInFile[MAX_NUMBER_OF_WRITER_THREADS]; - - /** packets in current file */ - uint64_t totalPacketsInFile[MAX_NUMBER_OF_WRITER_THREADS]; - - /**Total packet count written by each writing thread */ - uint64_t totalWritingPacketCount[MAX_NUMBER_OF_LISTENING_THREADS]; - - - /* Acquisition started */ - bool acqStarted; - - /* Measurement started - for each thread to get progress print outs*/ - bool measurementStarted[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Total packet Count listened to by listening threads */ - int totalListeningPacketCount[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Total packet Count ignored by listening threads */ - int totalIgnoredPacketCount[MAX_NUMBER_OF_LISTENING_THREADS]; - - - - - - - //***receiver parameters*** - /** Receiver Buffer */ - char *buffer[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Memory allocated */ - char *mem0[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Circular fifo to point to addresses of data listened to */ - CircularFifo* fifo[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Circular fifo to point to address already written and freed, to be reused */ - CircularFifo* fifoFree[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** UDP Sockets - Detector to Receiver */ - genericSocket* udpSocket[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Number of Jobs Per Buffer */ - int numberofJobsPerBuffer; - - /** Total fifo size */ - uint32_t fifoSize; - - /** fifo buffer header size */ - uint32_t fifoBufferHeaderSize; - - /** Dummy Packet identifier value */ - const static uint32_t dummyPacketValue = 0xFFFFFFFF; - - - - //***receiver to GUI parameters*** - /** Current Frame copied for GUI */ - char* latestData[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Pointer to file name to be sent to GUI */ - char guiFileName[MAX_NUMBER_OF_WRITER_THREADS][MAX_STR_LENGTH]; - - /** Number of packets copied to be sent to gui (others padded) */ - uint32_t guiNumPackets[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Semaphore to synchronize Writer and GuiReader threads*/ - sem_t writerGuiSemaphore[MAX_NUMBER_OF_WRITER_THREADS]; //datacompression, only first thread sends to gui - - /** Semaphore to synchronize Writer and GuiReader threads*/ - sem_t dataCallbackWriterSemaphore[MAX_NUMBER_OF_WRITER_THREADS]; //datacompression, only first thread sends to gui - - /** counter for nth frame to gui */ - int frametoGuiCounter[MAX_NUMBER_OF_WRITER_THREADS]; - - - - //***data call back thread parameters*** - /** Ensures if zmq threads created successfully */ - bool zmqThreadStarted; - - /** Number of data callback Threads */ - int numberofDataCallbackThreads; - - /** Data Callback Threads */ - pthread_t dataCallbackThreads[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Semaphores Synchronizing DataCallback Threads */ - sem_t dataCallbackSemaphore[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Mask with each bit indicating status of each data callback thread */ - volatile uint32_t dataCallbackThreadsMask; - - /** Set to self-terminate data callback threads waiting for semaphores */ - bool killAllDataCallbackThreads; - - - - //***general and listening thread parameters*** - /** Ensures if threads created successfully */ - bool threadStarted; - - /** Current Thread Index*/ - int currentThreadIndex; - - /** Number of Listening Threads */ - int numberofListeningThreads; - - /** Listening Threads */ - pthread_t listeningThreads[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Semaphores Synchronizing Listening Threads */ - sem_t listenSemaphore[MAX_NUMBER_OF_LISTENING_THREADS]; - - /** Mask with each bit indicating status of each listening thread */ - volatile uint32_t listeningThreadsMask; - - /** Set to self-terminate listening threads waiting for semaphores */ - bool killAllListeningThreads; - - - - //***writer thread parameters*** - /** Number of Writer Threads */ - int numberofWriterThreads; - - /** Writer Threads */ - pthread_t writingThreads[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Semaphores Synchronizing Writer Threads */ - sem_t writerSemaphore[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Mask with each bit indicating status of each writer thread */ - volatile uint32_t writerThreadsMask; - - /** Mask with each bit indicating file created for each writer thread*/ - volatile uint32_t createFileMask; - - /** Set to self-terminate writer threads waiting for semaphores */ - bool killAllWritingThreads; - - //***data shape *** - /** Number of pixels in x axis */ - int NX; - /** Number of pixels in y axis */ - int NY; - - int TILE_NX; - int TILE_NY; - - //***filter parameters*** - /** Common Mode Subtraction Enable FIXME: Always false, only moench uses, Ask Anna */ - bool commonModeSubtractionEnable; - - /** Moench Common Mode Subtraction */ - moenchCommonMode *moenchCommonModeSubtraction; - - /** Single Photon Detector Object for each writer thread */ - singlePhotonDetector *singlePhotonDetectorObject[MAX_NUMBER_OF_WRITER_THREADS]; - - /** Receiver Data Object for each writer thread */ - slsReceiverData *receiverData[MAX_NUMBER_OF_WRITER_THREADS]; - - - - - //***mutex*** - /** Status mutex */ - pthread_mutex_t statusMutex; - - /** Writing mutex */ - pthread_mutex_t writeMutex; - - /** GuiDataReady Mutex */ - pthread_mutex_t dataReadyMutex; - - /** Progress (currentFrameNumber) Mutex */ - pthread_mutex_t progressMutex; - - - //***callback*** - /** The action which decides what the user and default responsibilities to save data are - * 0 raw data ready callback takes care of open,close,write file - * 1 callback writes file, we have to open, close it - * 2 we open, close, write file, callback does not do anything */ - int cbAction; + /** Fifo Structure to store addresses of memory writes */ + std::vector fifo; + /** File writer implemented as binary or hdf5 filewriter */ + std::vector fileWriter; }; diff --git a/slsReceiverSoftware/include/UDPStandardImplementation_copy.h b/slsReceiverSoftware/include/UDPStandardImplementation_copy.h new file mode 100644 index 000000000..57c7fa916 --- /dev/null +++ b/slsReceiverSoftware/include/UDPStandardImplementation_copy.h @@ -0,0 +1,873 @@ +//#ifdef UDP_BASE_IMPLEMENTATION +#ifndef UDP_STANDARD_IMPLEMENTATION_H +#define UDP_STANDARD_IMPLEMENTATION_H +/********************************************//** + * @file UDPBaseImplementation.h + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + +#include "UDPBaseImplementation.h" + +#include "genericSocket.h" +#include "circularFifo.h" +#include "singlePhotonDetector.h" +#include "slsReceiverData.h" +#include "moenchCommonMode.h" + + +#ifdef MYROOT1 +#include +#include +#endif + +#include +#include +#include +#include + +#ifdef HDF5C +#include "H5Cpp.h" +#ifndef H5_NO_NAMESPACE + using namespace H5; +#endif +#endif + +/** + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + */ + + +class UDPStandardImplementationCopy: private virtual slsReceiverDefs, public UDPBaseImplementation { + public: + + + /************************************************************************* + * Constructor & Destructor ********************************************** + *************************************************************************/ + /** + * Constructor + */ + UDPStandardImplementation(); + + /** + * Destructor + */ + virtual ~UDPStandardImplementation(); + + + /************************************************************************* + * Getters *************************************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + + + /************************************************************************* + * Setters *************************************************************** + * They modify the local cache of configuration or detector parameters *** + *************************************************************************/ + + //**initial parameters*** + //*** file parameters*** + /** + * Set File Name Prefix (without frame index, file index and extension (_d0_f000000000000_8.raw)) + * Does not check for file existence since it is created only at startReceiver + * @param c file name (max of 1000 characters) + */ + void setFileName(const char c[]); + + /** + * Overridden method + * Set data compression, by saving only hits (so far implemented only for Moench and Gotthard) + * @param b true for data compression enable, else false + * @return OK or FAIL + */ + int setDataCompressionEnable(const bool b); + + //***acquisition count parameters*** + /** + * Get Total Frames Caught for an entire acquisition (including all scans) + * @return total number of frames caught for entire acquisition + */ + uint64_t getTotalFramesCaught() const; + + /** + * Get Frames Caught for each real time acquisition (eg. for each scan) + * @return number of frames caught for each scan + */ + uint64_t getFramesCaught() const; + + //***acquisition parameters*** + /** + * Overridden method + * Set Short Frame Enabled, later will be moved to getROI (so far only for gotthard) + * @param i index of adc enabled, else -1 if all enabled + */ + void setShortFrameEnable(const int i); + + /** + * Set the Frequency of Frames Sent to GUI + * @param freq 0 for random frame requests, n for nth frame frequency + * @return OK or FAIL + */ + int setFrameToGuiFrequency(const uint32_t freq); + + /** + * Set the data stream enable + * @param enable 0 to disable, 1 to enable + * @return OK or FAIL + */ + uint32_t setDataStreamEnable(const uint32_t enable); + + /** + * Overridden method + * Set Acquisition Period + * @param i acquisition period + * @return OK or FAIL + */ + int setAcquisitionPeriod(const uint64_t i); + + /** + * Set Acquisition Time + * @param i acquisition time + * @return OK or FAIL + */ + int setAcquisitionTime(const uint64_t i); + + /** + * Overridden method + * Set Number of Frames expected by receiver from detector + * The data receiver status will change from running to idle when it gets this number of frames + * @param i number of frames expected + * @return OK or FAIL + */ + int setNumberOfFrames(const uint64_t i); + + /** + * Overridden method + * Set Dynamic Range or Number of Bits Per Pixel + * @param i dynamic range that is 4, 8, 16 or 32 + * @return OK or FAIL + */ + int setDynamicRange(const uint32_t i); + + /** + * Overridden method + * Set Ten Giga Enable + * @param b true if 10Giga enabled, else false (1G enabled) + * @return OK or FAIL + */ + int setTenGigaEnable(const bool b); + + + /** + * Overridden method + * Set Fifo Depth + * @param i fifo depth value + * @return OK or FAIL + */ + int setFifoDepth(const uint32_t i); + + /************************************************************************* + * Behavioral functions*************************************************** + * They may modify the status of the receiver **************************** + *************************************************************************/ + + //***initial functions*** + /** + * Overridden method + * Set receiver type (and corresponding detector variables in derived STANDARD class) + * It is the first function called by the client when connecting to receiver + * @param d detector type + * @return OK or FAIL + */ + int setDetectorType(const detectorType d); + + //***acquisition functions*** + /** + * Overridden method + * Reset acquisition parameters such as total frames caught for an entire acquisition (including all scans) + */ + void resetAcquisitionCount(); + + /** + * Overridden method + * Start Listening for Packets by activating all configuration settings to receiver + * When this function returns, it has status RUNNING(upon SUCCESS) or IDLE (upon failure) + * @param c error message if FAIL + * @return OK or FAIL + */ + int startReceiver(char *c=NULL); + + /** + * Overridden method + * Stop Listening for Packets + * Calls startReadout(), which stops listening and sets status to Transmitting + * When it has read every frame in buffer, the status changes to Run_Finished + * When this function returns, receiver has status IDLE + * Pre: status is running, semaphores have been instantiated, + * Post: udp sockets shut down, status is idle, semaphores destroyed + */ + void stopReceiver(); + + /** + * Overridden method + * Stop Listening to Packets + * and sets status to Transmitting + * Next step would be to get all data and stop receiver completely and return with idle state + * Pre: status is running, udp sockets have been initialized, stop receiver initiated + * Post:udp sockets closed, status is transmitting + */ + void startReadout(); + + /** + * Overridden method + * Shuts down and deletes UDP Sockets + * TCPIPInterface can also call this in case of illegal shutdown of receiver + * @return OK or FAIL + */ + int shutDownUDPSockets(); + + /** + * Overridden method + * Get the buffer-current frame read by receiver + * @param ithread writer thread + * @param c pointer to current file name + * @param raw address of pointer, pointing to current frame to send to gui + * @param startAcq start index of the acquisition + * @param startFrame start index of the scan + */ + void readFrame(int ithread, char* c,char** raw, int64_t &startAcq, int64_t &startFrame); + + + void resetGuiPointer(int ithread); + /** + * Overridden method + * Closes file / all files(data compression involves multiple files) + * TCPIPInterface can also call this in case of illegal shutdown of receiver + * @param ithread writer thread index + */ + void closeFile(int ithread = 0); + + /** + * Activate / Deactivate Receiver + * If deactivated, receiver will write dummy packets 0xFF + * (as it will receive nothing from detector) + */ + int setActivate(int enable = -1); + +private: + /************************************************************************* + * Getters *************************************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + +/* + uint64_t (*getFrameNumber)(); + uint64_t eigerGetFrameNumber(); + uint64_t generalGetFrameNumber(); + getframenumber = &generalgetframenumber; + if(dettpe == eiger) getframenumber = &eigerGerFramenumber; + + call using getframenumber(); +*/ + + //**initial parameters*** + + /** + * Delete and free member parameters + */ + void deleteMembers(); + + /** + * Deletes all the filter objects for single photon data + * Deals with data compression + */ + void deleteFilter(); + + /** + * Initialize base member parameters + */ + void initializeBaseMembers(); + + /** + * Initialize member parameters + */ + void initializeMembers(); + + /** + * Sets up all the filter objects for single photon data + * Deals with data compression + */ + void initializeFilter(); + + /** + * Set up the Fifo Structure for processing buffers + * between listening and writer threads + * When the parameters ahve been determined and if fifostructure needs to be changes, + * the listerning and writing threads are also destroyed together with this + * @return OK or FAIL + */ + int setupFifoStructure(); + + + + /************************************************************************* + * Listening and Writing Threads ***************************************** + *************************************************************************/ + /** + * Create Data Call Back Threads + * @param destroy is true to destroy all the threads + * @return OK or FAIL + */ + int createDataCallbackThreads(bool destroy = false); + + /** + * Create Listening Threads + * @param destroy is true to destroy all the threads + */ + int createListeningThreads(bool destroy = false); + + /** + * Create Writer Threads + * @param destroy is true to destroy all the threads + * @return OK or FAIL + */ + int createWriterThreads(bool destroy = false); + + + + + /** + * Set Thread Priorities + */ + void setThreadPriorities(); + + /** + * Creates UDP Sockets + * @return OK or FAIL + */ + int createUDPSockets(); + + /** + * Initializes writer variables and creates the first file + * also does the startAcquisitionCallBack + * @return OK or FAIL + */ + int setupWriter(); + + /** + * Creates new file and reset some parameters + * @param ithread writer thread index + * @return OK or FAIL + */ + int createNewFile(int ithread); + + /** + * Creates new tree and file for compression + * @param ithread thread number + * @param iframe frame number + * @return OK or FAIL + */ + int createCompressionFile(int ithread, int iframe); + + /** + * Static function - Starts Data Callback Thread of this object + * @param this_pointer pointer to this object + */ + static void* startDataCallbackThread(void *this_pointer); + + /** + * Static function - Starts Listening Thread of this object + * @param this_pointer pointer to this object + */ + static void* startListeningThread(void *this_pointer); + + /** + * Static function - Starts Writing Thread of this object + * @param this_pointer pointer to this object + */ + static void* startWritingThread(void *this_pointer); + + /** + * Thread that sends data packets to client + */ + void startDataCallback(); + + /** + * Thread that listens to packets + * It pops the fifofree for free addresses, listens to packets and pushes them into the fifo + * This is continuously looped for each buffer in a nested loop, which is again looped for each acquisition + * Exits only for changing dynamic range, 10G parameters etc and recreated + * + */ + void startListening(); + + /** + * Called by startListening + * Listens to buffer, until packet(s) received or shutdownUDPsocket called by client + * Also copies carryovers from previous frame in front of buffer (gotthard and moench) + * For eiger, it ignores packets less than onePacketSize + * @param ithread listening thread index + * @param cSize number of bytes carried on from previous buffer + * @param temp temporary storage of previous buffer + * @return the number of bytes actually received + */ + int prepareAndListenBuffer(int ithread, int cSize, char* temp); + + /** + * Called by startListening + * Creates the packets + * @param ithread listening thread index + * @return the number of bytes actually received + */ + int prepareAndListenBufferDeactivated(int ithread); + + + /** + * Called by startListening + * Listens to each packet and copies only complete frames + * until all receiver or shutdownUDPsocket called by client + * @param ithread listening thread index + * @return the number of bytes copied to buffer + */ + int prepareAndListenBufferCompleteFrames(int ithread); + + /** + * Called by startListening + * Its called for the first packet of a scan or acquistion + * Sets the startframeindices and the variables to know if acquisition started + * @param ithread listening thread number + */ + void startFrameIndices(int ithread); + + /** + * Called by prepareAndListenBuffer + * This is called when udp socket is shut down by client + * It pushes ffff instead of packet number into fifo + * to inform writers about the end of listening session + * Then sets the listening mask so that it stops listening and wait for next acquisition trigger + * @param ithread listening thread number + * @param numbytes number of bytes received + */ + void stopListening(int ithread, int numbytes); + + /* + * Called by startListening for gotthard and moench to handle split frames + * It processes listening thread buffers by ensuring split frames are in the same buffer + * @param ithread listening thread index + * @param cSize number of bytes carried over to the next buffer to reunite with split frame + * @param temp temporary buffer to store the split frame + * @param rc number of bytes received + * @return packet count + */ + uint32_t processListeningBuffer(int ithread, int &cSize,char* temp, int rc); + + /** + * Thread started which writes packets to file. + * It calls popAndCheckEndofAcquisition to pop fifo and check if it is a dummy end buffer + * It then calls a function to process and write packets to file and pushes the addresses into the fifoFree + * This is continuously looped for each buffer in a nested loop, which is again looped for each acquisition + * Exits only for changing dynamic range, 10G parameters etc and recreated + * + */ + void startWriting(); + + /** + * Called by processWritingBuffer and processWritingBufferPacketByPacket + * When dummy-end buffers are popped from all FIFOs (acquisition over), this is called + * It frees the FIFO addresses, closes all files + * For data compression, it waits for all threads to be done + * Changes the status to RUN_FINISHED and prints statistics + * @param ithread writing thread index + * @param wbuffer writing buffer popped out from FIFO + */ + void stopWriting(int ithread, char* wbuffer); + + /** + * Called by processWritingBuffer and processWritingBufferPacketByPacket + * Updates parameters, (writes headers for eiger) and writes to file when not a dummy frame + * Copies data for gui display and frees addresses popped from FIFOs + * @param ithread writing thread index + * @param wbuffer writing buffer popped out from FIFO + * @param npackets number of packets + */ + void handleWithoutDataCompression(int ithread, char* wbuffer,uint32_t npackets); + + /** + * Called by startWriting for jungfrau and eiger + * writes complete frames to file + * Copies data for gui display and frees addresses popped from FIFOs + * @param ithread writing thread index + * @param wbuffer writing buffer popped out from FIFO + */ + void handleCompleteFramesOnly(int ithread, char* wbuffer); + + /** + * Calle by handleWithoutDataCompression + * Creating headers Writing to file without compression + * @param ithread writer thread index + * @param wbuffer is the address of buffer popped out of FIFO + * @param numpackets is the number of packets + */ + void writeFileWithoutCompression(int ithread, char* wbuffer,uint32_t numpackets); + + /** + * Called by writeToFileWithoutCompression + * Create headers for file writing (at the moment, this is eiger specific) + * @param wbuffer writing buffer popped from FIFOs + */ + void createHeaders(char* wbuffer); + + /** + * Updates the file header char aray, each time the corresp parameter is changed + * @param ithread writer thread index + */ + void updateFileHeader(int ithread); + + /** + * Called by handleWithoutDataCompression and handleWithCompression after writing to file + * Copy frames for GUI and updates appropriate parameters for frequency frames to gui + * Uses semaphore for nth frame mode + * @param ithread writer thread index + * @param buffer buffer to copy + * @param numpackets number of packets to copy + */ + void copyFrameToGui(int ithread, char* buffer, uint32_t numpackets); + + void waitWritingBufferForNextAcquisition(int ithread); + + /** + * Called by processWritingBuffer + * Processing fifo popped buffers for data compression + * Updates parameters and writes to file + * Copies data for gui display and frees addresses popped from FIFOs + * @param ithread writing thread number + * @param wbuffer writer buffer + * @param nf number of frames + */ + void handleDataCompression(int ithread, char* wbuffer, uint64_t &nf); + + + /** + * Get Frame Number + * @param ithread writer thread index + * @param wbuffer writer buffer + * @param framenumber reference to the frame number + * @param packetnumber reference to the packet number + * @param subframenumber reference to the subframe number + * @oaram bunchid reference to the bunch id + * @return OK or FAIL + */ + int getFrameandPacketNumber(int ithread, char* wbuffer, uint64_t &framenumber, uint32_t &packetnumber, uint32_t &subframenumber, uint64_t &bunchid); + + /** + * Find offset upto this frame number and write it to file + * @param ithread writer thread index + * @param wbuffer writer buffer + * @param offset reference of offset to look from and replaces offset to starting of nextframenumber + * @param nextFrameNumber frame number up to which data written + * @param numpackets number of packets in buffer + * @param numPacketsWritten number of packets written to file + */ + int writeUptoFrameNumber(int ithread, char* wbuffer, int &offset, uint64_t nextFrameNumber, uint32_t numpackets, int &numPacketsWritten); + + /** function that returns the name variable from the receiver complete file name prefix + @param fname complete file name prefix + @returns file name + */ + string getNameFromReceiverFilePrefix(string fname); + + /************************************************************************* + * Class Members ********************************************************* + *************************************************************************/ + + /** Maximum Number of Writer Threads */ + +#ifdef DCOMPRESS + /**** most likely not used ***/ + const static int MAX_NUMBER_OF_WRITER_THREADS = 15; +#else + const static int MAX_NUMBER_OF_WRITER_THREADS = 2; +#endif + + //**detector parameters*** + /*Detector Readout ID*/ + int detID; + + /** Size of 1 buffer processed at a time */ + int bufferSize; + + /** One Packet Size including headers */ + int onePacketSize; + + /** One Packet Size without headers */ + int oneDataSize; + + /** Frame Index Mask */ + uint64_t frameIndexMask; + + /** Frame Index Offset */ + int frameIndexOffset; + + /** Packet Index Mask */ + uint64_t packetIndexMask; + + /** Footer offset from start of Packet*/ + int footerOffset; + + /** variable to exclude missing packet */ + bool excludeMissingPackets; + + + //***File parameters*** +#ifdef MYROOT1 + /** Tree where the hits are stored */ + TTree *myTree[MAX_NUMBER_OF_WRITER_THREADS]; + + /** File where the tree is saved */ + TFile *myFile[MAX_NUMBER_OF_WRITER_THREADS]; +#endif + + /** Complete File name */ + char completeFileName[MAX_NUMBER_OF_WRITER_THREADS][MAX_STR_LENGTH]; + + /** File Name without frame index, file index and extension (_d0_f000000000000_8.raw)*/ + char fileNamePerThread[MAX_NUMBER_OF_WRITER_THREADS][MAX_STR_LENGTH]; + + /** Maximum Frames Per File **/ + uint64_t maxFramesPerFile; + const static int progressFrequency = 10; + + /** If file created successfully for all Writer Threads */ + bool fileCreateSuccess; + + /** File header */ + const static unsigned int FILE_HEADER_SIZE = 500; + char fileHeader[MAX_NUMBER_OF_WRITER_THREADS][FILE_HEADER_SIZE]; + + /** File Descriptor */ + FILE *sfilefd[MAX_NUMBER_OF_WRITER_THREADS]; +#ifdef HDF5C + DataSpace *hdf5_dataspaceId[MAX_NUMBER_OF_WRITER_THREADS]; + DataSet *hdf5_datasetId[MAX_NUMBER_OF_WRITER_THREADS]; + H5File *hdf5_fileId[MAX_NUMBER_OF_WRITER_THREADS]; + H5File* hdf5_masterFileId; + H5File* hdf5_virtualFileId; + DataType hdf5_datatype; +#endif + //***acquisition indices/count parameters*** + /** Frame Number of First Frame of an entire Acquisition (including all scans) */ + uint64_t startAcquisitionIndex; + + /** Frame index at start of each real time acquisition (eg. for each scan) */ + uint64_t startFrameIndex; + + /** Actual current frame index of each time acquisition (eg. for each scan) */ + uint64_t frameIndex[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Current Frame Number */ + uint64_t currentFrameNumber[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Previous Frame number from buffer to calculate loss */ + int64_t frameNumberInPreviousFile[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Previous Frame number from last check to calculate loss */ + int64_t frameNumberInPreviousCheck[MAX_NUMBER_OF_WRITER_THREADS]; + + /** total packet count from last check */ + int64_t totalWritingPacketCountFromLastCheck[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Pckets currently in current file, starts new file when it reaches max */ + int64_t lastFrameNumberInFile[MAX_NUMBER_OF_WRITER_THREADS]; + + /** packets in current file */ + uint64_t totalPacketsInFile[MAX_NUMBER_OF_WRITER_THREADS]; + + /**Total packet count written by each writing thread */ + uint64_t totalWritingPacketCount[MAX_NUMBER_OF_LISTENING_THREADS]; + + + /* Acquisition started */ + bool acqStarted; + + /* Measurement started - for each thread to get progress print outs*/ + bool measurementStarted[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Total packet Count listened to by listening threads */ + int totalListeningPacketCount[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Total packet Count ignored by listening threads */ + int totalIgnoredPacketCount[MAX_NUMBER_OF_LISTENING_THREADS]; + + + + + + + //***receiver parameters*** + /** Receiver Buffer */ + char *buffer[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Memory allocated */ + char *mem0[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Circular fifo to point to addresses of data listened to */ + CircularFifo* fifo[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Circular fifo to point to address already written and freed, to be reused */ + CircularFifo* fifoFree[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** UDP Sockets - Detector to Receiver */ + genericSocket* udpSocket[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Number of Jobs Per Buffer */ + int numberofJobsPerBuffer; + + /** Total fifo size */ + uint32_t fifoSize; + + /** fifo buffer header size */ + uint32_t fifoBufferHeaderSize; + + /** Dummy Packet identifier value */ + const static uint32_t dummyPacketValue = 0xFFFFFFFF; + + + + //***receiver to GUI parameters*** + /** Current Frame copied for GUI */ + char* latestData[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Pointer to file name to be sent to GUI */ + char guiFileName[MAX_NUMBER_OF_WRITER_THREADS][MAX_STR_LENGTH]; + + /** Number of packets copied to be sent to gui (others padded) */ + uint32_t guiNumPackets[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Semaphore to synchronize Writer and GuiReader threads*/ + sem_t writerGuiSemaphore[MAX_NUMBER_OF_WRITER_THREADS]; //datacompression, only first thread sends to gui + + /** Semaphore to synchronize Writer and GuiReader threads*/ + sem_t dataCallbackWriterSemaphore[MAX_NUMBER_OF_WRITER_THREADS]; //datacompression, only first thread sends to gui + + /** counter for nth frame to gui */ + int frametoGuiCounter[MAX_NUMBER_OF_WRITER_THREADS]; + + + + //***data call back thread parameters*** + /** Ensures if zmq threads created successfully */ + bool zmqThreadStarted; + + /** Number of data callback Threads */ + int numberofDataCallbackThreads; + + /** Data Callback Threads */ + pthread_t dataCallbackThreads[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Semaphores Synchronizing DataCallback Threads */ + sem_t dataCallbackSemaphore[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Mask with each bit indicating status of each data callback thread */ + volatile uint32_t dataCallbackThreadsMask; + + /** Set to self-terminate data callback threads waiting for semaphores */ + bool killAllDataCallbackThreads; + + + + //***general and listening thread parameters*** + /** Ensures if threads created successfully */ + bool threadStarted; + + /** Current Thread Index*/ + int currentThreadIndex; + + /** Number of Listening Threads */ + int numberofListeningThreads; + + /** Listening Threads */ + pthread_t listeningThreads[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Semaphores Synchronizing Listening Threads */ + sem_t listenSemaphore[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Mask with each bit indicating status of each listening thread */ + volatile uint32_t listeningThreadsMask; + + /** Set to self-terminate listening threads waiting for semaphores */ + bool killAllListeningThreads; + + + + //***writer thread parameters*** + /** Number of Writer Threads */ + int numberofWriterThreads; + + /** Writer Threads */ + pthread_t writingThreads[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Semaphores Synchronizing Writer Threads */ + sem_t writerSemaphore[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Mask with each bit indicating status of each writer thread */ + volatile uint32_t writerThreadsMask; + + /** Mask with each bit indicating file created for each writer thread*/ + volatile uint32_t createFileMask; + + /** Set to self-terminate writer threads waiting for semaphores */ + bool killAllWritingThreads; + + //***data shape *** + /** Number of pixels in x axis */ + int NX; + /** Number of pixels in y axis */ + int NY; + + int TILE_NX; + int TILE_NY; + + //***filter parameters*** + /** Common Mode Subtraction Enable FIXME: Always false, only moench uses, Ask Anna */ + bool commonModeSubtractionEnable; + + /** Moench Common Mode Subtraction */ + moenchCommonMode *moenchCommonModeSubtraction; + + /** Single Photon Detector Object for each writer thread */ + singlePhotonDetector *singlePhotonDetectorObject[MAX_NUMBER_OF_WRITER_THREADS]; + + /** Receiver Data Object for each writer thread */ + slsReceiverData *receiverData[MAX_NUMBER_OF_WRITER_THREADS]; + + + + + //***mutex*** + /** Status mutex */ + pthread_mutex_t statusMutex; + + /** Writing mutex */ + pthread_mutex_t writeMutex; + + /** GuiDataReady Mutex */ + pthread_mutex_t dataReadyMutex; + + /** Progress (currentFrameNumber) Mutex */ + pthread_mutex_t progressMutex; + + + //***callback*** + /** The action which decides what the user and default responsibilities to save data are + * 0 raw data ready callback takes care of open,close,write file + * 1 callback writes file, we have to open, close it + * 2 we open, close, write file, callback does not do anything */ + int cbAction; + +}; + + +#endif + +//#endif diff --git a/slsReceiverSoftware/include/logger.h b/slsReceiverSoftware/include/logger.h index a91dea9f4..b27e5cf48 100644 --- a/slsReceiverSoftware/include/logger.h +++ b/slsReceiverSoftware/include/logger.h @@ -1,5 +1,5 @@ -//#ifndef __LOG_H__ -//#define __LOG_H__ +#ifndef __LOG_H__ +#define __LOG_H__ #include #include @@ -243,4 +243,4 @@ inline void Output2FILE::Output(const std::string& msg, TLogLevel level) -//#endif //__LOG_H__ +#endif //__LOG_H__ diff --git a/slsReceiverSoftware/include/receiver_defs.h b/slsReceiverSoftware/include/receiver_defs.h index 7162fcc9f..f4a9dee04 100755 --- a/slsReceiverSoftware/include/receiver_defs.h +++ b/slsReceiverSoftware/include/receiver_defs.h @@ -5,6 +5,144 @@ #include +#define GOODBYE -200 + +//local network parameters +#define RECEIVE_SOCKET_BUFFER_SIZE (100*1024*1024) +#define MAX_SOCKET_INPUT_PACKET_QUEUE 250000 + +//files +#define DO_NOTHING 0 +#define CREATE_FILES 1 +#define DO_EVERYTHING 2 + +//binary +#define FILE_BUF_SIZE (16*1024*1024) //16mb +#define FILE_FRAME_HEADER_LENGTH 16 +#define FILE_HEADER_BUNCHID_OFFSET 8 + +//hdf5 +#ifdef HDF5C +#define HDF5_WRITER_VERSION 1.0 +#define MAX_CHUNKED_IMAGES 1 +#define MAX_IMAGES_IN_DATASET 1000 +#endif + + +#define HEADER_SIZE_NUM_TOT_PACKETS 4 +#define SAMPLE_TIME_IN_NS 100000000//100ms +#define MAX_JOBS_PER_THREAD 1000 +#define ALL_MASK_32 0xFFFFFFFF + + + +//gottard +#define GOTTHARD_FIFO_SIZE 25000 //cannot be less than max jobs per thread = 1000 +#define GOTTHARD_PIXELS_IN_ROW 1280 +#define GOTTHARD_PIXELS_IN_COL 1 +#define GOTTHARD_PACKETS_PER_FRAME 2 +#define GOTTHARD_ONE_PACKET_SIZE 1286 +#define GOTTHARD_ONE_DATA_SIZE 1280 +#define GOTTHARD_BUFFER_SIZE (GOTTHARD_ONE_PACKET_SIZE*GOTTHARD_PACKETS_PER_FRAME) //1286*2 +#define GOTTHARD_DATA_BYTES (GOTTHARD_ONE_DATA_SIZE*GOTTHARD_PACKETS_PER_FRAME) //1280*2 +#define GOTTHARD_FRAME_INDEX_MASK 0xFFFFFFFE +#define GOTTHARD_FRAME_INDEX_OFFSET 1 +#define GOTTHARD_PACKET_INDEX_MASK 0x1 + + +//short gotthard +#define GOTTHARD_SHORT_PIXELS_IN_ROW 256 +#define GOTTHARD_SHORT_PIXELS_IN_COL 1 +#define GOTTHARD_SHORT_PACKETS_PER_FRAME 1 +#define GOTTHARD_SHORT_ONE_PACKET_SIZE 518 +#define GOTTHARD_SHORT_ONE_DATA_SIZE 512 +#define GOTTHARD_SHORT_BUFFER_SIZE (GOTTHARD_SHORT_ONE_PACKET_SIZE*GOTTHARD_SHORT_PACKETS_PER_FRAME)//518*1 +#define GOTTHARD_SHORT_DATABYTES (GOTTHARD_SHORT_ONE_DATA_SIZE*GOTTHARD_SHORT_PACKETS_PER_FRAME) //512*1 +#define GOTTHARD_SHORT_FRAME_INDEX_MASK 0xFFFFFFFF +#define GOTTHARD_SHORT_FRAME_INDEX_OFFSET 0 +#define GOTTHARD_SHORT_PACKET_INDEX_MASK 0 + + +//propix +#define PROPIX_FIFO_SIZE 25000 //cannot be less than max jobs per thread = 1000 +#define PROPIX_PIXELS_IN_ROW 22 +#define PROPIX_PIXELS_IN_COL 22 +#define PROPIX_PACKETS_PER_FRAME 2 +#define PROPIX_ONE_PACKET_SIZE 1286 +#define PROPIX_ONE_DATA_SIZE 1280 +#define PROPIX_BUFFER_SIZE (PROPIX_ONE_PACKET_SIZE*PROPIX_PACKETS_PER_FRAME) //1286*2 +#define PROPIX_DATABYTES_PER_PIXEL 2 +//#define PROPIX_DATA_BYTES (1280*PROPIX_PACKETS_PER_FRAME) //1280*2 +#define PROPIX_DATA_BYTES (PROPIX_PIXELS_IN_ROW * PROPIX_PIXELS_IN_COL * PROPIX_DATABYTES_PER_PIXEL) //22 * 22 * 2 +#define PROPIX_FRAME_INDEX_MASK 0xFFFFFFFE +#define PROPIX_FRAME_INDEX_OFFSET 1 +#define PROPIX_PACKET_INDEX_MASK 0x1 + + +//moench +#define MOENCH_FIFO_SIZE 2500 //cannot be less than max jobs per thread = 1000 +#define MOENCH_BYTES_IN_ONE_ROW (MOENCH_PIXELS_IN_ONE_ROW*2) +#define MOENCH_BYTES_PER_ADC (40*2) +#define MOENCH_PIXELS_IN_ONE_ROW 160 +#define MOENCH_PACKETS_PER_FRAME 40 +#define MOENCH_ONE_PACKET_SIZE 1286 +#define MOENCH_ONE_DATA_SIZE 1280 +#define MOENCH_BUFFER_SIZE (MOENCH_ONE_PACKET_SIZE*MOENCH_PACKETS_PER_FRAME) //1286*40 +#define MOENCH_DATA_BYTES (MOENCH_ONE_DATA_SIZE*MOENCH_PACKETS_PER_FRAME) //1280*40 +#define MOENCH_FRAME_INDEX_MASK 0xFFFFFF00 +#define MOENCH_FRAME_INDEX_OFFSET 8 +#define MOENCH_PACKET_INDEX_MASK 0xFF + + +//jungfrau +#define JFRAU_FIFO_SIZE 2500 +#define JFRAU_PIXELS_IN_ONE_ROW (256*4) +#define JFRAU_PIXELS_IN_ONE_COL (256) +#define JFRAU_BYTES_IN_ONE_ROW (JFRAU_PIXELS_IN_ONE_ROW*2) +#define JFRAU_PACKETS_PER_FRAME 128 +#define JFRAU_HEADER_LENGTH 22 +#define JFRAU_ONE_DATA_SIZE 8192 +#define JFRAU_ONE_PACKET_SIZE (JFRAU_HEADER_LENGTH+JFRAU_ONE_DATA_SIZE) //8214 +#define JFRAU_BUFFER_SIZE (JFRAU_ONE_PACKET_SIZE*JFRAU_PACKETS_PER_FRAME) //8214*128 +#define JFRAU_DATA_BYTES (JFRAU_ONE_DATA_SIZE*JFRAU_PACKETS_PER_FRAME) //8192*128 +#define JFRAU_FRAME_INDEX_MASK 0xffffff //mask after using struct (48 bit) +#define JFRAU_FRAME_INDEX_OFFSET 0x0 //Not Applicable, use struct +#define JFRAU_PACKET_INDEX_MASK 0x0 //Not Applicable, use struct + + +//jungrau chip test board +#define JCTB_FIFO_SIZE 2500 +#define JCTB_PIXELS_IN_ONE_ROW 32 +#define JCTB_BYTES_IN_ONE_ROW (JCTB_PIXELS_IN_ONE_ROW*2) +#define JCTB_BYTES_PER_ADC (2) +#define JCTB_PACKETS_PER_FRAME 1 +#define JCTB_ONE_PACKET_SIZE 8224 +#define JCTB_BUFFER_SIZE (JCTB_ONE_PACKET_SIZE*40) +#define JCTB_DATA_BYTES (8192*JCTB_PACKETS_PER_FRAME) +#define JCTB_FRAME_INDEX_MASK 0xFFFFFFFF +#define JCTB_FRAME_INDEX_OFFSET 6+8 +#define JCTB_PACKET_INDEX_MASK 0xFFFFFFFF + + +//eiger +#define EIGER_FIFO_SIZE 100 +#define EIGER_PIXELS_IN_ONE_ROW (256*2) +#define EIGER_PIXELS_IN_ONE_COL (256) +#define EIGER_PORTS_PER_READOUT 2 +#define EIGER_HEADER_PACKET_LENGTH 48 +#define EIGER_ONE_GIGA_CONSTANT 16 +#define EIGER_TEN_GIGA_CONSTANT 4 +#define EIGER_ONE_GIGA_ONE_PACKET_SIZE 1040 +#define EIGER_ONE_GIGA_ONE_DATA_SIZE 1024 +#define EIGER_TEN_GIGA_ONE_PACKET_SIZE 4112 +#define EIGER_TEN_GIGA_ONE_DATA_SIZE 4096 +#define EIGER_DATA_PACKET_HEADER_SIZE 8 +#define EIGER_FRAME_INDEX_MASK 0xFFFFFFFF //32 bit for now +#define EIGER_FRAME_INDEX_OFFSET 0 +#define EIGER_PACKET_INDEX_MASK 0x0 + + +//data structures /** * structure of an eiger packet header * subframenum subframe number for 32 bit mode (already written by firmware) @@ -43,127 +181,4 @@ typedef struct { unsigned char bunchid[8]; } jfrau_packet_header_t; - -#define HDF5_WRITER_VERSION 1.0 - -#define GOODBYE -200 -#define DO_NOTHING 0 -#define CREATE_FILES 1 -#define DO_EVERYTHING 2 - -#define HEADER_SIZE_NUM_TOT_PACKETS 4 -#define SAMPLE_TIME_IN_NS 100000000//100ms -#define MAX_JOBS_PER_THREAD 1000 -#define ALL_MASK_32 0xFFFFFFFF - -//binary file size and file header -#define FILE_BUF_SIZE (16*1024*1024) //16mb -#define FILE_FRAME_HEADER_LENGTH 16 -#define FILE_HEADER_BUNCHID_OFFSET 8 - -//HDF5 -#define MAX_CHUNKED_IMAGES 1 -#define MAX_IMAGES_IN_DATASET 1000 - -//all max frames per file defined in sls_receiver_defs.h - - -#define GOTTHARD_FIFO_SIZE 25000 //cannot be less than max jobs per thread = 1000 -#define GOTTHARD_PIXELS_IN_ROW 1280 -#define GOTTHARD_PIXELS_IN_COL 1 -#define GOTTHARD_PACKETS_PER_FRAME 2 -#define GOTTHARD_ONE_PACKET_SIZE 1286 -#define GOTTHARD_ONE_DATA_SIZE 1280 -#define GOTTHARD_BUFFER_SIZE (GOTTHARD_ONE_PACKET_SIZE*GOTTHARD_PACKETS_PER_FRAME) //1286*2 -#define GOTTHARD_DATA_BYTES (GOTTHARD_ONE_DATA_SIZE*GOTTHARD_PACKETS_PER_FRAME) //1280*2 -#define GOTTHARD_FRAME_INDEX_MASK 0xFFFFFFFE -#define GOTTHARD_FRAME_INDEX_OFFSET 1 -#define GOTTHARD_PACKET_INDEX_MASK 0x1 -//short -#define GOTTHARD_SHORT_PIXELS_IN_ROW 256 -#define GOTTHARD_SHORT_PIXELS_IN_COL 1 -#define GOTTHARD_SHORT_PACKETS_PER_FRAME 1 -#define GOTTHARD_SHORT_ONE_PACKET_SIZE 518 -#define GOTTHARD_SHORT_ONE_DATA_SIZE 512 -#define GOTTHARD_SHORT_BUFFER_SIZE (GOTTHARD_SHORT_ONE_PACKET_SIZE*GOTTHARD_SHORT_PACKETS_PER_FRAME)//518*1 -#define GOTTHARD_SHORT_DATABYTES (GOTTHARD_SHORT_ONE_DATA_SIZE*GOTTHARD_SHORT_PACKETS_PER_FRAME) //512*1 -#define GOTTHARD_SHORT_FRAME_INDEX_MASK 0xFFFFFFFF -#define GOTTHARD_SHORT_FRAME_INDEX_OFFSET 0 -#define GOTTHARD_SHORT_PACKET_INDEX_MASK 0 - - -#define PROPIX_FIFO_SIZE 25000 //cannot be less than max jobs per thread = 1000 -#define PROPIX_PIXELS_IN_ROW 22 -#define PROPIX_PIXELS_IN_COL 22 -#define PROPIX_PACKETS_PER_FRAME 2 -#define PROPIX_ONE_PACKET_SIZE 1286 -#define PROPIX_ONE_DATA_SIZE 1280 -#define PROPIX_BUFFER_SIZE (PROPIX_ONE_PACKET_SIZE*PROPIX_PACKETS_PER_FRAME) //1286*2 -#define PROPIX_DATABYTES_PER_PIXEL 2 -//#define PROPIX_DATA_BYTES (1280*PROPIX_PACKETS_PER_FRAME) //1280*2 -#define PROPIX_DATA_BYTES (PROPIX_PIXELS_IN_ROW * PROPIX_PIXELS_IN_COL * PROPIX_DATABYTES_PER_PIXEL) //22 * 22 * 2 -#define PROPIX_FRAME_INDEX_MASK 0xFFFFFFFE -#define PROPIX_FRAME_INDEX_OFFSET 1 -#define PROPIX_PACKET_INDEX_MASK 0x1 - - -#define MOENCH_FIFO_SIZE 2500 //cannot be less than max jobs per thread = 1000 -#define MOENCH_BYTES_IN_ONE_ROW (MOENCH_PIXELS_IN_ONE_ROW*2) -#define MOENCH_BYTES_PER_ADC (40*2) -#define MOENCH_PIXELS_IN_ONE_ROW 160 -#define MOENCH_PACKETS_PER_FRAME 40 -#define MOENCH_ONE_PACKET_SIZE 1286 -#define MOENCH_ONE_DATA_SIZE 1280 -#define MOENCH_BUFFER_SIZE (MOENCH_ONE_PACKET_SIZE*MOENCH_PACKETS_PER_FRAME) //1286*40 -#define MOENCH_DATA_BYTES (MOENCH_ONE_DATA_SIZE*MOENCH_PACKETS_PER_FRAME) //1280*40 -#define MOENCH_FRAME_INDEX_MASK 0xFFFFFF00 -#define MOENCH_FRAME_INDEX_OFFSET 8 -#define MOENCH_PACKET_INDEX_MASK 0xFF - - -#define JFRAU_FIFO_SIZE 2500 //cannot be less than max jobs per thread = 1000 -#define JFRAU_PIXELS_IN_ONE_ROW (256*4) -#define JFRAU_PIXELS_IN_ONE_COL (256) -#define JFRAU_BYTES_IN_ONE_ROW (JFRAU_PIXELS_IN_ONE_ROW*2) -#define JFRAU_PACKETS_PER_FRAME 128 -#define JFRAU_HEADER_LENGTH 22 -#define JFRAU_ONE_DATA_SIZE 8192 -#define JFRAU_ONE_PACKET_SIZE (JFRAU_HEADER_LENGTH+JFRAU_ONE_DATA_SIZE) //8214 -#define JFRAU_BUFFER_SIZE (JFRAU_ONE_PACKET_SIZE*JFRAU_PACKETS_PER_FRAME) //8214*128 -#define JFRAU_DATA_BYTES (JFRAU_ONE_DATA_SIZE*JFRAU_PACKETS_PER_FRAME) //8192*128 -#define JFRAU_FRAME_INDEX_MASK 0xffffff //mask after using struct (48 bit) -#define JFRAU_FRAME_INDEX_OFFSET 0x0 //Not Applicable, use struct -#define JFRAU_PACKET_INDEX_MASK 0x0 //Not Applicable, use struct - - -#define JCTB_FIFO_SIZE 2500 //cannot be less than max jobs per thread = 1000 -#define JCTB_PIXELS_IN_ONE_ROW 32 -#define JCTB_BYTES_IN_ONE_ROW (JCTB_PIXELS_IN_ONE_ROW*2) -#define JCTB_BYTES_PER_ADC (2) -#define JCTB_PACKETS_PER_FRAME 1 -#define JCTB_ONE_PACKET_SIZE 8224 -#define JCTB_BUFFER_SIZE (JCTB_ONE_PACKET_SIZE*40) -#define JCTB_DATA_BYTES (8192*JCTB_PACKETS_PER_FRAME) -#define JCTB_FRAME_INDEX_MASK 0xFFFFFFFF -#define JCTB_FRAME_INDEX_OFFSET 6+8 -#define JCTB_PACKET_INDEX_MASK 0xFFFFFFFF - - -#define EIGER_FIFO_SIZE 100 -#define EIGER_PIXELS_IN_ONE_ROW (256*2) -#define EIGER_PIXELS_IN_ONE_COL (256) -#define EIGER_MAX_PORTS 2 -#define EIGER_HEADER_PACKET_LENGTH 48 -#define EIGER_ONE_GIGA_CONSTANT 16 -#define EIGER_TEN_GIGA_CONSTANT 4 -#define EIGER_ONE_GIGA_ONE_PACKET_SIZE 1040 -#define EIGER_ONE_GIGA_ONE_DATA_SIZE 1024 -#define EIGER_TEN_GIGA_ONE_PACKET_SIZE 4112 -#define EIGER_TEN_GIGA_ONE_DATA_SIZE 4096 -#define EIGER_DATA_PACKET_HEADER_SIZE 8 -#define EIGER_FRAME_INDEX_MASK 0xFFFFFFFF //32 bit for now -#define EIGER_FRAME_INDEX_OFFSET 0 -#define EIGER_PACKET_INDEX_MASK 0x0 - - #endif diff --git a/slsReceiverSoftware/src/BinaryFileWriter.cpp b/slsReceiverSoftware/src/BinaryFileWriter.cpp new file mode 100644 index 000000000..777658079 --- /dev/null +++ b/slsReceiverSoftware/src/BinaryFileWriter.cpp @@ -0,0 +1,22 @@ +/************************************************ + * @file BinaryFileWriter.h + * @short sets/gets properties for the binary file, + * creates/closes the file and writes data to it + ***********************************************/ + +#include "BinaryFileWriter.h" + +#include +using namespace std; + + +BinaryFileWriter::BinaryFileWriter(char* fname): + FileWriter(fname) { + +} + + +BinaryFileWriter::~BinaryFileWriter() { + +} + diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp new file mode 100644 index 000000000..c45b5c762 --- /dev/null +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -0,0 +1,112 @@ +/************************************************ + * @file DataProcessor.h + * @short creates data processor thread that + * pulls pointers to memory addresses from fifos + * and processes data stored in them & writes them to file + ***********************************************/ + + +#include "DataProcessor.h" +#include "Fifo.h" + +#include +#include +using namespace std; + +const string DataProcessor::TypeName = "DataProcessor"; + +int DataProcessor::NumberofDataProcessors(0); + +uint64_t DataProcessor::ErrorMask(0x0); + +uint64_t DataProcessor::RunningMask(0x0); + +pthread_mutex_t DataProcessor::Mutex = PTHREAD_MUTEX_INITIALIZER; + + +DataProcessor::DataProcessor(Fifo*& f) : ThreadObject(NumberofDataProcessors), fifo(f) { + FILE_LOG(logDEBUG) << __AT__ << " called"; + + if(ThreadObject::CreateThread()){ + pthread_mutex_lock(&Mutex); + ErrorMask ^= (1<PopAddress(buffer); +#ifdef FIFODEBUG + cprintf(BLUE,"DataProcessor %d, pop 0x%p buffer:%s\n", index,(void*)(buffer),buffer); +#endif + + if(!strcmp(buffer,"done")){ + StopRunning(); + } + fifo->FreeAddress(buffer); +} diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp new file mode 100644 index 000000000..aecfa227a --- /dev/null +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -0,0 +1,94 @@ +/************************************************ + * @file DataStreamer.h + * @short streams data from receiver via ZMQ + ***********************************************/ + + +#include "DataStreamer.h" + +#include +using namespace std; + +const string DataStreamer::TypeName = "DataStreamer"; + +int DataStreamer::NumberofDataStreamers(0); + +uint64_t DataStreamer::ErrorMask(0x0); + +uint64_t DataStreamer::RunningMask(0x0); + +pthread_mutex_t DataStreamer::Mutex = PTHREAD_MUTEX_INITIALIZER; + + +DataStreamer::DataStreamer() : ThreadObject(NumberofDataStreamers) { + FILE_LOG(logDEBUG) << __AT__ << " called"; + + if(ThreadObject::CreateThread()){ + pthread_mutex_lock(&Mutex); + ErrorMask ^= (1< +#include +using namespace std; + +int Fifo::NumberofFifoClassObjects(0); + +Fifo::Fifo(uint32_t fifoItemSize, uint32_t fifoDepth, bool &success): + memory(0), + fifoBound(0), + fifoFree(0) { + FILE_LOG(logDEBUG) << __AT__ << " called"; + index = NumberofFifoClassObjects++; + if(CreateFifos(fifoItemSize, fifoDepth) == FAIL) + success = false; +} + + +Fifo::~Fifo() { + FILE_LOG(logDEBUG) << __AT__ << " called"; + DestroyFifos(); + NumberofFifoClassObjects--; +} + + + +int Fifo::CreateFifos(uint32_t fifoItemSize, uint32_t fifoDepth) { + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //destroy if not already + DestroyFifos(); + //create fifos + fifoBound = new CircularFifo(fifoDepth); + fifoFree = new CircularFifo(fifoDepth); + //allocate memory + memory = (char*) calloc (fifoItemSize * fifoDepth, sizeof(char)); + if (memory == NULL){ + FILE_LOG(logERROR) << "Could not allocate memory for fifos"; + return FAIL; + } + + { //push free addresses into fifoFree fifo + char* buffer = memory; + while (buffer < (memory + fifoItemSize * (fifoDepth-1))) { + sprintf(buffer,"memory"); +#ifdef FIFODEBUG + cprintf(MAGENTA,"Fifofree %d: value:%d, pop 0x%p\n", index, fifoFree->getSemValue(), (void*)(buffer)); +#endif + FreeAddress(buffer); + buffer += fifoItemSize; + } + } + FILE_LOG(logINFO) << "Fifo Structure " << index << " reconstructed"; + return OK; +} + + +void Fifo::DestroyFifos(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + if (fifoBound) { + delete fifoBound; + fifoBound = 0; + } + if (fifoFree) { + delete fifoFree; + fifoFree = 0; + } + if(memory) { + free(memory); + memory = 0; + } +} + + + +void Fifo::GetNewAddress(char*& address) { + fifoFree->pop(address); +} + +void Fifo::FreeAddress(char*& address) { + while(!fifoFree->push(address)); +} + +void Fifo::PushAddress(char*& address) { + while(!fifoBound->push(address)); +} + +void Fifo::PopAddress(char*& address) { + fifoBound->pop(address); +} + diff --git a/slsReceiverSoftware/src/FileReader.cpp b/slsReceiverSoftware/src/FileReader.cpp new file mode 100644 index 000000000..424310e7f --- /dev/null +++ b/slsReceiverSoftware/src/FileReader.cpp @@ -0,0 +1,19 @@ +/********************************************//** + * @file FileWriter.cpp + * @short sets/gets properties for the file, creates/closes the file and writes data to it + ***********************************************/ + + + +#include "FileWriter.h" + +#include +using namespace std; + + + +FileWriter::FileWriter(){} + + +FileWriter::~FileWriter() {} + diff --git a/slsReceiverSoftware/src/FileWriter.cpp b/slsReceiverSoftware/src/FileWriter.cpp new file mode 100644 index 000000000..0c7fb7542 --- /dev/null +++ b/slsReceiverSoftware/src/FileWriter.cpp @@ -0,0 +1,24 @@ +/************************************************ + * @file FileWriter.h + * @short sets/gets properties for the file, + * creates/closes the file and writes data to it + ***********************************************/ + +#include "FileWriter.h" + +#include +using namespace std; + + +FileWriter::FileWriter(char* fname): + fileName(fname) { + cout<<"fileName:"< +using namespace std; + + +HDF5FileWriter::HDF5FileWriter(char* fname): + FileWriter(fname) { + +} + + +HDF5FileWriter::~HDF5FileWriter() { + +} + + diff --git a/slsReceiverSoftware/src/Listener.cpp b/slsReceiverSoftware/src/Listener.cpp new file mode 100644 index 000000000..c3b3871f5 --- /dev/null +++ b/slsReceiverSoftware/src/Listener.cpp @@ -0,0 +1,118 @@ +/************************************************ + * @file Listener.cpp + * @short creates the listener thread that + * listens to udp sockets, writes data to memory + * & puts pointers to their memory addresses into fifos + ***********************************************/ + + +#include "Listener.h" +#include "Fifo.h" + +#include +#include +using namespace std; + +const string Listener::TypeName = "Listener"; + +int Listener::NumberofListeners(0); + +uint64_t Listener::ErrorMask(0x0); + +uint64_t Listener::RunningMask(0x0); + +pthread_mutex_t Listener::Mutex = PTHREAD_MUTEX_INITIALIZER; + +Listener::Listener(Fifo*& f) : ThreadObject(NumberofListeners), fifo(f) { + FILE_LOG(logDEBUG) << __AT__ << " called"; + + if(ThreadObject::CreateThread()){ + pthread_mutex_lock(&Mutex); + ErrorMask ^= (1<GetNewAddress(buffer); +#ifdef FIFODEBUG + cprintf(GREEN,"Listener %d, pop 0x%p buffer:%s\n", index,(void*)(buffer),buffer); +#endif + + strcpy(buffer,"changed"); + + if(count == 3){ + strcpy(buffer,"done\0"); + StopRunning(); + } + + fifo->PushAddress(buffer); + count++; +} + + diff --git a/slsReceiverSoftware/src/ThreadObject.cpp b/slsReceiverSoftware/src/ThreadObject.cpp new file mode 100644 index 000000000..cc2fa1d5a --- /dev/null +++ b/slsReceiverSoftware/src/ThreadObject.cpp @@ -0,0 +1,113 @@ +/************************************************ + * @file ThreadObject.h + * @short creates/destroys a thread + ***********************************************/ + + + +#include "ThreadObject.h" + +#include +using namespace std; + + + +ThreadObject::ThreadObject(int ind): + index(ind), + alive(false), + killThread(false), + thread(0) { + FILE_LOG(logDEBUG) << __AT__ << " called"; + PrintMembers(); +} + + +ThreadObject::~ThreadObject() { + FILE_LOG(logDEBUG) << __AT__ << " called"; + DestroyThread(); +} + + +void ThreadObject::PrintMembers() { + FILE_LOG(logDEBUG) << __AT__ << " called"; + FILE_LOG(logDEBUG) << "Index : " << index + << "\nalive: " << alive + << "\nkillThread: " << killThread + << "\npthread: " << thread; +} + + +void ThreadObject::DestroyThread() { + FILE_LOG(logDEBUG) << __AT__ << " called"; + if(alive){ + killThread = true; + sem_post(&semaphore); + pthread_join(thread,NULL); + sem_destroy(&semaphore); + killThread = false; + alive = false; + FILE_LOG(logDEBUG) << GetType() << " thread with index " << index << " destroyed successfully."; + } +} + + +int ThreadObject::CreateThread() { + FILE_LOG(logDEBUG) << __AT__ << " called"; + if(alive){ + FILE_LOG(logERROR) << "Cannot create thread " << index << ". Already alive"; + return FAIL; + } + sem_init(&semaphore,1,0); + killThread = false; + + if(pthread_create(&thread, NULL,StartThread, (void*) this)){ + FILE_LOG(logERROR) << "Could not create " << GetType() << " thread with index " << index; + return FAIL; + } + alive = true; + FILE_LOG(logINFO) << GetType() << " thread " << index << " created successfully."; + + return OK; +} + + +void* ThreadObject::StartThread(void* thisPointer) { + FILE_LOG(logDEBUG) << __AT__ << " called"; + ((ThreadObject*)thisPointer)->RunningThread(); + return thisPointer; +} + + +void ThreadObject::RunningThread() { + FILE_LOG(logDEBUG) << __AT__ << " called"; + + + while(true) { + + while(IsRunning()) { + + ThreadExecution(); + + }/*--end of inner loop */ + + + //wait till the next acquisition + sem_wait(&semaphore); + + if(killThread) { + cprintf(BLUE,"%s Thread %d: Goodbye\n",GetType().c_str(),index); + pthread_exit(NULL); + } + + }/*--end of loop for each acquisition (outer loop) */ +} + + + + +void ThreadObject::Continue() { + sem_post(&semaphore); +} + + + diff --git a/slsReceiverSoftware/src/UDPBaseImplementation.cpp b/slsReceiverSoftware/src/UDPBaseImplementation.cpp index d6b956bd7..d5e8c3524 100644 --- a/slsReceiverSoftware/src/UDPBaseImplementation.cpp +++ b/slsReceiverSoftware/src/UDPBaseImplementation.cpp @@ -191,7 +191,7 @@ uint32_t UDPBaseImplementation::getFrameToGuiFrequency() const{ FILE_LOG(logDEBU uint32_t UDPBaseImplementation::getFrameToGuiTimer() const{ FILE_LOG(logDEBUG) << __AT__ << " starting"; return frameToGuiTimerinMS;} -uint32_t UDPBaseImplementation::getDataStreamEnable() const{ FILE_LOG(logDEBUG) << __AT__ << " starting"; return dataStreamEnable;} +bool UDPBaseImplementation::getDataStreamEnable() const{ FILE_LOG(logDEBUG) << __AT__ << " starting"; return dataStreamEnable;} uint64_t UDPBaseImplementation::getAcquisitionPeriod() const{ FILE_LOG(logDEBUG) << __AT__ << " starting"; return acquisitionPeriod;} @@ -342,11 +342,13 @@ void UDPBaseImplementation::setEthernetInterface(const char* c){ /***acquisition parameters***/ -void UDPBaseImplementation::setShortFrameEnable(const int i){ +int UDPBaseImplementation::setShortFrameEnable(const int i){ FILE_LOG(logDEBUG) << __AT__ << " starting"; shortFrameEnable = i; FILE_LOG(logINFO) << "Short Frame Enable: " << stringEnable(shortFrameEnable); + //overrridden child classes might return FAIL + return OK; } int UDPBaseImplementation::setFrameToGuiFrequency(const uint32_t freq){ @@ -367,7 +369,7 @@ void UDPBaseImplementation::setFrameToGuiTimer(const uint32_t time_in_ms){ } -uint32_t UDPBaseImplementation::setDataStreamEnable(const uint32_t enable){ +int UDPBaseImplementation::setDataStreamEnable(const bool enable){ FILE_LOG(logDEBUG) << __AT__ << " starting"; dataStreamEnable = enable; diff --git a/slsReceiverSoftware/src/UDPStandardImplementation.cpp b/slsReceiverSoftware/src/UDPStandardImplementation.cpp index ad2f16af0..aca9e872e 100644 --- a/slsReceiverSoftware/src/UDPStandardImplementation.cpp +++ b/slsReceiverSoftware/src/UDPStandardImplementation.cpp @@ -5,4022 +5,358 @@ #include "UDPStandardImplementation.h" +#include "GeneralData.h" +#include "Listener.h" +#include "DataProcessor.h" +#include "DataStreamer.h" +#include "Fifo.h" +#include "BinaryFileWriter.h" +#ifdef HDF5C +#include "HDF5FileWriter.h" +#endif -#include "moench02ModuleData.h" -#include "gotthardModuleData.h" -#include "gotthardShortModuleData.h" - -#include // exit() -#include //set precision for printing parameters for create new file -#include //map -#include -#include -#include -#include - -#include //zmq -#include - - +#include //system +#include //strcpy using namespace std; -#define WRITE_HEADERS -/************************************************************************* - * Constructor & Destructor ********************************************** - * They access local cache of configuration or detector parameters ******* - *************************************************************************/ +/** cosntructor & destructor */ -UDPStandardImplementation::UDPStandardImplementation(){ +UDPStandardImplementation::UDPStandardImplementation() { FILE_LOG(logDEBUG) << __AT__ << " called"; + InitializeMembers(); - initializeMembers(); - - //***mutex*** - pthread_mutex_init(&statusMutex,NULL); - pthread_mutex_init(&writeMutex,NULL); - pthread_mutex_init(&dataReadyMutex,NULL); - pthread_mutex_init(&progressMutex,NULL); - - //to increase socket receiver buffer size and max length of input queue by changing kernel settings - if(myDetectorType == EIGER); - else if(system("echo $((100*1024*1024)) > /proc/sys/net/core/rmem_max")){ - FILE_LOG(logDEBUG) << "Warning: No root permission to change socket receiver buffer size in file /proc/sys/net/core/rmem_max"; - }else if(system("echo 250000 > /proc/sys/net/core/netdev_max_backlog")){ - FILE_LOG(logDEBUG) << "Warning: No root permission to change max length of input queue in file /proc/sys/net/core/netdev_max_backlog"; - } - - /** permanent setting by heiner - net.core.rmem_max = 104857600 # 100MiB - net.core.netdev_max_backlog = 250000 - sysctl -p - // from the manual - sysctl -w net.core.rmem_max=16777216 - sysctl -w net.core.netdev_max_backlog=250000 - */ } + UDPStandardImplementation::~UDPStandardImplementation(){ FILE_LOG(logDEBUG) << __AT__ << " called"; - for(int i=0;i(receiverData[i], csize, sigma, sign, moenchCommonModeSubtraction); -} + bool success = true; + fifo.push_back(new Fifo(1024*256,5, success)); + if (!success) cprintf(RED,"not successful\n"); + listener.push_back(new Listener(fifo[i])); + dataProcessor.push_back(new DataProcessor(fifo[i])); + //dataStreamer.push_back(new DataStreamer(fifo[i])); -int UDPStandardImplementation::setupFifoStructure(){ - FILE_LOG(logDEBUG) << __AT__ << " called"; + //listener[i]->SetFifo(fifo[i]); + //dataProcessor[i]->SetFifo(fifo[i]); - - //number of jobs per buffer - int64_t i; - int oldNumberofJobsPerBuffer = numberofJobsPerBuffer; - //eiger always listens to 1 packet at a time - if(excludeMissingPackets){ - numberofJobsPerBuffer = 1; - FILE_LOG(logDEBUG) << "Info: 1 packet per buffer"; - } - //else calculate best possible number of frames to listen to at a time (for fast readouts like gotthard) - else{ - //if frequency to gui is not random (every nth frame), then listen to only n frames per buffer - if(frameToGuiFrequency) - numberofJobsPerBuffer = frameToGuiFrequency; - //random frame sent to gui, then frames per buffer depends on acquisition period - else{ - //calculate 100ms/period to get frames to listen to at a time - if(acquisitionPeriod) - i = SAMPLE_TIME_IN_NS/acquisitionPeriod; - else{ - if(acquisitionTime) - i = SAMPLE_TIME_IN_NS/acquisitionTime; - else - i = SAMPLE_TIME_IN_NS; - } - //max frames to listen to at a time is limited by 1000 - if (i > MAX_JOBS_PER_THREAD) - numberofJobsPerBuffer = MAX_JOBS_PER_THREAD; - else if (i < 1) - numberofJobsPerBuffer = 1; - else - numberofJobsPerBuffer = i; - - } - FILE_LOG(logINFO) << "Number of Frames per buffer:" << numberofJobsPerBuffer << endl; - } - - - - // fifo depth - uint32_t oldFifoSize = fifoSize; - - - //reduce fifo depth if > 1 numberofJobsPerBuffer - if(fifoDepth % numberofJobsPerBuffer) - fifoSize = (fifoDepth/numberofJobsPerBuffer)+1; - else - fifoSize = fifoDepth/numberofJobsPerBuffer; - - //do not rebuild fifo structure if it is the same (oldfifosize differs only for different packetsperframe) - if((oldNumberofJobsPerBuffer == numberofJobsPerBuffer) && (oldFifoSize == fifoSize)) - return OK; - FILE_LOG(logINFO) << "Info: Total Fifo Size:" << fifoSize; - - - - //delete threads - if(threadStarted){ - createListeningThreads(true); - createWriterThreads(true); - } - - - //set up fifo structure - for(int i=0;iisEmpty()){ - fifoFree[i]->pop(buffer[i]); - //cprintf(BLUE,"FifoFree[%d]: value:%d, pop 0x%x\n",i,fifoFree[i]->getSemValue(),(void*)(buffer[i])); - } - delete fifoFree[i]; - fifoFree[i] = 0; - } - if(fifo[i]){ - while(!fifo[i]->isEmpty()){ - fifo[i]->pop(buffer[i]); - //cprintf(CYAN,"Fifo[%d]: value:%d, pop 0x%x\n",i,fifo[i]->getSemValue(),(void*)(buffer[i])); - } - delete fifo[i]; - fifo[i] = 0; - } - if(mem0[i]){ - free(mem0[i]); - mem0[i] = 0; - } + fileWriter.push_back(new BinaryFileWriter(fileName)); } - for(int i=0;i(fifoSize); - fifo[i] = new CircularFifo(fifoSize); - - //allocate memory - mem0[i] = (char*)calloc((bufferSize * numberofJobsPerBuffer + fifoBufferHeaderSize) * fifoSize,sizeof(char)); - if (mem0[i] == NULL){ - cprintf(BG_RED,"Error: Could not allocate memory for listening \n"); - return FAIL; - } - - //push free address into fifoFree - buffer[i]=mem0[i]; - while (buffer[i] < (mem0[i]+(bufferSize * numberofJobsPerBuffer + fifoBufferHeaderSize) * (fifoSize-1))) { - //cprintf(BLUE,"fifofree %d: push 0x%p\n",i,(void*)buffer[i]); - /*for(int k=0;kpush(buffer[i])); - //cprintf(GREEN,"Fifofree[%d]: value:%d, push 0x%x\n",i,fifoFree[i]->getSemValue(),(void*)(buffer[i])); -#ifdef DEBUG5 - cprintf(BLUE,"Info: %d fifostructure free pushed into fifofree %p\n", i, (void*)(buffer[i])); -#endif - buffer[i] += (bufferSize * numberofJobsPerBuffer + fifoBufferHeaderSize); - } + if (Listener::GetErrorMask() || DataProcessor::GetErrorMask()){ + cprintf(RED, "Error in creating threads\n"); } - cout << "Fifo structure(s) reconstructed" << endl; - //create threads - if(createListeningThreads() == FAIL){ - FILE_LOG(logERROR) << "Could not create listening thread"; - return FAIL; - } - if(createWriterThreads() == FAIL){ - FILE_LOG(logERROR) << "Could not create writer threads"; - return FAIL; - } - setThreadPriorities(); + + //start receiver functions + //create udp sockets + //create file + //reset status + //reset all masks + Listener::ResetRunningMask(); + DataProcessor::ResetRunningMask(); + //DataStreamer::ResetRunningMask(); + + + for( unsigned int i=0; i < listener.size();i++ ) { + listener[i]->StartRunning(); + dataProcessor[i]->StartRunning(); + listener[i]->Continue(); + dataProcessor[i]->Continue(); + } + + + // for (vector::iterator it = listener.begin(); it != listener.end(); ++it) { + //*it->StartRunning(); + + usleep (5 * 1000 * 1000); + + + SetLocalNetworkParameters(); return OK; } +uint64_t UDPStandardImplementation::getTotalFramesCaught() const{ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + //preventing divide by 0 using ternary operator + return (totalPacketsCaught/(packetsPerFrame*(listener.size()>0?listener.size():1))); +} - - - +uint64_t UDPStandardImplementation::getFramesCaught() const{ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + //preventing divide by 0 using ternary operator + return (packetsCaught/(packetsPerFrame*(listener.size()>0?listener.size():1))); +} void UDPStandardImplementation::setFileName(const char c[]){ FILE_LOG(logDEBUG) << __AT__ << " starting"; - char oldfilename[MAX_STR_LENGTH]; - strcpy(oldfilename,fileName); - - if(strlen(c)) - strcpy(fileName, c); - - if(strlen(fileName)){ + if (strlen(c)) { + strcpy(fileName, c); //automatically update fileName in Filewriter (pointer) int detindex = -1; string tempname(fileName); size_t uscore=tempname.rfind("_"); - if (uscore!=string::npos){ - if (sscanf(tempname.substr(uscore+1,tempname.size()-uscore-1).c_str(),"d%d",&detindex)) { + if (uscore!=string::npos) { + if (sscanf(tempname.substr(uscore+1, tempname.size()-uscore-1).c_str(), "d%d", &detindex)) { detID = detindex; } } - if(detindex == -1) + if (detindex == -1) detID = 0; } - FILE_LOG(logINFO) << "File name:" << fileName; } -int UDPStandardImplementation::setDataCompressionEnable(const bool b){ - FILE_LOG(logDEBUG) << __AT__ << " starting"; - if(myDetectorType != EIGER){ - cout << "Info: Setting up Data Compression Enable to " << stringEnable(b); -#ifdef MYROOT1 - cout << " WITH ROOT" << endl; -#else - cout << " WITHOUT ROOT" << endl; -#endif - } - - //set data compression enable - dataCompressionEnable = b; - - //-- create writer threads depending on enable - pthread_mutex_lock(&statusMutex); - writerThreadsMask = 0x0; - pthread_mutex_unlock(&(statusMutex)); - - createWriterThreads(true); - if(b) - numberofWriterThreads = MAX_NUMBER_OF_WRITER_THREADS; - else - numberofWriterThreads = 1; - if(createWriterThreads() == FAIL){ - cprintf(BG_RED,"Error: Could not create writer threads\n"); - return FAIL; - } - //-- end of create writer threads - setThreadPriorities(); - - //filter - deleteFilter(); - if(b) - initializeFilter(); - - FILE_LOG(logINFO) << "Data Compression: " << stringEnable(dataCompressionEnable); - - return OK; -} - -/***acquisition count parameters***/ -uint64_t UDPStandardImplementation::getTotalFramesCaught() const{ - FILE_LOG(logDEBUG) << __AT__ << " starting"; - - return (totalPacketsCaught/(packetsPerFrame*numberofListeningThreads)); -} - -uint64_t UDPStandardImplementation::getFramesCaught() const{ - FILE_LOG(logDEBUG) << __AT__ << " starting"; - return (packetsCaught/(packetsPerFrame*numberofListeningThreads)); -} - -/***acquisition parameters***/ -void UDPStandardImplementation::setShortFrameEnable(const int i){ +int UDPStandardImplementation::setShortFrameEnable(const int i){ FILE_LOG(logDEBUG) << __AT__ << " called"; - shortFrameEnable = i; - - if(shortFrameEnable!=-1){ - bufferSize = GOTTHARD_SHORT_BUFFER_SIZE; - onePacketSize = GOTTHARD_SHORT_BUFFER_SIZE; - oneDataSize = GOTTHARD_SHORT_DATABYTES; - maxFramesPerFile = SHORT_MAX_FRAMES_PER_FILE; - packetsPerFrame = GOTTHARD_SHORT_PACKETS_PER_FRAME; - frameIndexMask = GOTTHARD_SHORT_FRAME_INDEX_MASK; - frameIndexOffset = GOTTHARD_SHORT_FRAME_INDEX_OFFSET; - packetIndexMask = GOTTHARD_SHORT_PACKET_INDEX_MASK; - - }else{ - bufferSize = GOTTHARD_BUFFER_SIZE; - onePacketSize = GOTTHARD_ONE_PACKET_SIZE; - oneDataSize = GOTTHARD_ONE_DATA_SIZE; - maxFramesPerFile = MAX_FRAMES_PER_FILE; - packetsPerFrame = GOTTHARD_PACKETS_PER_FRAME; - frameIndexMask = GOTTHARD_FRAME_INDEX_MASK; - frameIndexOffset = GOTTHARD_FRAME_INDEX_OFFSET; - packetIndexMask = GOTTHARD_PACKET_INDEX_MASK; + if (myDetectorType != GOTTHARD) { + cprintf(RED, "Error: Can not set short frame for this detector\n"); + return FAIL; } - //filter - deleteFilter(); - if(dataCompressionEnable) - initializeFilter(); + if (shortFrameEnable != i) { + shortFrameEnable = i; + if (generalData) + delete generalData; + if (i != -1) + generalData = new ShortGotthardData(); + else + generalData = new GotthardData(); + numberofJobs = -1; //changes to imagesize has to be noted to recreate fifo structure + if(SetupFifoStructure() == FAIL) + return FAIL; + } FILE_LOG(logINFO) << "Short Frame Enable: " << shortFrameEnable; + return OK; } int UDPStandardImplementation::setFrameToGuiFrequency(const uint32_t freq){ FILE_LOG(logDEBUG) << __AT__ << " called"; - frameToGuiFrequency = freq; - if(setupFifoStructure() == FAIL) - return FAIL; + if (frameToGuiFrequency != freq){ + frameToGuiFrequency = freq; + //only the ones lisening to more than 1 frame at a time needs to change fifo structure + switch (myDetectorType) { + case GOTTHARD: + case PROPIX: + if(SetupFifoStructure() == FAIL) + return FAIL; + break; + default: + break; + } + } FILE_LOG(logINFO) << "Frame to Gui Frequency: " << frameToGuiFrequency; - return OK; } - -uint32_t UDPStandardImplementation::setDataStreamEnable(const uint32_t enable){ +int UDPStandardImplementation::setDataStreamEnable(const bool enable){ FILE_LOG(logDEBUG) << __AT__ << " called"; - int oldvalue = dataStreamEnable; - dataStreamEnable = enable; - FILE_LOG(logINFO) << "Data Send to Gui: " << dataStreamEnable; + if (dataStreamEnable != enable) { + dataStreamEnable = enable; - - if(oldvalue!=dataStreamEnable){ //data sockets have to be created again as the client ones are - if(zmqThreadStarted) - createDataCallbackThreads(true); + if(dataStreamer.size()) + dataStreamer.clear(); - if(dataStreamEnable){ - numberofDataCallbackThreads = numberofListeningThreads; - if(createDataCallbackThreads() == FAIL){ - cprintf(BG_RED,"Error: Could not create data callback threads\n"); + if(enable){ + for ( int i=0; i < numThreads; ++i ) { + dataStreamer.push_back(new DataStreamer()); + if (DataStreamer::GetErrorMask()) { + cprintf(BG_RED,"Error: Could not create data callback threads\n"); + return FAIL; + } } } } - + FILE_LOG(logINFO) << "Data Send to Gui: " << dataStreamEnable; return OK; } - int UDPStandardImplementation::setAcquisitionPeriod(const uint64_t i){ FILE_LOG(logDEBUG) << __AT__ << " called"; - acquisitionPeriod = i; - if(setupFifoStructure() == FAIL) - return FAIL; - - FILE_LOG(logINFO) << "Acquisition Period: " << (double)acquisitionPeriod/(1E9) << "s"; - - if(myDetectorType == EIGER && fileFormatType == BINARY) - for(int i=0; iShutDownSocket(); - FILE_LOG(logINFO) << "Shut down UDP Socket " << i; - delete udpSocket[i]; - udpSocket[i] = 0; - } - } - return OK; -} - - - - -/** - * Pre: status is running, udp sockets have been initialized, stop receiver initiated - * Post:udp sockets closed, status is transmitting - * */ -void UDPStandardImplementation::startReadout(){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - FILE_LOG(logDEBUG) << "Transmitting last data"; - - if(status == RUNNING){ - - - //needs to wait for packets only if activated - if(activated){ - //check if all packets got - int totalP = 0,prev=-1; - for(int i=0; igetCurrentTotalReceived(); - - //wait for all packets - if((unsigned long long int)totalP!=numberOfFrames*packetsPerFrame*numberofListeningThreads){ - - //wait as long as there is change from prev totalP, - //and also change from received in buffer to previous value - //(as one listens to many at a time, shouldnt cut off in between) - while((prev != totalP) || (prevReceivedInBuffer!= currentReceivedInBuffer)){ -#ifdef DEBUG5 - cprintf(MAGENTA,"waiting for all packets prevP:%d totalP:%d PrevBuffer:%d currentBuffer:%d\n",prev,totalP,prevReceivedInBuffer,currentReceivedInBuffer); - -#endif - //usleep(2*1000*1000); - usleep(5*1000);/* Need to find optimal time (exposure time and acquisition period) **/ - prev = totalP; - totalP = 0; - for(int i=0; igetCurrentTotalReceived(); -#ifdef DEBUG5 - cprintf(MAGENTA,"\tupdated: totalP:%d currently in buffer:%d\n",totalP,currentReceivedInBuffer); - -#endif - } - - } - } - - //set status - pthread_mutex_lock(&statusMutex); - status = TRANSMITTING; - pthread_mutex_unlock(&statusMutex); - - FILE_LOG(logINFO) << "Status: Transmitting"; - } - - //shut down udp sockets and make listeners push dummy (end) packets for writers - shutDownUDPSockets(); -} - - - -/**make this better by asking all of it at once*/ -void UDPStandardImplementation::readFrame(int ithread, char* c,char** raw, int64_t &startAcq, int64_t &startFrame){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - -} - - - -void UDPStandardImplementation::closeFile(int ithread){ - FILE_LOG(logDEBUG) << __AT__ << " called for " << ithread ; - - //normal - if(!dataCompressionEnable){ - if(sfilefd[ithread]){ -#ifdef DEBUG4 - FILE_LOG(logDEBUG4) << "Going to close file: " << fileno(sfilefd)); -#endif - fflush(sfilefd[ithread]); - fclose(sfilefd[ithread]); - sfilefd[ithread] = 0; - } -#ifdef HDF5C - pthread_mutex_lock(&writeMutex); - try{ - Exception::dontPrint(); //to handle errors - if(hdf5_dataspaceId[ithread]) {delete hdf5_dataspaceId[ithread]; hdf5_dataspaceId[ithread] = 0;} - if(hdf5_datasetId[ithread]) {delete hdf5_datasetId[ithread]; hdf5_datasetId[ithread] = 0;} - if(hdf5_fileId[ithread]) {delete hdf5_fileId[ithread]; hdf5_fileId[ithread] = 0;} - if(hdf5_masterFileId) {delete hdf5_masterFileId; hdf5_masterFileId = 0;} - if(hdf5_virtualFileId) {delete hdf5_virtualFileId; hdf5_virtualFileId = 0;} - } - catch(Exception error){ - cprintf(RED,"Error in closing HDF5 handles\n"); - error.printError(); - } - pthread_mutex_unlock(&writeMutex); -#endif - } - - //compression - else{ -#if (defined(MYROOT1) && defined(ALLFILE_DEBUG)) || !defined(MYROOT1) - if(sfilefd[0]){ -#ifdef DEBUG4 - FILE_LOG(logDEBUG4) << "sfilefd: " << (int)sfilefd[0]; -#endif - fclose(sfilefd[0]); - sfilefd[0] = 0; - } -#endif - -#ifdef MYROOT1 - pthread_mutex_lock(&writeMutex); - //write to file - if(myTree[ithread] && myFile[ithread]){ - myFile[ithread] = myTree[ithread]->GetCurrentFile(); - - if(myFile[ithread]->Write()) - //->Write(tall->GetName(),TObject::kOverwrite); - cout << "Thread " << ithread <<": wrote frames to file" << endl; - else - cout << "Thread " << ithread << ": could not write frames to file" << endl; - - }else - cout << "Thread " << ithread << ": could not write frames to file: No file or No Tree" << endl; - //close file - if(myTree[ithread] && myFile[ithread]) - myFile[ithread] = myTree[ithread]->GetCurrentFile(); - if(myFile[ithread] != 0) - myFile[ithread]->Close(); - myFile[ithread] = 0; - myTree[ithread] = 0; - pthread_mutex_unlock(&writeMutex); - -#endif - } -} - - -//eiger only -int UDPStandardImplementation::setActivate(int enable){ - FILE_LOG(logDEBUG) << __AT__ << " starting"; - - if(enable != -1){ - activated = enable; - FILE_LOG(logINFO) << "Activation: " << stringEnable(activated); - } - - if(fileFormatType == BINARY) - for(int i=0; igetErrorStatus(); - if(!iret){ - cout << "UDP port opened at port " << port[i] << endl; - }else{ - FILE_LOG(logERROR) << "Could not create UDP socket on port " << port[i] << " error: " << iret; - shutDownUDPSockets(); - return FAIL; - } - } - - FILE_LOG(logDEBUG) << "UDP socket(s) created successfully."; - cout << "Listener Ready ..." << endl; - - return OK; -} - - - -int UDPStandardImplementation::setupWriter(){ - FILE_LOG(logDEBUG) << __AT__ << " starting"; - - //acquisition start call back returns enable write - cbAction = DO_EVERYTHING; - if (startAcquisitionCallBack) - cbAction=startAcquisitionCallBack(filePath,fileNamePerThread[0],(int)fileIndex,bufferSize,pStartAcquisition); - - - if(cbAction < DO_EVERYTHING){ - FILE_LOG(logINFO) << "Call back activated. Data saving must be taken care of by user in call back."; - if (rawDataReadyCallBack){ - FILE_LOG(logINFO) << "Data Write has been defined externally"; - } - }else if(!fileWriteEnable){ - FILE_LOG(logINFO) << "Data will not be saved"; - } - - - //creating first file - //setting all value to 1 - pthread_mutex_lock(&statusMutex); - for(int i=0; i DO_NOTHING){ - - - if(fileFormatType == BINARY){ - //close file pointers - if(sfilefd[ithread]){ - //all threads need to close file, reset mask and exit loop - if(myDetectorType == EIGER && fileWriteEnable && (cbAction > DO_NOTHING)){ - updateFileHeader(ithread); - fseek(sfilefd[ithread],0,0); - fwrite((void*)fileHeader[ithread], 1, FILE_HEADER_SIZE, sfilefd[ithread]); - } - fflush(sfilefd[ithread]); - fclose(sfilefd[ithread]); - sfilefd[ithread] = 0; - } - - - //create file - if(!overwriteEnable){ - if (NULL == (sfilefd[ithread] = fopen((const char *) (completeFileName[ithread]), "wx"))){ - FILE_LOG(logERROR) << "Could not create/overwrite file" << completeFileName[ithread]; - sfilefd[ithread] = 0; - return FAIL; - } - }else if (NULL == (sfilefd[ithread] = fopen((const char *) (completeFileName[ithread]), "w"))){ - FILE_LOG(logERROR) << "Could not create file" << completeFileName[ithread]; - sfilefd[ithread] = 0; - return FAIL; - } - //setting file buffer size to 16mb - setvbuf(sfilefd[ithread],NULL,_IOFBF,FILE_BUF_SIZE); - - - //Print packet loss and filenames - if(totalWritingPacketCount[ithread]){ - if(numberofWriterThreads>1){ - cprintf(BLUE,"File:%s" - "\nThread:%d" - "\tLost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - completeFileName[ithread],ithread, - ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) - ?(long long int)((numberOfFrames-(frameNumberInPreviousFile[ithread]+1))*packetsPerFrame - totalPacketsInFile[ithread]) - :(long long int)((frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread])*packetsPerFrame - totalPacketsInFile[ithread]), - (long long int)totalPacketsInFile[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousFile[ithread] - ); - }else{ - cprintf(BLUE,"File:%s" - "\nLost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - completeFileName[ithread], - ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) - ?(long long int)(numberOfFrames-(frameNumberInPreviousFile[ithread]+1)) - :(long long int)(frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread]), - (long long int)totalPacketsInFile[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousFile[ithread] - ); - } - - }else - printf("Thread:%d File opened:%s\n",ithread, completeFileName[ithread]); - - //write file header - if(myDetectorType == EIGER) - fwrite((void*)fileHeader[ithread], 1, FILE_HEADER_SIZE, sfilefd[ithread]); - } - - -#ifdef HDF5C - else if(fileFormatType == HDF5){ - struct timespec begin,end; - - pthread_mutex_lock(&writeMutex); - if(!ithread) - clock_gettime(CLOCK_REALTIME, &begin); - //closing file - try{ - Exception::dontPrint(); //to handle errors - if(hdf5_dataspaceId[ithread]) {delete hdf5_dataspaceId[ithread]; hdf5_dataspaceId[ithread] = 0;} - if(hdf5_datasetId[ithread]) {delete hdf5_datasetId[ithread]; hdf5_datasetId[ithread] = 0;} - if(hdf5_fileId[ithread]) {delete hdf5_fileId[ithread]; hdf5_fileId[ithread] = 0; } - if(hdf5_masterFileId) {delete hdf5_masterFileId; hdf5_masterFileId = 0;} - if(hdf5_virtualFileId) {delete hdf5_virtualFileId; hdf5_virtualFileId = 0;} - } - catch(AttributeIException error){ - cprintf(RED,"Error in creating attributes in thread %d\n",ithread); - error.printError(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - catch(Exception error){ - cprintf(RED,"Error in closing HDF5 handles in thread %d\n",ithread); - error.printError(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - }//end of closing file - - char masterFileName[1000]="", virtualFileName[1000]=""; - sprintf(masterFileName, "%s/%s_master_%lld.h5", filePath,getNameFromReceiverFilePrefix(fileName).c_str(),(long long int)fileIndex); - sprintf(virtualFileName, "%s/%s_%lld.h5", filePath,getNameFromReceiverFilePrefix(fileName).c_str(),(long long int)fileIndex); - - - //creating file - try{ - Exception::dontPrint(); //to handle errors - - if(!detID && !ithread){ - //creating master file with metadata - try{ - //creating file - FileAccPropList flist; - flist.setFcloseDegree(H5F_CLOSE_STRONG); - if(!overwriteEnable) - hdf5_masterFileId = new H5File( masterFileName, H5F_ACC_EXCL, NULL, flist ); - else - hdf5_masterFileId = new H5File( masterFileName, H5F_ACC_TRUNC, NULL, flist ); - - //create attributes - DataSpace dataspace = DataSpace (H5S_SCALAR); - Attribute attribute; - double dValue=0; - - //version - dValue=HDF5_WRITER_VERSION; - attribute = hdf5_masterFileId->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace); - attribute.write(PredType::NATIVE_DOUBLE, &dValue); - - - //Create a group in the file - Group group1( hdf5_masterFileId->createGroup( "entry" ) ); - Group group2( group1.createGroup("data") ); - Group group3( group1.createGroup("instrument") ); - Group group4( group3.createGroup("beam") ); - Group group5( group3.createGroup("detector") ); - Group group6( group1.createGroup("sample") ); - - - int iValue=0; - StrType strdatatype(PredType::C_S1,256); - DataSet dataset; - - //Dynamic Range - dataset = group5.createDataSet ( "dynamic range", PredType::NATIVE_INT, dataspace ); - dataset.write ( &dynamicRange, PredType::NATIVE_INT); - attribute = dataset.createAttribute("unit",strdatatype, dataspace); - attribute.write(strdatatype, string("bits")); - //Ten Giga - iValue = tengigaEnable; - dataset = group5.createDataSet ( "ten giga enable", PredType::NATIVE_INT, dataspace ); - dataset.write ( &iValue, PredType::NATIVE_INT); - //Image Size - dataset = group5.createDataSet ( "image size", PredType::NATIVE_INT, dataspace ); - dataset.write ( &bufferSize, PredType::NATIVE_INT); - attribute = dataset.createAttribute("unit",strdatatype, dataspace); - attribute.write(strdatatype, string("bytes")); - //x - dataset = group5.createDataSet ( "number of pixels in x axis", PredType::NATIVE_INT, dataspace ); - dataset.write ( &NX, PredType::NATIVE_INT); - //y - dataset = group5.createDataSet ( "number of pixels in y axis", PredType::NATIVE_INT, dataspace ); - dataset.write ( &NY, PredType::NATIVE_INT); - //Total Frames - dataset = group5.createDataSet ( "total frames", PredType::STD_U64LE, dataspace ); - dataset.write ( &numberOfFrames, PredType::STD_U64LE); - //Exptime - dataset = group5.createDataSet ( "exposure time", PredType::STD_U64LE, dataspace ); - dataset.write ( &acquisitionTime, PredType::STD_U64LE); - attribute = dataset.createAttribute("unit",strdatatype, dataspace); - attribute.write(strdatatype, string("ns")); - //Period - dataset = group5.createDataSet ( "acquisition period", PredType::STD_U64LE, dataspace ); - dataset.write ( &acquisitionPeriod, PredType::STD_U64LE); - attribute = dataset.createAttribute("unit",strdatatype, dataspace); - attribute.write(strdatatype, string("ns")); - //Timestamp - time_t t = time(0); - dataset = group5.createDataSet ( "timestamp", strdatatype, dataspace ); - dataset.write ( string(ctime(&t)), strdatatype ); - - group1.close(); - group2.close(); - group3.close(); - group4.close(); - group5.close(); - group6.close(); - - }catch(Exception error){ - cprintf(RED,"Error in creating HDF5 master file in thread %d\n",ithread); - error.printError(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - -/* - // creating virtual file - try{ - FileAccPropList flist; - flist.setFcloseDegree(H5F_CLOSE_STRONG); - if(!overwriteEnable) - hdf5_virtualFileId = new H5File( virtualFileName, H5F_ACC_EXCL, NULL,flist ); - else - hdf5_virtualFileId = new H5File( virtualFileName, H5F_ACC_TRUNC, NULL, flist ); - - //create dataspace for the dataset in the file - char dsetname[100]; - try{ - int numimagesindataset = ((numberOfFrames < MAX_IMAGES_IN_DATASET)? numberOfFrames:MAX_IMAGES_IN_DATASET); - hsize_t srcdims[3] = { numimagesindataset, NY*TILE_NY, NX*TILE*NX }; - if(dynamicRange == 4) - srcdims[2] = NX/2; - DataSpace dataspace(3,srcdims); - sprintf(dsetname, "/virtualdata_%012lld", (long long int)currentFrameNumber[ithread]+1); - - //create property list for a dataset - DSetCreatPropList plist = H5P_DEFAULT; - - //create chunked dataset if greater than max_chunked_images - if(numimagesindataset > MAX_CHUNKED_IMAGES){ - //set up fill values - int fillvalue = -1; /*Aldo suggested its time consuming*/ - - /* - plist.setFillValue(hdf5_datatype, &fillvalue); - hsize_t chunk_dims[3] ={MAX_CHUNKED_IMAGES, srcdims[1], srcdims[2]}; - plist.setChunk(3, chunk_dims); - } - - //Create dataset and write it into the file - hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( - dsetname, hdf5_datatype, dataspace, plist)); - -*/ - - /* fix this to mapp - hsize_t src_dims[1]={NZ}; - hsize_t start[RANK]= {0,0,0},count[RANK] = {1,1,NZ}; - for(int i=0;iclose(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - - }catch(Exception error){ - cprintf(RED,"Error in creating HDF5 file %s in thread %d\n",completeFileName[ithread], ithread); - error.printError(); - hdf5_masterFileId->close(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - */ - - /*//link ... master file should create link to the virtual file.. - try{ - char linkPath[1000]=""; - sprintf(linkPath,"/entry/data/%s",dsetname); - //herr_t H5Lcreate_external( const char *target_file_name, const char *target_obj_name, hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id ) - H5Lcreate_external(masterFileName, dsetname, "/entry/data",dsetname,H5P_DEFAULT,H5P_DEFAULT - //hdf5_fileId[ithread]->link(H5G_LINK_HARD,dsetname,linkPath); - }catch(Exception error){ - cprintf(RED,"Error in creating link in thread %d\n", ithread); - error.printError(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - */ - } - - - //creating file - FileAccPropList flist; - flist.setFcloseDegree(H5F_CLOSE_STRONG); - try{ - if(!overwriteEnable) - hdf5_fileId[ithread] = new H5File( completeFileName[ithread], H5F_ACC_EXCL, NULL,flist ); - else - hdf5_fileId[ithread] = new H5File( completeFileName[ithread], H5F_ACC_TRUNC, NULL, flist ); - }catch(Exception error){ - cprintf(RED,"Error in creating HDF5 file %s in thread %d\n",completeFileName[ithread], ithread); - error.printError(); - hdf5_masterFileId->close(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - //create attributes - - try{ - DataSpace dataspace = DataSpace (H5S_SCALAR); - Attribute attribute; - double dValue=0; - - //version - dValue=HDF5_WRITER_VERSION; - attribute = hdf5_fileId[ithread]->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace); - attribute.write(PredType::NATIVE_DOUBLE, &dValue); - - - int iValue=0; - StrType strdatatype(PredType::C_S1,256); - DataSet dataset; - if(myDetectorType == EIGER){ - //top - iValue = (flippedData[0]?0:1); - attribute = hdf5_fileId[ithread]->createAttribute("top",PredType::NATIVE_INT, dataspace); - attribute.write(PredType::NATIVE_INT, &iValue); - /*dataset = group5.createDataSet ( "top", PredType::NATIVE_INT, dataspace );dataset.write ( &iValue, PredType::NATIVE_INT);*/ - //left - iValue = (ithread?0:1); - attribute = hdf5_fileId[ithread]->createAttribute("left",PredType::NATIVE_INT, dataspace); - attribute.write(PredType::NATIVE_INT, &iValue); - /*dataset = group5.createDataSet ( "left", PredType::NATIVE_INT, dataspace );dataset.write ( &iValue, PredType::NATIVE_INT);*/ - //active - iValue = activated; - attribute = hdf5_fileId[ithread]->createAttribute("active",PredType::NATIVE_INT, dataspace); - attribute.write(PredType::NATIVE_INT, &iValue); - /*dataset = group5.createDataSet ( "active", PredType::NATIVE_INT, dataspace );dataset.write ( &iValue, PredType::NATIVE_INT);*/ - } - - }catch(Exception error){ - cprintf(RED,"Error in creating attribute to file in thread %d\n", ithread); - error.printError(); - hdf5_masterFileId->close(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - //data - //create dataspace for the dataset in the file - char dsetname[100]; - try{ - - /*int numimagesindataset = ((numberOfFrames < MAX_IMAGES_IN_DATASET)? numberOfFrames:MAX_IMAGES_IN_DATASET); - hsize_t srcdims[3] = {numimagesindataset,NY,NX}; - */ - hsize_t srcdims[3] = {numberOfFrames,NY,NX}; - - - if(dynamicRange == 4) - srcdims[2] = NX/2; - hdf5_dataspaceId[ithread] = new DataSpace (3,srcdims); - sprintf(dsetname, "/data_%012lld", (long long int)currentFrameNumber[ithread]+1); - - //create chunked dataset if greater than max_chunked_images - /*if(numimagesindataset > MAX_CHUNKED_IMAGES){*/ - //create property list for a dataset - DSetCreatPropList plist; - //set up fill values - /*Aldo suggested its time consuming*/ - int fillvalue = -1; - plist.setFillValue(hdf5_datatype, &fillvalue); - - hsize_t chunk_dims[3] ={MAX_CHUNKED_IMAGES, NY, srcdims[2]}; - plist.setChunk(3, chunk_dims); - //Create dataset and write it into the file - hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( - dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread], plist)); - /*}else - hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( - dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread]));*/ - }catch(Exception error){ - cprintf(RED,"Error in creating dataset in thread %d\n",ithread); - error.printError(); - hdf5_masterFileId->close(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - } - - } - catch(Exception error){ - cprintf(RED,"Error in creating HDF5 handles in thread %d\n",ithread); - error.printError(); - hdf5_masterFileId->close(); - pthread_mutex_unlock(&writeMutex); - return FAIL; - }//end of creating file - - if(!detID && !ithread){ - if(hdf5_masterFileId) - hdf5_masterFileId->close(); - if(hdf5_virtualFileId) - hdf5_virtualFileId->close(); - } - - if(!ithread){ - clock_gettime(CLOCK_REALTIME, &end); - cprintf(RED,"%d Elapsed time:%f seconds\n",ithread,( end.tv_sec - begin.tv_sec ) + ( end.tv_nsec - begin.tv_nsec ) / 1000000000.0); - } - pthread_mutex_unlock(&writeMutex); - - if(!totalWritingPacketCount[ithread]) - printf("Thread:%d File opened:%s\n",ithread, completeFileName[ithread]); - } -#endif - - } - - //reset counters for each new file - if(totalWritingPacketCount[ithread]){ - frameNumberInPreviousFile[ithread] = currentFrameNumber[ithread]; - totalPacketsInFile[ithread] = 0; - }else{ - frameNumberInPreviousFile[ithread] = -1; - frameNumberInPreviousCheck[ithread] = -1; - } - - - + FILE_LOG(logINFO) << "Acquisition Period: " << (double)acquisitionPeriod/(1E9) << "s"; return OK; } -int UDPStandardImplementation::createCompressionFile(int ithread, int iframe){ +void UDPStandardImplementation::SetLocalNetworkParameters(){ FILE_LOG(logDEBUG) << __AT__ << " called"; -#ifdef MYROOT1 - char temp[MAX_STR_LENGTH]; - //create file name for gui purposes, and set up acquistion parameters - sprintf(temp, "%s/%s_fxxx_%d_%d.root", filePath,fileNamePerThread[ithread],fileIndex,ithread); - //file - myFile[ithread] = new TFile(temp,"RECREATE");/** later return error if it exists */ - cprintf(GREEN,"Writing_Thread %d: Created Compression File: %s\n",ithread, temp); - //tree - sprintf(temp, "%s_fxxx_%d_%d",fileNamePerThread[ithread],fileIndex,ithread); - myTree[ithread]=singlePhotonDetectorObject[ithread]->initEventTree(temp, &iframe); - //resets the pedestalSubtraction array and the commonModeSubtraction - singlePhotonDetectorObject[ithread]->newDataSet(); - if(myFile[ithread]==NULL){ - FILE_LOG(logERROR) << "File Null"; - return FAIL; - } - if(!myFile[ithread]->IsOpen()){ - FILE_LOG(logERROR) << "File Not Open"; - return FAIL; - } - return OK; -#endif - return FAIL; -} + //to increase socket receiver buffer size and max length of input queue by changing kernel settings + if (myDetectorType == EIGER) + return; + char command[255]; - -void* UDPStandardImplementation::startDataCallbackThread(void* this_pointer){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - ((UDPStandardImplementation*)this_pointer)->startDataCallback(); - return this_pointer; -} - - - -void* UDPStandardImplementation::startListeningThread(void* this_pointer){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - ((UDPStandardImplementation*)this_pointer)->startListening(); - return this_pointer; -} - - - -void* UDPStandardImplementation::startWritingThread(void* this_pointer){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - ((UDPStandardImplementation*)this_pointer)->startWriting(); - return this_pointer; -} - - - - -void UDPStandardImplementation::startDataCallback(){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //set current thread value index - int ithread = currentThreadIndex; - struct timespec begin,end; - - // server address to bind - char hostName[100] = "tcp://*:";//"tcp://127.0.0.1:"; - int portno = DEFAULT_ZMQ_PORTNO + (detID*numberofListeningThreads+ithread); - sprintf(hostName,"%s%d",hostName,portno); - - //socket details - void *context = zmq_ctx_new(); - void *zmqsocket = zmq_socket(context, ZMQ_PUSH); // create a publisher - int val = -1; - zmq_setsockopt(zmqsocket, ZMQ_LINGER, &val,sizeof(val)); // wait for the unsent packets before closing socket - //val = 10; - //zmq_setsockopt(zmqsocket,ZMQ_SNDHWM,&val,sizeof(val)); //set SEND HIGH WATER MARK (8-9ms slower) - zmq_bind(zmqsocket,hostName); // bind - FILE_LOG(logINFO) << "Thread" << ithread << ": ZMQ Server at " << hostName; - - - int headersize=0; - switch(myDetectorType){ - case EIGER: - headersize = EIGER_DATA_PACKET_HEADER_SIZE; break; - default: - headersize = 0; break; - } - - //let calling function know thread started and obtained current (after sockets created) - if(!zmqThreadStarted) - zmqThreadStarted = true; - - /* outer loop - loops once for each acquisition */ - //infinite loop, exited only to change dynamic range, 10G parameters etc (then recreated again) - while(true){ - - int oneframesize = oneDataSize * packetsPerFrame; - char* buffer = new char[packetsPerFrame*oneDataSize](); - memset(buffer,0xFF,oneframesize); - int size = 0; - int offset = 0; - uint32_t currentfnum = 0; - uint64_t fnum = 0; - uint32_t pnum = 0; - uint32_t snum = 0; - uint64_t bid = 0; - bool randomSendNow = true; - bool newFrame = false; - - - - //header details - const char *type = "float64"; - const char *shape= "[1024, 512]"; - const char *jsonFmt ="{\"htype\":[\"chunk-1.0\"], \"type\":\"%s\", \"shape\":%s, \"acqIndex\":%d, \"fIndex\":%d, \"subfnum\":%d, \"fname\":\"%s\"}"; - char buf[1000]; - int acquisitionIndex = -1; - int frameIndex = -1; - int subframeIndex = -1; -#ifdef DEBUG - int oldpnum = -1; -#endif - int datapacketscaught = 0; - - /* inner loop - loop for each buffer */ - //until mask reset (dummy pcaket got by writer) - while((1 << ithread) & dataCallbackThreadsMask){ - - //let the writer thread continue, while we process carry over if any - sem_post(&writerGuiSemaphore[ithread]); - //wait for receiver to send more data - sem_wait(&dataCallbackWriterSemaphore[ithread]); - - //end if acquistion - if(guiNumPackets[ithread] == dummyPacketValue){ - - //sending previous half frames if any - if(!excludeMissingPackets && newFrame){ - //send header - //update frame details - frameIndex = fnum; - acquisitionIndex = fnum - startAcquisitionIndex; - if(dynamicRange == 32) subframeIndex = snum; - int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); - zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); - //send data - zmq_send(zmqsocket, buffer, oneframesize, 0); - newFrame = false; - } - - - - //send final header - //update frame details -#ifdef DEBUG - cout << "sending dummy" << endl; -#endif - frameIndex = -9; - acquisitionIndex = -9; - subframeIndex = -9; - int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); - zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); - //send final data - zmq_send (zmqsocket, "end", 3, 0); - - pthread_mutex_lock(&statusMutex); - dataCallbackThreadsMask^=(1<0) && (getFrameandPacketNumber(ithread, latestData[ithread]+offset, fnum, pnum,snum,bid)==FAIL)){ - offset+= onePacketSize; - } - //if(!ithread) cout<< ithread <<" fnum:"<< fnum<<" pnum:"<= size) - break; - - if(!frameToGuiFrequency) - currentfnum = fnum; - - - //last packet of same frame - if(fnum == currentfnum && pnum == (packetsPerFrame-1)){ -#ifdef DEBUG - oldpnum=0; -#endif - memcpy(buffer+(pnum*oneDataSize), latestData[ithread]+offset+headersize,oneDataSize); - offset+= onePacketSize; - //send header - //update frame details - frameIndex = fnum; - acquisitionIndex = fnum - startAcquisitionIndex; - if(dynamicRange == 32) subframeIndex = snum; - int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); - zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); - //send data - zmq_send(zmqsocket, buffer, oneframesize, 0); - newFrame = false; -#ifdef DEBUG - if(!ithread)cprintf(BLUE,"%d sent (last packet)\n",ithread); -#endif - currentfnum++; - //start clock after sending - if(!frameToGuiFrequency){ - randomSendNow = false; - clock_gettime(CLOCK_REALTIME, &begin); - } - memset(buffer,0xFF,oneframesize); - - } - //same frame (not last) or next frame - else { - //next frame -#ifdef DEBUG - int once = true; -#endif - while(fnum > currentfnum){ -#ifdef DEBUG - if(once){ - if((fnum-currentfnum-1)>1) cprintf(RED,"%d Complete sub image missing:%d (cfnum:%d nfnum:%d)\n", - ithread,fnum-currentfnum-1,currentfnum,fnum); - once = false; - } -#endif - //send header - //update frame details - frameIndex = fnum; - acquisitionIndex = fnum - startAcquisitionIndex; - if(dynamicRange == 32) subframeIndex = snum; - int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); - zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); - //send data - zmq_send(zmqsocket, buffer, oneframesize, 0); - newFrame = false; -#ifdef DEBUG - cprintf(BLUE,"%d sent (last packet of previous frame)\n",ithread); -#endif - currentfnum++; - //start clock after sending - if(!frameToGuiFrequency){ - randomSendNow = false; - clock_gettime(CLOCK_REALTIME, &begin); - } - memset(buffer,0xFF,oneframesize); - } - - memcpy(buffer+(pnum*oneDataSize), latestData[ithread]+offset+headersize,oneDataSize); - offset+= onePacketSize; - newFrame = true; - } - - } - } - - - - }/*--end of loop for each buffer (inner loop)*/ - - //free resources - delete[] buffer; - - //end of acquisition, wait for next acquisition/change of parameters - sem_wait(&dataCallbackSemaphore[ithread]); - - - //check to exit thread (for change of parameters) - only EXIT possibility - if(killAllDataCallbackThreads){ - break;//pthread_exit(NULL); - } - - }/*--end of loop for each acquisition (outer loop) */ - - - //free resources - zmq_unbind(zmqsocket, hostName); /* will this be too soon and cut the sending*/ - zmq_close(zmqsocket); - zmq_ctx_destroy(context); - cprintf(MAGENTA,"DataCallback_Thread %d:Goodbye!\n",ithread); -} - - - - -void UDPStandardImplementation::startListening(){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //set current thread value index - int ithread = currentThreadIndex; - //let calling function know thread started and obtained current - threadStarted = 1; - - - uint32_t rc = 0; //size of buffer received in bytes - //split frames for data compression - int carryonBufferSize = 0; //from previous buffer to keep frames together in a buffer - char* tempBuffer = 0; //temporary buffer to store split frames - - - /* outer loop - loops once for each acquisition */ - //infinite loop, exited only to change dynamic range, 10G parameters etc (then recreated again) - while(true){ - - //compression variables reset before acquisition - if(dataCompressionEnable){ - carryonBufferSize = 0; - if(tempBuffer){delete []tempBuffer;tempBuffer=0;} - tempBuffer = new char[onePacketSize * (packetsPerFrame - 1)](); //store maximum of 1 packets less in a frame - } - - /* inner loop - loop for each buffer */ - //until mask reset (udp sockets shut down by client) - while((1 << ithread) & listeningThreadsMask){ - - - //pop from fifo - fifoFree[ithread]->pop(buffer[ithread]); - - //udpsocket doesnt exist - if(activated && !udpSocket[ithread]){ - FILE_LOG(logERROR) << "Listening_Thread " << ithread << ": UDP Socket not created or shut down earlier"; - stopListening(ithread,0); - continue; - } - - if(!activated) //eiger not activated modules - rc = prepareAndListenBufferDeactivated(ithread); - else if(excludeMissingPackets) //eiger and jungfrau - rc = prepareAndListenBufferCompleteFrames(ithread); - else{ - rc = prepareAndListenBuffer(ithread, carryonBufferSize, tempBuffer); //others - carryonBufferSize = 0; - } - - //problem in receiving or end of acquisition - if (status == TRANSMITTING||(rc <= 0 && activated == 0)){ - stopListening(ithread,rc); - continue; - } - - if(dataCompressionEnable) - (*((uint32_t*)(buffer[ithread]))) = processListeningBuffer(ithread, carryonBufferSize, tempBuffer, rc); - - //push buffer to FIFO - while(!fifo[ithread]->push(buffer[ithread])); - - }/*--end of loop for each buffer (inner loop)*/ - - //end of acquisition, wait for next acquisition/change of parameters - sem_wait(&listenSemaphore[ithread]); - - //check to exit thread (for change of parameters) - only EXIT possibility - if(killAllListeningThreads){ - cprintf(BLUE,"Listening_Thread %d:Goodbye!\n",ithread); - //free resources at exit - if(tempBuffer) delete[] tempBuffer; - pthread_exit(NULL); - } - - }/*--end of loop for each acquisition (outer loop) */ -} - - - - - -int UDPStandardImplementation::prepareAndListenBuffer(int ithread, int cSize, char* temp){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - int receivedSize = 0; - - //carry over from previous buffer - if(cSize) - memcpy(buffer[ithread] + fifoBufferHeaderSize, temp, cSize); - - //listen to after the carry over buffer - if(status != TRANSMITTING) - receivedSize = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + fifoBufferHeaderSize + cSize, - (bufferSize * numberofJobsPerBuffer) - cSize); - - if(receivedSize > 0){ - //write packet count to buffer - *((uint32_t*)(buffer[ithread])) = (receivedSize/onePacketSize); - totalListeningPacketCount[ithread] += (receivedSize/onePacketSize); - - //start indices for each start of scan/acquisition - if(!measurementStarted[ithread]) //and rc>0 - startFrameIndices(ithread); - } -#ifdef DEBUG - cprintf(BLUE, "Listening_Thread %d : Received bytes: %d. Expected bytes: %d\n", ithread, receivedSize, bufferSize * numberofJobsPerBuffer-cSize); -#endif - return receivedSize; -} - - - - - - - -int UDPStandardImplementation::prepareAndListenBufferDeactivated(int ithread){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //last - if(currentFrameNumber[ithread] == numberOfFrames) - return 0; - - //copy dummy packets - memset(buffer[ithread] + fifoBufferHeaderSize, 0xFF,bufferSize); - - //write fnum and number of packets - (*((uint64_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS))) = currentFrameNumber[ithread]+1; - (*((uint32_t*)(buffer[ithread]))) = packetsPerFrame; - - //start indices for each start of scan/acquisition (rc > 0) - if(!measurementStarted[ithread]) - startFrameIndices(ithread); - - return bufferSize; -} - - - - -int UDPStandardImplementation::prepareAndListenBufferCompleteFrames(int ithread){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - int headerlength = 0; - uint32_t LASTPNUM = 0; - uint32_t FIRSTPNUM = 0; - int INCORDECR = 0; - switch(myDetectorType){ - case JUNGFRAU: - headerlength = JFRAU_HEADER_LENGTH; - FIRSTPNUM = packetsPerFrame-1; - LASTPNUM = 0; - INCORDECR = -1; - break; - case EIGER: - headerlength = EIGER_DATA_PACKET_HEADER_SIZE; - FIRSTPNUM = 0; - LASTPNUM = packetsPerFrame-1; - INCORDECR = 1; - break; - default:break; - } - - - int offset = fifoBufferHeaderSize; - uint32_t pnum = 0; - uint64_t fnum = 0; - uint64_t bnum = 0; - int rc = 0; - //from getframeandpacketnumber() - uint32_t pi = 0; - uint64_t fi = 0; - uint64_t bi = 0; - uint32_t si = 0; - - - //read first packet - pnum = FIRSTPNUM; //first packet number to validate - if(status != TRANSMITTING) rc = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + offset); - if(rc <= 0) return 0; - if(getFrameandPacketNumber(ithread,buffer[ithread] + offset,fi,pi,si,bi) == FAIL){ - pi = ALL_MASK_32; //got 0 from fpga - fi = ALL_MASK_32; - } - else - fnum = fi; //fnum of first packet - bnum = bi; //bnum of first packet - totalListeningPacketCount[ithread]++; -#ifdef VERBOSE - if(!ithread) cout << "1 pnum:" << pnum << endl; -#endif - //start indices for each start of scan/acquisition (rc > 0) - if(!measurementStarted[ithread]) - startFrameIndices(ithread); - - - while(true){ - - //------------------------------------------------------ correct packet -------------------------------------------------------- - if((myDetectorType == JUNGFRAU && pnum == pi) || //jungfrau only looks at pnum - (myDetectorType == EIGER && pnum == pi && fnum == fi)){ // eiger looks at pnum and fnum -#ifdef VERBOSE - if(!ithread) cout << "correct packet" << endl; -#endif - //copy only data - memcpy(buffer[ithread] + offset,buffer[ithread] + offset + headerlength, oneDataSize); - offset+=oneDataSize; - - //if complete frame - if(pnum == LASTPNUM) - break; - //else increment/decrement - pnum += INCORDECR; - - rc=0; //listen again - if(status != TRANSMITTING) - rc = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + offset); - if(rc <= 0){ //end: update ignored and return - if(myDetectorType == JUNGFRAU) - totalIgnoredPacketCount[ithread] += (packetsPerFrame - pnum); - else - totalIgnoredPacketCount[ithread] += (pnum + 1); - return 0; - } - totalListeningPacketCount[ithread]++; - if(getFrameandPacketNumber(ithread, buffer[ithread] + offset,fi,pi,si,bi) == FAIL){ - pi = ALL_MASK_32; //got 0 from fpga - fi = ALL_MASK_32; - totalIgnoredPacketCount[ithread] += (pnum + 1); - } - else if(myDetectorType == EIGER) - fnum = fi; //update currentfnum for eiger (next packets should have currentfnum value) -#ifdef VERBOSE - if(!ithread) cout << "next currentpnum :" << pnum << endl; -#endif - } - - //------------------------------------------------------ wrong packet -------------------------------------------------------- - else{ -#ifdef VERBOSE - if(!ithread) cprintf(RED,"wrong packet %d, expected packet %d fnum of last good one:%d\n", - pi,pnum,(*((uint32_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS)))); -#endif - if(myDetectorType == JUNGFRAU) - totalIgnoredPacketCount[ithread] += (packetsPerFrame - pnum -1); //extra 1 subtracted now to be added in the while loop anyway - else - totalIgnoredPacketCount[ithread] += pnum; //extra 1 subtracted now to be added in the while loop anyway - pnum = FIRSTPNUM; - offset = fifoBufferHeaderSize; - - //find the start of next image - while(pnum != pi){ - totalIgnoredPacketCount[ithread]++; - - rc=0; - if(status != TRANSMITTING) - rc = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + offset); - if(rc <= 0){ - if(myDetectorType == JUNGFRAU) - totalIgnoredPacketCount[ithread] += (packetsPerFrame - pnum); - else - totalIgnoredPacketCount[ithread] += (pnum + 1); - return 0; - } - totalListeningPacketCount[ithread]++; - if(getFrameandPacketNumber(ithread, buffer[ithread] + offset,fi,pi,si,bi) == FAIL){ - pi = ALL_MASK_32; //got 0 from fpga - fi = ALL_MASK_32; - } -#ifdef VERBOSE - if(!ithread) cout << "trying to find pnum:" << pnum << " got " << pi << endl; -#endif - } - if(fi!=ALL_MASK_32) - fnum = fi; //fnum of first packet - bnum = bi; //bnum of first packet - } - } - //------------------------------------------------------ got a complete frame -------------------------------------------------------- - - //write frame number - (*((uint64_t*)(buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS))) = fnum + startAcquisitionIndex; -#ifdef VERBOSE - if(!ithread) cout << "fnum:" << (*((uint64_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS))) << endl; -#endif - if(myDetectorType == JUNGFRAU) - (*((uint64_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS + FILE_HEADER_BUNCHID_OFFSET))) = bnum; - //write packet count to buffer - *((uint32_t*)(buffer[ithread])) = packetsPerFrame; - return bufferSize; -} - - - -void UDPStandardImplementation::startFrameIndices(int ithread){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - - jfrau_packet_header_t* header=0; - switch(myDetectorType){ - case EIGER: - startFrameIndex = 1; //frame number always resets - break; - case JUNGFRAU: - header = (jfrau_packet_header_t*)(buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS); - startFrameIndex = (*( (uint32_t*) header->frameNumber))&frameIndexMask; - break; - default: - if(shortFrameEnable < 0){ - startFrameIndex = (((((uint32_t)(*((uint32_t*)(buffer[ithread] + fifoBufferHeaderSize))))+1) - & (frameIndexMask)) >> frameIndexOffset); - }else{ - startFrameIndex = ((((uint32_t)(*((uint32_t*)(buffer[ithread]+fifoBufferHeaderSize)))) - & (frameIndexMask)) >> frameIndexOffset); - } - break; - } - - //start of entire acquisition - if(!acqStarted){ - pthread_mutex_lock(&progressMutex); - startAcquisitionIndex = startFrameIndex; - acqStarted = true; - pthread_mutex_unlock(&progressMutex); - cprintf(BLUE,"Listening_Thread %d: startAcquisitionIndex:%lld\n",ithread,(long long int)startAcquisitionIndex); - } - - //set start of scan/real time measurement - cprintf(BLUE,"Listening_Thread %d: startFrameIndex: %lld\n", ithread,(long long int)startFrameIndex); - measurementStarted[ithread] = true; -} - - - - - - - -void UDPStandardImplementation::stopListening(int ithread, int numbytes){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - -#ifdef DEBUG4 - cprintf(BLUE,"Listening_Thread %d: Stop Listening\nStatus: %s numbytes:%d\n", ithread, runStatusType(status).c_str(),numbytes); -#endif - - //free empty buffer - if(numbytes <= 0){ - FILE_LOG(logINFO) << "Listening "<< ithread << ": End of Acquisition"; - while(!fifoFree[ithread]->push(buffer[ithread])); - } - - - //push last non empty buffer into fifo - else{ - if(excludeMissingPackets){ - (*((uint32_t*)(buffer[ithread]))) = numbytes/oneDataSize; - totalListeningPacketCount[ithread] += (numbytes/oneDataSize); - }else{ - (*((uint32_t*)(buffer[ithread]))) = numbytes/onePacketSize; - totalListeningPacketCount[ithread] += (numbytes/onePacketSize); - } -#ifdef DEBUG - cprintf(BLUE,"Listening_Thread %d: Last Buffer numBytes:%d\n",ithread, numbytes); - cprintf(BLUE,"Listening_Thread %d: Last Buffer packet count:%d\n",ithread,(*((uint32_t*)(buffer[ithread]))) ); -#endif - while(!fifo[ithread]->push(buffer[ithread])); - } - - //push dummy-end buffer into fifo for all writer threads - fifoFree[ithread]->pop(buffer[ithread]); - - //creating dummy-end buffer with pc=0xFFFF - (*((uint32_t*)(buffer[ithread]))) = dummyPacketValue; - while(!fifo[ithread]->push(buffer[ithread])); - - - //reset mask and exit loop - pthread_mutex_lock(&statusMutex); - listeningThreadsMask^=(1<> frameIndexOffset)); -#endif - cSize = onePacketSize; - --packetCount; - } - } -#ifdef DEBUG4 - cprintf(BLUE, "Listening_Thread %d: First Header:%d\n", (((((uint32_t)(*((uint32_t*)(buffer[ithread] + fifoBufferHeaderSize))))+1) - & (frameIndexMask)) >> frameIndexOffset)); -#endif - break; - - case MOENCH: - lastPacketOffset = (((packetCount - 1) * onePacketSize) + fifoBufferHeaderSize); -#ifdef DEBUG4 - cprintf(BLUE, "Listening_Thread %d: First Header:%d\t First Packet:%d\t Last Header:%d\t Last Packet:%d\tLast Packet Offset:%d\n", - (((((uint32_t)(*((uint32_t*)(buffer[ithread]+fifoBufferHeaderSize))))) & (frameIndexMask)) >> frameIndexOffset), - ((((uint32_t)(*((uint32_t*)(buffer[ithread]+fifoBufferHeaderSize))))) & (packetIndexMask)), - (((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastpacketoffset))))) & (frameIndexMask)) >> frameIndexOffset), - ((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastpacketoffset))))) & (packetIndexMask)), - lastPacketOffset); -#endif - //moench last packet value is 0, so find the last packet and store the others in a temp storage - if( ((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastPacketOffset))))) & (packetIndexMask))){ - lastFrameHeader = ((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastPacketOffset))))) - & (frameIndexMask)) >> frameIndexOffset; - cSize += onePacketSize; - lastPacketOffset -= onePacketSize; - --packetCount; - while (lastFrameHeader == (((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastPacketOffset))))) & (frameIndexMask)) >> frameIndexOffset)){ - cSize += onePacketSize; - lastPacketOffset -= onePacketSize; - --packetCount; - } - memcpy(temp, buffer[ithread]+(lastPacketOffset+onePacketSize), cSize); -#ifdef DEBUG4 - cprintf(BLUE, "Listening_Thread %d: temp Header:%d\t temp Packet:%d\n", - (((((uint32_t)(*((uint32_t*)(temp)))))& (frameIndexMask)) >> frameIndexOffset), - ((((uint32_t)(*((uint32_t*)(temp))))) & (packetIndexMask))); -#endif - } - break; - - default: - cprintf(RED,"Listening_Thread %d: Error: This detector %s is not implemented in the receiver\n", - ithread, getDetectorType(myDetectorType).c_str()); - break; - } - -#ifdef DEBUG4 - cprintf(BLUE,"Listening_Thread %d: PacketCount:%d CarryonBufferSize:%d\n",ithread, packetCount, cSize); -#endif - - return packetCount; -} - - - - - - -void UDPStandardImplementation::startWriting(){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - int ithread = currentThreadIndex; //set current thread value index - threadStarted = 1; //let calling function know thread started and obtained current - - char* wbuf = NULL; //buffer popped from FIFO - sfilefd[ithread] = 0; //file pointer - uint64_t nf = 0; //for compression, number of frames - - - /* outer loop - loops once for each acquisition */ - //infinite loop, exited only to change dynamic range, 10G parameters etc (then recreated again) - while(true){ - - //--reset parameters before acquisition (depending on compression) - nf = 0; //compression has only one listening thread (anything not eiger) - - - /* inner loop - loop for each buffer */ - //until mask unset (udp sockets shut down by client) - while((1 << ithread) & writerThreadsMask){ - - //pop - if(!dataCompressionEnable) - fifo[ithread]->pop(wbuf); - else - fifo[0]->pop(wbuf); - uint32_t numPackets = (uint32_t)(*((uint32_t*)wbuf)); - -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread %d: Number of Packets: %d for FIFO %d\n", ithread, numPackets, dataCompressionEnable?0:ithread); -#endif - - - //end of acquisition - if(numPackets == dummyPacketValue){ -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread %d: Dummy frame popped out of FIFO %d",ithread, dataCompressionEnable?0:ithread); -#endif - stopWriting(ithread,wbuf); - continue; - } - - //jungfrau and eiger - if(excludeMissingPackets) - handleCompleteFramesOnly(ithread, wbuf); - //normal - else if(!dataCompressionEnable) - handleWithoutDataCompression(ithread, wbuf, numPackets); - - //compression - else{ -#if defined(MYROOT1) && defined(ALLFILE_DEBUG) - if(npackets > 0) - writeFileWithoutCompression(wbuf, numPackets); -#endif - handleDataCompression(ithread,wbuf,nf); - } - }/*--end of loop for each buffer (inner loop)*/ - - waitWritingBufferForNextAcquisition(ithread); - - }/*--end of loop for each acquisition (outer loop) */ -} - - - - - - - - -void UDPStandardImplementation::waitWritingBufferForNextAcquisition(int ithread){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //in case they are not closed already - closeFile(ithread); -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread %d: Done with acquisition. Waiting for 1st sem to create new file/change of parameters\n", ithread); -#endif - //end of acquisition, wait for file create/change of parameters - sem_wait(&writerSemaphore[ithread]); - //check to exit thread (for change of parameters) - only EXIT possibility - if(killAllWritingThreads){ - cprintf(GREEN,"Writing_Thread %d:Goodbye!\n",ithread); - pthread_exit(NULL); - } -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread %d: Got 1st post. Creating File\n", ithread); -#endif - - - //pop fifo so that its empty - char* temp; - while(!fifo[ithread]->isEmpty()){ - cprintf(RED,"%d:fifo emptied\n", ithread); - fifo[ithread]->pop(temp); - fifoFree[ithread]->push(temp); - } - - //create file - if((1<push(wbuffer)); - - if(dataStreamEnable){ - sem_wait(&writerGuiSemaphore[ithread]); //ensure previous frame was processed - guiNumPackets[ithread] = dummyPacketValue; - sem_post(&dataCallbackWriterSemaphore[ithread]); //let it know its got data - } - - - //all threads need to close file, reset mask and exit loop - if(fileWriteEnable && (cbAction > DO_NOTHING)){ - if(fileFormatType == BINARY && myDetectorType == EIGER){ - updateFileHeader(ithread); - fseek(sfilefd[ithread],0,0); - fwrite((void*)fileHeader[ithread], 1, FILE_HEADER_SIZE, sfilefd[ithread]); - } - } - - //Print packet loss - //if(totalWritingPacketCountFromLastCheck[ithread]){ -#ifdef VERBOSE - if(fileFormatType == BINARY){ - if(numberofWriterThreads>1){ - printf("Thread:%d" - "\tLost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - ithread, - ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) - ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) - :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), - (long long int)totalWritingPacketCountFromLastCheck[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousCheck[ithread] - ); - }else{ - printf("Lost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) - ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) - :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), - (long long int)totalWritingPacketCountFromLastCheck[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousCheck[ithread] - ); - } - - if(numberofWriterThreads>1){ - cprintf(BLUE,"File:%s" - "\nThread:%d" - "\tLost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - completeFileName[ithread],ithread, - ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) - ?(long long int)((numberOfFrames-(frameNumberInPreviousFile[ithread]+1))*packetsPerFrame - totalPacketsInFile[ithread]) - :(long long int)((frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread])*packetsPerFrame - totalPacketsInFile[ithread]), - (long long int)totalPacketsInFile[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousFile[ithread] - ); - }else{ - cprintf(BLUE,"File:%s" - "\nLost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - completeFileName[ithread], - ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) - ?(long long int)(numberOfFrames-(frameNumberInPreviousFile[ithread]+1)) - :(long long int)(frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread]), - (long long int)totalPacketsInFile[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousFile[ithread] - ); - } - } -#endif - //} - - closeFile(ithread); - pthread_mutex_lock(&statusMutex); - writerThreadsMask^=(1<push(wbuffer)); - + //to increase Socket Receiver Buffer size + sprintf(command,"echo $((%d)) > /proc/sys/net/core/rmem_max",RECEIVE_SOCKET_BUFFER_SIZE); + if (system(command)){ + FILE_LOG(logWARNING) << "No root permission to change Socket Receiver Buffer size (/proc/sys/net/core/rmem_max)"; return; } + FILE_LOG(logINFO) << "Socket Receiver Buffer size (/proc/sys/net/core/rmem_max) modified to " << RECEIVE_SOCKET_BUFFER_SIZE ; - //callback to write data - if (cbAction < DO_EVERYTHING) - rawDataReadyCallBack((int)tempframenumber, wbuffer + fifoBufferHeaderSize, npackets * onePacketSize, - sfilefd[ithread], latestData[ithread],pRawDataReady);//know which thread from sfilefd - - - //write to file if enabled and update write parameters - if(npackets > 0) - writeFileWithoutCompression(ithread, wbuffer, npackets); -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread: Writing done\nGoing to copy frame\n"); -#endif - - - //copy frame for gui - //if(npackets >= (packetsPerFrame/numberofListeningThreads)) - if(dataStreamEnable && npackets > 0) - copyFrameToGui(ithread, wbuffer,npackets); -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread: Copied frame\n"); -#endif - - - //free fifo addresses - int listenfifoThread = ithread; - if(dataCompressionEnable) - listenfifoThread = 0; - while(!fifoFree[listenfifoThread]->push(wbuffer)); -#ifdef EVERYFIFODEBUG - if(fifoFree[listenfifoThread]->getSemValue()<100) - cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",listenfifoThread,fifoFree[listenfifoThread]->getSemValue(),(void*)(wbuffer)); -#endif -#ifdef DEBUG5 - cprintf(GREEN,"Writing_Thread %d: Freed buffer, pushed into fifofree %p for listener %d \n",listenfifoThread, (void*)(wbuffer), listenfifoThread); -#endif - -} - - - - -void UDPStandardImplementation::handleCompleteFramesOnly(int ithread, char* wbuffer){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //get current frame number - uint64_t tempframenumber; - tempframenumber = (*((uint64_t*)(wbuffer+HEADER_SIZE_NUM_TOT_PACKETS))); - tempframenumber -= startFrameIndex; - - - if (cbAction < DO_EVERYTHING) - rawDataReadyCallBack((int)tempframenumber, wbuffer + HEADER_SIZE_NUM_TOT_PACKETS, bufferSize + FILE_FRAME_HEADER_LENGTH, - sfilefd[ithread], latestData[ithread],pRawDataReady); - - - //write to file if enabled and update write parameters - if((fileWriteEnable) && (sfilefd[ithread] -#ifdef HDF5C - ||hdf5_fileId[ithread])){ -#else - )){ -#endif - - if(fileFormatType == BINARY){ - if(tempframenumber && (tempframenumber%maxFramesPerFile) == 0) - createNewFile(ithread); - fwrite(wbuffer + HEADER_SIZE_NUM_TOT_PACKETS, 1, (bufferSize + FILE_FRAME_HEADER_LENGTH), sfilefd[ithread]); - } - - - -#ifdef HDF5C - else if (fileFormatType == HDF5){ - pthread_mutex_lock(&writeMutex); - - /* if(tempframenumber && (tempframenumber%MAX_IMAGES_IN_DATASET) == 0){ - try{ - Exception::dontPrint(); //to handle errors - if(hdf5_datasetId[ithread]) {delete hdf5_datasetId[ithread]; hdf5_datasetId[ithread] = 0;} - char dsetname[100]; - sprintf(dsetname, "/entry/data/data_%012lld", (long long int)currentFrameNumber[ithread]+1); - //create new dataspace if fewer than max images/dataset - int numimagesindataset = (((numberOfFrames-tempframenumber) < MAX_IMAGES_IN_DATASET)? (numberOfFrames-tempframenumber):MAX_IMAGES_IN_DATASET); - if(numimagesindataset MAX_CHUNKED_IMAGES){ - DSetCreatPropList plist; - hsize_t chunk_dims[3] ={MAX_CHUNKED_IMAGES, NY, NX}; - if(dynamicRange == 4) - chunk_dims[2] = NX/2; - plist.setChunk(3, chunk_dims); - - hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( - dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread],plist)); - } - else - hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( - dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread])); - - //link - char linkPath[1000]=""; - sprintf(linkPath,"/entry/data/%s",dsetname); - hdf5_fileId[ithread]->link(H5G_LINK_HARD,dsetname,linkPath); - } - catch(Exception error){ - cprintf(RED,"Error in closing HDF5 dataset to create a new one in thread %d\n",ithread); - error.printError(); - } - } -*/ - struct timespec begin,end; - if(!ithread && !tempframenumber) - clock_gettime(CLOCK_REALTIME, &begin); - - //wite to file - hsize_t count[3] = {1, NY,NX}; - hsize_t start[3] = {tempframenumber%MAX_IMAGES_IN_DATASET, 0 , 0}; - hsize_t dims2[2]={NY,NX}; - if(dynamicRange == 4){ - dims2[1] = NX/2; - count[1] = NX/2; - } - - try{ - Exception::dontPrint(); //to handle errors - hdf5_dataspaceId[ithread]->selectHyperslab( H5S_SELECT_SET, count, start); - DataSpace memspace(2,dims2); - hdf5_datasetId[ithread]->write(wbuffer + fifoBufferHeaderSize, hdf5_datatype, memspace, *hdf5_dataspaceId[ithread]); - memspace.close(); - } - catch(Exception error){ - cprintf(RED,"Error in writing to file in thread %d\n",ithread); - error.printError(); - } - - if(!ithread && !tempframenumber){ - clock_gettime(CLOCK_REALTIME, &end); - cprintf(RED,"%d Writing packets Elapsed time:%f seconds\n",ithread,( end.tv_sec - begin.tv_sec ) + ( end.tv_nsec - begin.tv_nsec ) / 1000000000.0); - } - - pthread_mutex_unlock(&writeMutex); - } -#endif - - } - - - //progress - if(tempframenumber && (tempframenumber%(maxFramesPerFile/progressFrequency)) == 0){ - if(numberofWriterThreads>1){ - printf("Thread:%d" - "\tLost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - ithread, - ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) - ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) - :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), - (long long int)totalWritingPacketCountFromLastCheck[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousCheck[ithread] - ); - }else{ - printf("Lost:%lld" - "\t\tPackets:%lld" - "\tFrame#:%lld" - "\tPFrame#:%lld\n", - ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) - ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) - :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), - (long long int)totalWritingPacketCountFromLastCheck[ithread], - (long long int)currentFrameNumber[ithread], - (long long int)frameNumberInPreviousCheck[ithread] - ); - } - //reset counters for each new file - frameNumberInPreviousCheck[ithread] = currentFrameNumber[ithread]; - totalWritingPacketCountFromLastCheck[ithread] = 0; - } - - totalWritingPacketCountFromLastCheck[ithread]+= packetsPerFrame; - totalPacketsInFile[ithread] += packetsPerFrame; - totalWritingPacketCount[ithread] += packetsPerFrame; - lastFrameNumberInFile[ithread] = tempframenumber; - currentFrameNumber[ithread] = tempframenumber; - //cout<<"curentframenumber:"< 1) - pthread_mutex_lock(&writeMutex); - - packetsCaught += packetsPerFrame; - totalPacketsCaught += packetsPerFrame; - if((currentFrameNumber[ithread] - startAcquisitionIndex) > acquisitionIndex) - acquisitionIndex = currentFrameNumber[ithread] - startAcquisitionIndex; - if((currentFrameNumber[ithread] - startFrameIndex) > frameIndex[ithread]) - frameIndex[ithread] = currentFrameNumber[ithread] - startFrameIndex; - - if(numberofWriterThreads > 1) - pthread_mutex_unlock(&writeMutex); - - if(!activated) - currentFrameNumber[ithread]++; - -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread: Writing done\nGoing to copy frame\n"); -#endif - - - //copy frame for gui - if(dataStreamEnable) - copyFrameToGui(ithread, wbuffer, packetsPerFrame); -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread: Copied frame\n"); -#endif - - - //free fifo addresses - while(!fifoFree[ithread]->push(wbuffer)); -#ifdef DEBUG5 - cprintf(GREEN,"Writing_Thread %d: Freed buffer, pushed into fifofree %p for listener %d \n",ithread, (void*)(wbuffer), ithread); -#endif - -} - - - -void UDPStandardImplementation::writeFileWithoutCompression(int ithread, char* wbuffer,uint32_t numpackets){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //if write enabled - if((fileWriteEnable) && (sfilefd[ithread])){ - if(numpackets){ - int offset = fifoBufferHeaderSize; - uint64_t nextFileFrameNumber; - int packetsWritten = 0; - //if(ithread) cout<<"numpackets:"<=0)){ - //get start frame (required to create new file at the right juncture) - uint64_t startframe = 0; - uint32_t pnum = 0; - uint32_t snum = 0; - uint64_t bunchid = 0; - //if(ithread) cout<<"getting start frame number"<push(wbuffer)); - return; - } - //if(ithread) cout<<"done getting start frame number"<=0) &&(!((lastFrameNumberInFile[ithread]+1) % maxFramesPerFile))) - createNewFile(ithread); - - - //frames to save in one file - nextFileFrameNumber = (lastFrameNumberInFile[ithread]+1) + - (maxFramesPerFile - ((lastFrameNumberInFile[ithread]+1)%maxFramesPerFile)); - - if(writeUptoFrameNumber(ithread, wbuffer, offset, nextFileFrameNumber, numpackets, packetsWritten) == FAIL) - //weird frame number of zero from fpga - return; - - //update stats - numpackets -= packetsWritten; - totalPacketsInFile[ithread] += packetsWritten; - totalWritingPacketCount[ithread] += packetsWritten; - pthread_mutex_lock(&writeMutex); - packetsCaught += packetsWritten; - totalPacketsCaught += packetsWritten; - pthread_mutex_unlock(&writeMutex); - currentFrameNumber[ithread] = lastFrameNumberInFile[ithread]; - } - } - } - - //only update parameters - else{ - - if(numpackets){ - //get last frame number - uint64_t finalLastFrameNumberToSave = 0; - uint32_t pnum; - uint32_t snum; - uint64_t bunchid = 0; - if(getFrameandPacketNumber(ithread, wbuffer + fifoBufferHeaderSize + ((numpackets - 1) * onePacketSize), finalLastFrameNumberToSave,pnum,snum,bunchid) == FAIL){ - //error in frame number sent by fpga - while(!fifoFree[ithread]->push(wbuffer)); - return; - } - totalPacketsInFile[ithread] += numpackets; - totalWritingPacketCount[ithread] += numpackets; - lastFrameNumberInFile[ithread] = finalLastFrameNumberToSave; - currentFrameNumber[ithread] = finalLastFrameNumberToSave; - - } - - if(numberofWriterThreads > 1) pthread_mutex_lock(&writeMutex); - packetsCaught += numpackets; - totalPacketsCaught += numpackets; - if(numberofWriterThreads > 1) pthread_mutex_unlock(&writeMutex); - } - - //set indices - pthread_mutex_lock(&progressMutex); - if((currentFrameNumber[ithread] - startAcquisitionIndex) > acquisitionIndex) - acquisitionIndex = currentFrameNumber[ithread] - startAcquisitionIndex; - if((currentFrameNumber[ithread] - startFrameIndex) > frameIndex[ithread]) - frameIndex[ithread] = currentFrameNumber[ithread] - startFrameIndex; - pthread_mutex_unlock(&progressMutex); -} - - - - - - -void UDPStandardImplementation::updateFileHeader(int ithread){ - //update file header - time_t t = time(0); - sprintf(fileHeader[ithread], - "\nHeader\t\t: %d bytes\n" - "Top\t\t: %d\n" - "Left\t\t: %d\n" - "Active\t\t: %d\n" - "Frames Caught\t: %lld\n" - "Frames Lost\t: %lld\n" - "Dynamic Range\t: %d\n" - "Ten Giga\t: %d\n" - "Image Size\t: %d bytes\n" - "x\t\t: %d pixels\n" - "y\t\t: %d pixels\n" - "Total Frames\t: %lld\n" - "Exptime (ns)\t: %lld\n" - "Period (ns)\t: %lld\n" - "Timestamp\t: %s\n\n" - - "#Frame Header\n" - "Frame Number\t: 8 bytes\n" - "Bunch ID\t: 8 bytes\n", - FILE_HEADER_SIZE, - (flippedData[0]?0:1), - (ithread?0:1), - activated, - (long long int)(totalPacketsInFile[ithread]/packetsPerFrame), - ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) - ?(long long int)((numberOfFrames-(frameNumberInPreviousFile[ithread]+1)) - (totalPacketsInFile[ithread]/packetsPerFrame)) - :(long long int)((frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread]) - (totalPacketsInFile[ithread]/packetsPerFrame)), - dynamicRange,tengigaEnable, - bufferSize, - //only for eiger right now - EIGER_PIXELS_IN_ONE_ROW,EIGER_PIXELS_IN_ONE_COL, - (long long int)numberOfFrames, - (long long int)acquisitionTime, - (long long int)acquisitionPeriod, - ctime(&t)); - if(strlen(fileHeader[ithread]) > FILE_HEADER_SIZE) - cprintf(BG_RED,"File Header Size %d is too small for fixed file header size %d\n",(int)strlen(fileHeader[ithread]),(int)FILE_HEADER_SIZE); - - -} - -//called only if datacallback enabled -void UDPStandardImplementation::copyFrameToGui(int ithread, char* buffer, uint32_t numpackets){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //if nthe frame, wait for your turn (1st frame always shown as its zero) - if(frameToGuiFrequency && ((frametoGuiCounter[ithread])%frameToGuiFrequency)); - - //random read (gui ready) or nth frame read: gui needs data now or it is the first frame - else{ - -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread: CopyingFrame: Going to copy data\n"); -#endif - //ensure previous frame was processed - sem_wait(&writerGuiSemaphore[ithread]); - - //copy date - guiNumPackets[ithread] = numpackets; - strcpy(guiFileName[ithread],completeFileName[ithread]); - - if(excludeMissingPackets) //copy also the header - memcpy(latestData[ithread],buffer+HEADER_SIZE_NUM_TOT_PACKETS, bufferSize + FILE_FRAME_HEADER_LENGTH); - else //copy only the data - memcpy(latestData[ithread],buffer+ fifoBufferHeaderSize , numpackets*onePacketSize); - //let it know its got data - sem_post(&dataCallbackWriterSemaphore[ithread]); - -#ifdef DEBUG4 - cprintf(GREEN,"Writing_Thread: CopyingFrame: Copied Data\n"); -#endif - - } - - //update the counter for nth frame - if(frameToGuiFrequency) - frametoGuiCounter[ithread]++; - - -} - - - - - -void UDPStandardImplementation::handleDataCompression(int ithread, char* wbuffer, uint64_t &nf){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - - //get frame number - uint64_t tempframenumber=-1; - uint32_t pnum; - uint32_t snum; - uint64_t bunchid=-1; - if(getFrameandPacketNumber(ithread, wbuffer + fifoBufferHeaderSize, tempframenumber,pnum,snum,bunchid) == FAIL){ - //error in frame number sent by fpga - while(!fifoFree[ithread]->push(wbuffer)); + // to increase Max length of input packet queue + sprintf(command,"echo %d > /proc/sys/net/core/netdev_max_backlog",MAX_SOCKET_INPUT_PACKET_QUEUE); + if (system(command)){ + FILE_LOG(logWARNING) << "No root permission to change Max length of input packet queue (/proc/sys/net/core/netdev_max_backlog)"; return; } - currentFrameNumber[ithread] = tempframenumber; - - - //set indices - pthread_mutex_lock(&progressMutex); - if((currentFrameNumber[ithread] - startAcquisitionIndex) > acquisitionIndex) - acquisitionIndex = currentFrameNumber[ithread] - startAcquisitionIndex; - if((currentFrameNumber[ithread] - startFrameIndex) > frameIndex[ithread]) - frameIndex[ithread] = currentFrameNumber[ithread] - startFrameIndex; - pthread_mutex_unlock(&progressMutex); - - //variable definitions - char* buff[2]={0,0}; //an array just to be compatible with copyframetogui - char* data = wbuffer+ fifoBufferHeaderSize; //data pointer to the next memory to be analysed - int ndata; //size of data returned - uint32_t np; //remaining number of packets returned - uint32_t npackets = (uint32_t)(*((uint32_t*)wbuffer)); //number of total packets - int remainingsize = npackets * onePacketSize; //size of the memory slot to be analyzed - - eventType thisEvent = PEDESTAL; - int once = 0; - int xmax = 0, ymax = 0; //max pixels in x and y direction - int xmin = 1, ymin = 1; //min pixels in x and y direction - double tot, tl, tr, bl, br; - - //determining xmax and ymax - switch(myDetectorType){ - case MOENCH: - xmax = MOENCH_PIXELS_IN_ONE_ROW-1; - ymax = MOENCH_PIXELS_IN_ONE_ROW-1; - break; - case GOTTHARD: - if(shortFrameEnable == -1){ - xmax = GOTTHARD_PIXELS_IN_ROW-1; - ymax = GOTTHARD_PIXELS_IN_COL-1; - }else{ - xmax = GOTTHARD_SHORT_PIXELS_IN_ROW-1; - ymax = GOTTHARD_SHORT_PIXELS_IN_COL-1; - } - break; - default: - break; - } - - while(buff[0] = receiverData[ithread]->findNextFrame(data,ndata,remainingsize)){ - - //remaining number of packets - np = ndata/onePacketSize; - - if ((np == packetsPerFrame) && (buff[0]!=NULL)){ - if(nf == 1000) - cprintf(GREEN, "Writing_Thread %d: pedestal done\n", ithread); - - singlePhotonDetectorObject[ithread]->newFrame(); - - //only for moench - if(commonModeSubtractionEnable){ - for(int ix = xmin - 1; ix < xmax+1; ix++){ - for(int iy = ymin - 1; iy < ymax+1; iy++){ - thisEvent = singlePhotonDetectorObject[ithread]->getEventType(buff[0], ix, iy, 0); - } - } - } - - - for(int ix = xmin - 1; ix < xmax+1; ix++) - for(int iy = ymin - 1; iy < ymax+1; iy++){ - thisEvent=singlePhotonDetectorObject[ithread]->getEventType(buff[0], ix, iy, commonModeSubtractionEnable); - if (nf>1000) { - tot=0; - tl=0; - tr=0; - bl=0; - br=0; - if (thisEvent==PHOTON_MAX) { - receiverData[ithread]->getFrameNumber(buff[0]); - //iFrame=receiverData[ithread]->getFrameNumber(buff); -#ifdef MYROOT1 - myTree[ithread]->Fill(); - //cout << "Fill in event: frmNr: " << iFrame << " ix " << ix << " iy " << iy << " type " << thisEvent << endl; -#else - pthread_mutex_lock(&writeMutex); - if((fileWriteEnable) && (sfilefd[0])) - singlePhotonDetectorObject[ithread]->writeCluster(sfilefd[0]); - pthread_mutex_unlock(&writeMutex); -#endif - } - } - } - - nf++; - - -#ifndef ALLFILE - totalPacketsInFile[ithread] += (bufferSize/packetsPerFrame); - totalWritingPacketCount[ithread] += (bufferSize/packetsPerFrame); - pthread_mutex_lock(&writeMutex); - if((packetsCaught%packetsPerFrame) >= (uint32_t)maxFramesPerFile) - createNewFile(ithread); - packetsCaught += (bufferSize/packetsPerFrame); - totalPacketsCaught += (bufferSize/packetsPerFrame); - pthread_mutex_unlock(&writeMutex); - - -#endif - if(!once){ - if(dataStreamEnable) - copyFrameToGui(ithread, buff[0],(uint32_t)packetsPerFrame); - once = 1; - } - } - - remainingsize -= ((buff[0] + ndata) - data); - data = buff[0] + ndata; - if(data > (wbuffer + fifoBufferHeaderSize + npackets * onePacketSize) ) - cprintf(BG_RED,"Writing_Thread %d: Error: Compression data goes out of bounds!\n", ithread); - } - - - while(!fifoFree[0]->push(wbuffer)); -#ifdef EVERYFIFODEBUG - if(fifoFree[0]->getSemValue()<100) - cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",0,fifoFree[0]->getSemValue(),(void*)(wbuffer)); -#endif -#ifdef DEBUG5 - cprintf(GREEN,"Writing_Thread %d: Compression free pushed into fifofree %p for listerner 0\n", ithread, (void*)(wbuffer)); -#endif + FILE_LOG(logINFO) << "Max length of input packet queue (/proc/sys/net/core/netdev_max_backlog) modified to " << MAX_SOCKET_INPUT_PACKET_QUEUE ; } -int UDPStandardImplementation::getFrameandPacketNumber(int ithread, char* wbuffer, uint64_t &framenumber, uint32_t &packetnumber,uint32_t &subframenumber, uint64_t &bunchid){ +int UDPStandardImplementation::SetupFifoStructure(){ FILE_LOG(logDEBUG) << __AT__ << " called"; - eiger_packet_footer_t* footer=0; - eiger_packet_header_t* e_header=0; - jfrau_packet_header_t* header=0; - framenumber = 0; - packetnumber = 0; - subframenumber = 0; - bunchid = 0; - switch(myDetectorType){ + //recalculate number of jobs & fifodepth, return if no change + if ((myDetectortype == GOTTHARD) || (myDetectortype = PROPIX)) { - case EIGER: - footer = (eiger_packet_footer_t*)(wbuffer + footerOffset); - framenumber = (uint32_t)(*( (uint64_t*) footer)); - //error in frame number sent by fpga - if(((uint32_t)(*( (uint64_t*) footer)))==0){ - framenumber = 0; - FILE_LOG(logERROR) << "Fifo "<< ithread << ": Frame Number is zero from firmware."; + int oldnumberofjobs = numberofJobs; + //listen to only n jobs at a time + if (frameToGuiFrequency) + numberofJobs = frameToGuiFrequency; + else { + //random freq depends on acquisition period/time (calculate upto 100ms/period) + i = ((acquisitionPeriod > 0) ? + (SAMPLE_TIME_IN_NS/acquisitionPeriod): + ((acquisitionTime > 0) ? (SAMPLE_TIME_IN_NS/acquisitionTime) : SAMPLE_TIME_IN_NS)); + //must be > 0 and < max jobs + numberofJobs = ((i < 1) ? 1 : ((i > MAX_JOBS_PER_THREAD) ? MAX_JOBS_PER_THREAD : i)); + } + FILE_LOG(logINFO) << "Number of Jobs Per Thread:" << numberofJobs << endl; + + + uint32_t oldfifodepth = fifoDepth; + //reduce fifo depth if numberofJobsPerBuffer > 1 (to save memory) + if(numberofJobsPerBuffer >1){ + fifoDepth = ((fifoDepth % numberofJobsPerBuffer) ? + ((fifoDepth/numberofJobsPerBuffer)+1) : //if not directly divisible + (fifoDepth/numberofJobsPerBuffer)); + } + FILE_LOG(logINFO) << "Total Fifo Size:" << fifoSize; + + //no change, return + if ((oldnumberofjobs == numberofJobs) && (oldfifodepth == fifoDepth)) + return OK; + } + + + //delete fifostructure + fifo.clear(); + for ( int i=0; i < numThreads; i++ ) { + + //create fifo structure + bool success = true; + fifo.push_back( new Fifo ((generalData->fifoBufferSize) * numberofJobs + (generalData->fifoBufferHeaderSize), success)); + if (!success){ + cprintf(BG_RED,"Error: Could not allocate memory for listening \n"); return FAIL; } - packetnumber = (*( (uint16_t*) footer->packetNumber))-1; - e_header = (eiger_packet_header_t*) (wbuffer); - subframenumber = *( (uint32_t*) e_header->subFrameNumber); -#ifdef DEBUG4 - if(!ithread) cprintf(GREEN,"Writing_Thread %d: fnum:%lld pnum:%d FPGA_fnum:%d subfnum:%d footeroffset:%d\n", - ithread, - (long long int)framenumber, - packetnumber, - framenumber, - subframenumber, - footerOffset); -#endif - framenumber -= startFrameIndex; - break; - case JUNGFRAU: - header = (jfrau_packet_header_t*)(wbuffer); - framenumber = (*( (uint32_t*) header->frameNumber))&frameIndexMask; - packetnumber = (uint32_t)(*( (uint8_t*) header->packetNumber)); - bunchid = (*((uint64_t*) header->bunchid)); -#ifdef DEBUG4 - cprintf(GREEN, "Writing_Thread %d: fnum:%lld\t pnum:%d bunchid:%lld\n", - (long long int)framenumber, - packetnumber, - (long long int)bunchid); -#endif - framenumber -= startFrameIndex; - break; - - default: - framenumber = ((uint32_t)(*((uint32_t*)(wbuffer)))); - //for gotthard and normal frame, increment frame number to separate fnum and pnum - if (myDetectorType == PROPIX ||(myDetectorType == GOTTHARD && shortFrameEnable == -1)) - framenumber++; - packetnumber = framenumber&packetIndexMask; - framenumber = (framenumber & frameIndexMask) >> frameIndexOffset; -#ifdef DEBUG4 - cprintf(GREEN, "Writing_Thread %d: fnum:%lld\t pnum:%d\n", - (long long int)framenumber, - packetnumber); -#endif - framenumber -= startFrameIndex; - break; + //set the listener & dataprocessor threads to point to the right fifo + listener[i]->SetFifo(fifo[i]); + dataProcessor[i]->SetFifo(fifo[i]); } + FILE_LOG(logINFO) << "Fifo structure(s) reconstructed"; return OK; } - - - - -int UDPStandardImplementation::writeUptoFrameNumber(int ithread, char* wbuffer, int &offset, uint64_t nextFrameNumber, uint32_t numpackets, int &numPacketsWritten){ - FILE_LOG(logDEBUG) << __AT__ << " called"; - //if(ithread) cout<<"at writeUptoFrameNumber " << nextFrameNumber<< endl; - - - int startoffset = offset; - int endoffset = startoffset + numpackets * onePacketSize; - uint64_t tempframenumber=-1; - offset = endoffset; - uint32_t pnum; - uint32_t snum; - uint64_t bunchid=-1; - //get last frame number - if(getFrameandPacketNumber(ithread, wbuffer + (endoffset-onePacketSize), tempframenumber,pnum,snum,bunchid) == FAIL){ - //error in frame number sent by fpga - while(!fifoFree[ithread]->push(wbuffer)); - return FAIL; - } - //last packet's frame number < nextframenumber - if(tempframenumber=nextFrameNumber){ - offset -= bigIncrements; - if(offsetpush(wbuffer)); - return FAIL; - } - } - if(offsetpush(wbuffer)); - return FAIL; - } - } - while(tempframenumberpush(wbuffer)); - return FAIL; - } - } - - - fwrite(wbuffer + startoffset, 1, offset-startoffset, sfilefd[ithread]); - numPacketsWritten += ((offset-startoffset)/onePacketSize); - lastFrameNumberInFile[ithread] = (nextFrameNumber-1); - //if(ithread) cout<<"done with writeUptoFrameNumber" << endl; - return OK; -} - - - - -/** function that returns the name variable from the receiver complete file name prefix - \param fname complete file name prefix - \returns file name -*/ -string UDPStandardImplementation::getNameFromReceiverFilePrefix(string fname) { - int i; - string s=fname; - size_t uscore=s.rfind("_"); - if (sscanf( s.substr(uscore+1,s.size()-uscore-1).c_str(),"d%d",&i)) - s=fname.substr(0,uscore); - return s; -}; - - - - - diff --git a/slsReceiverSoftware/src/UDPStandardImplementation_copy.cpp b/slsReceiverSoftware/src/UDPStandardImplementation_copy.cpp new file mode 100644 index 000000000..ad2f16af0 --- /dev/null +++ b/slsReceiverSoftware/src/UDPStandardImplementation_copy.cpp @@ -0,0 +1,4026 @@ +/********************************************//** + * @file UDPStandardImplementation.cpp + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + + +#include "UDPStandardImplementation.h" + +#include "moench02ModuleData.h" +#include "gotthardModuleData.h" +#include "gotthardShortModuleData.h" + +#include // exit() +#include //set precision for printing parameters for create new file +#include //map +#include +#include +#include +#include + +#include //zmq +#include + + +using namespace std; + +#define WRITE_HEADERS + +/************************************************************************* + * Constructor & Destructor ********************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + +UDPStandardImplementation::UDPStandardImplementation(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + initializeMembers(); + + //***mutex*** + pthread_mutex_init(&statusMutex,NULL); + pthread_mutex_init(&writeMutex,NULL); + pthread_mutex_init(&dataReadyMutex,NULL); + pthread_mutex_init(&progressMutex,NULL); + + //to increase socket receiver buffer size and max length of input queue by changing kernel settings + if(myDetectorType == EIGER); + else if(system("echo $((100*1024*1024)) > /proc/sys/net/core/rmem_max")){ + FILE_LOG(logDEBUG) << "Warning: No root permission to change socket receiver buffer size in file /proc/sys/net/core/rmem_max"; + }else if(system("echo 250000 > /proc/sys/net/core/netdev_max_backlog")){ + FILE_LOG(logDEBUG) << "Warning: No root permission to change max length of input queue in file /proc/sys/net/core/netdev_max_backlog"; + } + + /** permanent setting by heiner + net.core.rmem_max = 104857600 # 100MiB + net.core.netdev_max_backlog = 250000 + sysctl -p + // from the manual + sysctl -w net.core.rmem_max=16777216 + sysctl -w net.core.netdev_max_backlog=250000 + */ +} + +UDPStandardImplementation::~UDPStandardImplementation(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + for(int i=0;i(receiverData[i], csize, sigma, sign, moenchCommonModeSubtraction); +} + + + + +int UDPStandardImplementation::setupFifoStructure(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + + //number of jobs per buffer + int64_t i; + int oldNumberofJobsPerBuffer = numberofJobsPerBuffer; + //eiger always listens to 1 packet at a time + if(excludeMissingPackets){ + numberofJobsPerBuffer = 1; + FILE_LOG(logDEBUG) << "Info: 1 packet per buffer"; + } + //else calculate best possible number of frames to listen to at a time (for fast readouts like gotthard) + else{ + //if frequency to gui is not random (every nth frame), then listen to only n frames per buffer + if(frameToGuiFrequency) + numberofJobsPerBuffer = frameToGuiFrequency; + //random frame sent to gui, then frames per buffer depends on acquisition period + else{ + //calculate 100ms/period to get frames to listen to at a time + if(acquisitionPeriod) + i = SAMPLE_TIME_IN_NS/acquisitionPeriod; + else{ + if(acquisitionTime) + i = SAMPLE_TIME_IN_NS/acquisitionTime; + else + i = SAMPLE_TIME_IN_NS; + } + //max frames to listen to at a time is limited by 1000 + if (i > MAX_JOBS_PER_THREAD) + numberofJobsPerBuffer = MAX_JOBS_PER_THREAD; + else if (i < 1) + numberofJobsPerBuffer = 1; + else + numberofJobsPerBuffer = i; + + } + FILE_LOG(logINFO) << "Number of Frames per buffer:" << numberofJobsPerBuffer << endl; + } + + + + // fifo depth + uint32_t oldFifoSize = fifoSize; + + + //reduce fifo depth if > 1 numberofJobsPerBuffer + if(fifoDepth % numberofJobsPerBuffer) + fifoSize = (fifoDepth/numberofJobsPerBuffer)+1; + else + fifoSize = fifoDepth/numberofJobsPerBuffer; + + //do not rebuild fifo structure if it is the same (oldfifosize differs only for different packetsperframe) + if((oldNumberofJobsPerBuffer == numberofJobsPerBuffer) && (oldFifoSize == fifoSize)) + return OK; + FILE_LOG(logINFO) << "Info: Total Fifo Size:" << fifoSize; + + + + //delete threads + if(threadStarted){ + createListeningThreads(true); + createWriterThreads(true); + } + + + //set up fifo structure + for(int i=0;iisEmpty()){ + fifoFree[i]->pop(buffer[i]); + //cprintf(BLUE,"FifoFree[%d]: value:%d, pop 0x%x\n",i,fifoFree[i]->getSemValue(),(void*)(buffer[i])); + } + delete fifoFree[i]; + fifoFree[i] = 0; + } + if(fifo[i]){ + while(!fifo[i]->isEmpty()){ + fifo[i]->pop(buffer[i]); + //cprintf(CYAN,"Fifo[%d]: value:%d, pop 0x%x\n",i,fifo[i]->getSemValue(),(void*)(buffer[i])); + } + delete fifo[i]; + fifo[i] = 0; + } + if(mem0[i]){ + free(mem0[i]); + mem0[i] = 0; + } + + } + + + for(int i=0;i(fifoSize); + fifo[i] = new CircularFifo(fifoSize); + + //allocate memory + mem0[i] = (char*)calloc((bufferSize * numberofJobsPerBuffer + fifoBufferHeaderSize) * fifoSize,sizeof(char)); + if (mem0[i] == NULL){ + cprintf(BG_RED,"Error: Could not allocate memory for listening \n"); + return FAIL; + } + + //push free address into fifoFree + buffer[i]=mem0[i]; + while (buffer[i] < (mem0[i]+(bufferSize * numberofJobsPerBuffer + fifoBufferHeaderSize) * (fifoSize-1))) { + //cprintf(BLUE,"fifofree %d: push 0x%p\n",i,(void*)buffer[i]); + /*for(int k=0;kpush(buffer[i])); + //cprintf(GREEN,"Fifofree[%d]: value:%d, push 0x%x\n",i,fifoFree[i]->getSemValue(),(void*)(buffer[i])); +#ifdef DEBUG5 + cprintf(BLUE,"Info: %d fifostructure free pushed into fifofree %p\n", i, (void*)(buffer[i])); +#endif + buffer[i] += (bufferSize * numberofJobsPerBuffer + fifoBufferHeaderSize); + } + } + cout << "Fifo structure(s) reconstructed" << endl; + + //create threads + if(createListeningThreads() == FAIL){ + FILE_LOG(logERROR) << "Could not create listening thread"; + return FAIL; + } + if(createWriterThreads() == FAIL){ + FILE_LOG(logERROR) << "Could not create writer threads"; + return FAIL; + } + setThreadPriorities(); + + return OK; +} + + + + + + + + +void UDPStandardImplementation::setFileName(const char c[]){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + char oldfilename[MAX_STR_LENGTH]; + strcpy(oldfilename,fileName); + + if(strlen(c)) + strcpy(fileName, c); + + if(strlen(fileName)){ + int detindex = -1; + string tempname(fileName); + size_t uscore=tempname.rfind("_"); + if (uscore!=string::npos){ + if (sscanf(tempname.substr(uscore+1,tempname.size()-uscore-1).c_str(),"d%d",&detindex)) { + detID = detindex; + } + } + if(detindex == -1) + detID = 0; + } + + FILE_LOG(logINFO) << "File name:" << fileName; +} + +int UDPStandardImplementation::setDataCompressionEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + if(myDetectorType != EIGER){ + cout << "Info: Setting up Data Compression Enable to " << stringEnable(b); +#ifdef MYROOT1 + cout << " WITH ROOT" << endl; +#else + cout << " WITHOUT ROOT" << endl; +#endif + } + + //set data compression enable + dataCompressionEnable = b; + + //-- create writer threads depending on enable + pthread_mutex_lock(&statusMutex); + writerThreadsMask = 0x0; + pthread_mutex_unlock(&(statusMutex)); + + createWriterThreads(true); + if(b) + numberofWriterThreads = MAX_NUMBER_OF_WRITER_THREADS; + else + numberofWriterThreads = 1; + if(createWriterThreads() == FAIL){ + cprintf(BG_RED,"Error: Could not create writer threads\n"); + return FAIL; + } + //-- end of create writer threads + setThreadPriorities(); + + //filter + deleteFilter(); + if(b) + initializeFilter(); + + FILE_LOG(logINFO) << "Data Compression: " << stringEnable(dataCompressionEnable); + + return OK; +} + +/***acquisition count parameters***/ +uint64_t UDPStandardImplementation::getTotalFramesCaught() const{ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + return (totalPacketsCaught/(packetsPerFrame*numberofListeningThreads)); +} + +uint64_t UDPStandardImplementation::getFramesCaught() const{ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + return (packetsCaught/(packetsPerFrame*numberofListeningThreads)); +} + +/***acquisition parameters***/ +void UDPStandardImplementation::setShortFrameEnable(const int i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + shortFrameEnable = i; + + if(shortFrameEnable!=-1){ + bufferSize = GOTTHARD_SHORT_BUFFER_SIZE; + onePacketSize = GOTTHARD_SHORT_BUFFER_SIZE; + oneDataSize = GOTTHARD_SHORT_DATABYTES; + maxFramesPerFile = SHORT_MAX_FRAMES_PER_FILE; + packetsPerFrame = GOTTHARD_SHORT_PACKETS_PER_FRAME; + frameIndexMask = GOTTHARD_SHORT_FRAME_INDEX_MASK; + frameIndexOffset = GOTTHARD_SHORT_FRAME_INDEX_OFFSET; + packetIndexMask = GOTTHARD_SHORT_PACKET_INDEX_MASK; + + }else{ + bufferSize = GOTTHARD_BUFFER_SIZE; + onePacketSize = GOTTHARD_ONE_PACKET_SIZE; + oneDataSize = GOTTHARD_ONE_DATA_SIZE; + maxFramesPerFile = MAX_FRAMES_PER_FILE; + packetsPerFrame = GOTTHARD_PACKETS_PER_FRAME; + frameIndexMask = GOTTHARD_FRAME_INDEX_MASK; + frameIndexOffset = GOTTHARD_FRAME_INDEX_OFFSET; + packetIndexMask = GOTTHARD_PACKET_INDEX_MASK; + } + + //filter + deleteFilter(); + if(dataCompressionEnable) + initializeFilter(); + + FILE_LOG(logINFO) << "Short Frame Enable: " << shortFrameEnable; +} + + +int UDPStandardImplementation::setFrameToGuiFrequency(const uint32_t freq){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + frameToGuiFrequency = freq; + if(setupFifoStructure() == FAIL) + return FAIL; + + FILE_LOG(logINFO) << "Frame to Gui Frequency: " << frameToGuiFrequency; + + return OK; +} + + + +uint32_t UDPStandardImplementation::setDataStreamEnable(const uint32_t enable){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + int oldvalue = dataStreamEnable; + dataStreamEnable = enable; + FILE_LOG(logINFO) << "Data Send to Gui: " << dataStreamEnable; + + + if(oldvalue!=dataStreamEnable){ + //data sockets have to be created again as the client ones are + if(zmqThreadStarted) + createDataCallbackThreads(true); + + if(dataStreamEnable){ + numberofDataCallbackThreads = numberofListeningThreads; + if(createDataCallbackThreads() == FAIL){ + cprintf(BG_RED,"Error: Could not create data callback threads\n"); + } + } + } + + return OK; +} + + + +int UDPStandardImplementation::setAcquisitionPeriod(const uint64_t i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + acquisitionPeriod = i; + if(setupFifoStructure() == FAIL) + return FAIL; + + FILE_LOG(logINFO) << "Acquisition Period: " << (double)acquisitionPeriod/(1E9) << "s"; + + if(myDetectorType == EIGER && fileFormatType == BINARY) + for(int i=0; iShutDownSocket(); + FILE_LOG(logINFO) << "Shut down UDP Socket " << i; + delete udpSocket[i]; + udpSocket[i] = 0; + } + } + return OK; +} + + + + +/** + * Pre: status is running, udp sockets have been initialized, stop receiver initiated + * Post:udp sockets closed, status is transmitting + * */ +void UDPStandardImplementation::startReadout(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + FILE_LOG(logDEBUG) << "Transmitting last data"; + + if(status == RUNNING){ + + + //needs to wait for packets only if activated + if(activated){ + //check if all packets got + int totalP = 0,prev=-1; + for(int i=0; igetCurrentTotalReceived(); + + //wait for all packets + if((unsigned long long int)totalP!=numberOfFrames*packetsPerFrame*numberofListeningThreads){ + + //wait as long as there is change from prev totalP, + //and also change from received in buffer to previous value + //(as one listens to many at a time, shouldnt cut off in between) + while((prev != totalP) || (prevReceivedInBuffer!= currentReceivedInBuffer)){ +#ifdef DEBUG5 + cprintf(MAGENTA,"waiting for all packets prevP:%d totalP:%d PrevBuffer:%d currentBuffer:%d\n",prev,totalP,prevReceivedInBuffer,currentReceivedInBuffer); + +#endif + //usleep(2*1000*1000); + usleep(5*1000);/* Need to find optimal time (exposure time and acquisition period) **/ + prev = totalP; + totalP = 0; + for(int i=0; igetCurrentTotalReceived(); +#ifdef DEBUG5 + cprintf(MAGENTA,"\tupdated: totalP:%d currently in buffer:%d\n",totalP,currentReceivedInBuffer); + +#endif + } + + } + } + + //set status + pthread_mutex_lock(&statusMutex); + status = TRANSMITTING; + pthread_mutex_unlock(&statusMutex); + + FILE_LOG(logINFO) << "Status: Transmitting"; + } + + //shut down udp sockets and make listeners push dummy (end) packets for writers + shutDownUDPSockets(); +} + + + +/**make this better by asking all of it at once*/ +void UDPStandardImplementation::readFrame(int ithread, char* c,char** raw, int64_t &startAcq, int64_t &startFrame){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + +} + + + +void UDPStandardImplementation::closeFile(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called for " << ithread ; + + //normal + if(!dataCompressionEnable){ + if(sfilefd[ithread]){ +#ifdef DEBUG4 + FILE_LOG(logDEBUG4) << "Going to close file: " << fileno(sfilefd)); +#endif + fflush(sfilefd[ithread]); + fclose(sfilefd[ithread]); + sfilefd[ithread] = 0; + } +#ifdef HDF5C + pthread_mutex_lock(&writeMutex); + try{ + Exception::dontPrint(); //to handle errors + if(hdf5_dataspaceId[ithread]) {delete hdf5_dataspaceId[ithread]; hdf5_dataspaceId[ithread] = 0;} + if(hdf5_datasetId[ithread]) {delete hdf5_datasetId[ithread]; hdf5_datasetId[ithread] = 0;} + if(hdf5_fileId[ithread]) {delete hdf5_fileId[ithread]; hdf5_fileId[ithread] = 0;} + if(hdf5_masterFileId) {delete hdf5_masterFileId; hdf5_masterFileId = 0;} + if(hdf5_virtualFileId) {delete hdf5_virtualFileId; hdf5_virtualFileId = 0;} + } + catch(Exception error){ + cprintf(RED,"Error in closing HDF5 handles\n"); + error.printError(); + } + pthread_mutex_unlock(&writeMutex); +#endif + } + + //compression + else{ +#if (defined(MYROOT1) && defined(ALLFILE_DEBUG)) || !defined(MYROOT1) + if(sfilefd[0]){ +#ifdef DEBUG4 + FILE_LOG(logDEBUG4) << "sfilefd: " << (int)sfilefd[0]; +#endif + fclose(sfilefd[0]); + sfilefd[0] = 0; + } +#endif + +#ifdef MYROOT1 + pthread_mutex_lock(&writeMutex); + //write to file + if(myTree[ithread] && myFile[ithread]){ + myFile[ithread] = myTree[ithread]->GetCurrentFile(); + + if(myFile[ithread]->Write()) + //->Write(tall->GetName(),TObject::kOverwrite); + cout << "Thread " << ithread <<": wrote frames to file" << endl; + else + cout << "Thread " << ithread << ": could not write frames to file" << endl; + + }else + cout << "Thread " << ithread << ": could not write frames to file: No file or No Tree" << endl; + //close file + if(myTree[ithread] && myFile[ithread]) + myFile[ithread] = myTree[ithread]->GetCurrentFile(); + if(myFile[ithread] != 0) + myFile[ithread]->Close(); + myFile[ithread] = 0; + myTree[ithread] = 0; + pthread_mutex_unlock(&writeMutex); + +#endif + } +} + + +//eiger only +int UDPStandardImplementation::setActivate(int enable){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + if(enable != -1){ + activated = enable; + FILE_LOG(logINFO) << "Activation: " << stringEnable(activated); + } + + if(fileFormatType == BINARY) + for(int i=0; igetErrorStatus(); + if(!iret){ + cout << "UDP port opened at port " << port[i] << endl; + }else{ + FILE_LOG(logERROR) << "Could not create UDP socket on port " << port[i] << " error: " << iret; + shutDownUDPSockets(); + return FAIL; + } + } + + FILE_LOG(logDEBUG) << "UDP socket(s) created successfully."; + cout << "Listener Ready ..." << endl; + + return OK; +} + + + +int UDPStandardImplementation::setupWriter(){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + //acquisition start call back returns enable write + cbAction = DO_EVERYTHING; + if (startAcquisitionCallBack) + cbAction=startAcquisitionCallBack(filePath,fileNamePerThread[0],(int)fileIndex,bufferSize,pStartAcquisition); + + + if(cbAction < DO_EVERYTHING){ + FILE_LOG(logINFO) << "Call back activated. Data saving must be taken care of by user in call back."; + if (rawDataReadyCallBack){ + FILE_LOG(logINFO) << "Data Write has been defined externally"; + } + }else if(!fileWriteEnable){ + FILE_LOG(logINFO) << "Data will not be saved"; + } + + + //creating first file + //setting all value to 1 + pthread_mutex_lock(&statusMutex); + for(int i=0; i DO_NOTHING){ + + + if(fileFormatType == BINARY){ + //close file pointers + if(sfilefd[ithread]){ + //all threads need to close file, reset mask and exit loop + if(myDetectorType == EIGER && fileWriteEnable && (cbAction > DO_NOTHING)){ + updateFileHeader(ithread); + fseek(sfilefd[ithread],0,0); + fwrite((void*)fileHeader[ithread], 1, FILE_HEADER_SIZE, sfilefd[ithread]); + } + fflush(sfilefd[ithread]); + fclose(sfilefd[ithread]); + sfilefd[ithread] = 0; + } + + + //create file + if(!overwriteEnable){ + if (NULL == (sfilefd[ithread] = fopen((const char *) (completeFileName[ithread]), "wx"))){ + FILE_LOG(logERROR) << "Could not create/overwrite file" << completeFileName[ithread]; + sfilefd[ithread] = 0; + return FAIL; + } + }else if (NULL == (sfilefd[ithread] = fopen((const char *) (completeFileName[ithread]), "w"))){ + FILE_LOG(logERROR) << "Could not create file" << completeFileName[ithread]; + sfilefd[ithread] = 0; + return FAIL; + } + //setting file buffer size to 16mb + setvbuf(sfilefd[ithread],NULL,_IOFBF,FILE_BUF_SIZE); + + + //Print packet loss and filenames + if(totalWritingPacketCount[ithread]){ + if(numberofWriterThreads>1){ + cprintf(BLUE,"File:%s" + "\nThread:%d" + "\tLost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + completeFileName[ithread],ithread, + ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) + ?(long long int)((numberOfFrames-(frameNumberInPreviousFile[ithread]+1))*packetsPerFrame - totalPacketsInFile[ithread]) + :(long long int)((frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread])*packetsPerFrame - totalPacketsInFile[ithread]), + (long long int)totalPacketsInFile[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousFile[ithread] + ); + }else{ + cprintf(BLUE,"File:%s" + "\nLost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + completeFileName[ithread], + ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) + ?(long long int)(numberOfFrames-(frameNumberInPreviousFile[ithread]+1)) + :(long long int)(frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread]), + (long long int)totalPacketsInFile[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousFile[ithread] + ); + } + + }else + printf("Thread:%d File opened:%s\n",ithread, completeFileName[ithread]); + + //write file header + if(myDetectorType == EIGER) + fwrite((void*)fileHeader[ithread], 1, FILE_HEADER_SIZE, sfilefd[ithread]); + } + + +#ifdef HDF5C + else if(fileFormatType == HDF5){ + struct timespec begin,end; + + pthread_mutex_lock(&writeMutex); + if(!ithread) + clock_gettime(CLOCK_REALTIME, &begin); + //closing file + try{ + Exception::dontPrint(); //to handle errors + if(hdf5_dataspaceId[ithread]) {delete hdf5_dataspaceId[ithread]; hdf5_dataspaceId[ithread] = 0;} + if(hdf5_datasetId[ithread]) {delete hdf5_datasetId[ithread]; hdf5_datasetId[ithread] = 0;} + if(hdf5_fileId[ithread]) {delete hdf5_fileId[ithread]; hdf5_fileId[ithread] = 0; } + if(hdf5_masterFileId) {delete hdf5_masterFileId; hdf5_masterFileId = 0;} + if(hdf5_virtualFileId) {delete hdf5_virtualFileId; hdf5_virtualFileId = 0;} + } + catch(AttributeIException error){ + cprintf(RED,"Error in creating attributes in thread %d\n",ithread); + error.printError(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + catch(Exception error){ + cprintf(RED,"Error in closing HDF5 handles in thread %d\n",ithread); + error.printError(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + }//end of closing file + + char masterFileName[1000]="", virtualFileName[1000]=""; + sprintf(masterFileName, "%s/%s_master_%lld.h5", filePath,getNameFromReceiverFilePrefix(fileName).c_str(),(long long int)fileIndex); + sprintf(virtualFileName, "%s/%s_%lld.h5", filePath,getNameFromReceiverFilePrefix(fileName).c_str(),(long long int)fileIndex); + + + //creating file + try{ + Exception::dontPrint(); //to handle errors + + if(!detID && !ithread){ + //creating master file with metadata + try{ + //creating file + FileAccPropList flist; + flist.setFcloseDegree(H5F_CLOSE_STRONG); + if(!overwriteEnable) + hdf5_masterFileId = new H5File( masterFileName, H5F_ACC_EXCL, NULL, flist ); + else + hdf5_masterFileId = new H5File( masterFileName, H5F_ACC_TRUNC, NULL, flist ); + + //create attributes + DataSpace dataspace = DataSpace (H5S_SCALAR); + Attribute attribute; + double dValue=0; + + //version + dValue=HDF5_WRITER_VERSION; + attribute = hdf5_masterFileId->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace); + attribute.write(PredType::NATIVE_DOUBLE, &dValue); + + + //Create a group in the file + Group group1( hdf5_masterFileId->createGroup( "entry" ) ); + Group group2( group1.createGroup("data") ); + Group group3( group1.createGroup("instrument") ); + Group group4( group3.createGroup("beam") ); + Group group5( group3.createGroup("detector") ); + Group group6( group1.createGroup("sample") ); + + + int iValue=0; + StrType strdatatype(PredType::C_S1,256); + DataSet dataset; + + //Dynamic Range + dataset = group5.createDataSet ( "dynamic range", PredType::NATIVE_INT, dataspace ); + dataset.write ( &dynamicRange, PredType::NATIVE_INT); + attribute = dataset.createAttribute("unit",strdatatype, dataspace); + attribute.write(strdatatype, string("bits")); + //Ten Giga + iValue = tengigaEnable; + dataset = group5.createDataSet ( "ten giga enable", PredType::NATIVE_INT, dataspace ); + dataset.write ( &iValue, PredType::NATIVE_INT); + //Image Size + dataset = group5.createDataSet ( "image size", PredType::NATIVE_INT, dataspace ); + dataset.write ( &bufferSize, PredType::NATIVE_INT); + attribute = dataset.createAttribute("unit",strdatatype, dataspace); + attribute.write(strdatatype, string("bytes")); + //x + dataset = group5.createDataSet ( "number of pixels in x axis", PredType::NATIVE_INT, dataspace ); + dataset.write ( &NX, PredType::NATIVE_INT); + //y + dataset = group5.createDataSet ( "number of pixels in y axis", PredType::NATIVE_INT, dataspace ); + dataset.write ( &NY, PredType::NATIVE_INT); + //Total Frames + dataset = group5.createDataSet ( "total frames", PredType::STD_U64LE, dataspace ); + dataset.write ( &numberOfFrames, PredType::STD_U64LE); + //Exptime + dataset = group5.createDataSet ( "exposure time", PredType::STD_U64LE, dataspace ); + dataset.write ( &acquisitionTime, PredType::STD_U64LE); + attribute = dataset.createAttribute("unit",strdatatype, dataspace); + attribute.write(strdatatype, string("ns")); + //Period + dataset = group5.createDataSet ( "acquisition period", PredType::STD_U64LE, dataspace ); + dataset.write ( &acquisitionPeriod, PredType::STD_U64LE); + attribute = dataset.createAttribute("unit",strdatatype, dataspace); + attribute.write(strdatatype, string("ns")); + //Timestamp + time_t t = time(0); + dataset = group5.createDataSet ( "timestamp", strdatatype, dataspace ); + dataset.write ( string(ctime(&t)), strdatatype ); + + group1.close(); + group2.close(); + group3.close(); + group4.close(); + group5.close(); + group6.close(); + + }catch(Exception error){ + cprintf(RED,"Error in creating HDF5 master file in thread %d\n",ithread); + error.printError(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + +/* + // creating virtual file + try{ + FileAccPropList flist; + flist.setFcloseDegree(H5F_CLOSE_STRONG); + if(!overwriteEnable) + hdf5_virtualFileId = new H5File( virtualFileName, H5F_ACC_EXCL, NULL,flist ); + else + hdf5_virtualFileId = new H5File( virtualFileName, H5F_ACC_TRUNC, NULL, flist ); + + //create dataspace for the dataset in the file + char dsetname[100]; + try{ + int numimagesindataset = ((numberOfFrames < MAX_IMAGES_IN_DATASET)? numberOfFrames:MAX_IMAGES_IN_DATASET); + hsize_t srcdims[3] = { numimagesindataset, NY*TILE_NY, NX*TILE*NX }; + if(dynamicRange == 4) + srcdims[2] = NX/2; + DataSpace dataspace(3,srcdims); + sprintf(dsetname, "/virtualdata_%012lld", (long long int)currentFrameNumber[ithread]+1); + + //create property list for a dataset + DSetCreatPropList plist = H5P_DEFAULT; + + //create chunked dataset if greater than max_chunked_images + if(numimagesindataset > MAX_CHUNKED_IMAGES){ + //set up fill values + int fillvalue = -1; /*Aldo suggested its time consuming*/ + + /* + plist.setFillValue(hdf5_datatype, &fillvalue); + hsize_t chunk_dims[3] ={MAX_CHUNKED_IMAGES, srcdims[1], srcdims[2]}; + plist.setChunk(3, chunk_dims); + } + + //Create dataset and write it into the file + hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( + dsetname, hdf5_datatype, dataspace, plist)); + +*/ + + /* fix this to mapp + hsize_t src_dims[1]={NZ}; + hsize_t start[RANK]= {0,0,0},count[RANK] = {1,1,NZ}; + for(int i=0;iclose(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + + }catch(Exception error){ + cprintf(RED,"Error in creating HDF5 file %s in thread %d\n",completeFileName[ithread], ithread); + error.printError(); + hdf5_masterFileId->close(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + */ + + /*//link ... master file should create link to the virtual file.. + try{ + char linkPath[1000]=""; + sprintf(linkPath,"/entry/data/%s",dsetname); + //herr_t H5Lcreate_external( const char *target_file_name, const char *target_obj_name, hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id ) + H5Lcreate_external(masterFileName, dsetname, "/entry/data",dsetname,H5P_DEFAULT,H5P_DEFAULT + //hdf5_fileId[ithread]->link(H5G_LINK_HARD,dsetname,linkPath); + }catch(Exception error){ + cprintf(RED,"Error in creating link in thread %d\n", ithread); + error.printError(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + */ + } + + + //creating file + FileAccPropList flist; + flist.setFcloseDegree(H5F_CLOSE_STRONG); + try{ + if(!overwriteEnable) + hdf5_fileId[ithread] = new H5File( completeFileName[ithread], H5F_ACC_EXCL, NULL,flist ); + else + hdf5_fileId[ithread] = new H5File( completeFileName[ithread], H5F_ACC_TRUNC, NULL, flist ); + }catch(Exception error){ + cprintf(RED,"Error in creating HDF5 file %s in thread %d\n",completeFileName[ithread], ithread); + error.printError(); + hdf5_masterFileId->close(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + //create attributes + + try{ + DataSpace dataspace = DataSpace (H5S_SCALAR); + Attribute attribute; + double dValue=0; + + //version + dValue=HDF5_WRITER_VERSION; + attribute = hdf5_fileId[ithread]->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace); + attribute.write(PredType::NATIVE_DOUBLE, &dValue); + + + int iValue=0; + StrType strdatatype(PredType::C_S1,256); + DataSet dataset; + if(myDetectorType == EIGER){ + //top + iValue = (flippedData[0]?0:1); + attribute = hdf5_fileId[ithread]->createAttribute("top",PredType::NATIVE_INT, dataspace); + attribute.write(PredType::NATIVE_INT, &iValue); + /*dataset = group5.createDataSet ( "top", PredType::NATIVE_INT, dataspace );dataset.write ( &iValue, PredType::NATIVE_INT);*/ + //left + iValue = (ithread?0:1); + attribute = hdf5_fileId[ithread]->createAttribute("left",PredType::NATIVE_INT, dataspace); + attribute.write(PredType::NATIVE_INT, &iValue); + /*dataset = group5.createDataSet ( "left", PredType::NATIVE_INT, dataspace );dataset.write ( &iValue, PredType::NATIVE_INT);*/ + //active + iValue = activated; + attribute = hdf5_fileId[ithread]->createAttribute("active",PredType::NATIVE_INT, dataspace); + attribute.write(PredType::NATIVE_INT, &iValue); + /*dataset = group5.createDataSet ( "active", PredType::NATIVE_INT, dataspace );dataset.write ( &iValue, PredType::NATIVE_INT);*/ + } + + }catch(Exception error){ + cprintf(RED,"Error in creating attribute to file in thread %d\n", ithread); + error.printError(); + hdf5_masterFileId->close(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + //data + //create dataspace for the dataset in the file + char dsetname[100]; + try{ + + /*int numimagesindataset = ((numberOfFrames < MAX_IMAGES_IN_DATASET)? numberOfFrames:MAX_IMAGES_IN_DATASET); + hsize_t srcdims[3] = {numimagesindataset,NY,NX}; + */ + hsize_t srcdims[3] = {numberOfFrames,NY,NX}; + + + if(dynamicRange == 4) + srcdims[2] = NX/2; + hdf5_dataspaceId[ithread] = new DataSpace (3,srcdims); + sprintf(dsetname, "/data_%012lld", (long long int)currentFrameNumber[ithread]+1); + + //create chunked dataset if greater than max_chunked_images + /*if(numimagesindataset > MAX_CHUNKED_IMAGES){*/ + //create property list for a dataset + DSetCreatPropList plist; + //set up fill values + /*Aldo suggested its time consuming*/ + int fillvalue = -1; + plist.setFillValue(hdf5_datatype, &fillvalue); + + hsize_t chunk_dims[3] ={MAX_CHUNKED_IMAGES, NY, srcdims[2]}; + plist.setChunk(3, chunk_dims); + //Create dataset and write it into the file + hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( + dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread], plist)); + /*}else + hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( + dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread]));*/ + }catch(Exception error){ + cprintf(RED,"Error in creating dataset in thread %d\n",ithread); + error.printError(); + hdf5_masterFileId->close(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + } + + } + catch(Exception error){ + cprintf(RED,"Error in creating HDF5 handles in thread %d\n",ithread); + error.printError(); + hdf5_masterFileId->close(); + pthread_mutex_unlock(&writeMutex); + return FAIL; + }//end of creating file + + if(!detID && !ithread){ + if(hdf5_masterFileId) + hdf5_masterFileId->close(); + if(hdf5_virtualFileId) + hdf5_virtualFileId->close(); + } + + if(!ithread){ + clock_gettime(CLOCK_REALTIME, &end); + cprintf(RED,"%d Elapsed time:%f seconds\n",ithread,( end.tv_sec - begin.tv_sec ) + ( end.tv_nsec - begin.tv_nsec ) / 1000000000.0); + } + pthread_mutex_unlock(&writeMutex); + + if(!totalWritingPacketCount[ithread]) + printf("Thread:%d File opened:%s\n",ithread, completeFileName[ithread]); + } +#endif + + } + + //reset counters for each new file + if(totalWritingPacketCount[ithread]){ + frameNumberInPreviousFile[ithread] = currentFrameNumber[ithread]; + totalPacketsInFile[ithread] = 0; + }else{ + frameNumberInPreviousFile[ithread] = -1; + frameNumberInPreviousCheck[ithread] = -1; + } + + + + return OK; +} + + + + +int UDPStandardImplementation::createCompressionFile(int ithread, int iframe){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + +#ifdef MYROOT1 + char temp[MAX_STR_LENGTH]; + //create file name for gui purposes, and set up acquistion parameters + sprintf(temp, "%s/%s_fxxx_%d_%d.root", filePath,fileNamePerThread[ithread],fileIndex,ithread); + //file + myFile[ithread] = new TFile(temp,"RECREATE");/** later return error if it exists */ + cprintf(GREEN,"Writing_Thread %d: Created Compression File: %s\n",ithread, temp); + //tree + sprintf(temp, "%s_fxxx_%d_%d",fileNamePerThread[ithread],fileIndex,ithread); + myTree[ithread]=singlePhotonDetectorObject[ithread]->initEventTree(temp, &iframe); + //resets the pedestalSubtraction array and the commonModeSubtraction + singlePhotonDetectorObject[ithread]->newDataSet(); + if(myFile[ithread]==NULL){ + FILE_LOG(logERROR) << "File Null"; + return FAIL; + } + if(!myFile[ithread]->IsOpen()){ + FILE_LOG(logERROR) << "File Not Open"; + return FAIL; + } + return OK; +#endif + return FAIL; +} + + + +void* UDPStandardImplementation::startDataCallbackThread(void* this_pointer){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + ((UDPStandardImplementation*)this_pointer)->startDataCallback(); + return this_pointer; +} + + + +void* UDPStandardImplementation::startListeningThread(void* this_pointer){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + ((UDPStandardImplementation*)this_pointer)->startListening(); + return this_pointer; +} + + + +void* UDPStandardImplementation::startWritingThread(void* this_pointer){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + ((UDPStandardImplementation*)this_pointer)->startWriting(); + return this_pointer; +} + + + + +void UDPStandardImplementation::startDataCallback(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //set current thread value index + int ithread = currentThreadIndex; + struct timespec begin,end; + + // server address to bind + char hostName[100] = "tcp://*:";//"tcp://127.0.0.1:"; + int portno = DEFAULT_ZMQ_PORTNO + (detID*numberofListeningThreads+ithread); + sprintf(hostName,"%s%d",hostName,portno); + + //socket details + void *context = zmq_ctx_new(); + void *zmqsocket = zmq_socket(context, ZMQ_PUSH); // create a publisher + int val = -1; + zmq_setsockopt(zmqsocket, ZMQ_LINGER, &val,sizeof(val)); // wait for the unsent packets before closing socket + //val = 10; + //zmq_setsockopt(zmqsocket,ZMQ_SNDHWM,&val,sizeof(val)); //set SEND HIGH WATER MARK (8-9ms slower) + zmq_bind(zmqsocket,hostName); // bind + FILE_LOG(logINFO) << "Thread" << ithread << ": ZMQ Server at " << hostName; + + + int headersize=0; + switch(myDetectorType){ + case EIGER: + headersize = EIGER_DATA_PACKET_HEADER_SIZE; break; + default: + headersize = 0; break; + } + + //let calling function know thread started and obtained current (after sockets created) + if(!zmqThreadStarted) + zmqThreadStarted = true; + + /* outer loop - loops once for each acquisition */ + //infinite loop, exited only to change dynamic range, 10G parameters etc (then recreated again) + while(true){ + + int oneframesize = oneDataSize * packetsPerFrame; + char* buffer = new char[packetsPerFrame*oneDataSize](); + memset(buffer,0xFF,oneframesize); + int size = 0; + int offset = 0; + uint32_t currentfnum = 0; + uint64_t fnum = 0; + uint32_t pnum = 0; + uint32_t snum = 0; + uint64_t bid = 0; + bool randomSendNow = true; + bool newFrame = false; + + + + //header details + const char *type = "float64"; + const char *shape= "[1024, 512]"; + const char *jsonFmt ="{\"htype\":[\"chunk-1.0\"], \"type\":\"%s\", \"shape\":%s, \"acqIndex\":%d, \"fIndex\":%d, \"subfnum\":%d, \"fname\":\"%s\"}"; + char buf[1000]; + int acquisitionIndex = -1; + int frameIndex = -1; + int subframeIndex = -1; +#ifdef DEBUG + int oldpnum = -1; +#endif + int datapacketscaught = 0; + + /* inner loop - loop for each buffer */ + //until mask reset (dummy pcaket got by writer) + while((1 << ithread) & dataCallbackThreadsMask){ + + //let the writer thread continue, while we process carry over if any + sem_post(&writerGuiSemaphore[ithread]); + //wait for receiver to send more data + sem_wait(&dataCallbackWriterSemaphore[ithread]); + + //end if acquistion + if(guiNumPackets[ithread] == dummyPacketValue){ + + //sending previous half frames if any + if(!excludeMissingPackets && newFrame){ + //send header + //update frame details + frameIndex = fnum; + acquisitionIndex = fnum - startAcquisitionIndex; + if(dynamicRange == 32) subframeIndex = snum; + int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); + zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); + //send data + zmq_send(zmqsocket, buffer, oneframesize, 0); + newFrame = false; + } + + + + //send final header + //update frame details +#ifdef DEBUG + cout << "sending dummy" << endl; +#endif + frameIndex = -9; + acquisitionIndex = -9; + subframeIndex = -9; + int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); + zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); + //send final data + zmq_send (zmqsocket, "end", 3, 0); + + pthread_mutex_lock(&statusMutex); + dataCallbackThreadsMask^=(1<0) && (getFrameandPacketNumber(ithread, latestData[ithread]+offset, fnum, pnum,snum,bid)==FAIL)){ + offset+= onePacketSize; + } + //if(!ithread) cout<< ithread <<" fnum:"<< fnum<<" pnum:"<= size) + break; + + if(!frameToGuiFrequency) + currentfnum = fnum; + + + //last packet of same frame + if(fnum == currentfnum && pnum == (packetsPerFrame-1)){ +#ifdef DEBUG + oldpnum=0; +#endif + memcpy(buffer+(pnum*oneDataSize), latestData[ithread]+offset+headersize,oneDataSize); + offset+= onePacketSize; + //send header + //update frame details + frameIndex = fnum; + acquisitionIndex = fnum - startAcquisitionIndex; + if(dynamicRange == 32) subframeIndex = snum; + int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); + zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); + //send data + zmq_send(zmqsocket, buffer, oneframesize, 0); + newFrame = false; +#ifdef DEBUG + if(!ithread)cprintf(BLUE,"%d sent (last packet)\n",ithread); +#endif + currentfnum++; + //start clock after sending + if(!frameToGuiFrequency){ + randomSendNow = false; + clock_gettime(CLOCK_REALTIME, &begin); + } + memset(buffer,0xFF,oneframesize); + + } + //same frame (not last) or next frame + else { + //next frame +#ifdef DEBUG + int once = true; +#endif + while(fnum > currentfnum){ +#ifdef DEBUG + if(once){ + if((fnum-currentfnum-1)>1) cprintf(RED,"%d Complete sub image missing:%d (cfnum:%d nfnum:%d)\n", + ithread,fnum-currentfnum-1,currentfnum,fnum); + once = false; + } +#endif + //send header + //update frame details + frameIndex = fnum; + acquisitionIndex = fnum - startAcquisitionIndex; + if(dynamicRange == 32) subframeIndex = snum; + int len = sprintf(buf,jsonFmt,type,shape, acquisitionIndex, frameIndex, subframeIndex,completeFileName[ithread]); + zmq_send(zmqsocket, buf,len, ZMQ_SNDMORE); + //send data + zmq_send(zmqsocket, buffer, oneframesize, 0); + newFrame = false; +#ifdef DEBUG + cprintf(BLUE,"%d sent (last packet of previous frame)\n",ithread); +#endif + currentfnum++; + //start clock after sending + if(!frameToGuiFrequency){ + randomSendNow = false; + clock_gettime(CLOCK_REALTIME, &begin); + } + memset(buffer,0xFF,oneframesize); + } + + memcpy(buffer+(pnum*oneDataSize), latestData[ithread]+offset+headersize,oneDataSize); + offset+= onePacketSize; + newFrame = true; + } + + } + } + + + + }/*--end of loop for each buffer (inner loop)*/ + + //free resources + delete[] buffer; + + //end of acquisition, wait for next acquisition/change of parameters + sem_wait(&dataCallbackSemaphore[ithread]); + + + //check to exit thread (for change of parameters) - only EXIT possibility + if(killAllDataCallbackThreads){ + break;//pthread_exit(NULL); + } + + }/*--end of loop for each acquisition (outer loop) */ + + + //free resources + zmq_unbind(zmqsocket, hostName); /* will this be too soon and cut the sending*/ + zmq_close(zmqsocket); + zmq_ctx_destroy(context); + cprintf(MAGENTA,"DataCallback_Thread %d:Goodbye!\n",ithread); +} + + + + +void UDPStandardImplementation::startListening(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //set current thread value index + int ithread = currentThreadIndex; + //let calling function know thread started and obtained current + threadStarted = 1; + + + uint32_t rc = 0; //size of buffer received in bytes + //split frames for data compression + int carryonBufferSize = 0; //from previous buffer to keep frames together in a buffer + char* tempBuffer = 0; //temporary buffer to store split frames + + + /* outer loop - loops once for each acquisition */ + //infinite loop, exited only to change dynamic range, 10G parameters etc (then recreated again) + while(true){ + + //compression variables reset before acquisition + if(dataCompressionEnable){ + carryonBufferSize = 0; + if(tempBuffer){delete []tempBuffer;tempBuffer=0;} + tempBuffer = new char[onePacketSize * (packetsPerFrame - 1)](); //store maximum of 1 packets less in a frame + } + + /* inner loop - loop for each buffer */ + //until mask reset (udp sockets shut down by client) + while((1 << ithread) & listeningThreadsMask){ + + + //pop from fifo + fifoFree[ithread]->pop(buffer[ithread]); + + //udpsocket doesnt exist + if(activated && !udpSocket[ithread]){ + FILE_LOG(logERROR) << "Listening_Thread " << ithread << ": UDP Socket not created or shut down earlier"; + stopListening(ithread,0); + continue; + } + + if(!activated) //eiger not activated modules + rc = prepareAndListenBufferDeactivated(ithread); + else if(excludeMissingPackets) //eiger and jungfrau + rc = prepareAndListenBufferCompleteFrames(ithread); + else{ + rc = prepareAndListenBuffer(ithread, carryonBufferSize, tempBuffer); //others + carryonBufferSize = 0; + } + + //problem in receiving or end of acquisition + if (status == TRANSMITTING||(rc <= 0 && activated == 0)){ + stopListening(ithread,rc); + continue; + } + + if(dataCompressionEnable) + (*((uint32_t*)(buffer[ithread]))) = processListeningBuffer(ithread, carryonBufferSize, tempBuffer, rc); + + //push buffer to FIFO + while(!fifo[ithread]->push(buffer[ithread])); + + }/*--end of loop for each buffer (inner loop)*/ + + //end of acquisition, wait for next acquisition/change of parameters + sem_wait(&listenSemaphore[ithread]); + + //check to exit thread (for change of parameters) - only EXIT possibility + if(killAllListeningThreads){ + cprintf(BLUE,"Listening_Thread %d:Goodbye!\n",ithread); + //free resources at exit + if(tempBuffer) delete[] tempBuffer; + pthread_exit(NULL); + } + + }/*--end of loop for each acquisition (outer loop) */ +} + + + + + +int UDPStandardImplementation::prepareAndListenBuffer(int ithread, int cSize, char* temp){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + int receivedSize = 0; + + //carry over from previous buffer + if(cSize) + memcpy(buffer[ithread] + fifoBufferHeaderSize, temp, cSize); + + //listen to after the carry over buffer + if(status != TRANSMITTING) + receivedSize = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + fifoBufferHeaderSize + cSize, + (bufferSize * numberofJobsPerBuffer) - cSize); + + if(receivedSize > 0){ + //write packet count to buffer + *((uint32_t*)(buffer[ithread])) = (receivedSize/onePacketSize); + totalListeningPacketCount[ithread] += (receivedSize/onePacketSize); + + //start indices for each start of scan/acquisition + if(!measurementStarted[ithread]) //and rc>0 + startFrameIndices(ithread); + } +#ifdef DEBUG + cprintf(BLUE, "Listening_Thread %d : Received bytes: %d. Expected bytes: %d\n", ithread, receivedSize, bufferSize * numberofJobsPerBuffer-cSize); +#endif + return receivedSize; +} + + + + + + + +int UDPStandardImplementation::prepareAndListenBufferDeactivated(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //last + if(currentFrameNumber[ithread] == numberOfFrames) + return 0; + + //copy dummy packets + memset(buffer[ithread] + fifoBufferHeaderSize, 0xFF,bufferSize); + + //write fnum and number of packets + (*((uint64_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS))) = currentFrameNumber[ithread]+1; + (*((uint32_t*)(buffer[ithread]))) = packetsPerFrame; + + //start indices for each start of scan/acquisition (rc > 0) + if(!measurementStarted[ithread]) + startFrameIndices(ithread); + + return bufferSize; +} + + + + +int UDPStandardImplementation::prepareAndListenBufferCompleteFrames(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + int headerlength = 0; + uint32_t LASTPNUM = 0; + uint32_t FIRSTPNUM = 0; + int INCORDECR = 0; + switch(myDetectorType){ + case JUNGFRAU: + headerlength = JFRAU_HEADER_LENGTH; + FIRSTPNUM = packetsPerFrame-1; + LASTPNUM = 0; + INCORDECR = -1; + break; + case EIGER: + headerlength = EIGER_DATA_PACKET_HEADER_SIZE; + FIRSTPNUM = 0; + LASTPNUM = packetsPerFrame-1; + INCORDECR = 1; + break; + default:break; + } + + + int offset = fifoBufferHeaderSize; + uint32_t pnum = 0; + uint64_t fnum = 0; + uint64_t bnum = 0; + int rc = 0; + //from getframeandpacketnumber() + uint32_t pi = 0; + uint64_t fi = 0; + uint64_t bi = 0; + uint32_t si = 0; + + + //read first packet + pnum = FIRSTPNUM; //first packet number to validate + if(status != TRANSMITTING) rc = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + offset); + if(rc <= 0) return 0; + if(getFrameandPacketNumber(ithread,buffer[ithread] + offset,fi,pi,si,bi) == FAIL){ + pi = ALL_MASK_32; //got 0 from fpga + fi = ALL_MASK_32; + } + else + fnum = fi; //fnum of first packet + bnum = bi; //bnum of first packet + totalListeningPacketCount[ithread]++; +#ifdef VERBOSE + if(!ithread) cout << "1 pnum:" << pnum << endl; +#endif + //start indices for each start of scan/acquisition (rc > 0) + if(!measurementStarted[ithread]) + startFrameIndices(ithread); + + + while(true){ + + //------------------------------------------------------ correct packet -------------------------------------------------------- + if((myDetectorType == JUNGFRAU && pnum == pi) || //jungfrau only looks at pnum + (myDetectorType == EIGER && pnum == pi && fnum == fi)){ // eiger looks at pnum and fnum +#ifdef VERBOSE + if(!ithread) cout << "correct packet" << endl; +#endif + //copy only data + memcpy(buffer[ithread] + offset,buffer[ithread] + offset + headerlength, oneDataSize); + offset+=oneDataSize; + + //if complete frame + if(pnum == LASTPNUM) + break; + //else increment/decrement + pnum += INCORDECR; + + rc=0; //listen again + if(status != TRANSMITTING) + rc = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + offset); + if(rc <= 0){ //end: update ignored and return + if(myDetectorType == JUNGFRAU) + totalIgnoredPacketCount[ithread] += (packetsPerFrame - pnum); + else + totalIgnoredPacketCount[ithread] += (pnum + 1); + return 0; + } + totalListeningPacketCount[ithread]++; + if(getFrameandPacketNumber(ithread, buffer[ithread] + offset,fi,pi,si,bi) == FAIL){ + pi = ALL_MASK_32; //got 0 from fpga + fi = ALL_MASK_32; + totalIgnoredPacketCount[ithread] += (pnum + 1); + } + else if(myDetectorType == EIGER) + fnum = fi; //update currentfnum for eiger (next packets should have currentfnum value) +#ifdef VERBOSE + if(!ithread) cout << "next currentpnum :" << pnum << endl; +#endif + } + + //------------------------------------------------------ wrong packet -------------------------------------------------------- + else{ +#ifdef VERBOSE + if(!ithread) cprintf(RED,"wrong packet %d, expected packet %d fnum of last good one:%d\n", + pi,pnum,(*((uint32_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS)))); +#endif + if(myDetectorType == JUNGFRAU) + totalIgnoredPacketCount[ithread] += (packetsPerFrame - pnum -1); //extra 1 subtracted now to be added in the while loop anyway + else + totalIgnoredPacketCount[ithread] += pnum; //extra 1 subtracted now to be added in the while loop anyway + pnum = FIRSTPNUM; + offset = fifoBufferHeaderSize; + + //find the start of next image + while(pnum != pi){ + totalIgnoredPacketCount[ithread]++; + + rc=0; + if(status != TRANSMITTING) + rc = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + offset); + if(rc <= 0){ + if(myDetectorType == JUNGFRAU) + totalIgnoredPacketCount[ithread] += (packetsPerFrame - pnum); + else + totalIgnoredPacketCount[ithread] += (pnum + 1); + return 0; + } + totalListeningPacketCount[ithread]++; + if(getFrameandPacketNumber(ithread, buffer[ithread] + offset,fi,pi,si,bi) == FAIL){ + pi = ALL_MASK_32; //got 0 from fpga + fi = ALL_MASK_32; + } +#ifdef VERBOSE + if(!ithread) cout << "trying to find pnum:" << pnum << " got " << pi << endl; +#endif + } + if(fi!=ALL_MASK_32) + fnum = fi; //fnum of first packet + bnum = bi; //bnum of first packet + } + } + //------------------------------------------------------ got a complete frame -------------------------------------------------------- + + //write frame number + (*((uint64_t*)(buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS))) = fnum + startAcquisitionIndex; +#ifdef VERBOSE + if(!ithread) cout << "fnum:" << (*((uint64_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS))) << endl; +#endif + if(myDetectorType == JUNGFRAU) + (*((uint64_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS + FILE_HEADER_BUNCHID_OFFSET))) = bnum; + //write packet count to buffer + *((uint32_t*)(buffer[ithread])) = packetsPerFrame; + return bufferSize; +} + + + +void UDPStandardImplementation::startFrameIndices(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + + jfrau_packet_header_t* header=0; + switch(myDetectorType){ + case EIGER: + startFrameIndex = 1; //frame number always resets + break; + case JUNGFRAU: + header = (jfrau_packet_header_t*)(buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS); + startFrameIndex = (*( (uint32_t*) header->frameNumber))&frameIndexMask; + break; + default: + if(shortFrameEnable < 0){ + startFrameIndex = (((((uint32_t)(*((uint32_t*)(buffer[ithread] + fifoBufferHeaderSize))))+1) + & (frameIndexMask)) >> frameIndexOffset); + }else{ + startFrameIndex = ((((uint32_t)(*((uint32_t*)(buffer[ithread]+fifoBufferHeaderSize)))) + & (frameIndexMask)) >> frameIndexOffset); + } + break; + } + + //start of entire acquisition + if(!acqStarted){ + pthread_mutex_lock(&progressMutex); + startAcquisitionIndex = startFrameIndex; + acqStarted = true; + pthread_mutex_unlock(&progressMutex); + cprintf(BLUE,"Listening_Thread %d: startAcquisitionIndex:%lld\n",ithread,(long long int)startAcquisitionIndex); + } + + //set start of scan/real time measurement + cprintf(BLUE,"Listening_Thread %d: startFrameIndex: %lld\n", ithread,(long long int)startFrameIndex); + measurementStarted[ithread] = true; +} + + + + + + + +void UDPStandardImplementation::stopListening(int ithread, int numbytes){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + +#ifdef DEBUG4 + cprintf(BLUE,"Listening_Thread %d: Stop Listening\nStatus: %s numbytes:%d\n", ithread, runStatusType(status).c_str(),numbytes); +#endif + + //free empty buffer + if(numbytes <= 0){ + FILE_LOG(logINFO) << "Listening "<< ithread << ": End of Acquisition"; + while(!fifoFree[ithread]->push(buffer[ithread])); + } + + + //push last non empty buffer into fifo + else{ + if(excludeMissingPackets){ + (*((uint32_t*)(buffer[ithread]))) = numbytes/oneDataSize; + totalListeningPacketCount[ithread] += (numbytes/oneDataSize); + }else{ + (*((uint32_t*)(buffer[ithread]))) = numbytes/onePacketSize; + totalListeningPacketCount[ithread] += (numbytes/onePacketSize); + } +#ifdef DEBUG + cprintf(BLUE,"Listening_Thread %d: Last Buffer numBytes:%d\n",ithread, numbytes); + cprintf(BLUE,"Listening_Thread %d: Last Buffer packet count:%d\n",ithread,(*((uint32_t*)(buffer[ithread]))) ); +#endif + while(!fifo[ithread]->push(buffer[ithread])); + } + + //push dummy-end buffer into fifo for all writer threads + fifoFree[ithread]->pop(buffer[ithread]); + + //creating dummy-end buffer with pc=0xFFFF + (*((uint32_t*)(buffer[ithread]))) = dummyPacketValue; + while(!fifo[ithread]->push(buffer[ithread])); + + + //reset mask and exit loop + pthread_mutex_lock(&statusMutex); + listeningThreadsMask^=(1<> frameIndexOffset)); +#endif + cSize = onePacketSize; + --packetCount; + } + } +#ifdef DEBUG4 + cprintf(BLUE, "Listening_Thread %d: First Header:%d\n", (((((uint32_t)(*((uint32_t*)(buffer[ithread] + fifoBufferHeaderSize))))+1) + & (frameIndexMask)) >> frameIndexOffset)); +#endif + break; + + case MOENCH: + lastPacketOffset = (((packetCount - 1) * onePacketSize) + fifoBufferHeaderSize); +#ifdef DEBUG4 + cprintf(BLUE, "Listening_Thread %d: First Header:%d\t First Packet:%d\t Last Header:%d\t Last Packet:%d\tLast Packet Offset:%d\n", + (((((uint32_t)(*((uint32_t*)(buffer[ithread]+fifoBufferHeaderSize))))) & (frameIndexMask)) >> frameIndexOffset), + ((((uint32_t)(*((uint32_t*)(buffer[ithread]+fifoBufferHeaderSize))))) & (packetIndexMask)), + (((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastpacketoffset))))) & (frameIndexMask)) >> frameIndexOffset), + ((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastpacketoffset))))) & (packetIndexMask)), + lastPacketOffset); +#endif + //moench last packet value is 0, so find the last packet and store the others in a temp storage + if( ((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastPacketOffset))))) & (packetIndexMask))){ + lastFrameHeader = ((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastPacketOffset))))) + & (frameIndexMask)) >> frameIndexOffset; + cSize += onePacketSize; + lastPacketOffset -= onePacketSize; + --packetCount; + while (lastFrameHeader == (((((uint32_t)(*((uint32_t*)(buffer[ithread]+lastPacketOffset))))) & (frameIndexMask)) >> frameIndexOffset)){ + cSize += onePacketSize; + lastPacketOffset -= onePacketSize; + --packetCount; + } + memcpy(temp, buffer[ithread]+(lastPacketOffset+onePacketSize), cSize); +#ifdef DEBUG4 + cprintf(BLUE, "Listening_Thread %d: temp Header:%d\t temp Packet:%d\n", + (((((uint32_t)(*((uint32_t*)(temp)))))& (frameIndexMask)) >> frameIndexOffset), + ((((uint32_t)(*((uint32_t*)(temp))))) & (packetIndexMask))); +#endif + } + break; + + default: + cprintf(RED,"Listening_Thread %d: Error: This detector %s is not implemented in the receiver\n", + ithread, getDetectorType(myDetectorType).c_str()); + break; + } + +#ifdef DEBUG4 + cprintf(BLUE,"Listening_Thread %d: PacketCount:%d CarryonBufferSize:%d\n",ithread, packetCount, cSize); +#endif + + return packetCount; +} + + + + + + +void UDPStandardImplementation::startWriting(){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + int ithread = currentThreadIndex; //set current thread value index + threadStarted = 1; //let calling function know thread started and obtained current + + char* wbuf = NULL; //buffer popped from FIFO + sfilefd[ithread] = 0; //file pointer + uint64_t nf = 0; //for compression, number of frames + + + /* outer loop - loops once for each acquisition */ + //infinite loop, exited only to change dynamic range, 10G parameters etc (then recreated again) + while(true){ + + //--reset parameters before acquisition (depending on compression) + nf = 0; //compression has only one listening thread (anything not eiger) + + + /* inner loop - loop for each buffer */ + //until mask unset (udp sockets shut down by client) + while((1 << ithread) & writerThreadsMask){ + + //pop + if(!dataCompressionEnable) + fifo[ithread]->pop(wbuf); + else + fifo[0]->pop(wbuf); + uint32_t numPackets = (uint32_t)(*((uint32_t*)wbuf)); + +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread %d: Number of Packets: %d for FIFO %d\n", ithread, numPackets, dataCompressionEnable?0:ithread); +#endif + + + //end of acquisition + if(numPackets == dummyPacketValue){ +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread %d: Dummy frame popped out of FIFO %d",ithread, dataCompressionEnable?0:ithread); +#endif + stopWriting(ithread,wbuf); + continue; + } + + //jungfrau and eiger + if(excludeMissingPackets) + handleCompleteFramesOnly(ithread, wbuf); + //normal + else if(!dataCompressionEnable) + handleWithoutDataCompression(ithread, wbuf, numPackets); + + //compression + else{ +#if defined(MYROOT1) && defined(ALLFILE_DEBUG) + if(npackets > 0) + writeFileWithoutCompression(wbuf, numPackets); +#endif + handleDataCompression(ithread,wbuf,nf); + } + }/*--end of loop for each buffer (inner loop)*/ + + waitWritingBufferForNextAcquisition(ithread); + + }/*--end of loop for each acquisition (outer loop) */ +} + + + + + + + + +void UDPStandardImplementation::waitWritingBufferForNextAcquisition(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //in case they are not closed already + closeFile(ithread); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread %d: Done with acquisition. Waiting for 1st sem to create new file/change of parameters\n", ithread); +#endif + //end of acquisition, wait for file create/change of parameters + sem_wait(&writerSemaphore[ithread]); + //check to exit thread (for change of parameters) - only EXIT possibility + if(killAllWritingThreads){ + cprintf(GREEN,"Writing_Thread %d:Goodbye!\n",ithread); + pthread_exit(NULL); + } +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread %d: Got 1st post. Creating File\n", ithread); +#endif + + + //pop fifo so that its empty + char* temp; + while(!fifo[ithread]->isEmpty()){ + cprintf(RED,"%d:fifo emptied\n", ithread); + fifo[ithread]->pop(temp); + fifoFree[ithread]->push(temp); + } + + //create file + if((1<push(wbuffer)); + + if(dataStreamEnable){ + sem_wait(&writerGuiSemaphore[ithread]); //ensure previous frame was processed + guiNumPackets[ithread] = dummyPacketValue; + sem_post(&dataCallbackWriterSemaphore[ithread]); //let it know its got data + } + + + //all threads need to close file, reset mask and exit loop + if(fileWriteEnable && (cbAction > DO_NOTHING)){ + if(fileFormatType == BINARY && myDetectorType == EIGER){ + updateFileHeader(ithread); + fseek(sfilefd[ithread],0,0); + fwrite((void*)fileHeader[ithread], 1, FILE_HEADER_SIZE, sfilefd[ithread]); + } + } + + //Print packet loss + //if(totalWritingPacketCountFromLastCheck[ithread]){ +#ifdef VERBOSE + if(fileFormatType == BINARY){ + if(numberofWriterThreads>1){ + printf("Thread:%d" + "\tLost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + ithread, + ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) + ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) + :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), + (long long int)totalWritingPacketCountFromLastCheck[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousCheck[ithread] + ); + }else{ + printf("Lost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) + ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) + :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), + (long long int)totalWritingPacketCountFromLastCheck[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousCheck[ithread] + ); + } + + if(numberofWriterThreads>1){ + cprintf(BLUE,"File:%s" + "\nThread:%d" + "\tLost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + completeFileName[ithread],ithread, + ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) + ?(long long int)((numberOfFrames-(frameNumberInPreviousFile[ithread]+1))*packetsPerFrame - totalPacketsInFile[ithread]) + :(long long int)((frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread])*packetsPerFrame - totalPacketsInFile[ithread]), + (long long int)totalPacketsInFile[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousFile[ithread] + ); + }else{ + cprintf(BLUE,"File:%s" + "\nLost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + completeFileName[ithread], + ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) + ?(long long int)(numberOfFrames-(frameNumberInPreviousFile[ithread]+1)) + :(long long int)(frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread]), + (long long int)totalPacketsInFile[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousFile[ithread] + ); + } + } +#endif + //} + + closeFile(ithread); + pthread_mutex_lock(&statusMutex); + writerThreadsMask^=(1<push(wbuffer)); + + return; + } + + + //callback to write data + if (cbAction < DO_EVERYTHING) + rawDataReadyCallBack((int)tempframenumber, wbuffer + fifoBufferHeaderSize, npackets * onePacketSize, + sfilefd[ithread], latestData[ithread],pRawDataReady);//know which thread from sfilefd + + + //write to file if enabled and update write parameters + if(npackets > 0) + writeFileWithoutCompression(ithread, wbuffer, npackets); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: Writing done\nGoing to copy frame\n"); +#endif + + + //copy frame for gui + //if(npackets >= (packetsPerFrame/numberofListeningThreads)) + if(dataStreamEnable && npackets > 0) + copyFrameToGui(ithread, wbuffer,npackets); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: Copied frame\n"); +#endif + + + //free fifo addresses + int listenfifoThread = ithread; + if(dataCompressionEnable) + listenfifoThread = 0; + while(!fifoFree[listenfifoThread]->push(wbuffer)); +#ifdef EVERYFIFODEBUG + if(fifoFree[listenfifoThread]->getSemValue()<100) + cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",listenfifoThread,fifoFree[listenfifoThread]->getSemValue(),(void*)(wbuffer)); +#endif +#ifdef DEBUG5 + cprintf(GREEN,"Writing_Thread %d: Freed buffer, pushed into fifofree %p for listener %d \n",listenfifoThread, (void*)(wbuffer), listenfifoThread); +#endif + +} + + + + +void UDPStandardImplementation::handleCompleteFramesOnly(int ithread, char* wbuffer){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //get current frame number + uint64_t tempframenumber; + tempframenumber = (*((uint64_t*)(wbuffer+HEADER_SIZE_NUM_TOT_PACKETS))); + tempframenumber -= startFrameIndex; + + + if (cbAction < DO_EVERYTHING) + rawDataReadyCallBack((int)tempframenumber, wbuffer + HEADER_SIZE_NUM_TOT_PACKETS, bufferSize + FILE_FRAME_HEADER_LENGTH, + sfilefd[ithread], latestData[ithread],pRawDataReady); + + + //write to file if enabled and update write parameters + if((fileWriteEnable) && (sfilefd[ithread] +#ifdef HDF5C + ||hdf5_fileId[ithread])){ +#else + )){ +#endif + + if(fileFormatType == BINARY){ + if(tempframenumber && (tempframenumber%maxFramesPerFile) == 0) + createNewFile(ithread); + fwrite(wbuffer + HEADER_SIZE_NUM_TOT_PACKETS, 1, (bufferSize + FILE_FRAME_HEADER_LENGTH), sfilefd[ithread]); + } + + + +#ifdef HDF5C + else if (fileFormatType == HDF5){ + pthread_mutex_lock(&writeMutex); + + /* if(tempframenumber && (tempframenumber%MAX_IMAGES_IN_DATASET) == 0){ + try{ + Exception::dontPrint(); //to handle errors + if(hdf5_datasetId[ithread]) {delete hdf5_datasetId[ithread]; hdf5_datasetId[ithread] = 0;} + char dsetname[100]; + sprintf(dsetname, "/entry/data/data_%012lld", (long long int)currentFrameNumber[ithread]+1); + //create new dataspace if fewer than max images/dataset + int numimagesindataset = (((numberOfFrames-tempframenumber) < MAX_IMAGES_IN_DATASET)? (numberOfFrames-tempframenumber):MAX_IMAGES_IN_DATASET); + if(numimagesindataset MAX_CHUNKED_IMAGES){ + DSetCreatPropList plist; + hsize_t chunk_dims[3] ={MAX_CHUNKED_IMAGES, NY, NX}; + if(dynamicRange == 4) + chunk_dims[2] = NX/2; + plist.setChunk(3, chunk_dims); + + hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( + dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread],plist)); + } + else + hdf5_datasetId[ithread] = new DataSet (hdf5_fileId[ithread]->createDataSet( + dsetname, hdf5_datatype, *hdf5_dataspaceId[ithread])); + + //link + char linkPath[1000]=""; + sprintf(linkPath,"/entry/data/%s",dsetname); + hdf5_fileId[ithread]->link(H5G_LINK_HARD,dsetname,linkPath); + } + catch(Exception error){ + cprintf(RED,"Error in closing HDF5 dataset to create a new one in thread %d\n",ithread); + error.printError(); + } + } +*/ + struct timespec begin,end; + if(!ithread && !tempframenumber) + clock_gettime(CLOCK_REALTIME, &begin); + + //wite to file + hsize_t count[3] = {1, NY,NX}; + hsize_t start[3] = {tempframenumber%MAX_IMAGES_IN_DATASET, 0 , 0}; + hsize_t dims2[2]={NY,NX}; + if(dynamicRange == 4){ + dims2[1] = NX/2; + count[1] = NX/2; + } + + try{ + Exception::dontPrint(); //to handle errors + hdf5_dataspaceId[ithread]->selectHyperslab( H5S_SELECT_SET, count, start); + DataSpace memspace(2,dims2); + hdf5_datasetId[ithread]->write(wbuffer + fifoBufferHeaderSize, hdf5_datatype, memspace, *hdf5_dataspaceId[ithread]); + memspace.close(); + } + catch(Exception error){ + cprintf(RED,"Error in writing to file in thread %d\n",ithread); + error.printError(); + } + + if(!ithread && !tempframenumber){ + clock_gettime(CLOCK_REALTIME, &end); + cprintf(RED,"%d Writing packets Elapsed time:%f seconds\n",ithread,( end.tv_sec - begin.tv_sec ) + ( end.tv_nsec - begin.tv_nsec ) / 1000000000.0); + } + + pthread_mutex_unlock(&writeMutex); + } +#endif + + } + + + //progress + if(tempframenumber && (tempframenumber%(maxFramesPerFile/progressFrequency)) == 0){ + if(numberofWriterThreads>1){ + printf("Thread:%d" + "\tLost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + ithread, + ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) + ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) + :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), + (long long int)totalWritingPacketCountFromLastCheck[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousCheck[ithread] + ); + }else{ + printf("Lost:%lld" + "\t\tPackets:%lld" + "\tFrame#:%lld" + "\tPFrame#:%lld\n", + ((frameNumberInPreviousCheck[ithread]+1+(maxFramesPerFile/progressFrequency))>numberOfFrames) + ?(long long int)((numberOfFrames-(frameNumberInPreviousCheck[ithread]+1))*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]) + :(long long int)((frameNumberInPreviousCheck[ithread]+(maxFramesPerFile/progressFrequency) - frameNumberInPreviousCheck[ithread])*packetsPerFrame - totalWritingPacketCountFromLastCheck[ithread]), + (long long int)totalWritingPacketCountFromLastCheck[ithread], + (long long int)currentFrameNumber[ithread], + (long long int)frameNumberInPreviousCheck[ithread] + ); + } + //reset counters for each new file + frameNumberInPreviousCheck[ithread] = currentFrameNumber[ithread]; + totalWritingPacketCountFromLastCheck[ithread] = 0; + } + + totalWritingPacketCountFromLastCheck[ithread]+= packetsPerFrame; + totalPacketsInFile[ithread] += packetsPerFrame; + totalWritingPacketCount[ithread] += packetsPerFrame; + lastFrameNumberInFile[ithread] = tempframenumber; + currentFrameNumber[ithread] = tempframenumber; + //cout<<"curentframenumber:"< 1) + pthread_mutex_lock(&writeMutex); + + packetsCaught += packetsPerFrame; + totalPacketsCaught += packetsPerFrame; + if((currentFrameNumber[ithread] - startAcquisitionIndex) > acquisitionIndex) + acquisitionIndex = currentFrameNumber[ithread] - startAcquisitionIndex; + if((currentFrameNumber[ithread] - startFrameIndex) > frameIndex[ithread]) + frameIndex[ithread] = currentFrameNumber[ithread] - startFrameIndex; + + if(numberofWriterThreads > 1) + pthread_mutex_unlock(&writeMutex); + + if(!activated) + currentFrameNumber[ithread]++; + +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: Writing done\nGoing to copy frame\n"); +#endif + + + //copy frame for gui + if(dataStreamEnable) + copyFrameToGui(ithread, wbuffer, packetsPerFrame); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: Copied frame\n"); +#endif + + + //free fifo addresses + while(!fifoFree[ithread]->push(wbuffer)); +#ifdef DEBUG5 + cprintf(GREEN,"Writing_Thread %d: Freed buffer, pushed into fifofree %p for listener %d \n",ithread, (void*)(wbuffer), ithread); +#endif + +} + + + +void UDPStandardImplementation::writeFileWithoutCompression(int ithread, char* wbuffer,uint32_t numpackets){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //if write enabled + if((fileWriteEnable) && (sfilefd[ithread])){ + if(numpackets){ + int offset = fifoBufferHeaderSize; + uint64_t nextFileFrameNumber; + int packetsWritten = 0; + //if(ithread) cout<<"numpackets:"<=0)){ + //get start frame (required to create new file at the right juncture) + uint64_t startframe = 0; + uint32_t pnum = 0; + uint32_t snum = 0; + uint64_t bunchid = 0; + //if(ithread) cout<<"getting start frame number"<push(wbuffer)); + return; + } + //if(ithread) cout<<"done getting start frame number"<=0) &&(!((lastFrameNumberInFile[ithread]+1) % maxFramesPerFile))) + createNewFile(ithread); + + + //frames to save in one file + nextFileFrameNumber = (lastFrameNumberInFile[ithread]+1) + + (maxFramesPerFile - ((lastFrameNumberInFile[ithread]+1)%maxFramesPerFile)); + + if(writeUptoFrameNumber(ithread, wbuffer, offset, nextFileFrameNumber, numpackets, packetsWritten) == FAIL) + //weird frame number of zero from fpga + return; + + //update stats + numpackets -= packetsWritten; + totalPacketsInFile[ithread] += packetsWritten; + totalWritingPacketCount[ithread] += packetsWritten; + pthread_mutex_lock(&writeMutex); + packetsCaught += packetsWritten; + totalPacketsCaught += packetsWritten; + pthread_mutex_unlock(&writeMutex); + currentFrameNumber[ithread] = lastFrameNumberInFile[ithread]; + } + } + } + + //only update parameters + else{ + + if(numpackets){ + //get last frame number + uint64_t finalLastFrameNumberToSave = 0; + uint32_t pnum; + uint32_t snum; + uint64_t bunchid = 0; + if(getFrameandPacketNumber(ithread, wbuffer + fifoBufferHeaderSize + ((numpackets - 1) * onePacketSize), finalLastFrameNumberToSave,pnum,snum,bunchid) == FAIL){ + //error in frame number sent by fpga + while(!fifoFree[ithread]->push(wbuffer)); + return; + } + totalPacketsInFile[ithread] += numpackets; + totalWritingPacketCount[ithread] += numpackets; + lastFrameNumberInFile[ithread] = finalLastFrameNumberToSave; + currentFrameNumber[ithread] = finalLastFrameNumberToSave; + + } + + if(numberofWriterThreads > 1) pthread_mutex_lock(&writeMutex); + packetsCaught += numpackets; + totalPacketsCaught += numpackets; + if(numberofWriterThreads > 1) pthread_mutex_unlock(&writeMutex); + } + + //set indices + pthread_mutex_lock(&progressMutex); + if((currentFrameNumber[ithread] - startAcquisitionIndex) > acquisitionIndex) + acquisitionIndex = currentFrameNumber[ithread] - startAcquisitionIndex; + if((currentFrameNumber[ithread] - startFrameIndex) > frameIndex[ithread]) + frameIndex[ithread] = currentFrameNumber[ithread] - startFrameIndex; + pthread_mutex_unlock(&progressMutex); +} + + + + + + +void UDPStandardImplementation::updateFileHeader(int ithread){ + //update file header + time_t t = time(0); + sprintf(fileHeader[ithread], + "\nHeader\t\t: %d bytes\n" + "Top\t\t: %d\n" + "Left\t\t: %d\n" + "Active\t\t: %d\n" + "Frames Caught\t: %lld\n" + "Frames Lost\t: %lld\n" + "Dynamic Range\t: %d\n" + "Ten Giga\t: %d\n" + "Image Size\t: %d bytes\n" + "x\t\t: %d pixels\n" + "y\t\t: %d pixels\n" + "Total Frames\t: %lld\n" + "Exptime (ns)\t: %lld\n" + "Period (ns)\t: %lld\n" + "Timestamp\t: %s\n\n" + + "#Frame Header\n" + "Frame Number\t: 8 bytes\n" + "Bunch ID\t: 8 bytes\n", + FILE_HEADER_SIZE, + (flippedData[0]?0:1), + (ithread?0:1), + activated, + (long long int)(totalPacketsInFile[ithread]/packetsPerFrame), + ((frameNumberInPreviousFile[ithread]+1+maxFramesPerFile)>numberOfFrames) + ?(long long int)((numberOfFrames-(frameNumberInPreviousFile[ithread]+1)) - (totalPacketsInFile[ithread]/packetsPerFrame)) + :(long long int)((frameNumberInPreviousFile[ithread]+maxFramesPerFile - frameNumberInPreviousFile[ithread]) - (totalPacketsInFile[ithread]/packetsPerFrame)), + dynamicRange,tengigaEnable, + bufferSize, + //only for eiger right now + EIGER_PIXELS_IN_ONE_ROW,EIGER_PIXELS_IN_ONE_COL, + (long long int)numberOfFrames, + (long long int)acquisitionTime, + (long long int)acquisitionPeriod, + ctime(&t)); + if(strlen(fileHeader[ithread]) > FILE_HEADER_SIZE) + cprintf(BG_RED,"File Header Size %d is too small for fixed file header size %d\n",(int)strlen(fileHeader[ithread]),(int)FILE_HEADER_SIZE); + + +} + +//called only if datacallback enabled +void UDPStandardImplementation::copyFrameToGui(int ithread, char* buffer, uint32_t numpackets){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //if nthe frame, wait for your turn (1st frame always shown as its zero) + if(frameToGuiFrequency && ((frametoGuiCounter[ithread])%frameToGuiFrequency)); + + //random read (gui ready) or nth frame read: gui needs data now or it is the first frame + else{ + +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: CopyingFrame: Going to copy data\n"); +#endif + //ensure previous frame was processed + sem_wait(&writerGuiSemaphore[ithread]); + + //copy date + guiNumPackets[ithread] = numpackets; + strcpy(guiFileName[ithread],completeFileName[ithread]); + + if(excludeMissingPackets) //copy also the header + memcpy(latestData[ithread],buffer+HEADER_SIZE_NUM_TOT_PACKETS, bufferSize + FILE_FRAME_HEADER_LENGTH); + else //copy only the data + memcpy(latestData[ithread],buffer+ fifoBufferHeaderSize , numpackets*onePacketSize); + //let it know its got data + sem_post(&dataCallbackWriterSemaphore[ithread]); + +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: CopyingFrame: Copied Data\n"); +#endif + + } + + //update the counter for nth frame + if(frameToGuiFrequency) + frametoGuiCounter[ithread]++; + + +} + + + + + +void UDPStandardImplementation::handleDataCompression(int ithread, char* wbuffer, uint64_t &nf){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //get frame number + uint64_t tempframenumber=-1; + uint32_t pnum; + uint32_t snum; + uint64_t bunchid=-1; + if(getFrameandPacketNumber(ithread, wbuffer + fifoBufferHeaderSize, tempframenumber,pnum,snum,bunchid) == FAIL){ + //error in frame number sent by fpga + while(!fifoFree[ithread]->push(wbuffer)); + return; + } + currentFrameNumber[ithread] = tempframenumber; + + + //set indices + pthread_mutex_lock(&progressMutex); + if((currentFrameNumber[ithread] - startAcquisitionIndex) > acquisitionIndex) + acquisitionIndex = currentFrameNumber[ithread] - startAcquisitionIndex; + if((currentFrameNumber[ithread] - startFrameIndex) > frameIndex[ithread]) + frameIndex[ithread] = currentFrameNumber[ithread] - startFrameIndex; + pthread_mutex_unlock(&progressMutex); + + //variable definitions + char* buff[2]={0,0}; //an array just to be compatible with copyframetogui + char* data = wbuffer+ fifoBufferHeaderSize; //data pointer to the next memory to be analysed + int ndata; //size of data returned + uint32_t np; //remaining number of packets returned + uint32_t npackets = (uint32_t)(*((uint32_t*)wbuffer)); //number of total packets + int remainingsize = npackets * onePacketSize; //size of the memory slot to be analyzed + + eventType thisEvent = PEDESTAL; + int once = 0; + int xmax = 0, ymax = 0; //max pixels in x and y direction + int xmin = 1, ymin = 1; //min pixels in x and y direction + double tot, tl, tr, bl, br; + + //determining xmax and ymax + switch(myDetectorType){ + case MOENCH: + xmax = MOENCH_PIXELS_IN_ONE_ROW-1; + ymax = MOENCH_PIXELS_IN_ONE_ROW-1; + break; + case GOTTHARD: + if(shortFrameEnable == -1){ + xmax = GOTTHARD_PIXELS_IN_ROW-1; + ymax = GOTTHARD_PIXELS_IN_COL-1; + }else{ + xmax = GOTTHARD_SHORT_PIXELS_IN_ROW-1; + ymax = GOTTHARD_SHORT_PIXELS_IN_COL-1; + } + break; + default: + break; + } + + while(buff[0] = receiverData[ithread]->findNextFrame(data,ndata,remainingsize)){ + + //remaining number of packets + np = ndata/onePacketSize; + + if ((np == packetsPerFrame) && (buff[0]!=NULL)){ + if(nf == 1000) + cprintf(GREEN, "Writing_Thread %d: pedestal done\n", ithread); + + singlePhotonDetectorObject[ithread]->newFrame(); + + //only for moench + if(commonModeSubtractionEnable){ + for(int ix = xmin - 1; ix < xmax+1; ix++){ + for(int iy = ymin - 1; iy < ymax+1; iy++){ + thisEvent = singlePhotonDetectorObject[ithread]->getEventType(buff[0], ix, iy, 0); + } + } + } + + + for(int ix = xmin - 1; ix < xmax+1; ix++) + for(int iy = ymin - 1; iy < ymax+1; iy++){ + thisEvent=singlePhotonDetectorObject[ithread]->getEventType(buff[0], ix, iy, commonModeSubtractionEnable); + if (nf>1000) { + tot=0; + tl=0; + tr=0; + bl=0; + br=0; + if (thisEvent==PHOTON_MAX) { + receiverData[ithread]->getFrameNumber(buff[0]); + //iFrame=receiverData[ithread]->getFrameNumber(buff); +#ifdef MYROOT1 + myTree[ithread]->Fill(); + //cout << "Fill in event: frmNr: " << iFrame << " ix " << ix << " iy " << iy << " type " << thisEvent << endl; +#else + pthread_mutex_lock(&writeMutex); + if((fileWriteEnable) && (sfilefd[0])) + singlePhotonDetectorObject[ithread]->writeCluster(sfilefd[0]); + pthread_mutex_unlock(&writeMutex); +#endif + } + } + } + + nf++; + + +#ifndef ALLFILE + totalPacketsInFile[ithread] += (bufferSize/packetsPerFrame); + totalWritingPacketCount[ithread] += (bufferSize/packetsPerFrame); + pthread_mutex_lock(&writeMutex); + if((packetsCaught%packetsPerFrame) >= (uint32_t)maxFramesPerFile) + createNewFile(ithread); + packetsCaught += (bufferSize/packetsPerFrame); + totalPacketsCaught += (bufferSize/packetsPerFrame); + pthread_mutex_unlock(&writeMutex); + + +#endif + if(!once){ + if(dataStreamEnable) + copyFrameToGui(ithread, buff[0],(uint32_t)packetsPerFrame); + once = 1; + } + } + + remainingsize -= ((buff[0] + ndata) - data); + data = buff[0] + ndata; + if(data > (wbuffer + fifoBufferHeaderSize + npackets * onePacketSize) ) + cprintf(BG_RED,"Writing_Thread %d: Error: Compression data goes out of bounds!\n", ithread); + } + + + while(!fifoFree[0]->push(wbuffer)); +#ifdef EVERYFIFODEBUG + if(fifoFree[0]->getSemValue()<100) + cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",0,fifoFree[0]->getSemValue(),(void*)(wbuffer)); +#endif +#ifdef DEBUG5 + cprintf(GREEN,"Writing_Thread %d: Compression free pushed into fifofree %p for listerner 0\n", ithread, (void*)(wbuffer)); +#endif +} + + + +int UDPStandardImplementation::getFrameandPacketNumber(int ithread, char* wbuffer, uint64_t &framenumber, uint32_t &packetnumber,uint32_t &subframenumber, uint64_t &bunchid){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + eiger_packet_footer_t* footer=0; + eiger_packet_header_t* e_header=0; + jfrau_packet_header_t* header=0; + framenumber = 0; + packetnumber = 0; + subframenumber = 0; + bunchid = 0; + + switch(myDetectorType){ + + case EIGER: + footer = (eiger_packet_footer_t*)(wbuffer + footerOffset); + framenumber = (uint32_t)(*( (uint64_t*) footer)); + //error in frame number sent by fpga + if(((uint32_t)(*( (uint64_t*) footer)))==0){ + framenumber = 0; + FILE_LOG(logERROR) << "Fifo "<< ithread << ": Frame Number is zero from firmware."; + return FAIL; + } + packetnumber = (*( (uint16_t*) footer->packetNumber))-1; + e_header = (eiger_packet_header_t*) (wbuffer); + subframenumber = *( (uint32_t*) e_header->subFrameNumber); +#ifdef DEBUG4 + if(!ithread) cprintf(GREEN,"Writing_Thread %d: fnum:%lld pnum:%d FPGA_fnum:%d subfnum:%d footeroffset:%d\n", + ithread, + (long long int)framenumber, + packetnumber, + framenumber, + subframenumber, + footerOffset); +#endif + framenumber -= startFrameIndex; + break; + + case JUNGFRAU: + header = (jfrau_packet_header_t*)(wbuffer); + framenumber = (*( (uint32_t*) header->frameNumber))&frameIndexMask; + packetnumber = (uint32_t)(*( (uint8_t*) header->packetNumber)); + bunchid = (*((uint64_t*) header->bunchid)); +#ifdef DEBUG4 + cprintf(GREEN, "Writing_Thread %d: fnum:%lld\t pnum:%d bunchid:%lld\n", + (long long int)framenumber, + packetnumber, + (long long int)bunchid); +#endif + framenumber -= startFrameIndex; + break; + + default: + framenumber = ((uint32_t)(*((uint32_t*)(wbuffer)))); + //for gotthard and normal frame, increment frame number to separate fnum and pnum + if (myDetectorType == PROPIX ||(myDetectorType == GOTTHARD && shortFrameEnable == -1)) + framenumber++; + packetnumber = framenumber&packetIndexMask; + framenumber = (framenumber & frameIndexMask) >> frameIndexOffset; +#ifdef DEBUG4 + cprintf(GREEN, "Writing_Thread %d: fnum:%lld\t pnum:%d\n", + (long long int)framenumber, + packetnumber); +#endif + framenumber -= startFrameIndex; + break; + } + return OK; +} + + + + + +int UDPStandardImplementation::writeUptoFrameNumber(int ithread, char* wbuffer, int &offset, uint64_t nextFrameNumber, uint32_t numpackets, int &numPacketsWritten){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + //if(ithread) cout<<"at writeUptoFrameNumber " << nextFrameNumber<< endl; + + + int startoffset = offset; + int endoffset = startoffset + numpackets * onePacketSize; + uint64_t tempframenumber=-1; + offset = endoffset; + uint32_t pnum; + uint32_t snum; + uint64_t bunchid=-1; + //get last frame number + if(getFrameandPacketNumber(ithread, wbuffer + (endoffset-onePacketSize), tempframenumber,pnum,snum,bunchid) == FAIL){ + //error in frame number sent by fpga + while(!fifoFree[ithread]->push(wbuffer)); + return FAIL; + } + //last packet's frame number < nextframenumber + if(tempframenumber=nextFrameNumber){ + offset -= bigIncrements; + if(offsetpush(wbuffer)); + return FAIL; + } + } + if(offsetpush(wbuffer)); + return FAIL; + } + } + while(tempframenumberpush(wbuffer)); + return FAIL; + } + } + + + fwrite(wbuffer + startoffset, 1, offset-startoffset, sfilefd[ithread]); + numPacketsWritten += ((offset-startoffset)/onePacketSize); + lastFrameNumberInFile[ithread] = (nextFrameNumber-1); + //if(ithread) cout<<"done with writeUptoFrameNumber" << endl; + return OK; +} + + + + +/** function that returns the name variable from the receiver complete file name prefix + \param fname complete file name prefix + \returns file name +*/ +string UDPStandardImplementation::getNameFromReceiverFilePrefix(string fname) { + int i; + string s=fname; + size_t uscore=s.rfind("_"); + if (sscanf( s.substr(uscore+1,s.size()-uscore-1).c_str(),"d%d",&i)) + s=fname.substr(0,uscore); + return s; +}; + + + + + diff --git a/slsReceiverSoftware/src/main.cpp b/slsReceiverSoftware/src/main.cpp index b4e5ef142..baab52674 100644 --- a/slsReceiverSoftware/src/main.cpp +++ b/slsReceiverSoftware/src/main.cpp @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) { //receiver->registerCallBackRawDataReady(rawDataReadyCallBack,NULL); - +/* //start tcp server thread if(receiver->start() == slsReceiverDefs::OK){ FILE_LOG(logDEBUG1) << "DONE!" << endl; @@ -113,7 +113,7 @@ int main(int argc, char *argv[]) { //stop tcp server thread, stop udp socket receiver->stop(); } - +*/ deleteReceiver(receiver); cout << "Goodbye!" << endl; return 0; diff --git a/slsReceiverSoftware/src/slsReceiver.cpp b/slsReceiverSoftware/src/slsReceiver.cpp index 04bc29563..c9fb94e4b 100644 --- a/slsReceiverSoftware/src/slsReceiver.cpp +++ b/slsReceiverSoftware/src/slsReceiver.cpp @@ -127,6 +127,7 @@ slsReceiver::slsReceiver(int argc, char *argv[], int &success){ udp_interface = UDPInterface::create(udp_interface_type); udp_interface->configure(configuration_map); #endif + udp_interface = UDPInterface::create("standard"); tcpipInterface = new slsReceiverTCPIPInterface(success, udp_interface, tcpip_port_no); } } diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 609cfcca9..eef507e93 100644 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -23,8 +23,8 @@ using namespace std; slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { - stop(); - if(mySock) {delete mySock; mySock=NULL;} + /*stop(); + if(mySock) {delete mySock; mySock=NULL;}*/ } slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int &success, UDPInterface* rbase, int pn): @@ -58,7 +58,7 @@ slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int &success, UDPInterface* success=OK; - //create socket + /*//create socket if(success == OK){ mySock = new MySocketTCP(port_no); if (mySock->getErrorStatus()) { @@ -76,7 +76,7 @@ slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int &success, UDPInterface* cout << "Function table assigned." << endl; #endif } - } + }*/ } @@ -2927,8 +2927,8 @@ int slsReceiverTCPIPInterface::set_fifo_depth() { ret=FAIL; }else{ retval = receiverBase->getFifoDepth(); - if(value >= 0 && retval != value) - ret = FAIL; + /*if(value >= 0 && retval != value) + ret = FAIL;*/ } }