MIDAS
Loading...
Searching...
No Matches
feudp.cxx File Reference
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <string>
#include <vector>
#include "midas.h"
#include "mfe.h"
#include "mstrlcpy.h"
#include <sys/time.h>
Include dependency graph for feudp.cxx:

Go to the source code of this file.

Classes

struct  Source
 

Macros

#define EQ_NAME   "UDP"
 
#define EQ_EVID   1
 
#define MAX_UDP_SIZE   (0x10000)
 

Functions

int interrupt_configure (INT cmd, INT source, PTYPE adr)
 
INT poll_event (INT source, INT count, BOOL test)
 
int frontend_init ()
 Frontend initialization.
 
int frontend_exit ()
 Frontend exit.
 
int begin_of_run (int run, char *err)
 Begin of Run.
 
int end_of_run (int run, char *err)
 End of Run.
 
int pause_run (int run, char *err)
 Pause Run.
 
int resume_run (int run, char *err)
 Resume Run.
 
int frontend_loop ()
 Frontend loop.
 
int read_event (char *pevent, INT off)
 
static double GetTimeSec ()
 
int open_udp_socket (int server_port)
 
bool addr_match (const Source *s, void *addr, int addr_len)
 
int wait_udp (int socket, int msec)
 
int find_source (Source *src, const sockaddr *paddr, int addr_len)
 
int read_udp (int socket, char *buf, int bufsize, char *pbankname)
 

Variables

const charfrontend_name = "feudp"
 
const charfrontend_file_name = __FILE__
 
BOOL frontend_call_loop = TRUE
 
int display_period = 0
 
int max_event_size = 1*1024*1024
 
int max_event_size_frag = 5 * 1024 * 1024
 
int event_buffer_size = 8*1024*1024
 
BOOL equipment_common_overwrite = FALSE
 
EQUIPMENT equipment []
 
static std::vector< SourcegSrc
 
static HNDLE hKeySet
 
static int gDataSocket
 
static int gUnknownPacketCount = 0
 
static bool gSkipUnknownPackets = false
 

Macro Definition Documentation

◆ EQ_EVID

#define EQ_EVID   1

Definition at line 47 of file feudp.cxx.

◆ EQ_NAME

#define EQ_NAME   "UDP"

Definition at line 43 of file feudp.cxx.

◆ MAX_UDP_SIZE

#define MAX_UDP_SIZE   (0x10000)

Definition at line 401 of file feudp.cxx.

Function Documentation

◆ addr_match()

bool addr_match ( const Source s,
void addr,
int  addr_len 
)

Definition at line 150 of file feudp.cxx.

151{
152 int v = memcmp(&s->addr, addr, addr_len);
153#if 0
154 for (int i=0; i<addr_len; i++)
155 printf("%3d - 0x%02x 0x%02x\n", i, ((char*)&s->addr)[i], ((char*)addr)[i]);
156 printf("match %d, hostname [%s] bank [%s], status %d\n", addr_len, s->host_name.c_str(), s->bank_name, v);
157#endif
158 return v==0;
159}
char addr[128]
Definition mcnaf.cxx:104
INT i
Definition mdump.cxx:32
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
struct sockaddr addr
Definition feudp.cxx:75
std::string host_name
Definition feudp.cxx:77
char bank_name[5]
Definition feudp.cxx:76
Here is the call graph for this function:
Here is the caller graph for this function:

◆ begin_of_run()

int begin_of_run ( int  run,
char err 
)

Begin of Run.

Called every run start transition. Set equipment status in ODB, start acquisition on the modules.

Parameters
[in]run_numberNumber of the run being started
[out]errorCan be used to write a message string to midas.log

Definition at line 361 of file feudp.cxx.

362{
364 gSkipUnknownPackets = false;
365 return SUCCESS;
366}
static int gUnknownPacketCount
Definition feudp.cxx:87
static bool gSkipUnknownPackets
Definition feudp.cxx:88
#define SUCCESS
Definition mcstd.h:54

◆ end_of_run()

int end_of_run ( int  run,
char err 
)

End of Run.

Called every stop run transition. Set equipment status in ODB, stop acquisition on the modules.

Parameters
[in]run_numberNumber of the run being ended
[out]errorCan be used to write a message string to midas.log

