MIDAS
Loading...
Searching...
No Matches
mevb.cxx File Reference
#include <stdio.h>
#include "midas.h"
#include "mevb.h"
#include "msystem.h"
#include "mdsupport.h"
#include "mfe.h"
Include dependency graph for mevb.cxx:

Go to the source code of this file.

Macros

#define SERVER_CACHE_SIZE   100000 /* event cache before buffer */
 
#define ODB_UPDATE_TIME   1000 /* 1 seconds for ODB update */
 
#define DEFAULT_FE_TIMEOUT   60000 /* 60 seconds for watchdog timeout */
 
#define TIMEOUT_ABORT   300 /* seconds waiting for data before aborting run */
 
#define EQUIPMENT_STATISTICS_STR   "\Events sent = DOUBLE : 0\n\Events per sec. = DOUBLE : 0\n\kBytes per sec. = DOUBLE : 0\n\"
 

Functions

INT handFlush (void)
 
INT source_booking (void)
 
INT source_unbooking (void)
 
INT close_buffers (void)
 
INT source_scan (INT fmt, EQUIPMENT_INFO *eq_info)
 
INT eb_mfragment_add (char *pdest, char *psrce, INT *size)
 
INT eb_yfragment_add (char *pdest, char *psrce, INT *size)
 
INT eb_begin_of_run (INT, char *, char *)
 
INT eb_end_of_run (INT, char *)
 
INT eb_user (INT, BOOL mismatch, EBUILDER_CHANNEL *, EVENT_HEADER *, void *, INT *)
 
INT load_fragment (void)
 
INT scan_fragment (void)
 
INT ebuilder_init (void)
 
INT ebuilder_exit (void)
 
INT ebuilder_loop (void)
 
INT md_event_swap (INT fmt, void *pevt)
 
INT register_equipment (void)
 
INT tr_start (INT rn, char *error)
 
INT tr_resume (INT rn, char *error)
 
INT tr_pause (INT rn, char *error)
 
INT tr_stop (INT rn, char *error)
 
void free_event_buffer (INT nfrag)
 
int main (int argc, char **argv)
 

Variables

EBUILDER_SETTINGS ebset
 
EBUILDER_CHANNEL ebch [MAX_CHANNELS]
 
INT run_state
 
INT run_number
 
DWORD last_time
 
DWORD actual_time
 
DWORD actual_millitime
 
char host_name [HOST_NAME_LENGTH]
 
char expt_name [NAME_LENGTH]
 
char buffer_name [NAME_LENGTH]
 
INT nfragment
 
chardest_event
 
HNDLE hDB
 main ODB handle
 
HNDLE hKey
 
HNDLE hStatKey
 
HNDLE hSubkey
 
HNDLE hEqKey
 
HNDLE hESetKey
 
BOOL debug = FALSE
 debug printouts
 
BOOL debug1 = FALSE
 
BOOL wheel = FALSE
 
char bars [] = "|\\-/"
 
int i_bar
 
BOOL abort_requested = FALSE
 
BOOL stop_requested = TRUE
 
DWORD stop_time = 0
 
DWORD request_stop_time = 0
 
INT(* meb_fragment_add )(char *, char *, INT *)
 
BOOL frontend_call_loop
 
INT max_event_size
 maximum event size produced by this frontend
 
INT max_event_size_frag
 maximum event size for fragmented events (EQ_FRAGMENTED)
 
INT event_buffer_size
 buffer size to hold events
 
INT display_period
 a frontend status page is displayed with this frequency in ms
 
EQUIPMENT equipment []
 Main structure for midas equipment.
 
static int waiting_for_stop = FALSE
 

Macro Definition Documentation

◆ DEFAULT_FE_TIMEOUT

#define DEFAULT_FE_TIMEOUT   60000 /* 60 seconds for watchdog timeout */

Definition at line 28 of file mevb.cxx.

◆ EQUIPMENT_STATISTICS_STR

#define EQUIPMENT_STATISTICS_STR   "\Events sent = DOUBLE : 0\n\Events per sec. = DOUBLE : 0\n\kBytes per sec. = DOUBLE : 0\n\"

Definition at line 86 of file mevb.cxx.

◆ ODB_UPDATE_TIME

#define ODB_UPDATE_TIME   1000 /* 1 seconds for ODB update */

Definition at line 26 of file mevb.cxx.

◆ SERVER_CACHE_SIZE

#define SERVER_CACHE_SIZE   100000 /* event cache before buffer */

dox

Definition at line 24 of file mevb.cxx.

◆ TIMEOUT_ABORT

#define TIMEOUT_ABORT   300 /* seconds waiting for data before aborting run */

Definition at line 32 of file mevb.cxx.

Function Documentation

◆ close_buffers()

INT close_buffers ( void  )

Definition at line 935 of file mevb.cxx.

936{
937 INT status;
938 char error[256];
939 EQUIPMENT *eq;
940
941 eq = &equipment[0];
942
943 /* Flush local destination cache */
944 bm_flush_cache(equipment[0].buffer_handle, BM_WAIT);
945 /* Call user function */
947 /* Cleanup buffers */
948 handFlush();
949 /* Detach all source from midas */
951
952 /* Compose message */
954 sprintf(error, "Run %d Stop after %1.0lf + %d events sent DT:%d[ms]",
955 run_number, eq->stats.events_sent, eq->events_sent, stop_time);
956 cm_msg(MINFO, "close_buffers", "%s", error);
957
960 return status;
961}
#define FALSE
Definition cfortran.h:309
INT bm_flush_cache(int buffer_handle, int timeout_msec)
Definition midas.cxx:10207
#define STATE_STOPPED
Definition midas.h:305
#define MINFO
Definition midas.h:560
#define BM_WAIT
Definition midas.h:365
DWORD ss_millitime()
Definition system.cxx:3393
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:915
std::vector< FMT_ID > eq
Definition mdump.cxx:55
INT run_number
Definition mevb.cxx:38
BOOL abort_requested
Definition mevb.cxx:54
INT handFlush(void)
Definition mevb.cxx:786
INT source_unbooking(void)
Definition mevb.cxx:901
INT run_state
Definition mevb.cxx:37
INT eb_end_of_run(INT, char *)
Definition ebuser.cxx:121
DWORD stop_time
Definition mevb.cxx:55
EQUIPMENT equipment[]
Main structure for midas equipment.
Definition feudp.cxx:52
DWORD request_stop_time
Definition mevb.cxx:55
int INT
Definition midas.h:129
DWORD status
Definition odbhist.cxx:39
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ eb_begin_of_run()

INT eb_begin_of_run ( INT  rn,
char UserField,
char error 
)

Hook to the event builder task at PreStart transition.

Parameters
rnrun number
UserFieldargument from /Ebuilder/Settings
errorerror string to be passed back to the system.
Returns
EB_SUCCESS

Definition at line 106 of file ebuser.cxx.

107{
108 printf("In eb_begin_of_run for run:%d User_field:%s \n", rn, UserField);
110 return EB_SUCCESS;
111}
INT lModulo
Global var for testing passed at BOR.
Definition ebuser.cxx:48
#define EB_SUCCESS
Definition mevb.h:57
INT rn
Definition mstat.cxx:30
Here is the caller graph for this function:

◆ eb_end_of_run()

INT eb_end_of_run ( INT  rn,
char error 
)

Hook to the event builder task at completion of event collection after receiving the Stop transition.

Parameters
rnrun number
errorerror string to be passed back to the system.
Returns
EB_SUCCESS

Definition at line 121 of file ebuser.cxx.

122{
123 printf("In eb_end_of_run\n");
124 return EB_SUCCESS;
125}
Here is the caller graph for this function:

◆ eb_mfragment_add()

INT eb_mfragment_add ( char pdest,
char psrce,
INT size 
)

Definition at line 473 of file mevb.cxx.

