diff --git a/slsReceiverSoftware/.gitignore b/slsReceiverSoftware/.gitignore new file mode 100644 index 0000000000..31dd1b8d22 --- /dev/null +++ b/slsReceiverSoftware/.gitignore @@ -0,0 +1,7 @@ +*~ +*.o +build/* +GPATH +GRTAGS +GSYMS +GTAGS diff --git a/slsReceiverSoftware/Makefile b/slsReceiverSoftware/Makefile new file mode 100644 index 0000000000..b7d1c10a95 --- /dev/null +++ b/slsReceiverSoftware/Makefile @@ -0,0 +1,115 @@ +include ../Makefile.include + +DESTDIR ?= ../bin +LIBDIR ?= $(DESTDIR) +DOCDIR ?= docs +SRCDIR = src +TESTDIR = test +BUILDDIR = build +PROGS = $(DESTDIR)/slsReceiver + + +CFLAGS= -g -DC_ONLY -fPIC +#FLAGS+= #-DVERBOSE -DVERYVERBOSE + +DFLAGS= -g -DDACS_INT -DSLS_RECEIVER_UDP_FUNCTIONS + +INCLUDES?= $(INCLUDESRXR) -I include/ -I ../slsDetectorCalibration + +#-Iinclude -I../slsDetectorCalibration -I$(ASM) + +SRC_CLNT = MySocketTCP.cpp UDPInterface.cpp UDPBaseImplementation.cpp UDPStandardImplementation.cpp slsReceiverTCPIPInterface.cpp slsReceiver.cpp slsReceiverUsers.cpp utilities.cpp + +ifeq ($(REST), yes) + SRC_CLNT += UDPRESTImplementation.cpp +endif + +MAIN_SRC = main.cpp + +DUMMY_MAIN_SRC = dummyMain.cpp + +OBJS=$(SRC_CLNT:%.cpp=$(BUILDDIR)/%.o) + + +$(info ) +$(info #######################################) +$(info # Compiling slsReceiverSoftware #) +$(info #######################################) +$(info ) + + +.PHONY: all intdoc package eigerReceiver clean + +all: builddir lib receiver + +dummy: $(DESTDIR)/dummyReceiver + +intdoc: $(SRC_H) $(SRC_CLNT) + doxygen doxy.config + +$(BUILDDIR)/%.o : $(SRCDIR)/%.cpp Makefile +ifeq ($(ROOTSLS),yes) + $(CXX) -DROOTSLS -o $@ -c $< $(INCLUDES) $(DFLAGS) $(ROOTFLAGS) -fPIC $(EPICSFLAGS) $(LDFLAGRXR) -L/usr/lib64/ $(FLAGS) +else + $(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) $(LDFLAGRXR) -lpthread $(FLAGS) +endif + +lib: $(OBJS) $(DESTDIR)/libSlsReceiver.so $(DESTDIR)/libSlsReceiver.a + +receiver: $(DESTDIR)/slsReceiver + + +$(DESTDIR)/libSlsReceiver.so: $(OBJS) + $(CXX) -shared -Wl,-soname,libSlsReceiver.so -o libSlsReceiver.so $(OBJS) -lc $(INCLUDES) $(DFLAGS) $(FLAGS) $(EPICSFLAGS) -L/usr/lib64 -lpthread + $(shell test -d $(DESTDIR) || mkdir -p $(DESTDIR)) + mv libSlsReceiver.so $(DESTDIR) + +$(DESTDIR)/libSlsReceiver.a: $(OBJS) + ar rcs libSlsReceiver.a $(OBJS) + mv libSlsReceiver.a $(DESTDIR) + + +$(DESTDIR)/slsReceiver: lib + $(CXX) -o $@ $(SRCDIR)/$(MAIN_SRC) $(FLAGS) $(INCLUDES) $(CLAGS) $(LIBS) $(LDFLAGRXR) -fPIC +#$(EIGERFLAGS) + + +$(DESTDIR)/dummyReceiver: lib + $(CXX) -o $@ $(SRCDIR)/$(DUMMY_MAIN_SRC) $(FLAGS) $(INCLUDES) $(CLAGS) $(LIBS) $(LDFLAGRXR) -fPIC +#$(EIGERFLAGS) + + +# Stand-alone Mysocket tests +mysocket_test: + g++ -o $(TESTDIR)/MySocketTCP.o -c $(SRCDIR)/MySocketTCP.cpp -I include + g++ -o $(TESTDIR)/rec $(TESTDIR)/MySocketTCP.o $(TESTDIR)/rec.cxx -I include + g++ -o $(TESTDIR)/send $(TESTDIR)/MySocketTCP.o $(TESTDIR)/send.cxx -I include + + +clean: buildclean + make testclean + if test -e $(DESTDIR)/libSlsReceiver.a; then rm $(DESTDIR)/libSlsReceiver.a;fi + if test -e $(DESTDIR)/libSlsReceiver.so; then rm $(DESTDIR)/libSlsReceiver.so;fi + if test -e $(PROGS); then rm $(PROGS);fi + +builddir: + if [ ! -d $(BUILDDIR) ]; then mkdir $(BUILDDIR); fi + +buildclean: + rm -rf $(OBJS) + +testclean: + if [ -f $(TESTDIR)/rec ]; then \ + cd $(TESTDIR) && rm *.o rec send; \ + fi + + +#------------------------------------------------------------------------------- + +install: package + +install_inc: + $(shell test -d $(DESTDIR) || mkdir -p $(DESTDIR)) + cp -P slsReceiver/slsReceiverUsers.h $(DESTDIR) + + diff --git a/slsReceiverSoftware/gitInfo.txt b/slsReceiverSoftware/gitInfo.txt new file mode 100644 index 0000000000..4d39e43143 --- /dev/null +++ b/slsReceiverSoftware/gitInfo.txt @@ -0,0 +1,9 @@ +Path: slsDetectorsPackage/slsReceiverSoftware +URL: origin git@git.psi.ch:sls_detectors_software/sls_receiver_software.git +Repository Root: origin git@git.psi.ch:sls_detectors_software/sls_receiver_software.git +Repsitory UUID: a10bf5ae88d113a482dca646085abcb7a45dc52e +Revision: 249 +Branch: master +Last Changed Author: Dhanya_Maliakal +Last Changed Rev: 249 +Last Changed Date: 2016-08-04 17:19:31 +0200 diff --git a/slsReceiverSoftware/include/MySocketTCP.h b/slsReceiverSoftware/include/MySocketTCP.h new file mode 100644 index 0000000000..31f56d453e --- /dev/null +++ b/slsReceiverSoftware/include/MySocketTCP.h @@ -0,0 +1,79 @@ + +#ifndef MY_SOCKET_TCP_H +#define MY_SOCKET_TCP_H + + + + +/** + * + * @libdoc The MySocketTCP class provides a simple interface for creating and sending/receiving data over a TCP socket. + * + * @short This class provides a simple interface for creating and sending/receiving data over a TCP socket. + * @author Ian Johnson + * @version 1.0 + */ + + + +//version 1.0, base development, Ian 19/01/09 + +/* Modified by anna on 19.01.2009 */ +/* + canceled SetupParameters() and varaibles intialized in the constructors' headers; + defined SEND_REC_MAX_SIZE (for compatibilty with mythen (and possibly other) pure C servers (i would move it to the common header file) + + added #ifndef C_ONLY... to cutout class definition when including in pure C servers (can be removed if SEND_REC_MAX_SIZE is moved to the common header file) + + defined private variables char hostname[1000] and int portno to store connection informations; + + defined public functions int getHostname(char *name) and int getPortNumber() to retrieve connection informations + + added public function int getErrorStatus() returning 1 if socketDescriptor<0 + + remove exits in the constructors and replace them with socketDescriptor=-1 + + replaced the argument of send/receive data with void (to avoid too much casting or compiler errors/warnings) + + added a function which really does not close the socket between send/receive (senddataonly, receivedataonly) + +*/ + + +/* Modified by Anna on 31.10.2012 + +developed and + +*/ + + +#include "genericSocket.h" +#define TCP_PACKET_SIZE 4096 + +class MySocketTCP: public genericSocket { + + public: + MySocketTCP(const char* const host_ip_or_name, unsigned short int const port_number): genericSocket(host_ip_or_name, port_number,TCP), last_keep_connection_open_action_was_a_send(0){setPacketSize(TCP_PACKET_SIZE);}; // sender (client): where to? ip + MySocketTCP(unsigned short int const port_number):genericSocket(port_number,TCP), last_keep_connection_open_action_was_a_send(0) {setPacketSize(TCP_PACKET_SIZE);}; // receiver (server) local no need for ip + + + //The following two functions will connectioned->send/receive->disconnect + int SendData(void* buf,int length);//length in characters + int ReceiveData(void* buf,int length); + + + //The following two functions stay connected, blocking other connections, and must be manually disconnected, + // when the last call is a SendData() or ReceiveData() the disconnection will be done automatically + //These function will also automatically disconnect->reconnect if + // two reads (or two writes) are called in a row to preserve the data send/receive structure + int SendDataAndKeepConnection(void* buf,int length); + int ReceiveDataAndKeepConnection(void* buf,int length); + + private: + + + bool last_keep_connection_open_action_was_a_send; + + +}; +#endif diff --git a/slsReceiverSoftware/include/RestHelper.h b/slsReceiverSoftware/include/RestHelper.h new file mode 100644 index 0000000000..92846750d6 --- /dev/null +++ b/slsReceiverSoftware/include/RestHelper.h @@ -0,0 +1,296 @@ +/** + * @file RestHelper.h + * @author Leonardo Sala + * @date Tue Mar 25 09:28:19 2014 + * + * @brief + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "JsonBox/Value.h" + +//#include "logger.h" + +#include +#include +#include +#include +#include + + + +using namespace Poco::Net; +using namespace Poco; +using namespace std; + +class RestHelper { + public: + + RestHelper(int timeout=10, int n_tries=1){ + /** + * + * + * @param timeout default=10 + * @param n_tries default=1 + */ + + http_timeout = timeout; + n_connection_tries = n_tries; + } + + ~RestHelper(){ + delete session; + }; + + + void set_connection_params(int timeout, int n_tries){ + http_timeout = timeout; + n_connection_tries = n_tries; + } + + + void get_connection_params(int *timeout, int *n_tries){ + *timeout = http_timeout; + *n_tries = n_connection_tries; + + } + + + void init(string hostname, int port){ + /** Initialize the RestHelper. Hostname and port parameters are not supposed to change. + * + * + * @param hostname FQDN of the host to connect to , e.g. www.iamfake.org, or sodoi.org + * @param port + * + * @return + */ + + //Check for http:// string + string proto_str = "http://"; + + if( size_t found = hostname.find(proto_str) != string::npos ){ + char c1[hostname.size()-found-1]; + size_t length1 = hostname.copy(c1, hostname.size()-found-1, proto_str.size()); + c1[length1]='\0'; + hostname = c1; + } + + full_hostname = "http://"+hostname; + session = new HTTPClientSession(hostname, port ); + session->setKeepAliveTimeout( Timespan( http_timeout,0) ); + }; + + + void init(string hostname_port){ + /** Initialize the RestHelper. Hostname_port parameters are not supposed to change. + * + * + * @param hostname FQDN and port of the host to connect to , e.g. www.iamfake.org:8080, or sodoi.org:1111. Default port is 8080 + * + * @return + */ + + //Check for http:// string + string proto_str = "http://"; + if( size_t found = hostname_port.find(proto_str) != string::npos ){ + char c1[hostname_port.size()-found-1]; + size_t length1 = hostname_port.copy(c1, hostname_port.size()-found-1, proto_str.size()); + c1[length1]='\0'; + hostname_port = c1; + } + + size_t found = hostname_port.rfind(":"); + char c1[ found ], c2[hostname_port.size()-found-1]; + string hostname; + size_t length1 = hostname_port.copy(c1, found); + + c1[length1]='\0'; + hostname = c1; + size_t length2 = hostname_port.copy(c2, found-1, found+1); + c2[length2]='\0'; + int port = atoi(c2); + + full_hostname = proto_str+hostname; + session = new HTTPClientSession(hostname,port ); + session->setKeepAliveTimeout( Timespan( http_timeout,0) ); + }; + + + int get_json(string request, string* answer){ + /** Retrieves a reply from the RESTful webservice. + * + * + * @param request Request without the hostname, e.g. if the full request would have been http://fake.org/fakemethod, request=fakemethod + * @param answer + * + * @return 0 if successful, -1 if failure happens. + */ + URI * uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + + // send request + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + req.setContentType("application/json\r\n"); + int code = send_request(session, req, answer); + delete uri; + return code; + }; + + + int get_json(string request, JsonBox::Value* json_value){ + /** + * + * + * @param request + * @param json_value + * + * @return + */ + URI *uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + // send request + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + req.setContentType("application/json\r\n"); + string answer; + int code = send_request(session, req, &answer); + if(code == 0 ) { + FILE_LOG(logDEBUG) << __AT__ << " REQUEST: " << " ANSWER: " << answer; + json_value->loadFromString(answer); + } + delete uri; + return code; + }; + + + int post_json(string request, string *answer, string request_body="{}"){ + /** + * + * + * @param request + * @param answer + * @param request_body Eventual arguments to the URL, e.g. action=login&name=mammamia + * + * @return + */ + //from: http://stackoverflow.com/questions/1499086/poco-c-net-ssl-how-to-post-https-request + URI *uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + HTTPRequest req(HTTPRequest::HTTP_POST, path, HTTPMessage::HTTP_1_1 ); + req.setContentType("application/json\r\n"); + req.setContentLength( request_body.length() ); + int code = send_request(session, req, answer, request_body); + + delete uri; + return code; + } + + + int post_json(string request, JsonBox::Value* json_value, string request_body="{}"){ + /** + * + * + * @param request + * @param json_value + * @param request_body Eventual arguments to the URL, e.g. action=login&name=mammamia + * + * @return + */ + + URI *uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + HTTPRequest req(HTTPRequest::HTTP_POST, path, HTTPMessage::HTTP_1_1 ); + //this does not work + //req.setContentType("application/json\r\n"); + //req.setContentLength( request.length() ); + string answer; + int code = send_request(session, req, &answer, request_body); + if(code==0){ + json_value->loadFromString(answer); + } + delete uri; + return code; + } + + + private: + + HTTPClientSession *session; + string full_hostname; + /// HTTP timeout in seconds, default is 8 + int http_timeout; + /// Number of connection tries + int n_connection_tries; + + + int send_request(HTTPClientSession *session, HTTPRequest &req, string *answer, string request_body=""){ + /** + * + * + * @param session + * @param req + * @param answer + * @param request_body + * + * @return + */ + + int n = 0; + int code = -1; + while(n < n_connection_tries){ + + req.setContentType("application/json"); + //without this you need to tell the lenght: http://pocoproject.org/forum/viewtopic.php?f=12&t=5741&p=10019&hilit=post+json#p10019 + // request.setContentLength(my_string.length()); + req.setChunkedTransferEncoding(true); + try { + //istringstream rs(request_body); + //req.read(rs); + //cout << " --- " << rs << endl; + if (request_body == "") + session->sendRequest( (req) ); + else{ + ostream &os = session->sendRequest( req ) ; + os << request_body; + } + + HTTPResponse res; + istream &is = session->receiveResponse(res); + StreamCopier::copyToString(is, *answer); + code = res.getStatus(); + if (code != 200){ + FILE_LOG(logERROR) << "HTTP ERROR " << res.getStatus() << ": " << res.getReason() ; + code = -1; + } + else + code = 0; + return code; + } + catch (exception& e){ + FILE_LOG(logERROR) << "Exception connecting to "<< full_hostname << ": "<< e.what() << ", sleeping 5 seconds (" << n << "/"< + +/** + * @short does all the base functions for a receiver, set/get parameters, start/stop etc. + */ + +class UDPBaseImplementation : protected virtual slsReceiverDefs, public UDPInterface { + + public: + + /************************************************************************* + * Constructor & Destructor ********************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + /** + * Constructor + */ + UDPBaseImplementation(); + + /** + * Destructor + */ + virtual ~UDPBaseImplementation(); + + /* + * Initialize class members + */ + void initializeMembers(); + + /************************************************************************* + * Getters *************************************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + + //**initial parameters*** + /* + * Get detector hostname + * @return NULL or hostname or NULL if uninitialized (max of 1000 characters) + */ + char *getDetectorHostname() const; + + + //***file parameters*** + /** + * Get File Name Prefix (without frame index, file index and extension (_d0_f000000000000_8.raw)) + * @return NULL or file name prefix (max of 1000 characters) + */ + char *getFileName() const; + + /** + * Get File Path + * @return NULL or file path (max of 1000 characters) + */ + char *getFilePath() const; + + /** + * Get File Index + * @return file index of acquisition + */ + uint64_t getFileIndex() const; + + /** + * Get Scan Tag + * @return scan tag //FIXME: needed? (unsigned integer?) + */ + int getScanTag() const; + + /** + * Get if Frame Index is enabled (acquisition of more than 1 frame adds '_f000000000000' to file name ) + * @return true if frame index needed, else false + */ + bool getFrameIndexEnable() const; + + /** + * Get File Write Enable + * @return true if file write enabled, else false + */ + bool getFileWriteEnable() const; + + /** + * Get File Over Write Enable + * @return true if file over write enabled, else false + */ + bool getOverwriteEnable() const; + + /** + * Get data compression, by saving only hits (so far implemented only for Moench and Gotthard) + * @return true if data compression enabled, else false + */ + bool getDataCompressionEnable() const; + + + //***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; + + /** + * Get Current Frame Index for an entire acquisition (including all scans) + * @return current frame index (represents all scans too) + */ + int64_t getAcquisitionIndex() const; + + + //***connection parameters*** + /** + * Get UDP Port Number + * @return udp port number + */ + uint32_t getUDPPortNumber() const; + + /** + * Get Second UDP Port Number (eiger specific) + * @return second udp port number + */ + uint32_t getUDPPortNumber2() const; + + /** + * Get Ehernet Interface + * @ethernet interface. eg. eth0 or "" if listening to all (max of 1000 characters) + */ + char *getEthernetInterface() const; + + + //***acquisition parameters*** + /** + * Get Short Frame Enabled, later will be moved to getROI (so far only for gotthard) + * @return index of adc enabled, else -1 if all enabled + */ + int getShortFrameEnable() const; + + /** + * Get the Frequency of Frames Sent to GUI + * @return 0 for random frame requests, n for nth frame frequency + */ + uint32_t getFrameToGuiFrequency() const; + + /** + * Get Acquisition Period + * @return acquisition period + */ + uint64_t getAcquisitionPeriod() const; + + /* + * Get 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 FIXME: (Not implemented) + * @return number of frames expected + */ + uint64_t getNumberOfFrames() const; + + /** + * Get Dynamic Range or Number of Bits Per Pixel + * @return dynamic range that is 4, 8, 16 or 32 + */ + uint32_t getDynamicRange() const; + + /** + * Get Ten Giga Enable + * @return true if 10Giga enabled, else false (1G enabled) + */ + bool getTenGigaEnable() const; + + /** + * Get Fifo Depth + * @return fifo depth + */ + uint32_t getFifoDepth() const; + + + //***receiver status*** + /** + * Get Listening Status of Receiver + * @return can be idle, listening or error depending on if the receiver is listening or not + */ + runStatus getStatus() const; + + + + + /************************************************************************* + * Setters *************************************************************** + * They modify the local cache of configuration or detector parameters *** + *************************************************************************/ + + //**initial parameters*** + /** + * Configure command line parameters + * @param config_map mapping of config parameters passed from command line arguments + */ + void configure(map config_map); + + /** + * Set Bottom Enable (eiger specific, should be moved to configure, and later from client via TCPIP) + * @param b is true for bottom enabled or false for bottom disabled + */ + void setBottomEnable(const bool b); + + + //***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[]); + + /** + * Set File Path + * Checks for file directory existence before setting file path, + * If it doesn't exist, it will set it blank + * @param c file path (max of 1000 characters) + */ + void setFilePath(const char c[]); + + /** + * Set File Index of acquisition + * @param i file index of acquisition + */ + void setFileIndex(const uint64_t i); + + /** + * Set Scan Tag + * @param i scan tag //FIXME: needed? (unsigned integer?) + */ + void setScanTag(const int i); + + /** + * Set Frame Index Enable (acquisition of more than 1 frame adds '_f000000000000' to file name ) + * @param b true for frame index enable, else false + */ + void setFrameIndexEnable(const bool b); + + /** + * Set File Write Enable + * @param b true for file write enable, else false + */ + void setFileWriteEnable(const bool b); + + /** + * Set File Overwrite Enable + * @param b true for file overwrite enable, else false + */ + void setOverwriteEnable(const bool b); + + /** + * 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); + + + //***connection parameters*** + /** + * Set UDP Port Number + * @param i udp port number + */ + void setUDPPortNumber(const uint32_t i); + + /** + * Set Second UDP Port Number (eiger specific) + * @return second udp port number + */ + void setUDPPortNumber2(const uint32_t i); + + /** + * Set Ethernet Interface to listen to + * @param c ethernet inerface eg. eth0 (max of 1000 characters) + */ + void setEthernetInterface(const char* c); + + + //***acquisition parameters*** + /** + * 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 i 0 for random frame requests, n for nth frame frequency + * @return OK or FAIL + */ + int setFrameToGuiFrequency(const uint32_t i); + + /** + * Set Acquisition Period + * @param i acquisition period + * @return OK or FAIL + */ + int setAcquisitionPeriod(const uint64_t i); + + /** + * 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); + + /** + * 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); + + /** + * Set Ten Giga Enable + * @param b true if 10Giga enabled, else false (1G enabled) + * @return OK or FAIL + */ + int setTenGigaEnable(const bool b); + + /** + * 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*** + /** + * 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); + + /** + * Sets detector hostname (and corresponding detector variables in derived REST class) + * It is second function called by the client when connecting to receiver. + * you can call this function only once. //FIXME: is this still valid, this implemented in derived REST class? + * @param c detector hostname + */ + void initialize(const char *c); + + + //***acquisition functions*** + /** + * Reset acquisition parameters such as total frames caught for an entire acquisition (including all scans) + */ + void resetAcquisitionCount(); + + /** + * Start Listening for Packets by activating all configuration settings to receiver + * @param c error message if FAIL + * @return OK or FAIL + */ + int startReceiver(char *c=NULL); + + /** + * Stop Listening for Packets + * Calls startReadout(), which stops listening and sets status to Transmitting + * When it has read every frame in buffer,it returns with the status Run_Finished + */ + void stopReceiver(); + + /** + * Stop Listening to Packets + * and sets status to Transmitting + */ + void startReadout(); + + /** + * Shuts down and deletes UDP Sockets + * @return OK or FAIL + */ + int shutDownUDPSockets(); + + /** + * Get the buffer-current frame read by receiver + * @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(char* c,char** raw, uint64_t &startAcq, uint64_t &startFrame); + + /** + * abort acquisition with minimum damage: close open files, cleanup. + * does nothing if state already is 'idle' + */ + void abort(); //FIXME: needed, isn't stopReceiver enough? + + /** + * Closes file / all files(if multiple files) + * @param i thread index (if multiple files used eg. root files) -1 for all threads + */ + void closeFile(int i = -1); + + + //***callback functions*** + /** + * Call back for start acquisition + * callback arguments are + * filepath + * filename + * fileindex + * datasize + * + * return value is the action which decides what the user and default responsibilities to save data are + * 0 callback takes care of open,close,wrie file + * 1 callback writes file, we have to open, close it + * 2 we open, close, write file, callback does not do anything + */ + void registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg); + + /** + * Call back for acquisition finished + * callback argument is + * total frames caught + */ + void registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg); + + /** + * Call back for raw data + * args to raw data ready callback are + * framenum + * datapointer + * datasize in bytes + * file descriptor + * guidatapointer (NULL, no data required) + */ + void registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg); + + + + + protected: + + /************************************************************************* + * Class Members ********************************************************* + *************************************************************************/ + //**detector parameters*** + /** detector type */ + detectorType myDetectorType; + /** detector hostname */ + char detHostname[MAX_STR_LENGTH]; + /** Number of Packets per Frame*/ + uint32_t packetsPerFrame; + /** Acquisition Period */ + int64_t acquisitionPeriod; + /** Frame Number */ + int64_t numberOfFrames; + /** Dynamic Range */ + uint32_t dynamicRange; + /** Ten Giga Enable*/ + bool tengigaEnable; + /** Fifo Depth */ + uint32_t fifoDepth; + /** Bottom Half Module Enable */ + bool bottomEnable; + + //***receiver parameters*** + /** Maximum Number of Listening Threads/ UDP Ports */ + const static int MAX_NUMBER_OF_LISTENING_THREADS = 2; + /** Receiver Status */ + runStatus status; + + //***connection parameters*** + /** Ethernet Interface */ + char eth[MAX_STR_LENGTH]; + /** Server UDP Port Number*/ + uint32_t udpPortNum[MAX_NUMBER_OF_LISTENING_THREADS]; + + //***file parameters*** + /** File Name without frame index, file index and extension (_d0_f000000000000_8.raw)*/ + char fileName[MAX_STR_LENGTH]; + /** File Path */ + char filePath[MAX_STR_LENGTH]; + /** File Index */ + uint64_t fileIndex; + /** Scan Tag */ + int scanTag; + /** Frame Index Enable */ + bool frameIndexEnable; + /** File Write enable */ + bool fileWriteEnable; + /** Overwrite enable */ + bool overwriteEnable; + /** Data Compression Enable - save only hits */ + bool dataCompressionEnable; + + //***acquisition count parameters*** + /** Total packets caught for an entire acquisition (including all scans) */ + uint64_t totalPacketsCaught; + /** Frames Caught for each real time acquisition (eg. for each scan) */ + uint64_t packetsCaught; + + //***acquisition indices parameters*** + /** Actual current frame index of an entire acquisition (including all scans) */ + uint64_t acquisitionIndex; + + //***acquisition parameters*** + /* Short Frame Enable or index of adc enabled, else -1 if all enabled (gotthard specific) TODO: move to setROI */ + int shortFrameEnable; + /** Frequency of Frames sent to GUI */ + uint32_t FrameToGuiFrequency; + + + + //***callback parameters*** + /** + * function being called back for start acquisition + * callback arguments are + * filepath + * filename + * fileindex + * datasize + * + * return value is + * 0 callback takes care of open,close,wrie file + * 1 callback writes file, we have to open, close it + * 2 we open, close, write file, callback does not do anything + */ + int (*startAcquisitionCallBack)(char*, char*,int, int, void*); + void *pStartAcquisition; + + /** + * function being called back for acquisition finished + * callback argument is + * total frames caught + */ + void (*acquisitionFinishedCallBack)(int, void*); + void *pAcquisitionFinished; + + + /** + * function being called back for raw data + * args to raw data ready callback are + * framenum + * datapointer + * datasize in bytes + * file descriptor + * guidatapointer (NULL, no data required) + */ + void (*rawDataReadyCallBack)(int, char*, int, FILE*, char*, void*); + void *pRawDataReady; + + +private: + +}; + + +#endif + +//#endif diff --git a/slsReceiverSoftware/include/UDPInterface.h b/slsReceiverSoftware/include/UDPInterface.h new file mode 100644 index 0000000000..9ad5a7e6a5 --- /dev/null +++ b/slsReceiverSoftware/include/UDPInterface.h @@ -0,0 +1,518 @@ +#ifndef UDPINTERFACE_H +#define UDPINTERFACE_H + +/*********************************************** + * @file UDPInterface.h + * @short Base class with all the functions for the UDP inteface of the receiver + ***********************************************/ +/** + * \mainpage Base class with all the functions for the UDP inteface of the receiver + */ + +/** + * @short Base class with all the functions for the UDP inteface of the receiver + */ + +#include + +#include "sls_receiver_defs.h" +#include "receiver_defs.h" +#include "utilities.h" +#include "logger.h" + + +class UDPInterface { + + + /* abstract class that defines the UDP interface of an sls detector data receiver. + * + * Use the factory method UDPInterface::create() to get an instance: + * + * UDPInterface *udp_interface = UDPInterface::create() + * + * + * supported sequence of method-calls: + * + * initialize() : once and only once after create() //FIXME: only once functionality implemented in the derived REST class, so not mention here? + * + * get*() : anytime after initialize(), multiples times + * + * set*() : anytime after initialize(), multiple times + * + * startReceiver(): anytime after initialize(). Will fail in TCPIP itself if state already is 'running': + * + * Only startReceiver() does change the data receiver configuration, it does pass the whole configuration cache to the data receiver. + * + * abort(), //FIXME: needed? + * + * stopReceiver() : anytime after initialize(). Will do nothing if state already is idle. + * Otherwise, sets status to transmitting when shutting down sockets + * then to run_finished when all data obtained + * then to idle when returning from this function + * + * + * getStatus() returns the actual state of the data receiver - idle, running or error, enum defined in include/sls_receiver_defs.h + * + * + * + * get*() and set*() methods access the local cache of configuration values only and *do not* modify the data receiver settings. + * + * set methods return nothing, use get methods to validate a set method success + * + * get-methods that return a char array (char *) allocate a new array at each call. The caller is responsible to free the allocated space: + * + * char *c = receiver->getFileName(); + * Or + * FIXME: so that the pointers are not shared external to the class, do the following way in the calling method? + * char *c = new char[MAX_STR_LENGTH]; + * strcpy(c,receiver->getFileName()); + * .... + * + * delete[] c; + * + * All pointers passed in externally will be allocated and freed by the calling function + * + * OK and FAIL are defined in include/sls_receiver_defs.h for functions implementing behavior + * + */ + + public: + + /************************************************************************* + * Constructor & Destructor ********************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + /** + * Constructor + * Only non virtual function implemented in this class + * Factory create method to create a standard or REST object + * @param [in] receiver_type type can be standard or REST + * @return a UDPInterface reference to object depending on receiver type + */ + static UDPInterface *create(string receiver_type = "standard"); + + /** + * Destructor + */ + virtual ~UDPInterface() {}; + + + + /************************************************************************* + * Getters *************************************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + + //**initial parameters*** + /* + * Get detector hostname + * @return hostname or NULL if uninitialized, must be released by calling function (max of 1000 characters) + */ + virtual char *getDetectorHostname() const = 0; + + + //***file parameters*** + /** + * Get File Name Prefix (without frame index, file index and extension (_d0_f000000000000_8.raw)) + * @return NULL or pointer to file name prefix, must be released by calling function (max of 1000 characters) + */ + virtual char *getFileName() const = 0; + + /** + * Get File Path + * @return NULL or pointer to file path, must be released by calling function (max of 1000 characters) + */ + virtual char *getFilePath() const = 0; + + /** + * Get File Index + * @return NULL or file index of acquisition + */ + virtual uint64_t getFileIndex() const = 0; + + /** + * Get Scan Tag + * @return scan tag //FIXME: needed? (unsigned integer?) + */ + virtual int getScanTag() const = 0; + + /** + * Get if Frame Index is enabled (acquisition of more than 1 frame adds '_f000000000000' to file name ) + * @return true if frame index needed, else false + */ + virtual bool getFrameIndexEnable() const = 0; + + /** + * Get File Write Enable + * @return true if file write enabled, else false + */ + virtual bool getFileWriteEnable() const = 0; + + /** + * Get File Over Write Enable + * @return true if file over write enabled, else false + */ + virtual bool getOverwriteEnable() const = 0; + + /** + * Get data compression, by saving only hits (so far implemented only for Moench and Gotthard) + * @return true if data compression enabled, else false + */ + virtual bool getDataCompressionEnable() const = 0; + + + //***acquisition count parameters*** + /** + * Get Total Frames Caught for an entire acquisition (including all scans) + * @return total number of frames caught for entire acquisition + */ + virtual uint64_t getTotalFramesCaught() const = 0; + + /** + * Get Frames Caught for each real time acquisition (eg. for each scan) + * @return number of frames caught for each scan + */ + virtual uint64_t getFramesCaught() const = 0; + + /** + * Get Current Frame Index for an entire acquisition (including all scans) + * @return current frame index (represents all scans too) or -1 if no packets caught + */ + virtual int64_t getAcquisitionIndex() const = 0; + + + //***connection parameters*** + /** + * Get UDP Port Number + * @return udp port number + */ + virtual uint32_t getUDPPortNumber() const = 0; + + /** + * Get Second UDP Port Number (eiger specific) + * @return second udp port number + */ + virtual uint32_t getUDPPortNumber2() const = 0; + + /** + * Get Ehernet Interface + * @return ethernet interface. eg. eth0 (max of 1000 characters) + */ + virtual char *getEthernetInterface() const = 0; + + + //***acquisition parameters*** + /** + * Get Short Frame Enabled, later will be moved to getROI (so far only for gotthard) + * @return index of adc enabled, else -1 if all enabled + */ + virtual int getShortFrameEnable() const = 0; + + /** + * Get the Frequency of Frames Sent to GUI + * @return 0 for random frame requests, n for nth frame frequency + */ + virtual uint32_t getFrameToGuiFrequency() const = 0; + + /** + * Get Acquisition Period + * @return acquisition period + */ + virtual uint64_t getAcquisitionPeriod() const = 0; + + /* + * Get 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 FIXME: (Not implemented) + * @return number of frames expected + */ + virtual uint64_t getNumberOfFrames() const = 0; + + /** + * Get Dynamic Range or Number of Bits Per Pixel + * @return dynamic range that is 4, 8, 16 or 32 + */ + virtual uint32_t getDynamicRange() const = 0; + + /** + * Get Ten Giga Enable + * @return true if 10Giga enabled, else false (1G enabled) + */ + virtual bool getTenGigaEnable() const = 0; + + /** + * Get Fifo Depth + * @return fifo depth + */ + virtual uint32_t getFifoDepth() const = 0; + + //***receiver status*** + /** + * Get Listening Status of Receiver + * @return can be idle, listening or error depending on if the receiver is listening or not + */ + virtual slsReceiverDefs::runStatus getStatus() const = 0; + + + + + /************************************************************************* + * Setters *************************************************************** + * They modify the local cache of configuration or detector parameters *** + *************************************************************************/ + + //**initial parameters*** + /** + * Configure command line parameters + * @param config_map mapping of config parameters passed from command line arguments + */ + virtual void configure(map config_map) = 0; + + /** + * Set Bottom Enable (eiger specific, should be moved to configure, and later from client via TCPIP) + * @param b is true for bottom enabled or false for bottom disabled + */ + virtual void setBottomEnable(const bool b)= 0; + + + //***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) + */ + virtual void setFileName(const char c[]) = 0; + + /** + * Set File Path + * Checks for file directory existence before setting file path + * @param c file path (max of 1000 characters) + */ + virtual void setFilePath(const char c[]) = 0; + + /** + * Set File Index of acquisition + * @param i file index of acquisition + */ + virtual void setFileIndex(const uint64_t i) = 0; + + /** + * Set Scan Tag + * @param i scan tag //FIXME: needed? (unsigned integer?) + */ + virtual void setScanTag(const int i) = 0; + + /** + * Set Frame Index Enable (acquisition of more than 1 frame adds '_f000000000000' to file name ) + * @param b true for frame index enable, else false + */ + virtual void setFrameIndexEnable(const bool b) = 0; + + /** + * Set File Write Enable + * @param b true for file write enable, else false + */ + virtual void setFileWriteEnable(const bool b) = 0; + + /** + * Set File Overwrite Enable + * @param b true for file overwrite enable, else false + */ + virtual void setOverwriteEnable(const bool b) = 0; + + /** + * 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 + */ + virtual int setDataCompressionEnable(const bool b) = 0; + + //***connection parameters*** + /** + * Set UDP Port Number + * @param i udp port number + */ + virtual void setUDPPortNumber(const uint32_t i) = 0; + + /** + * Set Second UDP Port Number (eiger specific) + * @return second udp port number + */ + virtual void setUDPPortNumber2(const uint32_t i) = 0; + + /** + * Set Ethernet Interface to listen to + * @param c ethernet inerface eg. eth0 (max of 1000 characters) + */ + virtual void setEthernetInterface(const char* c) = 0; + + + //***acquisition parameters*** + /** + * 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 + */ + virtual void setShortFrameEnable(const int i) = 0; + + /** + * Set the Frequency of Frames Sent to GUI + * @param i 0 for random frame requests, n for nth frame frequency + * @return OK or FAIL + */ + virtual int setFrameToGuiFrequency(const uint32_t i) = 0; + + /** + * Set Acquisition Period + * @param i acquisition period + * @return OK or FAIL + */ + virtual int setAcquisitionPeriod(const uint64_t i) = 0; + + /** + * 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 FIXME: (Not implemented) + * @param i number of frames expected + * @return OK or FAIL + */ + virtual int setNumberOfFrames(const uint64_t i) = 0; + + /** + * Set Dynamic Range or Number of Bits Per Pixel + * @param i dynamic range that is 4, 8, 16 or 32 + * @return OK or FAIL + */ + virtual int setDynamicRange(const uint32_t i) = 0; + + /** + * Set Ten Giga Enable + * @param b true if 10Giga enabled, else false (1G enabled) + * @return OK or FAIL + */ + virtual int setTenGigaEnable(const bool b) = 0; + + /** + * Set Fifo Depth + * @param i fifo depth value + * @return OK or FAIL + */ + virtual int setFifoDepth(const uint32_t i) = 0; + + + /************************************************************************* + * Behavioral functions*************************************************** + * They may modify the status of the receiver **************************** + *************************************************************************/ + + + //***initial functions*** + /** + * 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 + */ + virtual int setDetectorType(const slsReceiverDefs::detectorType d) = 0; + + /** + * Sets detector hostname (and corresponding detector variables in derived REST class) + * It is second function called by the client when connecting to receiver. + * you can call this function only once. //FIXME: is this still valid, this implemented in derived REST class? + * @param c detector hostname + */ + virtual void initialize(const char *c) = 0; + + + //***acquisition functions*** + /** + * Reset acquisition parameters such as total frames caught for an entire acquisition (including all scans) + */ + virtual void resetAcquisitionCount() = 0; + + /** + * Start Listening for Packets by activating all configuration settings to receiver + * @param c error message if FAIL + * @return OK or FAIL + */ + virtual int startReceiver(char *c=NULL) = 0; + + /** + * Stop Listening for Packets + * Calls startReadout(), which stops listening and sets status to Transmitting + * When it has read every frame in buffer,it returns with the status Run_Finished + */ + virtual void stopReceiver() = 0; + + /** + * Stop Listening to Packets + * and sets status to Transmitting + */ + virtual void startReadout() = 0; + + /** + * Shuts down and deletes UDP Sockets + * @return OK or FAIL + */ + virtual int shutDownUDPSockets() = 0; + + /** + * Get the buffer-current frame read by receiver + * @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 + */ + virtual void readFrame(char* c,char** raw, uint64_t &startAcq, uint64_t &startFrame)=0; + + /** + * abort acquisition with minimum damage: close open files, cleanup. + * does nothing if state already is 'idle' + */ + virtual void abort() = 0; //FIXME: needed, isnt stopReceiver enough? + + /** + * Closes file / all files(if multiple files) + * @param i thread index (if multiple files used eg. root files) -1 for all threads + */ + virtual void closeFile(int i = -1) = 0; + + + //***callback functions*** + /** + * Call back for start acquisition + * callback arguments are + * filepath + * filename + * fileindex + * datasize + * + * return value is + * 0 callback takes care of open,close,wrie file + * 1 callback writes file, we have to open, close it + * 2 we open, close, write file, callback does not do anything + */ + virtual void registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg) = 0; + + /** + * Call back for acquisition finished + * callback argument is + * total frames caught + */ + virtual void registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg) = 0; + + /** + * Call back for raw data + * args to raw data ready callback are + * framenum + * datapointer + * datasize in bytes + * file descriptor + * guidatapointer (NULL, no data required) + */ + virtual void registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg) = 0; + + + protected: + private: + +}; + +#endif /* #ifndef UDPINTERFACE_H */ diff --git a/slsReceiverSoftware/include/UDPRESTImplementation.h b/slsReceiverSoftware/include/UDPRESTImplementation.h new file mode 100644 index 0000000000..3741997214 --- /dev/null +++ b/slsReceiverSoftware/include/UDPRESTImplementation.h @@ -0,0 +1,153 @@ +//#ifdef REST +#ifndef UDP_REST_IMPLEMENTATION_H +#define UDP_REST_IMPLEMENTATION_H +/********************************************//** + * @file UDPRESTImplementation.h + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + + +#include "UDPBaseImplementation.h" +#include "RestHelper.h" + +#include +#include + +/** + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + */ + +class UDPRESTImplementation : protected virtual slsReceiverDefs, public UDPBaseImplementation { +public: + /************************************************************************* + * Constructor & Destructor ********************************************** + *************************************************************************/ + /** + * Constructor + */ + UDPRESTImplementation(); + + /** + * Destructor + */ + virtual ~UDPRESTImplementation(); + + + protected: + + /************************************************************************* + * Getters *************************************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + /** + * Get Rest State + */ + int get_rest_state(RestHelper * rest, string *rest_state); + + + /************************************************************************* + * Setters *************************************************************** + * They modify the local cache of configuration or detector parameters *** + *************************************************************************/ + /** + * Initialize REST + */ + void initialize_REST(); + + + + + public: + /************************************************************************* + * Getters *************************************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ + + + /************************************************************************* + * Setters *************************************************************** + * They modify the local cache of configuration or detector parameters *** + *************************************************************************/ + + /** + * Overridden method + * Configure command line parameters + * @param config_map mapping of config parameters passed from command line arguments + */ + void configure(map config_map); + + + /************************************************************************* + * Behavioral functions*************************************************** + * They may modify the status of the receiver **************************** + *************************************************************************/ + + /** + * 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 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(char* c,char** raw, uint64_t &startAcq, uint64_t &startFrame); + + /** + * Overridden method + * Closes file / all files(data compression involves multiple files) + * TCPIPInterface can also call this in case of illegal shutdown of receiver + * @param i thread index valid for datacompression using root files, -1 for all threads + */ + void closeFile(int i = -1); + +private: + + bool isInitialized; + RestHelper * rest ; + int rest_port; // receiver backend port + string rest_hostname; // receiver hostname + +}; + + +#endif + +//#endif /*REST*/ diff --git a/slsReceiverSoftware/include/UDPStandardImplementation.h b/slsReceiverSoftware/include/UDPStandardImplementation.h new file mode 100644 index 0000000000..26f63ddc0f --- /dev/null +++ b/slsReceiverSoftware/include/UDPStandardImplementation.h @@ -0,0 +1,718 @@ +//#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 + + +/** + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + */ + + +class UDPStandardImplementation: 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*** + + /** + * Overridden method + * Configure command line parameters + * @param config_map mapping of config parameters passed from command line arguments + */ + void configure(map config_map); + + //*** file parameters*** + /** + * 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 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); + + /** + * Overridden method + * Set the Frequency of Frames Sent to GUI + * @param i 0 for random frame requests, n for nth frame frequency + * @return OK or FAIL + */ + int setFrameToGuiFrequency(const uint32_t i); + + /** + * Overridden method + * Set Acquisition Period + * @param i acquisition period + * @return OK or FAIL + */ + int setAcquisitionPeriod(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 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(char* c,char** raw, uint64_t &startAcq, uint64_t &startFrame); + + /** + * Overridden method + * Closes file / all files(data compression involves multiple files) + * TCPIPInterface can also call this in case of illegal shutdown of receiver + * @param i thread index valid for datacompression using root files, -1 for all threads + */ + void closeFile(int i = -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 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 + * @return OK or FAIL + */ + int createNewFile(); + + /** + * 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 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 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 lSize number of bytes to listen to + * @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 lSize, int cSize, char* temp); + + /** + * 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 + * @return packet count + */ + uint32_t processListeningBuffer(int ithread, int cSize,char* temp); + + /** + * 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 + * Pops buffer from all the FIFOs and checks for dummy frames and end of acquisition + * @param ithread current thread index + * @param wbuffer the buffer array that is popped from all the FIFOs + * @param ready if that FIFO is allowed to pop (depends on if dummy buffer already popped/ waiting for other FIFO to finish a frame(eiger)) + * @param nP number of packets in the buffer popped out + * @param fifoTempFree circular fifo to save addresses of packets adding upto a frame before pushing into fifofree (eiger specific) + * @return true if end of acquisition else false + */ + bool popAndCheckEndofAcquisition(int ithread, char* wbuffer[], bool ready[], uint32_t nP[],CircularFifo* fifoTempFree[]); + + /** + * 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); + + /** + * Calle by handleWithoutDataCompression + * Creating headers Writing to file without compression + * @param wbuffer is the address of buffer popped out of FIFO + * @param numpackets is the number of packets + */ + void writeFileWithoutCompression(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 + */ + void updateFileHeader(); + + /** + * 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 buffer buffer to copy + */ + void copyFrameToGui(char* buffer[]); + + void processWritingBuffer(int ithread); + + void processWritingBufferPacketByPacket(int ithread); + + 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); + + + + + /************************************************************************* + * Class Members ********************************************************* + *************************************************************************/ + + //**detector parameters*** + /** Size of 1 Frame including headers */ + int frameSize; + + /** 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; + + + //***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_STR_LENGTH]; + + /** Maximum Packets Per File **/ + int maxPacketsPerFile; + + /** If file created successfully for all Writer Threads */ + bool fileCreateSuccess; + + char fileHeader[1000]; + + + + + //***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; + + /** Current Frame Number */ + uint64_t currentFrameNumber; + + /** Previous Frame number from buffer to calculate loss */ + int64_t previousFrameNumber; + + /** Last Frame Index Listened To */ + int32_t lastFrameIndex; + + /* Acquisition started */ + bool acqStarted; + + /* Measurement started */ + bool measurementStarted; + + /** Total Frame Count listened to by listening threads */ + int totalListeningFrameCount[MAX_NUMBER_OF_LISTENING_THREADS]; + + /** Pckets currently in current file, starts new file when it reaches max */ + uint32_t packetsInFile; + + /** Number of Missing Packets per buffer*/ + uint32_t numMissingPackets; + + /** Total Number of Missing Packets in acquisition*/ + uint32_t numTotMissingPackets; + + /** Number of Missing Packets in file */ + uint32_t numTotMissingPacketsInFile; + + + + + + //***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]; + + /** File Descriptor */ + FILE *sfilefd; + + /** Number of Jobs Per Buffer */ + int numberofJobsPerBuffer; + + /** Total fifo size */ + uint32_t fifoSize; + + /** Missing Packet identifier value */ + const static uint16_t missingPacketValue = 0xFFFF; + + /** Dummy Packet identifier value */ + const static uint32_t dummyPacketValue = 0xFFFFFFFF; + + //***receiver to GUI parameters*** + /** Current Frame copied for GUI */ + char* latestData; + + /** If Data to be sent to GUI is ready */ + bool guiDataReady; + + /** Pointer to data to be sent to GUI */ + char* guiData; + + /** Pointer to file name to be sent to GUI */ + char guiFileName[MAX_STR_LENGTH]; + + /** Semaphore to synchronize Writer and GuiReader threads*/ + sem_t writerGuiSemaphore; + + + + + + //***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]; + + /** Current Listening Thread Index*/ + int currentListeningThreadIndex; + + /** 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*** + /** Maximum Number of Writer Threads */ + const static int MAX_NUMBER_OF_WRITER_THREADS = 15; + + /** 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; + + + + + + //***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/ansi.h b/slsReceiverSoftware/include/ansi.h new file mode 100644 index 0000000000..2104913737 --- /dev/null +++ b/slsReceiverSoftware/include/ansi.h @@ -0,0 +1,60 @@ +#define RED "\x1b[31m" +#define GREEN "\x1b[32m" +#define YELLOW "\x1b[33m" +#define BLUE "\x1b[34m" +#define MAGENTA "\x1b[35m" +#define CYAN "\x1b[36m" +#define GRAY "\x1b[37m" +#define BG_RED "\x1b[41m" +#define BG_GREEN "\x1b[42m" +#define BG_YELLOW "\x1b[43m" +#define BG_BLUE "\x1b[44m" +#define BG_MAGENTA "\x1b[45m" +#define BG_CYAN "\x1b[46m" +#define RESET "\x1b[0m" +#define BOLD "\x1b[1m" + +#define cprintf(code, format, ...) printf(code format RESET, ##__VA_ARGS__) + +/* + +Code examples + +example 1 (a snippet): + + +#ifdef MARTIN + cprintf(BLUE, "LL Write - Len: %2d - If: %X - Data: ",buffer_len, ll->ll_fifo_base); + for (i=0; i < buffer_len/4; i++) + cprintf(BLUE, "%.8X ",*(((unsigned *) buffer)+i)); + printf("\n"); +#endif + +#ifdef MARTIN + cprintf(CYAN, "LL Read - If: %X - Data: ",ll->ll_fifo_base); +#endif + + + +example 2: + +int main() +{ + int i=1; + printf("Normal %i\n", i); + cprintf(RED, "Red\n"); + cprintf(GREEN, "Green\n"); + cprintf(YELLOW, "Yellow\n"); + cprintf(BLUE, "Blue\n"); + cprintf(MAGENTA, "Mangenta %i\n", i); + cprintf(CYAN, "Cyan %i\n", i); + cprintf(BOLD, "White %i\n", i); + cprintf(RED BOLD, "Red %i\n", i); + cprintf(GREEN BOLD, "Green\n"); + cprintf(YELLOW BOLD, "Yellow\n"); + cprintf(BLUE BOLD, "Blue\n"); + cprintf(MAGENTA BOLD, "Mangenta %i\n", i); + cprintf(CYAN BOLD, "Cyan %i\n", i); +} + +*/ diff --git a/slsReceiverSoftware/include/circularFifo.h b/slsReceiverSoftware/include/circularFifo.h new file mode 100644 index 0000000000..1d6fd427de --- /dev/null +++ b/slsReceiverSoftware/include/circularFifo.h @@ -0,0 +1,160 @@ +/* CircularFifo.h +* Not any company's property but Public-Domain +* Do with source-code as you will. No requirement to keep this +* header if need to use it/change it/ or do whatever with it +* +* Note that there is No guarantee that this code will work +* and I take no responsibility for this code and any problems you +* might get if using it. The code is highly platform dependent! +* +* Code & platform dependent issues with it was originally +* published at http://www.kjellkod.cc/threadsafecircularqueue +* 2009-11-02 +* @author Kjell Hedstr�m, hedstrom@kjellkod.cc */ + +#ifndef CIRCULARFIFO_H_ +#define CIRCULARFIFO_H_ + +//#include "sls_receiver_defs.h" +#include +#include +#include +using namespace std; + +typedef double double32_t; +typedef float float32_t; +typedef int int32_t; + + + +/** Circular Fifo (a.k.a. Circular Buffer) +* Thread safe for one reader, and one writer */ +template +class CircularFifo { +public: + + CircularFifo(unsigned int Size) : tail(0), head(0){ + Capacity = Size + 1; + array.resize(Capacity); + sem_init(&free_mutex,0,0); + } + virtual ~CircularFifo() { + sem_destroy(&free_mutex); + } + + bool push(Element*& item_); + bool pop(Element*& item_); + + bool isEmpty() const; + bool isFull() const; + + int getSemValue(); + +private: + volatile unsigned int tail; // input index + vector array; + volatile unsigned int head; // output index + unsigned int Capacity; + sem_t free_mutex; + + unsigned int increment(unsigned int idx_) const; +}; + +template +int CircularFifo::getSemValue() +{ + int value; + sem_getvalue(&free_mutex, &value); + return value; +} + + +/** Producer only: Adds item to the circular queue. +* If queue is full at 'push' operation no update/overwrite +* will happen, it is up to the caller to handle this case +* +* \param item_ copy by reference the input item +* \return whether operation was successful or not */ +template +bool CircularFifo::push(Element*& item_) +{ + + //cout<<"*head:"< +bool CircularFifo::pop(Element*& item_) +{ + //cout<<"-tail:"< +bool CircularFifo::isEmpty() const +{ + return (head == tail); +} + +/** Useful for testing and Producer check of status + * Remember that the 'full' status can change quickly + * as the Consumer catches up. + * + * \return true if circular buffer is full. */ +template +bool CircularFifo::isFull() const +{ + int tailCheck = (tail+1) % Capacity; + return (tailCheck == head); +} + +/** Increment helper function for index of the circular queue +* index is inremented or wrapped +* +* \param idx_ the index to the incremented/wrapped +* \return new value for the index */ +template +unsigned int CircularFifo::increment(unsigned int idx_) const +{ + // increment or wrap + // ================= + // index++; + // if(index == array.lenght) -> index = 0; + // + //or as written below: + // index = (index+1) % array.length + idx_ = (idx_+1) % Capacity; + return idx_; +} + +#endif /* CIRCULARFIFO_H_ */ diff --git a/slsReceiverSoftware/include/dummyUDPInterface.h b/slsReceiverSoftware/include/dummyUDPInterface.h new file mode 100644 index 0000000000..5cba675cc0 --- /dev/null +++ b/slsReceiverSoftware/include/dummyUDPInterface.h @@ -0,0 +1,436 @@ +#ifndef DUMMYUDPINTERFACE_H +#define DUMMYUDPINTERFACE_H + +/*********************************************** + * @file UDPInterface.h + * @short Base class with all the functions for the UDP inteface of the receiver + ***********************************************/ +/** + * \mainpage Base class with all the functions for the UDP inteface of the receiver + */ + +/** + * @short Base class with all the functions for the UDP inteface of the receiver + */ + +#include "UDPInterface.h" +#include "sls_receiver_defs.h" +#include "genericSocket.h" + + +class dummyUDPInterface : public UDPInterface { + + + /* abstract class that defines the UDP interface of an sls detector data receiver. + * + * Use the factory method UDPInterface::create() to get an instance: + * + * UDPInterface *udp_interface = UDPInterface::create() + * + * supported sequence of method-calls: + * + * initialize() : once and only once after create() + * + * get*() : anytime after initialize(), multiples times + * set*() : anytime after initialize(), multiple times + * + * startReceiver(): anytime after initialize(). Will fail if state already is 'running' + * + * abort(), + * stopReceiver() : anytime after initialize(). Will do nothing if state already is idle. + * + * getStatus() returns the actual state of the data receiver - running or idle. All other + * get*() and set*() methods access the local cache of configuration values only and *do not* modify the data receiver settings. + * + * Only startReceiver() does change the data receiver configuration, it does pass the whole configuration cache to the data receiver. + * + * get- and set-methods that return a char array (char *) allocate a new array at each call. The caller is responsible to free the allocated space: + * + * char *c = receiver->getFileName(); + * .... + * delete[] c; + * + * always: 1:YES 0:NO for int as bool-like arguments + * + */ + + public: + + /** + * Destructor + */ + dummyUDPInterface() : UDPInterface(), dynamicRange(16), scanTag(1000), nFrames(100), fWrite(1), fOverwrite(1), fIndex(0), fCaught(0), totfCaught(0), startAcqIndex(0), startFrameIndex(0), acqIndex(0), dataCompression(false), period(0), type(slsReceiverDefs::GENERIC), framesNeeded(100), udpPort1(1900), udpPort2(1901), shortFrame(0), nFramesToGui(0), e10G(0) {strcpy(detHostname,"none"); strcpy(fName,"run"); strcpy(fPath,"/scratch/"); strcpy(eth,"eth0"); cout << "New dummy UDP Interface" << endl; + + + + +}; + + ~dummyUDPInterface() {cout << "Destroying dummy UDP Interface" << endl;}; + + + void del(){cout << "Destroying dummy UDP Interface" << endl;}; + + virtual void configure(map config_map) {}; + /** + * Initialize the Receiver + @param detectorHostName detector hostname + * you can call this function only once. You must call it before you call startReceiver() for the first time. + */ + virtual void initialize(const char *detectorHostName){ cout << "set detector hostname to" << detHostname << endl; strcpy(detHostname,detectorHostName);}; + + + /* Returns detector hostname + /returns hostname + * caller needs to deallocate the returned char array. + * if uninitialized, it must return NULL + */ + virtual char *getDetectorHostname() const { cout << "get detector hostname " << detHostname << endl; return (char*) detHostname;}; + + /** + * Returns status of receiver: idle, running or error + */ + virtual slsReceiverDefs::runStatus getStatus() const { cout << "get dsummy status IDLE " << endl; return slsReceiverDefs::IDLE;};; + + /** + * Returns File Name + * caller is responsible to deallocate the returned char array. + */ + virtual char *getFileName() const { cout << "get file name " << fName << endl; return (char*) fName;}; + + + /** + * Returns File Path + * caller is responsible to deallocate the returned char array + */ + virtual char *getFilePath() const { cout << "get file path " << fPath << endl; return (char*) fPath;};; + + + /** + * Returns the number of bits per pixel + */ + virtual int getDynamicRange() const { cout << "get dynamic range " << dynamicRange << endl; return dynamicRange;};; + + /** + * Returns scan tag + */ + virtual int getScanTag() const { cout << "get scan tag " << scanTag << endl; return scanTag;}; + + /* + * Returns number of frames to receive + * This is the number of frames to expect to receiver from the detector. + * The data receiver will change from running to idle when it got this number of frames + */ + virtual int getNumberOfFrames() const { cout << "get number of frames " << nFrames << endl; return nFrames;}; + + /** + * Returns file write enable + * 1: YES 0: NO + */ + virtual int getEnableFileWrite() const { cout << "get enable file write " << fWrite << endl; return fWrite;}; + + /** + * Returns file over write enable + * 1: YES 0: NO + */ + virtual int getEnableOverwrite() const { cout << "get enable file overwrite " << fOverwrite << endl; return fOverwrite;}; + + /** + * Set File Name (without frame index, file index and extension) + @param c file name + /returns file name + * returns NULL on failure (like bad file name) + * does not check the existence of the file - we don't know which path we'll finally use, so no point to check. + * caller is responsible to deallocate the returned char array. + */ + virtual char* setFileName(const char c[]) { strcpy(fName,c); cout << "set file name " << fName << endl; return fName; }; + + /** + * Set File Path + @param c file path + /returns file path + * checks the existence of the directory. returns NULL if directory does not exist or is not readable. + * caller is responsible to deallocate the returned char array. + */ + virtual char* setFilePath(const char c[]) { strcpy(fPath,c); cout << "set file path " << fPath << endl; return fPath; }; + + /** + * Returns the number of bits per pixel + @param dr sets dynamic range + /returns dynamic range + * returns -1 on failure + * FIXME: what are the allowd values - should we use an enum as argument? + */ + virtual int setDynamicRange(const int dr) {dynamicRange=dr; cout << "set dynamic range " << dynamicRange << endl; return dynamicRange; }; + + + /** + * Set scan tag + @param tag scan tag + /returns scan tag (always non-negative) + * FIXME: valid range - only positive? 16bit ore 32bit? + * returns -1 on failure + */ + virtual int setScanTag(const int tag) {scanTag=tag; cout << "set scan tag " << scanTag << endl; return scanTag; }; + + + /** + * Sets number of frames + @param fnum number of frames + /returns number of frames + */ + virtual int setNumberOfFrames(const int fnum) {nFrames=fnum; cout << "set number of frames " << nFrames << endl; return nFrames; }; + + + /** + * Set enable file write + * @param i file write enable + /returns file write enable + */ + virtual int setEnableFileWrite(const int i) {fWrite=i; cout << "set enable file write " << fWrite << endl; return fWrite; }; + + + /** + * Set enable file overwrite + * @param i file overwrite enable + /returns file overwrite enable + */ + virtual int setEnableOverwrite(const int i) {fOverwrite=i; cout << "set enable file overwrite " << fOverwrite << endl; return fOverwrite; }; + + + /** + * Starts Receiver - activate all configuration settings to the eiger receiver and start to listen for packets + @param message is the error message if there is an error + /returns 0 on success or -1 on failure + */ + //FIXME: success == 0 or success == 1? + virtual int startReceiver(char *message=NULL) {cout << "dummy start receiver" << endl; + char buff[8225]; + buff[8224]='\0'; + int ip=0; + int ib; + genericSocket *udpSocket= new genericSocket(50004,genericSocket::UDP,8224); + while((ib=udpSocket->ReceiveDataOnly(buff,8224))>0) { + cout << "*** "<< ib <<" ************************** " << ip++ << endl; + cout << buff << endl; + cout << "*****************************" << endl << endl<< endl ; + } +return 0;}; + + /** + * Stops Receiver - stops listening for packets + /returns success + * same as abort(). Always returns 0. + */ + virtual int stopReceiver() {cout << "dummy stop receiver" << endl; return 0;}; + + /** + * abort acquisition with minimum damage: close open files, cleanup. + * does nothing if state already is 'idle' + */ + virtual void abort() {cout << "Aborting receiver" << endl; }; + + + +/******************************************************************************************************************* + **************************************** Added by Dhanya ********************************************************* + *******************************************************************************************************************/ + + /** + * Returns File Index + */ + virtual int getFileIndex() {cout << "get file index " << fIndex << endl; return fIndex;}; + + /** + * Returns Total Frames Caught for an entire acquisition (including all scans) + */ + virtual int getTotalFramesCaught() {cout << "get total frames caught " << totfCaught << endl ; return totfCaught;}; + + /** + * Returns Frames Caught for each real time acquisition (eg. for each scan) + */ + virtual int getFramesCaught() {cout << "get frames caught " << fCaught << endl; return fCaught;}; + + + /** + * Returns the frame index at start of entire acquisition (including all scans) + */ + virtual uint32_t getStartAcquisitionIndex(){ cout << "get start acquisition index " << startAcqIndex << endl; return startAcqIndex; }; + + /** + * Returns current Frame Index Caught for an entire acquisition (including all scans) + */ + virtual uint32_t getAcquisitionIndex(){ cout << "get acquisition index " << acqIndex << endl; return acqIndex; }; + + + /** + * Returns the frame index at start of each real time acquisition (eg. for each scan) + */ + virtual uint32_t getStartFrameIndex() { cout << "get start frame index " << startFrameIndex << endl; return startFrameIndex; }; + + + /** get data compression, by saving only hits + */ + virtual bool getDataCompression() { cout << "get data compression " << dataCompression << endl; return dataCompression;}; + + /** + * Set receiver type + * @param det detector type + * Returns success or FAIL + */ + virtual int setDetectorType(slsReceiverDefs::detectorType det) {type=det; cout << "set detector type " << det << endl; return slsReceiverDefs::OK;}; + + /** + * Set File Index + * @param i file index + */ + virtual int setFileIndex(int i) {fIndex=i; cout << "get file index " << fIndex << endl; return fIndex;}; + + /** set acquisition period if a positive number + */ + virtual int64_t setAcquisitionPeriod(int64_t index) {if (index>=0) {period=index; cout << "set period " << period << endl;} else { cout << "get period " << period << endl;} return period;}; + + /** + * Set Frame Index Needed + * @param i frame index needed + */ + virtual int setFrameIndexNeeded(int i) {framesNeeded=i; cout << "set frame index needed " << period << endl; return framesNeeded;}; + + /** + * Set UDP Port Number + */ + virtual void setUDPPortNo(int p){udpPort1=p; cout << "set UDP port 1 " << udpPort1 << endl; }; + + + /** + * Set UDP Port Number + */ + virtual void setUDPPortNo2(int p) {udpPort2=p; cout << "set UDP port 2 " << udpPort2 << endl; }; + + /** + * Set Ethernet Interface or IP to listen to + */ + virtual void setEthernetInterface(char* c){strcpy(eth,c); cout << "set eth " << c;}; + + /** + * Set short frame + * @param i if shortframe i=1 + */ + virtual int setShortFrame(int i){shortFrame=i; cout << " set short frame" << shortFrame << endl; return shortFrame;}; + + /** + * Set the variable to send every nth frame to gui + * or if 0,send frame only upon gui request + */ + virtual int setNFrameToGui(int i) {nFramesToGui=i; cout << "set nframes to gui " << nFramesToGui << endl; return nFramesToGui;}; + + /** + * Resets the Total Frames Caught + * This is how the receiver differentiates between entire acquisitions + * Returns 0 + */ + virtual void resetTotalFramesCaught() {totfCaught=0; cout << "total frames caugh reset " << totfCaught << endl;}; + + /** enabl data compression, by saving only hits + /returns if failed + */ + virtual int enableDataCompression(bool enable) {dataCompression=enable; cout << "set data compression " << dataCompression<< endl; return dataCompression;}; + + /** + * enable 10Gbe + @param enable 1 for 10Gbe or 0 for 1 Gbe, -1 to read out + \returns enable for 10Gbe + */ + virtual int enableTenGiga(int enable = -1) {if (enable>=0) {e10G=enable; cout << "set 10Gb "<< e10G << endl;} else cout << "get 10Gb "<< e10G << endl; return e10G;}; + + /** + * Returns the buffer-current frame read by receiver + * @param c pointer to current file name + * @param raw address of pointer, pointing to current frame to send to gui + * @param fnum frame number for eiger as it is not in the packet + * @param startAcquisitionIndex is the start index of the acquisition + * @param startFrameIndex is the start index of the scan + */ + virtual void readFrame(char* c,char** raw, uint32_t &fnum, uint32_t &startAcquisitionIndex, uint32_t &startFrameIndex){cout << "dummy read frame" << endl; }; + + /** set status to transmitting and + * when fifo is empty later, sets status to run_finished + */ + virtual void startReadout(){cout << "dummy start readout" << endl; }; + + /** + * shuts down the udp sockets + * \returns if success or fail + */ + virtual int shutDownUDPSockets(){cout << "dummy shut down udp sockets" << endl; return slsReceiverDefs::OK;}; + + /** + * Closes all files + * @param ithr thread index, -1 for all threads + */ + virtual void closeFile(int ithr = -1){cout << "dummy close file" << ithr << endl; }; + + /** + * Call back for start acquisition + callback arguments are + filepath + filename + fileindex + datasize + + return value is + 0 callback takes care of open,close,wrie file + 1 callback writes file, we have to open, close it + 2 we open, close, write file, callback does not do anything + */ + virtual void registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){cout << "dummy register callback start acquisition" << endl; }; + + /** + * Call back for acquisition finished + callback argument is + total frames caught + */ + virtual void registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){cout << "dummy register callback acquisition finished" << endl; }; + + /** + * Call back for raw data + args to raw data ready callback are + framenum + datapointer + datasize in bytes + file descriptor + guidatapointer (NULL, no data required) + */ +virtual void registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){cout << "dummy register callback get raw data" << endl; }; + + protected: + + private: + char detHostname[1000]; + char fName[10000]; + char fPath[10000]; + int dynamicRange; + int scanTag; + int nFrames; + int fWrite; + int fOverwrite; + + int fIndex; + int fCaught; +int totfCaught; +int startAcqIndex; +int startFrameIndex; +int acqIndex; +bool dataCompression; + int64_t period; + slsReceiverDefs::detectorType type; + int framesNeeded; + int udpPort1; + int udpPort2; + char eth[1000]; + int shortFrame; + int nFramesToGui; + int e10G; +}; + +#endif /* #ifndef DUMMYUDPINTERFACE_H */ diff --git a/slsReceiverSoftware/include/genericSocket.h b/slsReceiverSoftware/include/genericSocket.h new file mode 100644 index 0000000000..3facb0a2bb --- /dev/null +++ b/slsReceiverSoftware/include/genericSocket.h @@ -0,0 +1,732 @@ + +#ifndef GENERIC_SOCKET_H +#define GENERIC_SOCKET_H + + + + + +/** + * + * @libdoc genericSocket provides some functions to open/close sockets both TCP and UDP + * + * @short some functions to open/close sockets both TCP and UDP + * @author Anna Bergamaschi + * @version 0.0 + */ + + + +//version 1.0, base development, Ian 19/01/09 + +/* Modified by anna on 19.01.2009 */ +/* + canceled SetupParameters() and varaibles intialized in the constructors' headers; + defined SEND_REC_MAX_SIZE (for compatibilty with mythen (and possibly other) pure C servers (i would move it to the common header file) + + added #ifndef C_ONLY... to cutout class definition when including in pure C servers (can be removed if SEND_REC_MAX_SIZE is moved to the common header file) + + defined private variables char hostname[1000] and int portno to store connection informations; + + defined public functions int getHostname(char *name) and int getPortNumber() to retrieve connection informations + + added public function int getErrorStatus() returning 1 if socketDescriptor<0 + + remove exits in the constructors and replace them with socketDescriptor=-1 + + replaced the argument of send/receive data with void (to avoid too much casting or compiler errors/warnings) + + added a function which really does not close the socket between send/receive (senddataonly, receivedataonly) +*/ + +#ifdef __CINT__ +//class sockaddr_in; +class socklen_t; +class uint32_t; +class uint32_t_ss; +// CINT view of types: +class sockaddr_in; +// { +// unsigned short int sa_family; +// unsigned char sa_data[14]; +// }; +#else + +#include +#include +#include +#include +#include +#include + +#endif +#include /******exit */ + +#include +#include +#include + +#include +#include +#include + + + +using namespace std; + +#define DEFAULT_PACKET_SIZE 1286 +/*#define SOCKET_BUFFER_SIZE (100*1024*1024) //100MB*/ +#define SOCKET_BUFFER_SIZE (2000*1024*1024) //100MB +#define DEFAULT_PORTNO 1952 +#define DEFAULT_BACKLOG 5 +#define DEFAULT_UDP_PORTNO 50001 +#define DEFAULT_GUI_PORTNO 65000 + +class genericSocket{ + + public: + + /** + Communication protocol +*/ +enum communicationProtocol{ + TCP, /**< TCP/IP */ + UDP /**< UDP */ +}; + + + + genericSocket(const char* const host_ip_or_name, unsigned short int const port_number, communicationProtocol p, int ps = DEFAULT_PACKET_SIZE) : + // portno(port_number), + protocol(p), + is_a_server(0), + socketDescriptor(-1), + file_des(-1), + packet_size(ps), + nsending(0), + nsent(0), + total_sent(0)// sender (client): where to? ip + { + //memset(&serverAddress, 0, sizeof(sockaddr_in)); + //memset(&clientAddress, 0, sizeof(sockaddr_in)); + // serverAddress = {0}; + // clientAddress = {0}; + // strcpy(hostname,host_ip_or_name); + + strcpy(lastClientIP,"none"); + strcpy(thisClientIP,"none1"); + strcpy(dummyClientIP,"dummy"); + differentClients = 0; + + struct hostent *hostInfo = gethostbyname(host_ip_or_name); + if (hostInfo == NULL){ + cerr << "Exiting: Problem interpreting host: " << host_ip_or_name << "\n"; + } else { + // Set some fields in the serverAddress structure. + serverAddress.sin_family = hostInfo->h_addrtype; + memcpy((char *) &serverAddress.sin_addr.s_addr, + hostInfo->h_addr_list[0], hostInfo->h_length); + serverAddress.sin_port = htons(port_number); + socketDescriptor=0; //You can use send and recv, //would it work????? + } + clientAddress_length=sizeof(clientAddress); + } + + + int getProtocol(communicationProtocol p) { + switch (p) { + case TCP: + return SOCK_STREAM; + break; + case UDP: + return SOCK_DGRAM; + + default: + cerr << "unknow protocol " << p << endl; + return -1; + } + } + + int getProtocol() {return getProtocol(protocol);}; + + + + + /** + The constructor for a server + @short the contructor for a server + \param port_number port number to listen to + \param p TCP or UDP + \param eth interface name or IP address to listen to (if NULL, listen to all interfaces) + + */ + + genericSocket(unsigned short int const port_number, communicationProtocol p, int ps = DEFAULT_PACKET_SIZE, const char *eth=NULL): + //portno(port_number), + protocol(p), + is_a_server(1), + socketDescriptor(-1), + file_des(-1), + packet_size(ps), + nsending(0), + nsent(0), + total_sent(0) + { + +/* // you can specify an IP address: */ +/* // or you can let it automatically select one: */ +/* myaddr.sin_addr.s_addr = INADDR_ANY; */ + + + strcpy(lastClientIP,"none"); + strcpy(thisClientIP,"none1"); + strcpy(dummyClientIP,"dummy"); + differentClients = 0; + + if(serverAddress.sin_port == htons(port_number)){ + socketDescriptor = -10; + return; + } + + char ip[20]; + + strcpy(ip,"0.0.0.0"); + clientAddress_length=sizeof(clientAddress); + if (eth) { + strcpy(ip,nameToIp(string(eth)).c_str()); + if (string(ip)==string("0.0.0.0")) + strcpy(ip,eth); + } + + // strcpy(hostname,"localhost"); //needed?!?!?!? + + + socketDescriptor = socket(AF_INET, getProtocol(),0); //tcp + + if (socketDescriptor < 0) { + cerr << "Can not create socket "<= 0){ \ + close(socketDescriptor); \ + } \ + if(is_a_server and getProtocol() == TCP){\ + if(file_des>0)\ + close(file_des);\ + } + file_des=-1; \ + serverAddress.sin_port=-1; \ + }; + + +/* /\** @short if client returns hostname for connection */ +/* \param name string to write the hostname to */ +/* \returns 0 if client, 1 if server (in this case ignore name return value) */ + +/* *\/ */ +/* int getHostname(char *name){ */ +/* if (is_a_server==0) { */ +/* strcpy(name,getHostname().c_str()); */ +/* } */ +/* return is_a_server; */ +/* }; */ +/* /\** @short if client returns hostname for connection */ +/* \returns hostname */ + +/* *\/ */ +/* string getHostname(){return string(hostname);}; */ + +/* /\** @short returns port number for connection */ +/* \returns port number */ +/* *\/ */ +/* int getPortNumber(){return portno;}; */ + + /** @short returns communication protocol + \returns TCP or UDP + */ + int getCommunicationProtocol(){return protocol;}; + + + /** @short returns error status + \returns 1 if error + */ + int getErrorStatus(){if (socketDescriptor==-10) return -10; else if (socketDescriptor<0) return 1; else return 0;}; + + + /** @short etablishes connection; disconnect should always follow + \returns 1 if error + */ + int Connect(){//cout<<"connect"<0) return file_des; + if (protocol==UDP) return -1; + + if(is_a_server && protocol==TCP){ //server tcp; the server will wait for the clients connection + if (socketDescriptor>0) { + if ((file_des = accept(socketDescriptor,(struct sockaddr *) &clientAddress, &clientAddress_length)) < 0) { + cerr << "Error: with server accept, connection refused"<=0){ + close(socketDescriptor); + socketDescriptor = -1; + } + } + } + + /** @short free connection */ + void Disconnect(){ + if (protocol==UDP){ + close(socketDescriptor); + socketDescriptor=-1; + } + else{ + if(file_des>=0){ //then was open + if(is_a_server){ + close(file_des); + } + else { + close(socketDescriptor); + socketDescriptor=-1; + } + file_des=-1; + } + } + }; + + + void ShutDownSocket(){ + while(!shutdown(socketDescriptor, SHUT_RDWR)); + Disconnect(); + }; + + + + /** Set the socket timeout ts is in seconds */ + int SetTimeOut(int ts){ + + + if (ts<=0) + return -1; + + //cout << "socketdescriptor "<< socketDescriptor << endl; + struct timeval tout; + tout.tv_sec = 0; + tout.tv_usec = 0; + if(::setsockopt(socketDescriptor, SOL_SOCKET, SO_RCVTIMEO, &tout, sizeof(struct timeval)) <0) + { + cerr << "Error in setsockopt SO_RCVTIMEO "<< 0 << endl; + } + tout.tv_sec = ts; + tout.tv_usec = 0; + if(::setsockopt(socketDescriptor, SOL_SOCKET, SO_SNDTIMEO, &tout, sizeof(struct timeval)) < 0) + { + cerr << "Error in setsockopt SO_SNDTIMEO " << ts << endl; + } + return 0; + + + }; + + + int setPacketSize(int i=-1) { if (i>=0) packet_size=i; return packet_size;}; + + + + static string ipToName(string ip) { + struct ifaddrs *addrs, *iap; + struct sockaddr_in *sa; + char buf[32]; + + strcpy(buf,"none"); + + getifaddrs(&addrs); + for (iap = addrs; iap != NULL; iap = iap->ifa_next) { + if (iap->ifa_addr && (iap->ifa_flags & IFF_UP) && iap->ifa_addr->sa_family == AF_INET) { + sa = (struct sockaddr_in *)(iap->ifa_addr); + inet_ntop(iap->ifa_addr->sa_family, (void *)&(sa->sin_addr), buf, sizeof(buf)); + if (ip==string(buf)) { + //printf("%s\n", iap->ifa_name); + strcpy(buf,iap->ifa_name); + break; + } + } + } + freeifaddrs(addrs); + return string(buf); + }; + + static string nameToMac(string inf) { + struct ifreq ifr; + int sock, j, k; + char mac[32]; + + sock=getSock(inf,&ifr); + + if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) { + perror("ioctl(SIOCGIFHWADDR) "); + return string("00:00:00:00:00:00"); + } + for (j=0, k=0; j<6; j++) { + k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X", + (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]); + } + mac[sizeof(mac)-1]='\0'; + + if(sock!=1){ + close(sock); + } + return string(mac); + + }; + + + + static string nameToIp(string inf){ + struct ifreq ifr; + int sock; + char *p, addr[32]; + + sock=getSock(inf,&ifr); + + if (-1==ioctl(sock, SIOCGIFADDR, &ifr)) { + perror("ioctl(SIOCGIFADDR) "); + return string("0.0.0.0"); + } + p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr); + strncpy(addr,p,sizeof(addr)-1); + addr[sizeof(addr)-1]='\0'; + + if(sock!=1){ + close(sock); + } + return string(addr); + + }; + + static int getSock(string inf, struct ifreq *ifr) { + + int sock; + sock=socket(PF_INET, SOCK_STREAM, 0); + if (-1==sock) { + perror("socket() "); + return 1; + } + strncpy(ifr->ifr_name,inf.c_str(),sizeof(ifr->ifr_name)-1); + ifr->ifr_name[sizeof(ifr->ifr_name)-1]='\0'; + + return sock; + + }; + + + int ReceiveDataOnly(void* buf,int length=0){ + + if (buf==NULL) return -1; + + + total_sent=0; + + switch(protocol) { + case TCP: + if (file_des<0) return -1; + while(length>0){ + nsending = (length>packet_size) ? packet_size:length; + nsent = read(file_des,(char*)buf+total_sent,nsending); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + + if (total_sent>0) + strcpy(thisClientIP,dummyClientIP); + + if (strcmp(lastClientIP,thisClientIP)) + differentClients=1; + else + differentClients=0; + + break; + case UDP: + if (socketDescriptor<0) return -1; + + //if length given, listens to length, else listens for packetsize till length is reached + if(length){ + /*int k = 0;*/ + + while(length>0){ + nsending = (length>packet_size) ? packet_size:length; + /* + //created for debugging on 11.05.2015 + nsending=5000; + nsent = recvfrom(socketDescriptor,(char*)buf,nsending, 0, (struct sockaddr *) &clientAddress, &clientAddress_length); + if(nsent <1000){ + if(nsent < 48){ + cout << " "<fnum)<< "\t"; + cout << k <<" packets" << endl; + k = 0; + } + } + else + k++; + */ + nsent = recvfrom(socketDescriptor,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, &clientAddress_length); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + } + //listens to only 1 packet + else{ + //normal + nsending=packet_size; + nsent = recvfrom(socketDescriptor,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, &clientAddress_length); + //nsent = 1040; + total_sent+=nsent; + } + break; + default: + ; + } +#ifdef VERY_VERBOSE + cout << "sent "<< total_sent << " Bytes" << endl; +#endif + + + return total_sent; + + + + } + + + int SendDataOnly(void *buf, int length) { +#ifdef VERY_VERBOSE + cout << "want to send "<< length << " Bytes" << endl; +#endif + if (buf==NULL) return -1; + + total_sent=0; + + + switch(protocol) { + case TCP: + if (file_des<0) return -1; + while(length>0){ + nsending = (length>packet_size) ? packet_size:length; + nsent = write(file_des,(char*)buf+total_sent,nsending); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + break; + case UDP: + if (socketDescriptor<0) return -1; + while(length>0){ + nsending = (length>packet_size) ? packet_size:length; + nsent = sendto(socketDescriptor,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, clientAddress_length); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + + break; + default: + ; + } +#ifdef VERY_VERBOSE + cout << "sent "<< total_sent << " Bytes" << endl; +#endif + return total_sent; + + + } + + char lastClientIP[INET_ADDRSTRLEN]; + char thisClientIP[INET_ADDRSTRLEN]; + int differentClients; + + + protected: + + communicationProtocol protocol; + int is_a_server; + int socketDescriptor; + int file_des; + int packet_size; + struct sockaddr_in clientAddress, serverAddress; + socklen_t clientAddress_length; + char dummyClientIP[INET_ADDRSTRLEN]; + + + private: + + int nsending; + int nsent; + int total_sent; + + + + // pthread_mutex_t mp; +}; +#endif diff --git a/slsReceiverSoftware/include/gitInfoReceiver.h b/slsReceiverSoftware/include/gitInfoReceiver.h new file mode 100644 index 0000000000..b3eb26e836 --- /dev/null +++ b/slsReceiverSoftware/include/gitInfoReceiver.h @@ -0,0 +1,11 @@ +//#define SVNPATH "" +#define SVNURL "git@git.psi.ch:sls_detectors_software/sls_receiver_software.git" +//#define SVNREPPATH "" +#define SVNREPUUID "a10bf5ae88d113a482dca646085abcb7a45dc52e" +//#define SVNREV 0x249 +//#define SVNKIND "" +//#define SVNSCHED "" +#define SVNAUTH "Dhanya_Maliakal" +#define SVNREV 0x249 +#define SVNDATE 0x20160804 +// diff --git a/slsReceiverSoftware/include/gitInfoReceiverTmp.h b/slsReceiverSoftware/include/gitInfoReceiverTmp.h new file mode 100644 index 0000000000..58e48f4978 --- /dev/null +++ b/slsReceiverSoftware/include/gitInfoReceiverTmp.h @@ -0,0 +1,11 @@ +//#define SVNPATH "" +#define SVNURL "" +//#define SVNREPPATH "" +#define SVNREPUUID "" +//#define SVNREV "" +//#define SVNKIND "" +//#define SVNSCHED "" +#define SVNAUTH "" +#define SVNREV "" +#define SVNDATE "" +// diff --git a/slsReceiverSoftware/include/logger.h b/slsReceiverSoftware/include/logger.h new file mode 100644 index 0000000000..7732abffcf --- /dev/null +++ b/slsReceiverSoftware/include/logger.h @@ -0,0 +1,245 @@ +//#ifndef __LOG_H__ +//#define __LOG_H__ + +#include +#include +#include +#include +#include + +#ifdef VERBOSE +#define FILELOG_MAX_LEVEL logDEBUG +#endif + +#ifdef VERYVERBOSE +#define FILELOG_MAX_LEVEL logDEBUG4 +#endif + +#ifdef FIFODEBUG +#define FILELOG_MAX_LEVEL logDEBUG5 +#endif + +#ifndef FILELOG_MAX_LEVEL +#define FILELOG_MAX_LEVEL logINFO +#endif + + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define MYCONCAT(x,y) +#define __AT__ string(__FILE__) + string("::") + string(__func__) + string("(): ") +#define __SHORT_FORM_OF_FILE__ \ +(strrchr(__FILE__,'/') \ +? strrchr(__FILE__,'/')+1 \ +: __FILE__ \ +) +#define __SHORT_AT__ string(__SHORT_FORM_OF_FILE__) + string("::") + string(__func__) + string("(): ") + +//":" TOSTRING(__LINE__) + +/* +void error(const char *location, const char *msg){ + printf("Error at %s: %s\n", location, msg); +} +*/ + +inline std::string NowTime(); + +enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4, logDEBUG5}; + +template class Log{ + public: + Log(); + virtual ~Log(); + std::ostringstream& Get(TLogLevel level = logINFO); + static TLogLevel& ReportingLevel(); + static std::string ToString(TLogLevel level); + static TLogLevel FromString(const std::string& level); + protected: + std::ostringstream os; + TLogLevel lev; + private: + Log(const Log&); + Log& operator =(const Log&); +}; + + +class Output2FILE { +public: + static FILE*& Stream(); + static void Output(const std::string& msg); + static void Output(const std::string& msg, TLogLevel level); +}; + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# if defined (BUILDING_FILELOG_DLL) +# define FILELOG_DECLSPEC __declspec (dllexport) +# elif defined (USING_FILELOG_DLL) +# define FILELOG_DECLSPEC __declspec (dllimport) +# else +# define FILELOG_DECLSPEC +# endif // BUILDING_DBSIMPLE_DLL +#else +# define FILELOG_DECLSPEC +#endif // _WIN32 + +class FILELOG_DECLSPEC FILELog : public Log {}; +//typedef Log FILELog; + +#ifdef REST +#define FILE_LOG(level) \ + if (level > FILELOG_MAX_LEVEL) ; \ + else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \ + else FILELog().Get(level) +#else + #define FILE_LOG(level) \ + if (level > FILELOG_MAX_LEVEL) ; \ + else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \ + else FILELog().Get(level) +#endif + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + +#include + + + +inline std::string NowTime() + +{ + const int MAX_LEN = 200; + char buffer[MAX_LEN]; + if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, + "HH':'mm':'ss", buffer, MAX_LEN) == 0) + return "Error in NowTime()"; + + char result[100] = {0}; + static DWORD first = GetTickCount(); + sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000); + return result; +} + +#else + +#include + +inline std::string NowTime() +{ + char buffer[11]; + time_t t; + time(&t); + tm r = {0}; + strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r)); + struct timeval tv; + gettimeofday(&tv, 0); + char result[100] = {0}; + sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); + return result; +} + +#endif //WIN32 + + +template Log::Log():lev(logDEBUG){} + +template std::ostringstream& Log::Get(TLogLevel level) +{ + lev = level; + os << "- " << NowTime(); + os << " " << ToString(level) << ": "; + os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t'); + return os; +} + +template Log::~Log() +{ + os << std::endl; +#ifdef REST + T::Output( os.str()); +#else + T::Output( os.str(),lev); +#endif +} + +template TLogLevel& Log::ReportingLevel() +{ + static TLogLevel reportingLevel = logDEBUG5; + return reportingLevel; +} + +template std::string Log::ToString(TLogLevel level) +{ + static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4","DEBUG5"}; + return buffer[level]; +} + +template +TLogLevel Log::FromString(const std::string& level) +{ + if (level == "DEBUG5") + return logDEBUG5; + if (level == "DEBUG4") + return logDEBUG4; + if (level == "DEBUG3") + return logDEBUG3; + if (level == "DEBUG2") + return logDEBUG2; + if (level == "DEBUG1") + return logDEBUG1; + if (level == "DEBUG") + return logDEBUG; + if (level == "INFO") + return logINFO; + if (level == "WARNING") + return logWARNING; + if (level == "ERROR") + return logERROR; + Log().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default."; + return logINFO; +} + + +inline FILE*& Output2FILE::Stream() +{ + static FILE* pStream = stderr; + return pStream; +} + +inline void Output2FILE::Output(const std::string& msg) +{ + FILE* pStream = Stream(); + if (!pStream) + return; + fprintf(pStream, "%s", msg.c_str()); + fflush(pStream); +} + +inline void Output2FILE::Output(const std::string& msg, TLogLevel level) +{ + FILE* pStream = Stream(); + if (!pStream) + return; + switch(level){ + case logERROR: cprintf(RED BOLD,"%s",msg.c_str()); break; + case logWARNING: cprintf(YELLOW BOLD,"%s",msg.c_str()); break; + case logINFO: cprintf(GRAY,"%s",msg.c_str()); break; + default: fprintf(pStream,"%s",msg.c_str()); break; + } + fflush(pStream); +} + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# if defined (BUILDING_FILELOG_DLL) +# define FILELOG_DECLSPEC __declspec (dllexport) +# elif defined (USING_FILELOG_DLL) +# define FILELOG_DECLSPEC __declspec (dllimport) +# else +# define FILELOG_DECLSPEC +# endif // BUILDING_DBSIMPLE_DLL +#else +# define FILELOG_DECLSPEC +#endif // _WIN32 + + + +//#endif //__LOG_H__ diff --git a/slsReceiverSoftware/include/receiver_defs.h b/slsReceiverSoftware/include/receiver_defs.h new file mode 100755 index 0000000000..4c621a67fc --- /dev/null +++ b/slsReceiverSoftware/include/receiver_defs.h @@ -0,0 +1,197 @@ +#ifndef RECEIVER_DEFS_H +#define RECEIVER_DEFS_H + +#include "sls_receiver_defs.h" + +#include + + +/** + * structure of an eiger packet header + * subframenum subframe number for 32 bit mode (already written by firmware) + * missingpacket explicitly put to 0xFF to recognize it in file read (written by software) + * portnum 0 for the first port and 1 for the second port (written by software to file) + * dynamicrange dynamic range or bits per pixel (written by software to file) + */ +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 + * framenum 48 bit frame number (already written by firmware) + * packetnum packet number (already written by firmware) + */ +typedef struct { + unsigned char frameNumber[6]; + unsigned char packetNumber[2]; +} eiger_packet_footer_t; + +/** + * structure of an jungfrau packet header + * empty header + * framenumber + * packetnumber + */ +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; + + +#define GOODBYE -200 + +#define DO_NOTHING 0 +#define CREATE_FILES 1 +#define DO_EVERYTHING 2 + +#define BUF_SIZE (16*1024*1024) //16mb +#define SAMPLE_TIME_IN_NS 100000000//100ms +#define MAX_JOBS_PER_THREAD 1000 +#define HEADER_SIZE_NUM_TOT_PACKETS 4 +#define HEADER_SIZE_NUM_FRAMES 2 +#define HEADER_SIZE_NUM_PACKETS 1 + + +//all max frames defined in sls_receiver_defs.h. 20000 gotthard, 100000 for short gotthard, 1000 for moench, eiger 20000 + + + +#define GOTTHARD_FIFO_SIZE 25000 //cannot be less than max jobs per thread = 1000 +/*#define GOTTHARD_ALIGNED_FRAME_SIZE 4096*/ +#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 + +#define GOTTHARD_PIXELS_IN_ROW 1280 +#define GOTTHARD_PIXELS_IN_COL 1 + + +#define GOTTHARD_SHORT_PACKETS_PER_FRAME 1 +#define GOTTHARD_SHORT_ONE_PACKET_SIZE 518 +#define GOTTHARD_SHORT_BUFFER_SIZE 518 +#define GOTTHARD_SHORT_DATABYTES 512 +#define GOTTHARD_SHORT_FRAME_INDEX_MASK 0xFFFFFFFF +#define GOTTHARD_SHORT_FRAME_INDEX_OFFSET 0 +#define GOTTHARD_SHORT_PACKET_INDEX_MASK 0 +#define GOTTHARD_SHORT_PIXELS_IN_ROW 256 +#define GOTTHARD_SHORT_PIXELS_IN_COL 1 + + + + + +#define PROPIX_PIXELS_IN_ROW 22 +#define PROPIX_PIXELS_IN_COL 22 +#define PROPIX_DATABYTES_PER_PIXEL 2 + +#define PROPIX_FIFO_SIZE 25000 //cannot be less than max jobs per thread = 1000 +#define PROPIX_PACKETS_PER_FRAME 2 +#define PROPIX_ONE_PACKET_SIZE 1286 +#define PROPIX_BUFFER_SIZE (PROPIX_ONE_PACKET_SIZE*PROPIX_PACKETS_PER_FRAME) //1286*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_ALIGNED_FRAME_SIZE 65536*/ +#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 MOENCH_BYTES_PER_ADC (40*2) +#define MOENCH_PIXELS_IN_ONE_ROW 160 +#define MOENCH_BYTES_IN_ONE_ROW (MOENCH_PIXELS_IN_ONE_ROW*2) + + + + +#define JFRAU_FIFO_SIZE 2500 //cannot be less than max jobs per thread = 1000 +#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_DATA_BYTES (JFRAU_ONE_DATA_SIZE*JFRAU_PACKETS_PER_FRAME) //8192*128 +#define JFRAU_BUFFER_SIZE (JFRAU_ONE_PACKET_SIZE*JFRAU_PACKETS_PER_FRAME) //8214*128 + + +#define JFRAU_FRAME_INDEX_MASK 0x0 //Not Applicable, use struct +#define JFRAU_FRAME_INDEX_OFFSET 0x0 //Not Applicable, use struct +#define JFRAU_PACKET_INDEX_MASK 0x0//Not Applicable, use struct + +#define JFRAU_PIXELS_IN_ONE_ROW (256*4) +#define JFRAU_PIXELS_IN_ONE_COL (256*2) +#define JFRAU_BYTES_IN_ONE_ROW (JFRAU_PIXELS_IN_ONE_ROW*2) + + + +#define JCTB_FIFO_SIZE 2500 //cannot be less than max jobs per thread = 1000 +/*#define MOENCH_ALIGNED_FRAME_SIZE 65536*/ +#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 JCTB_BYTES_PER_ADC (2) +#define JCTB_PIXELS_IN_ONE_ROW 32 +#define JCTB_BYTES_IN_ONE_ROW (JCTB_PIXELS_IN_ONE_ROW*2) + + + + +#define EIGER_MAX_PORTS 2 +#define EIGER_HEADER_LENGTH 48 + +#define EIGER_FIFO_SIZE 100 +/*#define EIGER_ALIGNED_FRAME_SIZE 65536*/ +#define EIGER_ONE_GIGA_CONSTANT 16 +#define EIGER_TEN_GIGA_CONSTANT 4 +//#define EIGER_PACKETS_PER_FRAME_COSTANT (16*EIGER_MAX_PORTS)//*bit mode 4*16=64, 8*16=128, 16*16=256, 32*16=512 +#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_PACKET_HEADER_SIZE 8 +//#define EIGER_BUFFER_SIZE_CONSTANT (EIGER_ONE_PACKET_SIZE*EIGER_PACKETS_PER_FRAME_COSTANT)//1040*16*2//*bit mode +//#define EIGER_DATA_BYTES_CONSTANT (EIGER_ONE_DATA_SIZE*EIGER_PACKETS_PER_FRAME_COSTANT) //1024*16*2//*bit mode + +#define EIGER_FRAME_INDEX_MASK 0xFFFFFFFF //32 bit for now +#define EIGER_FRAME_INDEX_OFFSET 0 +#define EIGER_PACKET_INDEX_MASK 0x0 + +#define EIGER_IMAGE_HEADER_SIZE 48 + +#define EIGER_PIXELS_IN_ONE_ROW (256*4) +#define EIGER_PIXELS_IN_ONE_COL (256) + + +#endif diff --git a/slsReceiverSoftware/include/slsReceiver.h b/slsReceiverSoftware/include/slsReceiver.h new file mode 100644 index 0000000000..e76ea7d1bf --- /dev/null +++ b/slsReceiverSoftware/include/slsReceiver.h @@ -0,0 +1,91 @@ +/********************************************//** + * @file slsReceiver.h + * @short creates the UDP and TCP class objects + ***********************************************/ +#ifndef SLS_RECEIVER_H +#define SLS_RECEIVER_H + + +#include "slsReceiverTCPIPInterface.h" +#include "UDPInterface.h" + +#include "receiver_defs.h" +#include "MySocketTCP.h" +//#include "utilities.h" + + +/** + *@short creates the UDP and TCP class objects + */ + +class slsReceiver : private virtual slsReceiverDefs { + + public: + /** + * Constructor + * creates the tcp interface and the udp class + * @param argc from command line + * @param argv from command line + * @param succecc socket creation was successfull + */ + slsReceiver(int argc, char *argv[], int &success); + + /** + * Destructor + */ + ~slsReceiver(); + + /** + * starts listening on the TCP port for client comminication + \return 0 for success or 1 for FAIL in creating TCP server + */ + int start(); + + /** + * stops listening to the TCP & UDP port and exit receiver program + */ + void stop(); + + /** + * Close File and exits receiver server + */ + void closeFile(int p); + + /** + * get get Receiver Version + \returns id + */ + int64_t getReceiverVersion(); + + /** + @sort register calbback for starting the acquisition + @param func callback to be called when starting the acquisition. Its arguments are filepath filename fileindex data size + \returns 0 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 + */ + void registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg); + + + /** + callback argument is + toatal farmes caught + */ + void registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg); + + /** + args to raw data ready callback are + framenum + datapointer + datasize in bytes + file descriptor + guidatapointer (NULL, no data required) + */ + void registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg); + + + private: + slsReceiverTCPIPInterface* tcpipInterface; + UDPInterface* udp_interface; +}; + + +#endif diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h new file mode 100644 index 0000000000..8b5c4527f4 --- /dev/null +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -0,0 +1,329 @@ +/********************************************//** + * @file slsReceiverTCPIPInterface.h + * @short interface between receiver and client + ***********************************************/ +#ifndef SLS_RECEIVER_TCP_IP_INTERFACE_H +#define SLS_RECEIVER_TCP_IP_INTERFACE_H + + +#include "sls_receiver_defs.h" +#include "receiver_defs.h" +#include "MySocketTCP.h" +#include "UDPInterface.h" + + + +/** + *@short interface between receiver and client + */ + +class slsReceiverTCPIPInterface : private virtual slsReceiverDefs { + + public: + /** + * Constructor + * reads config file, creates socket, assigns function table + * @param succecc socket creation was successfull + * @param rbase pointer to the receiver base + * @param pn port number (defaults to default port number) + * @param bot mode is bottom if true, else its a top half module + */ + + slsReceiverTCPIPInterface(int &success, UDPInterface* rbase, int pn=-1, bool bot=false); + + /** + * Sets the port number to listen to. + Take care that the client must know to whcih port it has to listen to, so normally it is better to use a fixes port from the instatiation or change it from the client. + @param pn port number (-1 only get) + \returns actual port number + */ + int setPortNumber(int pn=-1); + + /** + * Starts listening on the TCP port for client comminication + \returns OK or FAIL + */ + int start(); + + /** stop listening on the TCP & UDP port for client comminication */ + void stop(); + + /** Destructor */ + virtual ~slsReceiverTCPIPInterface(); + + /** Close all threaded Files and exit */ + void closeFile(int p); + + /** gets version */ + int64_t getReceiverVersion(); + + //***callback functions*** + /** + * Call back for start acquisition + * callback arguments are + * filepath + * filename + * fileindex + * datasize + * + * return value is the action which decides what the user and default responsibilities to save data are + * 0 callback takes care of open,close,wrie file + * 1 callback writes file, we have to open, close it + * 2 we open, close, write file, callback does not do anything + */ + void registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg); + + /** + * Call back for acquisition finished + * callback argument is + * total frames caught + */ + void registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg); + + /** + * Call back for raw data + * args to raw data ready callback are + * framenum + * datapointer + * datasize in bytes + * file descriptor + * guidatapointer (NULL, no data required) + */ + void registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg); + +private: + + /** + * Static function - Thread started which is a TCP server + * Called by start() + * @param this_pointer pointer to this object + */ + static void* startTCPServerThread(void *this_pointer); + + + /** + * Thread started which is a TCP server + * Called by start() + */ + void startTCPServer(); + + /** assigns functions to the fnum enum */ + int function_table(); + + /** Decodes Function */ + int decode_function(); + + /** Unrecognized Function */ + int M_nofunc(); + + /** Set detector type */ + int set_detector_type(); + + /** Set File name without frame index, file index and extension */ + int set_file_name(); + + /** Set File path */ + int set_file_dir(); + + /** Set up UDP Details */ + int setup_udp(); + + /** Set File index */ + int set_file_index(); + + /** Set Frame index */ + int set_frame_index(); + + /** Start Receiver - starts listening to udp packets from detector */ + int start_receiver(); + + /** Stop Receiver - stops listening to udp packets from detector*/ + int stop_receiver(); + + /** Gets receiver status */ + int get_status(); + + /** Gets Total Frames Caught */ + int get_frames_caught(); + + /** Gets frame index for each acquisition */ + int get_frame_index(); + + /** Resets Total Frames Caught */ + int reset_frames_caught(); + + /** set short frame */ + int set_short_frame(); + + /** Reads Frame/ buffer */ + int read_frame(); + + /** gotthard specific read frame */ + int gotthard_read_frame(); + + /** propix specific read frame */ + int propix_read_frame(); + + /** moench specific read frame */ + int moench_read_frame(); + + /** eiger specific read frame */ + int eiger_read_frame(); + + /** jungfrau specific read frame */ + int jungfrau_read_frame(); + + /** Sets the receiver to send every nth frame to gui, or only upon gui request */ + int set_read_frequency(); + + /** Enable File Write*/ + int enable_file_write(); + + /** get version, calls get_version */ + int get_id(); + + /** set status to transmitting and + * when fifo is empty later, sets status to run_finished */ + int start_readout(); + + /** set acquisition period, frame number etc */ + int set_timer(); + + /** enable compression */ + int enable_compression(); + + /** set detector hostname */ + int set_detector_hostname(); + + /** set dynamic range */ + int set_dynamic_range(); + + /** enable overwrite */ + int enable_overwrite(); + + /** enable 10Gbe */ + int enable_tengiga(); + + /** set fifo depth */ + int set_fifo_depth(); + + //General Functions + /** Locks Receiver */ + int lock_receiver(); + + /** Set port */ + int set_port(); + + /** Get Last Client IP*/ + int get_last_client_ip(); + + /** Updates Client if different clients connect */ + int update_client(); + + /** Sends the updated parameters to client */ + int send_update(); + + /** Exit Receiver Server */ + int exit_server(); + + /** Execute command */ + int exec_command(); + + + + //private: + /** detector type */ + detectorType myDetectorType; + + /** slsReceiverBase object */ + UDPInterface *receiverBase; + + /** Number of functions */ + static const int numberOfFunctions = 256; + + /** Function List */ + int (slsReceiverTCPIPInterface::*flist[numberOfFunctions])(); + + /** Message */ + char mess[MAX_STR_LENGTH]; + + /** success/failure */ + int ret; + + /** Lock Status if server locked to a client */ + int lockStatus; + + /** Short frame */ + int shortFrame; + + /** Packets per frame */ + int packetsPerFrame; + + /** Dynamic Range */ + int dynamicrange; + + /** kill tcp server thread */ + int killTCPServerThread; + + /** thread for TCP server */ + pthread_t TCPServer_thread; + + /** size of one frame*/ + int tenGigaEnable; + + /** port number */ + int portNumber; + + /** true if bottom half module for eiger */ + bool bottom; + + /** Receiver not setup error message */ + char SET_RECEIVER_ERR_MESSAGE[MAX_STR_LENGTH]; + + + //***callback parameters*** + /** + * function being called back for start acquisition + * callback arguments are + * filepath + * filename + * fileindex + * datasize + * + * return value is + * 0 callback takes care of open,close,wrie file + * 1 callback writes file, we have to open, close it + * 2 we open, close, write file, callback does not do anything + */ + int (*startAcquisitionCallBack)(char*, char*,int, int, void*); + void *pStartAcquisition; + + /** + * function being called back for acquisition finished + * callback argument is + * total frames caught + */ + void (*acquisitionFinishedCallBack)(int, void*); + void *pAcquisitionFinished; + + + /** + * function being called back for raw data + * args to raw data ready callback are + * framenum + * datapointer + * datasize in bytes + * file descriptor + * guidatapointer (NULL, no data required) + */ + void (*rawDataReadyCallBack)(int, char*, int, FILE*, char*, void*); + void *pRawDataReady; + + +protected: + /** Socket */ + MySocketTCP* socket; +}; + + +#endif diff --git a/slsReceiverSoftware/include/slsReceiverUsers.h b/slsReceiverSoftware/include/slsReceiverUsers.h new file mode 100644 index 0000000000..eea4035601 --- /dev/null +++ b/slsReceiverSoftware/include/slsReceiverUsers.h @@ -0,0 +1,91 @@ +#ifndef SLS_RECEIVER_USERS_H +#define SLS_RECEIVER_USERS_H + +#include +#include + + +class slsReceiver; + + /** +@short Class for implementing the SLS data receiver in the users application. Callbacks can be defined for processing and/or saving data + */ +/** + + + @libdoc slsReceiverUsers is a class that can be instantiated in the users software to receive the data from the detectors. Callbacks can be defined for processing and/or saving data + + + ***********************************************/ + +class slsReceiverUsers { + +public: + /** + * Constructor + * reads config file, creates socket, assigns function table + * @param argc from command line + * @param argv from command line + * @param succecc socket creation was successfull + */ + slsReceiverUsers(int argc, char *argv[], int &success); + + + /** Destructor */ + ~slsReceiverUsers(); + + /** Close File and exits receiver server */ + void closeFile(int p); + + /** + * starts listening on the TCP port for client comminication + \return 0 for success or 1 for FAIL in creating TCP server + */ + int start(); + + /** stops listening to the TCP & UDP port and exit receiver program*/ + void stop(); + + /** + get get Receiver Version + \returns id + */ + int64_t getReceiverVersion(); + + /** + + @sort register calbback for starting the acquisition + \param func callback to be called when starting the acquisition. Its arguments are filepath filename fileindex data size + + \returns 0 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 + + */ + + void registerCallBackStartAcquisition(int (*func)(char* filepath, char* filename,int fileindex, int datasize, void*),void *arg); + + + /** + @sort register callback for end of acquisition + \param func end of acquisition callback. Argument nf is total frames caught + \returns nothing + */ + + + void registerCallBackAcquisitionFinished(void (*func)(int nf, void*),void *arg); + + + + /** + @sort register callback to be called when data are available (to process and/or save the data). + \param func raw data ready callback. arguments are framenum datapointer datasize file descriptor guidatapointer (NULL, no data required) + \returns nothing + */ + + void registerCallBackRawDataReady(void (*func)(int framenumber, char* datapointer, int datasize, FILE* filedescriptor, char* guidatapointer, void*),void *arg); + + //receiver object + slsReceiver* receiver; +}; + + +#endif diff --git a/slsReceiverSoftware/include/sls_receiver_defs.h b/slsReceiverSoftware/include/sls_receiver_defs.h new file mode 100755 index 0000000000..e37639b076 --- /dev/null +++ b/slsReceiverSoftware/include/sls_receiver_defs.h @@ -0,0 +1,195 @@ +#ifndef SLS_RECEIVER_DEFS_H +#define SLS_RECEIVER_DEFS_H + + +#ifdef __CINT__ +#define MYROOT +#define __cplusplus +#endif + +#include +#ifdef __cplusplus +#include +#endif +#include "ansi.h" + + +typedef double double32_t; +typedef float float32_t; +typedef int int32_t; + +/** default maximum string length */ +#define MAX_STR_LENGTH 1000 +#define MAX_FRAMES_PER_FILE 20000 +#define SHORT_MAX_FRAMES_PER_FILE 100000 +#define MOENCH_MAX_FRAMES_PER_FILE 1000 +#define EIGER_MAX_FRAMES_PER_FILE 2000 +#define JFRAU_MAX_FRAMES_PER_FILE 2000 +#define JFCTB_MAX_FRAMES_PER_FILE 100000 + + +/** + \file sls_receiver_defs.h +This file contains all the basic definitions common to the slsReceiver class +and to the server programs running on the receiver + * @author Anna Bergamaschi + * @version 0.1alpha (any string) + * @see slsDetector +$Revision: 809 $ + */ + + +#ifdef __cplusplus + +/** @short class containing all the constants and enum definitions */ +class slsReceiverDefs { +public: + + slsReceiverDefs(){}; + +#endif + + /** + Type of the detector + */ + enum detectorType { + GET_DETECTOR_TYPE=-1, /**< the detector will return its type */ + GENERIC, /**< generic sls detector */ + MYTHEN, /**< mythen */ + PILATUS, /**< pilatus */ + EIGER, /**< eiger */ + GOTTHARD, /**< gotthard */ + PICASSO, /**< picasso */ + AGIPD, /**< agipd */ + MOENCH, /**< moench */ + JUNGFRAU, /**< jungfrau */ + JUNGFRAUCTB, /**< jungfrauCTBversion */ + PROPIX /**< propix */ + }; + + + /** + return values + */ + enum { + OK, /**< function succeeded */ + FAIL, /**< function failed */ + FINISHED, /**< acquisition finished */ + FORCE_UPDATE + }; + + + /** + indexes for the acquisition timers + */ + enum timerIndex { + FRAME_NUMBER, /**< number of real time frames: total number of acquisitions is number or frames*number of cycles */ + ACQUISITION_TIME, /**< exposure time */ + FRAME_PERIOD, /**< period between exposures */ + DELAY_AFTER_TRIGGER, /**< delay between trigger and start of exposure or readout (in triggered mode) */ + GATES_NUMBER, /**< number of gates per frame (in gated mode) */ + PROBES_NUMBER, /**< number of probe types in pump-probe mode */ + CYCLES_NUMBER, /**< number of cycles: total number of acquisitions is number or frames*number of cycles */ + ACTUAL_TIME, /**< Actual time of the detector's internal timer */ + MEASUREMENT_TIME, /**< Time of the measurement from the detector (fifo) */ + + PROGRESS, /**< fraction of measurement elapsed - only get! */ + MEASUREMENTS_NUMBER, + FRAMES_FROM_START, + FRAMES_FROM_START_PG, + SAMPLES_JCTB, + SUBFRAME_ACQUISITION_TIME, /**< subframe exposure time */ + MAX_TIMERS + }; + + + /** + staus mask + */ + enum runStatus { + IDLE, /**< detector ready to start acquisition - no data in memory */ + ERROR, /**< error i.e. normally fifo full */ + WAITING, /**< waiting for trigger or gate signal */ + RUN_FINISHED, /**< acquisition not running but data in memory */ + TRANSMITTING, /**< acquisition running and data in memory */ + RUNNING, /**< acquisition running, no data in memory */ + STOPPED /**< acquisition stopped externally */ + }; + +#ifdef __cplusplus + /** returns string from enabled/disabled + \param b true or false + \returns string enabled, disabled + */ + static std::string stringEnable(bool b){\ + if(b) return std::string("enabled"); \ + else return std::string("disabled"); \ + }; + + /** returns detector type string from detector type index + \param t string can be Mythen, Pilatus, Eiger, Gotthard, Agipd, Unknown + \returns MYTHEN, PILATUS, EIGER, GOTTHARD, AGIPD, MÖNCH, GENERIC + */ + static std::string getDetectorType(detectorType t){ \ + switch (t) { \ + case MYTHEN: return std::string("Mythen"); \ + case PILATUS: return std::string("Pilatus"); \ + case EIGER: return std::string("Eiger"); \ + case GOTTHARD: return std::string("Gotthard"); \ + case AGIPD: return std::string("Agipd"); \ + case MOENCH: return std::string("Moench"); \ + case JUNGFRAU: return std::string("Jungfrau"); \ + case JUNGFRAUCTB: return std::string("JungfrauCTB"); \ + case PROPIX: return std::string("Propix"); \ + default: return std::string("Unknown"); \ + }}; + + /** returns detector type index from detector type string + \param type can be MYTHEN, PILATUS, EIGER, GOTTHARD, AGIPD, GENERIC + \returns Mythen, Pilatus, Eiger, Gotthard, Agipd, Mönch, Unknown + */ + static detectorType getDetectorType(std::string const type){\ + if (type=="Mythen") return MYTHEN; \ + if (type=="Pilatus") return PILATUS; \ + if (type=="Eiger") return EIGER; \ + if (type=="Gotthard") return GOTTHARD; \ + if (type=="Agipd") return AGIPD; \ + if (type=="Moench") return MOENCH; \ + if (type=="Jungfrau") return JUNGFRAU; \ + if (type=="JungfrauCTB") return JUNGFRAUCTB; \ + if (type=="Propix") return PROPIX; \ + return GENERIC; \ + }; + + + /** returns string from run status index + \param s can be ERROR, WAITING, RUNNING, TRANSMITTING, RUN_FINISHED + \returns string error, waiting, running, data, finished + */ + static std::string runStatusType(runStatus s){\ + switch (s) { \ + case ERROR: return std::string("error"); \ + case WAITING: return std::string("waiting"); \ + case RUNNING: return std::string("running"); \ + case TRANSMITTING: return std::string("data"); \ + case RUN_FINISHED: return std::string("finished"); \ + case STOPPED: return std::string("stopped"); \ + default: return std::string("idle"); \ + }}; + +#endif + +#ifdef __cplusplus +protected: +#endif + +#ifndef MYROOT +#include "sls_receiver_funcs.h" +#endif + +#ifdef __cplusplus +}; +#endif +; +#endif +; diff --git a/slsReceiverSoftware/include/sls_receiver_funcs.h b/slsReceiverSoftware/include/sls_receiver_funcs.h new file mode 100644 index 0000000000..e1ef930402 --- /dev/null +++ b/slsReceiverSoftware/include/sls_receiver_funcs.h @@ -0,0 +1,58 @@ +/** + @internal + function indexes to call on the server + All set functions with argument -1 work as get, when possible + */ +#ifndef SLS_RECEIVER_FUNCS_H +#define SLS_RECEIVER_FUNCS_H + +enum { + //General functions + F_EXEC_RECEIVER_COMMAND=128, /**< command is executed */ + F_EXIT_RECEIVER, /**< turn off receiver server */ + F_LOCK_RECEIVER, /**< Locks/Unlocks server communication to the given client */ + F_GET_LAST_RECEIVER_CLIENT_IP, /**< returns the IP of the client last connected to the receiver */ + F_SET_RECEIVER_PORT, /**< Changes communication port of the receiver */ + F_UPDATE_RECEIVER_CLIENT, /**< Returns all the important parameters to update the shared memory of the client */ + + // Identification + F_GET_RECEIVER_ID, /**< get receiver id of version */ + F_GET_RECEIVER_TYPE, /**< return receiver type */ + F_SEND_RECEIVER_DETHOSTNAME, /**< set detector hostname to receiver */ + + //network functions + F_RECEIVER_SHORT_FRAME, /**< Sets receiver to receive short frames */ + F_SETUP_RECEIVER_UDP, /**< sets the receiver udp connection and returns receiver mac address */ + + //Acquisition setup functions + F_SET_RECEIVER_TIMER, /**< set/get timer value */ + F_SET_RECEIVER_DYNAMIC_RANGE, /**< set/get detector dynamic range */ + F_READ_RECEIVER_FREQUENCY, /**< sets the frequency of receiver sending frames to gui */ + + // Acquisition functions + F_GET_RECEIVER_STATUS, /**< gets the status of receiver listening mode */ + F_START_RECEIVER, /**< starts the receiver listening mode */ + F_STOP_RECEIVER, /**< stops the receiver listening mode */ + F_START_RECEIVER_READOUT, /**< acquisition has stopped. start remaining readout in receiver */ + F_READ_RECEIVER_FRAME, /**< read one frame to gui*/ + + //file functions + F_SET_RECEIVER_FILE_PATH, /**< sets receiver file directory */ + F_SET_RECEIVER_FILE_NAME, /**< sets receiver file name */ + F_SET_RECEIVER_FILE_INDEX, /**< sets receiver file index */ + F_SET_RECEIVER_FRAME_INDEX, /**< sets the receiver frame index */ + F_GET_RECEIVER_FRAME_INDEX, /**< gets the receiver frame index */ + F_GET_RECEIVER_FRAMES_CAUGHT, /**< gets the number of frames caught by receiver */ + F_RESET_RECEIVER_FRAMES_CAUGHT, /**< resets the frames caught by receiver */ + F_ENABLE_RECEIVER_FILE_WRITE, /**< sets the receiver file write */ + F_ENABLE_RECEIVER_COMPRESSION, /**< enable compression in receiver */ + F_ENABLE_RECEIVER_OVERWRITE, /**< set overwrite flag in receiver */ + + F_ENABLE_RECEIVER_TEN_GIGA, /**< enable 10Gbe in receiver */ + F_SET_RECEIVER_FIFO_DEPTH /**< set receiver fifo depth */ + + /* Always append functions hereafter!!! */ +}; + +#endif +/** @endinternal */ diff --git a/slsReceiverSoftware/include/utilities.h b/slsReceiverSoftware/include/utilities.h new file mode 100644 index 0000000000..b28d4f32c4 --- /dev/null +++ b/slsReceiverSoftware/include/utilities.h @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include + +using namespace std; +#include "sls_receiver_defs.h" + +/* uncomment next line to enable debug output */ +//#define EIGER_DEBUG + + +int read_config_file(string fname, int *tcpip_port_no, map * configuration_map); + diff --git a/slsReceiverSoftware/slsReceiverUsers.doxy b/slsReceiverSoftware/slsReceiverUsers.doxy new file mode 100644 index 0000000000..b5d37ae18e --- /dev/null +++ b/slsReceiverSoftware/slsReceiverUsers.doxy @@ -0,0 +1,86 @@ +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + + + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +INTERNAL_DOCS = NO + +SHOW_INCLUDE_FILES = NO + +SHOW_FILES = NO + +SHOW_NAMESPACES = NO + +COMPACT_LATEX = YES + +PAPER_TYPE = a4 + +PDF_HYPERLINKS = YES + +USE_PDFLATEX = YES + +LATEX_HIDE_INDICES = YES + + +PREDEFINED = __cplusplus + +INPUT = slsReceiver/slsReceiverBase.h + +OUTPUT_DIRECTORY = slsReceiverUsersDocs diff --git a/slsReceiverSoftware/src/.cproject b/slsReceiverSoftware/src/.cproject new file mode 100644 index 0000000000..d34dce2968 --- /dev/null +++ b/slsReceiverSoftware/src/.cproject @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/slsReceiverSoftware/src/.project b/slsReceiverSoftware/src/.project new file mode 100644 index 0000000000..3c7b965619 --- /dev/null +++ b/slsReceiverSoftware/src/.project @@ -0,0 +1,28 @@ + + + Receiver + + + newMythenSoftware + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/slsReceiverSoftware/src/MySocketTCP.cpp b/slsReceiverSoftware/src/MySocketTCP.cpp new file mode 100644 index 0000000000..ba9583c1ca --- /dev/null +++ b/slsReceiverSoftware/src/MySocketTCP.cpp @@ -0,0 +1,53 @@ + +//version 1.0, base development, Ian 19/01/09 + + +#include "MySocketTCP.h" +#include +#include +#include + +using namespace std; + + + + + + + + + +int MySocketTCP::SendData(void* buf,int length){//length in characters + int ndata = SendDataAndKeepConnection(buf,length); + Disconnect(); + return ndata; +} + +int MySocketTCP::SendDataAndKeepConnection(void* buf,int length){//length in characters + if(last_keep_connection_open_action_was_a_send) Disconnect(); //to keep a structured data flow; + + Connect(); + int total_sent=SendDataOnly(buf,length); + last_keep_connection_open_action_was_a_send=1; + return total_sent; +} + + + + +int MySocketTCP::ReceiveData(void* buf,int length){//length in characters + int ndata = ReceiveDataAndKeepConnection(buf,length); + Disconnect(); + return ndata; +} + +int MySocketTCP::ReceiveDataAndKeepConnection(void* buf,int length){//length in characters + if(!last_keep_connection_open_action_was_a_send) Disconnect(); //to a keep structured data flow; + + Connect(); + // should preform two reads one to receive incomming char count + int total_received=ReceiveDataOnly(buf,length); + last_keep_connection_open_action_was_a_send=0; + return total_received; +} + diff --git a/slsReceiverSoftware/src/UDPBaseImplementation.cpp b/slsReceiverSoftware/src/UDPBaseImplementation.cpp new file mode 100644 index 0000000000..a76cf0e9f2 --- /dev/null +++ b/slsReceiverSoftware/src/UDPBaseImplementation.cpp @@ -0,0 +1,468 @@ +//#ifdef SLS_RECEIVER_UDP_FUNCTIONS +/********************************************//** + * @file UDPBaseImplementation.cpp + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + +#include "UDPBaseImplementation.h" +#include "genericSocket.h" + +#include // stat +#include +#include +using namespace std; + + + +/************************************************************************* + * Constructor & Destructor ********************************************** + * They access local cache of configuration or detector parameters ******* + *************************************************************************/ +UDPBaseImplementation::UDPBaseImplementation(){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + initializeMembers(); + + //***callback parameters*** + startAcquisitionCallBack = NULL; + pStartAcquisition = NULL; + acquisitionFinishedCallBack = NULL; + pAcquisitionFinished = NULL; + rawDataReadyCallBack = NULL; + pRawDataReady = NULL; +} + +void UDPBaseImplementation::initializeMembers(){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + FILE_LOG(logDEBUG) << "Info: Initializing base members"; + //**detector parameters*** + myDetectorType = GENERIC; + strcpy(detHostname,""); + packetsPerFrame = 0; + acquisitionPeriod = 0; + numberOfFrames = 0; + dynamicRange = 16; + tengigaEnable = false; + fifoDepth = 0; + bottomEnable = false; + + //***receiver parameters*** + status = IDLE; + + //***connection parameters*** + strcpy(eth,""); + for(int i=0;i config_map){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; +} + +void UDPBaseImplementation::setBottomEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + bottomEnable = b; + FILE_LOG(logINFO) << "Bottom - " << stringEnable(bottomEnable); +} + + +/***file parameters***/ +void UDPBaseImplementation::setFileName(const char c[]){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + if(strlen(c)) + strcpy(fileName, c); + FILE_LOG(logINFO) << "File name:" << fileName; +} + +void UDPBaseImplementation::setFilePath(const char c[]){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + if(strlen(c)){ + //check if filepath exists + struct stat st; + if(stat(c,&st) == 0) + strcpy(filePath,c); + else{ + strcpy(filePath,""); + FILE_LOG(logWARNING) << "FilePath does not exist:" << filePath; + } + strcpy(filePath, c); + } + FILE_LOG(logDEBUG) << "Info: File path:" << filePath; +} + +void UDPBaseImplementation::setFileIndex(const uint64_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + fileIndex = i; + FILE_LOG(logINFO) << "File Index:" << fileIndex; +} + +//FIXME: needed? +void UDPBaseImplementation::setScanTag(const int i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + scanTag = i; + FILE_LOG(logINFO) << "Scan Tag:" << scanTag; + +} + +void UDPBaseImplementation::setFrameIndexEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + frameIndexEnable = b; + FILE_LOG(logINFO) << "Frame Index Enable: " << stringEnable(frameIndexEnable); +} + +void UDPBaseImplementation::setFileWriteEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + fileWriteEnable = b; + FILE_LOG(logINFO) << "File Write Enable: " << stringEnable(fileWriteEnable); +} + +void UDPBaseImplementation::setOverwriteEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + overwriteEnable = b; + FILE_LOG(logINFO) << "Overwrite Enable: " << stringEnable(overwriteEnable); +} + +int UDPBaseImplementation::setDataCompressionEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + dataCompressionEnable = b; + FILE_LOG(logINFO) << "Data Compression : " << stringEnable(dataCompressionEnable); + + //overridden methods might return FAIL + return OK; +} + + +/***connection parameters***/ +void UDPBaseImplementation::setUDPPortNumber(const uint32_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + udpPortNum[0] = i; + FILE_LOG(logINFO) << "UDP Port Number[0]:" << udpPortNum[0]; +} + +void UDPBaseImplementation::setUDPPortNumber2(const uint32_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + udpPortNum[1] = i; + FILE_LOG(logINFO) << "UDP Port Number[1]:" << udpPortNum[1]; +} + +void UDPBaseImplementation::setEthernetInterface(const char* c){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + strcpy(eth, c); + FILE_LOG(logINFO) << "Ethernet Interface: " << eth; +} + + +/***acquisition parameters***/ +void UDPBaseImplementation::setShortFrameEnable(const int i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + shortFrameEnable = i; + FILE_LOG(logINFO) << "Short Frame Enable: " << stringEnable(shortFrameEnable); +} + +int UDPBaseImplementation::setFrameToGuiFrequency(const uint32_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + FrameToGuiFrequency = i; + FILE_LOG(logINFO) << "Frame To Gui Frequency:" << FrameToGuiFrequency; + + //overrridden child classes might return FAIL + return OK; +} + +int UDPBaseImplementation::setAcquisitionPeriod(const uint64_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + acquisitionPeriod = i; + FILE_LOG(logINFO) << "Acquisition Period:" << (double)acquisitionPeriod/(1E9) << "s"; + + //overrridden child classes might return FAIL + return OK; +} + +int UDPBaseImplementation::setNumberOfFrames(const uint64_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + numberOfFrames = i; + FILE_LOG(logINFO) << "Number of Frames:" << numberOfFrames; + + //overrridden child classes might return FAIL + return OK; +} + +int UDPBaseImplementation::setDynamicRange(const uint32_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + dynamicRange = i; + FILE_LOG(logINFO) << "Dynamic Range:" << dynamicRange; + + //overrridden child classes might return FAIL + return OK; +} + +int UDPBaseImplementation::setTenGigaEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + tengigaEnable = b; + FILE_LOG(logINFO) << "Ten Giga Enable: " << stringEnable(tengigaEnable); + + //overridden functions might return FAIL + return OK; +} + +int UDPBaseImplementation::setFifoDepth(const uint32_t i){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + fifoDepth = i; + FILE_LOG(logINFO) << "Fifo Depth: " << i; + + //overridden functions might return FAIL + return OK; +} + +/************************************************************************* + * Behavioral functions*************************************************** + * They may modify the status of the receiver **************************** + *************************************************************************/ + + +/***initial functions***/ +int UDPBaseImplementation::setDetectorType(const detectorType d){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + myDetectorType = d; + //if eiger, set numberofListeningThreads = 2; + FILE_LOG(logINFO) << "Detector Type:" << getDetectorType(d); + return OK; +} + +void UDPBaseImplementation::initialize(const char *c){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + if(strlen(c)) + strcpy(detHostname, c); + FILE_LOG(logINFO) << "Detector Hostname:" << detHostname; +} + + +/***acquisition functions***/ +void UDPBaseImplementation::resetAcquisitionCount(){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + totalPacketsCaught = 0; + FILE_LOG(logINFO) << "totalPacketsCaught:" << totalPacketsCaught; +} + +int UDPBaseImplementation::startReceiver(char *c){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; + return OK; +} + +void UDPBaseImplementation::stopReceiver(){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; +} + +void UDPBaseImplementation::startReadout(){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; +} + +int UDPBaseImplementation::shutDownUDPSockets(){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; + + //overridden functions might return FAIL + return OK; +} + +void UDPBaseImplementation::readFrame(char* c,char** raw, uint64_t &startAcquisitionIndex, uint64_t &startFrameIndex){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; +} + +//FIXME: needed, isnt stopReceiver enough? +void UDPBaseImplementation::abort(){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; +} + +void UDPBaseImplementation::closeFile(int i){ + FILE_LOG(logWARNING) << __AT__ << " doing nothing..."; + FILE_LOG(logERROR) << __AT__ << " must be overridden by child classes"; +} + + +/***callback functions***/ +void UDPBaseImplementation::registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){ + startAcquisitionCallBack=func; + pStartAcquisition=arg; +} + +void UDPBaseImplementation::registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){ + acquisitionFinishedCallBack=func; + pAcquisitionFinished=arg; +} + +void UDPBaseImplementation::registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){ + rawDataReadyCallBack=func; + pRawDataReady=arg; +} + + +//#endif diff --git a/slsReceiverSoftware/src/UDPInterface.cpp b/slsReceiverSoftware/src/UDPInterface.cpp new file mode 100644 index 0000000000..17491bc3a9 --- /dev/null +++ b/slsReceiverSoftware/src/UDPInterface.cpp @@ -0,0 +1,41 @@ +//#ifdef SLS_RECEIVER_UDP_FUNCTIONS +/********************************************//** + * @file slsReceiverUDPFunctions.cpp + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + + +#include +#include +using namespace std; + + +#include "UDPInterface.h" +#include "UDPBaseImplementation.h" +#include "UDPStandardImplementation.h" +#ifdef REST +#include "UDPRESTImplementation.h" +#endif + + +using namespace std; + +UDPInterface * UDPInterface::create(string receiver_type){ + + if (receiver_type == "standard"){ + FILE_LOG(logINFO) << "Starting " << receiver_type; + return new UDPStandardImplementation(); + } +#ifdef REST + else if (receiver_type == "REST"){ + return new UDPRESTImplementation(); + } +#endif + else{ + FILE_LOG(logWARNING) << "[ERROR] UDP interface not supported, using standard implementation"; + return new UDPBaseImplementation(); + } +} + + +//#endif diff --git a/slsReceiverSoftware/src/UDPRESTImplementation.cpp b/slsReceiverSoftware/src/UDPRESTImplementation.cpp new file mode 100644 index 0000000000..ab650257f4 --- /dev/null +++ b/slsReceiverSoftware/src/UDPRESTImplementation.cpp @@ -0,0 +1,331 @@ +#ifdef SLS_RECEIVER_UDP_FUNCTIONS +/********************************************//** + * @file UDPRESTImplementation.cpp + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + + +#include "UDPRESTImplementation.h" + +#include // exit() +#include // set precision +#include // map +#include +#include +#include +#include +//#include "utilities.h" +using namespace std; + +/* + TODO + + filePath != getFilePath + + better state handling. Now it is only IDLE - RUNNING - IDLE + */ + + +UDPRESTImplementation::UDPRESTImplementation(){ + FILE_LOG(logDEBUG) << "PID: " << getpid() << __AT__ << " called"; + + //TODO I do not really know what to do with bottom... + // Default values + isInitialized = false; + rest = NULL; + rest_hostname = "localhost"; + rest_port = 8081; +} + + +UDPRESTImplementation::~UDPRESTImplementation(){ + delete rest; +} + + +void UDPRESTImplementation::configure(map config_map){ + FILE_LOG(logWARNING) << __AT__ << " called"; + + map::const_iterator pos; + + pos = config_map.find("rest_hostname"); + if (pos != config_map.end() ){ + string host_port_str = pos->second; + std::size_t pos = host_port_str.find(":"); // position of "live" in str + if(pos != string::npos){ + istringstream (host_port_str.substr (pos)) >> rest_port; + rest_hostname = host_port_str.substr(0, pos); + } + } + + /* + for(map::const_iterator i=config_map.begin(); i != config_map.end(); i++){ + std::cout << i->first << " " << i->second<< std::endl; + } + */ + +} + + +int UDPRESTImplementation::get_rest_state(RestHelper * rest, string *rest_state){ + + JsonBox::Value answer; + //string rest_state = ""; + int code = rest->get_json("state", &answer); + if ( code != -1 ){ + (*rest_state) = answer["state"].getString(); + } + + return code; +} + + +void UDPRESTImplementation::initialize_REST(){ + + FILE_LOG(logDEBUG) << __AT__ << " called"; + FILE_LOG(logDEBUG) << __AT__ << " REST status is initialized: " << isInitialized; + + if (rest_hostname.empty()) { + FILE_LOG(logDEBUG) << __AT__ <<"can't initialize with empty string or NULL for detectorHostname"; + } + else if (isInitialized == true) { + FILE_LOG(logDEBUG) << __AT__ << "already initialized, can't initialize several times"; + } + else { + FILE_LOG(logDEBUG) << __AT__ << "with receiverHostName=" << rest_hostname << ":" << rest_port; + + rest = new RestHelper() ; + std::string answer; + int code; + try{ + rest->init(rest_hostname, rest_port); + code = get_rest_state(rest, &answer); + std::cout << "AAAAAAAa " << answer << std::endl; + + + if (code != 0){ + FILE_LOG(logERROR) << __AT__ << " REST state returned: " << answer; + throw; + } + else{ + isInitialized = true; + status = slsReceiverDefs::IDLE; + } + FILE_LOG(logDEBUG) << __func__ << "Answer: " << answer; + } + catch(std::string e){ + FILE_LOG(logERROR) << __func__ << ": " << e; + throw; + } + + //JsonBox::Object json_object; + //json_object["configfile"] = JsonBox::Value("FILENAME"); + JsonBox::Value json_request; + //json_request["configfile"] = "config.py"; + json_request["path"] = filePath; + + stringstream ss; + string test; + //std::cout << "GetSTring: " << json_request << std::endl; + json_request.writeToStream(ss, false); + //ss << json_request; + ss >> test; + + + code = rest->get_json("state", &answer); + FILE_LOG(logDEBUG) << __AT__ << " state got " << code << " " << answer << "\n"; + if (answer != "INITIALIZED"){ + test = "{\"path\":\"" + string( getFilePath() ) + "\"}"; + code = rest->post_json("state/initialize", &answer, test); + } + else{ + test = "{\"path\":\"" + string( getFilePath() ) + "\"}"; + code = rest->post_json("state/configure", &answer, test); + } + FILE_LOG(logDEBUG) << __AT__ << " state/configure got " << code; + code = rest->get_json("state", &answer); + FILE_LOG(logDEBUG) << __AT__ << " state got " << code << " " << answer << "\n"; + + + /* + std::std::cout << string << std::endl; << "---- REST test 3: true, json object "<< std::endl; + JsonBox::Value json_value; + code = rest.get_json("status", &json_value); + std::cout << "JSON " << json_value["status"] << std::endl; + */ + } + + FILE_LOG(logDEBUG) << __func__ << ": initialize() done"; + +} + + + + + +/** acquisition functions */ + + +int UDPRESTImplementation::startReceiver(char message[]){ + int i; + + FILE_LOG(logDEBUG) << __FILE__ << "::" << __func__ << " starting"; + initialize_REST(); + FILE_LOG(logDEBUG) << __FILE__ << "::" << __func__ << " initialized"; + + cout << "Starting Receiver" << endl; + + std::string answer; + int code; + //char *intStr = itoa(a); + //string str = string(intStr); + // TODO: remove hardcode!!! + stringstream ss; + ss << getDynamicRange(); + string str_dr = ss.str(); + stringstream ss2; + ss2 << getNumberOfFrames(); + string str_n = ss2.str(); + + + cout << "Starting Receiver" << endl; + + std::string request_body = "{\"settings\": {\"bit_depth\": " + str_dr + ", \"nimages\": " + str_n + "}}"; + //std::string request_body = "{\"settings\": {\"nimages\":1, \"scanid\":999, \"bit_depth\":16}}"; + FILE_LOG(logDEBUG) << __FILE__ << "::" << " sending this configuration body: " << request_body; + code = rest->post_json("state/configure", &answer, request_body); + code = rest->get_json("state", &answer); + FILE_LOG(logDEBUG) << __FILE__ << "::" << " got: " << answer; + + //code = rest->post_json("state/open", &answer); + //code = rest->get_json("state", &answer); + + status = RUNNING; + + return OK; +} + + + + +void UDPRESTImplementation::stopReceiver(){ + + FILE_LOG(logDEBUG) << __AT__ << "called"; + + if(status == RUNNING) + startReadout(); + + while(status == TRANSMITTING) + usleep(5000); + + //change status + status = IDLE; + + FILE_LOG(logDEBUG) << __AT__ << "exited, status " << endl; + +} + + + + + +void UDPRESTImplementation::startReadout(){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + status = TRANSMITTING; + + //kill udp socket to tell the listening thread to push last packet + shutDownUDPSockets(); + FILE_LOG(logDEBUG) << __FILE__ << "::" << __func__ << " done"; + +} + + + + + +/* FIXME + * Its also called by TCP in case of illegal shut down such as Ctrl + c. + * Upto you what you want to do with it. + */ +int UDPRESTImplementation::shutDownUDPSockets(){ + + FILE_LOG(logDEBUG) << __AT__ << "called"; + + // this is just to be sure, it could be removed + for(int i=0;iShutDownSocket(); + delete udpSocket[i]; + udpSocket[i] = NULL; + } + } + + JsonBox::Value answer; + int code; + string be_state = ""; + + FILE_LOG(logDEBUG) << __AT__ << " numListeningThreads=" << numListeningThreads; + if (rest == NULL){ + FILE_LOG(logWARNING) << __AT__ << "No REST object initialized, closing..."; + return OK; + } + + // getting the state + FILE_LOG(logWARNING) << "PLEASE WAIT WHILE CHECKING AND SHUTTING DOWN ALL CONNECTIONS!"; + code = rest->get_json("state", &answer); + be_state = answer["state"].getString(); + + // LEO: this is probably wrong + if (be_state == "OPEN"){ + while (be_state != "TRANSIENT"){ + code = rest->get_json("state", &answer); + be_state = answer["state"].getString(); + cout << "be_State: " << be_state << endl; + usleep(10000); + } + + code = rest->post_json("state/close", &answer); + std::cout <post_json("state/reset", &answer); + std::cout << code << " " << answer << std::endl; + + code = rest->get_json("state", &answer); + std::cout << code << " " << answer << std::endl; + } + status = slsReceiverDefs::RUN_FINISHED; + + //LEO: not sure it's needed + delete rest; + + FILE_LOG(logDEBUG) << __AT__ << "finished"; + return OK; +} + + + +/* FIXME + * do you really need this, this is called if registerDataCallback() is activated + * in your gui to get data from receiver. you probably have a different way + * of reconstructing complete data set from all receivers + */ +void UDPRESTImplementation::readFramee(char* c,char** raw, uint64_t &startAcq, uint64_t &startFrame){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + strcpy(c,""); + *raw = NULL; +} + + + + +/* FIXME + * Its called by TCP in case of illegal shut down such as Ctrl + c. + * Upto you what you want to do with it. + */ +void UDPRESTImplementation::closeFile(int ithr){ + FILE_LOG(logDEBUG) << __AT__ << "called for thread " << ithr; + FILE_LOG(logDEBUG) << __AT__ << "exited for thread " << ithr; +} + + + +#endif diff --git a/slsReceiverSoftware/src/UDPStandardImplementation.cpp b/slsReceiverSoftware/src/UDPStandardImplementation.cpp new file mode 100644 index 0000000000..6ab655ac0f --- /dev/null +++ b/slsReceiverSoftware/src/UDPStandardImplementation.cpp @@ -0,0 +1,3078 @@ +/********************************************//** + * @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 +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"; + closeFile(); + deleteMembers(); +} + + +/************************************************************************* + * Setters *************************************************************** + * They modify the local cache of configuration or detector parameters *** + *************************************************************************/ + +/***initial parameters***/ + +void UDPStandardImplementation::deleteMembers(){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + FILE_LOG(logDEBUG) << "Info: Deleting member pointers"; + shutDownUDPSockets(); + closeFile(); + //filter + deleteFilter(); + 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((myDetectorType == EIGER) || (myDetectorType == JUNGFRAU)){ + 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; + else i = SAMPLE_TIME_IN_NS/acquisitionPeriod; + //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; + + if(myDetectorType == EIGER) + fifoSize = fifoDepth * packetsPerFrame;//listens to 1 packet at a time and size depends on packetsperframe + else + fifoSize = fifoDepth; + + //reduce fifo depth if > 1 numberofJobsPerBuffer + if(fifoSize % numberofJobsPerBuffer) + fifoSize = (fifoSize/numberofJobsPerBuffer)+1; + else + fifoSize = fifoSize/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])); + } +#ifdef DEBUG5 + cprintf(BLUE,"Info: %d fifostructure popped from fifofree %p\n", i, (void*)(buffer[i])); +#endif + delete fifoFree[i]; + } + 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]; + } + if(mem0[i]) free(mem0[i]); + + //creating + fifoFree[i] = new CircularFifo(fifoSize); + fifo[i] = new CircularFifo(fifoSize); + + //allocate memory + mem0[i] = (char*)malloc((bufferSize * numberofJobsPerBuffer + HEADER_SIZE_NUM_TOT_PACKETS) * fifoSize); + 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 + HEADER_SIZE_NUM_TOT_PACKETS) * (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 + HEADER_SIZE_NUM_TOT_PACKETS); + } + } + 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::configure(map config_map){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + map::const_iterator pos; + pos = config_map.find("mode"); + if (pos != config_map.end() ){ + int b; + if(!sscanf(pos->second.c_str(), "%d", &b)){ + cout << "Warning: Could not parse mode. Assuming top mode." << endl; + b = 0; + } + bottomEnable = b!= 0; + FILE_LOG(logINFO) << "Bottom: " << stringEnable(bottomEnable); + } + +} + + +/***file parameters***/ +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 parameters***/ +void UDPStandardImplementation::setShortFrameEnable(const int i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + shortFrameEnable = i; + + if(shortFrameEnable!=-1){ + frameSize = GOTTHARD_SHORT_BUFFER_SIZE; + bufferSize = GOTTHARD_SHORT_BUFFER_SIZE; + onePacketSize = GOTTHARD_SHORT_BUFFER_SIZE; + oneDataSize = GOTTHARD_SHORT_DATABYTES; + maxPacketsPerFile = SHORT_MAX_FRAMES_PER_FILE * GOTTHARD_SHORT_PACKETS_PER_FRAME; + 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{ + frameSize = GOTTHARD_BUFFER_SIZE; + bufferSize = GOTTHARD_BUFFER_SIZE; + onePacketSize = GOTTHARD_ONE_PACKET_SIZE; + oneDataSize = GOTTHARD_ONE_DATA_SIZE; + maxPacketsPerFile = MAX_FRAMES_PER_FILE * GOTTHARD_PACKETS_PER_FRAME; + 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 i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + FrameToGuiFrequency = i; + if(setupFifoStructure() == FAIL) + return FAIL; + + FILE_LOG(logINFO) << "Frame to Gui Frequency: " << FrameToGuiFrequency; + + return OK; +} + + +int UDPStandardImplementation::setAcquisitionPeriod(const uint64_t i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + acquisitionPeriod = i; + if((myDetectorType == GOTTHARD) && (myDetectorType == MOENCH)) + if(setupFifoStructure() == FAIL) + return FAIL; + + FILE_LOG(logINFO) << "Acquisition Period: " << (double)acquisitionPeriod/(1E9) << "s"; + + return OK; +} + + +int UDPStandardImplementation::setNumberOfFrames(const uint64_t i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + numberOfFrames = i; + if((myDetectorType == GOTTHARD) && (myDetectorType == MOENCH)) + if(setupFifoStructure() == FAIL) + return FAIL; + + FILE_LOG(logINFO) << "Number of Frames:" << numberOfFrames; + + return OK; +} + +int UDPStandardImplementation::setDynamicRange(const uint32_t i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + uint32_t oldDynamicRange = dynamicRange; + + FILE_LOG(logDEBUG) << "Info: Setting Dynamic Range to " << i; + dynamicRange = i; + + if(myDetectorType == EIGER){ + + //set parameters depending on new dynamic range. + packetsPerFrame = (tengigaEnable ? EIGER_TEN_GIGA_CONSTANT : EIGER_ONE_GIGA_CONSTANT) + * dynamicRange * EIGER_MAX_PORTS; + frameSize = onePacketSize * packetsPerFrame; + maxPacketsPerFile = EIGER_MAX_FRAMES_PER_FILE * packetsPerFrame; + + updateFileHeader(); + + //new dynamic range, then restart threads and resetup fifo structure + if(oldDynamicRange != dynamicRange){ + + //gui buffer + if(latestData){delete[] latestData; latestData = NULL;} + latestData = new char[frameSize]; + + //restructure fifo + numberofJobsPerBuffer = -1; + if(setupFifoStructure() == FAIL) + return FAIL; + + } + + } + + FILE_LOG(logINFO) << "Dynamic Range: " << dynamicRange; + + return OK; +} + + + +int UDPStandardImplementation::setTenGigaEnable(const bool b){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + FILE_LOG(logDEBUG) << "Info: Setting Ten Giga to " << stringEnable(b); + bool oldTenGigaEnable = tengigaEnable; + tengigaEnable = b; + + if(myDetectorType == EIGER){ + + //set parameters depending on 10g + if(tengigaEnable){ + packetsPerFrame = EIGER_TEN_GIGA_CONSTANT * dynamicRange * EIGER_MAX_PORTS; + onePacketSize = EIGER_TEN_GIGA_ONE_PACKET_SIZE; + oneDataSize = EIGER_TEN_GIGA_ONE_DATA_SIZE; + }else{ + packetsPerFrame = EIGER_ONE_GIGA_CONSTANT * dynamicRange * EIGER_MAX_PORTS; + onePacketSize = EIGER_ONE_GIGA_ONE_PACKET_SIZE; + oneDataSize = EIGER_ONE_GIGA_ONE_DATA_SIZE; + } + frameSize = onePacketSize * packetsPerFrame; + bufferSize = onePacketSize; + maxPacketsPerFile = EIGER_MAX_FRAMES_PER_FILE * packetsPerFrame; + footerOffset = EIGER_PACKET_HEADER_SIZE + oneDataSize; + FILE_LOG(logDEBUG) << dec << + "packetsPerFrame:" << packetsPerFrame << + "\nonePacketSize:" << onePacketSize << + "\noneDataSize:" << oneDataSize << + "\nframesize:" << frameSize << + "\nbufferSize:" << bufferSize << + "\nmaxPacketsPerFile:" << maxPacketsPerFile; + + + updateFileHeader(); + + //new enable, then restart threads and resetup fifo structure + if(oldTenGigaEnable != tengigaEnable){ + + //gui buffer + if(latestData){delete[] latestData; latestData = NULL;} + latestData = new char[frameSize]; + + //restructure fifo + if(setupFifoStructure() == FAIL) + return FAIL; + + } + + } + + FILE_LOG(logINFO) << "Ten Giga: " << stringEnable(tengigaEnable); + + return OK; +} + + +int UDPStandardImplementation::setFifoDepth(const uint32_t i){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + if(i != fifoDepth){ + FILE_LOG(logINFO) << "Fifo Depth: " << i << endl; + fifoDepth = i; + return setupFifoStructure(); + } + return OK; +} + + + + +/************************************************************************* + * Behavioral functions*************************************************** + * They may modify the status of the receiver **************************** + *************************************************************************/ + + +/***initial functions***/ +int UDPStandardImplementation::setDetectorType(const detectorType d){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + FILE_LOG(logDEBUG) << "Setting receiver type"; + + deleteMembers(); + initializeBaseMembers(); + initializeMembers(); + + myDetectorType = d; + switch(myDetectorType){ + case GOTTHARD: + case PROPIX: + case MOENCH: + case EIGER: + case JUNGFRAUCTB: + case JUNGFRAU: + FILE_LOG(logINFO) << " ***** " << getDetectorType(d) << " Receiver *****"; + break; + default: + FILE_LOG(logERROR) << "This is an unknown receiver type " << (int)d; + return FAIL; + } + + //set detector specific variables + switch(myDetectorType){ + case GOTTHARD: + packetsPerFrame = GOTTHARD_PACKETS_PER_FRAME; + onePacketSize = GOTTHARD_ONE_PACKET_SIZE; + oneDataSize = GOTTHARD_ONE_DATA_SIZE; + frameSize = GOTTHARD_BUFFER_SIZE; + bufferSize = GOTTHARD_BUFFER_SIZE; + frameIndexMask = GOTTHARD_FRAME_INDEX_MASK; + frameIndexOffset = GOTTHARD_FRAME_INDEX_OFFSET; + packetIndexMask = GOTTHARD_PACKET_INDEX_MASK; + maxPacketsPerFile = MAX_FRAMES_PER_FILE * GOTTHARD_PACKETS_PER_FRAME; + fifoSize = GOTTHARD_FIFO_SIZE; + fifoDepth = GOTTHARD_FIFO_SIZE; + //footerOffset = Not applicable; + break; + case PROPIX: + packetsPerFrame = PROPIX_PACKETS_PER_FRAME; + onePacketSize = PROPIX_ONE_PACKET_SIZE; + //oneDataSize = Not applicable; + frameSize = PROPIX_BUFFER_SIZE; + bufferSize = PROPIX_BUFFER_SIZE; + frameIndexMask = PROPIX_FRAME_INDEX_MASK; + frameIndexOffset = PROPIX_FRAME_INDEX_OFFSET; + packetIndexMask = PROPIX_PACKET_INDEX_MASK; + maxPacketsPerFile = MAX_FRAMES_PER_FILE * PROPIX_PACKETS_PER_FRAME; + fifoSize = PROPIX_FIFO_SIZE; + fifoDepth = PROPIX_FIFO_SIZE; + //footerOffset = Not applicable; + break; + case MOENCH: + packetsPerFrame = MOENCH_PACKETS_PER_FRAME; + onePacketSize = MOENCH_ONE_PACKET_SIZE; + oneDataSize = MOENCH_ONE_DATA_SIZE; + frameSize = MOENCH_BUFFER_SIZE; + bufferSize = MOENCH_BUFFER_SIZE; + frameIndexMask = MOENCH_FRAME_INDEX_MASK; + frameIndexOffset = MOENCH_FRAME_INDEX_OFFSET; + packetIndexMask = MOENCH_PACKET_INDEX_MASK; + maxPacketsPerFile = MOENCH_MAX_FRAMES_PER_FILE * MOENCH_PACKETS_PER_FRAME; + fifoSize = MOENCH_FIFO_SIZE; + fifoDepth = MOENCH_FIFO_SIZE; + //footerOffset = Not applicable; + break; + case EIGER: + //assuming 1G in the beginning + packetsPerFrame = EIGER_ONE_GIGA_CONSTANT * dynamicRange * EIGER_MAX_PORTS; + onePacketSize = EIGER_ONE_GIGA_ONE_PACKET_SIZE; + oneDataSize = EIGER_ONE_GIGA_ONE_DATA_SIZE; + frameSize = onePacketSize * packetsPerFrame; + bufferSize = onePacketSize; + frameIndexMask = EIGER_FRAME_INDEX_MASK; + frameIndexOffset = EIGER_FRAME_INDEX_OFFSET; + packetIndexMask = EIGER_PACKET_INDEX_MASK; + maxPacketsPerFile = EIGER_MAX_FRAMES_PER_FILE * packetsPerFrame; + fifoSize = EIGER_FIFO_SIZE; + fifoDepth = EIGER_FIFO_SIZE; + footerOffset = EIGER_PACKET_HEADER_SIZE + oneDataSize; + break; + case JUNGFRAUCTB: + packetsPerFrame = JCTB_PACKETS_PER_FRAME; + onePacketSize = JCTB_ONE_PACKET_SIZE; + //oneDataSize = Not applicable; + frameSize = JCTB_BUFFER_SIZE; + bufferSize = JCTB_BUFFER_SIZE; + frameIndexMask = JCTB_FRAME_INDEX_MASK; + frameIndexOffset = JCTB_FRAME_INDEX_OFFSET; + packetIndexMask = JCTB_PACKET_INDEX_MASK; + maxPacketsPerFile = JFCTB_MAX_FRAMES_PER_FILE * JCTB_PACKETS_PER_FRAME; + fifoSize = JCTB_FIFO_SIZE; + fifoDepth = JCTB_FIFO_SIZE; + //footerOffset = Not applicable; + break; + case JUNGFRAU: + packetsPerFrame = JFRAU_PACKETS_PER_FRAME; + onePacketSize = JFRAU_ONE_PACKET_SIZE; + oneDataSize = JFRAU_DATA_BYTES; + frameSize = JFRAU_BUFFER_SIZE; + bufferSize = JFRAU_BUFFER_SIZE; + frameIndexMask = JFRAU_FRAME_INDEX_MASK; + frameIndexOffset = JFRAU_FRAME_INDEX_OFFSET; + packetIndexMask = JFRAU_PACKET_INDEX_MASK; + maxPacketsPerFile = JFRAU_MAX_FRAMES_PER_FILE * JFRAU_PACKETS_PER_FRAME; + fifoDepth = JFRAU_FIFO_SIZE; + fifoSize = JFRAU_FIFO_SIZE; + //footerOffset = Not applicable; + break; + default: + FILE_LOG(logERROR) << "This is an unknown receiver type " << (int)d; + return FAIL; + } + + //delete threads and set number of listening threads + if(myDetectorType == EIGER){ + pthread_mutex_lock(&statusMutex); + listeningThreadsMask = 0x0; + pthread_mutex_unlock(&(statusMutex)); + if(threadStarted) + createListeningThreads(true); + numberofListeningThreads = MAX_NUMBER_OF_LISTENING_THREADS; + } + + //set up fifo structure -1 for numberofJobsPerBuffer ensure it is done + numberofJobsPerBuffer = -1; + setupFifoStructure(); + + //allocate for latest data (frame copy for gui) + latestData = new char[frameSize]; + + //updates File Header + if(myDetectorType == EIGER) + updateFileHeader(); + + FILE_LOG(logDEBUG) << " Detector type set to " << getDetectorType(d); + + return OK; +} + + +/***acquisition functions***/ +void UDPStandardImplementation::resetAcquisitionCount(){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + totalPacketsCaught = 0; + acqStarted = false; + startAcquisitionIndex = 0; + + FILE_LOG(logINFO) << "Acquisition Count has been reset"; +} + + +int UDPStandardImplementation::startReceiver(char *c){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + FILE_LOG(logINFO) << "Stopping Receiver"; + + + //RESET + //reset measurement variables + measurementStarted = false; + startFrameIndex = 0; + frameIndex = 0; + if(!acqStarted){ + currentFrameNumber = 0; //has to be zero to add to startframeindex for each scan + acquisitionIndex = 0; + frameIndex = 0; + } + for(int i = 0; i < numberofListeningThreads; ++i) + totalListeningFrameCount[i] = 0; + packetsCaught = 0; + numMissingPackets = 0; + numTotMissingPackets = 0; + numTotMissingPacketsInFile = 0; + //reset file parameters + packetsInFile = 0; + if(sfilefd){ + fclose(sfilefd); + sfilefd = NULL; + } + //reset gui variables + guiData = NULL; + guiDataReady=0; + strcpy(guiFileName,""); + //reset masks + pthread_mutex_lock(&statusMutex); + writerThreadsMask = 0x0; + createFileMask = 0x0; + fileCreateSuccess = false; + pthread_mutex_unlock(&statusMutex); + + + //Print Receiver Configuration + if(myDetectorType != EIGER){ + FILE_LOG(logINFO) << "Data Compression has been " << stringEnable(dataCompressionEnable); + FILE_LOG(logINFO) << "Number of Jobs Per Buffer: " << numberofJobsPerBuffer; + FILE_LOG(logINFO) << "Max Packets Per File:" << maxPacketsPerFile; + } + if(FrameToGuiFrequency) + FILE_LOG(logINFO) << "Frequency of frames sent to gui: " << FrameToGuiFrequency; + else + FILE_LOG(logINFO) << "Frequency of frames sent to gui: Random"; + + + + //create UDP sockets + if(createUDPSockets() == FAIL){ + strcpy(c,"Could not create UDP Socket(s)."); + FILE_LOG(logERROR) << c; + return FAIL; + } + + if(setupWriter() == FAIL){ + //stop udp socket + shutDownUDPSockets(); + sprintf(c,"Could not create file %s.",completeFileName); + //FILE_LOG(logERROR) << c; + for(int i=0; i < numberofWriterThreads; i++) sem_post(&writerSemaphore[i]); + return FAIL; + } + + + //For compression, just for gui purposes + if(dataCompressionEnable) + sprintf(completeFileName, "%s/%s_fxxx_%lld_xx.root", filePath,fileName,(long long int)fileIndex); + + //initialize semaphore to synchronize between writer and gui reader threads + sem_init(&writerGuiSemaphore,1,0); + + //status and thread masks + pthread_mutex_lock(&statusMutex); + status = RUNNING; + for(int i=0;iShutDownSocket(); + FILE_LOG(logINFO) << "Shut down UDP Socket " << i; + delete udpSocket[i]; + udpSocket[i] = NULL; + } + } + 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){ + + //check if all packets got + int totalP = 0,prev,i; + for(i=0; iGetCurrentFile(); + + if(myFile[i]->Write()) + //->Write(tall->GetName(),TObject::kOverwrite); + cout << "Thread " << i <<": wrote frames to file" << endl; + else + cout << "Thread " << i << ": could not write frames to file" << endl; + + }else + cout << "Thread " << i << ": could not write frames to file: No file or No Tree" << endl; + //close file + if(myTree[i] && myFile[i]) + myFile[i] = myTree[i]->GetCurrentFile(); + if(myFile[i] != NULL) + myFile[i]->Close(); + myFile[i] = NULL; + myTree[i] = NULL; + pthread_mutex_unlock(&writeMutex); + +#endif + } +} + + + + +/************************************************************************* + * Listening and Writing Threads ***************************************** + *************************************************************************/ + + +int UDPStandardImplementation::createListeningThreads(bool destroy){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + //reset masks + killAllListeningThreads = false; + pthread_mutex_lock(&statusMutex); + listeningThreadsMask = 0x0; + pthread_mutex_unlock(&(statusMutex)); + + //destroy + if(destroy){ + FILE_LOG(logDEBUG) << "Info: Destroying Listening Thread(s)"; + + killAllListeningThreads = true; + for(int i = 0; i < numberofListeningThreads; ++i){ + sem_post(&listenSemaphore[i]); + pthread_join(listeningThreads[i],NULL); + FILE_LOG(logDEBUG) << "." << flush; + } + killAllListeningThreads = false; + threadStarted = false; + FILE_LOG(logDEBUG) << "Info: Listening thread(s) destroyed"; + } + + //create + else{ + FILE_LOG(logDEBUG) << "Info: Creating Listening Thread(s)"; + + //reset current index + currentThreadIndex = -1; + + for(int i = 0; i < numberofListeningThreads; ++i){ + sem_init(&listenSemaphore[i],1,0); + threadStarted = false; + currentThreadIndex = i; + if(pthread_create(&listeningThreads[i], NULL,startListeningThread, (void*) this)){ + FILE_LOG(logERROR) << "Could not create listening thread with index " << i; + return FAIL; + } + while(!threadStarted); + FILE_LOG(logDEBUG) << "." << flush; + } + FILE_LOG(logDEBUG) << "Info: Listening thread(s) created successfully."; + } + + return OK; +} + + + +int UDPStandardImplementation::createWriterThreads(bool destroy){ + FILE_LOG(logDEBUG) << __AT__ << " starting"; + + //reset masks + killAllWritingThreads = false; + pthread_mutex_lock(&statusMutex); + writerThreadsMask = 0x0; + createFileMask = 0x0; + pthread_mutex_unlock(&(statusMutex)); + + //destroy threads + if(destroy){ + FILE_LOG(logDEBUG) << "Info: Destroying Writer Thread(s)"; + + killAllWritingThreads = true; + for(int i = 0; i < numberofWriterThreads; ++i){ + sem_post(&writerSemaphore[i]); + pthread_join(writingThreads[i],NULL); + FILE_LOG(logDEBUG) <<"."<getErrorStatus(); + 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,fileName,(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){ + + //close file pointers + if(sfilefd){ + fclose(sfilefd); + sfilefd = NULL; + } + + //create file + if(!overwriteEnable){ + if (NULL == (sfilefd = fopen((const char *) (completeFileName), "wx"))){ + FILE_LOG(logERROR) << "Could not create/overwrite file" << completeFileName; + return FAIL; + } + }else if (NULL == (sfilefd = fopen((const char *) (completeFileName), "w"))){ + FILE_LOG(logERROR) << "Could not create file" << completeFileName; + return FAIL; + } + //setting file buffer size to 16mb + setvbuf(sfilefd,NULL,_IOFBF,BUF_SIZE); + + //Print packet loss and filenames + if(!packetsCaught){ + previousFrameNumber = -1; + cout << "File: " << completeFileName << endl; + }else{ + if (previousFrameNumber == -1) + previousFrameNumber = startFrameIndex-1; + + cout << completeFileName + << "\tPacket Loss: " << setw(4)<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::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::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; + + + //variable definitions + int listenSize = 0; //listen to only 1 packet + uint32_t rc; //size of buffer received in bytes + //split frames + int carryonBufferSize; //from previous buffer to keep frames together in a buffer + char* tempBuffer = NULL; //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){ + + //reset parameters before acquisition + carryonBufferSize = 0; + if(myDetectorType != EIGER){ + listenSize = bufferSize * numberofJobsPerBuffer; //listen to more than 1 packet + if(tempBuffer!=NULL){delete []tempBuffer;tempBuffer=NULL;} + tempBuffer = new char[onePacketSize * (packetsPerFrame - 1)]; //store maximum of 1 packets less in a frame + } + + /* inner loop - loop for each buffer */ + //until mask unset (udp sockets shut down by client) + while((1 << ithread) & listeningThreadsMask){ + + + //pop from fifo + fifoFree[ithread]->pop(buffer[ithread]); + +#ifdef EVERYFIFODEBUG + if(fifoFree[ithread]->getSemValue()<100) + cprintf(BLUE,"FifoFree[%d]: value:%d, pop 0x%x\n",ithread,fifoFree[ithread]->getSemValue(),(void*)(buffer[ithread])); +#endif +#ifdef CFIFODEBUG + if(ithread == 0) + cprintf(CYAN,"Listening_Thread %d :Listener popped from fifofree %p\n", ithread, (void*)(buffer[ithread])); + else + cprintf(YELLOW,"Listening_Thread %d :Listener popped from fifofree %p\n", ithread, (void*)(buffer[ithread])); +#endif + + //udpsocket doesnt exist + if(udpSocket[ithread] == NULL){ + FILE_LOG(logERROR) << "Listening_Thread " << ithread << ": UDP Socket not created or shut down earlier"; + stopListening(ithread,0); + continue; + } + + rc = prepareAndListenBuffer(ithread, listenSize, carryonBufferSize, tempBuffer); + + //start indices for each start of scan/acquisition + if((!measurementStarted) && (rc > 0)){ + pthread_mutex_lock(&progressMutex); + if(!measurementStarted) + startFrameIndices(ithread); + pthread_mutex_unlock(&progressMutex); + } + + + //problem in receiving or end of acquisition + if (status == TRANSMITTING){ + stopListening(ithread,rc); + continue; + } + //write packet count to buffer + if(myDetectorType == EIGER) + (*((uint32_t*)(buffer[ithread]))) = 1; + //handling split frames and writing packet Count to buffer + else + (*((uint32_t*)(buffer[ithread]))) = processListeningBuffer(ithread, carryonBufferSize, tempBuffer); + + + //push buffer to FIFO + while(!fifo[ithread]->push(buffer[ithread])); + +#ifdef EVERYFIFODEBUG + if(fifo[ithread]->getSemValue()>(fifoSize-100)) + cprintf(MAGENTA,"Fifo[%d]: value:%d, push 0x%x\n",ithread,fifo[ithread]->getSemValue(),(void*)(buffer[ithread])); +#endif +#ifdef CFIFODEBUG + if(ithread == 0) + cprintf(CYAN,"Listening_Thread %d: Listener pushed into fifo %p\n",ithread, (void*)(buffer[ithread])); + else + cprintf(YELLOW,"Listening_Thread %d: Listener pushed into fifo %p\n",ithread, (void*)(buffer[ithread])); + +#endif + + + }/*--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 lSize, int cSize, char* temp){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //listen to UDP packets + if(cSize) + memcpy(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS, temp, cSize); + + int receivedSize = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS + cSize, lSize + cSize); + + //throw away packets that is not one packet size, need to check status if socket is shut down + while(status != TRANSMITTING && myDetectorType == EIGER && receivedSize != onePacketSize) { + if(receivedSize != EIGER_HEADER_LENGTH){ + cprintf(RED,"Listening_Thread %d: Listened to a weird packet size %d\n",ithread, receivedSize); + } +#ifdef DEBUG + else + cprintf(BLUE,"Listening_Thread %d: Listened to a header packet\n",ithread); +#endif + receivedSize = udpSocket[ithread]->ReceiveDataOnly(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS); + } + totalListeningFrameCount[ithread] += (receivedSize/onePacketSize); + +#ifdef MANUALDEBUG + if(receivedSize>0){ + if(myDetectorType == JUNGFRAU){ + jfrau_packet_header_t* header; + + for(int iloop=0;iloop<2;iloop++){ + header = (jfrau_packet_header_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS + iloop * (JFRAU_HEADER_LENGTH+JFRAU_ONE_DATA_SIZE)); + cprintf(RED,"[%d]: packetnumber:%x\n",iloop, (*( (uint8_t*) header->packetNumber))); + cprintf(RED," : framenumber :%x\n", (*( (uint32_t*) header->frameNumber))&0xffffff); + } + }else if(myDetectorType == EIGER){ + eiger_packet_header_t* header = (eiger_packet_header_t*) (buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS); + eiger_packet_footer_t* footer = (eiger_packet_footer_t*)(buffer[ithread] + footerOffset + HEADER_SIZE_NUM_TOT_PACKETS); + cprintf(GREEN,"thread:%d footeroffset:%dsubframenum:%d oldpacketnum:%d new pnum:%d new fnum:%d\n", + ithread,footerOffset, + (*( (unsigned int*) header->subFrameNumber)), + (*( (uint8_t*) header->dynamicRange)), + (*( (uint16_t*) footer->packetNumber)), + (uint32_t)(*( (uint64_t*) footer))); + } + } +#endif + + +#ifdef DEBUG + cprintf(BLUE, "Listening_Thread %d : Received bytes: %d. Expected bytes: %d\n", ithread, receivedSize, bufferSize * numberofJobsPerBuffer-cSize); +#endif + return receivedSize; +} + + + + + + +void UDPStandardImplementation::startFrameIndices(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //determine startFrameIndex + jfrau_packet_header_t* header=0; + switch(myDetectorType){ + case EIGER: + startFrameIndex = 0; //frame number always resets + break; + case JUNGFRAU: + header = (jfrau_packet_header_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS); + startFrameIndex = (*( (uint32_t*) header->frameNumber))&0xffffff; + break; + default: + if(shortFrameEnable < 0){ + startFrameIndex = (((((uint32_t)(*((uint32_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS))))+1) + & (frameIndexMask)) >> frameIndexOffset); + }else{ + startFrameIndex = ((((uint32_t)(*((uint32_t*)(buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS)))) + & (frameIndexMask)) >> frameIndexOffset); + } + break; + } + + //start of entire acquisition + if(!acqStarted){ + startAcquisitionIndex = startFrameIndex; + acqStarted = true; + 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 = 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 + + //less than 1 packet size (especially for eiger), ignore the buffer (so that 2 dummy buffers are not sent with pc=0) + if(numbytes < onePacketSize) + numbytes = 0; + + + //free empty buffer + if(numbytes <= 0){ + FILE_LOG(logINFO) << "Listening "<< ithread << ": End of Acquisition"; + while(!fifoFree[ithread]->push(buffer[ithread])); +#ifdef EVERYFIFODEBUG + if(fifoFree[ithread]->getSemValue()<100) + cprintf(GREEN,"Fifofree[%d]: value:%d, push 0x%x\n",ithread,fifoFree[ithread]->getSemValue(),(void*)(buffer[ithread])); +#endif +#ifdef CFIFODEBUG + if(ithread == 0) + cprintf(CYAN,"Listening_Thread %d :Listener push empty buffer into fifofree %p\n", ithread, (void*)(buffer[ithread])); + else + cprintf(YELLOW,"Listening_Thread %d :Listener push empty buffer into fifofree %p\n", ithread, (void*)(buffer[ithread])); +#endif + } + + + //push last non empty buffer into fifo + else{ + (*((uint32_t*)(buffer[ithread]))) = numbytes/onePacketSize; + totalListeningFrameCount[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, numbytes/onePacketSize); +#endif + while(!fifo[ithread]->push(buffer[ithread])); +#ifdef EVERYFIFODEBUG + if(fifo[ithread]->getSemValue()>(fifoSize-100)) + cprintf(MAGENTA,"Fifo[%d]: value:%d, push 0x%x\n",ithread,fifo[ithread]->getSemValue(),(void*)(buffer[ithread])); +#endif +#ifdef CFIFODEBUG + if(ithread == 0) + cprintf(CYAN,"Listening_Thread %d: Listener Last Buffer pushed into fifo %p\n", ithread,(void*)(buffer[ithread])); + else + cprintf(YELLOW,"Listening_Thread %d: Listener Last Buffer pushed into fifo %p\n", ithread,(void*)(buffer[ithread])); +#endif + } + + //push dummy-end buffer into fifo for all writer threads + for(int i=0; ipop(buffer[ithread]); +#ifdef EVERYFIFODEBUG + if(fifoFree[ithread]->getSemValue()<100) + cprintf(BLUE,"FifoFree[%d]: value:%d, pop 0x%x\n",ithread,fifoFree[ithread]->getSemValue(),(void*)(buffer[ithread])); +#endif +#ifdef CFIFODEBUG + if(ithread == 0) + cprintf(CYAN,"Listening_Thread %d: Popped Dummy from fifoFree %p\n", ithread,(void*)(buffer[ithread])); + else + cprintf(YELLOW,"Listening_Thread %d: Popped Dummy from fifoFree %p\n", ithread,(void*)(buffer[ithread])); +#endif + //creating dummy-end buffer with pc=0xFFFF + (*((uint32_t*)(buffer[ithread]))) = dummyPacketValue; + while(!fifo[ithread]->push(buffer[ithread])); +#ifdef EVERYFIFODEBUG + if(fifo[ithread]->getSemValue()>(fifoSize-100)) + cprintf(MAGENTA,"Fifo[%d]: value:%d, push 0x%x\n",ithread,fifo[ithread]->getSemValue(),(void*)(buffer[ithread])); +#endif +#ifdef CFIFODEBUG + if(ithread == 0) + cprintf(CYAN,"Listening_Thread %d: Listener pushed dummy-end buffer into fifo %p\n", ithread,(void*)(buffer[ithread])); + else + cprintf(YELLOW,"Listening_Thread %d: Listener pushed dummy-end buffer into fifo %p\n", ithread,(void*)(buffer[ithread])); +#endif + } + + + //reset mask and exit loop + pthread_mutex_lock(&statusMutex); + listeningThreadsMask^=(1< 1) + cprintf(BLUE,"Listening_Thread %d: Waiting for other listening threads to be done.. current mask:0x%x\n", ithread, listeningThreadsMask); +#endif + while(listeningThreadsMask) + usleep(5000); +#ifdef DEBUG4 + int t=0; + for(i=0;i> frameIndexOffset)); +#endif + cSize = onePacketSize; + --packetCount; + } + } +#ifdef DEBUG4 + cprintf(BLUE, "Listening_Thread %d: First Header:%d\n", (((((uint32_t)(*((uint32_t*)(buffer[ithread] + HEADER_SIZE_NUM_TOT_PACKETS))))+1) + & (frameIndexMask)) >> frameIndexOffset)); +#endif + break; + + case MOENCH: + lastPacketOffset = (((numberofJobsPerBuffer * packetsPerFrame - 1) * onePacketSize) + HEADER_SIZE_NUM_TOT_PACKETS); +#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]+HEADER_SIZE_NUM_TOT_PACKETS))))) & (frameIndexMask)) >> frameIndexOffset), + ((((uint32_t)(*((uint32_t*)(buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS))))) & (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; + + + case JUNGFRAU: + lastPacketOffset = (((numberofJobsPerBuffer * packetsPerFrame - 1) * onePacketSize) + HEADER_SIZE_NUM_TOT_PACKETS); +#ifdef DEBUG4 + header = (jfrau_packet_header_t*) (buffer[ithread]+HEADER_SIZE_NUM_TOT_PACKETS); + cprintf(BLUE, "Listening_Thread: First Header:%d\t First Packet:%d\n", + (*( (uint32_t*) header->frameNumber))&0xffffff, + (*( (uint8_t*) header->packetNumber))); +#endif + header = (jfrau_packet_header_t*) (buffer[ithread]+lastPacketOffset); +#ifdef DEBUG4 + cprintf(BLUE, "Listening_Thread: Last Header:%du\t Last Packet:%d\n", + (*( (uint32_t*) header->frameNumber))&0xffffff, + (*( (uint8_t*) header->packetNumber))); +#endif + //jungfrau last packet value is 0, so find the last packet and store the others in a temp storage + if((*( (uint8_t*) header->packetNumber))){ + //cprintf(RED,"entering missing packet zone\n"); + lastFrameHeader64 = (*( (uint32_t*) header->frameNumber))&0xffffff; + cSize += onePacketSize; + lastPacketOffset -= onePacketSize; + --packetCount; + while (lastFrameHeader64 == ((*( (uint32_t*) header->frameNumber))&0xffffff)){ + cSize += onePacketSize; + lastPacketOffset -= onePacketSize; + header = (jfrau_packet_header_t*) (buffer[ithread]+lastPacketOffset); +#ifdef DEBUG4 + cprintf(RED,"new header:%d new packet:%d\n", + (*( (uint32_t*) header->frameNumber))&0xffffff, + (*( (uint8_t*) header->packetNumber))); +#endif + --packetCount; + } + memcpy(temp, buffer[ithread]+(lastPacketOffset+onePacketSize), cSize); + } + + 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"; + + //set current thread value index + int ithread = currentThreadIndex; + //let calling function know thread started and obtained current + threadStarted = 1; + + switch(myDetectorType){ + case EIGER: + processWritingBufferPacketByPacket(ithread); + break; + default: + processWritingBuffer(ithread); + break; + } + +} + + + +void UDPStandardImplementation::processWritingBuffer(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //variable definitions + char* wbuf[numberofListeningThreads]; //buffer popped from FIFO + sfilefd = NULL; //file pointer + uint64_t nf; //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 + nf = 0; + guiData = latestData; //so that the first frame is always copied + + + /* inner loop - loop for each buffer */ + //until mask unset (udp sockets shut down by client) + while((1 << ithread) & writerThreadsMask){ + //pop + fifo[0]->pop(wbuf[0]); +#ifdef EVERYFIFODEBUG + if(fifo[0]->getSemValue()>(fifoSize-100)) + cprintf(CYAN,"Fifo[%d]: value:%d, pop 0x%x\n",0,fifo[0]->getSemValue(),(void*)(wbuf[0])); +#endif +#ifdef DEBUG5 + cprintf(GREEN,"Writing_Thread %d: Popped %p from FIFO %d\n", ithread, (void*)(wbuf[0]),0); +#endif + uint32_t numPackets = (uint32_t)(*((uint32_t*)wbuf[0])); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread %d: Number of Packets: %d for FIFO %d\n", ithread, numPackets, 0); +#endif + + + //end of acquisition + if(numPackets == dummyPacketValue){ +#ifdef DEBUG3 + cprintf(GREEN,"Writing_Thread %d: Dummy frame popped out of FIFO %d",ithread, 0); +#endif + stopWriting(ithread,wbuf); + continue; + } + + + + //process + if(!dataCompressionEnable) + handleWithoutDataCompression(ithread, wbuf, numPackets); + 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::processWritingBufferPacketByPacket(int ithread){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + //variable definitions + char* packetBuffer[numberofListeningThreads]; //buffer popped from FIFO + sfilefd = NULL; //file pointer + bool popReady[numberofListeningThreads]; //if the FIFO can be popped + uint32_t numPackets[numberofListeningThreads]; //number of packets popped from the FIFO + + int MAX_NUM_PACKETS = 1024; //highest 32 bit has 1024 number of packets + uint32_t LAST_PACKET_VALUE; //last packet number + + CircularFifo* fifoTempFree[numberofListeningThreads];//ciruclar fifo to keep track of one frame packets to be freed and reused later + char* temp = NULL; + + char* frameBuffer[MAX_NUM_PACKETS]; //buffer offset created for a whole frame + int frameBufferoffset[numberofListeningThreads]; //buffer offset created for a whole frame for both listening threads + char* blankframe[MAX_NUM_PACKETS]; //blank buffer for a whole frame with missing packets + int blankoffset; //blank buffer offset + + bool fullframe[numberofListeningThreads]; //if full frame processed for each listening thread + volatile uint32_t threadFrameNumber[numberofListeningThreads]; //thread frame number for each listening thread buffer popped out + volatile uint32_t presentFrameNumber; //the current frame number aiming to be built + volatile uint32_t lastPacketNumber[numberofListeningThreads]; //last packet number got + volatile uint32_t currentPacketNumber[numberofListeningThreads];//current packet number + volatile int numberofMissingPackets[numberofListeningThreads]; // number of missing packets in this buffer + + for(int i=0; iisEmpty()){ + fifoTempFree[i]->pop(temp); +#ifdef EVERYFIFODEBUG + if(fifoTempFree[i]->getSemValue()>((packetsPerFrame/numberofListeningThreads)-3)) + cprintf(RED,"FifoTempFree[%d]: value:%d, pop 0x%x\n",i,fifoTempFree[i]->getSemValue(),(void*)(temp)); +#endif + } + delete fifoTempFree[i]; + } + fifoTempFree[i] = new CircularFifo(MAX_NUM_PACKETS); + } + + for(uint32_t i=0; imissingPacket) = missingPacketValue; + *( (uint16_t*) blankframe_footer->packetNumber) = i+1; + + //set each value inside blank frame to 0xff + for(int j=0;j<(oneDataSize);++j){ + unsigned char* blankframe_data = (unsigned char*)blankframe[i] + sizeof(eiger_packet_header_t) + j; + *(blankframe_data) = 0xFF; + } + } + //last frame read out + lastFrameIndex = -1; + + + + + /* inner loop - loop for each buffer */ + //until mask unset (udp sockets shut down by client) + while((1 << ithread) & writerThreadsMask){ + + + //pop fifo and if end of acquisition + //cprintf(BLUE,"popready[0]:%d popready[1]:%d\n",popReady[0],popReady[1]); + if(popAndCheckEndofAcquisition(ithread, packetBuffer, popReady, numPackets,fifoTempFree)){ +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread All dummy-end buffers popped\n"); +#endif + //finish missing packets + if(((frameBufferoffset[0]!=0) || (frameBufferoffset[1]!=((int)packetsPerFrame/numberofListeningThreads)))); + else{ + stopWriting(ithread,packetBuffer); + continue; + } + } +#ifdef DEBUG4 + else{cprintf(BLUE,"POPped but i see?\n");} +#endif + + //get a full frame------------------------------------------------------------------------------------------------------- + for(int i=0;ipacketNumber); +#ifdef DEBUG4 + cprintf(MAGENTA,"Fifo %d: threadframenumber original:%d currentpacketnumber real:%d\n", + i,threadFrameNumber[i],currentPacketNumber[i]); +#endif + } + + //calculate number of missing packets----------------------------------------------------- + numberofMissingPackets[i] = 0; + if((numPackets[i] == dummyPacketValue) || (threadFrameNumber[i] != presentFrameNumber)) + numberofMissingPackets[i] = (LAST_PACKET_VALUE - lastPacketNumber[i]); + else + numberofMissingPackets[i] = (currentPacketNumber[i] - lastPacketNumber[i] - 1); + numMissingPackets += numberofMissingPackets[i]; + +#ifdef DEBUG4 + if(numPackets[i] == dummyPacketValue) + cprintf(GREEN, "Fifo %d: Calc missing packets (Dummy): Adding missing packets %d to the last frame\n", + i, numberofMissingPackets[i]); + else{ + cprintf(GREEN,"Fifo %d: Calc missing packets: fnum %d, fnum_thread %d, " + "pnum %d, last_pnum %d, pnum_offset %d missing_packets %d\n", + i,presentFrameNumber,threadFrameNumber[i], + currentPacketNumber[i],lastPacketNumber[i],frameBufferoffset[i],numberofMissingPackets[i]); + } +#endif + + + //add missing packets--------------------------------------------------------------------- + for(int j=0;jmissingPacket)!= missingPacketValue){ + eiger_packet_header_t* blankframe_header = (eiger_packet_header_t*) blankframe[blankoffset]; + cprintf(BG_RED, "Fifo %d: Add Missing Packet Error: " + "pnum_offset %d, pnum %d, fnum_thread %d, missingpacket_buffer 0x%x, missingpacket_blank 0x%x\n", + i,frameBufferoffset[i],currentPacketNumber[i],threadFrameNumber[i], + *( (uint16_t*) frameBuffer_header->missingPacket), + *( (uint16_t*) blankframe_header->missingPacket)); + exit(-1); + }else{ +#ifdef DEBUG4 + cprintf(RED, "Fifo %d: Add Missing Packet success: " + "pnum_offset %d, pnum_got %d, fnum_thread %d, missingpacket_buffer 0x%x\n", + i,frameBufferoffset[i],currentPacketNumber[i],threadFrameNumber[i], + *( (uint16_t*) frameBuffer_header->missingPacket)); +#endif + frameBufferoffset[i]=frameBufferoffset[i]+1; + } + } + + //missed packets/future packet: do not pop over and determine fullframe-------------------- + popReady[i] = false; + if((numPackets[i] == dummyPacketValue) ||(threadFrameNumber[i] != presentFrameNumber)) + fullframe[i] = true; + else + fullframe[i] = false; + if(threadFrameNumber[i] != presentFrameNumber) + threadFrameNumber[i] = presentFrameNumber; + + + //add current packet-------------------------------------------------------------- + if(fullframe[i] == false){ + if(currentPacketNumber[i] != (uint32_t)(frameBufferoffset[i]-(i*packetsPerFrame/numberofListeningThreads))+1){ + cprintf(BG_RED, "Fifo %d: Correct Packet Offset Error: " + "pnum_offset %d,pnum %d fnum_thread %d\n", + i,frameBufferoffset[i],currentPacketNumber[i],threadFrameNumber[i]); + exit(-1); + } + + + while(!fifoTempFree[i]->push(packetBuffer[i])); +#ifdef EVERYFIFODEBUG + if(fifoTempFree[i]->getSemValue()>((packetsPerFrame/numberofListeningThreads)-3)) + cprintf(YELLOW,"FifoTempfree[%d]: value:%d, push 0x%x\n",i,fifoTempFree[i]->getSemValue(),(void*)(wbuffer[i])); +#endif + + + + //cprintf(RED,"Current Packet frameBufferoffset[i]:%d\n",frameBufferoffset[i]); + frameBuffer[frameBufferoffset[i]] = (packetBuffer[i] + HEADER_SIZE_NUM_TOT_PACKETS); +#ifdef DEBUG4 + eiger_packet_header_t* frameBuffer_header = (eiger_packet_header_t*) frameBuffer[frameBufferoffset[i]]; + eiger_packet_footer_t* frameBuffer_footer = (eiger_packet_footer_t*) (frameBuffer[frameBufferoffset[i]] + footerOffset); + cprintf(GREEN, "Fifo %d: Current Packet added success:" + "pnum_offset %d, pnum %d, real pnum %d fnum_thread %d, missingpacket_buffer 0x%x\n", + i,frameBufferoffset[i],currentPacketNumber[i],*( (uint16_t*) frameBuffer_footer->packetNumber),threadFrameNumber[i], + *( (uint16_t*) frameBuffer_header->missingPacket)); +#endif + frameBufferoffset[i]=frameBufferoffset[i]+1; + //update last packet + lastPacketNumber[i] = currentPacketNumber[i]; + popReady[i] = true; + fullframe[i] = false; + if(currentPacketNumber[i] == LAST_PACKET_VALUE){ +#ifdef DEBUG4 + cprintf(GREEN, "Fifo %d: Got last packet\n",i); +#endif + popReady[i] = false; + fullframe[i] = true; + } //end of last packet + }//end of add current packet + }//end of if(!fullframe) + }//end of for listening threads + + + //full frame + if(fullframe[0] && fullframe[1]){ + currentFrameNumber = presentFrameNumber; + numTotMissingPacketsInFile += numMissingPackets; + numTotMissingPackets += numMissingPackets; + +/* + cprintf(CYAN,"**framenum:%lld\n ",(long long int)currentFrameNumber); + if(currentFrameNumber>500){ + cprintf(BG_RED,"too high frame number %lld \n",(long long int)currentFrameNumber ); + exit(-1); + } + for(int i=0;ipacketNumber), (void*)(packetBuffer[i])); + }*/ +#ifdef DEBUG4 + cprintf(BLUE," nummissingpackets:%d\n",numMissingPackets); +#endif +#ifdef FNUM_DEBUG + cprintf(GREEN,"**fnum:%lld**\n",(long long int)currentFrameNumber); +#endif +#ifdef MISSINGP_DEBUG + if(numMissingPackets){ + cprintf(RED, "Total missing packets %d for fnum %d\n",numMissingPackets,currentFrameNumber); + for (int j=0;jmissingPacket)==missingPacketValue) + cprintf(RED,"Found missing packet at pnum %d\n",j); + } + } +#endif + + //write and copy to gui + handleWithoutDataCompression(ithread,frameBuffer,packetsPerFrame); + + //reset a few stuff + presentFrameNumber++; + for(int i=0; iisEmpty()){ + fifoTempFree[i]->pop(temp); +#ifdef EVERYFIFODEBUG + if(fifoTempFree[i]->getSemValue()>((packetsPerFrame/numberofListeningThreads)-3)) + cprintf(GRAY,"FifoTempFree[%d]: value:%d, pop 0x%x\n",i,fifoTempFree[i]->getSemValue(),(void*)(temp)); +#endif + while(!fifoFree[i]->push(temp)); +#ifdef EVERYFIFODEBUG + if(fifoFree[i]->getSemValue()<100) + cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",i,fifoFree[i]->getSemValue(),(void*)(temp)); +#endif +#ifdef CFIFODEBUG + if(i==0) + cprintf(CYAN,"Fifo %d: Writing_Thread freed: pushed into fifofree %p\n",i, (void*)(temp)); + else + cprintf(YELLOW,"Fifo %d: Writing_Thread freed: pushed into fifofree %p\n",i, (void*)(temp)); +#endif + } + } +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: finished freeing\n"); +#endif + + + }//end of full frame + + }/*--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(); +#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:emptied buffer in fifo\n", ithread); + fifo[ithread]->pop(temp); +#ifdef EVERYFIFODEBUG + if(fifo[ithread]->getSemValue()>(fifoSize-100)) + cprintf(CYAN,"Fifo[%d]: value:%d, pop 0x%x\n",ithread,fifo[ithread]->getSemValue(),(void*)(temp)); +#endif + } + + //create file + if((1<* fifoTempFree[]){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + bool endofAcquisition = true; + for(int i=0; ipop(wbuffer[i]); +#ifdef EVERYFIFODEBUG + if(fifo[i]->getSemValue()>(fifoSize-100)) + cprintf(CYAN,"Fifo[%d]: value:%d, pop 0x%x\n",i,fifo[i]->getSemValue(),(void*)(wbuffer[i])); +#endif +#ifdef CFIFODEBUG + if(i == 0) + cprintf(CYAN,"Writing_Thread %d: Popped %p from FIFO %d\n", ithread, (void*)(wbuffer[i]),i); + else + cprintf(YELLOW,"Writing_Thread %d: Popped %p from FIFO %d\n", ithread, (void*)(wbuffer[i]),i); +#endif + nP[i] = (uint32_t)(*((uint32_t*)wbuffer[i])); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread %d: Number of Packets: %d for FIFO %d\n", ithread, nP[i], i); +#endif + //dummy-end buffer + if(nP[i] == dummyPacketValue){ + ready[i] = false; +#ifdef DEBUG3 + cprintf(GREEN,"Writing_Thread %d: Dummy frame popped out of FIFO %d",ithread, i); +#endif + } + //normal buffer popped out + else{ + endofAcquisition = false; +#ifdef DEBUG4 + if(myDetectorType == EIGER){ + eiger_packet_footer_t* wbuf_footer = (eiger_packet_footer_t*)(wbuffer[i] + footerOffset + HEADER_SIZE_NUM_TOT_PACKETS); + //cprintf(BLUE,"footer value:0x%x\n",i,(uint64_t)(*( (uint64_t*) wbuf_footer))); + //if(*( (uint16_t*) wbuf_footer->packetNumber) == 1){ + cprintf(BLUE,"Fnum[%d]:%d\n",i,(uint32_t)(*( (uint64_t*) wbuf_footer))); + cprintf(BLUE,"Pnum[%d]:%d\n",i,*( (uint16_t*) wbuf_footer->packetNumber)); + //} + } +#endif + } + } + //when both are not popped but curretn frame number is being processed + else{ + if(nP[i] != dummyPacketValue) + endofAcquisition = false; + } + } + + return endofAcquisition; +} + + + +void UDPStandardImplementation::stopWriting(int ithread, char* wbuffer[]){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + FILE_LOG(logINFO) << "Writing "<< ithread << ": End of Acquisition"; + + //free fifo + for(int i=0; ipush(wbuffer[i])); +#ifdef EVERYFIFODEBUG + if(fifoFree[i]->getSemValue()<100) + cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",i,fifoFree[i]->getSemValue(),(void*)(wbuffer[i])); +#endif +#ifdef CFIFODEBUG + if(i==0) + cprintf(CYAN,"Writing_Thread %d: Freeing dummy-end buffer. Pushed into fifofree %p for listener %d\n", ithread,(void*)(wbuffer[i]),i); + else + cprintf(YELLOW,"Writing_Thread %d: Freeing dummy-end buffer. Pushed into fifofree %p for listener %d\n", ithread,(void*)(wbuffer[i]),i); +#endif + } + + //all threads need to close file, reset mask and exit loop + closeFile(ithread); + pthread_mutex_lock(&statusMutex); + writerThreadsMask^=(1<frameNumber))&0xffffff; + }else{ + uint64_t tempframenumber = ((uint32_t)(*((uint32_t*)(wbuffer[0] + HEADER_SIZE_NUM_TOT_PACKETS)))); + //for gotthard and normal frame, increment frame number to separate fnum and pnum + if (myDetectorType == PROPIX ||(myDetectorType == GOTTHARD && shortFrameEnable == -1)) + tempframenumber++; + //get frame number + currentFrameNumber = (tempframenumber & frameIndexMask) >> frameIndexOffset; + } + //set indices + acquisitionIndex = currentFrameNumber - startAcquisitionIndex; + frameIndex = currentFrameNumber - startFrameIndex; + } + + + + + //callback to write data + if (cbAction < DO_EVERYTHING){ + switch(myDetectorType){ + case EIGER: + for(uint32_t i=0;i 0) + writeFileWithoutCompression(wbuffer, npackets); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: Writing done\nGoing to copy frame\n"); +#endif + + + //copy frame for gui + if(npackets >= packetsPerFrame) + copyFrameToGui(wbuffer); +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: Copied frame\n"); +#endif + + + //free fifo addresses (eiger frees for each packet later) + if(myDetectorType != EIGER){ + while(!fifoFree[0]->push(wbuffer[0])); +#ifdef EVERYFIFODEBUG + if(fifoFree[0]->getSemValue()<100) + cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",0,fifoFree[0]->getSemValue(),(void*)(wbuffer[0])); +#endif +#ifdef DEBUG5 + cprintf(GREEN,"Writing_Thread %d: Freed buffer, pushed into fifofree %p for listener 0\n",ithread, (void*)(wbuffer[0])); +#endif + } +} + + + + +void UDPStandardImplementation::writeFileWithoutCompression(char* wbuffer[],uint32_t numpackets){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + + //create headers for eiger +#ifdef WRITE_HEADERS + if (myDetectorType == EIGER && cbAction == DO_EVERYTHING) + createHeaders(wbuffer); +#endif + + //if write enabled + if((fileWriteEnable) && (sfilefd)){ + int offset = HEADER_SIZE_NUM_TOT_PACKETS; //offset (not eiger) to keep track of how many packets saved + uint32_t packetsToSave; //how many packets to save at a time + volatile uint64_t tempframenumber; + int lastpacket; + + //loop to take care of creating new files when it reaches max packets per file + while(numpackets > 0){ + + //new file + if(packetsInFile >= (uint32_t)maxPacketsPerFile){ + //for packet loss, because currframenum is the latest one for eiger + //get frame number (eiger already gets it when it does packet to packet processing) + if(myDetectorType != EIGER){ + lastpacket = (((packetsToSave - 1) * onePacketSize) + offset); + if(myDetectorType == JUNGFRAU){ + jfrau_packet_header_t* header = (jfrau_packet_header_t*) (wbuffer[0] + lastpacket); + currentFrameNumber = (*( (uint32_t*) header->frameNumber))&0xffffff; + }else{ + tempframenumber = ((uint32_t)(*((uint32_t*)(wbuffer[0] + lastpacket)))); + //for gotthard and normal frame, increment frame number to separate fnum and pnum + if (myDetectorType == PROPIX ||(myDetectorType == GOTTHARD && shortFrameEnable == -1)) + tempframenumber++; + //get frame number + currentFrameNumber = (tempframenumber & frameIndexMask) >> frameIndexOffset; + } + + //set indices + acquisitionIndex = currentFrameNumber - startAcquisitionIndex; + frameIndex = currentFrameNumber - startFrameIndex; + } +#ifdef DEBUG3 + cprintf(GREEN,"Writing_Thread: Current Frame Number:%d\n",currentFrameNumber); +#endif + createNewFile(); + } + //to create new file when max reached + packetsToSave = maxPacketsPerFile - packetsInFile; + if(packetsToSave > numpackets) + packetsToSave = numpackets; + + //write to file + if(cbAction == DO_EVERYTHING){ + switch(myDetectorType){ + case EIGER: + for(uint32_t i=0; i 1) pthread_mutex_lock(&writeMutex); + packetsInFile += numpackets; + packetsCaught += (numpackets - numMissingPackets); + totalPacketsCaught += (numpackets - numMissingPackets); + numMissingPackets = 0; + if(numberofWriterThreads > 1) pthread_mutex_unlock(&writeMutex); + } + +} + + + + + +void UDPStandardImplementation::createHeaders(char* wbuffer[]){ + + + int port = 0, missingPacket; + bool exitVal = 0; + eiger_packet_header_t* wbuf_header; + eiger_packet_footer_t* wbuf_footer; + + for (uint32_t i = 0; i < packetsPerFrame; i++){ + + + wbuf_header = (eiger_packet_header_t*) wbuffer[i]; + wbuf_footer = (eiger_packet_footer_t*)(wbuffer[i] + footerOffset); +#ifdef DEBUG4 + cprintf(GREEN, "Loop index:%d Pnum:%d real fnum %d,missingPacket 0x%x\n", + i, + *( (uint16_t*) wbuf_footer->packetNumber), + (uint32_t)(*( (uint64_t*) wbuf_footer)), + *( (uint16_t*) wbuf_header->missingPacket) + ); cout <missingPacket)== missingPacketValue){ +#ifdef DEBUG4 + cprintf(RED,"-Missing packet at Loop Index %d\n", i); +#endif + missingPacket = 1; + + //DEBUGGING + if(*( (uint16_t*) wbuf_footer->packetNumber) != (i+1)){ + cprintf(BG_RED, "Writing_Thread: Packet Number Mismatch (missing p)! " + "i %d, real pnum %d, real fnum %d, missingPacket 0x%x\n", + i, + *( (uint16_t*) wbuf_footer->packetNumber), + (uint32_t)(*( (uint64_t*) wbuf_footer)), + *( (uint16_t*) wbuf_header->missingPacket)); + exitVal =1; + } + + //add frame number + *( (uint64_t*) wbuf_footer) = (currentFrameNumber+1) | (((uint64_t)(*( (uint16_t*) wbuf_footer->packetNumber)))<<0x30); + //*( (uint16_t*) wbuf_footer->packetNumber) = (i+1); // missing frames already have the right packet number +#ifdef DEBUG4 + cprintf(RED, "Missing Packet Loop index:%d fnum:%d Pnum:%d\n",i, + (uint32_t)(*( (uint64_t*) wbuf_footer)), + *( (uint16_t*) wbuf_footer->packetNumber)); +#endif + } + //normal packet + else{ + missingPacket = 0; + + //DEBUGGING + if(*( (uint16_t*) wbuf_footer->packetNumber) != ( (i>((packetsPerFrame/2)-1)?(i-(packetsPerFrame/2)+1):i+1) )){ + cprintf(BG_RED, "Writing_Thread: Packet Number Mismatch! " + "i %d, real pnum %d, real fnum %d, missingPacket 0x%x\n", + i, + *( (uint16_t*) wbuf_footer->packetNumber), + (uint32_t)(*( (uint64_t*) wbuf_footer)), + *( (uint16_t*) wbuf_header->missingPacket)); + exitVal =1; + } + + uint16_t p = *( (uint16_t*) wbuf_footer->packetNumber); + //correct the packet numbers of port2 so that port1 and 2 are not the same + if(port) *( (uint16_t*) wbuf_footer->packetNumber) = (p +(packetsPerFrame/2)); + + } + + //overwriting port number and dynamic range + *( (uint8_t*) wbuf_header->portIndex) = (uint8_t)port; + //*( (uint8_t*) wbuf_header->dynamicRange) = (uint8_t)dynamicRange; + + //DEBUGGING + if(*( (uint16_t*) wbuf_footer->packetNumber) != (i+1)){ + cprintf(BG_RED, "Writing_Thread: Packet Number Mismatch! " + "i %d, real pnum %d, real fnum %d, missingPacket 0x%x\n", + i, + *( (uint16_t*) wbuf_footer->packetNumber), + (uint32_t)(*( (uint64_t*) wbuf_footer)), + *( (uint16_t*) wbuf_header->missingPacket)); + exitVal =1; + } + } + + if(exitVal){exit(-1);} + +} + + +void UDPStandardImplementation::updateFileHeader(){ + int xpix=-1,ypix=-1; + + //create detector specific packet header + char packetheader[1000]; + strcpy(packetheader,""); + + //only for eiger right now + /*switch(myDetectorType){ + case EIGER: + */ sprintf(packetheader,"#Packet Header\n" + "Sub Frame Number 4 bytes\n" + "Missing Packet\t 2 bytes\n" + "Port Number\t 1 byte\n" + "Unused\t\t 1 byte\n\n" + "#Packet Footer\n" + "Frame Number\t 6 bytes\n" + "Packet Number\t 2 bytes\n"); + xpix = EIGER_PIXELS_IN_ONE_ROW; + ypix = EIGER_PIXELS_IN_ONE_COL; + /* break; + default: + break; + } +*/ + + //update file header + time_t t = time(0); + int length = sizeof(fileHeader); + while((unsigned int)length!=strlen(fileHeader)){ + length = strlen(fileHeader); + sprintf(fileHeader,"\nHeader\t\t %d bytes\n" + "Dynamic Range\t %d\n" + "Packet\t\t %d bytes\n" + "x\t\t %d pixels\n" + "y\t\t %d pixels\n" + "Timestamp\t %s\n\n" + "%s", + length,dynamicRange,onePacketSize,xpix,ypix,ctime(&t), + packetheader); + } + +} + + +void UDPStandardImplementation::copyFrameToGui(char* buffer[]){ + FILE_LOG(logDEBUG) << __AT__ << " called"; + + + //random read (gui not ready) + //need to toggle guiDataReady or the second frame wont be copied + if((!FrameToGuiFrequency) && (!guiData)){ +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: CopyingFrame: Resetting guiDataReady\n"); +#endif + pthread_mutex_lock(&dataReadyMutex); + guiDataReady=0; + pthread_mutex_unlock(&dataReadyMutex); + } + + //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: Gui needs data now OR 1st frame\n"); +#endif + pthread_mutex_lock(&dataReadyMutex); + guiDataReady=0; +#ifdef DEBUG4 + cprintf(GREEN,"Writing_Thread: CopyingFrame: guidataready is 0, Copying data\n"); +#endif + switch(myDetectorType){ + case EIGER: + for(uint32_t i=0; i> frameIndexOffset; + //handle multi threads + pthread_mutex_lock(&progressMutex); + if(tempframenumber > currentFrameNumber) + currentFrameNumber = tempframenumber; + pthread_mutex_unlock(&progressMutex); + //set indices + acquisitionIndex = currentFrameNumber - startAcquisitionIndex; + frameIndex = currentFrameNumber - startFrameIndex; + + + //variable definitions + char* buff[2]={0,0}; //an array just to be compatible with copyframetogui + char* data = wbuffer[0]+ HEADER_SIZE_NUM_TOT_PACKETS; //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[0])); //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)) + singlePhotonDetectorObject[ithread]->writeCluster(sfilefd); + pthread_mutex_unlock(&writeMutex); +#endif + } + } + } + + nf++; +#ifndef ALLFILE + pthread_mutex_lock(&progressMutex); + packetsInFile += packetsPerFrame; + packetsCaught += packetsPerFrame; + totalPacketsCaught += packetsPerFrame; + if(packetsInFile >= (uint32_t)maxPacketsPerFile) + createNewFile(); + pthread_mutex_unlock(&progressMutex); + +#endif + if(!once){ + copyFrameToGui(buff); + once = 1; + } + } + + remainingsize -= ((buff[0] + ndata) - data); + data = buff[0] + ndata; + if(data > (wbuffer[0] + HEADER_SIZE_NUM_TOT_PACKETS + npackets * onePacketSize) ) + cprintf(BG_RED,"Writing_Thread %d: Error: Compression data goes out of bounds!\n", ithread); + } + + + while(!fifoFree[0]->push(wbuffer[0])); +#ifdef EVERYFIFODEBUG + if(fifoFree[0]->getSemValue()<100) + cprintf(GREEN,"FifoFree[%d]: value:%d, push 0x%x\n",0,fifoFree[0]->getSemValue(),(void*)(wbuffer[0])); +#endif +#ifdef DEBUG5 + cprintf(GREEN,"Writing_Thread %d: Compression free pushed into fifofree %p for listerner 0\n", ithread, (void*)(wbuffer[0])); +#endif +} + + diff --git a/slsReceiverSoftware/src/dummyMain.cpp b/slsReceiverSoftware/src/dummyMain.cpp new file mode 100644 index 0000000000..3f4e9bb2d3 --- /dev/null +++ b/slsReceiverSoftware/src/dummyMain.cpp @@ -0,0 +1,48 @@ +/* A simple server in the internet domain using TCP + The port number is passed as an argument */ + +#include "sls_receiver_defs.h" +#include "dummyUDPInterface.h" +#include "slsReceiverTCPIPInterface.h" + +#include +#include + + +using namespace std; + + +int main(int argc, char *argv[]) { + int success; + int tcpip_port_no; + bool bottom = false; + cout << "CCCCCC" << endl; + dummyUDPInterface *udp=new dummyUDPInterface(); +// slsReceiverTCPIPInterface *tcpipInterface = new slsReceiverTCPIPInterface(success, udp, tcpip_port_no, bottom); + + + + +// if(tcpipInterface->start() == slsReceiverDefs::OK){ +// cout << "DONE!" << endl; +// string str; +// cin>>str; +// //wait and look for an exit keyword +// while(str.find("exit") == string::npos) +// cin>>str; +// //stop tcp server thread, stop udp socket +// tcpipInterface->stop(); +// } + +// if (tcpipInterface) +// delete tcpipInterface; + + udp->startReceiver(); + if(udp) + delete udp; + return 0; + + + +} + diff --git a/slsReceiverSoftware/src/main.cpp b/slsReceiverSoftware/src/main.cpp new file mode 100644 index 0000000000..a005f569d7 --- /dev/null +++ b/slsReceiverSoftware/src/main.cpp @@ -0,0 +1,118 @@ +/* A simple server in the internet domain using TCP + The port number is passed as an argument */ + +#include "sls_receiver_defs.h" +#include "slsReceiverUsers.h" + +#include +#include +#include //SIGINT + +#include "utilities.h" +#include "logger.h" +using namespace std; + +slsReceiverUsers *receiver; + +void deleteReceiver(slsReceiverUsers* r){ + if(r){delete r;r=0;} +} + +void closeFile(int p){ + deleteReceiver(receiver); +} + +/* +int startAcquisitionCallBack(char* filePath, char* fileName, int fileIndex, int bufferSize, void* context) { + cout << "#### startAcquisitionCallBack ####" << endl; + cout << "* filePath: " << filePath << endl; + cout << "* fileName: " << fileName << endl; + cout << "* fileIndex: " << fileIndex << endl; + cout << "* bufferSize: " << bufferSize << endl; + return 1; +} + +void acquisitionFinishedCallBack(int totalFramesCaught, void* context) { + cout << "#### acquisitionFinishedCallBack ####" << endl; + cout << "* totalFramesCaught: " << totalFramesCaught << endl; +} + +void rawDataReadyCallBack(int currFrameNum, char* dataPointer, int dataSize, FILE* file, char* guiDataPointer, void* context) { + cout << "#### rawDataReadyCallBack ####" << endl; + cout << "* currFrameNum: " << currFrameNum << endl; + cout << "* dataSize: " << dataSize << endl; +} +*/ + +int main(int argc, char *argv[]) { + + //Catch signal SIGINT to close files properly + signal(SIGINT,closeFile); + + int ret = slsReceiverDefs::OK; + receiver = new slsReceiverUsers(argc, argv, ret); + + if(ret==slsReceiverDefs::FAIL){ + deleteReceiver(receiver); + return -1; + } + + + //register callbacks + + /** + callback arguments are + filepath + filename + fileindex + datasize + + return value is + 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 + + registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg); + */ + //receiver->registerCallBackStartAcquisition(startAcquisitionCallBack,NULL); + + + /** + callback argument is + total farmes caught + registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg); + */ + //receiver->registerCallBackAcquisitionFinished(acquisitionFinishedCallBack,NULL); + + + /** + args to raw data ready callback are + framenum + datapointer + file descriptor + guidatapointer (NULL, no data required) + NEVER DELETE THE DATA POINTER + REMEMBER THAT THE CALLBACK IS BLOCKING + registerCallBackRawDataReady(void (*func)(int, char*, FILE*, char*, void*),void *arg); + */ + //receiver->registerCallBackRawDataReady(rawDataReadyCallBack,NULL); + + + + //start tcp server thread + if(receiver->start() == slsReceiverDefs::OK){ + FILE_LOG(logDEBUG1) << "DONE!" << endl; + string str; + cin>>str; + //wait and look for an exit keyword + while(str.find("exit") == string::npos) + cin>>str; + //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 new file mode 100644 index 0000000000..a6c231a3ef --- /dev/null +++ b/slsReceiverSoftware/src/slsReceiver.cpp @@ -0,0 +1,200 @@ +/********************************************//** + * @file slsReceiver.cpp + * @short creates the UDP and TCP class objects + ***********************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "slsReceiver.h" +//#include "UDPInterface.h" + +using namespace std; + + + +slsReceiver::slsReceiver(int argc, char *argv[], int &success){ + + /** + * Constructor method to start up a Receiver server. Reads configuration file, options, and + * assembles a Receiver using TCP and UDP detector interfaces + * + * @param iarg + * + * @return + */ + + udp_interface = NULL; + tcpipInterface = NULL; + + //creating base receiver + map configuration_map; + int tcpip_port_no = 1954; + success=OK; + string fname = ""; + string udp_interface_type = "standard"; + string rest_hostname = "localhost:8081"; + udp_interface = NULL; + + bool bottom = false; //TODO: properly set new parameter -> mode? + //parse command line for config + static struct option long_options[] = { + /* These options set a flag. */ + //{"verbose", no_argument, &verbose_flag, 1}, + /* These options don’t set a flag. + We distinguish them by their indices. */ + {"mode", required_argument, 0, 'm'}, + {"type", required_argument, 0, 't'}, + {"config", required_argument, 0, 'f'}, + {"rx_tcpport", required_argument, 0, 'b'}, + {"rest_hostname", required_argument, 0, 'r'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + /* getopt_long stores the option index here. */ + int option_index = 0; + int c=0; + optind = 1; + + while ( c != -1 ){ + c = getopt_long (argc, argv, "mbfhtr", long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch(c){ + + case 'm': + int b; + sscanf(optarg, "%d", &b); + bottom = b != 0; + configuration_map["mode"] = optarg; + break; + + case 'f': + fname = optarg; + //cout << long_options[option_index].name << " " << optarg << endl; + break; + + case 'b': + sscanf(optarg, "%d", &tcpip_port_no); + break; + + case 't': + udp_interface_type = optarg; + break; + + case 'r': + rest_hostname = optarg; + break; + + case 'h': + string help_message = """\nSLS Receiver Server\n\n"""; + help_message += """usage: slsReceiver --config config_fname [--rx_tcpport port]\n\n"""; + help_message += """\t--config:\t configuration filename for SLS Detector receiver\n"""; + help_message += """\t--mode:\t 1 for bottom and 0 for top\n"""; + help_message += """\t--rx_tcpport:\t TCP Communication Port with the client. Default: 1954.\n\n"""; + help_message += """\t--rest_hostname:\t Receiver hostname:port. It applies only to REST receivers, and indicates the hostname of the REST backend. Default: localhost:8081.\n\n"""; + + help_message += """\t--type:\t Type of the receiver. Possible arguments are: standard, REST. Default: standard.\n\n"""; + + cout << help_message << endl; + break; + + } + } + + // if required fname parameter not available, fail + //if (fname == "") + // success = FAIL; + + if( !fname.empty() ){ + try{ + FILE_LOG(logINFO) << "config file name " << fname; + success = read_config_file(fname, &tcpip_port_no, &configuration_map); + //VERBOSE_PRINT("Read configuration file of " + iline + " lines"); + } + catch(...){ + FILE_LOG(logERROR) << "Error opening configuration file " << fname ; + success = FAIL; + } + } + + + if(success != OK){ + FILE_LOG(logERROR) << "Failed: see output above for more information " ; + } + + if (success==OK){ + FILE_LOG(logINFO) << "SLS Receiver starting " << udp_interface_type << " on port " << tcpip_port_no << " with mode " << bottom << endl; +#ifdef REST + udp_interface = UDPInterface::create(udp_interface_type); + udp_interface->configure(configuration_map); +#endif + tcpipInterface = new slsReceiverTCPIPInterface(success, udp_interface, tcpip_port_no, bottom); + } +} + + +slsReceiver::~slsReceiver() { + if(udp_interface) + delete udp_interface; + if(tcpipInterface) + delete tcpipInterface; +} + + +int slsReceiver::start() { + return tcpipInterface->start(); +} + + +void slsReceiver::stop() { + tcpipInterface->stop(); +} + + +void slsReceiver::closeFile(int p) { + tcpipInterface->closeFile(p); +} + + +int64_t slsReceiver::getReceiverVersion(){ + return tcpipInterface->getReceiverVersion(); +} + + +void slsReceiver::registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){ + //tcpipInterface + if(udp_interface) + udp_interface->registerCallBackStartAcquisition(func,arg); + else + tcpipInterface->registerCallBackStartAcquisition(func,arg); +} + + + +void slsReceiver::registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){ + //tcpipInterface + if(udp_interface) + udp_interface->registerCallBackAcquisitionFinished(func,arg); + else + tcpipInterface->registerCallBackAcquisitionFinished(func,arg); +} + + +void slsReceiver::registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){ + //tcpipInterface + if(udp_interface) + udp_interface->registerCallBackRawDataReady(func,arg); + else + tcpipInterface->registerCallBackRawDataReady(func,arg); +} + + diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp new file mode 100644 index 0000000000..1e2b5c49e5 --- /dev/null +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -0,0 +1,3049 @@ +/********************************************//** + * @file slsReceiverTCPIPInterface.cpp + * @short interface between receiver and client + ***********************************************/ + +#include "slsReceiverTCPIPInterface.h" +#include "UDPInterface.h" +#include "gitInfoReceiver.h" +#include "slsReceiverUsers.h" +#include "slsReceiver.h" + +#include //EXIT +#include +#include +#include +#include +#include +#include //linux5 +#define be64toh(x) __bswap_64 (x) //linux5 +//#include //linux6 +using namespace std; + + + +slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { + stop(); + if(socket) {delete socket; socket=NULL;} +} + +slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int &success, UDPInterface* rbase, int pn, bool bot): + myDetectorType(GOTTHARD), + receiverBase(rbase), + ret(OK), + lockStatus(0), + shortFrame(-1), + packetsPerFrame(GOTTHARD_PACKETS_PER_FRAME), + dynamicrange(16), + killTCPServerThread(0), + tenGigaEnable(0), + portNumber(DEFAULT_PORTNO+2), + bottom(bot), + socket(NULL){ + + strcpy(SET_RECEIVER_ERR_MESSAGE,"Receiver not set up. Please use rx_hostname first.\n"); + + //***callback parameters*** + startAcquisitionCallBack = NULL; + pStartAcquisition = NULL; + acquisitionFinishedCallBack = NULL; + pAcquisitionFinished = NULL; + rawDataReadyCallBack = NULL; + pRawDataReady = NULL; + + int port_no=portNumber; + if(receiverBase == NULL) receiverBase = 0; + + if (pn>0) + port_no = pn; + + success=OK; + + //create socket + if(success == OK){ + socket = new MySocketTCP(port_no); + if (socket->getErrorStatus()) { + success = FAIL; + delete socket; + socket=NULL; + } else { + portNumber=port_no; + //initialize variables + strcpy(socket->lastClientIP,"none"); + strcpy(socket->thisClientIP,"none1"); + strcpy(mess,"dummy message"); + function_table(); +#ifdef VERYVERBOSE + cout << "Function table assigned." << endl; +#endif + } + } + +} + + +int slsReceiverTCPIPInterface::setPortNumber(int pn){ + int p_number; + + MySocketTCP *oldsocket=NULL;; + int sd=0; + + if (pn>0) { + p_number = pn; + + if (p_number<1024) { + sprintf(mess,"Too low port number %d\n", p_number); + cout << mess << endl; + } else { + + oldsocket=socket; + socket = new MySocketTCP(p_number); + if(socket){ + sd = socket->getErrorStatus(); + if (!sd){ + portNumber=p_number; + strcpy(socket->lastClientIP,oldsocket->lastClientIP); + delete oldsocket; + } else { + cout << "Could not bind port " << p_number << endl; + if (sd==-10) { + + cout << "Port "<< p_number << " already set" << endl; + } else { + delete socket; + socket=oldsocket; + } + } + + } else { + socket=oldsocket; + } + } + } + + return portNumber; +} + + + +int slsReceiverTCPIPInterface::start(){ + FILE_LOG(logDEBUG) << "Creating TCP Server Thread" << endl; + killTCPServerThread = 0; + if(pthread_create(&TCPServer_thread, NULL,startTCPServerThread, (void*) this)){ + cout << "Could not create TCP Server thread" << endl; + return FAIL; + } + //#ifdef VERYVERBOSE + FILE_LOG(logDEBUG) << "TCP Server thread created successfully." << endl; + //#endif + return OK; +} + + +void slsReceiverTCPIPInterface::stop(){ + cout << "Shutting down UDP Socket" << endl; + killTCPServerThread = 1; + if(socket) socket->ShutDownSocket(); + cout<<"Socket closed"<startTCPServer(); + return this_pointer; +} + + +void slsReceiverTCPIPInterface::startTCPServer(){ + + +#ifdef VERYVERBOSE + cout << "Starting Receiver TCP Server" << endl; +#endif + int v=OK; + + while(1) { +#ifdef VERYVERBOSE + cout<< endl; +#endif +#ifdef VERY_VERBOSE + cout << "Waiting for client call" << endl; +#endif + if(socket->Connect()>=0){ +#ifdef VERY_VERBOSE + cout << "Conenction accepted" << endl; +#endif + v = decode_function(); +#ifdef VERY_VERBOSE + cout << "function executed" << endl; +#endif + socket->Disconnect(); +#ifdef VERY_VERBOSE + cout << "connection closed" << endl; +#endif + } + + //if tcp command was to exit server + if(v==GOODBYE){ + cout << "Shutting down UDP Socket" << endl; + if(receiverBase){ + receiverBase->shutDownUDPSockets(); + + cout << "Closing Files... " << endl; + receiverBase->closeFile(); + } + + socket->exitServer(); + pthread_exit(NULL); + } + + //if user entered exit + if(killTCPServerThread) + pthread_exit(NULL); + + } +} + + + + + +int slsReceiverTCPIPInterface::function_table(){ + + for (int i=0;iReceiveDataOnly(&fnum,sizeof(fnum)); + if (n <= 0) { +#ifdef VERYVERBOSE + cout << "ERROR reading from socket " << n << ", " << fnum << endl; +#endif + return FAIL; + } +#ifdef VERYVERBOSE + else + cout << "size of data received " << n <numberOfFunctions-1) + fnum = numberOfFunctions-1; + //calling function + (this->*flist[fnum])(); + if (ret==FAIL) + cprintf(RED, "Error executing the function = %d\n",fnum); + + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::M_nofunc(){ + + ret=FAIL; + sprintf(mess,"Unrecognized Function\n"); + cout << mess << endl; + + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(mess,sizeof(mess)); + + return GOODBYE; +} + + + + +void slsReceiverTCPIPInterface::closeFile(int p){ + receiverBase->closeFile(); +} + + +int slsReceiverTCPIPInterface::set_detector_type(){ + ret=OK; + detectorType retval=GENERIC; + detectorType dr; + strcpy(mess,"Could not set detector type range\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&dr,sizeof(dr)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else{ + + switch(dr){ + case GOTTHARD: + case PROPIX: + case MOENCH: + case EIGER: + case JUNGFRAUCTB: + case JUNGFRAU: + break; + default: + sprintf(mess,"Unknown detector type: %d\n", dr); + ret = FAIL; + break; + } + if(ret != FAIL){ +#ifndef REST + receiverBase = UDPInterface::create("standard"); + if(startAcquisitionCallBack) + receiverBase->registerCallBackStartAcquisition(startAcquisitionCallBack,pStartAcquisition); + if(acquisitionFinishedCallBack) + receiverBase->registerCallBackAcquisitionFinished(acquisitionFinishedCallBack,pAcquisitionFinished); + if(rawDataReadyCallBack) + receiverBase->registerCallBackRawDataReady(rawDataReadyCallBack,pRawDataReady); +#endif + myDetectorType = dr; + ret=receiverBase->setDetectorType(myDetectorType); + retval = myDetectorType; +#ifndef REST + receiverBase->setBottomEnable(bottom); +#endif + } + + } + } + //#ifdef VERYVERBOSE + if(ret!=FAIL) + FILE_LOG(logDEBUG) << "detector type " << dr; + else + cprintf(RED, "%s\n", mess); + //#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::set_file_name() { + ret=OK; + char* retval = NULL; + char defaultVal[MAX_STR_LENGTH] = ""; + char fName[MAX_STR_LENGTH]; + strcpy(mess,"Could not set file name"); + + // receive arguments + if(socket->ReceiveDataOnly(fName,MAX_STR_LENGTH) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + receiverBase->setFileName(fName); + retval = receiverBase->getFileName(); + if(retval == NULL) + ret = FAIL; + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "file name:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + if(retval == NULL) + socket->SendDataOnly(defaultVal,MAX_STR_LENGTH); + else{ + socket->SendDataOnly(retval,MAX_STR_LENGTH); + delete[] retval; + } + + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::set_file_dir() { + ret=OK; + char* retval=NULL; + char defaultVal[MAX_STR_LENGTH] = ""; + char fPath[MAX_STR_LENGTH]; + strcpy(mess,"Could not set file path\n"); + + // receive arguments + if(socket->ReceiveDataOnly(fPath,MAX_STR_LENGTH) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + }/* + else if((strlen(fPath))&&(receiverBase->getStatus()==RUNNING)){ + strcpy(mess,"Can not set file path while receiver running\n"); + ret = FAIL; + }*/ + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + receiverBase->setFilePath(fPath); + retval = receiverBase->getFilePath(); + if(retval == NULL){ + ret = FAIL; + strcpy(mess,"receiver file path does not exist\n"); + } + } + + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "file path:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + if(retval == NULL) + socket->SendDataOnly(defaultVal,MAX_STR_LENGTH); + else{ + socket->SendDataOnly(retval,MAX_STR_LENGTH); + delete[] retval; + } + + //return ok/fail + return ret; +} + + + + + +// LEO: do we need it in the base class? +int slsReceiverTCPIPInterface::set_file_index() { + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not set file index\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + if(index >= 0) + receiverBase->setFileIndex(index); + retval=receiverBase->getFileIndex(); + if(index>=0 && retval!=index) + ret = FAIL; + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "file index:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + + +int slsReceiverTCPIPInterface::set_frame_index() { + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not set frame index\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + //client sets to 0, but for receiver it is just an enable + //client uses this value for other detectors not using receiver, + //so implement the interface here + + switch(index){ + case -1: index=0; break; + default: index=1; break; //value is 0 + } + receiverBase->setFrameIndexEnable(index); + retval=receiverBase->getFrameIndexEnable(); + switch(retval){ + case 0: retval=-1; break; + case 1: retval=0; break; + } + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "frame index:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + +//LEO: is the client that commands the setup, or you just need the args? +int slsReceiverTCPIPInterface::setup_udp(){ + ret=OK; + strcpy(mess,"could not set up udp connection"); + char retval[MAX_STR_LENGTH] = ""; + char args[3][MAX_STR_LENGTH]; + + string temp; + int udpport,udpport2; + char eth[MAX_STR_LENGTH]; + + + // receive arguments + + if(socket->ReceiveDataOnly(args,sizeof(args)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else if(receiverBase->getStatus()==RUNNING){ + ret = FAIL; + strcpy(mess,"cannot set up udp when receiver is running\n"); + } + else{ + //set up udp port + sscanf(args[1],"%d",&udpport); + sscanf(args[2],"%d",&udpport2); + receiverBase->setUDPPortNumber(udpport); + receiverBase->setUDPPortNumber2(udpport2); + //setup udpip + //get ethernet interface or IP to listen to + FILE_LOG(logINFO) << "Receiver UDP IP: " << args[0]; + temp = genericSocket::ipToName(args[0]); + if(temp=="none"){ + ret = FAIL; + strcpy(mess, "Failed to get ethernet interface or IP\n"); + FILE_LOG(logERROR) << mess; + } + else{ + strcpy(eth,temp.c_str()); + if (strchr(eth,'.')!=NULL) { + strcpy(eth,""); + ret = FAIL; + } + receiverBase->setEthernetInterface(eth); + + //get mac address from ethernet interface + if (ret != FAIL) + temp = genericSocket::nameToMac(eth); + + + if ((temp=="00:00:00:00:00:00") || (ret == FAIL)){ + ret = FAIL; + strcpy(mess,"failed to get mac adddress to listen to\n"); + } + else{ + strcpy(retval,temp.c_str()); + FILE_LOG(logINFO) << "Reciever MAC Address: " << retval; + } + } + } + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + FILE_LOG(logERROR) << mess; + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(retval,MAX_STR_LENGTH); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::start_receiver(){ + ret=OK; + ret=OK; + enum runStatus s = ERROR; + strcpy(mess,"Could not start receiver\n"); + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + /* + else if(!strlen(receiverBase->getFilePath())){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE"); + ret = FAIL; + } + */ + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else { + s = receiverBase->getStatus(); + if(s == IDLE) + ret=receiverBase->startReceiver(mess); + else{ + sprintf(mess,"Cannot start Receiver as it is in %s state\n",runStatusType(s).c_str()); + ret=FAIL; + } + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "Error:%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::stop_receiver(){ + ret=OK; + enum runStatus s = ERROR; + strcpy(mess,"Could not stop receiver\n"); + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + if(receiverBase->getStatus()!=IDLE) + receiverBase->stopReceiver(); + s = receiverBase->getStatus(); + if(s==IDLE) + ret = OK; + else{ + sprintf(mess,"Could not stop receiver. It is in %s state\n",runStatusType(s).c_str()); + ret = FAIL; + } + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::get_status(){ + ret=OK; + enum runStatus retval = ERROR; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + }else retval=receiverBase->getStatus(); +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::get_frames_caught(){ + ret=OK; + int retval=-1; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + }else retval=receiverBase->getTotalFramesCaught(); +#endif + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::get_frame_index(){ + ret=OK; + int retval=-1; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + }else + retval=receiverBase->getAcquisitionIndex(); +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::reset_frames_caught(){ + ret=OK; + + strcpy(mess,"Could not reset frames caught\n"); + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else + receiverBase->resetAcquisitionCount(); + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + //return ok/fail + return ret; + + +} + + + + + + +int slsReceiverTCPIPInterface::set_short_frame() { + ret=OK; + int index=0; + int retval=-100; + strcpy(mess,"Could not set/reset short frame for receiver\n"); + + //does not exist for moench + if(myDetectorType==MOENCH){ + strcpy(mess,"can not set short frame for moench\n"); + ret = FAIL; + } + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else if(receiverBase->getStatus()==RUNNING){ + strcpy(mess,"Cannot set short frame while status is running\n"); + ret=FAIL; + } + else{ + receiverBase->setShortFrameEnable(index); + retval = receiverBase->getShortFrameEnable(); + shortFrame = retval; + if(shortFrame==-1) + packetsPerFrame=GOTTHARD_PACKETS_PER_FRAME; + else + packetsPerFrame=GOTTHARD_SHORT_PACKETS_PER_FRAME; + } + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + +int slsReceiverTCPIPInterface::read_frame(){ + switch(myDetectorType){ + case MOENCH: + return moench_read_frame(); + case EIGER: + return eiger_read_frame(); + case PROPIX: + return propix_read_frame(); + case JUNGFRAU: + return jungfrau_read_frame(); + default: + return gotthard_read_frame(); + } +} + + + +int slsReceiverTCPIPInterface::moench_read_frame(){ + ret=OK; + char fName[MAX_STR_LENGTH]=""; + int acquisitionIndex = -1; + int frameIndex= -1; + int i; + + + int bufferSize = MOENCH_BUFFER_SIZE; + int rnel = bufferSize/(sizeof(int)); + int* retval = new int[rnel]; + int* origVal = new int[rnel]; + //all initialized to 0 + for(i=0;igetFramesCaught()){ + startAcquisitionIndex = -1; + cout<<"haven't caught any frame yet"<readFrame(fName,&raw,startAcquisitionIndex,startFrameIndex); + + /**send garbage with -1 index to try again*/ + if (raw == NULL){ + startAcquisitionIndex = -1; +#ifdef VERYVERBOSE + cout<<"data not ready for gui yet"<> MOENCH_FRAME_INDEX_OFFSET); + + uint32_t numPackets = MOENCH_PACKETS_PER_FRAME; //40 + uint32_t onePacketSize = MOENCH_DATA_BYTES / MOENCH_PACKETS_PER_FRAME; //1280*40 / 40 = 1280 + uint32_t packetDatabytes_row = onePacketSize * (MOENCH_BYTES_IN_ONE_ROW / MOENCH_BYTES_PER_ADC); //1280 * 4 = 5120 + uint32_t partsPerFrame = onePacketSize / MOENCH_BYTES_PER_ADC; // 1280 / 80 = 16 + uint32_t packetOffset = 0; + int packetIndex,x,y; + int iPacket = 0; + offset = 4; + + + while (iPacket < (int)numPackets){ +#ifdef VERYVERBOSE + printf("iPacket:%d\n",iPacket);cout << endl; +#endif + //if missing packets, dont send to gui + bindex = (*((uint32_t*)(((char*)origVal)+packetOffset))); + if (bindex == 0xFFFFFFFF){ + cout << "Missing Packet,Not sending to gui" << endl; + index = startAcquisitionIndex - 1; + break;//use continue and change index above if you want to display missing packets with 0 value anyway in gui + } + + packetIndex = bindex & MOENCH_PACKET_INDEX_MASK; + //cout<<"packetIndex:"<= 40) && (packetIndex < 0)) + cout << "cannot decode packet index:" << packetIndex << endl; + else{ + + x = packetIndex / 10; + y = packetIndex % 10; +#ifdef VERYVERBOSE + cout<<"x:"<differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + else{ + socket->SendDataOnly(fName,MAX_STR_LENGTH); + socket->SendDataOnly(&acquisitionIndex,sizeof(acquisitionIndex)); + socket->SendDataOnly(&frameIndex,sizeof(frameIndex)); + socket->SendDataOnly(retval,MOENCH_DATA_BYTES); + } + //return ok/fail + + + delete [] retval; + delete [] origVal; + delete [] raw; + + return ret; + +} + + + + +int slsReceiverTCPIPInterface::gotthard_read_frame(){ + ret=OK; + char fName[MAX_STR_LENGTH]=""; + int acquisitionIndex = -1; + int frameIndex= -1; + int i; + + + //retval is a full frame + int bufferSize = GOTTHARD_BUFFER_SIZE; + int rnel = bufferSize/(sizeof(int)); + int* retval = new int[rnel]; + int* origVal = new int[rnel]; + //all initialized to 0 + for(i=0;igetFramesCaught()){ + startAcquisitionIndex=-1; + cout<<"haven't caught any frame yet"<readFrame(fName,&raw,startAcquisitionIndex,startFrameIndex); + + /**send garbage with -1 index to try again*/ + if (raw == NULL){ + startAcquisitionIndex = -1; +#ifdef VERYVERBOSE + cout<<"data not ready for gui yet"<> GOTTHARD_SHORT_FRAME_INDEX_OFFSET); +#ifdef VERYVERBOSE + cout << "index:" << hex << index << endl; +#endif + }else{ + bindex = ((uint32_t)(*((uint32_t*)raw)))+1; + pindex = (bindex & GOTTHARD_PACKET_INDEX_MASK); + index = ((bindex & GOTTHARD_FRAME_INDEX_MASK) >> GOTTHARD_FRAME_INDEX_OFFSET); + bindex2 = ((uint32_t)(*((uint32_t*)((char*)(raw+onebuffersize)))))+1; + pindex2 =(bindex2 & GOTTHARD_PACKET_INDEX_MASK); + index2 =((bindex2 & GOTTHARD_FRAME_INDEX_MASK) >> GOTTHARD_FRAME_INDEX_OFFSET); +#ifdef VERYVERBOSE + cout << "index1:" << hex << index << endl; + cout << "index2:" << hex << index << endl; +#endif + } + + memcpy(origVal,raw,bufferSize); + raw=NULL; + + + //1 adc + if(shortFrame!=-1){ + if(bindex != 0xFFFFFFFF) + memcpy((((char*)retval)+(GOTTHARD_SHORT_DATABYTES*shortFrame)),((char*) origVal)+4, GOTTHARD_SHORT_DATABYTES); + else{ + index = startAcquisitionIndex - 1; + cout << "Missing Packet,Not sending to gui" << endl; + } + } + //all adc + else{ + /*//ignore if half frame is missing + if ((bindex != 0xFFFFFFFF) && (bindex2 != 0xFFFFFFFF)){*/ + + //should be same frame + if (index == index2){ + //ideal situation (should be odd, even(index+1)) + if(!pindex){ + memcpy(retval,((char*) origVal)+4, onedatasize); + memcpy((((char*)retval)+onedatasize), ((char*) origVal)+10+onedatasize, onedatasize); + } + //swap to even,odd + else{ + memcpy((((char*)retval)+onedatasize),((char*) origVal)+4, onedatasize); + memcpy(retval, ((char*) origVal)+10+onedatasize, onedatasize); + index=index2; + } + }else + cout << "different frames caught. frame1:"<< hex << index << ":"<differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + else{ + socket->SendDataOnly(fName,MAX_STR_LENGTH); + socket->SendDataOnly(&acquisitionIndex,sizeof(acquisitionIndex)); + socket->SendDataOnly(&frameIndex,sizeof(frameIndex)); + socket->SendDataOnly(retval,GOTTHARD_DATA_BYTES); + } + + delete [] retval; + delete [] origVal; + delete [] raw; + + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::propix_read_frame(){ + ret=OK; + char fName[MAX_STR_LENGTH]=""; + int acquisitionIndex = -1; + int frameIndex= -1; + int i; + + + //retval is a full frame + int bufferSize = PROPIX_BUFFER_SIZE; + int onebuffersize = bufferSize/PROPIX_PACKETS_PER_FRAME; + int onedatasize = PROPIX_DATA_BYTES; + + char* raw; + int rnel = bufferSize/(sizeof(int)); + int* retval = new int[rnel]; + int* origVal = new int[rnel]; + //all initialized to 0 + for(i=0;igetFramesCaught()){ + startAcquisitionIndex=-1; + cout<<"haven't caught any frame yet"<readFrame(fName,&raw,startAcquisitionIndex,startFrameIndex); + + /**send garbage with -1 index to try again*/ + if (raw == NULL){ + startAcquisitionIndex = -1; +#ifdef VERYVERBOSE + cout<<"data not ready for gui yet"<> PROPIX_FRAME_INDEX_OFFSET); + bindex2 = ((uint32_t)(*((uint32_t*)((char*)(raw+onebuffersize)))))+1; + pindex2 =(bindex2 & PROPIX_PACKET_INDEX_MASK); + index2 =((bindex2 & PROPIX_FRAME_INDEX_MASK) >> PROPIX_FRAME_INDEX_OFFSET); +#ifdef VERYVERBOSE + cout << "index1:" << hex << index << endl; + cout << "index2:" << hex << index << endl; +#endif + + memcpy(origVal,raw,bufferSize); + raw=NULL; + + /*//ignore if half frame is missing + if ((bindex != 0xFFFFFFFF) && (bindex2 != 0xFFFFFFFF)){*/ + + //should be same frame + if (index == index2){ + //ideal situation (should be odd, even(index+1)) + if(!pindex){ + memcpy(retval,((char*) origVal)+4, onedatasize); + memcpy((((char*)retval)+onedatasize), ((char*) origVal)+10+onedatasize, onedatasize); + } + //swap to even,odd + else{ + memcpy((((char*)retval)+onedatasize),((char*) origVal)+4, onedatasize); + memcpy(retval, ((char*) origVal)+10+onedatasize, onedatasize); + index=index2; + } + }else + cout << "different frames caught. frame1:"<< hex << index << ":"<differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + else{ + socket->SendDataOnly(fName,MAX_STR_LENGTH); + socket->SendDataOnly(&acquisitionIndex,sizeof(acquisitionIndex)); + socket->SendDataOnly(&frameIndex,sizeof(frameIndex)); + socket->SendDataOnly(retval,PROPIX_DATA_BYTES); + } + + delete [] retval; + delete [] origVal; + delete [] raw; + + return ret; +} + + + + + + + + + + +int slsReceiverTCPIPInterface::eiger_read_frame(){ + ret=OK; + + char fName[MAX_STR_LENGTH]=""; + int acquisitionIndex = -1; + int frameIndex= -1; + uint32_t index=0; + uint32_t subframenumber=-1; + + int frameSize = EIGER_ONE_GIGA_ONE_PACKET_SIZE * packetsPerFrame; + int dataSize = EIGER_ONE_GIGA_ONE_DATA_SIZE * packetsPerFrame; + int oneDataSize = EIGER_ONE_GIGA_ONE_DATA_SIZE; + if(tenGigaEnable){ + frameSize = EIGER_TEN_GIGA_ONE_PACKET_SIZE * packetsPerFrame; + dataSize = EIGER_TEN_GIGA_ONE_DATA_SIZE * packetsPerFrame; + oneDataSize = EIGER_TEN_GIGA_ONE_DATA_SIZE; + } + char* raw; + char* origVal = new char[frameSize]; + char* retval = new char[dataSize]; + uint64_t startAcquisitionIndex=0; + uint64_t startFrameIndex=0; + strcpy(mess,"Could not read frame\n"); + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + + //send garbage with -1 index to try again + else if(!receiverBase->getFramesCaught()){ + startAcquisitionIndex=-1; +#ifdef VERYVERBOSE + cout<<"haven't caught any frame yet"<readFrame(fName,&raw,startAcquisitionIndex,startFrameIndex); + //send garbage with -1 index to try again + if (raw == NULL){ + startAcquisitionIndex = -1; +#ifdef VERYVERBOSE + cout<<"data not ready for gui yet"<subFrameNumber); + } + +#ifdef VERYVERBOSE + cout << "index:" << dec << index << endl; + cout << "subframenumber:" << dec << subframenumber << endl; +#endif + + memcpy(origVal,raw,frameSize); + raw=NULL; + + int c1=8;//first port + int c2=(frameSize/2) + 8; //second port + int retindex=0; + int irow,ibytesperpacket; + int linesperpacket = (16*1/dynamicrange);// 16:1 line, 8:2 lines, 4:4 lines, 32: 0.5 + int numbytesperlineperport=(EIGER_PIXELS_IN_ONE_ROW/EIGER_MAX_PORTS)*dynamicrange/8;//16:1024,8:512,4:256,32:2048 + int datapacketlength = EIGER_ONE_GIGA_ONE_DATA_SIZE; + int total_num_bytes = EIGER_ONE_GIGA_ONE_PACKET_SIZE *(EIGER_ONE_GIGA_CONSTANT *dynamicrange)*2; + + if(tenGigaEnable){ + linesperpacket = (16*4/dynamicrange);// 16:4 line, 8:8 lines, 4:16 lines, 32: 2 + datapacketlength = EIGER_TEN_GIGA_ONE_DATA_SIZE; + total_num_bytes = EIGER_TEN_GIGA_ONE_PACKET_SIZE*(EIGER_TEN_GIGA_CONSTANT*dynamicrange)*2; + } + //if 1GbE, one line is split into two packets for 32 bit mode, so its special + else if(dynamicrange == 32){ + numbytesperlineperport = 1024; + linesperpacket = 1; //we repeat this twice anyway for 32 bit + } + + if(!bottom){ + + for(irow=0;irowdifferentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + else{ + socket->SendDataOnly(fName,MAX_STR_LENGTH); + socket->SendDataOnly(&acquisitionIndex,sizeof(acquisitionIndex)); + socket->SendDataOnly(&frameIndex,sizeof(frameIndex)); + socket->SendDataOnly(&subframenumber,sizeof(subframenumber)); + socket->SendDataOnly(retval,dataSize); + } + + delete [] retval; + delete [] origVal; + delete [] raw; + + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::jungfrau_read_frame(){ + ret=OK; + + char fName[MAX_STR_LENGTH]=""; + int acquisitionIndex = -1; + int frameIndex= -1; + int64_t currentIndex=0; + uint64_t startAcquisitionIndex=0; + uint64_t startFrameIndex=0; + strcpy(mess,"Could not read frame\n"); + + + int frameSize = JFRAU_ONE_PACKET_SIZE * packetsPerFrame; + int dataSize = JFRAU_ONE_DATA_SIZE * packetsPerFrame; + int oneDataSize = JFRAU_ONE_DATA_SIZE; + + char* raw; + char* origVal = new char[frameSize]; + char* retval = new char[dataSize]; + char* blackpacket = new char[oneDataSize]; + + for(int i=0;igetFramesCaught()){ + startAcquisitionIndex=-1; +#ifdef VERYVERBOSE + cout<<"haven't caught any frame yet"<readFrame(fName,&raw,startAcquisitionIndex,startFrameIndex); + //send garbage with -1 index to try again + if (raw == NULL){ + startAcquisitionIndex = -1; +#ifdef VERYVERBOSE + cout<<"data not ready for gui yet"<frameNumber))&0xffffff; +#ifdef VERYVERBOSE + cout << "currentIndex:" << dec << currentIndex << endl; +#endif + + int64_t currentPacket = packetsPerFrame-1; + int offsetsrc = 0; + int offsetdest = 0; + int64_t ifnum=-1; + int64_t ipnum=-1; + + while(currentPacket >= 0){ + header = (jfrau_packet_header_t*) (origVal + offsetsrc); + ifnum = (*( (uint32_t*) header->frameNumber))&0xffffff; + ipnum = (*( (uint8_t*) header->packetNumber)); + if(ifnum != currentIndex) { + cout << "current packet " << currentPacket << " Wrong Frame number " << ifnum << ", copying blank packet" << endl; + memcpy(retval+offsetdest,blackpacket,oneDataSize); + offsetdest += oneDataSize; + //no need to increase offsetsrc as all packets will be wrong + currentPacket--; + continue; + } + if(ipnum!= currentPacket){ + cout << "current packet " << currentPacket << " Wrong packet number " << ipnum << ", copying blank packet" << endl; + memcpy(retval+offsetdest,blackpacket,oneDataSize); + offsetdest += oneDataSize; + //no need to increase offsetsrc until we get the right packet + currentPacket--; + continue; + } + offsetsrc+=JFRAU_HEADER_LENGTH; + memcpy(retval+offsetdest,origVal+offsetsrc,oneDataSize); + offsetdest += oneDataSize; + offsetsrc += oneDataSize; + currentPacket--; + } + + + acquisitionIndex = (int)(currentIndex-startAcquisitionIndex); + if(acquisitionIndex == -1) + startFrameIndex = -1; + else + frameIndex = (int)(currentIndex-startFrameIndex); +#ifdef VERY_VERY_DEBUG + cout << "acquisitionIndex calculated is:" << acquisitionIndex << endl; + cout << "frameIndex calculated is:" << frameIndex << endl; + cout << "currentIndex:" << currentIndex << endl; + cout << "startAcquisitionIndex:" << startAcquisitionIndex << endl; + cout << "startFrameIndex:" << startFrameIndex << endl; +#endif + } + } + +#ifdef VERYVERBOSE + if(frameIndex!=-1){ + cout << "fName:" << fName << endl; + cout << "acquisitionIndex:" << acquisitionIndex << endl; + cout << "frameIndex:" << frameIndex << endl; + cout << "startAcquisitionIndex:" << startAcquisitionIndex << endl; + cout << "startFrameIndex:" << startFrameIndex << endl; + } +#endif + + + +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + else{ + socket->SendDataOnly(fName,MAX_STR_LENGTH); + socket->SendDataOnly(&acquisitionIndex,sizeof(acquisitionIndex)); + socket->SendDataOnly(&frameIndex,sizeof(frameIndex)); + socket->SendDataOnly(retval,dataSize); + } + + delete [] retval; + delete [] origVal; + delete [] raw; + + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::set_read_frequency(){ + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not set receiver read frequency\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + /* + else if((receiverBase->getStatus()==RUNNING) && (index >= 0)){ + ret = FAIL; + strcpy(mess,"cannot set up receiver mode when receiver is running\n"); + }*/ + else{ + if(index >= 0){ + ret = receiverBase->setFrameToGuiFrequency(index); + if(ret == FAIL) + strcpy(mess, "Could not allocate memory for listening fifo\n"); + } + retval=receiverBase->getFrameToGuiFrequency(); + if(index>=0 && retval!=index) + ret = FAIL; + } + } + +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::enable_file_write(){ + ret=OK; + int retval=-1; + int enable; + strcpy(mess,"Could not set/get enable file write\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&enable,sizeof(enable)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + if(enable >= 0) + receiverBase->setFileWriteEnable(enable); + retval=receiverBase->getFileWriteEnable(); + if(enable>=0 && enable!=retval) + ret=FAIL; + } + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + +int slsReceiverTCPIPInterface::get_id(){ + ret=OK; + int64_t retval=-1; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + retval = getReceiverVersion(); +#endif + + if(socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + +int64_t slsReceiverTCPIPInterface::getReceiverVersion(){ + int64_t retval = SVNREV; + retval= (retval <<32) | SVNDATE; + return retval; +} + + + + +int slsReceiverTCPIPInterface::start_readout(){ + ret=OK; + enum runStatus retval; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + }else{ + receiverBase->startReadout(); + retval = receiverBase->getStatus(); + if((retval == TRANSMITTING) || (retval == RUN_FINISHED) || (retval == IDLE)) + ret = OK; + else + ret = FAIL; + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + + + +int slsReceiverTCPIPInterface::set_timer() { + ret=OK; + int64_t retval = -1; + int64_t index[2]; + index[1] = -1; + strcpy(mess,"Could not set acquisition period or frame number in receiver\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + if(index[0] == FRAME_PERIOD){ + if(index[1]>=0){ + ret = receiverBase->setAcquisitionPeriod(index[1]); + if(ret == FAIL) + strcpy(mess,"Could not allocate memory for listening fifo\n"); + } + retval=receiverBase->getAcquisitionPeriod(); + }else{ + if(index[1]>=0) + receiverBase->setNumberOfFrames(index[1]); + retval=receiverBase->getNumberOfFrames(); + } + if(index[1]>=0 && retval!=index[1]) + ret = FAIL; + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL){ + if(index[0] == FRAME_PERIOD) + cout << "acquisition period:" << retval << endl; + else + cout << "frame number:" << retval << endl; + }else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::enable_compression() { + ret=OK; + int enable=-1; + int retval=-100; + strcpy(mess,"Could not enable/disable compression for receiver\n"); + + // receive arguments + if(socket->ReceiveDataOnly(&enable,sizeof(enable)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if(enable >= 0){ + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else if(receiverBase->getStatus()==RUNNING){ + strcpy(mess,"Cannot enable/disable compression while status is running\n"); + ret=FAIL; + } + else{ + if(enable >= 0) + ret = receiverBase->setDataCompressionEnable(enable); + } + } + + if(ret != FAIL){ + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + }else{ + retval = receiverBase->getDataCompressionEnable(); + if(enable >= 0 && retval != enable) + ret = FAIL; + } + } + + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + +int slsReceiverTCPIPInterface::set_detector_hostname() { + ret=OK; + char* retval = NULL; + char defaultVal[MAX_STR_LENGTH] = ""; + char hostname[MAX_STR_LENGTH]=""; + strcpy(mess,"Could not set detector hostname"); + + // receive arguments + if(socket->ReceiveDataOnly(hostname,MAX_STR_LENGTH) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + receiverBase->initialize(hostname); + retval = receiverBase->getDetectorHostname(); + if(retval == NULL){ + ret = FAIL; + } + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "hostname:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED, "%s\n", mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + if(retval == NULL) + socket->SendDataOnly(defaultVal,MAX_STR_LENGTH); + else{ + socket->SendDataOnly(retval,MAX_STR_LENGTH); + delete[] retval; + } + + //return ok/fail + return ret; +} + + + + + + +//LEO: why the receiver should set the dynamic range? +int slsReceiverTCPIPInterface::set_dynamic_range() { + ret=OK; + int retval=-1; + int dr; + strcpy(mess,"Could not set dynamic range\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&dr,sizeof(dr)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (dr>0) { + switch(dr){ + case 4: + case 8: + case 16: + case 32:break; + default: + sprintf(mess,"This dynamic range does not exist: %d\n",dr); + cprintf(RED,"%s", mess); + ret=FAIL; + break; + } + } + if(ret!=FAIL){ + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + }else{ + if(dr > 0){ + ret = receiverBase->setDynamicRange(dr); + if(ret == FAIL) + strcpy(mess, "Could not allocate memory for fifo or could not start listening/writing threads\n"); + } + retval = receiverBase->getDynamicRange(); + if(dr > 0 && retval != dr) + ret = FAIL; + else{ + dynamicrange = retval; + if(myDetectorType == EIGER){ + if(!tenGigaEnable) + packetsPerFrame = EIGER_ONE_GIGA_CONSTANT * dynamicrange * EIGER_MAX_PORTS; + else + packetsPerFrame = EIGER_TEN_GIGA_CONSTANT * dynamicrange * EIGER_MAX_PORTS; + }else if (myDetectorType == JUNGFRAU) + packetsPerFrame = JFRAU_PACKETS_PER_FRAME; + } + } + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "dynamic range" << dr << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::enable_overwrite() { + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not enable/disable overwrite\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + if(index >= 0) + receiverBase->setOverwriteEnable(index); + retval=receiverBase->getOverwriteEnable(); + if(index >=0 && retval != index) + ret = FAIL; + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "overwrite:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::enable_tengiga() { + ret=OK; + int retval=-1; + int val; + strcpy(mess,"Could not enable/disable 10Gbe\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&val,sizeof(val)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else{ + if(val >= 0) + ret = receiverBase->setTenGigaEnable(val); + retval=receiverBase->getTenGigaEnable(); + if((val >= 0) && (val != retval)) + ret = FAIL; + else + tenGigaEnable = retval; + } + } +#ifdef VERYVERBOSE + if(ret!=FAIL) + cout << "10Gbe:" << val << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::set_fifo_depth() { + ret=OK; + int value=-1; + int retval=-100; + strcpy(mess,"Could not set/get fifo depth for receiver\n"); + + // receive arguments + if(socket->ReceiveDataOnly(&value,sizeof(value)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if(value >= 0){ + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + else if(receiverBase->getStatus()==RUNNING){ + strcpy(mess,"Cannot set/get fifo depth while status is running\n"); + ret=FAIL; + } + else{ + if(value >= 0){ + ret = receiverBase->setFifoDepth(value); + } + } + } + + + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + }else{ + retval = receiverBase->getFifoDepth(); + if(value >= 0 && retval != value) + ret = FAIL; + } + + } +#endif + + if(ret==OK && socket->differentClients){ + FILE_LOG(logDEBUG) << "Force update"; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int slsReceiverTCPIPInterface::lock_receiver() { + ret=OK; + int lock; + + // receive arguments + if(socket->ReceiveDataOnly(&lock,sizeof(lock)) < 0 ){ + sprintf(mess,"Error reading from socket\n"); + cout << "Error reading from socket (lock)" << endl; + ret=FAIL; + } + // execute action if the arguments correctly arrived + if(ret==OK){ + if (lock>=0) { + if (lockStatus==0 || strcmp(socket->lastClientIP,socket->thisClientIP)==0 || strcmp(socket->lastClientIP,"none")==0) { + lockStatus=lock; + strcpy(socket->lastClientIP,socket->thisClientIP); + } else { + ret=FAIL; + sprintf(mess,"Receiver already locked by %s\n", socket->lastClientIP); + } + } + } + + if (socket->differentClients && ret==OK) + ret=FORCE_UPDATE; + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + } + else + socket->SendDataOnly(&lockStatus,sizeof(lockStatus)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::set_port() { + ret=OK; + MySocketTCP* mySocket=NULL; + char oldLastClientIP[INET_ADDRSTRLEN]; + int sd=-1; + enum runStatus p_type; /* just to get the input */ + int p_number; + + // receive arguments + if(socket->ReceiveDataOnly(&p_type,sizeof(p_type)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + cout << mess << endl; + ret=FAIL; + } + + if(socket->ReceiveDataOnly(&p_number,sizeof(p_number)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + cout << mess << endl; + ret=FAIL; + } + + // execute action if the arguments correctly arrived + if (ret==OK) { + if (socket->differentClients==1 && lockStatus==1 ) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",socket->lastClientIP); + } + else { + if (p_number<1024) { + sprintf(mess,"Too low port number %d\n", p_number); + cout << mess << endl; + ret=FAIL; + } + cout << "set port " << p_type << " to " << p_number <lastClientIP); + mySocket = new MySocketTCP(p_number); + } + if(mySocket){ + sd = mySocket->getErrorStatus(); + if (!sd){ + ret=OK; + strcpy(socket->lastClientIP,oldLastClientIP); + if (mySocket->differentClients) + ret=FORCE_UPDATE; + } else { + ret=FAIL; + sprintf(mess,"Could not bind port %d\n", p_number); + cout << mess << endl; + if (sd==-10) { + sprintf(mess,"Port %d already set\n", p_number); + cout << mess << endl; + } + } + } + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + }else { + socket->SendDataOnly(&p_number,sizeof(p_number)); + if(sd>=0){ + socket->Disconnect(); + delete socket; + socket = mySocket; + } + } + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::get_last_client_ip() { + ret=OK; + + if (socket->differentClients ) + ret=FORCE_UPDATE; + + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(socket->lastClientIP,sizeof(socket->lastClientIP)); + + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::send_update() { + ret=OK; + int ind; + char defaultVal[MAX_STR_LENGTH]=""; + char* path = NULL; + + socket->SendDataOnly(socket->lastClientIP,sizeof(socket->lastClientIP)); + + //index +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + + ind=receiverBase->getFileIndex(); + + socket->SendDataOnly(&ind,sizeof(ind)); +#endif + + //filepath +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + path = receiverBase->getFilePath(); +#endif + if(path == NULL) + socket->SendDataOnly(defaultVal,MAX_STR_LENGTH); + else{ + socket->SendDataOnly(path,MAX_STR_LENGTH); + delete[] path; + } + + + //filename +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + path = receiverBase->getFileName(); +#endif + if(path == NULL) + socket->SendDataOnly(defaultVal,MAX_STR_LENGTH); + else{ + socket->SendDataOnly(path,MAX_STR_LENGTH); + delete[] path; + } + + if (lockStatus==0) { + strcpy(socket->lastClientIP,socket->thisClientIP); + } + + return ret; + + +} + + + + + + +int slsReceiverTCPIPInterface::update_client() { + ret=OK; + if (receiverBase == NULL){ + strcpy(mess,SET_RECEIVER_ERR_MESSAGE); + ret=FAIL; + } + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cprintf(RED,"%s\n",mess); + socket->SendDataOnly(mess,sizeof(mess)); + return ret; + } + + return send_update(); +} + + + + + + + +int slsReceiverTCPIPInterface::exit_server() { + ret=GOODBYE; + socket->SendDataOnly(&ret,sizeof(ret)); + strcpy(mess,"closing server"); + socket->SendDataOnly(mess,sizeof(mess)); + cprintf(RED,"%s\n",mess); + return ret; +} + + + + + +int slsReceiverTCPIPInterface::exec_command() { + ret = OK; + char cmd[MAX_STR_LENGTH]; + char answer[MAX_STR_LENGTH]; + int sysret=0; + + // receive arguments + if(socket->ReceiveDataOnly(cmd,MAX_STR_LENGTH) < 0 ){ + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + + // execute action if the arguments correctly arrived + if (ret==OK) { +#ifdef VERYVERBOSE + cout << "executing command " << cmd << endl; +#endif + if (lockStatus==0 || socket->differentClients==0) + sysret=system(cmd); + + //should be replaced by popen + if (sysret==0) { + strcpy(answer,"Succeeded\n"); + if (lockStatus==1 && socket->differentClients==1) + sprintf(answer,"Detector locked by %s\n", socket->lastClientIP); + } else { + strcpy(answer,"Failed\n"); + ret=FAIL; + } + } else + strcpy(answer,"Could not receive the command\n"); + + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(socket->SendDataOnly(answer,MAX_STR_LENGTH) < 0){ + strcpy(mess,"Error writing to socket"); + ret=FAIL; + } + + //return ok/fail + return ret; +} + + + +/***callback functions***/ +void slsReceiverTCPIPInterface::registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){ + startAcquisitionCallBack=func; + pStartAcquisition=arg; +} + +void slsReceiverTCPIPInterface::registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){ + acquisitionFinishedCallBack=func; + pAcquisitionFinished=arg; +} + +void slsReceiverTCPIPInterface::registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){ + rawDataReadyCallBack=func; + pRawDataReady=arg; +} + + + + + diff --git a/slsReceiverSoftware/src/slsReceiverUsers.cpp b/slsReceiverSoftware/src/slsReceiverUsers.cpp new file mode 100644 index 0000000000..8a1d17f43a --- /dev/null +++ b/slsReceiverSoftware/src/slsReceiverUsers.cpp @@ -0,0 +1,45 @@ +#include "slsReceiverUsers.h" +#include "slsReceiver.h" + +slsReceiverUsers::slsReceiverUsers(int argc, char *argv[], int &success) { + receiver=new slsReceiver(argc, argv, success); +} + +slsReceiverUsers::~slsReceiverUsers() { + delete receiver; +} + +int slsReceiverUsers::start() { + return receiver->start(); +} + +void slsReceiverUsers::stop() { + receiver->stop(); +} + + +void slsReceiverUsers::closeFile(int p) { + receiver->closeFile(p); +} + +int64_t slsReceiverUsers::getReceiverVersion(){ + return receiver->getReceiverVersion(); +} + + +void slsReceiverUsers::registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){ + receiver->registerCallBackStartAcquisition(func,arg); +} + + + +void slsReceiverUsers::registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){ + receiver->registerCallBackAcquisitionFinished(func,arg); +} + + +void slsReceiverUsers::registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){ + receiver->registerCallBackRawDataReady(func,arg); +} + + diff --git a/slsReceiverSoftware/src/utilities.cpp b/slsReceiverSoftware/src/utilities.cpp new file mode 100644 index 0000000000..afb5a6c655 --- /dev/null +++ b/slsReceiverSoftware/src/utilities.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "utilities.h" + + +using namespace std; + + +int read_config_file(string fname, int *tcpip_port_no, map * configuration_map ){ + + ifstream infile; + string sLine,sargname, sargvalue; + int iline = 0; + int success = slsReceiverDefs::OK; + + + + infile.open(fname.c_str(), ios_base::in); + if (infile.is_open()) { + while(infile.good()){ + getline(infile,sLine); + iline++; + + //VERBOSE_PRINT(sLine); + + if(sLine.find('#') != string::npos) + continue; + + else if(sLine.length()<2) + continue; + + else{ + istringstream sstr(sLine); + + //parameter name + if(sstr.good()){ + sstr >> sargname; + + if (! sstr.good()) + continue; + + sstr >> sargvalue; + (*configuration_map)[sargname] = sargvalue; + } + //tcp port + if(sargname=="rx_tcpport"){ + if(sstr.good()) { + sstr >> sargname; + if(sscanf(sargname.c_str(),"%d",tcpip_port_no)) + cout<<"dataport:"< +#include "MySocketTCP.h" + +using namespace std; + +int main(){ + + char data[50000]; + int length=50000; + + unsigned short int portnum = 1952; + MySocketTCP* sock = new MySocketTCP(portnum); + + cout<<"\tReceived :"<ReceiveDataAndKeepConnection(data,23000)<ReceiveData(data,32200)<ReceiveData(data,33300)<ReceiveData(data,30000)<ReceiveData(data,3222)< +#include "MySocketTCP.h" + +using namespace std; + +int main(int argc, char *argv[]){ + + if(argc!=2){ + cout<<"Usage: send ip_addess/hostName"<SendDataAndKeepConnection(data,2000)<SendData(data,2200)<SendData(data,1200)<SendData(data,25000)<SendData(data,222)<