AbstractRTEquipment.cpp

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 
00003 #include <fesa-core/RealTime/AbstractRTEquipment.h>
00004 #include <fesa-core/RealTime/AbstractRTDeviceClass.h>
00005 #include <fesa-core/Diagnostic/FesaStream.h>
00006 #include <fesa-core/DataStore/EquipmentData.h>
00007 #include <fesa-core/RealTime/RTScheduler.h>
00008 #include <fesa-core/RealTime/RTController.h>
00009 #include <fesa-core/Core/AbstractEquipment.h>
00010 #include <pthread.h>
00011 
00012 #include <cmw-log/Logger.h>
00013 
00014 
00015 namespace
00016 {
00017 
00018 CMW::Log::Logger& logger = CMW::Log::LoggerFactory::getLogger("FESA.FWK.fesa-core.RealTime.AbstractRTEquipment");
00019 
00020 } // namespace
00021 
00022 
00023 namespace fesa
00024 {
00025 
00026 //init static members
00027 AbstractRTEquipment* AbstractRTEquipment::theInstance_ = NULL;
00028 
00029 AbstractRTEquipment::AbstractRTEquipment()
00030 
00031 {
00032 
00033         theInstance_ = this;
00034         rtController_ = new RTController();
00035 }
00036 
00037 void AbstractRTEquipment::initialize()
00038 {
00039         EquipmentData* eqData = EquipmentData::getInstance();
00040         *(eqData->rtUp_) = false;
00041         // set  processID
00042         if (*(eqData->rtProcessID_) != 0) // There is already a RT process registered
00043         {
00044                 // is the other process up?
00045                 if(kill(*(eqData->rtProcessID_), SIGFESA_CHECK_PROCESS_ALIVE) == 0) // if the signal is successfully sent means that the process is up and running
00046                 {
00047                         // then abort the current process
00048                         throw FesaException(__FILE__, __LINE__, FesaErrorRTProcessAlreadyExists.c_str());
00049                 }
00050                 else
00051                 {
00052                         if (errno != ESRCH)  // errno = ESRCH means that the process is not running
00053                         {
00054                                 // If the error is different that ESRCH (i.e. no rights to send signal) we should abort
00055                                 throw FesaException(__FILE__, __LINE__, FesaErrorNoPermissionToSendSignals.c_str());
00056                         }
00057                 }
00058         }
00059         *(eqData->rtProcessID_) = getpid();
00060 
00061         //trigger initialize the classes
00062         AbstractComponentEquipment::initialize();
00063         rtController_->initialize();
00064 }
00065 
00066 void AbstractRTEquipment::start(RunMode runMode)
00067 {
00068     // DIAGNOSTIC: Update configuration file to describe Event-sources & Scheduling
00069         AbstractEquipment* pEqp = AbstractEquipment::getInstance();
00070         std::string equipmentName = pEqp->getEquipmentName();
00071         FesaStream* configStream = FesaStream::getConfigStream(equipmentName + "Rt");
00072 
00073         *configStream << " fesa-version=\"" <<  pEqp->getFesaVersion() << "\" deploy-type=\"" << pEqp->getProcessTypeAsString() << "\" fesa-compilation-DT=\"" << pEqp->getFesaBuildDate() << "\">" << std::endl;
00074         *configStream << "\t<equipment-real-time class-name=\"\"  class-version=\"\"" << std::endl;
00075 
00076         rtController_->printConfigAll(configStream);
00077         configStream->update();
00078         delete configStream;
00079 
00080         rtController_->start();
00081 
00082         // specify that the RT part is ready
00083         *(EquipmentData::getInstance()->rtUp_) = true;
00084 
00085         if ( runMode == blocking )
00086         {
00087                 waitSignal();
00088         }
00089 }
00090 
00091 AbstractRTEquipment::~AbstractRTEquipment()
00092 {
00093         if (rtController_ != NULL)
00094         {
00095                 delete rtController_;
00096                 rtController_ = NULL;
00097         }
00098 
00099         theInstance_ = NULL;
00100 }
00101 
00102 void AbstractRTEquipment::printConfigAll(FesaStream* fesaStream)
00103 {
00104         rtController_->printConfigAll(fesaStream);
00105 }
00106 void AbstractRTEquipment::printStateAll(FesaStream* fesaStream, double elapsedTime)
00107 {
00108         rtController_->printStateAll(fesaStream, elapsedTime);
00109 }
00110 
00111 void AbstractRTEquipment::waitSignal()
00112 {
00113 //         fesa::FesaLogger* log = fesa::FesaLogger::getDefaultLogger();
00114 
00115         sigset_t sigset;
00116         sigemptyset(&sigset);
00117         sigaddset(&sigset, SIGTSTP);
00118         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
00119 
00120         sigemptyset(&sigset);
00121         sigaddset(&sigset, SIGHUP);
00122         sigaddset(&sigset, SIGINT);
00123         sigaddset(&sigset, SIGQUIT);
00124         sigaddset(&sigset, SIGILL);
00125         sigaddset(&sigset, SIGTRAP);
00126         sigaddset(&sigset, SIGABRT);
00127         sigaddset(&sigset, SIGBUS);
00128         sigaddset(&sigset, SIGFPE);
00129         sigaddset(&sigset, SIGSEGV);
00130         sigaddset(&sigset, SIGTERM);
00131         sigaddset(&sigset, SIGSTKFLT);
00132         sigaddset(&sigset, SIGSTOP);
00133         sigaddset(&sigset, SIGTTIN);
00134         sigaddset(&sigset, SIGTTOU);
00135         sigaddset(&sigset, SIGFESA_CHECK_PROCESS_ALIVE);
00136 
00137         int32_t signalID;
00138         for (;;)
00139         {
00140                 // Wait for any fatal signal
00141                 sigwait(&sigset, &signalID);
00142 
00143                 if(signalID == SIGFESA_CHECK_PROCESS_ALIVE)
00144                 {
00145                         continue; // If the signal was just to check if process alive, nothing to be done
00146                 }
00147 
00148                 // Inform server part about fatal signal
00149                 EquipmentData* equipmentData = EquipmentData::getInstance();
00150                 kill(*(equipmentData->srvProcessPid_), SIGFESA_RT_DOWN);
00151 
00152                 *(equipmentData->rtUp_) = false;
00153 
00154 //             log->logError(fesa::FesaLogger::warning) << "Fatal signal received, shutting down RT process. Informing Server process if any." << std::endl;
00155                 std::string errorStr("Fatal signal received, shutting down RT process. Informing Server process if any.");
00156                 LOG_WARNING_IF(logger, errorStr);
00157                 // TODO Should we call any shutdown (specificShutdown....)?
00158 
00159                 // We call the default action of the fatal signal, this will let us to create the core dump files
00160                 pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
00161                 signal(signalID, SIG_DFL);
00162                 raise(signalID);
00163 
00164         }
00165         return;
00166 }
00167 
00168 void AbstractRTEquipment::fillRTSchedulerInfo(std::vector<RTLayerInfo*>& layerCol)
00169 {
00170 
00171         RTLayerInfo* layer = new RTLayerInfo();
00172 
00173         layer->layerName_ = DIAGNOSTIC_LAYER;
00174         layer->queueSize_ = -1;
00175 
00176         RTSchedulingUnitRef schedulingUnit;
00177         schedulingUnit.className_ = AbstractEquipment::getInstance()->getEquipmentName();
00178         schedulingUnit.name_ = "diagnosticLayer";
00179         schedulingUnit.perDeviceCollection_ = false;
00180         schedulingUnit.found_ = false;
00181         layer->schedulingUnitRefCol_.push_back(schedulingUnit);
00182 
00183         layerCol.push_back(layer);
00184 }
00185 
00186 void RTLayerInfo::print()
00187 {
00188     if (logger.isLoggable(CMW::Log::Level::LL_DEBUG))
00189     {
00190         std::ostringstream msg;
00191         msg << " layerName_: " << layerName_ << " queueSize_: " << queueSize_;
00192         LOG_DEBUG_IF(logger, msg.str());
00193     }
00194 }
00195 
00196 }// end namespace

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1