Line data Source code
1 : /********************************************************************\
2 :
3 : Name: ebuser.c
4 : Created by: Pierre-Andre Amaudruz
5 :
6 : Contents: User section for the Event builder
7 :
8 : $Id$
9 :
10 : \********************************************************************/
11 : /** @file ebuser.c
12 : The Event builder user file
13 : */
14 :
15 : #include <stdio.h>
16 : #include <string.h>
17 : #include <stdlib.h> // atoi()
18 : #include "midas.h"
19 : #include "mevb.h"
20 :
21 : /* data type sizes */
22 : extern INT tid_size[];
23 : /*-- Globals -------------------------------------------------------*/
24 :
25 : /* The frontend name (client name) as seen by other MIDAS clients */
26 : const char *frontend_name = "Ebuilder";
27 :
28 : /* The frontend file name, don't change it */
29 : const char *frontend_file_name = __FILE__;
30 :
31 : /* frontend_loop is called periodically if this variable is TRUE */
32 : BOOL ebuilder_call_loop = FALSE;
33 :
34 : /* A frontend status page is displayed with this frequency in ms */
35 : INT display_period = 3000;
36 :
37 : /* maximum event size produced by this frontend */
38 : INT max_event_size = 500000;
39 :
40 : /* maximum event size for fragmented events (EQ_FRAGMENTED) */
41 : INT max_event_size_frag = 5 * 1024 * 1024;
42 :
43 : /* buffer size to hold events */
44 : INT event_buffer_size = 20 * 50000;
45 :
46 : /**
47 : Globals */
48 : INT lModulo = 100; ///< Global var for testing passed at BOR
49 :
50 : /*-- Function declarations -----------------------------------------*/
51 : INT ebuilder_init();
52 : INT ebuilder_exit();
53 : INT eb_begin_of_run(INT, char *, char *);
54 : INT eb_end_of_run(INT, char *);
55 : INT ebuilder_loop();
56 : INT ebuser(INT, BOOL mismatch, EBUILDER_CHANNEL *, EVENT_HEADER *, void *, INT *);
57 : INT read_scaler_event(char *pevent, INT off);
58 : extern EBUILDER_SETTINGS ebset;
59 : extern BOOL debug;
60 :
61 : /*-- Equipment list ------------------------------------------------*/
62 : EQUIPMENT equipment[] = {
63 : {"EB", /* equipment name */
64 : {1, 0, /* event ID, trigger mask */
65 : "SYSTEM", /* event buffer */
66 : 0, /* equipment type */
67 : 0, /* event source */
68 : "MIDAS", /* format */
69 : TRUE, /* enabled */
70 : },
71 : },
72 :
73 : {""}
74 : };
75 :
76 :
77 : /********************************************************************/
78 : /********************************************************************/
79 0 : INT ebuilder_init()
80 : {
81 0 : setbuf(stdout, NULL);
82 0 : setbuf(stderr, NULL);
83 0 : return EB_SUCCESS;
84 : }
85 :
86 : /********************************************************************/
87 0 : INT ebuilder_exit()
88 : {
89 0 : return EB_SUCCESS;
90 : }
91 :
92 : /********************************************************************/
93 0 : INT ebuilder_loop()
94 : {
95 0 : return EB_SUCCESS;
96 : }
97 :
98 : /********************************************************************/
99 : /**
100 : Hook to the event builder task at PreStart transition.
101 : @param rn run number
102 : @param UserField argument from /Ebuilder/Settings
103 : @param error error string to be passed back to the system.
104 : @return EB_SUCCESS
105 : */
106 0 : INT eb_begin_of_run(INT rn, char *UserField, char *error)
107 : {
108 0 : printf("In eb_begin_of_run for run:%d User_field:%s \n", rn, UserField);
109 0 : lModulo = atoi(UserField);
110 0 : return EB_SUCCESS;
111 : }
112 :
113 : /********************************************************************/
114 : /**
115 : Hook to the event builder task at completion of event collection after
116 : receiving the Stop transition.
117 : @param rn run number
118 : @param error error string to be passed back to the system.
119 : @return EB_SUCCESS
120 : */
121 0 : INT eb_end_of_run(INT rn, char *error)
122 : {
123 0 : printf("In eb_end_of_run\n");
124 0 : return EB_SUCCESS;
125 : }
126 :
127 : /********************************************************************/
128 : /**
129 : Hook to the event builder task after the reception of
130 : all fragments of the same serial number. The destination
131 : event has already the final EVENT_HEADER setup with
132 : the data size set to 0. It is than possible to
133 : add private data at this point using the proper
134 : bank calls. Therefore any new banks created within eb_user will be appearing
135 : before the collected banks from the fragments.
136 : When using the eb_user with the ODB flag "user build=y"
137 : (equipments/EB/settings) the automatic event builder is skipped.
138 : This allow the user to extract selectively from the different fragments the
139 : appropriate banks and compose the final destination event. In order to
140 : do so, the function "bk_copy(pevent, ebch[i].pfragment, bankname)" will copy
141 : a particular bank from a given fragment.
142 :
143 : <b>Note:</b> It exists two Midas event format to address bank size less than 32KB and
144 : larger bank size <4GB. This distinction is done by the call bk_init(pevent) for the small
145 : bank size and bk_init32(pevent) for large bank size. Within an experiment, this
146 : declaration has to be consistant. Therefore the bk_init in the eb_user should follow
147 : as well the type of the frontends.
148 :
149 : The ebch[] array structure points to nfragment channel structure
150 : with the following content:
151 : \code
152 : typedef struct {
153 : char name[32]; // Fragment name (Buffer name).
154 : DWORD serial; // Serial fragment number.
155 : char *pfragment; // Pointer to fragment (EVENT_HEADER *)
156 : ...
157 : } EBUILDER_CHANNEL;
158 : \endcode
159 :
160 : The correct code for including your own MIDAS bank is shown below where
161 : \b TID_xxx is one of the valid Bank type starting with \b TID_ for
162 : midas format \b bank_name is a 4 character descriptor.
163 : \b pdata has to be declared accordingly with the bank type.
164 : Refers to the ebuser.c source code for further description.
165 :
166 : <strong>
167 : It is not possible to mix within the same destination event different event format!
168 : No bk_swap performed when user build is requested.
169 : </strong>
170 :
171 : \code
172 : // Event is empty, fill it with BANK_HEADER
173 : // If you need to add your own bank at this stage
174 :
175 : // Need to match the decalration in the Frontends.
176 : bk_init(pevent);
177 : // bk_init32(pevent);
178 : bk_create(pevent, bank_name, TID_xxxx, &pdata);
179 : *pdata++ = ...;
180 : *dest_size = bk_close(pevent, pdata);
181 : pheader->data_size = *dest_size + sizeof(EVENT_HEADER);
182 : \endcode
183 :
184 : @param nfrag Number of fragment.
185 : @param mismatch Midas Serial number mismatch flag.
186 : @param ebch Structure to all the fragments.
187 : @param pheader Destination pointer to the header.
188 : @param pevent Destination pointer to the bank header.
189 : @param dest_size Destination event size in bytes.
190 : @return EB_SUCCESS
191 : */
192 0 : INT eb_user(INT nfrag, BOOL mismatch, EBUILDER_CHANNEL * ebch
193 : , EVENT_HEADER * pheader, void *pevent, INT * dest_size)
194 : {
195 0 : INT i, frag_size, serial, status;
196 0 : DWORD *pdata;
197 :
198 :
199 : //
200 : // Do some extra fragment consistency check
201 0 : if (mismatch){
202 0 : printf("Serial number do not match across fragments\n");
203 0 : for (i = 0; i < nfrag; i++) {
204 0 : serial = ((EVENT_HEADER *) ebch[i].pfragment)->serial_number;
205 0 : printf("Ser[%i]:%d ", i + 1, serial);
206 : }
207 0 : printf("\n");
208 0 : return EB_USER_ERROR;
209 : }
210 :
211 : //
212 : // Include my own bank
213 0 : bk_init(pevent);
214 0 : bk_create(pevent, "MYOW", TID_DWORD, (void**)&pdata);
215 0 : for (i = 0; i < nfrag; i++) {
216 0 : if (ebset.preqfrag[i]) { // if channel enable
217 0 : *pdata++ = ((EVENT_HEADER *) ebch[i].pfragment)->serial_number;
218 0 : *pdata++ = ((EVENT_HEADER *) ebch[i].pfragment)->time_stamp;
219 : }
220 : }
221 0 : *dest_size = bk_close(pevent, pdata);
222 0 : pheader->data_size = *dest_size + sizeof(EVENT_HEADER);
223 :
224 : // Copy the bank TC01 if found from fragment0 to the destination
225 0 : status = bk_copy((char*)pevent, ebch[0].pfragment, "TC01");
226 0 : if (status == EB_BANK_NOT_FOUND) {
227 0 : 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 0 : if (debug) {
243 0 : for (i = 0; i < nfrag; i++) {
244 0 : if (1) {
245 0 : if (ebset.preqfrag[i]) { // printf if channel enable
246 0 : frag_size = ((EVENT_HEADER *) ebch[i].pfragment)->data_size;
247 0 : serial = ((EVENT_HEADER *) ebch[i].pfragment)->serial_number;
248 0 : 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 0 : printf("\n");
255 : }
256 : return EB_SUCCESS;
257 : }
|