Definition at line 368 of file feudp.cxx.

369{
370 return SUCCESS;
371}

◆ find_source()

int find_source ( Source src,
const sockaddr paddr,
int  addr_len 
)

Definition at line 198 of file feudp.cxx.

199{
200 char host[NI_MAXHOST], service[NI_MAXSERV];
201
203
204 if (status != 0) {
205 cm_msg(MERROR, "read_udp", "getnameinfo() returned %d (%s), errno %d (%s)", status, gai_strerror(status), errno, strerror(errno));
206 return -1;
207 }
208
209 char bankname[NAME_LENGTH];
210 int size = sizeof(bankname);
211
213
214 if (status == DB_NO_KEY) {
215 cm_msg(MERROR, "read_udp", "UDP packet from unknown host \"%s\"", host);
216 cm_msg(MINFO, "read_udp", "Register this host by running following commands:");
217 cm_msg(MINFO, "read_udp", "odbedit -c \"create STRING /Equipment/%s/Settings/%s\"", EQ_NAME, host);
218 cm_msg(MINFO, "read_udp", "odbedit -c \"set /Equipment/%s/Settings/%s AAAA\", where AAAA is the MIDAS bank name for this host", EQ_NAME, host);
219 return -1;
220 } else if (status != DB_SUCCESS) {
221 cm_msg(MERROR, "read_udp", "db_get_value(\"/Equipment/%s/Settings/%s\") status %d", EQ_NAME, host, status);
222 return -1;
223 }
224
225 if (strlen(bankname) != 4) {
226 cm_msg(MERROR, "read_udp", "ODB \"/Equipment/%s/Settings/%s\" should be set to a 4 character MIDAS bank name", EQ_NAME, host);
227 cm_msg(MINFO, "read_udp", "Use this command:");
228 cm_msg(MINFO, "read_udp", "odbedit -c \"set /Equipment/%s/Settings/%s AAAA\", where AAAA is the MIDAS bank name for this host", EQ_NAME, host);
229 return -1;
230 }
231
232 cm_msg(MINFO, "read_udp", "UDP packets from host \"%s\" will be stored in bank \"%s\"", host, bankname);
233
234 src->host_name = host;
235 mstrlcpy(src->bank_name, bankname, 5);
236 memcpy(&src->addr, paddr, sizeof(src->addr));
237
238 return 0;
239}
#define FALSE
Definition cfortran.h:309
#define EQ_NAME
Definition feudp.cxx:43
static HNDLE hKeySet
Definition feudp.cxx:83
#define DB_SUCCESS
Definition midas.h:631
#define DB_NO_KEY
Definition midas.h:642
#define MINFO
Definition midas.h:560
#define TID_STRING
Definition midas.h:346
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:915
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition odb.cxx:5415
HNDLE hDB
main ODB handle
Definition mana.cxx:207
#define NAME_LENGTH
Definition midas.h:272
DWORD status
Definition odbhist.cxx:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ frontend_exit()

int frontend_exit ( void  )

Frontend exit.

Runs at frontend shutdown. Disconnect hardware and set equipment status in ODB

Returns
Midas status code

Definition at line 383 of file feudp.cxx.

384{
385 return SUCCESS;
386}

◆ frontend_init()

int frontend_init ( void  )

Frontend initialization.

Runs once at application startup. We initialize the hardware and optical interfaces and set the equipment status in ODB. We also lock the frontend to once physical cpu core.

Returns
Midas status code

Definition at line 309 of file feudp.cxx.

