00001
00002
00003 #ifndef SHM_FACTORY_H
00004 #define SHM_FACTORY_H
00005
00006 #include <fesa-core/DataStore/DeviceFactoryImp.h>
00007 #include <fesa-core/DataStore/EquipmentData.h>
00008 #include <fesa-core/Utilities/Semaphore.h>
00009
00010 #include <cmw-log/Logger.h>
00011
00012 #include <cstring>
00013 #include <string>
00014 #include <iostream>
00015 #include <cerrno>
00016 #include <sys/mman.h>
00017 #include <fcntl.h>
00018
00019 namespace fesa
00020 {
00021
00022 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType> class DeviceFactoryImp;
00023
00028 typedef struct
00029 {
00030 int32_t shmSize;
00031 int32_t globalDeviceSize;
00032 int32_t domainStoreSize;
00033 int32_t devicesSize;
00034 int32_t muxManagersSize;
00035 int32_t equipmentSize;
00036 } ShmHeader_t;
00037
00045 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType>
00046 class ShmFactory : public DeviceFactoryImp<GlobalDeviceType, DomainStoreType, DevInstType>
00047 {
00048 public:
00053 ShmFactory(const std::string& className);
00054
00060 bool setUpMemory();
00061
00065 void createSharedMemory();
00066
00071 bool attachSharedMemory(int32_t fd);
00072
00076 void removeSharedMemory();
00077
00082 ShmHeader_t* pShmHeader_;
00083
00088 int32_t shmSize_;
00089
00094 std::string shmName_;
00095
00100 char* pAddrMuxManagersSpace_;
00101
00106 char* pAddrDeviceInstanceSpace_;
00107
00112 char* pAddrGlobalDeviceSpace_;
00113
00117 char* pAddrDomainStoreSpace_;
00118
00119
00123 char* pAddrEquipmentDataSpace_;
00124
00125 private:
00126 static CMW::Log::Logger& logger_;
00127
00128 };
00129
00130
00131 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType>
00132 CMW::Log::Logger& ShmFactory<GlobalDeviceType, DomainStoreType, DevInstType>::logger_ = CMW::Log::LoggerFactory::getLogger("FESA.FWK.fesa-core.DataStore.ShmFactory");
00133
00134 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType>
00135 inline ShmFactory<GlobalDeviceType, DomainStoreType, DevInstType>::ShmFactory(const std::string& className) :
00136 DeviceFactoryImp<GlobalDeviceType, DomainStoreType, DevInstType> (className)
00137 {
00138 shmName_ = className + "EquipmentShm";
00139 }
00140
00141 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType>
00142 inline void ShmFactory<GlobalDeviceType, DomainStoreType, DevInstType>::removeSharedMemory()
00143 {
00144 try
00145 {
00146 if ((munmap(pShmHeader_, sizeof(shmSize_))) != -1)
00147 {
00148 shm_unlink(shmName_.c_str());
00149 }
00150 }
00151 catch (...)
00152 {
00153 throw FesaException(__FILE__, __LINE__, FesaErrorRemovingSharedMemory.c_str(), shmName_.c_str());
00154 }
00155 {
00156 std::ostringstream message;
00157 message << "\nShared Memory " << shmName_ << " destroyed!" << std::endl;
00158 LOG_TRACE_IF(logger_, message.str());
00159 }
00160 }
00161
00162 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType>
00163 inline bool ShmFactory<GlobalDeviceType, DomainStoreType, DevInstType>::setUpMemory()
00164 {
00165
00166
00167
00168 Semaphore sem("Shm" + AbstractEquipment::getInstance()->getEquipmentName(), 1);
00169 sem.wait();
00170 int32_t fd;
00171 bool shmHasBeenCreated = false;
00172 try
00173 {
00174
00175 if ((fd = shm_open(shmName_.c_str(), O_RDWR, S_IRWXU)) == -1)
00176 {
00177
00178 if (errno == EACCES)
00179 {
00180 throw FesaException(__FILE__, __LINE__, FesaErrorOpeningSharedMemory.c_str(), shmName_.c_str());
00181 }
00182
00183 createSharedMemory();
00184 this->mapFields(pAddrMuxManagersSpace_, true);
00185 shmHasBeenCreated = true;
00186 {
00187 std::ostringstream message;
00188 message << "Created shared-memory: " << shmName_ << std::endl;
00189 LOG_TRACE_IF(logger_, message.str());
00190 }
00191 }
00192 else
00193 {
00194 if (attachSharedMemory(fd))
00195 {
00196 EquipmentData* eqData = EquipmentData::getInstance();
00197
00198
00199
00200 bool checkProcessesAttachedShm = (eqData->isInitialize_ == NULL);
00201 this->mapFields(pAddrMuxManagersSpace_, false);
00202 shmHasBeenCreated = false;
00203
00204 if (checkProcessesAttachedShm == true)
00205 {
00206 bool isRTProcessRegistered = (*(eqData->rtProcessID_ )!= 0);
00207 bool isServerProcessRegistered = (*(eqData->serverProcessID_ )!= 0);
00208 bool isRegisteredRTProcessUp = false;
00209 bool isRegisteredServerProcessUp = false;
00210 if (isRTProcessRegistered)
00211 {
00212
00213 if(kill(*(eqData->rtProcessID_), SIGFESA_CHECK_PROCESS_ALIVE) == 0)
00214 {
00215 isRegisteredRTProcessUp = true;
00216 }
00217 else
00218 {
00219 if (errno != ESRCH)
00220 {
00221
00222 throw FesaException(__FILE__, __LINE__, FesaErrorNoPermissionToSendSignals.c_str());
00223 }
00224 }
00225 }
00226 if (isServerProcessRegistered)
00227 {
00228
00229 if(kill(*(eqData->serverProcessID_), SIGFESA_CHECK_PROCESS_ALIVE) == 0)
00230 {
00231 isRegisteredServerProcessUp = true;
00232 }
00233 else
00234 {
00235 if (errno != ESRCH)
00236 {
00237
00238 throw FesaException(__FILE__, __LINE__, FesaErrorNoPermissionToSendSignals.c_str());
00239 }
00240 }
00241 }
00242 if ( (!isRTProcessRegistered && !isServerProcessRegistered ) ||
00243 ( !isRegisteredServerProcessUp && !isRegisteredRTProcessUp) )
00244 {
00245 this->unmapFields();
00246 removeSharedMemory();
00247 createSharedMemory();
00248 this->mapFields(pAddrMuxManagersSpace_, true);
00249 shmHasBeenCreated = true;
00250 }
00251 }
00252 {
00253 std::ostringstream message;
00254 message <<"Attached Shared Memory: " << shmName_<< std::endl;
00255 LOG_TRACE_IF(logger_, message.str());
00256 }
00257 }
00258 else
00259 {
00260 removeSharedMemory();
00261 createSharedMemory();
00262 this->mapFields(pAddrMuxManagersSpace_, true);
00263 shmHasBeenCreated = true;
00264 {
00265 std::ostringstream message;
00266 message << "Remove and Created shared-memory: " << shmName_ << std::endl;
00267 LOG_TRACE_IF(logger_, message.str());
00268 }
00269 }
00270 }
00271 if(logger_.isLoggable(CMW::Log::Level::LL_TRACE)) {
00272 std::ostringstream message;
00273 message <<"Space allocated for mux managers :" << this->muxManagersSize_<< std::endl;
00274 message <<"Space allocated for GlobalDevice :" << this->globalDeviceSize_<< std::endl;
00275 message <<"Space allocated for DomainStore :" << this->domainStoreSize_<< std::endl;
00276 message <<"Space allocated for devices :" << this->devicesSize_<< std::endl;
00277 message <<"Total size of the SHM: " << shmSize_<< std::endl;
00278 LOG_TRACE_IF(logger_, message.str());
00279 }
00280 }
00281 catch (FesaException& ex)
00282 {
00283 close(fd);
00284 sem.post();
00285 throw FesaException(ex.getFileName(), ex.getLineNumber(), FesaErrorShmFactorySettingUpMemory.c_str());
00286 }
00287 close(fd);
00288 sem.post();
00289 return (shmHasBeenCreated);
00290 }
00291
00292 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType>
00293 inline void ShmFactory<GlobalDeviceType, DomainStoreType, DevInstType>::createSharedMemory()
00294
00295 {
00296 int32_t org_mask = umask(0);
00297 int32_t fd;
00298 if ((fd = shm_open(shmName_.c_str(), O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) == -1)
00299 {
00300 umask(org_mask);
00301 throw FesaException(__FILE__, __LINE__, FesaErrorCreatingSharedMemory.c_str(), shmName_.c_str());
00302 }
00303 umask(org_mask);
00304
00305 this->computeMemorySize();
00306
00307
00308 shmSize_ = 0;
00309 shmSize_ += sizeof(ShmHeader_t);
00310 shmSize_ += this->muxManagersSize_;
00311 shmSize_ += this->globalDeviceSize_;
00312 shmSize_ += this->domainStoreSize_;
00313 shmSize_ += this->devicesSize_;
00314 shmSize_ += this->equimentDataSize_;
00315
00316
00317 if ((ftruncate(fd, shmSize_)) < 0)
00318 {
00319 throw FesaException(__FILE__, __LINE__, FesaErrorResizingSharedMemory.c_str(), shmName_.c_str());
00320 }
00321
00322
00323 if ((pShmHeader_ = (ShmHeader_t*) mmap(0, shmSize_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == 0)
00324 {
00325 throw FesaException(__FILE__, __LINE__, FesaErrorMappingSharedMemory.c_str(), shmName_.c_str());
00326 }
00327
00328
00329 std::memset(pShmHeader_, 0, shmSize_);
00330
00331
00332 pShmHeader_->shmSize = shmSize_;
00333 pShmHeader_->muxManagersSize = this->muxManagersSize_;
00334 pShmHeader_->globalDeviceSize = this->globalDeviceSize_;
00335 pShmHeader_->domainStoreSize = this->domainStoreSize_;
00336 pShmHeader_->devicesSize = this->devicesSize_;
00337 pShmHeader_->equipmentSize = this->equimentDataSize_;
00338
00339
00340 pAddrMuxManagersSpace_ = (char*) ((char*) pShmHeader_ + sizeof(ShmHeader_t));
00341 pAddrGlobalDeviceSpace_ = pAddrMuxManagersSpace_ + this->muxManagersSize_;
00342 pAddrDomainStoreSpace_ = pAddrGlobalDeviceSpace_ + this->globalDeviceSize_;
00343 pAddrDeviceInstanceSpace_ = pAddrDomainStoreSpace_ + this->domainStoreSize_;
00344 pAddrEquipmentDataSpace_ = pAddrDeviceInstanceSpace_ + this->devicesSize_;
00345 close(fd);
00346 }
00347
00348 template<typename GlobalDeviceType, typename DomainStoreType, typename DevInstType>
00349 inline bool ShmFactory<GlobalDeviceType, DomainStoreType, DevInstType>::attachSharedMemory(int32_t fd)
00350
00351 {
00352
00353 if ((pShmHeader_ = (ShmHeader_t *) mmap(0, sizeof(ShmHeader_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0))
00354 == 0)
00355 {
00356 throw FesaException(__FILE__, __LINE__, FesaErrorMappingSharedMemory.c_str(), shmName_.c_str());
00357 }
00358 this->computeMemorySize();
00359
00360
00361 shmSize_ = 0;
00362 shmSize_ += sizeof(ShmHeader_t);
00363 shmSize_ += this->muxManagersSize_;
00364 shmSize_ += this->globalDeviceSize_;
00365 shmSize_ += this->domainStoreSize_;
00366 shmSize_ += this->devicesSize_;
00367 shmSize_ += this->equimentDataSize_;
00368
00369 if (shmSize_ != pShmHeader_->shmSize || this->muxManagersSize_ != pShmHeader_->muxManagersSize
00370 || this->globalDeviceSize_ != pShmHeader_->globalDeviceSize || this->domainStoreSize_
00371 != pShmHeader_->domainStoreSize || this->devicesSize_ != pShmHeader_->devicesSize || this->equimentDataSize_ != pShmHeader_->equipmentSize)
00372 {
00373
00374 if ((munmap(pShmHeader_, sizeof(ShmHeader_t))) == -1)
00375 {
00376 throw FesaException(__FILE__, __LINE__, FesaErrorUnMappingSharedMemory.c_str(), shmName_.c_str());
00377 }
00378 return false;
00379 }
00380
00381
00382 if ((munmap(pShmHeader_, sizeof(ShmHeader_t))) == -1)
00383 {
00384 throw FesaException(__FILE__, __LINE__, FesaErrorUnMappingSharedMemory.c_str(), shmName_.c_str());
00385 }
00386
00387
00388 char* pAddr;
00389 if ((pAddr = (char *) mmap(0, shmSize_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == 0)
00390 {
00391 throw FesaException(__FILE__, __LINE__, FesaErrorMappingSharedMemory.c_str(), shmName_.c_str());
00392 }
00393
00394
00395 pAddrMuxManagersSpace_ = pAddr + sizeof(ShmHeader_t);
00396 pAddrGlobalDeviceSpace_ = pAddrMuxManagersSpace_ + this->muxManagersSize_;
00397 pAddrDomainStoreSpace_ = pAddrGlobalDeviceSpace_ + this->globalDeviceSize_;
00398 pAddrDeviceInstanceSpace_ = pAddrDomainStoreSpace_ + this->domainStoreSize_;
00399 pAddrEquipmentDataSpace_ = pAddrDeviceInstanceSpace_ + this->devicesSize_;
00400
00401 return true;
00402 }
00403 }
00404 #endif // SHM_FACTORY_H