ChimeraTK-DeviceAccess-DoocsBackend  01.09.02
CatalogueFetcher.cc
Go to the documentation of this file.
1 #include "CatalogueFetcher.h"
2 
3 #include "ChimeraTK/MappedImage.h"
4 #include "DoocsBackend.h"
5 #include "RegisterInfo.h"
6 #include "StringUtility.h"
7 #include <doocs/EqCall.h>
8 
9 const std::vector<std::string> IGNORE_PATTERNS = {".HIST", ".FILT", "._FILT", ".EGU", ".DESC", ".HSTAT", "._HSTAT",
10  "._HIST", ".LIST", ".SAVE", ".COMMENT", ".XEGU", ".POLYPARA", "MESSAGE.TICKER"};
11 
12 /********************************************************************************************************************/
13 
14 std::pair<DoocsBackendRegisterCatalogue, bool> CatalogueFetcher::fetch() {
15  auto nSlashes = detail::slashes(serverAddress_);
16 
17  fillCatalogue(serverAddress_, nSlashes);
18 
19  bool isCatalogueComplete = not(isCancelled() || locationLookupError_ || catalogue_.getNumberOfRegisters() == 0);
20 
21  return {std::move(catalogue_), isCatalogueComplete};
22 }
23 
24 /********************************************************************************************************************/
25 
26 void CatalogueFetcher::fillCatalogue(std::string fixedComponents, long level) {
27  // obtain list of elements within the given partial address
28  doocs::EqAdr ea;
29  doocs::EqCall eq;
30  doocs::EqData src, propList;
31  ea.adr(fixedComponents + "/*");
32  int rc = eq.names(&ea, &propList);
33  if(rc) {
34  // if the enumeration failes, maybe the server is not available (but
35  // exists in ENS) -> just ignore this address but warn
36  std::cout << "DoocsBackend::CatalogueFetcher: Failed to query names for " + fixedComponents
37  << ": \"" + propList.get_string() + "\"" << std::endl;
38 
39  locationLookupError_ = true;
40  return;
41  }
42 
43  // iterate over list
44 
45  for(int i = 0; i < propList.array_length() && (isCancelled() == false); ++i) {
46  // obtain the name of the element
47  auto u = propList.get_ustr(i);
48  std::string name(u->str_data.str_data_val);
49  name = name.substr(0, name.find_first_of(" ")); // ignore comment which is following the space
50 
51  // if we are not yet at the property-level, recursivly call the function
52  // again to resolve the next hierarchy level
53  if(level < 2) {
54  fillCatalogue(fixedComponents + "/" + name, level + 1);
55  }
56  else { // this is a property: create RegisterInfo entry and set its name
57 
58  // It matches one of DOOCS's internal properties; skip
59  if(detail::endsWith(name, IGNORE_PATTERNS).first) {
60  continue;
61  }
62 
63  // read property once to determine its length and data type
65  std::string fqn = fixedComponents + "/" + name;
66  doocs::EqData dst;
67  ea.adr(fqn); // strip leading slash
68  rc = eq.get(&ea, &src, &dst);
69  if((rc && ChimeraTK::DoocsBackend::isCommunicationError(dst.error())) || dst.error() == eq_errors::device_error) {
70  // if the property is not accessible, ignore it. This happens frequently e.g. for archiver-related properties.
71  // device_error seems to be reported permanently by some x2timer properties, so exclude them, too.
72  continue;
73  }
74  else if(rc && dst.error()) {
75  // If error has been set, the shape information is not correct (because DOOCS seems to store a string instead).
76  // Until a better solution has been found, the entire catalogue fetching is marked as errornous to prevent
77  // saving it to the cache file.
78  std::cout << "DoocsBackend::CatalogueFetcher: Failed to query shape information for " + fqn
79  << ": \"" + dst.get_string() + "\" (" + std::to_string(dst.error()) + ")" << std::endl;
80  locationLookupError_ = true;
81  continue;
82  }
83 
84  auto regPath = fqn.substr(std::string(serverAddress_).length());
85  auto length = dst.array_length();
86  auto doocsTypeId = dst.type();
87 
88  ChimeraTK::AccessModeFlags flags{};
89  if(checkZmqAvailability(fqn)) {
90  flags.add(ChimeraTK::AccessMode::wait_for_new_data);
91  }
92  if(doocsTypeId == DATA_IMAGE) {
93  // length of the byte string (body part, no header) is reported by DOOCS.
94  // We must add our header length.
95  length += sizeof(ChimeraTK::ImgHeader);
96  }
97  catalogue_.addProperty(regPath, length, doocsTypeId, flags);
98  }
99  }
100 }
101 
102 /********************************************************************************************************************/
103 
104 bool CatalogueFetcher::checkZmqAvailability(const std::string& fullQualifiedName) const {
105  auto lastSlash = fullQualifiedName.find_last_of('/');
106  assert(lastSlash != std::string::npos && lastSlash > 0);
107  auto fullLocationPath = fullQualifiedName.substr(0, lastSlash);
108  auto propertyName = fullQualifiedName.substr(lastSlash + 1);
109 
110  int rc;
111  float f1;
112  float f2;
113  char* sp;
114  time_t tm;
115  doocs::EqAdr ea;
116  doocs::EqData dat;
117  doocs::EqData dst;
118  doocs::EqCall eq;
119  int portp;
120 
121  ea.adr(fullLocationPath + "/SPN");
122 
123  // get channel port number
124  dat.set(1, 0.0f, 0.0f, time_t{0}, propertyName, 0);
125 
126  // call get () to see whether it is supported
127  rc = eq.get(&ea, &dat, &dst);
128  if(rc) {
129  return false;
130  }
131 
132  rc = dst.get_ustr(&portp, &f1, &f2, &tm, &sp, 0);
133  if(rc && !portp && !static_cast<int>(f1 + f2)) rc = 0; // not supported
134 
135  if(!rc) {
136  dst.get_ustr(&portp, &f1, &f2, &tm, &sp, 0);
137  // get () not supported, call set ()
138  rc = eq.set(&ea, &dat, &dst);
139  if(rc) {
140  return false;
141  }
142  }
143 
144  if(dst.type() == DATA_INT) {
145  portp = dst.get_int();
146  }
147  else {
148  dst.get_ustr(&portp, &f1, &f2, &tm, &sp, 0);
149  }
150  return portp != 0;
151 }
152 
153 /********************************************************************************************************************/
DoocsBackendRegisterCatalogue::addProperty
void addProperty(const std::string &name, unsigned int length, int doocsType, ChimeraTK::AccessModeFlags flags)
Definition: RegisterInfo.cc:9
CatalogueFetcher.h
detail::slashes
long slashes(const std::string &s)
Definition: StringUtility.cc:20
IGNORE_PATTERNS
const std::vector< std::string > IGNORE_PATTERNS
Definition: CatalogueFetcher.cc:9
RegisterInfo.h
DoocsBackend.h
ChimeraTK::DoocsBackend::isCommunicationError
static bool isCommunicationError(int doocs_error)
Definition: DoocsBackend.cc:400
detail::endsWith
std::pair< bool, std::string > endsWith(std::string const &s, const std::vector< std::string > &patterns)
Definition: StringUtility.cc:9
StringUtility.h
CatalogueFetcher::fetch
std::pair< DoocsBackendRegisterCatalogue, bool > fetch()
Definition: CatalogueFetcher.cc:14