310{
311 int status;
312
314 if (status != CM_SUCCESS) {
315 cm_msg(MERROR, "frontend_init", "Cannot connect to ODB, cm_get_experiment_database() returned %d", status);
316 return FE_ERR_ODB;
317 }
318
319 std::string path;
320 path += "/Equipment";
321 path += "/";
322 path += EQ_NAME;
323 path += "/Settings";
324
325 std::string path1 = path + "/udp_port";
326
327 int udp_port = 50005;
328 int size = sizeof(udp_port);
329 status = db_get_value(hDB, 0, path1.c_str(), &udp_port, &size, TID_INT, TRUE);
330
331 if (status != DB_SUCCESS) {
332 cm_msg(MERROR, "frontend_init", "Cannot find \"%s\", db_get_value() returned %d", path1.c_str(), status);
333 return FE_ERR_ODB;
334 }
335
336 status = db_find_key(hDB, 0, path.c_str(), &hKeySet);
337
338 if (status != DB_SUCCESS) {
339 cm_msg(MERROR, "frontend_init", "Cannot find \"%s\", db_find_key() returned %d", path.c_str(), status);
340 return FE_ERR_ODB;
341 }
342
344
345 if (gDataSocket < 0) {
346 printf("frontend_init: cannot open udp socket\n");
347 cm_msg(MERROR, "frontend_init", "Cannot open UDP socket for port %d", udp_port);
348 return FE_ERR_HW;
349 }
350
351 cm_msg(MINFO, "frontend_init", "Frontend equipment \"%s\" is ready, listening on UDP port %d", EQ_NAME, udp_port);
352 return SUCCESS;
353}
int open_udp_socket(int server_port)
Definition feudp.cxx:90
static int gDataSocket
Definition feudp.cxx:85
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3011
#define CM_SUCCESS
Definition midas.h:582
#define FE_ERR_ODB
Definition midas.h:718
#define FE_ERR_HW
Definition midas.h:719
#define TID_INT
Definition midas.h:338
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4079
#define TRUE
Definition midas.h:182
Here is the call graph for this function:

◆ frontend_loop()

int frontend_loop ( void  )

Frontend loop.

If frontend_call_loop is true, this routine gets called when the frontend is idle or once between every event.

Returns
Midas status code

Definition at line 355 of file feudp.cxx.

356{
357 ss_sleep(10);
358 return SUCCESS;
359}
INT ss_sleep(INT millisec)
Definition system.cxx:3628
Here is the call graph for this function:

◆ GetTimeSec()

static double GetTimeSec ( )
static

Definition at line 66 of file feudp.cxx.

67{
68 struct timeval tv;
70 return tv.tv_sec + 0.000001*tv.tv_usec;
71}
int gettimeofday(struct timeval *tp, void *tzp)
timeval tv
Definition msysmon.cxx:1095
Here is the call graph for this function:
Here is the caller graph for this function:

◆ interrupt_configure()

int interrupt_configure ( INT  cmd,
INT  source,
PTYPE  adr 
)

Definition at line 304 of file feudp.cxx.

305{
306 return SUCCESS;
307}

◆ open_udp_socket()

int open_udp_socket ( int  server_port)

Definition at line 90 of file feudp.cxx.

91{
92 int status;
93
94 int fd = socket(AF_INET, SOCK_DGRAM, 0);
95
96 if (fd < 0) {
97 cm_msg(MERROR, "open_udp_socket", "socket(AF_INET,SOCK_DGRAM) returned %d, errno %d (%s)", fd, errno, strerror(errno));
98 return -1;
99 }
100
101 int opt = 1;
102 status = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
103
104 if (status == -1) {
105 cm_msg(MERROR, "open_udp_socket", "setsockopt(SOL_SOCKET,SO_REUSEADDR) returned %d, errno %d (%s)", status, errno, strerror(errno));
106 return -1;
107 }
108
109 int bufsize = 8*1024*1024;
110 //int bufsize = 20*1024;
111
113
114 if (status == -1) {
115 cm_msg(MERROR, "open_udp_socket", "setsockopt(SOL_SOCKET,SO_RCVBUF) returned %d, errno %d (%s)", status, errno, strerror(errno));
116 return -1;
117 }
118
119 struct sockaddr_in local_addr;
120 memset(&local_addr, 0, sizeof(local_addr));
121
122 local_addr.sin_family = AF_INET;
123 local_addr.sin_port = htons(server_port);
124 local_addr.sin_addr.s_addr = INADDR_ANY;
125
126 status = bind(fd, (struct sockaddr *)&local_addr, sizeof(local_addr));
127
128 if (status == -1) {
129 cm_msg(MERROR, "open_udp_socket", "bind(port=%d) returned %d, errno %d (%s)", server_port, status, errno, strerror(errno));
130 return -1;
131 }
132
133 int xbufsize = 0;
134 unsigned size = sizeof(xbufsize);
135
137
138 //printf("status %d, xbufsize %d, size %d\n", status, xbufsize, size);
139
140 if (status == -1) {
141 cm_msg(MERROR, "open_udp_socket", "getsockopt(SOL_SOCKET,SO_RCVBUF) returned %d, errno %d (%s)", status, errno, strerror(errno));
142 return -1;
143 }
144
145 cm_msg(MINFO, "open_udp_socket", "UDP port %d socket receive buffer size is %d", server_port, xbufsize);
146
147 return fd;
148}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pause_run()