474{
476 char *psdata, *pddata;
477 INT bksize;
478
479 /* Condition for new EVENT the data_size should be ZERO */
480 *size = ((EVENT_HEADER *) pdest)->data_size;
481
482 /* destination pointer */
483 pddata = pdest + *size + sizeof(EVENT_HEADER);
484
485 if (*size) {
486 /* NOT the first fragment */
487
488 /* Swap event source if necessary */
489 psbh = (BANK_HEADER *) (((EVENT_HEADER *) psrce) + 1);
491
492 /* source pointer */
493 psbh = (BANK_HEADER *) (((EVENT_HEADER *) psrce) + 1);
494 psdata = (char *) (psbh + 1);
495
496 /* copy all banks without the bank header */
497 bksize = psbh->data_size;
498
499 /* copy */
501
502 /* update event size */
503 ((EVENT_HEADER *) pdest)->data_size += bksize;
504
505 /* update bank size */
506 pdbh = (BANK_HEADER *) (((EVENT_HEADER *) pdest) + 1);
507 pdbh->data_size += bksize;
508
509 *size = ((EVENT_HEADER *) pdest)->data_size;
510 } else {
511 /* First event without the event header but with the
512 bank header as the size is zero */
513 *size = ((EVENT_HEADER *) psrce)->data_size;
514
515 /* Swap event if necessary */
516 psbh = (BANK_HEADER *) (((EVENT_HEADER *) psrce) + 1);
518
519 /* copy first fragment */
520 memcpy(pddata, psbh, *size);
521
522 /* update destination event size */
523 ((EVENT_HEADER *) pdest)->data_size = *size;
524 }
525 return CM_SUCCESS;
526}
INT bk_swap(void *event, BOOL force)
Definition midas.cxx:17157
#define CM_SUCCESS
Definition midas.h:582
DWORD data_size
Definition midas.h:1211
Here is the call graph for this function:
Here is the caller graph for this function:

◆ eb_user()

INT eb_user ( INT  nfrag,
BOOL  mismatch,
EBUILDER_CHANNEL ebch,
EVENT_HEADER pheader,
void pevent,
INT dest_size 
)

Hook to the event builder task after the reception of all fragments of the same serial number. The destination event has already the final EVENT_HEADER setup with the data size set to 0. It is than possible to add private data at this point using the proper bank calls. Therefore any new banks created within eb_user will be appearing before the collected banks from the fragments. When using the eb_user with the ODB flag "user build=y" (equipments/EB/settings) the automatic event builder is skipped. This allow the user to extract selectively from the different fragments the appropriate banks and compose the final destination event. In order to do so, the function "bk_copy(pevent, ebch[i].pfragment, bankname)" will copy a particular bank from a given fragment.

Note: It exists two Midas event format to address bank size less than 32KB and larger bank size <4GB. This distinction is done by the call bk_init(pevent) for the small bank size and bk_init32(pevent) for large bank size. Within an experiment, this declaration has to be consistant. Therefore the bk_init in the eb_user should follow as well the type of the frontends.

The ebch[] array structure points to nfragment channel structure with the following content:

typedef struct {
char name[32]; // Fragment name (Buffer name).
DWORD serial; // Serial fragment number.
char *pfragment; // Pointer to fragment (EVENT_HEADER *)
...
unsigned int DWORD
Definition mcstd.h:51
#define name(x)
Definition midas_macro.h:24
INT serial
Definition minife.c:20

The correct code for including your own MIDAS bank is shown below where TID_xxx is one of the valid Bank type starting with TID_ for midas format bank_name is a 4 character descriptor. pdata has to be declared accordingly with the bank type. Refers to the ebuser.c source code for further description.

It is not possible to mix within the same destination event different event format! No bk_swap performed when user build is requested.

// Event is empty, fill it with BANK_HEADER
// If you need to add your own bank at this stage
// Need to match the decalration in the Frontends.
bk_init(pevent);
// bk_init32(pevent);
*pdata++ = ...;
*dest_size = bk_close(pevent, pdata);
pheader->data_size = *dest_size + sizeof(EVENT_HEADER);
INT bk_close(void *event, void *pdata)
Definition midas.cxx:16780
void bk_init(void *event)
Definition midas.cxx:16406
void bk_create(void *event, const char *name, WORD type, void **pdata)
Definition midas.cxx:16561
char bank_name[4]
Definition mdump.cxx:26
Parameters
nfragNumber of fragment.
mismatchMidas Serial number mismatch flag.
ebchStructure to all the fragments.
pheaderDestination pointer to the header.
peventDestination pointer to the bank header.
dest_sizeDestination event size in bytes.
Returns
EB_SUCCESS

Definition at line 192 of file ebuser.cxx.

194{
196 DWORD *pdata;
197
198
199 //
200 // Do some extra fragment consistency check
201 if (mismatch){
202 printf("Serial number do not match across fragments\n");
203 for (i = 0; i < nfrag; i++) {
204 serial = ((EVENT_HEADER *) ebch[i].pfragment)->serial_number;
205 printf("Ser[%i]:%d ", i + 1, serial);
206 }
207 printf("\n");
208 return EB_USER_ERROR;
209 }
210
211 //
212 // Include my own bank
213 bk_init(pevent);
214 bk_create(pevent, "MYOW", TID_DWORD, (void**)&pdata);
215 for (i = 0; i < nfrag; i++) {
216 if (ebset.preqfrag[i]) { // if channel enable
217 *pdata++ = ((EVENT_HEADER *) ebch[i].pfragment)->serial_number;
218 *pdata++ = ((EVENT_HEADER *) ebch[i].pfragment)->time_stamp;
219 }
220 }
221 *dest_size = bk_close(pevent, pdata);
222 pheader->data_size = *dest_size + sizeof(EVENT_HEADER);
223
224 // Copy the bank TC01 if found from fragment0 to the destination
225 status = bk_copy((char*)pevent, ebch[0].pfragment, "TC01");
226 if (status == EB_BANK_NOT_FOUND) {
227 printf("bank TC01 not found\n");
228 }
229
230 // Destination access
231 // dest_serial = pheader->serial_number;
232 // printf("DSer#:%d ", dest_serial);
233
234 // Stop run if condition requires
235 // if (dest_serial == 505) return EB_USER_ERROR;
236
237 // Skip event if condition requires
238 // if (dest_serial == 505) return EB_SKIP;
239
240 //
241 // Loop over fragments.
242 if (debug) {
243 for (i = 0; i < nfrag; i++) {
244 if (1) {
245 if (ebset.preqfrag[i]) { // printf if channel enable
246 frag_size = ((EVENT_HEADER *) ebch[i].pfragment)->data_size;
247 serial = ((EVENT_HEADER *) ebch[i].pfragment)->serial_number;
248 printf("Frg#:%d Dsz:%d Ser:%d ", i, frag_size, serial);
249 // For Data fragment Access.
250 // psrcData = (DWORD *) (((EVENT_HEADER *) ebch[i].pfragment) + 1);
251 }
252 }
253 }
254 printf("\n");
255 }
256 return EB_SUCCESS;
257}
EBUILDER_SETTINGS ebset
Definition mevb.cxx:34
BOOL debug
Definition mana.cxx:254
INT bk_copy(char *pevent, char *psrce, const char *bkname)
Definition midas.cxx:16604
#define TID_DWORD
Definition midas.h:336
INT i
Definition mdump.cxx:32
EBUILDER_CHANNEL ebch[MAX_CHANNELS]
Definition mevb.cxx:35
#define EB_BANK_NOT_FOUND
Definition mevb.h:63
#define EB_USER_ERROR
Definition mevb.h:60
BOOL * preqfrag
Definition mevb.h:32
DWORD data_size
Definition midas.h:856
Here is the call graph for this function:
Here is the caller graph for this function:

◆ eb_yfragment_add()

INT eb_yfragment_add ( char pdest,
char psrce,
INT size 
)

Definition at line 529 of file mevb.cxx.

530{
531 /* pdest : EVENT_HEADER pointer
532 psrce : EVENT_HEADER pointer
533 Keep pbkh for later incrementation
534 */
535 char *psdata, *pddata;
536 DWORD *pslrl, *pdlrl;
538
539 /* Condition for new EVENT the data_size should be ZERO */
540 *size = ((EVENT_HEADER *) pdest)->data_size;
541
542 /* destination pointer skip the header as it has been already
543 composed and the usere may have modified it on purpose (Midas Control) */
544 pddata = pdest + *size + sizeof(EVENT_HEADER);
545
546 /* the Midas header is present for logger */
547 if (*size) { /* already filled with a fragment */
548
549 /* source pointer: number of DWORD (lrl included) */
550 pslrl = (DWORD *) (((EVENT_HEADER *) psrce) + 1);
551
552 /* Swap event if necessary */
554
555 /* copy done in bytes, do not include LRL */
556 psdata = (char *) (pslrl + 1);
557
558 /* copy size in I*4 (lrl included, remove it) */
559 i4frgsize = (*pslrl);
560 i1frgsize = 4 * i4frgsize;
561
562 /* append fragment */
564
565 /* update Midas header event size */
566 ((EVENT_HEADER *) pdest)->data_size += i1frgsize;
567
568 /* update LRL size (I*4) */
569 pdlrl = (DWORD *) (((EVENT_HEADER *) pdest) + 1);
570 *pdlrl += i4frgsize;
571
572 /* Return event size in bytes */
573 *size = ((EVENT_HEADER *) pdest)->data_size;
574 } else { /* new destination event */
575 /* The composed event has already the MIDAS header.
576 which may have been modified by the user in ebuser.c
577 Will be stripped by the logger (YBOS).
578 Copy the first full event ( no EVID suppression )
579 First event (without the event header) */
580
581 /* source pointer */
582 pslrl = (DWORD *) (((EVENT_HEADER *) psrce) + 1);
583
584 /* Swap event if necessary */
586
587 /* size in byte from the source midas header */
588 *size = ((EVENT_HEADER *) psrce)->data_size;
589
590 /* copy first fragment */
591 memcpy(pddata, (char *) pslrl, *size);
592
593 /* update destination Midas header event size */
594 ((EVENT_HEADER *) pdest)->data_size += *size;
595
596 }
597 return CM_SUCCESS;
598}
#define FORMAT_MIDAS
Definition midas.h:311
INT md_event_swap(INT fmt, void *pevt)
Here is the call graph for this function:

◆ ebuilder_exit()

INT ebuilder_exit ( void  )
extern

Definition at line 87 of file ebuser.cxx.

88{
89 return EB_SUCCESS;
90}
Here is the caller graph for this function:

◆ ebuilder_init()

INT ebuilder_init ( void  )
extern

Definition at line 79 of file ebuser.cxx.

80{
83 return EB_SUCCESS;
84}
Here is the caller graph for this function:

◆ ebuilder_loop()

INT ebuilder_loop ( void  )
extern

Definition at line 93 of file ebuser.cxx.

94{
95 return EB_SUCCESS;
96}

◆ free_event_buffer()

void free_event_buffer ( INT  nfrag)

Definition at line 774 of file mevb.cxx.

775{
776 INT i;
777 for (i = 0; i < nfrag; i++) {
778 if (ebch[i].pfragment) {
779 free(ebch[i].pfragment);
780 ebch[i].pfragment = NULL;
781 }
782 }
783}
char * pfragment
Definition mevb.h:54
Here is the caller graph for this function:

◆ handFlush()

INT handFlush ( void  )

Definition at line 786 of file mevb.cxx.

787{
788 int i, size, status;
789 char strout[256];
790
791 /* Do Hand flush until better way to garantee the input buffer to be empty */
792 if (debug)
793 printf("Hand flushing system buffer... \n");
794 for (i = 0; i < nfragment; i++) {
795 do {
796 status = 0;
797 if (ebset.preqfrag[i]) {
798 size = max_event_size;
799 status = bm_receive_event(ebch[i].hBuf, ebch[i].pfragment, &size, BM_NO_WAIT);
800 if (debug1) {
802 "booking:Hand flush bm_receive_event[%d] hndle:%d stat:%d Last Ser:%d",
803 i, ebch[i].hBuf, status, ((EVENT_HEADER *) ebch[i].pfragment)->serial_number);
804 printf("%s\n", strout);
805 }
806 }
807 } while (status == BM_SUCCESS);
808 }
809
810 /* Empty source buffer */
812 if (status != BM_SUCCESS)
813 cm_msg(MERROR, "handFlush", "bm_empty_buffers failure [%d]", status);
815 return status;
816}
INT bm_empty_buffers()
Definition midas.cxx:11240
INT bm_receive_event(INT buffer_handle, void *destination, INT *buf_size, int timeout_msec)
Definition midas.cxx:10650
#define BM_SUCCESS
Definition midas.h:605
#define BM_NO_WAIT
Definition midas.h:366
#define MERROR
Definition midas.h:559
INT max_event_size
maximum event size produced by this frontend
Definition mfed.cxx:30
EBUILDER_SETTINGS ebset
Definition mevb.cxx:34
BOOL debug
debug printouts
Definition mevb.cxx:49
BOOL debug1
Definition mevb.cxx:49
INT nfragment
Definition mevb.cxx:46
#define serial_number
HNDLE hBuf
Definition minife.c:23
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_fragment()

