00001
00002
00003 #include <fesa-core/RDADeviceServer/FesaDeviceServer.h>
00004
00005 #include <fesa-core/RDADeviceServer/SubscriptionTreeManager.h>
00006 #include <fesa-core/Core/AbstractEquipment.h>
00007 #include <fesa-core/Core/FesaDefs.h>
00008 #include <fesa-core/Core/ThreadPriorityConfiguration.h>
00009 #include <fesa-core/DataStore/AbstractDevice.h>
00010 #include <fesa-core/DataStore/AbstractDeviceFactory.h>
00011 #include <fesa-core/DataStore/EquipmentData.h>
00012 #include <fesa-core/DataStore/GlobalDevice.h>
00013 #include <fesa-core/Diagnostic/Diagnostics.h>
00014 #include <fesa-core/Exception/FesaException.h>
00015 #include <fesa-core/Server/AbstractServerDeviceClass.h>
00016 #include <fesa-core/Server/AbstractServerEquipment.h>
00017 #include <fesa-core/Server/Property.h>
00018 #include <fesa-core/Utilities/Lock.h>
00019 #include <fesa-core/Utilities/ProcessConfiguration.h>
00020 #include <fesa-core/Utilities/XMLParser.h>
00021
00022 #include <cmw-rda/Config.h>
00023 #include <cmw-rda/Data.h>
00024 #include <cmw-rda/Exception.h>
00025 #include <cmw-log/Logger.h>
00026
00027
00028 namespace
00029 {
00030
00031 CMW::Log::Logger& logger = CMW::Log::LoggerFactory::getLogger("FESA.FWK.fesa-core.RDADeviceServer.FesaDeviceServer");
00032 const std::string diagTopic = fesa::DiagnosticUtils::rdaTrackingStr;
00033
00034 }
00035
00036
00037 namespace fesa
00038 {
00039
00040 const std::string ERROR_CATEGORY = "FESA";
00041
00042 FesaDeviceServer::FesaDeviceServer(const std::string& name, const ProcessConfiguration* processConfiguration, SubscriptionTreeManager* pSubscriptionTreeManager) :
00043 rdaDeviceServerBase(name.c_str()),
00044 pTreeManager_(pSubscriptionTreeManager)
00045 {
00046 firstUpdateAcquisitionEnabled_ = processConfiguration->getBoolValue(PropertyTag::FIRST_UPDATE_ACQUISITION);
00047 firstUpdateSettingEnabled_ = processConfiguration->getBoolValue(PropertyTag::FIRST_UPDATE_SETTING);
00048 try
00049 {
00050 rdaConfig::useConfigFile(processConfiguration->getCMWConfigFile().c_str());
00051 }
00052 catch (rdaInternalError& ex)
00053 {
00054 std::ostringstream msg;
00055 msg << "rdaConfig::useConfigFile failed: " << ex.getMessage();
00056 LOG_ERROR_IF(logger, msg.str());
00057 }
00058 }
00059
00060 FesaDeviceServer::~FesaDeviceServer()
00061 {
00062 shutDown();
00063 mutex_.lock();
00064 }
00065
00066 void FesaDeviceServer::runDeviceServer()
00067 {
00068 const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00069 DiagnosticUtils::DiagnosticMessage diagMsg;
00070 diagMsg.side = DiagnosticUtils::framework;
00071 diagMsg.source = DiagnosticUtils::server;
00072 std::ostringstream traceStrStream;
00073 traceStrStream << "Starting FESA device server with name '" << getName() << "' - Server side startup should be finished here";
00074 diagMsg.msg = traceStrStream.str();
00075 diagnostics->log(diagTopic, diagMsg);
00076 try
00077 {
00078
00079 Lock lock(mutex_);
00080 runServer();
00081 }
00082 catch (const rdaInternalError& ex)
00083 {
00084 std::ostringstream errorStrStream;
00085 errorStrStream << "RDA server failure. RDA internal error:" << ex.getFile() << " : " << ex.getLine() << " : " << ex.getMessage();
00086 LOG_ERROR_IF(logger, errorStrStream.str());
00087 throw;
00088 }
00089
00090
00091 catch (const rdaException& ex)
00092 {
00093 std::ostringstream errorStrStream;
00094 errorStrStream << "RDA server failure. RDA internal error: " << ex.getType() << " " << ex.getMessage();
00095 LOG_ERROR_IF(logger, errorStrStream.str());
00096 throw;
00097 }
00098 catch (...)
00099 {
00100 LOG_ERROR_IF(logger, "RDA Server failure. Unknown exception in 'runRDADeviceServer'");
00101 throw;
00102 }
00103 }
00104
00105 rdaData* FesaDeviceServer::get(const rdaIOPoint& iop, const rdaData& ctx)
00106 {
00107 const std::string threadName = "GetSetLayer";
00108 Thread::registerThreadIdName(pthread_self(), threadName);
00109 const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00110 DiagnosticUtils::DiagnosticMessage diagMsg;
00111 diagMsg.side = DiagnosticUtils::framework;
00112 diagMsg.source = DiagnosticUtils::server;
00113 std::auto_ptr<rdaData> value;
00114
00115
00116 try
00117 {
00118 if (isRTProcessDown())
00119 {
00120 throw FesaException(__FILE__, __LINE__, FesaErrorRTProcessDown.c_str());
00121 }
00122 std::ostringstream traceStrStream;
00123 traceStrStream << "Device: " << iop.getDeviceName() << ". Property: " << iop.getPropertyName()
00124 << ". Client: " << getClientInfo()->getUserName() << " from " << getClientInfo()->getHostName();
00125 diagMsg.msg = traceStrStream.str();
00126 diagnostics->log(diagTopic, diagMsg);
00127
00128 Property* property;
00129 AbstractDevice* device;
00130 AbstractServerDeviceClass* srvDeviceClass;
00131 std::string cycleSelector("");
00132 decodeIOPoint(iop, srvDeviceClass, property, device, cycleSelector);
00133 value.reset(new rdaData());
00134 property->get(*device, cycleSelector, ctx, *value, GET);
00135 }
00136 catch (FesaException& ex)
00137 {
00138 throw rdaIOError(ERROR_CATEGORY.c_str(), ex.getErrorCodeAsLong(), ex.getMessage().c_str());
00139 }
00140 catch (rdaException& ex)
00141 {
00142 throw rdaIOError("RDA", 0, ex.getMessage());
00143 }
00144 catch (...)
00145 {
00146 throw rdaIOError(ERROR_CATEGORY.c_str(), 0, "failure performing 'Get': Unknown Error");
00147 }
00148 rdaData* pRDAData = value.get();
00149 value.release();
00150 return pRDAData;
00151 }
00152
00153 void FesaDeviceServer::set(const rdaIOPoint& iop, const rdaData& ctx, const rdaData& value)
00154 {
00155 const std::string threadName = "GetSetLayer";
00156 Thread::registerThreadIdName(pthread_self(), threadName);
00157 const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00158 DiagnosticUtils::DiagnosticMessage diagMsg;
00159 diagMsg.side = DiagnosticUtils::framework;
00160 diagMsg.source = DiagnosticUtils::server;
00161
00162
00163 try
00164 {
00165 if (isRTProcessDown())
00166 {
00167 throw FesaException(__FILE__, __LINE__, FesaErrorRTProcessDown.c_str());
00168 }
00169 std::ostringstream traceStrStream;
00170 traceStrStream << "Device: " << iop.getDeviceName() << ". Property: " << iop.getPropertyName()
00171 << ". Client: " << getClientInfo()->getUserName() << " from " << getClientInfo()->getHostName();
00172 diagMsg.msg = traceStrStream.str();
00173 diagnostics->log(diagTopic, diagMsg);
00174
00175 Property* property;
00176 AbstractDevice* device;
00177 AbstractServerDeviceClass* srvDeviceClass;
00178 std::string cycleSelector("");
00179 decodeIOPoint(iop, srvDeviceClass, property, device, cycleSelector);
00180 property->set(*device, cycleSelector, ctx, value);
00181 }
00182 catch (rdaException& ex)
00183 {
00184 throw rdaIOError("RDA", 0, ex.getMessage());
00185 }
00186 catch (FesaException& ex)
00187 {
00188 throw rdaIOError(ERROR_CATEGORY.c_str(), ex.getErrorCodeAsLong(), ex.getMessage().c_str());
00189 }
00190 catch (...)
00191 {
00192 throw rdaIOError(ERROR_CATEGORY.c_str(), 0, "failure performing 'Set': Unknown Error");
00193 }
00194 }
00195
00196 void FesaDeviceServer::monitorOn(const rdaIOPoint& iop, const rdaData& ctx, rdaValueChangeListener* listener)
00197 {
00198 const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00199 DiagnosticUtils::DiagnosticMessage diagMsg;
00200 diagMsg.side = DiagnosticUtils::framework;
00201 diagMsg.source = DiagnosticUtils::server;
00202 Property* property;
00203 AbstractDevice* device;
00204 std::string cycleSelector("");
00205 AbstractServerDeviceClass* srvDeviceClass;
00206
00207
00208 try
00209 {
00210 if (isRTProcessDown())
00211 {
00212 throw FesaException(__FILE__, __LINE__, FesaErrorRTProcessDown.c_str());
00213 }
00214 std::ostringstream traceStrStream;
00215 traceStrStream << "Device: " << iop.getDeviceName() << ". Property: " << iop.getPropertyName()
00216 << ". Client: " << getClientInfo()->getUserName() << " from " << getClientInfo()->getHostName();
00217 diagMsg.msg = traceStrStream.str();
00218 diagnostics->log(diagTopic, diagMsg);
00219 decodeIOPoint(iop, srvDeviceClass, property, device, cycleSelector);
00220 property->validateParameters(*device, cycleSelector, (ctx.isEmpty() ? false : true), SUBSCRIBE);
00221
00222 if (*(EquipmentData::getInstance()->notificationFailure_) == true)
00223 {
00224 throw FesaException(__FILE__, __LINE__, FesaErrorPropertySubscriptionDisabled.c_str());
00225 }
00226 pTreeManager_->addSubscriber(srvDeviceClass->getName(), *device, *property, cycleSelector, ctx, listener);
00227 }
00228 catch (rdaException& ex)
00229 {
00230 throw rdaIOError("RDA", 0, ex.getMessage());
00231 }
00232 catch (FesaException& ex)
00233 {
00234 throw rdaIOError(ERROR_CATEGORY.c_str(), ex.getErrorCodeAsLong(), ex.getMessage().c_str());
00235 }
00236 catch (...)
00237 {
00238 throw rdaIOError(ERROR_CATEGORY.c_str(), 0, "failure adding new Subscriber: Unknown Error");
00239 }
00240 }
00241
00242 void FesaDeviceServer::monitorOff(const rdaIOPoint& iop, rdaValueChangeListener* listener)
00243 {
00244 const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00245 DiagnosticUtils::DiagnosticMessage diagMsg;
00246 diagMsg.side = DiagnosticUtils::framework;
00247 diagMsg.source = DiagnosticUtils::server;
00248 AbstractServerDeviceClass* srvDeviceClass;
00249 Property* property;
00250 AbstractDevice* device;
00251 std::string cycleSelector;
00252
00253 std::ostringstream traceStrStream;
00254 traceStrStream << "Device: " << iop.getDeviceName() << ". Property: " << iop.getPropertyName()
00255 << ". Client: " << getClientInfo()->getUserName() << " from " << getClientInfo()->getHostName();
00256 diagMsg.msg = traceStrStream.str();
00257 diagnostics->log(diagTopic, diagMsg);
00258 try
00259 {
00260
00261 decodeIOPoint(iop, srvDeviceClass, property, device, cycleSelector);
00262 pTreeManager_->removeSubscriber(*device, *property, cycleSelector, listener);
00263
00264 }
00265 catch (rdaException& ex)
00266 {
00267 throw rdaIOError("RDA", 0, ex.getMessage());
00268 }
00269 catch (FesaException& ex)
00270 {
00271 throw rdaIOError(ERROR_CATEGORY.c_str(), ex.getErrorCodeAsLong(), ex.getMessage().c_str());
00272 }
00273 catch (...)
00274 {
00275 throw rdaIOError(ERROR_CATEGORY.c_str(), 0, "failure removing Subscriber: Unknown Error");
00276 }
00277 }
00278
00279 void FesaDeviceServer::decodeIOPoint(const rdaIOPoint& iop, AbstractServerDeviceClass*& srvDeviceClass, Property*& prop, AbstractDevice*& device,
00280 std::string& cycleSelector)
00281 {
00282 const std::string propertyName(iop.getPropertyName());
00283 const std::string deviceName(iop.getDeviceName());
00284
00285
00286
00287 const char* cs = const_cast<char*> (iop.getCycleSelector());
00288 if (!cs)
00289 cs = "";
00290 cycleSelector = cs;
00291
00292
00293 AbstractServerEquipment* equipment = AbstractServerEquipment::getInstance();
00294 srvDeviceClass = equipment->getDeviceClassFromDeviceName(deviceName);
00295 prop = srvDeviceClass->getProperty(propertyName);
00296 if (prop == NULL)
00297 {
00298 throw FesaException(__FILE__, __LINE__, FesaErrorPropertyNotFound.c_str(), propertyName.c_str());
00299 }
00300
00301 if (prop->isGlobal())
00302 {
00303 device = srvDeviceClass->getDeviceFactory()->getGlobalDevice();
00304 if (device == NULL)
00305 {
00306 device = srvDeviceClass->getDeviceFactory()->getDevice(deviceName);
00307 if (device != NULL)
00308
00309 throw FesaException(__FILE__, __LINE__, FesaErrorGlobalPropertyDeviceInstance.c_str(), propertyName.c_str());
00310
00311 throw FesaException(__FILE__, __LINE__, FesaErrorUnknownDevice.c_str(), deviceName.c_str());
00312 }
00313 }
00314 else
00315 {
00316 device = srvDeviceClass->getDeviceFactory()->getDevice(deviceName);
00317 if (device == NULL) {
00318 device = srvDeviceClass->getDeviceFactory()->getGlobalDevice();
00319 if (device != NULL)
00320
00321 throw FesaException(__FILE__, __LINE__, FesaErrorDevicePropertyGlobalDevice.c_str(), propertyName.c_str());
00322
00323 throw FesaException(__FILE__, __LINE__, FesaErrorUnknownDevice.c_str(), deviceName.c_str());
00324 }
00325 }
00326 }
00327
00328
00329 bool FesaDeviceServer::isRTProcessDown()
00330 {
00331 EquipmentData* eqData = EquipmentData::getInstance();
00332 if (*(eqData->hasRt_) && !(*(eqData->rtUp_)))
00333 {
00334 return true;
00335 }
00336 return false;
00337 }
00338
00339 void FesaDeviceServer::start()
00340 {
00341 {
00342 AbstractEquipment* eqp = AbstractEquipment::getInstance();
00343 std::string instanceFile = eqp->getDeviceDataFileName();
00344 XMLParser xmlParser(instanceFile, false);
00345 ThreadPriorityConfigurationFromFile conf(xmlParser, eqp->getProcessConfiguration());
00346 int32_t prio = conf.getPrioCMW();
00347 setPriority(prio);
00348 }
00349 Thread::start(false, "DeviceServer");
00350 }
00351
00352 void FesaDeviceServer::run()
00353 {
00354 try
00355 {
00356 runDeviceServer();
00357 }
00358 catch(const rdaInternalError& ex)
00359 {
00360 std::ostringstream errorStrStream;
00361 errorStrStream << "Fatal error in RDA runtime:" << ex.getFile() << " : " << ex.getLine() << " : " << ex.getMessage() << std::endl;
00362 LOG_ERROR_IF(logger, errorStrStream.str());
00363 throw FesaException(__FILE__, __LINE__, FesaErrorIRunningDeviceServer.c_str(), ex.getMessage());
00364 }
00365 catch(const rdaInternalException& ex)
00366 {
00367 std::ostringstream errorStrStream;
00368 errorStrStream << "Recoverable error in the RDA runtime:" << ex.getMessage() << std::endl;
00369 LOG_ERROR_IF(logger, errorStrStream.str());
00370 throw FesaException(__FILE__, __LINE__, FesaErrorIRunningDeviceServer.c_str(), ex.getMessage());
00371 }
00372 }
00373
00374 void FesaDeviceServer::initCMW()
00375 {
00376 const int argc = 0;
00377 char** argv = NULL;
00378 try
00379 {
00380 rdaDeviceServerBase::init(argc, argv);
00381 std::ostringstream infoStringStream;
00382 infoStringStream << "CMW initialized from " << AbstractEquipment::getInstance()->getProcessConfiguration()->getCMWConfigFile();
00383 LOG_INFO_IF(logger, infoStringStream.str());
00384 }
00385 catch (const rdaInternalError& ex)
00386 {
00387 throw FesaException(__FILE__, __LINE__, FesaErrorInitializingRdaDeviceServerBase.c_str(), ex.getMessage());
00388 }
00389 }
00390
00391 }