00001
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 }
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
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)
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
00162 workingData.getRefItems(evt->getMultiplexingContext(), *workingDevice);
00163
00164
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
00191 {
00192 diagMsg.action = DiagnosticUtils::start;
00193 diagnostics->log(setActionProfDiagTopic, diagMsg);
00194 try
00195 {
00196 workingData.setData(data, true, partialSetIsAllowed_);
00197
00198
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
00222
00223
00224
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
00240 notify(*evt->getMultiplexingContext(), dev, SET);
00241
00242
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
00266 RequestEvent pEvt(&pTransactionCtxt);
00267 commit(&pEvt, static_cast<DeviceType*> (transactionDevice));
00268
00269
00270
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 }
00284
00285 #endif // SERVER_ACTION_H_