INT load_fragment ( void  )

Definition at line 230 of file mevb.cxx.

231{
232 INT i, size, type;
235 KEY key;
236 char buffer[NAME_LENGTH];
237 char format[8];
238
239 /* Get equipment pointer, only one eqp for now */
240 eq_info = &equipment[0].info;
241
242 /* Scan Equipment/Common listing */
243 if (db_find_key(hDB, 0, "Equipment", &hEqKey) != DB_SUCCESS) {
244 cm_msg(MINFO, "load_fragment", "Equipment listing not found");
245 return EB_ERROR;
246 }
247
248 /* Scan the Equipment list for fragment info collection */
249 for (i = 0, nfragment = 0;; i++) {
251 if (!hSubkey)
252 break;
254 if (key.type == TID_KEY) {
255 /* Equipment name */
256 if (debug)
257 printf("Equipment name:%s\n", key.name);
258 /* Check if equipment is EQ_EB */
259 size = sizeof(INT);
260 db_get_value(hDB, hSubkey, "common/type", &type, &size, TID_INT, 0);
261 size = sizeof(buffer);
262 db_get_value(hDB, hSubkey, "common/Buffer", buffer, &size, TID_STRING, 0);
263 size = sizeof(format);
264 db_get_value(hDB, hSubkey, "common/Format", format, &size, TID_STRING, 0);
265 /* Check if equipment match EB requirements */
266 // if (debug)
267 // printf("Equipment name: %s, Type: 0x%x, Buffer: %s, Format: %s\n",
268 // key.name, type, buffer, format);
269 if ((type & EQ_EB)
270 && (strncmp(buffer, buffer_name, strlen(buffer_name)) == 0)
271 && (strncmp(format, eq_info->format, strlen(format)) == 0)) {
272 /* match=> fill internal eb structure */
273 strcpy(ebch[nfragment].format, format);
274 strcpy(ebch[nfragment].buffer, buffer);
275 size = sizeof(WORD);
276 db_get_value(hDB, hSubkey, "common/Trigger Mask", &ebch[nfragment].trigger_mask, &size, TID_WORD,
277 0);
278 size = sizeof(WORD);
279 db_get_value(hDB, hSubkey, "common/Event ID", &ebch[nfragment].event_id, &size, TID_WORD, 0);
280 printf("Fragment %d: Equipment name %s, evID %d, buffer %s\n",nfragment,key.name, ebch[nfragment].event_id, buffer);
281 // printf("Fragment %d: Equipment name %s, evID %d, buffer %s\n",key.name, ebch[nfragment].event_id, buffer);
282 nfragment++;
283 }
284 }
285 }
286
287 if (nfragment > 1)
288 printf("Found %d fragments for event building\n", nfragment);
289 else
290 printf("Found one fragment for event building\n");
291
292 /* Point to the Ebuilder settings */
293 /* Set fragment_add function based on the format */
294 if (equipment[0].format == FORMAT_MIDAS)
296 else {
297 cm_msg(MERROR, "load_fragment", "Unknown data format \"%s\"", format);
298 return EB_ERROR;
299 }
300
301 /* allocate destination event buffer */
302 dest_event = (char *) malloc(nfragment * (max_event_size + sizeof(EVENT_HEADER)));
304 if (dest_event == NULL) {
305 cm_msg(MERROR, "load_fragment", "%s: Not enough memory for event buffer", frontend_name);
306 return EB_ERROR;
307 }
308 return EB_SUCCESS;
309}
#define DB_SUCCESS
Definition midas.h:631
unsigned short int WORD
Definition mcstd.h:49
#define TID_KEY
Definition midas.h:349
#define EQ_EB
Definition midas.h:421
#define TID_WORD
Definition midas.h:332
#define TID_STRING
Definition midas.h:346
#define TID_INT
Definition midas.h:338
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
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6019
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4079
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5586
INT type
Definition mana.cxx:269
KEY key
Definition mdump.cxx:34
INT(* meb_fragment_add)(char *, char *, INT *)
Definition mevb.cxx:57
HNDLE hEqKey
Definition mevb.cxx:48
char buffer_name[NAME_LENGTH]
Definition mevb.cxx:45
INT eb_mfragment_add(char *pdest, char *psrce, INT *size)
Definition mevb.cxx:473
HNDLE hSubkey
Definition mevb.cxx:48
HNDLE hDB
main ODB handle
Definition mevb.cxx:48
char * dest_event
Definition mevb.cxx:47
#define EB_ERROR
Definition mevb.h:59
const char * frontend_name
The frontend name (client name) as seen by other MIDAS clients.
Definition feudp.cxx:22
INT HNDLE
Definition midas.h:132
#define NAME_LENGTH
Definition midas.h:272
#define trigger_mask
#define event_id
WORD event_id
Definition mevb.h:45
Definition midas.h:1026
DWORD type
Definition midas.h:1027
char name[NAME_LENGTH]
Definition midas.h:1029
EQUIPMENT_INFO info
Definition midas.h:1174
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 1140 of file mevb.cxx.

