AbstractRTAction.cpp

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 
00003 #include <fesa-core/RealTime/AbstractRTAction.h>
00004 
00005 #include <fesa-core/RealTime/RTEvent.h>
00006 #include <fesa-core/RealTime/AbstractRTEquipment.h>
00007 #include <fesa-core/DataStore/GlobalDevice.h>
00008 #include <fesa-core/DataStore/EquipmentData.h>
00009 #include <fesa-core/Core/NotificationIDManager.h>
00010 #include <fesa-core/Core/NotificationProducer.h>
00011 #include <fesa-core/Core/AbstractServiceLocator.h>
00012 #include <fesa-core/Core/MessageTypes.h>
00013 #include <fesa-core/Diagnostic/Diagnostics.h>
00014 #include <fesa-core/Core/OnDemandProducer.h>
00015 
00016 #include <cmw-log/Logger.h>
00017 
00018 
00019 namespace
00020 {
00021 
00022 CMW::Log::Logger& logger = CMW::Log::LoggerFactory::getLogger("FESA.FWK.fesa-core.RealTime.AbstractRTAction");
00023 const std::string diagTopic = fesa::DiagnosticUtils::rtActionProfilingStr;
00024 } // namespace
00025 
00026 
00027 namespace fesa
00028 {
00029 
00030 AbstractRTAction::AbstractRTAction(RTActionConfig& rtActionConfig, const AbstractServiceLocator* serviceLocator, const std::map<std::string, const AbstractServiceLocator*> serviceLocatorRelatedClasses) :
00031         AbstractAction(rtActionConfig.actionName_,rtActionConfig.className_,serviceLocator,serviceLocatorRelatedClasses),
00032         eventName_(rtActionConfig.eventName_),
00033         selectionCriterion_(rtActionConfig.selectionCriterion_),
00034         manuallyNotifiedPropertiesCol_(rtActionConfig.manuallyNotifiedPropertiesCol_),
00035         eventSourceName_(rtActionConfig.eventSourceName_),
00036         abstractDeviceCol_(rtActionConfig.deviceCol_),
00037         globalDevice_(rtActionConfig.globalDevice_),
00038         manualNotificationMessage_(NULL),
00039         automaticallyNotifiedPropertiesCol_(rtActionConfig.automaticallyNotifiedPropertiesCol_)
00040 
00041 {
00042         NotificationIDManager* notIDGen = NotificationIDManager::getInstance();
00043 
00044         std::set<std::string> deviceNames;
00045         for (std::vector<AbstractDevice*>::iterator devIter = abstractDeviceCol_.begin(); devIter != abstractDeviceCol_.end(); devIter++)
00046         {
00047                 deviceNames.insert((*devIter)->getName());
00048         }
00049         // If the flag tells that the list of properties to be notified contains at least one globalProperty,
00050         // the global device name is inserted.
00051         if (rtActionConfig.isGlobalPropertyToBeNotified_)
00052                 deviceNames.insert(globalDevice_->getName());
00053 
00054         if (!automaticallyNotifiedPropertiesCol_.empty())
00055                 notificationID_ = notIDGen->createNotificationID(automaticallyNotifiedPropertiesCol_, deviceNames, className_);
00056         else
00057                 notificationID_ = NO_NOTIFICATION;
00058 
00059         theNotificationProducer_ = NotificationProducer::getInstance();
00060 
00061         // Check if all the device collection shares the same timingDomain including the global device
00062         devicesShareTimingDomain_ = true;
00063         timingDomain_.assign("Undefined");
00064         for (uint32_t i = 0; i < (abstractDeviceCol_.size()); i++)
00065         {
00066                 if ((abstractDeviceCol_[i])->isMultiplexed())
00067                 {
00068                         if (timingDomain_.compare(abstractDeviceCol_[i]->timingDomain.getAsString()))
00069                         {
00070                                 //if it is the first time
00071                                 if (!timingDomain_.compare("Undefined"))
00072                                 {
00073                                         timingDomain_.assign(abstractDeviceCol_[i]->timingDomain.getAsString());
00074                                 }
00075                                 else
00076                                 {
00077                                         devicesShareTimingDomain_ = false;
00078                                         timingDomain_.assign("Undefined");
00079                                         break;
00080                                 }
00081                         }
00082                 }
00083         }
00084         if (globalDevice_->isMultiplexed() && devicesShareTimingDomain_ == true)
00085         {
00086                 if (timingDomain_.compare(globalDevice_->timingDomain.getAsString()))
00087                 {
00088                         devicesShareTimingDomain_ = false;
00089                         timingDomain_.assign("Undefined");
00090                 }
00091         }
00092 
00093         if (!manuallyNotifiedPropertiesCol_.empty())
00094         {
00095                 this->manualNotificationMessage_ = new ManualNotificationMessage(rtActionConfig.className_);
00096         }
00097 }
00098 
00099 AbstractRTAction::~AbstractRTAction()
00100 {
00101 
00102         std::vector<AbstractDevice*>::iterator devices;
00103 
00104         // DO NOT REMOVE THE DEVICES, do so in the device factory
00105         manuallyNotifiedPropertiesCol_.clear();
00106         automaticallyNotifiedPropertiesCol_.clear();
00107         theNotificationProducer_ = NULL;
00108 }
00109 
00110 void AbstractRTAction::executeAction(RTEvent* event)
00111 {
00112     // Check if event's timing domain is coherent with the timing domain of the device collection
00113     std::string ctxTimingDomainName = event->getMultiplexingContext()->getTimingDomainName();
00114     if (!ctxTimingDomainName.empty())
00115     {
00116         if (devicesShareTimingDomain_ == false)
00117         {
00118             throw FesaException(__FILE__, __LINE__, FesaErrorDevColHasMultipleTimingDomains.c_str());
00119         }
00120         else
00121         {
00122             if (timingDomain_.compare("Undefined")) // FIXME what's that double if logic?
00123             {
00124                 if (timingDomain_.compare(ctxTimingDomainName))
00125                 {
00126                     throw FesaException(__FILE__, __LINE__, FesaErrorInconsistentTimingDomain.c_str());
00127                 }
00128             }
00129         }
00130     }
00131     const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00132     DiagnosticUtils::DiagnosticMessage diagMsg;
00133     diagMsg.side = DiagnosticUtils::framework;
00134     diagMsg.source = DiagnosticUtils::rt;
00135     diagMsg.name = name_;
00136     diagMsg.action = DiagnosticUtils::start;
00137     diagMsg.msg = "";
00138     diagnostics->log(diagTopic, diagMsg);
00139 
00140     serviceLocator_->synchronizeSettingFields(*(event->getMultiplexingContext()));
00141     // reset the manual notification message
00142     if (this->manualNotificationMessage_ != NULL )
00143     {
00144         this->manualNotificationMessage_->reset();
00145     }
00146 
00147     try
00148     {
00149         execute(event);
00150         (completedActionCount_.current_)++;
00151 
00152         //Trigger all OnDemand-Event-Sources which need to be triggered automatically
00153         triggerAllAutomaticallyTriggeredOnDemandEventSources(event->getMultiplexingContext());
00154 
00155         if (notificationID_ != NO_NOTIFICATION && automaticallyNotifiedPropertiesCol_.empty() == false)
00156         {
00157             EquipmentData* eqData = EquipmentData::getInstance();
00158             if (*(eqData->serverUp_))
00159             {
00160                 theNotificationProducer_->sendAutomaticNotification(notificationID_, *event->getMultiplexingContext(), 0);
00161                 if(logger.isLoggable(CMW::Log::Level::LL_TRACE))
00162                 {
00163                     std::ostringstream msg;
00164                     msg << "Notifying the server from " << className_ << "::" << name_ << " (id=" << notificationID_ << ").";
00165                     LOG_TRACE_IF(logger, msg.str());
00166                 }
00167             }
00168         }
00169         else if (logger.isLoggable(CMW::Log::Level::LL_TRACE))
00170         {
00171             std::ostringstream msg;
00172             msg << "No server notification for " << className_ << "::" << name_ << ": id=" << notificationID_
00173                             << " & autoNotification=" << automaticallyNotifiedPropertiesCol_.empty() << ".";
00174             LOG_TRACE_IF(logger, msg.str());
00175         }
00176     }
00177     catch (FesaException& ex)
00178     {
00179         abortedActionCount_++;
00180         diagMsg.action = DiagnosticUtils::stop;
00181         diagnostics->log(diagTopic, diagMsg);
00182         throw;
00183     }
00184     diagMsg.action = DiagnosticUtils::stop;
00185     diagnostics->log(diagTopic, diagMsg);
00186 }
00187 
00188 void AbstractRTAction::sendManualNotification(MultiplexingContext* muxContext)
00189 {
00190         //if the Server part is down, throw an exception
00191         EquipmentData* eqData = EquipmentData::getInstance();
00192         if (!(*(eqData->serverUp_)))
00193         {
00194                 return;
00195         }
00196 
00197         if (this->manualNotificationMessage_ != NULL)
00198         {
00199                 this->manualNotificationMessage_->muxContext_ = muxContext;
00200                 theNotificationProducer_->sendManualNotification(*manualNotificationMessage_);
00201         }
00202 
00203 }
00204 
00205 }

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1