PSEnv/include/EpicsStore.h

Go to the documentation of this file.
00001 #ifndef PSENV_EPICSSTORE_H
00002 #define PSENV_EPICSSTORE_H
00003 
00004 //--------------------------------------------------------------------------
00005 // File and Version Information:
00006 //      $Id: EpicsStore.h 8341 2014-06-05 21:10:27Z davidsch@SLAC.STANFORD.EDU $
00007 //
00008 // Description:
00009 //      Class EpicsStore.
00010 //
00011 //------------------------------------------------------------------------
00012 
00013 //-----------------
00014 // C/C++ Headers --
00015 //-----------------
00016 #include <string>
00017 #include <vector>
00018 #include <boost/scoped_ptr.hpp>
00019 #include <boost/shared_ptr.hpp>
00020 #include <boost/utility.hpp>
00021 #include <boost/enable_shared_from_this.hpp>
00022 
00023 //----------------------
00024 // Base Class Headers --
00025 //----------------------
00026 
00027 //-------------------------------
00028 // Collaborating Class Headers --
00029 //-------------------------------
00030 #include "PSEnv/EpicsStoreImpl.h"
00031 #include "pdsdata/xtc/Src.hh"
00032 #include "psddl_psana/epics.ddl.h"
00033 
00034 //------------------------------------
00035 // Collaborating Class Declarations --
00036 //------------------------------------
00037 
00038 //              ---------------------
00039 //              -- Class Interface --
00040 //              ---------------------
00041 
00042 namespace PSEnv {
00043 
00044 /**
00045  *  @ingroup PSEnv
00046  *  
00047  *  @brief Class implementing storage for EPICS data in psana framework.
00048  *  
00049  *  The EPICS store keeps track of all current EPICS value during the event 
00050  *  loop in the framework. It is updated with the new values whenever 
00051  *  new EPICS data is read from the input file.
00052  *
00053  *  Epics data is retrieved by specifying a name. The EpicsStore first checks
00054  *  if this name is an alias, if not it is assumed to be a pvName.
00055  *
00056  *  When the initial EPICS data is added, the EpicsStore checks for aliases that 
00057  *  have the same name as a pvName. These aliases are discared (debug messages 
00058  *  are generated for discared  aliases). This prevents aliases that hide pv's.
00059  *  A consequence is that users cannot use aliases to swap the names of existing 
00060  *  epics pv's.
00061  *
00062  *  While the same EPICs pv can come from multiple sources, the EpicsStore does
00063  *  not expose the source to the user in the interface to get EPICs data. When a 
00064  *  user gets a pv, the EpicsStore returns the last one stored. When the same TIME 
00065  *  pv is coming from two or more sources during the same event, users will generally
00066  *  prefer the one with the latest internal time stamp value. When storing EPICS data, 
00067  *  an optional eventId can be passed. EpicsStore will use this to identify TIME pv's
00068  *  from the same event. For multiple pv's from the same event, it will then store the
00069  *  one with the most recent stamp.
00070  *
00071  *  This software was developed for the LCLS project.  If you use all or 
00072  *  part of it, please give an appropriate acknowledgment.
00073  *
00074  *  @see Env
00075  *
00076  *  @version \$Id: EpicsStore.h 8341 2014-06-05 21:10:27Z davidsch@SLAC.STANFORD.EDU $
00077  *
00078  *  @author Andrei Salnikov
00079  */
00080 
00081 class EpicsStore : public boost::enable_shared_from_this<EpicsStore>, boost::noncopyable {
00082 public:
00083 
00084   /**
00085    *  Helper class which converts the result of EpicsStore::getPV() call into
00086    *  real data object. The object of this type can be converted to smart
00087    *  pointer to one of the Psana::Epics::EpicsPv* classes (defined in psddl_psana
00088    *  package).
00089    */
00090   struct EpicsPV {
00091     
00092     // conversion operators
00093     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlHeader>() {
00094       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlHeader>(m_name);
00095     }
00096     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlString>() {
00097       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlString>(m_name);
00098     }
00099     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlShort>() {
00100       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlShort>(m_name);
00101     }
00102     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlFloat>() {
00103       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlFloat>(m_name);
00104     }
00105     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlEnum>() {
00106       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlEnum>(m_name);
00107     }
00108     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlChar>() {
00109       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlChar>(m_name);
00110     }
00111     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlLong>() {
00112       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlLong>(m_name);
00113     }
00114     operator boost::shared_ptr<Psana::Epics::EpicsPvCtrlDouble>() {
00115       return m_impl->getCtrl<Psana::Epics::EpicsPvCtrlDouble>(m_name);
00116     }
00117 
00118     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeHeader>() {
00119       return m_impl->getTime<Psana::Epics::EpicsPvTimeHeader>(m_name);
00120     }
00121     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeString>() {
00122       return m_impl->getTime<Psana::Epics::EpicsPvTimeString>(m_name);
00123     }
00124     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeShort>() {
00125       return m_impl->getTime<Psana::Epics::EpicsPvTimeShort>(m_name);
00126     }
00127     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeFloat>() {
00128       return m_impl->getTime<Psana::Epics::EpicsPvTimeFloat>(m_name);
00129     }
00130     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeEnum>() {
00131       return m_impl->getTime<Psana::Epics::EpicsPvTimeEnum>(m_name);
00132     }
00133     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeChar>() {
00134       return m_impl->getTime<Psana::Epics::EpicsPvTimeChar>(m_name);
00135     }
00136     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeLong>() {
00137       return m_impl->getTime<Psana::Epics::EpicsPvTimeLong>(m_name);
00138     }
00139     operator boost::shared_ptr<Psana::Epics::EpicsPvTimeDouble>() {
00140       return m_impl->getTime<Psana::Epics::EpicsPvTimeDouble>(m_name);
00141     }
00142 
00143     operator boost::shared_ptr<Psana::Epics::EpicsPvHeader>() {
00144       return m_impl->getAny(m_name);
00145     }
00146     
00147     EpicsStoreImpl* m_impl;
00148     std::string m_name;
00149   };
00150   
00151   /**
00152    *  Helper class which converts the result of EpicsStore::get() call into
00153    *  real data. Objects of this type can be converted to one of the basic
00154    *  numeric types or std::string.
00155    */
00156   struct EpicsValue {
00157     
00158     // conversion operators
00159     operator int() { return m_impl->getValue<int>(m_name, m_idx); }
00160     operator unsigned() { return m_impl->getValue<unsigned>(m_name, m_idx); }
00161     operator short() { return m_impl->getValue<short>(m_name, m_idx); }
00162     operator unsigned short() { return m_impl->getValue<unsigned short>(m_name, m_idx); }
00163     operator long() { return m_impl->getValue<long>(m_name, m_idx); }
00164     operator unsigned long() { return m_impl->getValue<unsigned long>(m_name, m_idx); }
00165     operator long long() { return m_impl->getValue<long long>(m_name, m_idx); }
00166     operator unsigned long long() { return m_impl->getValue<unsigned long long>(m_name, m_idx); }
00167     operator char() { return m_impl->getValue<char>(m_name, m_idx); }
00168     operator signed char() { return m_impl->getValue<signed char>(m_name, m_idx); }
00169     operator unsigned char() { return m_impl->getValue<unsigned char>(m_name, m_idx); }
00170     operator float() { return m_impl->getValue<float>(m_name, m_idx); }
00171     operator double() { return m_impl->getValue<double>(m_name, m_idx); }
00172     operator std::string() { return m_impl->getValue<std::string>(m_name, m_idx); }
00173     
00174     EpicsStoreImpl* m_impl;
00175     std::string m_name;
00176     int m_idx;
00177   };
00178   
00179   // Default constructor
00180   EpicsStore () ;
00181 
00182   // Destructor
00183   ~EpicsStore () ;
00184 
00185   /**
00186    *  @brief Store EPICS PV
00187    *
00188    *  storing a pv first requires identifying the pvName. If this is not stored in the 
00189    *  pv header (as with TIME pv's), or it is not passed explicitly through the optional 
00190    *  argument pvName, then the pvName will be found using the pvid in the pv header and the 
00191    *  source. If no pvName is found (this can happen for damaged data missing configuration 
00192    *  events) one will be created based on the src and pvId in the header.
00193    *
00194    *  The optional argument eventTag can be set to a value >= 0 to identify TIME pv's from the 
00195    *  same event. When store gets a TIME pv that is from the same event as the last one stored,
00196    *  it will only update the internal store if the new pv has a stamp value > than the stamp
00197    *  of the previously stored pv. If eventTag < 0, this check of the stamp values is not made.
00198    *
00199    *  @param[in] pv        pv header
00200    *  @param[in] src       src pv
00201    *  @param[in] pvName    optional pvName, overrides use of internal mechanism to find pvName
00202    *                       based on pvid and src. Note - if passed, this should be a valid pvName 
00203    *                       consinstent with the data, not an alias.
00204    *  @param[in] eventTag  optional key for grouping TIME pv's from the same event.
00205    *                       If eventTag >=0, it is treated as such a key. Can be a simple counter 
00206    *                       for identifying events - not related to the EventId of a psana Event.
00207    */
00208   void store(const boost::shared_ptr<Psana::Epics::EpicsPvHeader>& pv, const Pds::Src& src, 
00209              const std::string *pvName = NULL, long eventTag = -1) {
00210     m_impl->store(pv, src, pvName, eventTag);
00211   }
00212 
00213   /// Store alias name for EPICS PV.
00214   void storeAlias(const Pds::Src& src, int pvId, const std::string& alias) {
00215     m_impl->storeAlias(src, pvId, alias);
00216   }
00217 
00218   /**
00219    *  @brief  Get the full list of PV names and aliases.
00220    *
00221    *  Returned list includes the names of all PVs and aliases.
00222    */
00223   std::vector<std::string> names() const
00224   {
00225     std::vector<std::string> names;
00226     m_impl->names(names);
00227     return names;
00228   }
00229 
00230   /**
00231    *  @brief  Get the list of PV names.
00232    *
00233    *  Returned list includes the names of all PVs but no alias names.
00234    */
00235   std::vector<std::string> pvNames() const 
00236   {
00237     std::vector<std::string> names;
00238     m_impl->pvNames(names);
00239     return names;
00240   }
00241 
00242   /**
00243    *  @brief  Get the list of PV aliases.
00244    *
00245    *  Returned list includes the names of all alias names but no PV names.
00246    */
00247   std::vector<std::string> aliases() const
00248   {
00249     std::vector<std::string> names;
00250     m_impl->aliases(names);
00251     return names;
00252   }
00253 
00254   /**
00255    *  @brief  Get alias name for specified PV name.
00256    *
00257    *  If specified PV is not found or does not have an alias an empty string is returned.
00258    */
00259   std::string alias(const std::string& pv) const
00260   {
00261     return m_impl->alias(pv);
00262   }
00263 
00264   /**
00265    *  @brief  Get PV name for specified alias name.
00266    *
00267    *  If specified alias is not found an empty string is returned.
00268    */
00269   std::string pvName(const std::string& alias) const
00270   {
00271     return m_impl->pvName(alias);
00272   }
00273 
00274   /**
00275    *   @brief Get the value for a given PV or alias name.
00276    *   
00277    *   @param[in] name      PV name
00278    *   @param[in] idx       value index (for array PVs)
00279    *   @return  object that is convertible to regular numeric types or std::string.
00280    *   
00281    *   This method does not throw but conversion from EpicsValue to final 
00282    *   type can throw ExceptionEpicsName or ExceptionEpicsConversion.
00283    */
00284   EpicsValue value(const std::string& name, int idx=0) const {
00285     EpicsValue v = { m_impl.get(), name, idx };
00286     return v;
00287   }
00288   
00289   /**
00290    *   @brief Get status information for a given PV or alias name.
00291    *   
00292    *   @param[in] name      PV name
00293    *   @param[out] status   EPICS status value
00294    *   @param[out] severity EPICS severity value
00295    *   @param[out] time     Time of the last change, can be (0) if time is unknown
00296    *   
00297    *   @throw ExceptionEpicsName  if the name of the PV is not known
00298    */
00299   void status(const std::string& name, int& status, int& severity, PSTime::Time& time) const {
00300     m_impl->getStatus(name, status, severity, time);
00301   }
00302   
00303   /** 
00304    *  @brief Find EPICS PV given its PV or alias name.
00305    *  
00306    *  @param[in] name      PV name
00307    *  @return  Object convertible to shared_ptr<T> where T is one of the epics PV classes.
00308    *   
00309    */
00310   EpicsPV getPV(const std::string& name) const {
00311     EpicsPV pv = { m_impl.get(), name };
00312     return pv;
00313   }
00314   
00315   /**
00316    *  @brief Access implementation object.
00317    *
00318    *  Do not use this method unless you know what you are doing. This is not
00319    *  supposed to be used by end clients, but may be useful for other services
00320    *  like Python wrappers. The name is intentionally long to make you very
00321    *  uncomfortable using it.
00322    */
00323   const EpicsStoreImpl& internal_implementation() const { return *m_impl; }
00324 
00325 protected:
00326 
00327 private:
00328 
00329   // Data members
00330   boost::scoped_ptr<EpicsStoreImpl> m_impl;  ///< Pointer to implementation.
00331 
00332 };
00333 
00334 } // namespace PSEnv
00335 
00336 #endif // PSENV_EPICSSTORE_H

Generated on 19 Dec 2016 for PSANAclasses by  doxygen 1.4.7