1141{
1142 INT status, size, rstate;
1143 int i;
1144 BOOL daemon = FALSE;
1145 HNDLE hEqkey;
1147 char str[128];
1148 int auto_restart = 0;
1149 int restart_count = 0;
1150
1151 /* init structure */
1152 memset(&ebch[0], 0, sizeof(ebch));
1153
1154 /* set default */
1156
1157 /* set default buffer name */
1158 strcpy(buffer_name, "SYSTEM");
1159
1160 /* get parameters */
1161 for (i = 1; i < argc; i++) {
1162 if (argv[i][0] == '-' && argv[i][1] == 'd')
1163 debug = TRUE;
1164 else if (argv[i][0] == '-' && argv[i][1] == 'D')
1165 daemon = TRUE;
1166 else if (argv[i][0] == '-' && argv[i][1] == 'w')
1167 wheel = TRUE;
1168 else if (argv[i][0] == '-') {
1169 if (i + 1 >= argc || argv[i + 1][0] == '-')
1170 goto usage;
1171 if (strncmp(argv[i], "-e", 2) == 0)
1172 strcpy(expt_name, argv[++i]);
1173 else if (strncmp(argv[i], "-h", 2) == 0)
1174 strcpy(host_name, argv[++i]);
1175 else if (strncmp(argv[i], "-b", 2) == 0)
1176 strcpy(buffer_name, argv[++i]);
1177 } else {
1178 usage:
1179 printf("usage: mevb [-h <Hostname>] [-e <Experiment>] [-b <buffername>] [-d] [-w] [-D]\n");
1180 printf(" [-h <Hostname>] Host where midas experiment is running on\n");
1181 printf(" [-e <Experiment>] Midas experiment if more than one exists\n");
1182 printf(" [-b <buffername>] Specify evnet buffer name, use \"SYSTEM\" by default\n");
1183 printf(" [-d] Print debugging output\n");
1184 printf(" [-w] Show wheel\n");
1185 printf(" [-D] Start as a daemon\n");
1186 return 0;
1187 }
1188 }
1189
1190 printf("MIDAS example event builder. Press \"!\" to exit.\n");
1191
1192 if (daemon) {
1193 printf("Becoming a daemon...\n");
1195 }
1196
1197 /* Connect to experiment */
1199 if (status != CM_SUCCESS) {
1200 ss_sleep(5000);
1201 goto exit;
1202 }
1203
1204 if (debug)
1206
1207 /* Connect to ODB */
1209 if (status != EB_SUCCESS) {
1210 ss_sleep(5000);
1211 goto exit;
1212 }
1213
1214 /* check if Ebuilder is already running */
1216 if (status == CM_SUCCESS) {
1217 cm_msg(MERROR, "main", "%s running already!.", frontend_name);
1219 goto exit;
1220 }
1221
1222 /* Check if run in progess if so abort */
1223 size = sizeof(rstate);
1224 db_get_value(hDB, 0, "/Runinfo/State", &rstate, &size, TID_INT, FALSE);
1225 if (rstate != STATE_STOPPED) {
1226 cm_msg(MERROR, "main", "Run in Progress, EBuilder aborted!.");
1228 goto exit;
1229 }
1230
1231 if (ebuilder_init() != SUCCESS) {
1233 /* let user read message before window might close */
1234 ss_sleep(5000);
1235 goto exit;
1236 }
1237
1238 /* Register single equipment */
1240 if (status != EB_SUCCESS) {
1241 ss_sleep(5000);
1242 goto exit;
1243 }
1244
1245 /* Load Fragment info */
1247 if (status != EB_SUCCESS) {
1248 ss_sleep(5000);
1249 goto exit;
1250 }
1251
1252 /* Register transition for reset counters */
1254 return status;
1256 return status;
1258 goto exit;
1260 goto exit;
1261
1262 restart:
1263
1264 /* Set Initial EB/Settings */
1265 sprintf(str, "/Equipment/%s/Settings", equipment[0].name);
1266 if (db_find_key(hDB, 0, str, &hEqkey) != DB_SUCCESS) {
1268 }
1269
1270 if (auto_restart && restart_count > 0)
1271 {
1272 int run_number = 0;
1273 int size = sizeof(run_number);
1274 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
1275 assert(status == SUCCESS);
1276
1277 cm_msg(MINFO, frontend_name, "Restart the run!");
1278
1280 }
1281
1282 /* initialize ss_getchar */
1283 ss_getchar(0);
1284
1285 /* Scan fragments... will stay in */
1287 printf("%s-Out of scan_fragment\n", frontend_name);
1288
1289 /* Detach all source from midas */
1290 printf("%s-Unbooking\n", frontend_name);
1292
1293 ebuilder_exit();
1294
1295 auto_restart = 0;
1296 db_get_value(hDB, 0, "/Logger/Auto restart", &auto_restart, &size, TID_BOOL, FALSE);
1297
1298 cm_msg(MINFO, frontend_name, "evb exit status %d, auto_restart %d", status, auto_restart);
1299
1300 if (status == EB_USER_ERROR)
1301 {
1302 restart_count ++;
1303 goto restart;
1304 }
1305
1306 /* reset terminal */
1308
1309 exit:
1310 /* Free local memory */
1312
1313 /* Clean disconnect from midas */
1315 return 0;
1316}
static void usage()
INT cm_register_transition(INT transition, INT(*func)(INT, char *), INT sequence_number)
Definition midas.cxx:3593
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3011
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition midas.cxx:2278
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
Definition midas.cxx:5286
INT cm_disconnect_experiment(void)
Definition midas.cxx:2846
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
Definition midas.cxx:2134
INT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout)
Definition midas.cxx:3283
INT cm_exist(const char *name, BOOL bUnique)
Definition midas.cxx:7520
#define SUCCESS
Definition mcstd.h:54
#define TR_RESUME
Definition midas.h:408
#define TR_PAUSE
Definition midas.h:407
#define TID_BOOL
Definition midas.h:340
#define TR_START
Definition midas.h:405
#define TR_SYNC
Definition midas.h:358
#define TR_STOP
Definition midas.h:406
INT ss_getchar(BOOL reset)
Definition system.cxx:7503
INT ss_daemon_init(BOOL keep_stdout)
Definition system.cxx:2001
INT ss_sleep(INT millisec)
Definition system.cxx:3628
std::string strcomb1(const char **list)
Definition odb.cxx:598
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12800
BOOL daemon
Definition mana.cxx:258
INT ebuilder_exit(void)
Definition ebuser.cxx:87
void free_event_buffer(INT nfrag)
Definition mevb.cxx:774
INT tr_stop(INT rn, char *error)
Definition mevb.cxx:758
INT tr_start(INT rn, char *error)
Definition mevb.cxx:601
char expt_name[NAME_LENGTH]
Definition mevb.cxx:44
INT tr_pause(INT rn, char *error)
Definition mevb.cxx:749
HNDLE hKey
Definition mevb.cxx:48
BOOL wheel
Definition mevb.cxx:51
INT ebuilder_init(void)
Definition ebuser.cxx:79
INT load_fragment(void)
Definition mevb.cxx:230
INT register_equipment(void)
Definition mevb.cxx:94
INT scan_fragment(void)
Definition mevb.cxx:312
INT tr_resume(INT rn, char *error)
Definition mevb.cxx:731
char host_name[HOST_NAME_LENGTH]
Definition mevb.cxx:43
#define EBUILDER(_name)
Definition mevb.h:11
DWORD auto_restart
Definition mfe.cxx:51
DWORD BOOL
Definition midas.h:105
#define TRUE
Definition midas.h:182
char str[256]
Definition odbhist.cxx:33
Here is the call graph for this function:

◆ register_equipment()

INT register_equipment ( void  )

Definition at line 94 of file mevb.cxx.