int pause_run ( int  run,
char err 
)

Pause Run.

Called every pause run transition.

Parameters
[in]run_numberNumber of the run being ended
[out]errorCan be used to write a message string to midas.log
Returns
Midas status code

Definition at line 373 of file feudp.cxx.

374{
375 return SUCCESS;
376}

◆ poll_event()

INT poll_event ( INT  source,
INT  count,
BOOL  test 
)

Definition at line 388 of file feudp.cxx.

389{
390 //printf("poll_event: source %d, count %d, test %d\n", source, count, test);
391
392 if (test) {
393 for (int i=0; i<count; i++)
394 ss_sleep(10);
395 return 1;
396 }
397
398 return 1;
399}
double count
Definition mdump.cxx:33
program test
Definition miniana.f:6

◆ read_event()

INT read_event ( char pevent,
INT  off 
)

Definition at line 403 of file feudp.cxx.

404{
405 char buf[MAX_UDP_SIZE];
406 char bankname[5];
407
409 if (length <= 0)
410 return 0;
411
412 bk_init32(pevent);
413 char* pdata;
414 bk_create(pevent, bankname, TID_BYTE, (void**)&pdata);
415 memcpy(pdata, buf, length);
416 bk_close(pevent, pdata + length);
417 return bk_size(pevent);
418}
#define MAX_UDP_SIZE
Definition feudp.cxx:401
int read_udp(int socket, char *buf, int bufsize, char *pbankname)
Definition feudp.cxx:241
INT bk_close(void *event, void *pdata)
Definition midas.cxx:16780
void bk_init32(void *event)
Definition midas.cxx:16469
void bk_create(void *event, const char *name, WORD type, void **pdata)
Definition midas.cxx:16561
INT bk_size(const void *event)
Definition midas.cxx:16495
#define TID_BYTE
Definition midas.h:327
Here is the call graph for this function:

◆ read_udp()

int read_udp ( int  socket,
char buf,
int  bufsize,
char pbankname 
)

Definition at line 241 of file feudp.cxx.

242{
243 if (wait_udp(socket, 100) < 1)
244 return 0;
245
246#if 0
247 static int count = 0;
248 static double tt = 0;
249 double t = GetTimeSec();
250
251 double dt = (t-tt)*1e6;
252 count++;
253 if (dt > 1000) {
254 printf("read_udp: %5d %6.0f usec\n", count, dt);
255 count = 0;
256 }
257 tt = t;
258#endif
259
260 struct sockaddr addr;
261 socklen_t addr_len = sizeof(addr);
262 int rd = recvfrom(socket, buf, bufsize, 0, &addr, &addr_len);
263
264 if (rd < 0) {
265 cm_msg(MERROR, "read_udp", "recvfrom() returned %d, errno %d (%s)", rd, errno, strerror(errno));
266 return -1;
267 }
268
269 for (unsigned i=0; i<gSrc.size(); i++) {
270 if (addr_match(&gSrc[i], &addr, addr_len)) {
272 //printf("rd %d, bank [%s]\n", rd, pbankname);
273 return rd;
274 }
275 }
276
278 return -1;
279
280 Source sss;
281
283
284 if (status < 0) {
285
287
288 if (gUnknownPacketCount > 10) {
289 gSkipUnknownPackets = true;
290 cm_msg(MERROR, "read_udp", "further messages are now suppressed...");
291 return -1;
292 }
293
294 return -1;
295 }
296
297 gSrc.push_back(sss);
298
299 mstrlcpy(pbankname, sss.bank_name, 5);
300
301 return rd;
302}
bool addr_match(const Source *s, void *addr, int addr_len)
Definition feudp.cxx:150
int find_source(Source *src, const sockaddr *paddr, int addr_len)
Definition feudp.cxx:198
static double GetTimeSec()
Definition feudp.cxx:66
int wait_udp(int socket, int msec)
Definition feudp.cxx:161
static std::vector< Source > gSrc
Definition feudp.cxx:80
char bank_name[4]
Definition mdump.cxx:26
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resume_run()

