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