95{
96 INT index, size, status;
97 char str[256];
100 HNDLE hKey;
101
102 /* get current ODB run state */
103 size = sizeof(run_state);
105 db_get_value(hDB, 0, "/Runinfo/State", &run_state, &size, TID_INT, TRUE);
106 size = sizeof(run_number);
107 run_number = 1;
108 status = db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
109 assert(status == SUCCESS);
110
111 /* scan EQUIPMENT table from mevb.C */
112 for (index = 0; equipment[index].name[0]; index++) {
115
116 if (eq_info->event_id == 0) {
117 printf("\nEvent ID 0 for %s not allowed\n", equipment[index].name);
119 ss_sleep(5000);
120 exit(0);
121 }
122
123 /* init status */
125
126 sprintf(str, "/Equipment/%s/Common", equipment[index].name);
127
128 /* get last event limit from ODB */
129 if (eq_info->eq_type != EQ_SLOW) {
130 db_find_key(hDB, 0, str, &hKey);
131 size = sizeof(double);
132 if (hKey)
133 db_get_value(hDB, hKey, "Event limit", &eq_info->event_limit, &size, TID_DOUBLE, TRUE);
134 }
135
136 /* Create common subtree */
138 if (status != DB_SUCCESS) {
139 printf("Cannot check equipment record, status = %d\n", status);
140 ss_sleep(3000);
141 }
142 db_find_key(hDB, 0, str, &hKey);
143
144 if (equal_ustring(eq_info->format, "FIXED"))
146 else /* default format is MIDAS */
148
149 gethostname(eq_info->frontend_host, sizeof(eq_info->frontend_host));
150 strcpy(eq_info->frontend_name, frontend_name);
151 strcpy(eq_info->frontend_file_name, frontend_file_name);
152
153 /* set record from equipment[] table in frontend.c */
155
156 /* get record once at the start equipment info */
157 size = sizeof(EQUIPMENT_INFO);
158 db_get_record(hDB, hKey, eq_info, &size, 0);
159
160 /*---- Create just the key , leave it empty ---------------------------------*/
161 sprintf(str, "/Equipment/%s/Variables", equipment[index].name);
163 db_find_key(hDB, 0, str, &hKey);
165
166 /*---- Create and initialize statistics tree -------------------*/
167 sprintf(str, "/Equipment/%s/Statistics", equipment[index].name);
168
170 if (status != DB_SUCCESS) {
171 printf("Cannot create/check statistics record, error %d\n", status);
172 ss_sleep(3000);
173 }
174
175 status = db_find_key(hDB, 0, str, &hKey);
176 if (status != DB_SUCCESS) {
177 printf("Cannot find statistics record, error %d\n", status);
178 ss_sleep(3000);
179 }
180
181 eq_stats->events_sent = 0;
182 eq_stats->events_per_sec = 0;
183 eq_stats->kbytes_per_sec = 0;
184
185 /* open hot link to statistics tree */
187 if (status == DB_NO_ACCESS) {
188 /* record is probably still in exclusive access by dead FE, so reset it */
190 if (status != DB_SUCCESS)
191 cm_msg(MERROR, "register_equipment", "Cannot change access mode for record \'%s\', error %d", str, status);
192 else
193 cm_msg(MINFO, "register_equipment", "Recovered access mode for record \'%s\'", str);
195 }
196 if (status != DB_SUCCESS) {
197 cm_msg(MERROR, "register_equipment", "Cannot open statistics record, error %d. Probably other FE is using it", status);
198 ss_sleep(3000);
199 }
200
201 /*---- open event buffer ---------------------------------------*/
202 if (eq_info->buffer[0]) {
204 if (status != BM_SUCCESS && status != BM_CREATED) {
205 cm_msg(MERROR, "register_equipment",
206 "Cannot open event buffer. Try to reduce EVENT_BUFFER_SIZE in midas.h \
207 and rebuild the system.");
208 return 0;
209 }
210
211 if (1)
212 {
213 int level = 0;
214 bm_get_buffer_level(equipment[index].buffer_handle, &level);
215 printf("Buffer %s, level %d, info: \n", eq_info->buffer, level);
216 }
217
218 /* set the default buffer cache size */
220 } else {
221 cm_msg(MERROR, "register_equipment", "Destination buffer must be present");
222 ss_sleep(3000);
223 exit(0);
224 }
225 }
226 return SUCCESS;
227}
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
Definition midas.cxx:6717
INT bm_set_cache_size(INT buffer_handle, size_t read_size, size_t write_size)
Definition midas.cxx:8140
#define BM_CREATED
Definition midas.h:606
#define DB_NO_ACCESS
Definition midas.h:648
#define TID_DOUBLE
Definition midas.h:343
#define FORMAT_FIXED
Definition midas.h:314
#define MODE_DELETE
Definition midas.h:372
#define MODE_WRITE
Definition midas.h:371
#define MODE_READ
Definition midas.h:370
#define EQ_SLOW
Definition midas.h:418
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3201
INT db_open_record(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size, WORD access_mode, void(*dispatcher)(INT, INT, void *), void *info)
Definition odb.cxx:13291
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3308
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition odb.cxx:12972
INT db_get_record(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align)
Definition odb.cxx:11709
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
Definition odb.cxx:8027
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition odb.cxx:12291
INT index
Definition mana.cxx:271
#define SERVER_CACHE_SIZE
Definition mevb.cxx:24
#define EQUIPMENT_STATISTICS_STR
Definition mevb.cxx:86
const char * frontend_file_name
The frontend file name, don't change it.
Definition feudp.cxx:23
INT bm_get_buffer_level(INT buffer_handle, INT *n_bytes)
Definition midas.cxx:7838
#define DEFAULT_BUFFER_SIZE
Definition midas.h:255
#define EQUIPMENT_COMMON_STR
Definition midas.h:1112
EQUIPMENT_STATS stats
Definition midas.h:1194
HNDLE buffer_handle
Definition midas.h:1185
char name[NAME_LENGTH]
Definition midas.h:1173
HNDLE hkey_variables
Definition midas.h:1186
INT format
Definition midas.h:1184
INT status
Definition midas.h:1180
Here is the call graph for this function:
Here is the caller graph for this function:

◆ scan_fragment()

INT scan_fragment ( void  )

Definition at line 312 of file mevb.cxx.