int resume_run ( int  run,
char err 
)

Resume Run.

Called every resume run transition.

Parameters
[in]run_numberNumber of the run being ended
[out]errorCan be used to write a message string to midas.log
Returns
Midas status code

Definition at line 378 of file feudp.cxx.

379{
380 return SUCCESS;
381}

◆ wait_udp()

int wait_udp ( int  socket,
int  msec 
)

Definition at line 161 of file feudp.cxx.

162{
163 int status;
165 struct timeval timeout;
166
167 FD_ZERO(&fdset);
169
170 timeout.tv_sec = msec/1000;
171 timeout.tv_usec = (msec%1000)*1000;
172
173 status = select(socket+1, &fdset, NULL, NULL, &timeout);
174
175#ifdef EINTR
176 if (status < 0 && errno == EINTR) {
177 return 0; // watchdog interrupt, try again
178 }
179#endif
180
181 if (status < 0) {
182 cm_msg(MERROR, "wait_udp", "select() returned %d, errno %d (%s)", status, errno, strerror(errno));
183 return -1;
184 }
185
186 if (status == 0) {
187 return 0; // timeout
188 }
189
190 if (FD_ISSET(socket, &fdset)) {
191 return 1; // have data
192 }
193
194 // timeout
195 return 0;
196}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ display_period

int display_period = 0

Definition at line 26 of file feudp.cxx.

◆ equipment

EQUIPMENT equipment[]
Initial value:
= {
{ EQ_NAME,
{EQ_EVID, 0, "SYSTEM",
EQ_MULTITHREAD, 0, "MIDAS",
50, 0, 0, 0,
"", "", "",}, read_event,
},
{""}
}
int read_event(char *pevent, INT off)
Definition feudp.cxx:403
#define EQ_EVID
Definition feudp.cxx:47
#define EQ_MULTITHREAD
Definition midas.h:417
#define RO_ALWAYS
Definition midas.h:436

Definition at line 52 of file feudp.cxx.

52 {
53 { EQ_NAME, /* equipment name */
54 {EQ_EVID, 0, "SYSTEM", /* event ID, trigger mask, Evbuf */
55 EQ_MULTITHREAD, 0, "MIDAS", /* equipment type, EventSource, format */
56 TRUE, RO_ALWAYS, /* enabled?, WhenRead? */
57 50, 0, 0, 0, /* poll[ms], Evt Lim, SubEvtLim, LogHist */
58 "", "", "",}, read_event, /* readout routine */
59 },
60 {""}
61};

◆ equipment_common_overwrite

BOOL equipment_common_overwrite = FALSE

Definition at line 50 of file feudp.cxx.

◆ event_buffer_size

int event_buffer_size = 8*1024*1024

Definition at line 29 of file feudp.cxx.

◆ frontend_call_loop

BOOL frontend_call_loop = TRUE

Definition at line 25 of file feudp.cxx.

◆ frontend_file_name

const char* frontend_file_name = __FILE__

Definition at line 23 of file feudp.cxx.

◆ frontend_name

const char* frontend_name = "feudp"

Definition at line 22 of file feudp.cxx.

◆ gDataSocket

int gDataSocket
static

Definition at line 85 of file feudp.cxx.

◆ gSkipUnknownPackets

bool gSkipUnknownPackets = false
static

Definition at line 88 of file feudp.cxx.

◆ gSrc

std::vector<Source> gSrc
static

Definition at line 80 of file feudp.cxx.

◆ gUnknownPacketCount

int gUnknownPacketCount = 0
static

Definition at line 87 of file feudp.cxx.

◆ hKeySet

HNDLE hKeySet
static

Definition at line 83 of file feudp.cxx.

◆ max_event_size

int max_event_size = 1*1024*1024

Definition at line 27 of file feudp.cxx.

◆ max_event_size_frag

int max_event_size_frag = 5 * 1024 * 1024

Definition at line 28 of file feudp.cxx.