00001 #include "CalibrationControllerImpl.h"
00002 #include "ScanLibraryImpl.h"
00003 #include "TestLibraryImpl.h"
00004 #include "SequenceLibraryImpl.h"
00005 #include "SequenceRequestWorker.h"
00006 #include "RunController.h"
00007 #include "SctApiException.h"
00008 #include "ipc/SequenceRequest.h"
00009 #include "scripts/DefaultSequence.h"
00010 #include "scripts/DefaultTest.h"
00011 #include "Sequence.h"
00012 #include "Test.h"
00013 #include "ConfigUpdaterManager.h"
00014
00015 #include "Sct/SctNames.h"
00016 #include "Sct/LogicErrors.h"
00017 #include "Sct/IoExceptions.h"
00018 #include "Sct/IpcException.h"
00019 #include "Sct/IS/IOManagerIS.h"
00020 #include "Sct/IS/IONameIS.h"
00021 #include "Sct_SctApi/Sct_SctApi.hh"
00022 #include "SctData/TestResult.h"
00023 #include <ipc/server.h>
00024 #include <is/isinfotmpl.h>
00025 #include <ilu/iluxport.h>
00026 #include <boost/utility.hpp>
00027 #include <unistd.h>
00028 #include <iostream>
00029
00030 using namespace std;
00031 using namespace Sct;
00032
00033 namespace SctCalibrationController {
00034
00035 using namespace Scripts;
00036
00037 CalibrationControllerImpl::CalibrationControllerImpl(RunControl& rc) : rc(rc), runNumber(0),
00038 nextScanNumber(0), abortNow(false) {
00039 publish();
00040 status.currentScanIndex = 0;
00041 updateStatus();
00042 }
00043
00044 CalibrationControllerImpl::~CalibrationControllerImpl() {
00045 withdraw();
00046
00047
00048 string name = SctNames::getControlDataName();
00049 name += ".Status";
00050 ISInfoDictionary& is = SctNames::getISDictionary();
00051 is.remove(name.c_str());
00052 }
00053
00054 Sct_SctApi_T_SctApi* CalibrationControllerImpl::getApi() const {
00055 return api;
00056 }
00057
00058 void CalibrationControllerImpl::setApi(Sct_SctApi_T_SctApi& api) {
00059 this->api = &api;
00060 }
00061
00062 void CalibrationControllerImpl::reset() {
00063 status.status = status.LOADED;
00064 updateStatus();
00065 api = 0;
00066 }
00067
00068 void CalibrationControllerImpl::sctApiError(SctApiException& e) {
00069 rc.sctApiError(rc.SCTAPI_ACCESS_FAILURE, e.what());
00070 status.status = status.ERROR;
00071 updateStatus();
00072 api = 0;
00073 }
00074
00075 void CalibrationControllerImpl::takeControl(unsigned int runNumber) {
00076 if (status.status != status.LOADED || api == 0)
00077 return;
00078 this->runNumber = runNumber;
00079 nextScanNumber = 0;
00080 status.status = status.INCONTROL;
00081
00082 SctNames::Mrs() << "CC_START" << MRS_TEXT("Calibration Controller taking control") << MRS_INFORMATION << ENDM;
00083 updateStatus();
00084 }
00085
00086 void CalibrationControllerImpl::giveupControl() {
00087 if (status.status == status.INCONTROL) {
00088 SctNames::Mrs() << "CC_END" << MRS_TEXT("Calibration Controller giving up control") << MRS_INFORMATION << ENDM;
00089
00090 status.status = status.LOADED;
00091 updateStatus();
00092 }
00093 }
00094
00095 bool CalibrationControllerImpl::isInControl() {
00096 return status.status == status.INCONTROL;
00097 }
00098
00099 bool CalibrationControllerImpl::isBusy() {
00100 return status.status == status.BUSY;
00101 }
00102
00103 void CalibrationControllerImpl::setBusy(bool busy) {
00104 if (busy && status.status == status.INCONTROL)
00105 status.status = status.BUSY;
00106 else if (!busy && status.status == status.BUSY)
00107 status.status = status.INCONTROL;
00108 updateStatus();
00109 }
00110
00111 unsigned int CalibrationControllerImpl::getRunNumber() const {
00112 return runNumber;
00113 }
00114
00115 unsigned int CalibrationControllerImpl::getNextScanNumber() const {
00116 return nextScanNumber;
00117 }
00118
00119 void CalibrationControllerImpl::setNextScanNumber(unsigned int scanNumber) {
00120 nextScanNumber = scanNumber;
00121
00122 if (api) {
00123 Sct_SctApiStatus st;
00124 api->setScanNumber(&st, scanNumber);
00125 if (st.returnCode != 0)
00126 throw SctApiException(st.returnCode, "setScanNumber failed in setNextScanNumber", __FILE__, __LINE__);
00127 }
00128 }
00129
00130 void CalibrationControllerImpl::abort() {
00131 if (status.status != status.BUSY) return;
00132 abortNow = true;
00133
00134 SctNames::Mrs() << "CC_ABORT" << MRS_TEXT("User requested abort Sequence") << MRS_INFORMATION << ENDM;
00135 }
00136
00137 void CalibrationControllerImpl::executeSequence(SequenceRequest& sr) {
00138 SctNames::Mrs() << "CC_SEQ_START" << MRS_TEXT("Calibration Controller starting sequence") << MRS_INFORMATION << ENDM;
00139
00140 string name;
00141 try {
00142 name = sr.startSequence(*api);
00143 } catch (SctApiException& e) {
00144 sctApiError(e);
00145 throw;
00146 } catch (IpcException& e) {
00147 e.sendToMrs();
00148 return;
00149 }
00150
00151 shared_ptr<Sequence> s = Sequence::create(name, runNumber, nextScanNumber);
00152
00153 status.currentSequence = s->getUniqueID();
00154 updateStatus();
00155
00156 TestRequest* tr = 0;
00157 unsigned long index = 0;
00158 try {
00159 do {
00160 tr = sr.getNextTest(index);
00161 if (tr) {
00162 unsigned firstScanInTest = getNextScanNumber();
00163 unsigned runNumber = getRunNumber();
00164 s->addTest(executeTest(*tr));
00165
00166
00167 if (s->getTest(index)->getData().status != TestData::COMPLETED) {
00168 SctNames::Mrs() << "CC_SEQ_END" << MRS_TEXT("Calibration Controller aborting sequence") << MRS_INFORMATION << ENDM;
00169 s->setStatus(SequenceData::ABORTED);
00170 return;
00171 }
00172
00173 if (tr->canFeedback()) {
00174 std::list<std::string> moduleList = getAllModulesForScan(s->getTest(0)->getScan(0));
00175 applyChanges(runNumber, firstScanInTest, moduleList);
00176 Sct_SctApiStatus st;
00177
00178 api->setABCDModules(&st, Sct_SctApi_T_BankType_PHYICS_CONFIG);
00179 if (st.returnCode != 0)
00180 throw SctApiException(st.returnCode, "setABCDModules failed after update", __FILE__, __LINE__);
00181 }
00182 }
00183 ++index;
00184 } while (tr != 0);
00185
00186 SctNames::Mrs() << "CC_SEQ_END" << MRS_TEXT("Calibration Controller ending sequence") << MRS_INFORMATION << ENDM;
00187 sr.endSequence();
00188 s->setStatus(SequenceData::COMPLETED);
00189
00190 } catch (SctApiException& e) {
00191 sctApiError(e);
00192 throw;
00193 } catch (Throwable& e) {
00194 e.sendToMrs(MRS_INFORMATION);
00195 s->setStatus(SequenceData::ABORTED);
00196 }
00197 }
00198
00199
00200
00201 std::list<std::string> CalibrationControllerImpl::getAllModulesForScan(Sct_SctApi_T_Scan* scan) {
00202
00203 std::list<std::string> allmodules;
00204
00205 Sct_SctApiStatus status;
00206
00207 for (unsigned modulegroup=0; modulegroup<scan->getNGroups(&status); ++modulegroup) {
00208 sctConf_T_ModuleList modulelist = scan->getModuleList(&status, modulegroup);
00209
00210
00211 for (unsigned imod=0; imod<modulelist->Length(); ++imod) {
00212 allmodules.push_back(string (modulelist->Nth(imod) ) );
00213 }
00214 }
00215 return allmodules;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 void CalibrationControllerImpl::applyChanges(const unsigned long runNumber, const unsigned long scanNumber, const std::list<std::string>& modulelist ) {
00233
00234 cout << "Update option = " << status.updateOption << endl;
00235
00236 {
00237 bool printed=false;
00238 while (status.updateOption=="WAIT") {
00239
00240 if (!printed)
00241 cerr << "CalibrationController awaiting instructions as to whether to apply changes" << endl;
00242 printed=true;
00243 }
00244 }
00245
00246
00247 if (status.updateOption!="UPDATE")
00248 return;
00249
00250 cout << "updating " << modulelist.size() << "" << " modules" << endl;
00251
00252 std::ostringstream regexp;
00253 regexp << ".*TestResult\\." << runNumber << "\\." << scanNumber << "\\..*";
00254 cout << "Cal Controller looking for " << regexp.str() << endl;
00255
00256 unsigned nprinted=0;
00257
00258
00259 std::list<std::string> mylist=modulelist;
00260
00261 while (!mylist.empty() && status.updateOption=="UPDATE") {
00262 ISInfoIterator ii(SctNames::getPartition(),
00263 SctNames::getTestDataName().c_str(),
00264 regexp.str().c_str() );
00265
00266 while (ii() && status.updateOption=="UPDATE") {
00267 if (nprinted<10)
00268 cout << " checking " << ii.name() << endl;
00269
00270
00271
00272 Sct::IS::IONameIS isname(ii.name());
00273 std::string moduleName=isname.getModuleName();
00274
00275
00276 std::list<string>::iterator it = std::find( mylist.begin(), mylist.end(), moduleName);
00277
00278 if ( it != mylist.end() ) {
00279 shared_ptr<const Serializable> ob ( Sct::IS::IOManagerIS::instance().read(ii.name()) );
00280 shared_ptr<const SctData::TestResult> testResult = boost::dynamic_pointer_cast<const SctData::TestResult>(ob);
00281 if (!testResult)
00282 throw Sct::InvalidArgumentError("Fitter::applyChangesCallback not a SctData::TestResult.", __FILE__, __LINE__);
00283
00284 cout << "about to update " << moduleName << endl;
00285 ConfigUpdaterManager::instance().update(*testResult);
00286 it=mylist.erase(it);
00287 }
00288 }
00289
00290 sleep (1);
00291
00292 if (nprinted<10) {
00293 cout << "Cal Controller waiting for TestResults (have "
00294 << mylist.size() << " still to go)" << endl;
00295 }
00296 nprinted ++;
00297 }
00298 }
00299
00300 void CalibrationControllerImpl::setUpdateOption(Sct_CalibrationController_T_CalibrationController_UpdateOption opt) {
00301 cout << "CalibrationContrllerImpl: resetting update option to " << opt;
00302 switch (opt) {
00303 case Sct_CalibrationController_T_CalibrationController_UpdateOption_update : {
00304 status.updateOption="UPDATE";
00305 SctNames::Mrs() << "CC_UPDATE_CHANGE"
00306 << MRS_TEXT("CalibrationControllerImpl setting updateOption=UPDATE") << MRS_DIAGNOSTIC << ENDM;
00307 break;
00308 }
00309 case Sct_CalibrationController_T_CalibrationController_UpdateOption_noupdate : {
00310 status.updateOption="NOUPDATE";
00311 SctNames::Mrs() << "CC_UPDATE_CHANGE"
00312 << MRS_TEXT("CalibrationControllerImpl setting updateOption=NOUPDATE") << MRS_DIAGNOSTIC << ENDM;
00313 break;
00314 }
00315 case Sct_CalibrationController_T_CalibrationController_UpdateOption_wait : {
00316 status.updateOption="WAIT";
00317 SctNames::Mrs() << "CC_UPDATE_CHANGE"
00318 << MRS_TEXT("CalibrationControllerImpl setting updateOption=WAIT") << MRS_DIAGNOSTIC << ENDM;
00319 break;
00320 }
00321 default : {
00322 IllegalStateError e("CalibrationControllerImpl updateOption UNKNOWN", __FILE__, __LINE__);
00323 e.sendToMrs(MRS_DIAGNOSTIC);
00324 break;
00325 }
00326 }
00327 updateStatus();
00328 }
00329
00330 auto_ptr<Test> CalibrationControllerImpl::executeTest(TestRequest& tr) {
00331 TestData data;
00332 vector<double> testPoints;
00333
00334 SctNames::Mrs() << "CC_TEST_START" << MRS_TEXT("Calibration Controller starting test") << MRS_INFORMATION << ENDM;
00335
00336 Sct_SctApiStatus st;
00337 api->setABCDModules(&st, 2);
00338 if (st.returnCode != 0)
00339 throw SctApiException(st.returnCode, "setABCDModules failed", __FILE__, __LINE__);
00340
00341 data.runNumber = runNumber;
00342 data.startScanNumber = nextScanNumber;
00343 tr.startTest(*api, data.testName, data.testVariable, data.nScans, testPoints);
00344
00345 data.testPoints = new double[testPoints.size()];
00346 data.testPoints_size = testPoints.size();
00347 for (unsigned int i=0; i<testPoints.size(); ++i) {
00348 data.testPoints[i] = testPoints[i];
00349 }
00350
00351 auto_ptr<Test> test (new Test(data));
00352
00353 status.currentTest = test->getUniqueID();
00354 updateStatus();
00355
00356 try {
00357 unsigned int i=0;
00358 for (; i<data.nScans; ++i) {
00359 Sct_SctApi_T_Scan* scan = tr.getNextScan(i);
00360 test->addScan(scan);
00361 if (abortNow) {
00362 abortNow = false;
00363 break;
00364 }
00365 executeScan(scan, i);
00366 }
00367 if (i == data.nScans) {
00368 SctNames::Mrs() << "CC_TEST_END" << MRS_TEXT("Calibration Controller ending test") << MRS_INFORMATION << ENDM;
00369 test->setStatus(TestData::COMPLETED);
00370 } else {
00371 SctNames::Mrs() << "CC_TEST_ABORT" << MRS_TEXT("Calibration Controller aborting test") << MRS_INFORMATION << ENDM;
00372 test->setStatus(TestData::ABORTED);
00373
00374 const TestData& testData = test->getData();
00375 setNextScanNumber(testData.startScanNumber + testData.nScans);
00376 }
00377
00378 } catch (SctApiException& e) {
00379 sctApiError(e);
00380 throw;
00381 } catch (IpcException& e) {
00382 SctNames::Mrs() << "CC_TEST_ABORT" << MRS_TEXT("Calibration Controller aborting test") << MRS_INFORMATION << ENDM;
00383 test->setStatus(TestData::ABORTED);
00384 e.sendToMrs(MRS_INFORMATION);
00385
00386
00387 const TestData& testData = test->getData();
00388 setNextScanNumber(testData.startScanNumber + testData.nScans);
00389 }
00390
00391
00392 try {
00393 tr.endTest();
00394 } catch (IpcException& e) {
00395 e.sendToMrs(MRS_DIAGNOSTIC);
00396 }
00397
00398
00399 try {
00400 Sct_SctApiStatus st;
00401 api->getABCDModules(&st, 2);
00402 if (st.returnCode != 0)
00403 throw SctApiException(st.returnCode, "getABCDModules failed", __FILE__, __LINE__);
00404 } catch (SctApiException& e) {
00405 sctApiError(e);
00406 e.sendToMrs();
00407 }
00408
00409
00410 return test;
00411 }
00412
00413 void CalibrationControllerImpl::executeScan(Sct_SctApi_T_Scan* scan, unsigned int index) {
00414 ++nextScanNumber;
00415 SctNames::Mrs() << "CC_SCAN_START" << MRS_TEXT("Calibration Controller starting scan") << MRS_INFORMATION << ENDM;
00416
00417 status.currentScanIndex = index;
00418 updateStatus();
00419
00420 Sct_SctApiStatus st;
00421 api->doScan(&st, scan);
00422 if (st.returnCode != 0)
00423 throw SctApiException(st.returnCode, "doScan failed", __FILE__, __LINE__);
00424
00425 ISInfoInt i;
00426 i.setValue(-1);
00427 ISInfo::Status isStatus = ISInfo::Success;
00428 ISInfoDictionary& is = SctNames::getISDictionary();
00429 int nInitialSleeps = 0;
00430
00431 while ((i.getValue() == -1 && nInitialSleeps < 20) || (i.getValue() == 1 && isStatus == ISInfo::Success)) {
00432 isStatus = is.findValue("SCTAPIServer.scanning", i);
00433 usleep(100);
00434 ++nInitialSleeps;
00435 }
00436 SctNames::Mrs() << "CC_SCAN_END" << MRS_TEXT("Calibration Controller ending scan") << MRS_INFORMATION << ENDM;
00437 }
00438
00439 CalibrationControllerImpl& CalibrationControllerImpl::initialize(RunControl& rc) {
00440 inst = new CalibrationControllerImpl(rc);
00441 return *inst;
00442 }
00443
00444 CalibrationControllerImpl& CalibrationControllerImpl::instance() {
00445 if (inst == 0)
00446 throw InvariantViolatedError("Need to call CalibrationControllerImpl::initialize first!", __FILE__, __LINE__);
00447 return *inst;
00448 }
00449
00450 ScanLibrary& CalibrationControllerImpl::getScanLibrary() const {
00451 return ScanLibraryImpl::instance();
00452 }
00453
00454 TestLibrary& CalibrationControllerImpl::getTestLibrary() const {
00455 return TestLibraryImpl::instance();
00456 }
00457
00458 SequenceLibrary& CalibrationControllerImpl::getSequenceLibrary() const {
00459 cout << "Get Sequence Library" << endl;
00460 return SequenceLibraryImpl::instance();
00461 }
00462
00463 void CalibrationControllerImpl::doScan(Sct_SctApi_T_Scan* scan) {
00464 shared_ptr<DefaultTest> test(new DefaultTest(*scan));
00465 doTest(test);
00466 }
00467
00468 void CalibrationControllerImpl::doTest (shared_ptr<TestRequest> t) {
00469 shared_ptr<DefaultSequence> seq(new DefaultSequence(t));
00470 doSequence(seq);
00471 }
00472
00473 void CalibrationControllerImpl::doSequence (shared_ptr<SequenceRequest> r) {
00474 if (!isInControl() || isBusy()) {
00475 cerr << "Can't execute SequenceRequest - bad status: " << status.status << endl;
00476 return;
00477 }
00478
00479 cout << "do Sequence" << endl;
00480
00481 status.status = status.BUSY;
00482 updateStatus();
00483
00484
00485 m_sequence_request_thread_group.create_thread(SequenceRequestWorker(*this, r));
00486
00487
00488
00489
00490
00491 }
00492
00493 Sct_SctApi_T_Scan* CalibrationControllerImpl::getScan(unsigned long runNumber, unsigned long scanNumber) const {
00494 cerr << "CalibrationControllerImpl::getScan - Not implemented" << endl;
00495 return 0;
00496 }
00497
00498 void CalibrationControllerImpl::updateStatus() {
00499 string name = SctNames::getControlDataName();
00500 name += ".Status";
00501 ISInfoDictionary& is = SctNames::getISDictionary();
00502 ISInfo::Status st;
00503
00504 if (is.contains(name.c_str())) {
00505 st = is.update(name.c_str(), status);
00506 } else {
00507 st = is.insert(name.c_str(), status);
00508 }
00509 if (st != ISInfo::Success) {
00510 IsException error(st, "CalibrationControllerImpl can't update status", __FILE__, __LINE__);
00511 error.sendToMrs(MRS_DIAGNOSTIC);
00512 }
00513 }
00514
00515 CalibrationControllerImpl* CalibrationControllerImpl::inst = 0;
00516
00517 }