313{
315 EQUIPMENT *eq;
317 INT ch;
318
319 /* Get equipment pointer, only one eqp for now */
320 eq_info = &equipment[0].info;
321 status = 0;
322 eq = NULL;
323
324 /* Main event loop */
325 do {
326 switch (run_state) {
327 case STATE_STOPPED:
328 case STATE_PAUSED:
329 /* skip the source scan and yield */
330 status = cm_yield(500);
331 if (wheel) {
332 printf("...%c Snoring\r", bars[i_bar++ % 4]);
333 fflush(stdout);
334 }
335 break;
336 case STATE_RUNNING:
337 status = source_scan(equipment[0].format, eq_info);
338 switch (status) {
339 case BM_ASYNC_RETURN: // No event found for now, Check for timeout
340
341 if (1) {
342 /* advanced checking for timeouts */
343
344 time_t now = time(NULL);
345 int empty = 1;
346 int badfrag = -1;
347
348 /* check if we recieved any data */
349 for (fragn = 0; fragn < nfragment; fragn++)
350 if (ebset.received[fragn])
351 empty = 0;
352
353 /* only look for timeout if there is received data from any fragment */
354 if (!empty)
355 for (fragn = 0; fragn < nfragment; fragn++) {
356 //if (debug)
357 // printf("frag %d, timeout %d, threshold %d, received %d, time %d\n", fragn, ebch[fragn].timeout, TIMEOUT, ebset.received[fragn], now - ebch[fragn].time);
358 if (ebch[fragn].time && ebch[fragn].timeout)
359 if (now - ebch[fragn].time > TIMEOUT_ABORT) {
360 //cm_msg(MERROR, "scan_fragment", "frag %d, timeout %d, %d sec", fragn, ebch[fragn].timeout, now - ebch[fragn].time);
361 badfrag = fragn;
362 }
363 }
364
365 if (badfrag >= 0) {
366 //status = SS_ABORT;
368 cm_msg(MERROR, "scan_fragment", "timeout waiting for fragment %d, restarting run", badfrag);
369 cm_msg(MINFO, "scan_fragment", "spawning mtransition");
370 ss_system("mtransition STOP IF \"/Logger/Auto restart\" DELAY \"/Logger/Auto restart delay\" START &");
372 }
373 break;
374 }
375 }
376
377 for (fragn = 0; fragn < nfragment; fragn++) {
378 if (ebch[fragn].timeout > TIMEOUT) { /* Timeout */
379 if (stop_requested) { /* Stop */
380 if (debug)
381 printf("Timeout waiting for fragment %d while stopping the run\n", fragn);
383 break;
384 } else {
385 /* No stop requested but timeout, allow a yield to not
386 eat all the CPU */
387 status = cm_yield(10);
388 if (wheel) {
389 printf("...%c Timing on %1.0lf\r", bars[i_bar++ % 4], eq->stats.events_sent);
390 fflush(stdout);
391 }
392
393 }
394 }
395 //else { /* No timeout loop back */
396 } // for loop over all fragments
397 break;
398 case EB_ERROR:
399 case EB_USER_ERROR:
401 if (status == EB_USER_ERROR)
402 cm_msg(MTALK, "scan_fragment", "%s: Error signaled by user code - stopping run...",
404 else
405 cm_msg(MTALK, "EBuilder", "%s: Event mismatch - Stopping run...", frontend_name);
406
407 if (debug)
408 printf("Stop requested on Error %d\n", status);
410
411#if 0
413 cm_msg(MINFO, "scan_fragment", "spawning mtransition");
414 //ss_system("mtransition STOP IF \"/Logger/Auto restart\" DELAY \"/Logger/Auto restart delay\" START &");
415 ss_system("mtransition STOP &");
417 }
418#endif
419 for (ch=0; ch<5; ch++) {
420 if (cm_transition(TR_STOP, 0, NULL, 0, TR_SYNC, 0) == CM_SUCCESS)
421 break;
422 cm_msg(MERROR, "scan_fragment", "%s: Stop Transition request failed, trying again!", frontend_name);
423 }
424 return status;
425 break;
426 case EB_SUCCESS:
427 case EB_SKIP:
428 // Normal path if event has been assembled
429 // No yield in this case.
430 break;
431 default:
432 cm_msg(MERROR, "scan_fragment", "unexpected return %d", status);
434 } // switch scan_source
435 break;
436 }
437 /* EB job done, update statistics if its time */
438 /* Check if it's time to do statistics job */
439 if ((actual_millitime = ss_millitime()) - last_time > 1000) {
440 /* Force event to appear at the destination if Ebuilder is remote */
442 /* Force event ot appear at the destination if Ebuilder is local */
443 bm_flush_cache(equipment[0].buffer_handle, BM_NO_WAIT);
444
445 status = cm_yield(10);
446
447 eq = &equipment[0];
448 eq->stats.events_sent += eq->events_sent;
449 eq->stats.events_per_sec = eq->events_sent / ((actual_millitime - last_time) / 1000.0);
450 eq->stats.kbytes_per_sec = eq->bytes_sent / 1024.0 / ((actual_millitime - last_time) / 1000.0);
451 eq->bytes_sent = 0;
452 eq->events_sent = 0;
453 /* update destination statistics */
455 /* Keep track of last ODB update */
457 }
458
459 ch = 0;
460 if (ss_kbhit()) {
461 ch = ss_getchar(0);
462 if (ch == -1)
463 ch = getchar();
464 if ((char) ch == '!')
465 break;
466 }
467 } while (status != RPC_SHUTDOWN && status != SS_ABORT);
468
469 return status;
470}
INT cm_yield(INT millisec)
Definition midas.cxx:5642
#define BM_ASYNC_RETURN
Definition midas.h:613
#define SS_ABORT
Definition midas.h:677
#define RPC_SHUTDOWN
Definition midas.h:707
#define STATE_PAUSED
Definition midas.h:306
#define STATE_RUNNING
Definition midas.h:307
#define MTALK
Definition midas.h:564
BOOL ss_kbhit()
Definition system.cxx:3664
INT ss_system(const char *command)
Definition system.cxx:2116
INT db_send_changed_records()
Definition odb.cxx:13777
INT rpc_flush_event()
Definition midas.cxx:14038
INT close_buffers(void)
Definition mevb.cxx:935
char bars[]
Definition mevb.cxx:52
DWORD last_time
Definition mevb.cxx:39
DWORD actual_millitime
Definition mevb.cxx:41
static int waiting_for_stop
Definition mevb.cxx:91
BOOL stop_requested
Definition mevb.cxx:54
int i_bar
Definition mevb.cxx:53
INT source_scan(INT fmt, EQUIPMENT_INFO *eq_info)
Definition mevb.cxx:984
#define TIMEOUT_ABORT
Definition mevb.cxx:32
#define TIMEOUT
Definition mevb.h:64
#define EB_SKIP
Definition mevb.h:62
BOOL * received
Definition mevb.h:33
double events_sent
Definition midas.h:1138
Here is the call graph for this function:
Here is the caller graph for this function:

◆ source_booking()

INT source_booking ( void  )

Definition at line 820 of file mevb.cxx.

821{
823
824 if (debug)
825 printf("Entering booking\n");
826
827 status1 = status2 = 0;
828
829 /* Book all the source channels */
830 for (i = 0; i < nfragment; i++) {
831 /* Book only the requested event mask */
832 if (ebset.preqfrag[i]) {
833 /* Connect channel to source buffer */
835
836 if (debug)
837 printf("bm_open_buffer frag:%d buf:%s handle:%d stat:%d\n",
838 i, ebch[i].buffer, ebch[i].hBuf, status1);
839
840 if (1)
841 {
842 int level = 0;
844 printf("Buffer %s, level %d, info: \n", ebch[i].buffer, level);
845 }
846
847
848 /* Register for specified channel event ID and Trigger mask */
849 status2 =
851 TRIGGER_ALL, GET_ALL, &ebch[i].req_id, NULL);
852 if (debug)
853 printf("bm_request_event frag:%d id:%d msk:%d req_id:%d stat:%d\n",
854 i, ebch[i].event_id, ebch[i].trigger_mask, ebch[i].req_id, status2);
855 if (((status1 != BM_SUCCESS) && (status1 != BM_CREATED)) ||
856 ((status2 != BM_SUCCESS) && (status2 != BM_CREATED))) {
857 cm_msg(MERROR, "source_booking",
858 "Open buffer/event request failure [%d %d %d]", i, status1, status2);
859 return BM_CONFLICT;
860 }
861
862 /* allocate local source event buffer */
863 if (ebch[i].pfragment)
864 free(ebch[i].pfragment);
865 ebch[i].pfragment = (char *) malloc(max_event_size + sizeof(EVENT_HEADER));
866 if (debug)
867 printf("malloc pevent frag:%d pevent:%p\n", i, ebch[i].pfragment);
868 if (ebch[i].pfragment == NULL) {
870 cm_msg(MERROR, "source_booking", "Can't allocate space for buffer");
871 return BM_NO_MEMORY;
872 }
873 }
874 }
875
876 /* Empty source buffer */
878 if (status != BM_SUCCESS) {
879 cm_msg(MERROR, "source_booking", "bm_empty_buffers failure [%d]", status);
880 return status;
881 }
882
883 if (debug) {
884 printf("bm_empty_buffers stat:%d\n", status);
885 for (j = 0; j < ebset.nfragment; j++) {
886 printf(" buff:%s", ebch[j].buffer);
887 printf(" ser#:%d", ebch[j].serial);
888 printf(" hbuf:%2d", ebch[j].hBuf);
889 printf(" rqid:%2d", ebch[j].req_id);
890 printf(" opst:%d", status1);
891 printf(" rqst:%d", status2);
892 printf(" evid:%2d", ebch[j].event_id);
893 printf(" tmsk:0x%4.4x\n", ebch[j].trigger_mask);
894 }
895 }
896
897 return SUCCESS;
898}
INT bm_request_event(HNDLE buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, HNDLE *request_id, EVENT_HANDLER *func)
Definition midas.cxx:8465
#define BM_CONFLICT
Definition midas.h:617
#define BM_NO_MEMORY
Definition midas.h:607
#define GET_ALL
Definition midas.h:321
#define TRIGGER_ALL
Definition midas.h:538
INT j
Definition odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ source_scan()

INT source_scan ( INT  fmt,
EQUIPMENT_INFO eq_info 
)

Scan all the fragment source once per call.

  1. This will retrieve the full midas event not swapped (except the MIDAS_HEADER) for each fragment if possible. The fragment will be stored in the channel event pointer.
  2. if after a full nfrag path some frag are still not cellected, it returns with the frag# missing for timeout check.
  3. If ALL fragments are present it will check the midas serial# for a full match across all the fragments.
  4. If the serial check fails it returns with "event mismatch" and will abort the event builder but not stop the run for now.
  5. If the serial check is passed, it will call the user_build function where the destination event is going to be composed.
Parameters
fmtFragment format type
eq_infoEquipement pointer
Returns
EB_NO_MORE_EVENT, EB_COMPOSE_TIMEOUT if different then SUCCESS (bm_compose, rpc_sent error)

Definition at line 984 of file mevb.cxx.

