diff --git a/include/DoocsProcessArray.h b/include/DoocsProcessArray.h index 97d57a7814840bb2465d380aeedd3cadb3ff7bb3..b73c4d0e9bcd53b15526070b59d6a21b35a14f75 100644 --- a/include/DoocsProcessArray.h +++ b/include/DoocsProcessArray.h @@ -155,23 +155,25 @@ namespace ChimeraTK { this->fill_array(dataPtr, processVector.size()); modified = true; - // Convert time stamp from version number in Unix time (seconds and microseconds). - // Note that epoch of std::chrono::system_time might be different from Unix time, and Unix time omits leap seconds - // and hence is not the duration since the epoch! We have to convert to time_t and then find out the microseconds. - auto timestamp = _processArray->getVersionNumber().getTime(); - auto seconds = std::chrono::system_clock::to_time_t(timestamp); - auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>( - timestamp - std::chrono::system_clock::from_time_t(seconds)) - .count(); - this->set_tmstmp(seconds, microseconds); + // Convert time stamp from version number to DOOCS timestamp + doocs::Timestamp timestamp(_processArray->getVersionNumber().getTime()); + + // Make sure we never send out two absolute identical time stamps. If we would do so, the "watchdog" which + // corrects inconsistencies in ZeroMQ subscriptions between sender and subcriber cannot detect the inconsistency. + if(this->get_timestamp() == timestamp) { + timestamp += std::chrono::microseconds(1); + } + + this->set_timestamp(timestamp); if(_macroPulseNumberSource) this->set_mpnum(_macroPulseNumberSource->accessData(0)); // send data via ZeroMQ if enabled and if DOOCS initialisation is complete if(publishZMQ && ChimeraTK::DoocsAdapter::isInitialised) { dmsg_info info; memset(&info, 0, sizeof(info)); - info.sec = seconds; - info.usec = microseconds; + auto sinceEpoch = timestamp.get_seconds_and_microseconds_since_epoch(); + info.sec = sinceEpoch.seconds; + info.usec = sinceEpoch.microseconds; if(_macroPulseNumberSource != nullptr) { info.ident = _macroPulseNumberSource->accessData(0); } diff --git a/include/DoocsProcessScalar.h b/include/DoocsProcessScalar.h index bbfadeb7a4a238e85421cf95bdb9f83af581ac11..a79f8137dde72d931d83bc75bfdaf1fce754a542 100644 --- a/include/DoocsProcessScalar.h +++ b/include/DoocsProcessScalar.h @@ -61,13 +61,14 @@ namespace ChimeraTK { this->d_error(no_error); } - // Convert time stamp from version number in Unix time (seconds and microseconds). - // Note that epoch of std::chrono::system_time might be different from Unix time, and Unix time omits leap seconds - // and hence is not the duration since the epoch! We have to convert to time_t and then find out the microseconds. + // Convert time stamp from version number to DOOCS timestamp doocs::Timestamp timestamp(_processScalar->getVersionNumber().getTime()); - auto sinceEpoch = timestamp.get_seconds_and_microseconds_since_epoch(); - auto seconds = sinceEpoch.seconds; - auto microseconds = sinceEpoch.microseconds; + + // Make sure we never send out two absolute identical time stamps. If we would do so, the "watchdog" which + // corrects inconsistencies in ZeroMQ subscriptions between sender and subcriber cannot detect the inconsistency. + if(this->get_timestamp() == timestamp) { + timestamp += std::chrono::microseconds(1); + } // update global time stamp of DOOCS, but only if our time stamp is newer if(get_global_timestamp() < timestamp) { @@ -94,15 +95,16 @@ namespace ChimeraTK { // We must set the timestamp again so it is correctly attached to the variable. set_and_archive does not to it. // This must happen after set_and_archive, otherwise the global time stamp is taken. - this->set_tmstmp(seconds, microseconds); + this->set_timestamp(timestamp); if(_macroPulseNumberSource) this->set_mpnum(_macroPulseNumberSource->accessData(0)); // send data via ZeroMQ if enabled and if DOOCS initialisation is complete if(_publishZMQ && ChimeraTK::DoocsAdapter::isInitialised) { dmsg_info info; memset(&info, 0, sizeof(info)); - info.sec = seconds; - info.usec = microseconds; + auto sinceEpoch = timestamp.get_seconds_and_microseconds_since_epoch(); + info.sec = sinceEpoch.seconds; + info.usec = sinceEpoch.microseconds; if(_macroPulseNumberSource != nullptr) { info.ident = _macroPulseNumberSource->accessData(0); } diff --git a/src/DoocsIfff.cc b/src/DoocsIfff.cc index 2feec99c2b9a822797affd0e3e4c3eb95ce7fd65..fd2869791ec6e34c09275a52eeaf76024d98b4a7 100644 --- a/src/DoocsIfff.cc +++ b/src/DoocsIfff.cc @@ -87,6 +87,12 @@ namespace ChimeraTK { doocs::Timestamp timestamp(_i1Value->getVersionNumber().getTime()); + // Make sure we never send out two absolute identical time stamps. If we would do so, the "watchdog" which + // corrects inconsistencies in ZeroMQ subscriptions between sender and subcriber cannot detect the inconsistency. + if(this->get_timestamp() == timestamp) { + timestamp += std::chrono::microseconds(1); + } + // update global time stamp of DOOCS, but only if our time stamp is newer if(get_global_timestamp() < timestamp) { set_global_timestamp(timestamp); diff --git a/src/DoocsSpectrum.cc b/src/DoocsSpectrum.cc index f7b42197afd54e1212a703b2aac4734a506fe4ff..b0181fff54adb6ab69bf7da1dfbcfdcf250c3743 100644 --- a/src/DoocsSpectrum.cc +++ b/src/DoocsSpectrum.cc @@ -148,14 +148,18 @@ namespace ChimeraTK { } _doocsSuccessfullyUpdated = true; - // Convert time stamp from version number in Unix time (seconds and microseconds). - // Note that epoch of std::chrono::system_time might be different from Unix time, and Unix time omits leap seconds - // and hence is not the duration since the epoch! We have to convert to time_t and then find out the microseconds. - auto timestamp = _processArray->getVersionNumber().getTime(); - auto seconds = std::chrono::system_clock::to_time_t(timestamp); - auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>( - timestamp - std::chrono::system_clock::from_time_t(seconds)) - .count(); + // Convert time stamp from version number to DOOCS timestamp + doocs::Timestamp timestamp(_processArray->getVersionNumber().getTime()); + + // Make sure we never send out two absolute identical time stamps. If we would do so, the "watchdog" which + // corrects inconsistencies in ZeroMQ subscriptions between sender and subcriber cannot detect the inconsistency. + if(this->get_timestamp() == timestamp) { + timestamp += std::chrono::microseconds(1); + } + + auto sinceEpoch = timestamp.get_seconds_and_microseconds_since_epoch(); + auto seconds = sinceEpoch.seconds; + auto microseconds = sinceEpoch.microseconds; // set macro pulse number, buffer number and time stamp size_t ibuf = 0;