ServerAction.h

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 
00003 #ifndef SERVER_ACTION_H_
00004 #define SERVER_ACTION_H_
00005 
00006 #include <fesa-core/Server/AbstractServerAction.h>
00007 #include <fesa-core/Server/RequestEvent.h>
00008 #include <fesa-core/Server/AbstractServerEquipment.h>
00009 #include <fesa-core/Server/AbstractServerDeviceClass.h>
00010 #include <fesa-core/DataStore/AbstractDevice.h>
00011 #include <fesa-core/DataStore/FieldSynchroManager.h>
00012 #include <fesa-core/Synchronization/MultiplexingContext.h>
00013 #include <fesa-core/Persistency/PersistencyManager.h>
00014 #include <fesa-core/Exception/FesaException.h>
00015 #include <fesa-core/Diagnostic/Diagnostics.h>
00016 
00017 #include <cmw-rda/Data.h>
00018 #include <cmw-log/Logger.h>
00019 
00020 
00021 namespace
00022 {
00023 
00024 const std::string getActionProfDiagTopic = fesa::DiagnosticUtils::getActionProfilingStr;
00025 const std::string setActionProfDiagTopic = fesa::DiagnosticUtils::setActionProfilingStr;
00026 
00027 } // namespace
00028 
00029 
00030 namespace fesa
00031 {
00032 
00033 class BasicFilter
00034 {
00035   public:
00036     BasicFilter() :
00037         filter_(NULL)
00038     {
00039 
00040     }
00041     void setData(const rdaData& filter)
00042     {
00043         filter_ = &filter;
00044     }
00045   protected:
00046     const rdaData* filter_;
00047 };
00048 
00049 template<typename DeviceType, typename DataType, typename FilterType = BasicFilter>
00050 class ServerAction: public AbstractServerAction
00051 {
00052   public:
00057     ServerAction(ServerActionConfig& actionConfig, const AbstractServiceLocator* serviceLocator, const std::map<std::string, const AbstractServiceLocator*> serviceLocatorRelatedClasses);
00058 
00059     virtual ~ServerAction();
00060 
00070     void execute(RequestEvent* evt, AbstractDevice& dev, const rdaData& filter, rdaData& data, IOType ioType, RequestType reqType);
00071 
00075     void performCommit(MultiplexingContext& pTransactionCtxt, AbstractDevice *transactionDevice);
00076 
00080     void performRollback(MultiplexingContext& pTransactionCtxt, AbstractDevice* transactionDevice);
00081 
00082   protected:
00083 
00087     virtual void execute(RequestEvent* evt, DeviceType* device, DataType& data, const FilterType& filter)
00088     {
00089         throw FesaException(__FILE__, __LINE__, FesaErrorPropertyExecuteMethodIsNotImplemented.c_str(),
00090                             name_.c_str());
00091     };
00092 
00096     virtual void execute(RequestEvent* evt, DeviceType*, DataType& data)
00097     {
00098         throw FesaException(__FILE__, __LINE__, FesaErrorPropertyExecuteMethodIsNotImplemented.c_str(),
00099                             name_.c_str());
00100     };
00101 
00105     virtual void commit(RequestEvent*, DeviceType*)
00106     {
00107     };
00108 
00112     virtual void rollback(RequestEvent*, DeviceType*)
00113     {
00114     };
00115 };
00116 
00117 /****************** IMPLEMENTATION ************************/
00118 
00119 template<typename DeviceType, typename DataType, typename FilterType>
00120 inline ServerAction<DeviceType, DataType, FilterType>::ServerAction(ServerActionConfig& actionConfig, const AbstractServiceLocator* serviceLocator, const std::map<std::string, const AbstractServiceLocator*> serviceLocatorRelatedClasses) :
00121     AbstractServerAction(actionConfig, serviceLocator, serviceLocatorRelatedClasses)
00122 {
00123 }
00124 
00125 template<typename DeviceType, typename DataType, typename FilterType>
00126 ServerAction<DeviceType, DataType, FilterType>::~ServerAction()
00127 {
00128 }
00129 
00130 template<typename DeviceType, typename DataType, typename FilterType>
00131 inline void ServerAction<DeviceType, DataType, FilterType>::execute(RequestEvent* evt, AbstractDevice& dev,
00132                                                                     const rdaData& filter, rdaData& data, IOType ioType, RequestType reqType)
00133 {
00134     const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00135     DiagnosticUtils::DiagnosticMessage diagMsg;
00136     diagMsg.side = DiagnosticUtils::framework;
00137     diagMsg.source = DiagnosticUtils::server;
00138     diagMsg.name = name_;
00139     
00140     checkInvalidatingFields(&dev, evt->getMultiplexingContext());
00141     DeviceType* workingDevice = (DeviceType*) &dev;
00142     DataType workingData;
00143 
00144     if (ioType == Output)// ioType == Output --> we have a get-action
00145     {
00146         diagMsg.action = DiagnosticUtils::start;
00147         diagnostics->log(getActionProfDiagTopic, diagMsg);
00148         try
00149         {
00150             workingData.setData(data, false, false);
00151             if (needFilter_)
00152             {
00153                 FilterType workingFilter;
00154                 workingFilter.setData((rdaData&) filter);
00155                 execute(evt, workingDevice, workingData, workingFilter);
00156             }
00157             else
00158             {
00159                 execute(evt, workingDevice, workingData);
00160             }
00161             // Update the value-items linked to fields
00162             workingData.getRefItems(evt->getMultiplexingContext(), *workingDevice);
00163 
00164             //add common Data to the getaction - data
00165             int64_t stamp = evt->getMultiplexingContext()->getCycleStamp();
00166             if (stamp != 0)
00167             {
00168                 data.insert("cycleStamp", stamp);
00169             }
00170             if (reqType != GET)
00171             {
00172                 int32_t val = reqType;
00173                 data.insert("updateFlags", static_cast<long int>(val));
00174             }
00175             const std::string& cycleName = evt->getMultiplexingContext()->getCycleName();
00176             if (!cycleName.empty())
00177             {
00178                 data.insert("cycleName", cycleName.c_str());
00179             }
00180         }
00181         catch (FesaException& ex)
00182         {
00183             diagMsg.action = DiagnosticUtils::stop;
00184             diagnostics->log(getActionProfDiagTopic, diagMsg);
00185             throw;
00186         }
00187         diagMsg.action = DiagnosticUtils::stop;
00188         diagnostics->log(getActionProfDiagTopic, diagMsg);
00189     }
00190     else // ioType == Input --> we have a Set-Action
00191     {
00192         diagMsg.action = DiagnosticUtils::start;
00193         diagnostics->log(setActionProfDiagTopic, diagMsg);
00194         try
00195         {
00196             workingData.setData(data, true, partialSetIsAllowed_);
00197             // Update the fields linked to value-item: this needs to be done prior to the custom ServerAction execution
00198             // just in case the custom code fires OnDemand event expecting that all the data-fields contain the new setting.
00199             workingData.setRefItems(evt->getMultiplexingContext(), *workingDevice);
00200             if (needFilter_)
00201             {
00202                 FilterType workingFilter;
00203                 workingFilter.setData(const_cast<rdaData&> (filter));
00204                 execute(evt, workingDevice, workingData, workingFilter);
00205             }
00206             else
00207             {
00208                 execute(evt, workingDevice, workingData);
00209             }
00210             diagMsg.action = DiagnosticUtils::undefined;
00211             diagMsg.msg = "Will start commitModifiedFieldSynchronization(): Commit all the setting fields modified by the server action";
00212             diagnostics->log(setActionProfDiagTopic, diagMsg);
00213 
00214             FieldSynchroManager* pFieldSynchroManager = FieldSynchroManager::getInstance();
00215             pFieldSynchroManager->commitModifiedFieldSynchronization(evt->getMultiplexingContext());
00216 
00217             diagMsg.msg = "commitModifiedFieldSynchronization() ended";
00218             diagnostics->log(setActionProfDiagTopic, diagMsg);
00219 
00220             PersistencyManager* thePersistencyManager = PersistencyManager::getInstance();
00221             // Retrieve the class Name in order to trigger the persistence.
00222             // Due to Inheritance a ServerAction cannot keep the globalDevice, because in the context
00223             // of inheritance a derived class may re-use a serverAction defined by a base class but we
00224             // have to trigger the persistence of the derived class
00225             AbstractServerDeviceClass* pDevClass = AbstractServerEquipment::getInstance()->getDeviceClassFromDeviceName(std::string(dev.getName()));
00226             {
00227                 std::ostringstream traceStrStream;
00228                 traceStrStream << "Will trigger persistency for class '" << pDevClass->getName() << "'";
00229                 diagMsg.msg = traceStrStream.str();
00230                 diagnostics->log(setActionProfDiagTopic, diagMsg);
00231             }
00232             thePersistencyManager->trigger(pDevClass->getName());
00233             {
00234                 std::ostringstream traceStrStream;
00235                 traceStrStream << "Persistency for class '" << pDevClass->getName() << "' triggered";
00236                 diagMsg.msg = traceStrStream.str();
00237                 diagnostics->log(setActionProfDiagTopic, diagMsg);
00238             }
00239             // It's time to notify potential clients
00240             notify(*evt->getMultiplexingContext(), dev, SET);
00241 
00242             //Trigger all OnDemand-Event-Sources which need to be triggered automatically
00243             triggerAllAutomaticallyTriggeredOnDemandEventSources(evt->getMultiplexingContext());
00244 
00245         }
00246         catch (FesaException& ex)
00247         {
00248             FieldSynchroManager* pFieldSynchroManager = FieldSynchroManager::getInstance();
00249             pFieldSynchroManager->abortModifiedFieldSynchronization(evt->getMultiplexingContext());
00250             diagMsg.action = DiagnosticUtils::stop;
00251             diagMsg.msg = "";
00252             diagnostics->log(setActionProfDiagTopic, diagMsg);
00253             throw;
00254         }
00255         diagMsg.action = DiagnosticUtils::stop;
00256         diagMsg.msg = "";
00257         diagnostics->log(setActionProfDiagTopic, diagMsg);
00258     }
00259 }
00260 
00261 template<typename DeviceType, typename DataType, typename FilterType>
00262 inline void ServerAction<DeviceType, DataType, FilterType>::performCommit(MultiplexingContext& pTransactionCtxt,
00263                                                                           AbstractDevice *transactionDevice)
00264 {
00265     // TODO review the use of shared pointer while tackling transactions
00266     RequestEvent pEvt(&pTransactionCtxt);
00267     commit(&pEvt, static_cast<DeviceType*> (transactionDevice));
00268 
00269     //        PersistencyManager* thePersistencyManager = PersistencyManager::getInstance();
00270     //        thePersistencyManager->trigger(globalDevice_->className_.getAsString());
00271 }
00272 
00273 template<typename DeviceType, typename DataType, typename FilterType>
00274 inline void ServerAction<DeviceType, DataType, FilterType>::performRollback(MultiplexingContext& pTransactionCtxt,
00275                                                                             AbstractDevice* transactionDevice)
00276 {
00277 
00278     RequestEvent pEvt(&pTransactionCtxt);
00279     rollback(&pEvt, static_cast<DeviceType*> (transactionDevice));
00280 
00281 }
00282 
00283 } // fesa
00284 
00285 #endif // SERVER_ACTION_H_

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1