985{
986 static DWORD serial;
987 INT i, status, size;
991
992 status = 0;
993
994 /* Scan all channels at least once */
995 for (i = 0; i < nfragment; i++) {
996 /* Check if current channel needs to be received */
997 if (ebset.preqfrag[i] && !ebset.received[i]) {
998 /* Get fragment and store it in ebch[i].pfragment */
999 size = max_event_size;
1000 status = bm_receive_event(ebch[i].hBuf, ebch[i].pfragment, &size, BM_NO_WAIT);
1001 //printf("call bm_receive_event from %s, serial %d, status %d\n", ebch[i].buffer, serial, status);
1002 switch (status) {
1003 case BM_SUCCESS: /* event received */
1004 /* Mask event */
1005 ebset.received[i] = TRUE;
1006 /* Keep local serial */
1007 ebch[i].serial = ((EVENT_HEADER *) ebch[i].pfragment)->serial_number;
1008 /* clear timeout */
1009 ebch[i].timeout = 0;
1010 ebch[i].time = time(NULL);
1011
1012 /* Swap event depending on data format */
1013 switch (fmt) {
1014 case FORMAT_MIDAS:
1015 psbh = (BANK_HEADER *) (((EVENT_HEADER *) ebch[i].pfragment) + 1);
1016 bk_swap(psbh, FALSE);
1017 break;
1018 }
1019
1020 if (debug1) {
1021 printf("SUCC: ch:%d ser:%d rec:%d sz:%d\n", i, ebch[i].serial, ebset.received[i], size);
1022 }
1023 break;
1024 case BM_ASYNC_RETURN: /* timeout */
1025 ebch[i].timeout++;
1026 if (debug1) {
1027 printf("ASYNC: ch:%d ser:%d rec:%d sz:%d, timeout:%d\n", i, ebch[i].serial, ebset.received[i], size, ebch[i].timeout);
1028 }
1029 //return status;
1030 break;
1031 default: /* Error */
1032 cm_msg(MERROR, "source_scan", "bm_receive_event error %d", status);
1033 return status;
1034 break;
1035 }
1036 } /* next channel */
1037 }
1038
1039 /* Check if all fragments have been received */
1040 for (i = 0; i < nfragment; i++) {
1041 if (ebset.preqfrag[i] && !ebset.received[i])
1042 break;
1043 }
1044 if (i == nfragment) {
1045 /* Check if serial matches */
1047 serial = 0;
1048 /* Check Serial, mark first serial */
1049 for (i = 0; i < nfragment; i++) {
1050 if (ebset.preqfrag[i] && ebset.received[i] && !found) {
1051 serial = ebch[i].serial;
1052 found = TRUE;
1053 } else {
1054 if (ebset.preqfrag[i] && ebset.received[i] && (serial != ebch[i].serial)) {
1055 /* Event mismatch */
1057 }
1058 }
1059 }
1060
1061 /* internal action in case of event mismatch */
1062 if (event_mismatch && debug) {
1063 char str[256];
1064 char strsub[128];
1065 strcpy(str, "event mismatch: ");
1066 for (i = 0; i < nfragment; i++) {
1067 sprintf(strsub, "Ser[%d]:%d ", i, ebch[i].serial);
1068 strcat(str, strsub);
1069 }
1070 printf("event serial mismatch %s\n", str);
1071 }
1072
1073 /* In any case reset destination buffer */
1074 memset(dest_event, 0, sizeof(EVENT_HEADER));
1075 act_size = 0;
1076
1077 /* Fill reserved header space of destination event with
1078 final header information */
1079 bm_compose_event((EVENT_HEADER *) dest_event, eq_info->event_id, eq_info->trigger_mask,
1080 act_size, serial);
1081
1082 /* Pass fragments to user with mismatch flag, for final check before assembly */
1083 status =
1085 (void *) ((EVENT_HEADER *) dest_event + 1), &act_size);
1086 if (status != EB_SUCCESS) {
1087 if (status == EB_SKIP) {
1088 /* Reset mask and timeouts as if event has been successfully send out */
1089 for (i = 0; i < nfragment; i++) {
1090 ebch[i].timeout = 0;
1091 ebset.received[i] = FALSE;
1092 }
1093 }
1094 return status; // Event mark as EB_SKIP or EB_ABORT by user
1095 }
1096
1097 /* Allow bypass of fragment assembly if user did it on its own */
1098 if (!ebset.user_build) {
1099 for (i = 0; i < nfragment; i++) {
1100 if (ebset.preqfrag[i]) {
1102 if (status != EB_SUCCESS) {
1103 cm_msg(MERROR, "source_scan",
1104 "compose fragment:%d current size:%d (%d)", i, act_size, status);
1105 return EB_ERROR;
1106 }
1107 }
1108 }
1109 }
1110
1111 /* Overall event to be sent */
1112 act_size = ((EVENT_HEADER *) dest_event)->data_size + sizeof(EVENT_HEADER);
1113
1114 /* Send event and wait for completion */
1116 if (status != BM_SUCCESS) {
1117 if (debug)
1118 printf("rpc_send_event returned error %d, event_size %d\n", status, act_size);
1119 cm_msg(MERROR, "source_scan", "%s: rpc_send_event returned error %d", frontend_name, status);
1120 return EB_ERROR;
1121 }
1122
1123 /* Keep track of the total byte count */
1125
1126 /* update destination event count */
1128
1129 /* Reset mask and timeouts as even thave been succesfully send */
1130 for (i = 0; i < nfragment; i++) {
1131 ebch[i].timeout = 0;
1132 ebset.received[i] = FALSE;
1133 }
1134 } // all fragment recieved for this event
1135
1136 return status;
1137}
INT bm_compose_event(EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD serial)
Definition midas.cxx:8281
INT rpc_send_event(INT buffer_handle, const EVENT_HEADER *pevent, int unused, INT async_flag, INT mode)
Definition midas.cxx:13901
INT eb_user(INT, BOOL mismatch, EBUILDER_CHANNEL *, EVENT_HEADER *, void *, INT *)
Definition ebuser.cxx:192
time_t time
Definition mevb.h:51
DWORD serial
Definition mevb.h:53
BOOL user_build
Definition mevb.h:29
DWORD bytes_sent
Definition midas.h:1191
DWORD events_sent
Definition midas.h:1192
Here is the call graph for this function:
Here is the caller graph for this function:

◆ source_unbooking()

INT source_unbooking ( void  )

Definition at line 901 of file mevb.cxx.

902{
903 INT i, status;
904
905 /* unbook all source channels */
906 for (i = 0; i < nfragment; i++) {
907
908 /* Skip unbooking if already done */
909 if (ebch[i].pfragment != NULL) {
911
912 /* Remove event ID registration */
913 status = bm_delete_request(ebch[i].req_id);
914 if (debug)
915 printf("unbook: bm_delete_req[%d] req_id:%d stat:%d\n", i, ebch[i].req_id, status);
916
917 /* Close source buffer */
919 if (debug)
920 printf("unbook: bm_close_buffer[%d] hndle:%d stat:%d\n", i, ebch[i].hBuf, status);
921 if (status != BM_SUCCESS) {
922 cm_msg(MERROR, "source_unbooking", "Close buffer[%d] stat: %d", i, status);
923 return status;
924 }
925 }
926 }
927
928 /* release local event buffer memory */
930
931 return EB_SUCCESS;
932}
INT bm_delete_request(INT request_id)
Definition midas.cxx:8584
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7096
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr_pause()

INT tr_pause ( INT  rn,
char error 
)

Definition at line 749 of file mevb.cxx.

750{
751 printf("\n%s-Pause Run: %d detected\n", frontend_name, rn);
752
754 return CM_SUCCESS;
755}
Here is the caller graph for this function:

◆ tr_resume()

INT tr_resume ( INT  rn,
char error 
)

Definition at line 731 of file mevb.cxx.

732{
733 int fragn;
734 time_t now = time(NULL);
735
736 printf("\n%s-Resume Run: %d detected\n", frontend_name, rn);
737
738 // reset timeouts
739 for (fragn = 0; fragn < nfragment; fragn++) {
740 ebch[fragn].time = now;
741 ebch[fragn].timeout = 0;
742 }
743
745 return CM_SUCCESS;
746}
Here is the caller graph for this function:

◆ tr_start()

INT tr_start ( INT  rn,
char error 
)

Definition at line 601 of file mevb.cxx.

