AbstractServerEquipment.cpp

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 
00003 #include <fesa-core/Server/AbstractServerEquipment.h>
00004 
00005 #include <fesa-core/Server/AbstractServerController.h>
00006 #include <fesa-core/Server/AbstractServerAction.h>
00007 #include <fesa-core/Server/AbstractServerDeviceClass.h>
00008 #include <fesa-core/RDADeviceServer/SubscriptionTreeManager.h>
00009 #include <fesa-core/RDADeviceServer/FesaDeviceServer.h>
00010 #include <fesa-core/DataStore/EquipmentData.h>
00011 #include <fesa-core/DataStore/AbstractDeviceFactory.h>
00012 #include <fesa-core/DataStore/GlobalDevice.h>
00013 #include <fesa-core/Core/AbstractEquipment.h>
00014 #include <fesa-core/Utilities/ProcessConfiguration.h>
00015 #include <fesa-core/Diagnostic/Diagnostics.h>
00016 
00017 #include <cmw-log/Logger.h>
00018 
00019 
00020 namespace
00021 {
00022 
00023 CMW::Log::Logger& logger = CMW::Log::LoggerFactory::getLogger("FESA.FWK.fesa-core.Server.AbstractServerEquipment");
00024 const std::string diagTopic = fesa::DiagnosticUtils::rdaTrackingStr;
00025 
00026 } // namespace
00027 
00028 
00029 namespace fesa
00030 {
00031 
00032 AbstractServerEquipment* AbstractServerEquipment::theInstance_ = NULL;
00033 
00034 
00035 AbstractServerEquipment::AbstractServerEquipment()
00036 {
00037     const ProcessConfiguration* configuration = AbstractEquipment::getInstance()->getProcessConfiguration();
00038     bool useFastUpdate = (configuration->getStringValue(PropertyTag::CLIENT_UPDATE_POLICY) == "fast") ? true : false;
00039     pSubscriptionTreeManager_ = new SubscriptionTreeManager(useFastUpdate);
00040     theInstance_ = this;
00041     // Initialize RDA and instantiate the server. This needs to be done at this time due to some RDA constraints.
00042     // Briefly:  in case of Server and RDA client running inside the same process the rdaConfigfile (specified by the server)
00043     // should be set before a RDA Client executes any rdaRDAService::init().
00044     // This is accomplished in the deployUnitMixed.cpp.xsl, which generates first the initialization of the server.
00045     const std::string rdaServerName = getServerNameFromConfigurationFile();
00046     FesaDeviceServer::initCMW();
00047     pFesaDeviceServer_ = new FesaDeviceServer(rdaServerName, configuration, pSubscriptionTreeManager_);
00048     pServerController_ = new AbstractServerController(*pSubscriptionTreeManager_);
00049 }
00050 
00051 
00052 void AbstractServerEquipment::initialize()
00053 {
00054     EquipmentData* eqData = EquipmentData::getInstance();
00055     *(eqData->serverUp_) = false;
00056 
00057     // set  processID
00058     if (*(eqData->serverProcessID_ )!= 0) // There is already a Server process registered
00059     {
00060         // is the other process up?
00061         if(kill(*(eqData->serverProcessID_), SIGFESA_CHECK_PROCESS_ALIVE) == 0) // if the signal is successfully sent means that the process is up and running
00062         {
00063             // then abort the current process
00064             throw FesaException(__FILE__, __LINE__, FesaErrorServerProcessAlreadyExists.c_str());
00065         }
00066         else
00067         {
00068             if (errno != ESRCH)  // errno = ESRCH means that the process is not running
00069             {
00070                 // If the error is different that ESRCH (i.e. no rights to send signal) we should abort
00071                 throw FesaException(__FILE__, __LINE__, FesaErrorNoPermissionToSendSignals.c_str());
00072             }
00073         }
00074     }
00075     *(eqData->serverProcessID_) = getpid();
00076 
00077     AbstractComponentEquipment::initialize();
00078     pServerController_->initialize();
00079 
00080     //Initialization ends :time to dump the configuration
00081 }
00082 
00083 
00084 void AbstractServerEquipment::start(RunMode runMode)
00085 {
00086     pServerController_->start();
00087 
00088     // start the RDA device server
00089     pFesaDeviceServer_->start();
00090 
00091     // signal that the server part is ready
00092     *(EquipmentData::getInstance()->serverUp_) = true;
00093 
00094     if ( runMode == blocking )
00095     {
00096         waitSignal();
00097     }
00098 }
00099 
00100 
00101 AbstractServerEquipment::~AbstractServerEquipment()
00102 {
00103     LOG_DEBUG_IF(logger, "Shutting down RDA interface ");
00104 
00105     FesaDeviceServer::shutDown();
00106     if (pFesaDeviceServer_ !=NULL)
00107     {
00108         delete(pFesaDeviceServer_);
00109     }
00110 
00111     // remove static data in the AbstractServerAction
00112     AbstractServerAction::releaseStaticObjects();
00113     if (pServerController_ != NULL)
00114     {
00115         delete pServerController_;
00116         pServerController_ = NULL;
00117     }
00118 
00119     LOG_DEBUG_IF(logger, "Server equipment removed ");
00120 
00121 }
00122 
00123 
00124 AbstractServerDeviceClass* AbstractServerEquipment::getDeviceClassFromDeviceName(const std::string& devicename)
00125 {
00126     std::vector<AbstractDeviceClass*>::iterator iter = abstractDeviceClassCol_.begin();
00127     std::vector<AbstractDeviceClass*>::iterator end = abstractDeviceClassCol_.end();
00128 
00129     for (; iter != end; ++iter)
00130     {
00131         try
00132         {
00133             AbstractDeviceFactory* factory = (*iter)->getDeviceFactory();
00134             // check that the factory contains the device either as a global or as a normal one
00135             if (factory->getDevice(devicename) != NULL)
00136             {
00137                 return static_cast<AbstractServerDeviceClass*> (*iter);
00138             }
00139             else if((factory->getGlobalDevice() != 0 ) && (factory->getGlobalDevice()->getName() == devicename))
00140             {
00141                 return static_cast<AbstractServerDeviceClass*> (*iter);
00142             }
00143         }
00144         catch (FesaException& ex)
00145         {
00146             if (ex.getErrorCode() != FesaErrorUnknownDevice)
00147                 throw ex;
00148             //otherwise just continue the search
00149         }
00150     }
00151     //if not found
00152     throw FesaException(__FILE__, __LINE__, FesaErrorUnknownDevice.c_str(), devicename.c_str());
00153 }
00154 
00155 
00156 void AbstractServerEquipment::reportErrorToAllSubscribers(std::string Message)
00157 {
00158     AbstractEquipment* eqp = AbstractEquipment::getInstance();
00159     const std::vector<AbstractDeviceClass*>& classCol = eqp->getServerComponent()->getDeviceClassCol();
00160 
00161     std::vector<AbstractDeviceClass*>::const_iterator iter;
00162     for (iter = classCol.begin(); iter != classCol.end(); iter++)
00163     {
00164         (static_cast<AbstractServerDeviceClass*> (*iter))->reportErrorToSubscribers(Message);
00165     }
00166 }
00167 
00168 
00169 AbstractServerController* AbstractServerEquipment::getServerController()
00170 {
00171     return pServerController_;
00172 }
00173 
00174 
00175 void AbstractServerEquipment::waitSignal()
00176 {
00177     sigset_t sigset;
00178     sigemptyset(&sigset);
00179     sigaddset(&sigset, SIGTSTP);
00180     pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
00181 
00182     sigemptyset(&sigset);
00183     sigaddset(&sigset, SIGHUP);
00184     sigaddset(&sigset, SIGINT);
00185     sigaddset(&sigset, SIGQUIT);
00186     sigaddset(&sigset, SIGILL);
00187     sigaddset(&sigset, SIGTRAP);
00188     sigaddset(&sigset, SIGABRT);
00189     sigaddset(&sigset, SIGBUS);
00190     sigaddset(&sigset, SIGFPE);
00191     sigaddset(&sigset, SIGSEGV);
00192     sigaddset(&sigset, SIGTERM);
00193     sigaddset(&sigset, SIGSTKFLT);
00194     sigaddset(&sigset, SIGSTOP);
00195     sigaddset(&sigset, SIGTTIN);
00196     sigaddset(&sigset, SIGTTOU);
00197     sigaddset(&sigset, SIGFESA_RT_DOWN);
00198     sigaddset(&sigset, SIGFESA_NOTIFICATION_FAILURE);
00199     sigaddset(&sigset, SIGFESA_CHECK_PROCESS_ALIVE);
00200 
00201     int32_t signalID;
00202     for (;;)
00203     {
00204         sigwait(&sigset, &signalID);
00205 
00206         if(signalID == SIGFESA_CHECK_PROCESS_ALIVE)
00207         {
00208             continue; // If the signal was just to check if process alive, nothing to be done
00209         }
00210 
00211         // User signal used by RT to indicate the termination of the RT process
00212         // Switch cannot be used because SIGFESA_RT_DOWN and SIGFESA_NOTIFICATION_FAILURE are not constant-expression
00213         if(signalID == SIGFESA_RT_DOWN)
00214         {
00215             std::string errorStr("Server process received signal from RT: RT is going down.");
00216             LOG_WARNING_IF(logger, errorStr);
00217             pSubscriptionTreeManager_->reportInternalError(std::string("FesaInternalError"), -signalID, std::string("RealTime process is missing."));
00218             //skip the rest
00219             continue;
00220         }
00221         // User signal used by RT to indicate notification queue full
00222         if(signalID == SIGFESA_NOTIFICATION_FAILURE)
00223         {
00224             std::string errorStr("Server process received signal from RT: Notification queue is full.");
00225             LOG_WARNING_IF(logger, errorStr);
00226             pSubscriptionTreeManager_->reportInternalError(std::string("FesaInternalError"), -signalID, std::string("Notification failure (queue is full)."));
00227             //skip the rest
00228             continue;
00229         }
00230         // Otherwise the signal is fatal and the shutdown procedure should be called
00231         EquipmentData* eqData = EquipmentData::getInstance();
00232         *(eqData->serverUp_) = false;
00233         std::string errorStr("Fatal signal received, shutting down Server process.");
00234         LOG_WARNING_IF(logger, errorStr);
00235 
00236         // TODO Should we call any shutdown (specificShutdown....)?
00237 
00238         // We call the default action of the fatal signal, this will let us to create the core dump files
00239         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
00240         signal(signalID, SIG_DFL);
00241         raise(signalID);
00242     }
00243     return;
00244 }
00245 
00246 
00247 const std::string AbstractServerEquipment::getServerNameFromConfigurationFile()
00248 {
00249     const ProcessConfiguration* configuration = AbstractEquipment::getInstance()->getProcessConfiguration();
00250     std::string rdaServerName(configuration->getCMWServerName());
00251     if (rdaServerName.empty() == false)
00252     {
00253         const boost::shared_ptr<Diagnostics>& diagnostics = AbstractEquipment::getInstance()->getDiagnostics();
00254         DiagnosticUtils::DiagnosticMessage diagMsg;
00255         diagMsg.side = DiagnosticUtils::framework;
00256         diagMsg.source = DiagnosticUtils::server;
00257         std::ostringstream traceStrStream;
00258         traceStrStream << "Forcing RDADeviceServer name to '" << rdaServerName << "'";
00259         diagMsg.msg = traceStrStream.str();
00260         diagnostics->log(diagTopic, diagMsg);
00261     }
00262     else
00263     {
00264         rdaServerName += AbstractEquipment::getInstance()->getEquipmentName();
00265         rdaServerName += ".";
00266         rdaServerName += AbstractEquipment::getInstance()->getHostName();
00267     }
00268     return rdaServerName;
00269 }
00270 
00271 } // fesa

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1