00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "PSEnv/EpicsStoreImpl.h"
00017
00018
00019
00020
00021 #include <sstream>
00022 #include <boost/lexical_cast.hpp>
00023
00024
00025
00026
00027 #include "MsgLogger/MsgLogger.h"
00028
00029
00030
00031
00032
00033 namespace {
00034
00035 const char* logger = "EpicsStore";
00036
00037
00038 unsigned sec_1970_to_1990 = (20*365 + 5)*24*3600;
00039
00040 std::string pvId2str(const std::tr1::tuple<uint32_t, uint32_t, int> &pvId) {
00041 std::stringstream o;
00042 o << "src.log=0x" << std::hex << std::tr1::get<0>(pvId)
00043 << " src.phy=0x" << std::hex << std::tr1::get<1>(pvId)
00044 << " pvId=" << std::dec << std::tr1::get<2>(pvId);
00045 return o.str();
00046 }
00047
00048
00049 }
00050
00051
00052
00053
00054
00055 namespace PSEnv {
00056
00057
00058
00059
00060 EpicsStoreImpl::EpicsStoreImpl ()
00061 : m_id2name()
00062 , m_name2id()
00063 , m_id2alias()
00064 , m_alias2id()
00065 , m_ctrlMap()
00066 , m_timeMap()
00067 {
00068 }
00069
00070
00071
00072
00073 EpicsStoreImpl::~EpicsStoreImpl ()
00074 {
00075 }
00076
00077
00078 void
00079 EpicsStoreImpl::store(const boost::shared_ptr<Psana::Epics::EpicsPvHeader>& pv, const Pds::Src& src,
00080 const std::string *pvName, long eventTag)
00081 {
00082 PvId pvid(src.log(), src.phy(), pv->pvId());
00083
00084 if (pv->isTime()) {
00085
00086
00087 std::string name;
00088 if (pvName != NULL) {
00089 name = *pvName;
00090 MsgLog(logger, debug, "EpicsStore::store - storing TIME PV with passed in name=" << *pvName);
00091 } else {
00092 ID2Name::const_iterator it = m_id2name.find(pvid);
00093 if (it != m_id2name.end()) {
00094 name = it->second;
00095 } else {
00096 name = "PV:pvId=" + boost::lexical_cast<std::string>(pv->pvId()) +
00097 ":src_log=" + boost::lexical_cast<std::string>(src.log()) +
00098 ":src_phy=" + boost::lexical_cast<std::string>(src.phy());
00099 m_id2name.insert(std::make_pair(pvid, name));
00100 m_name2id.insert(std::make_pair(name, pvid));
00101 MsgLog(logger, warning, "EpicsStore::store - no name found. Created fictional name: " << name);
00102 }
00103 MsgLog(logger, debug, "EpicsStore::store - storing TIME PV with id=" << pv->pvId());
00104 }
00105 boost::shared_ptr<Psana::Epics::EpicsPvTimeHeader> tpv =
00106 boost::static_pointer_cast<Psana::Epics::EpicsPvTimeHeader>(pv);
00107 bool updatePv = true;
00108 bool eventTagSpecified = eventTag >= 0;
00109 if (eventTagSpecified) {
00110 TimeMap::iterator pos = m_timeMap.find(name);
00111 if (pos != m_timeMap.end()) {
00112 TimeHeaderAndEventTag &storedTimeHeaderAndEventTag = pos->second;
00113 long storedEventTag = storedTimeHeaderAndEventTag.eventTag;
00114 if (storedEventTag == eventTag) {
00115
00116 boost::shared_ptr<Psana::Epics::EpicsPvTimeHeader> storedTimePV = storedTimeHeaderAndEventTag.pv;
00117 const Psana::Epics::epicsTimeStamp storedStamp = storedTimePV->stamp();
00118 const Psana::Epics::epicsTimeStamp currentStamp = tpv->stamp();
00119 bool currentPvIsOlderThanStoredPv = ((currentStamp.sec() < storedStamp.sec()) or
00120 ((currentStamp.sec() == storedStamp.sec()) and
00121 (currentStamp.nsec() < storedStamp.nsec())));
00122 if (currentPvIsOlderThanStoredPv) {
00123 updatePv = false;
00124 }
00125 }
00126 }
00127 }
00128 if (updatePv) {
00129 m_timeMap[name] = TimeHeaderAndEventTag(tpv,eventTag);
00130 }
00131
00132 } else if (pv->isCtrl()) {
00133
00134 MsgLog(logger, debug, "EpicsStore::store - storing CTRL PV with id=" << pv->pvId());
00135 boost::shared_ptr<Psana::Epics::EpicsPvCtrlHeader> ctrl =
00136 boost::static_pointer_cast<Psana::Epics::EpicsPvCtrlHeader>(pv);
00137 std::string name = ctrl->pvName();
00138 Name2ID::iterator matchingAliasPos = m_alias2id.find(name);
00139 bool aliasNameFoundThatIsThisPvName = (matchingAliasPos != m_alias2id.end());
00140 if ( aliasNameFoundThatIsThisPvName ) {
00141 MsgLog(logger, trace, "EpicsStore::store - alias: " << name
00142 << " is also used for a pvName. Discarding its use as an alias");
00143 PvId pvId = matchingAliasPos->second;
00144 ID2Name::iterator matchingAliasIdPos = m_id2alias.find(pvId);
00145 m_alias2id.erase(matchingAliasPos);
00146 if (matchingAliasIdPos != m_id2alias.end()) {
00147 m_id2alias.erase(matchingAliasIdPos);
00148 } else {
00149 MsgLog(logger,debug, "EpicsStore::store - while removing alias " << name
00150 << " could not find it's pvId: " << ::pvId2str(pvId)
00151 << " in the id2alias map. Unexpected");
00152 }
00153 }
00154
00155 m_id2name.insert(std::make_pair(pvid, name));
00156 m_name2id.insert(std::make_pair(name, pvid));
00157 m_ctrlMap[name] = ctrl;
00158
00159 } else {
00160
00161 MsgLog(logger, warning, "EpicsStore::store - unexpected PV type: ID=" << pv->pvId() << " type=" << pv->dbrType());
00162
00163 }
00164 }
00165
00166
00167
00168 void
00169 EpicsStoreImpl::storeAlias(const Pds::Src& src, int pvId, const std::string& alias)
00170 {
00171 bool aliasIsAlsoPvName = m_name2id.find(alias) != m_name2id.end();
00172 if (aliasIsAlsoPvName) {
00173 MsgLog(logger, trace, "EpicsStore::storeAlias - alias: " << alias
00174 << " is also used for a pvName. Discarding its use as an alias");
00175 return;
00176 }
00177 PvId pvid(src.log(), src.phy(), pvId);
00178 ID2Name::iterator pvIdPos = m_id2alias.find(pvid);
00179 bool pvIdAlreadStored = (pvIdPos != m_id2alias.end());
00180 if (pvIdAlreadStored) {
00181 const std::string &previousAlias = pvIdPos->second;
00182 if (previousAlias != alias) {
00183 MsgLog(logger,trace,"EpicsStore::storeAlias - pvId " << ::pvId2str(pvid)
00184 << " has already been used with alias: " << previousAlias
00185 << ". Attempt to store new alias: " << alias
00186 << ". The new alias will not be stored.");
00187 }
00188 return;
00189 }
00190 m_alias2id[alias] = pvid;
00191 m_id2alias[pvid] = alias;
00192 }
00193
00194
00195
00196 void
00197 EpicsStoreImpl::names(std::vector<std::string>& names) const
00198 {
00199 names.clear();
00200 names.reserve(m_name2id.size() + m_alias2id.size());
00201 for (Name2ID::const_iterator it = m_name2id.begin(); it != m_name2id.end(); ++ it) {
00202 names.push_back(it->first);
00203 }
00204 for (Name2ID::const_iterator it = m_alias2id.begin(); it != m_alias2id.end(); ++ it) {
00205 names.push_back(it->first);
00206 }
00207
00208 for (TimeMap::const_iterator it = m_timeMap.begin(); it != m_timeMap.end(); ++ it) {
00209 bool nameAlreadyAdded = (m_name2id.find(it->first) != m_name2id.end());
00210 if (not nameAlreadyAdded) {
00211 names.push_back(it->first);
00212 }
00213 }
00214 }
00215
00216
00217 void
00218 EpicsStoreImpl::pvNames(std::vector<std::string>& names) const
00219 {
00220 names.clear();
00221 names.reserve(m_name2id.size());
00222 for (Name2ID::const_iterator it = m_name2id.begin(); it != m_name2id.end(); ++ it) {
00223 names.push_back(it->first);
00224 }
00225
00226 for (TimeMap::const_iterator it = m_timeMap.begin(); it != m_timeMap.end(); ++ it) {
00227 bool nameAlreadyAdded = (m_name2id.find(it->first) != m_name2id.end());
00228 if (not nameAlreadyAdded) {
00229 names.push_back(it->first);
00230 }
00231 }
00232 }
00233
00234
00235 void
00236 EpicsStoreImpl::aliases(std::vector<std::string>& names) const
00237 {
00238 names.clear();
00239 names.reserve(m_alias2id.size());
00240 for (Name2ID::const_iterator it = m_alias2id.begin(); it != m_alias2id.end(); ++ it) {
00241 names.push_back(it->first);
00242 }
00243 }
00244
00245
00246 std::string
00247 EpicsStoreImpl::alias(const std::string& pv) const
00248 {
00249 std::string name;
00250
00251 Name2ID::const_iterator it = m_name2id.find(pv);
00252 if (it != m_name2id.end()) {
00253 ID2Name::const_iterator ait = m_id2alias.find(it->second);
00254 if (ait != m_id2alias.end()) name = ait->second;
00255 }
00256
00257 return name;
00258 }
00259
00260
00261 std::string
00262 EpicsStoreImpl::pvName(const std::string& alias) const
00263 {
00264 std::string name;
00265
00266 Name2ID::const_iterator ait = m_alias2id.find(alias);
00267 if (ait != m_alias2id.end()) {
00268 ID2Name::const_iterator it = m_id2name.find(ait->second);
00269 if (it != m_id2name.end()) name = it->second;
00270 }
00271
00272 return name;
00273 }
00274
00275
00276
00277 boost::shared_ptr<Psana::Epics::EpicsPvHeader>
00278 EpicsStoreImpl::getAny(const std::string& name) const
00279 {
00280
00281 std::string pvName = this->pvName(name);
00282 if (pvName.empty()) pvName = name;
00283
00284
00285 TimeMap::const_iterator time_it = m_timeMap.find(pvName);
00286 if (time_it != m_timeMap.end()) return (time_it->second).pv;
00287
00288
00289 CrtlMap::const_iterator ctrl_it = m_ctrlMap.find(pvName);
00290 if (ctrl_it != m_ctrlMap.end()) return ctrl_it->second;
00291
00292 return boost::shared_ptr<Psana::Epics::EpicsPvHeader>();
00293 }
00294
00295
00296
00297 void
00298 EpicsStoreImpl::getStatus(const std::string& name, int& status, int& severity, PSTime::Time& time) const
00299 {
00300
00301 std::string pvName = this->pvName(name);
00302 if (pvName.empty()) pvName = name;
00303
00304
00305 TimeMap::const_iterator time_it = m_timeMap.find(pvName);
00306 if (time_it != m_timeMap.end()) {
00307 Psana::Epics::EpicsPvTimeHeader* tpv = (time_it->second).pv.get();
00308 status = tpv->status();
00309 severity = tpv->severity();
00310 const Psana::Epics::epicsTimeStamp& stamp = tpv->stamp();
00311 time = PSTime::Time(stamp.sec()+sec_1970_to_1990, stamp.nsec());
00312 return;
00313 }
00314
00315
00316 CrtlMap::const_iterator ctrl_it = m_ctrlMap.find(pvName);
00317 if (ctrl_it != m_ctrlMap.end()) {
00318 Psana::Epics::EpicsPvCtrlHeader* cpv = ctrl_it->second.get();
00319 status = cpv->status();
00320 severity = cpv->severity();
00321 time = PSTime::Time();
00322 return;
00323 }
00324
00325
00326 throw ExceptionEpicsName(ERR_LOC, name);
00327 }
00328
00329
00330 boost::shared_ptr<Psana::Epics::EpicsPvCtrlHeader>
00331 EpicsStoreImpl::getCtrlImpl(const std::string& name) const
00332 {
00333
00334 std::string pvName = this->pvName(name);
00335 if (pvName.empty()) pvName = name;
00336
00337 CrtlMap::const_iterator pvit = m_ctrlMap.find(pvName);
00338 if (pvit == m_ctrlMap.end()) return boost::shared_ptr<Psana::Epics::EpicsPvCtrlHeader>();
00339 return pvit->second;
00340 }
00341
00342
00343 boost::shared_ptr<Psana::Epics::EpicsPvTimeHeader>
00344 EpicsStoreImpl::getTimeImpl(const std::string& name) const
00345 {
00346
00347 std::string pvName = this->pvName(name);
00348 if (pvName.empty()) pvName = name;
00349
00350 TimeMap::const_iterator pvit = m_timeMap.find(pvName);
00351 if (pvit == m_timeMap.end()) return boost::shared_ptr<Psana::Epics::EpicsPvTimeHeader>();
00352 return (pvit->second).pv;
00353 }
00354
00355
00356
00357 EpicsStoreImpl::TimeHeaderAndEventTag EpicsStoreImpl::getTimeAndEventTag(const std::string& name) const
00358 {
00359
00360 std::string pvName = this->pvName(name);
00361 if (pvName.empty()) pvName = name;
00362
00363 TimeMap::const_iterator pvit = m_timeMap.find(pvName);
00364 if (pvit == m_timeMap.end()) return TimeHeaderAndEventTag();
00365 return pvit->second;
00366 }
00367
00368 }