602{
604 INT status, size, i;
605 char str[128];
606 KEY key;
609
610 if (debug)
611 printf("tr_start: run %d\n", rn);
612
613 eq_info = &equipment[0].info;
614
615 /* Get update eq_info from ODB */
616 sprintf(str, "/Equipment/%s/Common", equipment[0].name);
617 status = db_find_key(hDB, 0, str, &hKey);
618 size = sizeof(EQUIPMENT_INFO);
619 db_get_record(hDB, hKey, eq_info, &size, 0);
620
622
623 /* reset serial numbers */
624 for (i = 0; equipment[i].name[0]; i++) {
629 }
630
631 /* Get / Set Settings */
632 sprintf(str, "/Equipment/%s/Settings", equipment[0].name);
633 if (db_find_key(hDB, 0, str, &hEqkey) != DB_SUCCESS) {
635 }
636
637 /* Keep Key on Ebuilder/Settings */
638 sprintf(str, "/Equipment/%s/Settings", equipment[0].name);
639 if (db_find_key(hDB, 0, str, &hEqkey) != DB_SUCCESS) {
640 cm_msg(MINFO, "tr_start", "/Equipment/%s/Settings not found", equipment[0].name);
641 }
642
643 /* Update or Create User_field */
644 size = sizeof(ebset.user_field);
645 status = db_get_value(hDB, hEqkey, "User Field", ebset.user_field, &size, TID_STRING, TRUE);
646
647 /* Update or Create User_Build */
648 size = sizeof(ebset.user_build);
649 status = db_get_value(hDB, hEqkey, "User Build", &ebset.user_build, &size, TID_BOOL, TRUE);
650
651 /* update ODB */
652 size = sizeof(INT);
653 status = db_set_value(hDB, hEqkey, "Number of Fragment", &ebset.nfragment, size, 1, TID_INT);
654
655 /* Create or update the fragment request list */
656 status = db_find_key(hDB, hEqkey, "Fragment Required", &hEqFRkey);
658 assert(status == DB_SUCCESS);
659
660 if (key.num_values != ebset.nfragment) {
661 cm_msg(MINFO, "tr_start", "Number of Fragment mismatch ODB:%d - CUR:%d", key.num_values, ebset.nfragment);
662 free(ebset.preqfrag);
663 size = ebset.nfragment * sizeof(BOOL);
664 ebset.preqfrag = (BOOL*)malloc(size);
665 for (i = 0; i < ebset.nfragment; i++)
666 ebset.preqfrag[i] = TRUE;
667 status =
668 db_set_value(hDB, hEqkey, "Fragment Required", ebset.preqfrag, size, ebset.nfragment, TID_BOOL);
669 } else { // Take from ODBedit
670 size = key.total_size;
671 free(ebset.preqfrag);
672 ebset.preqfrag = (BOOL*)malloc(size);
674 }
675 /* Cleanup fragment flags */
676 free(ebset.received);
677 ebset.received = (BOOL*)malloc(size);
678 for (i = 0; i < ebset.nfragment; i++)
680
681 /* Check if at least one fragment is requested */
682 for (i = 0; i < ebset.nfragment; i++)
683 if (ebset.preqfrag[i])
684 break;
685
686 if (i == ebset.nfragment) {
687 cm_msg(MERROR, "tr_start", "Run start aborted because no fragment required");
688 return 0;
689 }
690
691 /* Call BOR user function */
693 if (status != EB_SUCCESS) {
694 cm_msg(MERROR, "tr_start", "run start aborted due to eb_begin_of_run (%d)", status);
695 return status;
696 }
697
698 /* Book all fragment */
700 if (status != SUCCESS)
701 return status;
702
703 if (!eq_info->enabled) {
704 cm_msg(MINFO, "tr_start", "Event Builder disabled");
705 return CM_SUCCESS;
706 }
707
708 /* local run state */
710 run_number = rn;
713 printf("%s-Starting New Run: %d\n", frontend_name, rn);
714
715 if (1) {
716 int fragn;
717 time_t now = time(NULL);
718
719 // reset timeouts
720 for (fragn = 0; fragn < nfragment; fragn++) {
721 ebch[fragn].time = now;
722 ebch[fragn].timeout = 0;
723 }
724 }
725
726 /* Reset global trigger mask */
727 return CM_SUCCESS;
728}
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition odb.cxx:6539
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
Definition odb.cxx:5261
INT source_booking(void)
Definition mevb.cxx:820
INT eb_begin_of_run(INT, char *, char *)
Definition ebuser.cxx:106
char user_field[64]
Definition mevb.h:30
INT num_values
Definition midas.h:1028
INT total_size
Definition midas.h:1031
DWORD subevent_number
Definition midas.h:1188
DWORD serial_number
Definition midas.h:1187
DWORD odb_out
Definition midas.h:1189
DWORD odb_in
Definition midas.h:1190
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr_stop()

INT tr_stop ( INT  rn,
char error 
)

Definition at line 758 of file mevb.cxx.

759{
761
762 if (debug)
763 printf("tr_stop: run %d\n", rn);
764
765 /* local stop */
767
768 /* local stop time */
770 return CM_SUCCESS;
771}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ abort_requested

BOOL abort_requested = FALSE

Definition at line 54 of file mevb.cxx.

◆ actual_millitime

DWORD actual_millitime

Definition at line 41 of file mevb.cxx.

◆ actual_time

DWORD actual_time

Definition at line 40 of file mevb.cxx.

◆ bars

char bars[] = "|\\-/"

Definition at line 52 of file mevb.cxx.

◆ buffer_name

char buffer_name[NAME_LENGTH]

Definition at line 45 of file mevb.cxx.

◆ debug

BOOL debug = FALSE

debug printouts

Definition at line 49 of file mevb.cxx.

◆ debug1

BOOL debug1 = FALSE

Definition at line 49 of file mevb.cxx.

◆ dest_event

char* dest_event

Definition at line 47 of file mevb.cxx.

◆ display_period

INT display_period
extern

a frontend status page is displayed with this frequency in ms

Definition at line 27 of file mfed.cxx.

◆ ebch

Definition at line 35 of file mevb.cxx.

◆ ebset

Definition at line 34 of file mevb.cxx.

◆ equipment

EQUIPMENT equipment[]
extern

Main structure for midas equipment.

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};
#define EQ_NAME
Definition feudp.cxx:43
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

◆ event_buffer_size

INT event_buffer_size
extern

buffer size to hold events

Definition at line 36 of file mfed.cxx.

◆ expt_name

char expt_name[NAME_LENGTH]

Definition at line 44 of file mevb.cxx.

◆ frontend_call_loop

BOOL frontend_call_loop

Definition at line 73 of file mevb.cxx.

◆ hDB

HNDLE hDB

main ODB handle

Definition at line 48 of file mevb.cxx.

◆ hEqKey

HNDLE hEqKey

Definition at line 48 of file mevb.cxx.

◆ hESetKey

HNDLE hESetKey

Definition at line 48 of file mevb.cxx.

◆ hKey

HNDLE hKey

Definition at line 48 of file mevb.cxx.

◆ host_name

char host_name[HOST_NAME_LENGTH]

Definition at line 43 of file mevb.cxx.

◆ hStatKey

HNDLE hStatKey

Definition at line 48 of file mevb.cxx.

◆ hSubkey

HNDLE hSubkey

Definition at line 48 of file mevb.cxx.

◆ i_bar

int i_bar

Definition at line 53 of file mevb.cxx.

◆ last_time

DWORD last_time

Definition at line 39 of file mevb.cxx.

◆ max_event_size

INT max_event_size
extern

maximum event size produced by this frontend

Definition at line 30 of file mfed.cxx.

◆ max_event_size_frag

INT max_event_size_frag
extern

maximum event size for fragmented events (EQ_FRAGMENTED)

Definition at line 33 of file mfed.cxx.

◆ meb_fragment_add

INT(* meb_fragment_add) (char *, char *, INT *) ( char ,
char ,
INT  
)

Definition at line 57 of file mevb.cxx.

◆ nfragment

INT nfragment

Definition at line 46 of file mevb.cxx.

◆ request_stop_time

DWORD request_stop_time = 0

Definition at line 55 of file mevb.cxx.

◆ run_number

INT run_number

Definition at line 38 of file mevb.cxx.

◆ run_state

INT run_state

Definition at line 37 of file mevb.cxx.

◆ stop_requested

BOOL stop_requested = TRUE

Definition at line 54 of file mevb.cxx.

◆ stop_time

DWORD stop_time = 0

Definition at line 55 of file mevb.cxx.

◆ waiting_for_stop

int waiting_for_stop = FALSE
static

Definition at line 91 of file mevb.cxx.

◆ wheel

BOOL wheel = FALSE

Definition at line 51 of file mevb.cxx.