00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TMidasOnline.h"
00013
00014 #include <string>
00015 #include <assert.h>
00016 #include "midas.h"
00017 #include "msystem.h"
00018
00019
00020
00021
00022 TMidasOnline::TMidasOnline()
00023 {
00024 fDB = 0;
00025 fStartHandler = 0;
00026 fStopHandler = 0;
00027 fPauseHandler = 0;
00028 fResumeHandler = 0;
00029 fEventRequests = 0;
00030 fEventHandler = 0;
00031 }
00032
00033 TMidasOnline::~TMidasOnline()
00034 {
00035 disconnect();
00036 }
00037
00038 TMidasOnline* TMidasOnline::instance()
00039 {
00040 if (!gfMidas)
00041 gfMidas = new TMidasOnline();
00042
00043 return gfMidas;
00044 }
00045
00046 int TMidasOnline::connect(const char*hostname,const char*exptname,const char*progname)
00047 {
00048 int status;
00049
00050 char xhostname[HOST_NAME_LENGTH];
00051 char xexptname[NAME_LENGTH];
00052
00053
00054 status = cm_get_environment(xhostname, sizeof(xhostname), xexptname, sizeof(xexptname));
00055 assert(status == CM_SUCCESS);
00056
00057 if (hostname)
00058 strlcpy(xhostname,hostname,sizeof(xhostname));
00059
00060 if (exptname)
00061 strlcpy(xexptname,exptname,sizeof(xexptname));
00062
00063 fHostname = xhostname;
00064 fExptname = xexptname;
00065
00066 fprintf(stderr, "TMidasOnline::connect: Connecting to experiment \"%s\" on host \"%s\"\n", fExptname.c_str(), fHostname.c_str());
00067
00068
00069 int watchdog = 60*1000;
00070
00071 status = cm_connect_experiment1((char*)fHostname.c_str(), (char*)fExptname.c_str(), (char*)progname, NULL, DEFAULT_ODB_SIZE, watchdog);
00072
00073 if (status == CM_UNDEF_EXP)
00074 {
00075 fprintf(stderr, "TMidasOnline::connect: Error: experiment \"%s\" not defined.\n", fExptname.c_str());
00076 return -1;
00077 }
00078 else if (status != CM_SUCCESS)
00079 {
00080 fprintf(stderr, "TMidasOnline::connect: Cannot connect to MIDAS, status %d.\n", status);
00081 return -1;
00082 }
00083
00084 status = cm_get_experiment_database(&fDB, NULL);
00085 assert(status == CM_SUCCESS);
00086
00087 cm_set_watchdog_params(true, 60*1000);
00088
00089 return 0;
00090 }
00091
00092 int TMidasOnline::disconnect()
00093 {
00094 if (fDB)
00095 {
00096 fprintf(stderr, "TMidasOnline::disconnect: Disconnecting from experiment \"%s\" on host \"%s\"\n", fExptname.c_str(), fHostname.c_str());
00097 cm_disconnect_experiment();
00098 fDB = 0;
00099 }
00100
00101 return 0;
00102 }
00103
00104 void TMidasOnline::registerTransitions()
00105 {
00106 cm_register_transition(TR_START, NULL, 300);
00107 cm_register_transition(TR_PAUSE, NULL, 700);
00108 cm_register_transition(TR_RESUME, NULL, 300);
00109 cm_register_transition(TR_STOP, NULL, 700);
00110 }
00111
00112 void TMidasOnline::setTransitionHandlers(TransitionHandler start,TransitionHandler stop,TransitionHandler pause,TransitionHandler resume)
00113 {
00114 fStartHandler = start;
00115 fStopHandler = stop;
00116 fPauseHandler = pause;
00117 fResumeHandler = resume;
00118 }
00119
00120 bool TMidasOnline::checkTransitions()
00121 {
00122 int transition, run_number, trans_time;
00123
00124 int status = cm_query_transition(&transition, &run_number, &trans_time);
00125 if (status != CM_SUCCESS)
00126 return false;
00127
00128
00129
00130 if (transition == TR_START)
00131 {
00132 if (fStartHandler)
00133 (*fStartHandler)(transition,run_number,trans_time);
00134 return true;
00135 }
00136 else if (transition == TR_STOP)
00137 {
00138 if (fStopHandler)
00139 (*fStopHandler)(transition,run_number,trans_time);
00140 return true;
00141
00142 }
00143 else if (transition == TR_PAUSE)
00144 {
00145 if (fPauseHandler)
00146 (*fPauseHandler)(transition,run_number,trans_time);
00147 return true;
00148
00149 }
00150 else if (transition == TR_RESUME)
00151 {
00152 if (fResumeHandler)
00153 (*fResumeHandler)(transition,run_number,trans_time);
00154 return true;
00155 }
00156
00157 return false;
00158 }
00159
00160 bool TMidasOnline::poll(int mdelay)
00161 {
00162
00163
00164 if (checkTransitions())
00165 return true;
00166
00167 int status = cm_yield(mdelay);
00168 if (status == RPC_SHUTDOWN || status == SS_ABORT)
00169 {
00170 fprintf(stderr, "TMidasOnline::poll: cm_yield(%d) status %d, shutting down.\n",mdelay,status);
00171 disconnect();
00172 return false;
00173 }
00174
00175 return true;
00176 }
00177
00178 void TMidasOnline::setEventHandler(EventHandler handler)
00179 {
00180 fEventHandler = handler;
00181 }
00182
00183 static void eventCallback(HNDLE buffer_handle, HNDLE request_id, EVENT_HEADER* pheader, void* pevent)
00184 {
00185 #if 0
00186 printf("eventCallback: buffer %d, request %d, pheader %p (event_id: %d, trigger mask: 0x%x, serial: %d, time: %d, size: %d), pevent %p\n",
00187 buffer_handle,
00188 request_id,
00189 pheader,
00190 pheader->event_id,
00191 pheader->trigger_mask,
00192 pheader->serial_number,
00193 pheader->time_stamp,
00194 pheader->data_size,
00195 pevent);
00196 #endif
00197
00198 if (TMidasOnline::instance()->fEventHandler)
00199 TMidasOnline::instance()->fEventHandler(pheader,pevent,pheader->data_size);
00200 }
00201
00202 int TMidasOnline::receiveEvent(int requestId, void* pevent, int size, bool async)
00203 {
00204 EventRequest* r = fEventRequests;
00205
00206 while (1)
00207 {
00208 if (!r)
00209 {
00210 fprintf(stderr, "TMidasOnline::receiveEvent: Cannot find request %d\n", requestId);
00211 return -1;
00212 }
00213
00214 if (r->fRequestId == requestId)
00215 break;
00216
00217 r = r->fNext;
00218 }
00219
00220 int flag = 0;
00221 if (async){
00222 #ifdef BM_NO_WAIT
00223 flag = BM_NO_WAIT;
00224 #else
00225 flag = ASYNC;
00226 #endif
00227 }
00228
00229
00230 int status = bm_receive_event(r->fBufferHandle, pevent, &size, flag);
00231
00232 if (status == BM_ASYNC_RETURN)
00233 {
00234 return 0;
00235 }
00236
00237 if (status != BM_SUCCESS)
00238 {
00239 fprintf(stderr, "TMidasOnline::receiveEvent: bm_receive_event() error %d\n", status);
00240 return -1;
00241 }
00242
00243 return size;
00244 }
00245
00246 #ifndef EVENT_BUFFER_SIZE
00247 #define EVENT_BUFFER_SIZE 0
00248 #endif
00249
00250 int TMidasOnline::eventRequest(const char* bufferName, int eventId, int triggerMask, int samplingType, bool poll)
00251 {
00252 int status;
00253 EventRequest* r = new EventRequest();
00254
00255 if (bufferName == NULL)
00256 bufferName = EVENT_BUFFER_NAME;
00257
00258 r->fNext = NULL;
00259 r->fBufferName = bufferName;
00260 r->fEventId = eventId;
00261 r->fTriggerMask = triggerMask;
00262 r->fSamplingType = samplingType;
00263
00264
00265
00266 status = bm_open_buffer((char*)bufferName, EVENT_BUFFER_SIZE, &r->fBufferHandle);
00267 if (status!=SUCCESS && status!=BM_CREATED)
00268 {
00269 fprintf(stderr, "TMidasOnline::eventRequest: Cannot find data buffer \"%s\", bm_open_buffer() error %d\n", bufferName, status);
00270 return -1;
00271 }
00272
00273
00274 status = bm_set_cache_size(r->fBufferHandle, 100000, 0);
00275 assert(status == BM_SUCCESS);
00276
00277 if (poll)
00278 status = bm_request_event(r->fBufferHandle, r->fEventId, r->fTriggerMask, r->fSamplingType, &r->fRequestId, NULL);
00279 else
00280 status = bm_request_event(r->fBufferHandle, r->fEventId, r->fTriggerMask, r->fSamplingType, &r->fRequestId, eventCallback);
00281 assert(status == BM_SUCCESS);
00282
00283 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);
00284
00285 r->fNext = fEventRequests;
00286 fEventRequests = r;
00287
00288 return r->fRequestId;
00289 };
00290
00291 int TMidasOnline::getBufferLevel(){
00292
00293 if(!fEventRequests || !fEventRequests->fBufferHandle) return -1;
00294
00295 int n_bytes;
00296 bm_get_buffer_level(fEventRequests->fBufferHandle, &n_bytes);
00297
00298 return n_bytes;
00299
00300 }
00301
00302 int TMidasOnline::getBufferSize(){
00303
00304 if(!fEventRequests || !fEventRequests->fBufferHandle) return -1;
00305
00306 BUFFER_HEADER buffer_header;
00307 bm_get_buffer_info(fEventRequests->fBufferHandle,&buffer_header);
00308
00309 return buffer_header.size;
00310
00311 }
00312 void TMidasOnline::deleteEventRequest(int requestId)
00313 {
00314 for (EventRequest* r = fEventRequests; r != NULL; r = r->fNext)
00315 if (r->fRequestId == requestId)
00316 {
00317 int status = bm_delete_request(r->fRequestId);
00318 assert(status == BM_SUCCESS);
00319
00320 r->fBufferHandle = -1;
00321 r->fRequestId = -1;
00322 }
00323 }
00324
00325
00326
00327
00328 int TMidasOnline::odbReadInt(const char*name,int index,int defaultValue)
00329 {
00330 int value = defaultValue;
00331 if (odbReadAny(name,index,TID_INT,&value) == 0)
00332 return value;
00333 else
00334 return defaultValue;
00335 };
00336
00337 uint32_t TMidasOnline::odbReadUint32(const char*name,int index,uint32_t defaultValue)
00338 {
00339 uint32_t value = defaultValue;
00340 if (odbReadAny(name,index,TID_DWORD,&value) == 0)
00341 return value;
00342 else
00343 return defaultValue;
00344 };
00345
00346 bool TMidasOnline::odbReadBool(const char*name,int index,bool defaultValue)
00347 {
00348 uint32_t value = defaultValue;
00349 if (odbReadAny(name,index,TID_BOOL,&value) == 0)
00350 return value;
00351 else
00352 return defaultValue;
00353 };
00354
00355 float TMidasOnline::odbReadFloat(const char*name,int index,float defaultValue)
00356 {
00357 float value = defaultValue;
00358 if (odbReadAny(name,index,TID_FLOAT,&value) == 0)
00359 return value;
00360 else
00361 return defaultValue;
00362 };
00363
00364 double TMidasOnline::odbReadDouble(const char*name,int index,double defaultValue)
00365 {
00366 double value = defaultValue;
00367 if (odbReadAny(name,index,TID_DOUBLE,&value) == 0)
00368 return value;
00369 else
00370 return defaultValue;
00371 };
00372
00373 const char* TMidasOnline::odbReadString(const char *name, int index, const char *defaultValue)
00374 {
00375 const int bufsize = 1024;
00376 static char buf[bufsize];
00377 if (odbReadAny(name, index, TID_STRING, buf, bufsize) == 0)
00378 return buf;
00379 else
00380 return defaultValue;
00381 };
00382
00383 int TMidasOnline::odbReadArraySize(const char*name)
00384 {
00385 int status;
00386 HNDLE hdir = 0;
00387 HNDLE hkey;
00388 KEY key;
00389
00390 status = db_find_key (fDB, hdir, (char*)name, &hkey);
00391 if (status != SUCCESS)
00392 return 0;
00393
00394 status = db_get_key(fDB, hkey, &key);
00395 if (status != SUCCESS)
00396 return 0;
00397
00398 return key.num_values;
00399 }
00400
00401 int TMidasOnline::odbReadAny(const char*name,int index,int tid,void* buf, int bufsize)
00402 {
00403 int status;
00404 int size = bufsize;
00405 HNDLE hdir = 0;
00406 HNDLE hkey;
00407
00408 if (size == 0)
00409 size = rpc_tid_size(tid);
00410
00411 status = db_find_key (fDB, hdir, (char*)name, &hkey);
00412 if (status == SUCCESS)
00413 {
00414 status = db_get_data_index(fDB, hkey, buf, &size, index, tid);
00415 if (status != SUCCESS)
00416 {
00417 cm_msg(MERROR, "TMidasOnline", "Cannot read \'%s\'[%d] of type %d from odb, db_get_data_index() status %d", name, index, tid, status);
00418 return -1;
00419 }
00420
00421 return 0;
00422 }
00423 else if (status == DB_NO_KEY)
00424 {
00425 cm_msg(MINFO, "TMidasOnline", "Creating \'%s\'[%d] of type %d", name, index, tid);
00426
00427 status = db_create_key(fDB, hdir, (char*)name, tid);
00428 if (status != SUCCESS)
00429 {
00430 cm_msg (MERROR, "TMidasOnline", "Cannot create \'%s\' of type %d, db_create_key() status %d", name, tid, status);
00431 return -1;
00432 }
00433
00434 status = db_find_key (fDB, hdir, (char*)name, &hkey);
00435 if (status != SUCCESS)
00436 {
00437 cm_msg(MERROR, "TMidasOnline", "Cannot create \'%s\', db_find_key() status %d", name, status);
00438 return -1;
00439 }
00440
00441 status = db_set_data_index(fDB, hkey, buf, size, index, tid);
00442 if (status != SUCCESS)
00443 {
00444 cm_msg(MERROR, "TMidasOnline", "Cannot write \'%s\'[%d] of type %d to odb, db_set_data_index() status %d", name, index, tid, status);
00445 return -1;
00446 }
00447
00448 return 0;
00449 }
00450 else
00451 {
00452 cm_msg(MERROR, "TMidasOnline", "Cannot read \'%s\'[%d] from odb, db_find_key() status %d", name, index, status);
00453 return -1;
00454 }
00455 };
00456
00457 TMidasOnline* TMidasOnline::gfMidas = NULL;
00458
00459