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

CalibrationControllerImpl.cpp

Go to the documentation of this file.
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     //Remove status from IS:
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     //Notify MRS    
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;  //Drop through
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         //Check we didn't fail somewhere
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; //All done!
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             // Save the changes that have been made (into the ROD)
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;  //Drop through  
00193     } catch (Throwable& e) {
00194     e.sendToMrs(MRS_INFORMATION);
00195     s->setStatus(SequenceData::ABORTED);
00196     }    
00197 }
00198 
00199 
00200 // return all modules for a scan:
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     // loop over module groups
00207     for (unsigned modulegroup=0; modulegroup<scan->getNGroups(&status); ++modulegroup) {
00208         sctConf_T_ModuleList modulelist = scan->getModuleList(&status, modulegroup);
00209 
00210         // loop over modules in that modulegroup
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   Currently not done by InfoIterator, rather than by callback.
00221   void CalibrationControllerImpl::applyChangesCallback(ISCallbackInfo * isc){
00222       if (isc->reason() != ISInfoCreated) return;
00223       unsigned *ctr=reinterpret_cast<unsigned *>( isc->parameter() );
00224       ++(*ctr);
00225       shared_ptr<const Serializable> ob ( Sct::IS::IOManagerIS::instance().read(*isc) );
00226       shared_ptr<const SctData::TestResult> testResult = boost::dynamic_pointer_cast<const SctData::TestResult>(ob);
00227       if (!testResult) throw InvalidArgument("Fitter::applyChangesCallback not a SctData::TestResult.");
00228       CalibrationControllerImpl::instance().findConfigUpdater( testResult->getClassName() )->update(*testResult);
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     //status.updateOption can be changed by other IPC method
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     // make another list which we can remove things from:
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             // make an IONameIS which allows us to interpret the IS name
00272             Sct::IS::IONameIS isname(ii.name());
00273             std::string moduleName=isname.getModuleName();
00274 
00275             // look for the module name in our list
00276             std::list<string>::iterator it = std::find( mylist.begin(), mylist.end(), moduleName);
00277             // if its there, then update that module, and remove it from our list.
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         } // end of loop over currently available TestResult
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;  //Drop through  
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     //Try an increment the scan number to the end of the test
00387     const TestData& testData = test->getData();     
00388     setNextScanNumber(testData.startScanNumber + testData.nScans);
00389     }
00390     
00391     //End the test
00392     try {
00393         tr.endTest();
00394     } catch (IpcException& e) {
00395     e.sendToMrs(MRS_DIAGNOSTIC);
00396     }
00397     
00398     //Reset the module configurations to the original
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;  // set back to INCONTROL by the SequenceRequestWorker
00482     updateStatus();
00483 
00484     
00485     m_sequence_request_thread_group.create_thread(SequenceRequestWorker(*this, r));
00486 
00487     //AJB executeSequence(r);
00488 
00489     //AJB status.status = status.INCONTROL;
00490     //AJB updateStatus();
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 }

Generated on Mon Dec 15 19:35:58 2003 for SCT DAQ/DCS Software by doxygen1.3-rc3