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 }
00177 }
00178 ++index;
00179 } while (tr != 0);
00180
00181 SctNames::Mrs() << "CC_SEQ_END" << MRS_TEXT("Calibration Controller ending sequence") << MRS_INFORMATION << ENDM;
00182 sr.endSequence();
00183 s->setStatus(SequenceData::COMPLETED);
00184
00185 } catch (SctApiException& e) {
00186 sctApiError(e);
00187 throw;
00188 } catch (Throwable& e) {
00189 e.sendToMrs(MRS_INFORMATION);
00190 s->setStatus(SequenceData::ABORTED);
00191 }
00192 }
00193
00194
00195
00196 std::list<std::string> CalibrationControllerImpl::getAllModulesForScan(Sct_SctApi_T_Scan* scan) {
00197
00198 std::list<std::string> allmodules;
00199
00200 Sct_SctApiStatus status;
00201
00202 for (unsigned modulegroup=0; modulegroup<scan->getNGroups(&status); ++modulegroup) {
00203 sctConf_T_ModuleList modulelist = scan->getModuleList(&status, modulegroup);
00204
00205
00206 for (unsigned imod=0; imod<modulelist->Length(); ++imod) {
00207 allmodules.push_back(string (modulelist->Nth(imod) ) );
00208 }
00209 }
00210 return allmodules;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 void CalibrationControllerImpl::applyChanges(const unsigned long runNumber, const unsigned long scanNumber, const std::list<std::string>& modulelist ) {
00228
00229 cout << "Update option = " << status.updateOption << endl;
00230
00231 {
00232 bool printed=false;
00233 while (status.updateOption=="WAIT") {
00234
00235 if (!printed)
00236 cerr << "CalibrationController awaiting instructions as to whether to apply changes" << endl;
00237 printed=true;
00238 }
00239 }
00240
00241
00242 if (status.updateOption!="UPDATE")
00243 return;
00244
00245 cout << "updating " << modulelist.size() << "" << " modules" << endl;
00246
00247 std::ostringstream regexp;
00248 regexp << ".*TestResult\\." << runNumber << "\\." << scanNumber << "\\..*";
00249 cout << "Cal Controller looking for " << regexp.str() << endl;
00250
00251 unsigned nprinted=0;
00252
00253
00254 std::list<std::string> mylist=modulelist;
00255
00256 while (!mylist.empty() && status.updateOption=="UPDATE") {
00257 ISInfoIterator ii(SctNames::getPartition(),
00258 SctNames::getTestDataName().c_str(),
00259 regexp.str().c_str() );
00260
00261 while (ii() && status.updateOption=="UPDATE") {
00262 if (nprinted<10)
00263 cout << " checking " << ii.name() << endl;
00264
00265
00266
00267 Sct::IS::IONameIS isname(ii.name());
00268 std::string moduleName=isname.getModuleName();
00269
00270
00271 std::list<string>::iterator it = std::find( mylist.begin(), mylist.end(), moduleName);
00272
00273 if ( it != mylist.end() ) {
00274 shared_ptr<const Serializable> ob ( Sct::IS::IOManagerIS::instance().read(ii.name()) );
00275 shared_ptr<const SctData::TestResult> testResult = boost::dynamic_pointer_cast<const SctData::TestResult>(ob);
00276 if (!testResult)
00277 throw Sct::InvalidArgumentError("Fitter::applyChangesCallback not a SctData::TestResult.", __FILE__, __LINE__);
00278
00279 cout << "about to update " << moduleName << endl;
00280 ConfigUpdaterManager::instance().update(*testResult);
00281 it=mylist.erase(it);
00282 }
00283 }
00284
00285 sleep (1);
00286
00287 if (nprinted<10) {
00288 cout << "Cal Controller waiting for TestResults (have "
00289 << mylist.size() << " still to go)" << endl;
00290 }
00291 nprinted ++;
00292 }
00293 }
00294
00295 void CalibrationControllerImpl::setUpdateOption(Sct_CalibrationController_T_CalibrationController_UpdateOption opt) {
00296 cout << "CalibrationContrllerImpl: resetting update option to " << opt;
00297 switch (opt) {
00298 case Sct_CalibrationController_T_CalibrationController_UpdateOption_update : {
00299 status.updateOption="UPDATE";
00300 SctNames::Mrs() << "CC_UPDATE_CHANGE"
00301 << MRS_TEXT("CalibrationControllerImpl setting updateOption=UPDATE") << MRS_DIAGNOSTIC << ENDM;
00302 break;
00303 }
00304 case Sct_CalibrationController_T_CalibrationController_UpdateOption_noupdate : {
00305 status.updateOption="NOUPDATE";
00306 SctNames::Mrs() << "CC_UPDATE_CHANGE"
00307 << MRS_TEXT("CalibrationControllerImpl setting updateOption=NOUPDATE") << MRS_DIAGNOSTIC << ENDM;
00308 break;
00309 }
00310 case Sct_CalibrationController_T_CalibrationController_UpdateOption_wait : {
00311 status.updateOption="WAIT";
00312 SctNames::Mrs() << "CC_UPDATE_CHANGE"
00313 << MRS_TEXT("CalibrationControllerImpl setting updateOption=WAIT") << MRS_DIAGNOSTIC << ENDM;
00314 break;
00315 }
00316 default : {
00317 IllegalStateError e("CalibrationControllerImpl updateOption UNKNOWN", __FILE__, __LINE__);
00318 e.sendToMrs(MRS_DIAGNOSTIC);
00319 break;
00320 }
00321 }
00322 updateStatus();
00323 }
00324
00325 auto_ptr<Test> CalibrationControllerImpl::executeTest(TestRequest& tr) {
00326 TestData data;
00327 vector<double> testPoints;
00328
00329 SctNames::Mrs() << "CC_TEST_START" << MRS_TEXT("Calibration Controller starting test") << MRS_INFORMATION << ENDM;
00330
00331 data.runNumber = runNumber;
00332 data.startScanNumber = nextScanNumber;
00333 tr.startTest(*api, data.testName, data.testVariable, data.nScans, testPoints);
00334
00335 data.testPoints = new double[testPoints.size()];
00336 data.testPoints_size = testPoints.size();
00337 for (unsigned int i=0; i<testPoints.size(); ++i) {
00338 data.testPoints[i] = testPoints[i];
00339 }
00340
00341 auto_ptr<Test> test (new Test(data));
00342
00343 status.currentTest = test->getUniqueID();
00344 updateStatus();
00345
00346 try {
00347 unsigned int i=0;
00348 for (; i<data.nScans; ++i) {
00349 Sct_SctApi_T_Scan* scan = tr.getNextScan(i);
00350 test->addScan(scan);
00351 if (abortNow) {
00352 abortNow = false;
00353 break;
00354 }
00355 executeScan(scan, i);
00356 }
00357 if (i == data.nScans) {
00358 SctNames::Mrs() << "CC_TEST_END" << MRS_TEXT("Calibration Controller ending test") << MRS_INFORMATION << ENDM;
00359 test->setStatus(TestData::COMPLETED);
00360 } else {
00361 SctNames::Mrs() << "CC_TEST_ABORT" << MRS_TEXT("Calibration Controller aborting test") << MRS_INFORMATION << ENDM;
00362 test->setStatus(TestData::ABORTED);
00363
00364 const TestData& testData = test->getData();
00365 setNextScanNumber(testData.startScanNumber + testData.nScans);
00366 }
00367
00368 } catch (SctApiException& e) {
00369 sctApiError(e);
00370 throw;
00371 } catch (IpcException& e) {
00372 SctNames::Mrs() << "CC_TEST_ABORT" << MRS_TEXT("Calibration Controller aborting test") << MRS_INFORMATION << ENDM;
00373 test->setStatus(TestData::ABORTED);
00374 e.sendToMrs(MRS_INFORMATION);
00375
00376
00377 const TestData& testData = test->getData();
00378 setNextScanNumber(testData.startScanNumber + testData.nScans);
00379 }
00380
00381
00382 try {
00383 tr.endTest();
00384 } catch (IpcException& e) {
00385 e.sendToMrs(MRS_DIAGNOSTIC);
00386 }
00387
00388 return test;
00389 }
00390
00391 void CalibrationControllerImpl::executeScan(Sct_SctApi_T_Scan* scan, unsigned int index) {
00392 ++nextScanNumber;
00393 SctNames::Mrs() << "CC_SCAN_START" << MRS_TEXT("Calibration Controller starting scan") << MRS_INFORMATION << ENDM;
00394
00395 status.currentScanIndex = index;
00396 updateStatus();
00397
00398 Sct_SctApiStatus st;
00399 api->doScan(&st, scan);
00400 if (st.returnCode != 0)
00401 throw SctApiException(st.returnCode, "doScan failed", __FILE__, __LINE__);
00402
00403 ISInfoInt i;
00404 i.setValue(-1);
00405 ISInfo::Status isStatus = ISInfo::Success;
00406 ISInfoDictionary& is = SctNames::getISDictionary();
00407 int nInitialSleeps = 0;
00408
00409 while ((i.getValue() == -1 && nInitialSleeps < 20) || (i.getValue() == 1 && isStatus == ISInfo::Success)) {
00410 isStatus = is.findValue("SCTAPIServer.scanning", i);
00411 usleep(100);
00412 ++nInitialSleeps;
00413 }
00414 SctNames::Mrs() << "CC_SCAN_END" << MRS_TEXT("Calibration Controller ending scan") << MRS_INFORMATION << ENDM;
00415 }
00416
00417 CalibrationControllerImpl& CalibrationControllerImpl::initialize(RunControl& rc) {
00418 inst = new CalibrationControllerImpl(rc);
00419 return *inst;
00420 }
00421
00422 CalibrationControllerImpl& CalibrationControllerImpl::instance() {
00423 if (inst == 0)
00424 throw InvariantViolatedError("Need to call CalibrationControllerImpl::initialize first!", __FILE__, __LINE__);
00425 return *inst;
00426 }
00427
00428 ScanLibrary& CalibrationControllerImpl::getScanLibrary() const {
00429 return ScanLibraryImpl::instance();
00430 }
00431
00432 TestLibrary& CalibrationControllerImpl::getTestLibrary() const {
00433 return TestLibraryImpl::instance();
00434 }
00435
00436 SequenceLibrary& CalibrationControllerImpl::getSequenceLibrary() const {
00437 cout << "Get Sequence Library" << endl;
00438 return SequenceLibraryImpl::instance();
00439 }
00440
00441 void CalibrationControllerImpl::doScan(Sct_SctApi_T_Scan* scan) {
00442 shared_ptr<DefaultTest> test(new DefaultTest(*scan));
00443 doTest(test);
00444 }
00445
00446 void CalibrationControllerImpl::doTest (shared_ptr<TestRequest> t) {
00447 shared_ptr<DefaultSequence> seq(new DefaultSequence(t));
00448 doSequence(seq);
00449 }
00450
00451 void CalibrationControllerImpl::doSequence (shared_ptr<SequenceRequest> r) {
00452 if (!isInControl() || isBusy()) {
00453 cerr << "Can't execute SequenceRequest - bad status: " << status.status << endl;
00454 return;
00455 }
00456
00457 cout << "do Sequence" << endl;
00458
00459 status.status = status.BUSY;
00460 updateStatus();
00461
00462
00463 m_sequence_request_thread_group.create_thread(SequenceRequestWorker(*this, r));
00464
00465
00466
00467
00468
00469 }
00470
00471 Sct_SctApi_T_Scan* CalibrationControllerImpl::getScan(unsigned long runNumber, unsigned long scanNumber) const {
00472 cerr << "CalibrationControllerImpl::getScan - Not implemented" << endl;
00473 return 0;
00474 }
00475
00476 void CalibrationControllerImpl::updateStatus() {
00477 string name = SctNames::getControlDataName();
00478 name += ".Status";
00479 ISInfoDictionary& is = SctNames::getISDictionary();
00480 ISInfo::Status st;
00481
00482 if (is.contains(name.c_str())) {
00483 st = is.update(name.c_str(), status);
00484 } else {
00485 st = is.insert(name.c_str(), status);
00486 }
00487 if (st != ISInfo::Success) {
00488 IsException error(st, "CalibrationControllerImpl can't update status", __FILE__, __LINE__);
00489 error.sendToMrs(MRS_DIAGNOSTIC);
00490 }
00491 }
00492
00493 CalibrationControllerImpl* CalibrationControllerImpl::inst = 0;
00494
00495 }