Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Related Pages

CalibrationControllerImpl.cpp

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

Generated on Thu Jul 8 11:41:09 2004 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5