84 const std::string& updateCache,
const std::string& dataConsistencyRealmName)
86 if(cacheFileExists() && isCachingEnabled()) {
89 _catalogueFromCache =
true;
92 if(updateCache ==
"1") {
93 std::thread(fetchCatalogue, serverAddress, cacheFile, _cancelFlag.get_future()).detach();
99 std::async(std::launch::async, fetchCatalogue, serverAddress, cacheFile, _cancelFlag.get_future());
105 doocs::zmq_set_subscription_timeout(10);
107 _dataConsistencyRealm = async::DataConsistencyRealmStore::getInstance().getRealm(dataConsistencyRealmName);
145 std::string address, std::map<std::string, std::string> parameters) {
147 if(address.empty()) {
148 RegisterPath serverAddress;
149 serverAddress /= parameters[
"facility"];
150 serverAddress /= parameters[
"device"];
151 serverAddress /= parameters[
"location"];
152 address = std::string(serverAddress).substr(1);
154 std::string cacheFile{};
155 std::string updateCache{
"0"};
157 cacheFile = parameters.at(
"cacheFile");
158 updateCache = parameters.at(
"updateCache");
160 catch(std::out_of_range&) {
165 std::string dataConsistencyRealmName{
"doocsEventId"};
166 if(parameters.find(
"dataConsistencyRealmName") != parameters.end()) {
167 dataConsistencyRealmName = parameters.at(
"dataConsistencyRealmName");
171 return boost::shared_ptr<DeviceBackend>(
172 new DoocsBackend(address, cacheFile, updateCache, dataConsistencyRealmName));
178 std::unique_lock<std::mutex> lk(_mxRecovery);
179 if(lastFailedAddress !=
"") {
182 std::string storedExceptionMessage;
183 if(!isFunctional()) {
184 storedExceptionMessage = getActiveExceptionMessage();
188 ea.adr(lastFailedAddress);
190 doocs::EqData src, dst;
191 int rc = eq.get(&ea, &src, &dst);
193 if(rc == doocs::TransactionResult::transaction_error || rc == doocs::TransactionResult::transport_error) {
197 auto message = storedExceptionMessage.empty() || storedExceptionMessage ==
"(exception cleared)" ?
198 std::format(
"Cannot read from DOOCS property '{}': {}", lastFailedAddress, dst.get_string()) :
199 storedExceptionMessage;
200 setException(message);
201 throw ChimeraTK::runtime_error(message);
203 lastFailedAddress =
"";
206 setOpenedAndClearException();
210 if(!_catalogueFromCache && !_catalogueFuture.valid() && !catalogue.
isComplete()) {
211 _cancelFlag = std::promise<void>{};
213 std::async(std::launch::async, fetchCatalogue,
_serverAddress, _cacheFile, _cancelFlag.get_future());
287 const RegisterPath& registerPathName,
size_t numberOfWords,
size_t wordOffsetInRegister, AccessModeFlags flags) {
288 boost::shared_ptr<NDRegisterAccessor<UserType>> p;
292 bool hasExtraLevel =
false;
293 if(!boost::starts_with(path,
"doocs://") && !boost::starts_with(path,
"epics://")) {
294 size_t nSlashes = std::count(path.begin(), path.end(),
'/');
296 hasExtraLevel =
true;
298 else if(nSlashes < 3 || nSlashes > 4) {
299 throw ChimeraTK::logic_error(std::string(
"DOOCS address has an illegal format: ") + path);
302 else if(boost::starts_with(path,
"doocs://")) {
303 size_t nSlashes = std::count(path.begin(), path.end(),
'/');
305 if(nSlashes == 4 + 3) {
306 hasExtraLevel =
true;
308 else if(nSlashes < 3 + 3 || nSlashes > 4 + 3) {
309 throw ChimeraTK::logic_error(std::string(
"DOOCS address has an illegal format: ") + path);
316 field = path.substr(path.find_last_of(
'/') + 1);
317 path = path.substr(0, path.find_last_of(
'/'));
321 int doocsTypeId = DATA_NULL;
325 doocs::EqData src, dst;
327 int rc = eq.get(&ea, &src, &dst);
329 doocsTypeId = dst.type();
334 if(doocsTypeId == DATA_NULL) {
336 doocsTypeId = reg.doocsTypeId;
340 bool extraLevelUsed =
false;
341 auto sharedThis = boost::static_pointer_cast<DoocsBackend>(shared_from_this());
343 if(field ==
"eventId") {
344 extraLevelUsed =
true;
347 else if(field ==
"timeStamp") {
348 extraLevelUsed =
true;
352 switch(doocsTypeId) {
374 sharedThis, path, registerPathName, numberOfWords, wordOffsetInRegister, flags));
379 sharedThis, path, registerPathName, numberOfWords, wordOffsetInRegister, flags));
384 throw ChimeraTK::logic_error(
"DOOCS property of IFFF type '" +
_serverAddress + registerPathName +
385 "' cannot be accessed as a whole.");
387 extraLevelUsed =
true;
389 sharedThis, path, field, registerPathName, numberOfWords, wordOffsetInRegister, flags));
395 sharedThis, path, registerPathName, numberOfWords, wordOffsetInRegister, flags));
400 sharedThis, path, registerPathName, numberOfWords, wordOffsetInRegister, flags);
401 if constexpr(std::is_same_v<UserType, std::uint8_t>) {
405 boost::shared_ptr<NDRegisterAccessor<std::uint8_t>> pImpl(accImpl);
407 boost::shared_ptr<NDRegisterAccessor<UserType>> accDecorated(
408 new TypeChangingRangeCheckingDecorator<UserType, std::uint8_t>(
409 boost::dynamic_pointer_cast<ChimeraTK::NDRegisterAccessor<std::uint8_t>>(pImpl)));
416 throw ChimeraTK::logic_error(
"Unsupported DOOCS data type " +
417 std::string(doocs::EqData().type_string(doocsTypeId)) +
" of property '" +
_serverAddress +
418 registerPathName +
"'");
423 if(hasExtraLevel && !extraLevelUsed) {
424 throw ChimeraTK::logic_error(
"Specifiaction of field name is not supported for the DOOCS data type " +
425 std::string(doocs::EqData().type_string(doocsTypeId)) +
": " +
_serverAddress + registerPathName);
428 p->setExceptionBackend(shared_from_this());