ROOTANA
Loading...
Searching...
No Matches
TMidasOnline.cxx
Go to the documentation of this file.
1/********************************************************************\
2
3 Name: TMidasOnline.cxx
4 Created by: Konstantin Olchanski - TRIUMF
5
6 Contents: C++ MIDAS analyzer
7
8 $Id$
9
10\********************************************************************/
11
12#include "TMidasOnline.h"
13
14#include <string>
15#include <assert.h>
16
17//#include "midas.h"
18#include "msystem.h"
19//#include "hardware.h"
20//#include "ybos.h"
21
22
24{
25 fDB = 0;
26 fStartHandler = 0;
27 fStopHandler = 0;
28 fPauseHandler = 0;
31 fEventHandler = 0;
32}
33
35{
36 disconnect();
37 assert(!"TMidasOnline::~TMidasOnline(): destruction of the TMidasOnline singleton is not permitted!");
38}
39
41{
42 if (!gfMidas)
43 gfMidas = new TMidasOnline();
44
45 return gfMidas;
46}
47
48int TMidasOnline::connect(const char*hostname,const char*exptname,const char*progname)
49{
50 int status;
51
52 char xhostname[HOST_NAME_LENGTH];
53 char xexptname[NAME_LENGTH];
54
55 /* get default from environment */
56 status = cm_get_environment(xhostname, sizeof(xhostname), xexptname, sizeof(xexptname));
57 assert(status == CM_SUCCESS);
58
59 if (hostname)
60 strlcpy(xhostname,hostname,sizeof(xhostname));
61
62 if (exptname)
63 strlcpy(xexptname,exptname,sizeof(xexptname));
64
65 fHostname = xhostname;
66 fExptname = xexptname;
67
68 fprintf(stderr, "TMidasOnline::connect: Connecting to experiment \"%s\" on host \"%s\"\n", fExptname.c_str(), fHostname.c_str());
69
70 //int watchdog = DEFAULT_WATCHDOG_TIMEOUT;
71 int watchdog = 60*1000;
72
73 status = cm_connect_experiment1((char*)fHostname.c_str(), (char*)fExptname.c_str(), (char*)progname, NULL, DEFAULT_ODB_SIZE, watchdog);
74
75 if (status == CM_UNDEF_EXP)
76 {
77 fprintf(stderr, "TMidasOnline::connect: Error: experiment \"%s\" not defined.\n", fExptname.c_str());
78 return -1;
79 }
80 else if (status != CM_SUCCESS)
81 {
82 fprintf(stderr, "TMidasOnline::connect: Cannot connect to MIDAS, status %d.\n", status);
83 return -1;
84 }
85
86 status = cm_get_experiment_database(&fDB, NULL);
87 assert(status == CM_SUCCESS);
88
89 cm_set_watchdog_params(true, 60*1000);
90
91 return 0;
92}
93
95{
96 if (fDB)
97 {
98 fprintf(stderr, "TMidasOnline::disconnect: Disconnecting from experiment \"%s\" on host \"%s\"\n", fExptname.c_str(), fHostname.c_str());
99 cm_disconnect_experiment();
100 fDB = 0;
101 }
102
103 return 0;
104}
105
107{
108 cm_register_transition(TR_START, NULL, 300);
109 cm_register_transition(TR_PAUSE, NULL, 700);
110 cm_register_transition(TR_RESUME, NULL, 300);
111 cm_register_transition(TR_STOP, NULL, 700);
112}
113
114void TMidasOnline::setTransitionHandlers(TransitionHandler start,TransitionHandler stop,TransitionHandler pause,TransitionHandler resume)
115{
116 fStartHandler = start;
117 fStopHandler = stop;
118 fPauseHandler = pause;
119 fResumeHandler = resume;
120}
121
123{
124 int transition, run_number, trans_time;
125
126 int status = cm_query_transition(&transition, &run_number, &trans_time);
127 if (status != CM_SUCCESS)
128 return false;
129
130 //printf("cm_query_transition: status %d, tr %d, run %d, time %d\n",status,transition,run_number,trans_time);
131
132 for (unsigned i=0; i<fHandlers.size(); i++)
133 fHandlers[i]->Transition(transition, run_number, trans_time);
134
135 if (transition == TR_START)
136 {
137 if (fStartHandler)
138 (*fStartHandler)(transition,run_number,trans_time);
139 return true;
140 }
141 else if (transition == TR_STOP)
142 {
143 if (fStopHandler)
144 (*fStopHandler)(transition,run_number,trans_time);
145 return true;
146
147 }
148 else if (transition == TR_PAUSE)
149 {
150 if (fPauseHandler)
151 (*fPauseHandler)(transition,run_number,trans_time);
152 return true;
153
154 }
155 else if (transition == TR_RESUME)
156 {
157 if (fResumeHandler)
158 (*fResumeHandler)(transition,run_number,trans_time);
159 return true;
160 }
161
162 return false;
163}
164
165bool TMidasOnline::poll(int mdelay)
166{
167 //printf("poll!\n");
168
169 if (checkTransitions())
170 return true;
171
172 int status = cm_yield(mdelay);
173 if (status == RPC_SHUTDOWN || status == SS_ABORT)
174 {
175 fprintf(stderr, "TMidasOnline::poll: cm_yield(%d) status %d, shutting down.\n",mdelay,status);
176 disconnect();
177 return false;
178 }
179
180 return true;
181}
182
183bool TMidasOnline::sleep(int mdelay)
184{
185 //printf("poll!\n");
186
187 if (checkTransitions())
188 return true;
189
190 int status = ss_suspend(mdelay, MSG_BM);
191 if (status == SS_SUCCESS)
192 return true;
193 if (status == SS_TIMEOUT)
194 return true;
195#if 0
196 if (status == SS_SERVER_RECV) {
197 //printf("ss_suspend status %d\n", status);
198 // FIXME: maybe sleep here?
199 return true;
200 }
201#endif
202 fprintf(stderr, "TMidasOnline::sleep(): Unexpected ss_suspend() status %d\n", status);
203#if 0
204 if (status == RPC_SHUTDOWN || status == SS_ABORT)
205 {
206 fprintf(stderr, "TMidasOnline::poll: cm_yield(%d) status %d, shutting down.\n",mdelay,status);
207 disconnect();
208 return false;
209 }
210#endif
211
212 return true;
213}
214
215void TMidasOnline::setEventHandler(EventHandler handler)
216{
217 fEventHandler = handler;
218}
219
220static void eventCallback(HNDLE buffer_handle, HNDLE request_id, EVENT_HEADER* pheader, void* pevent)
221{
222#if 0
223 printf("eventCallback: buffer %d, request %d, pheader %p (event_id: %d, trigger mask: 0x%x, serial: %d, time: %d, size: %d), pevent %p\n",
224 buffer_handle,
225 request_id,
226 pheader,
227 pheader->event_id,
228 pheader->trigger_mask,
229 pheader->serial_number,
230 pheader->time_stamp,
231 pheader->data_size,
232 pevent);
233#endif
234
236
237 for (unsigned i=0; i<midas->fHandlers.size(); i++)
238 midas->fHandlers[i]->Event(pheader, sizeof(EVENT_HEADER) + pheader->data_size);
239
240 if (midas->fEventHandler)
241 midas->fEventHandler(pheader,pevent,pheader->data_size);
242}
243
244int TMidasOnline::receiveEvent(int requestId, void* pevent, int size, bool async)
245{
247
248 while (1)
249 {
250 if (!r)
251 {
252 fprintf(stderr, "TMidasOnline::receiveEvent: Cannot find request %d\n", requestId);
253 return -1;
254 }
255
256 if (r->fRequestId == requestId)
257 break;
258
259 r = r->fNext;
260 }
261
262 int flag = 0;
263 if (async){
264#ifdef BM_NO_WAIT
265 flag = BM_NO_WAIT;
266#else
267 flag = ASYNC;
268#endif
269 }
270
271
272 int status = bm_receive_event(r->fBufferHandle, pevent, &size, flag);
273
274 if (status == BM_ASYNC_RETURN)
275 {
276 return 0;
277 }
278
279 if (status != BM_SUCCESS)
280 {
281 fprintf(stderr, "TMidasOnline::receiveEvent: bm_receive_event() error %d\n", status);
282 return -1;
283 }
284
285 return size;
286}
287
288#ifndef EVENT_BUFFER_SIZE
289#define EVENT_BUFFER_SIZE 0
290#endif
291
292int TMidasOnline::eventRequest(const char* bufferName, int eventId, int triggerMask, int samplingType, bool poll)
293{
294 int status;
295 EventRequest* r = new EventRequest();
296
297 if (bufferName == NULL)
298 bufferName = EVENT_BUFFER_NAME;
299
300 r->fNext = NULL;
301 r->fBufferName = bufferName;
302 r->fEventId = eventId;
303 r->fTriggerMask = triggerMask;
304 r->fSamplingType = samplingType;
305
306
307 /*---- open event buffer ---------------------------------------*/
308 status = bm_open_buffer((char*)bufferName, EVENT_BUFFER_SIZE, &r->fBufferHandle);
309 if (status!=SUCCESS && status!=BM_CREATED)
310 {
311 fprintf(stderr, "TMidasOnline::eventRequest: Cannot find data buffer \"%s\", bm_open_buffer() error %d\n", bufferName, status);
312 return -1;
313 }
314
315 /* set the default buffer cache size (but not GET_RECENT sampling type*/
316 if(samplingType != GET_RECENT){
317 status = bm_set_cache_size(r->fBufferHandle, 100000, 0);
318 assert(status == BM_SUCCESS);
319 }
320
321 if (poll)
322 status = bm_request_event(r->fBufferHandle, r->fEventId, r->fTriggerMask, r->fSamplingType, &r->fRequestId, NULL);
323 else
324 status = bm_request_event(r->fBufferHandle, r->fEventId, r->fTriggerMask, r->fSamplingType, &r->fRequestId, eventCallback);
325 assert(status == BM_SUCCESS);
326
327 fprintf(stderr, "TMidasOnline::eventRequest: Event request: buffer \"%s\" (%d), event id 0x%x, trigger mask 0x%x, sample %d, request id: %d\n",bufferName,r->fBufferHandle,r->fEventId,r->fTriggerMask,r->fSamplingType,r->fRequestId);
328
330 fEventRequests = r;
331
332 return r->fRequestId;
333};
334
336
337 if(!fEventRequests || !fEventRequests->fBufferHandle) return -1;
338
339 int n_bytes;
340 bm_get_buffer_level(fEventRequests->fBufferHandle, &n_bytes);
341
342 return n_bytes;
343
344}
345
347
348 if(!fEventRequests || !fEventRequests->fBufferHandle) return -1;
349
350 BUFFER_HEADER buffer_header;
351 bm_get_buffer_info(fEventRequests->fBufferHandle,&buffer_header);
352
353 return buffer_header.size;
354
355}
357{
358 for (EventRequest* r = fEventRequests; r != NULL; r = r->fNext)
359 if (r->fRequestId == requestId)
360 {
361 int status = bm_delete_request(r->fRequestId);
362 assert(status == BM_SUCCESS);
363
364 r->fBufferHandle = -1;
365 r->fRequestId = -1;
366 }
367}
368
372
374{
375 fHandlers.push_back(h);
376}
377
379
380//end
static void eventCallback(HNDLE buffer_handle, HNDLE request_id, EVENT_HEADER *pheader, void *pevent)
#define EVENT_BUFFER_SIZE
MIDAS online connection, including access to online ODB.
virtual ~TMHandlerInterface()
std::vector< TMHandlerInterface * > fHandlers
void RegisterHandler(TMHandlerInterface *h)
void setEventHandler(EventHandler handler)
Specify user handler for data events.
int receiveEvent(int requestId, void *pevent, int size, bool async)
Receive event by polling.
void registerTransitions()
Ask MIDAS to tell us about run transitions.
bool checkTransitions()
Check for pending transitions, call user handlers. Returns "true" if there were transitions.
TMidasOnline()
default constructor is private for singleton classes
std::string fExptname
experiment name, blank if only one experiment defined in exptab
TransitionHandler fPauseHandler
void deleteEventRequest(int requestId)
Delete data request.
TransitionHandler fStartHandler
bool sleep(int mdelay)
Sleep while checking for and answering MIDAS RPC requests (run transitions, etc)
int disconnect()
Disconnect from MIDAS.
TransitionHandler fStopHandler
TransitionHandler fResumeHandler
static TMidasOnline * instance()
EventRequest * fEventRequests
int getBufferLevel()
Get buffer level (ie the number of bytes in buffer)
int connect(const char *hostname, const char *exptname, const char *progname)
Connect to MIDAS experiment.
HNDLE fDB
ODB handle.
void setTransitionHandlers(TransitionHandler start, TransitionHandler stop, TransitionHandler pause, TransitionHandler resume)
Specify user handlers for run transitions.
virtual ~TMidasOnline()
destructor is private for singleton classes
int getBufferSize()
Get buffer size.
int eventRequest(const char *bufferName, int eventId, int triggerMask, int samplingType, bool poll=false)
Request data for delivery via callback (setEventHandler) or by polling (via receiveEvent)
EventHandler fEventHandler
static TMidasOnline * gfMidas
std::string fHostname
hostname where the mserver is running, blank if using shared memory
bool poll(int mdelay)
Check for all MIDAS events (new data events, run transitions)
Request events from online shared memory data buffer.
int fTriggerMask
request trigger mask
int fRequestId
request ID assigned by midas
int fEventId
request event ID
std::string fBufferName
name of the midas data buffer, e.g. "SYSTEM"
EventRequest * fNext
(internal use) list of all requests
HNDLE fBufferHandle
buffer handle from bm_open_buffer()
int fSamplingType
sampling type