Property.cpp

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 
00003 #include <fesa-core/Server/Property.h>
00004 
00005 #include <fesa-core/Server/RequestEvent.h>
00006 #include <fesa-core/Server/AbstractServerAction.h>
00007 #include <fesa-core/DataStore/GlobalDevice.h>
00008 #include <fesa-core/Synchronization/MultiplexingContext.h>
00009 #include <fesa-core/Synchronization/NoneContext.h>
00010 #include <fesa-core/Synchronization/TimingContext.h>
00011 #include <fesa-core/Synchronization/SynchronizationLabObjectFactory.h>
00012 #include <fesa-core/Synchronization/CycleDescriptor.h>
00013 #include <fesa-core/Diagnostic/FesaStream.h>
00014 
00015 #include <cmw-rda/Data.h>
00016 
00017 
00018 namespace fesa
00019 {
00020 
00021 Property::Property(const std::string& name, bool isGlobal, bool isOnChange, bool isSubscribable, PropertyType type,
00022                    bool multiplexed, int32_t priorityOffset, const std::string& notificationThreadKey, AbstractServerAction* getServerAction,
00023                    AbstractServerAction* setServerAction, const std::string& className) :
00024     name_(name),
00025     isGlobal_(isGlobal),
00026     isOnChange_(isOnChange),
00027     isSubscribable_(isSubscribable),
00028     type_(type),
00029     multiplexed_(multiplexed),
00030     priorityOffset_(priorityOffset),
00031     notificationThreadKey_(notificationThreadKey),
00032     getServerAction_(getServerAction),
00033     setServerAction_(setServerAction)
00034 {
00035     //TODO: Fix that as soon as the MetaModel supports the OnChange mechanism
00036     //isOnChange_ = isOnChange;
00037 }
00038 
00039 
00040 Property::~Property()
00041 {
00042     if (getServerAction_ != NULL)
00043     {
00044         delete getServerAction_;
00045         getServerAction_ = NULL;
00046     }
00047 
00048     if (setServerAction_ != NULL)
00049     {
00050         delete setServerAction_;
00051         setServerAction_ = NULL;
00052     }
00053 }
00054 
00055 void Property::get(AbstractDevice& device, const std::string& cycleSelector, const rdaData& filter, rdaData& value,
00056                    RequestType reqType)
00057 {
00058     // check if the action is not NULL
00059     if (getServerAction_ == NULL)
00060         throw FesaException(__FILE__, __LINE__, FesaErrorPropertyNotReadable.c_str(), name_.c_str());
00061 
00062     // validate the parameters
00063     validateParameters(device, cycleSelector, !(filter.isEmpty()), reqType);
00064 
00065     MultiplexingContext ctx;
00066     if (cycleSelector.empty())
00067     {
00068         ctx = NoneContext();
00069     }
00070     else
00071     {
00072         ctx = TimingContext(cycleSelector);
00073     }
00074 
00075     RequestEvent ev(&ctx);
00076 
00077     ctx.setSettingAccess(MultiplexingContext::CHECK_FLAG_TO_BE_SYNC);
00078     // acquisition fields (mux manager occurence type) should be only accessible  from RT part
00079     ctx.setAcquisitionAccess(MultiplexingContext::SET_NOT_ALLOWED);
00080 
00081     // Initialize the context with extra condition if any is specified
00082     if (!filter.isEmpty() && filter.contains(EXTRA_CRITERION_NAME.c_str()))
00083     {
00084         ctx.setExtraCondition(filter.extractString(EXTRA_CRITERION_NAME.c_str()));
00085     }
00086     getServerAction_->execute(&ev, device, filter, value, Output, reqType);
00087 
00088 }
00089 
00090 void Property::get(AbstractDevice& device, MultiplexingContext& context, const rdaData& filter, rdaData& value,
00091                    RequestType reqType)
00092 {
00093     // check if the action is not NULL
00094     if (getServerAction_ == NULL)
00095     {
00096         throw FesaException(__FILE__, __LINE__, FesaErrorPropertyNotReadable.c_str(), name_.c_str());
00097     }
00098 
00099     RequestEvent ev(&context);
00100     // The current method is used for the notification mechanism, and
00101     // in case of a setting property, any get access of setting fields should
00102     // access the latest updated data, being this either pending or active buffer.
00103 
00104 
00105     context.setSettingAccess(MultiplexingContext::CHECK_FLAG_TO_BE_SYNC);
00106     // acquisition fields (mux manager occurence type) should be only accessible  from RT part
00107     context.setAcquisitionAccess(MultiplexingContext::SET_NOT_ALLOWED);
00108     getServerAction_->execute(&ev, device, filter, value, Output, reqType);
00109 }
00110 
00111 void Property::set(AbstractDevice& device, const std::string& cycleSelector, const rdaData& filter,
00112                    const rdaData& value)
00113 {
00114     // check if the action is not NULL
00115     if (setServerAction_ == NULL)
00116         throw FesaException(__FILE__, __LINE__, FesaErrorPropertyNotWritable.c_str(), name_.c_str());
00117 
00118     // validate the parameters
00119     validateParameters(device, cycleSelector, !(filter.isEmpty()), SET);
00120 
00121     // TODO validate against control access manager
00122     MultiplexingContext ctx;
00123     if (cycleSelector.empty())
00124     {
00125         ctx = NoneContext();
00126     }
00127     else
00128     {
00129         ctx = TimingContext(cycleSelector);
00130     }
00131 
00132     // Modify the setting access mask for the context
00133     // we allow set access for setting fields
00134     ctx.setSettingAccess(MultiplexingContext::SET_ALLOWED);
00135     // acquisition fields (mux manager occurence type) should be only accessible  from RT part
00136     ctx.setAcquisitionAccess(MultiplexingContext::SET_NOT_ALLOWED);
00137 
00138     RequestEvent ev(&ctx);
00139     // Initialize the context with extra condition if any is specified
00140     if (!filter.isEmpty() && filter.contains(EXTRA_CRITERION_NAME.c_str()))
00141     {
00142         ctx.setExtraCondition(filter.extractString(EXTRA_CRITERION_NAME.c_str()));
00143     }
00144 
00145     //we have to cast the value here, because we recieve it from RDA as const
00146     //and the execute method has to work for get and set actions
00147     setServerAction_->execute(&ev, device, filter, *const_cast<rdaData*> (&value), Input, SET);
00148 }
00149 
00150 void Property::validateParameters(AbstractDevice& dev, const std::string& cycleSelector, bool hasFilter,
00151                                   RequestType reqType)
00152 {
00153 
00154     // Check if the device is a global-instance or a device-instance
00155     GlobalDevice* globdev = dynamic_cast<GlobalDevice*> (&dev);
00156     // Check the consistency: global-property can be used only with the global-deviceinstance
00157     // device-property can be used only with device-instance
00158     if (((globdev != NULL) && (!isGlobal_)) || ((globdev == NULL) && (isGlobal_)))
00159     {
00160         throw FesaException(__FILE__, __LINE__, FesaErrorMixedGlobalWithNoneGlobal.c_str());
00161     }
00162 
00163     if (reqType == SUBSCRIBE && !isSubscribable_)
00164     {
00165         throw FesaInvalidResourceException(__FILE__, __LINE__, FesaErrorPropertyNotSubscribable.c_str(),
00166                                            name_.c_str());
00167     }
00168 
00169     // cycleSelector cannot be empty if the dev/property is multiplexed and the requestType is Get or Set
00170     if (cycleSelector.empty())
00171     {
00172         if (dev.isMultiplexed() && multiplexed_ && reqType != SUBSCRIBE)
00173             throw FesaException(__FILE__, __LINE__, FesaErrorCycleNULLInMultiplexedProperty.c_str(), name_.c_str());
00174     }
00175     else
00176     {
00177         // Check cycleSelector validity
00178         validateCycleSelector(dev, cycleSelector, reqType);
00179     }
00180 
00181     // Check if a filter is required
00182     if (hasFilter != needFilter())
00183     {
00184         if (needFilter())
00185             throw FesaException(__FILE__, __LINE__, FesaErrorPropertyNeedsFilter.c_str(), name_.c_str());
00186         else
00187             throw FesaException(__FILE__, __LINE__, FesaErrorPropertyNotSupportFilter.c_str(), name_.c_str());
00188     }
00189 }// end validateParameters
00190 
00191 
00197 void Property::validateCycleSelector(fesa::AbstractDevice& device, const std::string& cycleSelector,
00198                                      fesa::RequestType reqType)
00199 {
00200     CycleSelector timingSelector;
00201     fesa::parseCycleSelector(cycleSelector, timingSelector);
00202 
00203     // check timingDomain between the device and the one specified by the cycleSelector
00204     const std::string& timDom = device.timingDomain.get();
00205 
00206     if (timingSelector.domain_ != timDom)
00207         throw FesaException(__FILE__, __LINE__, FesaErrorWrongTimingDomain.c_str(), timingSelector.domain_.c_str(),
00208                             timDom.c_str());
00209 
00210     // verify if the cycle-descriptor is valid
00211     SynchronizationLabObjectFactory* syncFactory = SynchronizationLabObjectFactory::getInstance();
00212     CycleDescriptor* td = syncFactory->getCycleDescriptor(timingSelector.domain_, timingSelector.criterion_);
00213 
00214     td->isValidCycleSelector(cycleSelector);
00215 
00216     if ((reqType != SUBSCRIBE) && (device.isMultiplexed()) && (strcmp(timingSelector.criterion_.c_str(),
00217                                                                       device.mainMuxCriterion.get()) != 0))
00218 
00219         throw FesaException(__FILE__, __LINE__, FesaErrorIllegalTiming.c_str(), name_.c_str());
00220 
00221     //Checking cycleSelector may require additional Lab specific check.
00222     //validateCycleSelector is a Lab implementation throwing an exception in case of invalid cycleSelector
00223     fesa::validateCycleSelector(timingSelector, reqType);
00224 }
00225 
00226 int64_t Property::getDataTimestamp(AbstractDevice& device, MultiplexingContext& context, const rdaData& filter)
00227 {
00228     //        return getServerAction_->getDataTimestamp(device, context, filter);
00229     return 0;
00230 }
00231 
00232 void Property::printConfig(FesaStream* configStream)
00233 {
00234     *configStream << "\t\t\t\t\t<property name=\"" << name_ << "\" multiplexed=\"" << multiplexed_
00235                   << "\" onChange=\"" << isOnChange_ << "\" subscribable=\"" << isSubscribable_ << "\">" << std::endl;
00236     if(getServerAction_ != NULL)
00237     {
00238         *configStream << "\t\t\t\t\t\t<get-server-action ";
00239         getServerAction_->printConfig(configStream);
00240         *configStream << "\t\t\t\t\t\t</get-server-action>";
00241     }
00242     if(setServerAction_ != NULL)
00243     {
00244         *configStream << "\t\t\t\t\t\t<set-server-action ";
00245         getServerAction_->printConfig(configStream);
00246         *configStream << "\t\t\t\t\t\t</set-server-action>";
00247     }
00248     *configStream << "\t\t\t\t\t</property>" << std::endl;
00249 }
00250 
00251 void Property::printState(FesaStream* fesaStream, double elapsedTime)
00252 {
00253 
00254 }
00255 
00256 const std::string& Property::getNotificationThreadKey()
00257 {
00258     return notificationThreadKey_;
00259 }
00260 
00261 const std::string& Property::getClassName()
00262 {
00263     return className_;
00264 }
00265 
00266 } // fesa

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1