00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <RunObject.hxx>
00029 #include <unistd.h>
00030 #include <time.h>
00031 #include <sstream>
00032
00033
00034 using namespace std;
00035 using namespace cmsg;
00036 using namespace codaObject;
00037
00038
00039
00040
00041
00052 RunObject::RunObject(const string& udl, const string& Name, const string& Descr, const string &cClass,
00053 const cMsgSubscriptionConfig *scfg) throw(CodaException)
00054 : SessionObject(udl,Name,Descr,cClass,scfg), runNumber(0), runType("unknown"),
00055 runStatisticsInterval(1), eventNumber(0), eventRate(0.0), dataCount(0), dataRate(0.0),
00056 hasDLL(false), dllFileName(""), dllHandle(NULL), dllUserArg(NULL),
00057 runControlCBD(new cMsgDispatcher<RunObject>(this,&RunObject::runControlCallback)),
00058 runTransitionCBD(new cMsgDispatcher<RunObject>(this,&RunObject::runTransitionCallback)),
00059 transitionThreadId(0), statisticsThreadDispatcher(NULL), rcsSubId(NULL), rtsSubId(NULL) {
00060
00061
00062 if(debug!=0)cout << "Entering RunObject constructor..." << endl;
00063
00064
00065
00066 objectType = "RunObject";
00067
00068
00069
00070 if(debug!=0)cout << "...RunObject constructor initializing mutexes..." << endl;
00071 pthread_mutex_init(&runTransitionMutex,NULL);
00072 pthread_mutex_init(&runResetMutex,NULL);
00073
00074
00075
00076 if(debug!=0)cout << "...RunObject constructor subscriptions..." << endl;
00077 try {
00078 rcConn->subscribe(name, "run/transition/*", runTransitionCBD, NULL, myscfg);
00079 rcConn->subscribe(name, "run/control/*", runControlCBD, NULL, myscfg);
00080 } catch (cMsgException &e) {
00081 string err = "?RunObject constructor...unable to subscribe";
00082 cerr << err << endl;
00083 daLogMsg(err,DALOG_ERROR);
00084 throw(CodaException(e.toString()));
00085 } catch (...) {
00086 throw(CodaException("?RunObject constructor...unknown exception, unable to subscribe"));
00087 }
00088
00089
00090
00091 #ifndef VXWORKS
00092 dllSysArg.pRunNumber = &runNumber;
00093 dllSysArg.pDataBuffer = NULL;
00094 #endif
00095
00096
00097 if(debug!=0)cout << "...leaving RunObject constructor" << endl;
00098 }
00099
00100
00101
00102
00103
00107 RunObject::~RunObject(void) throw() {
00108
00109 if(debug!=0)cout << "Entering RunObject destructor..." << endl;
00110
00111
00112 if(runStatisticsThreadId!=0) {
00113 pthread_cancel(runStatisticsThreadId);
00114 runStatisticsThreadId=0;
00115 if(statisticsThreadDispatcher!=NULL)delete(statisticsThreadDispatcher);
00116 statisticsThreadDispatcher=NULL;
00117 }
00118
00119 if(runControlCBD!=NULL) {
00120 delete(runControlCBD);
00121 runControlCBD=NULL;
00122 }
00123
00124 if(runTransitionCBD!=NULL) {
00125 delete(runTransitionCBD);
00126 runTransitionCBD=NULL;
00127 }
00128
00129 if(debug!=0)cout << "...leaving RunObject destructor" << endl;
00130 }
00131
00132
00133
00134
00135
00139 void RunObject::startProcessing(void) throw(CodaException) {
00140
00141
00142 if(debug!=0)cout << "Entering RunObject startProcessing..." << endl;
00143
00144
00145 if(statisticsThreadDispatcher==NULL) {
00146
00147
00148 statisticsThreadDispatcher = new pthreadDispatcher<RunObject,void*,void*>(this,&RunObject::runStatisticsThread,NULL);
00149
00150
00151
00152 if(debug!=0)cout << "...launching RunObject statistics thread..." << endl;
00153 if(pthread_create(&runStatisticsThreadId,NULL,
00154 pthreadDispatcher<RunObject,void*,void*>::dispatchIt,(void*)statisticsThreadDispatcher)==0) {
00155 pthread_detach(runStatisticsThreadId);
00156 } else {
00157 runStatisticsThreadId=0;
00158 delete(statisticsThreadDispatcher);
00159 statisticsThreadDispatcher=NULL;
00160 string err = "?RunObject::startProcessing...unable to launch run statistics thread";
00161 cerr << err << endl;
00162 daLogMsg(err,DALOG_ERROR);
00163 }
00164
00165 } else {
00166 cerr << "RunObject::startProcessing: attempt to start a second run statistics thread ignored" << endl;
00167 }
00168
00169
00170
00171 SessionObject::startProcessing();
00172
00173
00174 if(debug!=0)cout << "...leaving RunObject startProcessing" << endl;
00175 }
00176
00177
00178
00179
00180
00187 void RunObject::runControlCallback(cMsgMessage *msg, void* userArg) throw(CodaException) {
00188
00189 string s = msg->getType();
00190 std::transform(s.begin(), s.end(), s.begin(), (int(*)(int)) tolower);
00191
00192
00193 if(debug!=0)cout << "runControlCallback received message with subject,type " << msg->getSubject()
00194 << ", " << s << endl;
00195
00196
00197 if(s=="run/control/getrunnumber") {
00198 stringstream ss;
00199 ss << runNumber;
00200 sendResponse(msg,name,"rc/response/getRunNumber",ss.str(),0);
00201
00202 } else if(s=="run/control/setrunnumber") {
00203 runNumber=msg->getInt32("runNumber");
00204 stringstream ss;
00205 ss << "RunObject::runControlCallback: new run number is " << runNumber << ends;
00206 cout << ss.str() << endl;
00207 daLogMsg(ss.str(),DALOG_INFO);
00208
00209 } else if(s=="run/control/getruntype") {
00210 sendResponse(msg,name,"rc/response/getRunType",runType,0);
00211
00212 } else if(s=="run/control/setruntype") {
00213 runType=msg->getText();
00214
00215 } else if(s=="run/control/enabledll") {
00216 #ifndef VXWORKS
00217 hasDLL=true;
00218 #endif
00219
00220 } else if(s=="run/control/disabledll") {
00221 #ifndef VXWORKS
00222 hasDLL=false;
00223 #endif
00224
00225 } else {
00226
00227 userMsgHandler(msg,userArg);
00228 return;
00229 }
00230
00231 delete(msg);
00232 }
00233
00234
00235
00236
00237
00244 void RunObject::runTransitionCallback(cMsgMessage *msg, void* userArg) throw(CodaException) {
00245
00246 string s = msg->getType();
00247 std::transform(s.begin(), s.end(), s.begin(), (int(*)(int)) tolower);
00248
00249
00250 if(debug!=0)cout << "runTransitionCallback received message type " << s << endl;
00251
00252
00253 if(s=="run/transition/download") {
00254 handleDownload(msg);
00255
00256 } else if(s=="run/transition/prestart") {
00257 handlePrestart(msg);
00258
00259 } else if(s=="run/transition/go") {
00260 handleGo(msg);
00261
00262 } else if(s=="run/transition/pause") {
00263 handlePause(msg);
00264
00265 } else if(s=="run/transition/resume") {
00266 handleResume(msg);
00267
00268 } else if(s=="run/transition/end") {
00269 handleEnd(msg);
00270
00271 } else if(s=="run/transition/reset") {
00272 handleReset(msg);
00273
00274 } else if(s=="run/transition/configure") {
00275 handleConfigure(msg);
00276
00277 } else {
00278
00279 userMsgHandler(msg,userArg);
00280 return;
00281 }
00282
00283 delete(msg);
00284 }
00285
00286
00287
00288
00294 void RunObject::handleConfigure(const cMsgMessage *msg) throw(CodaException) {
00295 try {
00296
00297
00298 configure(msg);
00299
00300 } catch (cMsgException e) {
00301 cout << "?RunObject::handleConfigure: invalid payload items" << endl;
00302 }
00303
00304 }
00305
00306
00307
00313 void RunObject::handleDownload(const cMsgMessage *msg) throw(CodaException) {
00314 dispatchTransition(&RunObject::download,msg->getText());
00315 }
00316
00317
00318
00319
00320
00326 void RunObject::handlePrestart(const cMsgMessage *msg) throw(CodaException) {
00327 dispatchTransition(&RunObject::prestart,msg->getText());
00328 }
00329
00330
00331
00332
00333
00339 void RunObject::handleGo(const cMsgMessage *msg) throw(CodaException) {
00340 dispatchTransition(&RunObject::go,msg->getText());
00341 }
00342
00343
00344
00345
00346
00352 void RunObject::handlePause(const cMsgMessage *msg) throw(CodaException) {
00353 dispatchTransition(&RunObject::pause,msg->getText());
00354 }
00355
00356
00357
00358
00359
00365 void RunObject::handleResume(const cMsgMessage *msg) throw(CodaException) {
00366 dispatchTransition(&RunObject::resume,msg->getText());
00367 }
00368
00369
00370
00371
00372
00378 void RunObject::handleEnd(const cMsgMessage *msg) throw(CodaException) {
00379 dispatchTransition(&RunObject::end,msg->getText());
00380 }
00381
00382
00383
00384
00385
00391 void RunObject::handleReset(const cMsgMessage *msg) throw(CodaException) {
00392 reset(msg->getText());
00393 }
00394
00395
00396
00397
00398
00406 void RunObject::dispatchTransition(bool (RunObject::*mfp)(const string &s), const string &s) {
00407
00408
00409
00410 pthread_mutex_lock(&runTransitionMutex);
00411
00412
00413
00414 pthreadDispatcher<RunObject,bool,const string&> pd(this,mfp,s);
00415
00416
00417
00418 if(pthread_create(&transitionThreadId,NULL,pthreadDispatcher<RunObject,bool,const string&>::dispatchIt,(void*)&pd)==0) {
00419 static_cast<int>(pthread_join(transitionThreadId,NULL));
00420 transitionThreadId=0;
00421 }
00422
00423
00424
00425 pthread_mutex_unlock(&runTransitionMutex);
00426 }
00427
00428
00429
00430
00436 void RunObject::handleSetSession(const string &newSession) throw(CodaException) {
00437
00438 if(debug!=0)cout << "in RunObject::handleSetSession" << endl;
00439
00440
00441 if(newSession==session) {
00442 string info = "RunObject::handleSetSession...new session " + session + " same as old";
00443 cout << info << endl;
00444 daLogMsg(info,DALOG_INFO);
00445 return;
00446 }
00447
00448
00449
00450 try {
00451 if(rcsSubId!=NULL) {
00452 rcConn->unsubscribe(rcsSubId);
00453 rcsSubId=NULL;
00454 }
00455 if(rtsSubId!=NULL) {
00456 rcConn->unsubscribe(rtsSubId);
00457 rtsSubId=NULL;
00458 }
00459 } catch (cMsgException e) {
00460 string err = "?RunObject::handleSetSession...unable to unsubscribe";
00461 cerr << err << endl;
00462 daLogMsg(err,DALOG_ERROR);
00463 throw(CodaException(err));
00464 } catch (...) {
00465 string err = "?RunObject::handleSetSession...unknown exception, unable to unsubscribe";
00466 cerr << err << endl;
00467 daLogMsg(err,DALOG_ERROR);
00468 throw(CodaException(err));
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 try {
00484 rcsSubId=rcConn->subscribe(newSession,"run/control/*", runControlCBD, NULL, myscfg);
00485 rtsSubId=rcConn->subscribe(newSession,"run/transition/*", runTransitionCBD, NULL, myscfg);
00486 } catch (cMsgException e) {
00487 string err = "?RunObject::handleSetSession...unable to subscribe";
00488 cerr << err << endl;
00489 daLogMsg(err,DALOG_ERROR);
00490 throw(CodaException(e.toString()));
00491 } catch (...) {
00492 string err = "?RunObject::handleSetSession...unknown exception, unable to subscribe";
00493 cerr << err << endl;
00494 daLogMsg(err,DALOG_ERROR);
00495 throw(CodaException(err));
00496 }
00497
00498
00499
00500 string info = "RunObject...switched to new session " + newSession;
00501 cout << info << endl;
00502 daLogMsg(info,DALOG_INFO);
00503
00504
00505
00506 if(debug!=0)cout << "RunObject::handleSetSession dispatching to SessionObject::handleSetSession" << endl;
00507 SessionObject::handleSetSession(newSession);
00508 }
00509
00510
00511
00512
00513
00514 void RunObject::handleSetSession(const cMsgMessage *msg) throw(CodaException) {
00515 handleSetSession(msg->getText());
00516 }
00517
00518
00519
00520
00521
00525 void* RunObject::runStatisticsThread(void*) {
00526
00527 time_t now,lastTime=time(NULL);
00528 int delta,lastEventNumber=0,lastDataCount=0;
00529
00530 if(debug!=0)cout << "runStatisticsThread starting" << endl;
00531
00532
00533
00534 while(true) {
00535 sleep(runStatisticsInterval);
00536
00537
00538
00539 now = time(NULL);
00540 delta = now-lastTime;
00541 eventRate = (delta>0)?(eventNumber-lastEventNumber)/delta:0.0;
00542 dataRate = (delta>0)?(dataCount-lastDataCount)/delta:0.0;
00543 lastTime = now;
00544 lastEventNumber = eventNumber;
00545 lastDataCount = dataCount;
00546 }
00547
00548 return(NULL);
00549
00550 }
00551
00552
00553
00554
00555
00561 void RunObject::fillReport(cMsgMessage *m) throw() {
00562 SessionObject::fillReport(m);
00563 m->add("eventNumber",(int32_t)eventNumber);
00564 m->add("eventRate",eventRate);
00565 m->add("dataRate",dataRate);
00566 m->add("dataCount",(int32_t)dataCount);
00567 m->add("liveTime",liveTime);
00568
00569 }
00570
00571
00572
00578 int RunObject::getRunNumber(void) const throw() {
00579 return(runNumber);
00580 }
00581
00582
00583
00584
00585
00591 string RunObject::getRunType(void) const throw() {
00592 return(runType);
00593 }
00594
00595
00596
00597
00603 bool RunObject::configure(const cMsgMessage *msg) throw(CodaException) {
00604
00605 try {
00606 changeState("configuring");
00607 userConfigure(msg->getString("config"));
00608 changeState("configured");
00609 } catch (cMsgException e) {
00610 cout << "?RunObject::handleConfigure: Did not configure" << endl;
00611 }
00612 return(true);
00613 }
00614
00615
00616
00620 void RunObject::setDllUserArg(void *arg) throw() {
00621 #ifndef VXWORKS
00622 dllUserArg=arg;
00623 #endif
00624 }
00625
00626
00627
00628
00629
00636 bool RunObject::download(const string& s) throw(CodaException) {
00637
00638 if(debug!=0)cout << "Entering RunObject download" << endl;
00639
00640
00641 bool stat=true;
00642 changeState("downloading");
00643
00644
00645
00646 #ifndef VXWORKS
00647 if(hasDLL&&(s!=dllFileName)) {
00648 dllFileName=s;
00649
00650 if(dllHandle!=NULL)dlclose(dllHandle);
00651 dllHandle = dlopen(s.c_str(),RTLD_NOW);
00652 if(dllHandle==NULL) {
00653 stringstream ss;
00654 ss << "?RunObject::download unable to load dll: " << dllFileName << endl << " " << dlerror() << ends;
00655 cerr << ss.str() << endl;
00656 daLogMsg(ss.str(),DALOG_ERROR);
00657 return(false);
00658 }
00659 string info = "RunObject::download loaded dll file: " + dllFileName;
00660 cout << info << endl;
00661 daLogMsg(info,DALOG_INFO);
00662
00663
00664
00665 dllDownload = (dllFuncPtr)dlsym(dllHandle,"download");
00666 dllPrestart = (dllFuncPtr)dlsym(dllHandle,"prestart");
00667 dllGo = (dllFuncPtr)dlsym(dllHandle,"go");
00668 dllPause = (dllFuncPtr)dlsym(dllHandle,"pause");
00669 dllResume = (dllFuncPtr)dlsym(dllHandle,"resume");
00670 dllEnd = (dllFuncPtr)dlsym(dllHandle,"end");
00671 dllReset = (dllFuncPtr)dlsym(dllHandle,"reset");
00672 }
00673 #endif
00674
00675
00676
00677 if(hasDLL&&(dllDownload!=NULL)) {
00678 #ifndef VXWORKS
00679 stat=dllDownload(s.c_str(),(void *)&dllSysArg,NULL);
00680 #endif
00681 } else {
00682 stat=userDownload(s);
00683 }
00684
00685
00686
00687 if(stat)changeState("downloaded");
00688 daLogMsg(name + "..completed download transition",DALOG_INFO);
00689 return(stat);
00690 }
00691
00692
00693
00694
00695
00702 bool RunObject::prestart(const string& s) throw(CodaException) {
00703
00704 if(debug!=0)cout << "Entering RunObject prestart" << endl;
00705
00706
00707 bool stat=true;
00708 changeState("prestarting");
00709
00710
00711
00712 eventNumber=0;
00713 eventRate=0.0;
00714 dataCount=0;
00715 dataRate=0.0;
00716
00717
00718 if(hasDLL&&(dllPrestart!=NULL)) {
00719 #ifndef VXWORKS
00720 stat=dllPrestart(s.c_str(),(void *)&dllSysArg,NULL);
00721 #endif
00722 } else {
00723 stat=userPrestart(s);
00724 }
00725
00726 if(stat)changeState("paused");
00727 daLogMsg(name+"...completed prestart transition",DALOG_INFO);
00728 return(stat);
00729 }
00730
00731
00732
00733
00734
00741 bool RunObject::go(const string& s) throw(CodaException) {
00742
00743 if(debug!=0)cout << "Entering RunObject go" << endl;
00744
00745
00746 bool stat=true;
00747 changeState("going");
00748
00749
00750 if(hasDLL&&(dllGo!=NULL)) {
00751 #ifndef VXWORKS
00752 stat=dllGo(s.c_str(),(void *)&dllSysArg,NULL);
00753 #endif
00754 } else {
00755 stat=userGo(s);
00756 }
00757
00758 if(stat)changeState("active");
00759 daLogMsg(name+"...completed go transition",DALOG_INFO);
00760 return(stat);
00761 }
00762
00763
00764
00765
00766
00773 bool RunObject::pause(const string& s) throw(CodaException) {
00774
00775 if(debug!=0)cout << "Entering RunObject pause" << endl;
00776
00777
00778 bool stat=true;
00779 changeState("pausing");
00780
00781 if(hasDLL&&(dllPause!=NULL)) {
00782 #ifndef VXWORKS
00783 stat=dllPause(s.c_str(),(void *)&dllSysArg,NULL);
00784 #endif
00785 } else {
00786 stat=userPause(s);
00787 }
00788
00789 if(stat)changeState("paused");
00790 daLogMsg(name+"...completed pause transition",DALOG_INFO);
00791 return(stat);
00792 }
00793
00794
00795
00796
00797
00804 bool RunObject::resume(const string& s) throw(CodaException) {
00805
00806 if(debug!=0)cout << "Entering RunObject resume" << endl;
00807
00808
00809 bool stat=true;
00810 changeState("resuming");
00811
00812 if(hasDLL&&(dllResume!=NULL)) {
00813 #ifndef VXWORKS
00814 stat=dllResume(s.c_str(),(void *)&dllSysArg,NULL);
00815 #endif
00816 } else {
00817 stat=userResume(s);
00818 }
00819
00820 if(stat)changeState("active");
00821 daLogMsg(name+"...completed resume transition",DALOG_INFO);
00822 return(stat);
00823 }
00824
00825
00826
00827
00828
00835 bool RunObject::end(const string& s) throw(CodaException) {
00836
00837 if(debug!=0)cout << "Entering RunObject end" << endl;
00838
00839
00840 bool stat=true;
00841 changeState("ending");
00842
00843 if(hasDLL&&(dllEnd!=NULL)) {
00844 #ifndef VXWORKS
00845 stat=dllEnd(s.c_str(),(void *)&dllSysArg,NULL);
00846 #endif
00847 } else {
00848 stat=userEnd(s);
00849 }
00850
00851 if(stat)changeState("downloaded");
00852 daLogMsg(name+"...completed end transition",DALOG_INFO);
00853 return(stat);
00854 }
00855
00856
00857
00858
00859
00866 bool RunObject::reset(const string& s) throw(CodaException) {
00867
00868 if(debug!=0)cout << "Entering RunObject reset" << endl;
00869
00870
00871 bool stat1=true;
00872 bool stat2=true;
00873 changeState("resetting");
00874
00875
00876
00877 pthread_mutex_lock(&runResetMutex);
00878
00879
00880
00881 if(transitionThreadId!=0) {
00882 stat1=(pthread_cancel(transitionThreadId)==0);
00883 if(stat1)pthread_join(transitionThreadId,NULL);
00884 transitionThreadId=0;
00885 }
00886
00887
00888 if(hasDLL&&(dllReset!=NULL)) {
00889 #ifndef VXWORKS
00890 stat2=dllReset(s.c_str(),(void *)&dllSysArg,NULL);
00891 #endif
00892 } else {
00893 stat2=userReset(s);
00894 }
00895
00896
00897
00898 pthread_mutex_unlock(&runResetMutex);
00899
00900 if(stat1&&stat2)changeState("configured");
00901 daLogMsg(name+"...completed reset transition",DALOG_INFO);
00902 return(stat1&&stat2);
00903 }
00904
00905
00906
00907
00908
00914 void RunObject::daLogMsgFill(cMsgMessage &m) const throw(CodaException) {
00915 SessionObject::daLogMsgFill(m);
00916 m.add("RunType",getRunType());
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00928 bool RunObject::userConfigure(const string& runConfig) throw(CodaException) {
00929 string info = "default userConfigure called";
00930 cout << info << endl;
00931 daLogMsg(info,DALOG_INFO);
00932 return(true);
00933 }
00934
00936 bool RunObject::userDownload(const string& s) throw(CodaException) {
00937 string info = "default userDownload called";
00938 cout << info << endl;
00939 daLogMsg(info,DALOG_INFO);
00940 return(true);
00941 }
00942
00944 bool RunObject::userPrestart(const string& s) throw(CodaException) {
00945 string info = "default userPrestart called";
00946 cout << info << endl;
00947 daLogMsg(info,DALOG_INFO);
00948 return(true);
00949 }
00950
00952 bool RunObject::userGo(const string& s) throw(CodaException) {
00953 string info = "default userGo called";
00954 cout << info << endl;
00955 daLogMsg(info,DALOG_INFO);
00956 return(true);
00957 }
00958
00960 bool RunObject::userPause(const string& s) throw(CodaException) {
00961 string info = "default userPause called";
00962 cout << info << endl;
00963 daLogMsg(info,DALOG_INFO);
00964 return(true);
00965 }
00966
00968 bool RunObject::userResume(const string& s) throw(CodaException) {
00969 string info = "default userResume called";
00970 cout << info << endl;
00971 daLogMsg(info,DALOG_INFO);
00972 return(true);
00973 }
00974
00976 bool RunObject::userEnd(const string& s) throw(CodaException) {
00977 string info = "default userEnd called";
00978 cout << info << endl;
00979 daLogMsg(info,DALOG_INFO);
00980 return(true);
00981 }
00982
00984 bool RunObject::userReset(const string& s) throw(CodaException) {
00985 string info = "default userReset called";
00986 cout << info << endl;
00987 daLogMsg(info,DALOG_INFO);
00988 return(true);
00989 }
00990
00991