DUDS
Distributed Update of Data from Something
LinuxClock.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2017 Jeff Jackowski
9  */
10 #ifndef LINUXCLOCK_HPP
11 #define LINUXCLOCK_HPP
12 
15 #include <sys/timex.h>
16 #include <boost/exception/errinfo_api_function.hpp>
17 #include <boost/exception/errinfo_errno.hpp>
18 #include <errno.h>
19 
20 namespace duds { namespace hardware { namespace devices { namespace clocks {
21 
25 constexpr boost::uuids::uuid LinuxClockDeviceId = {
26  0xbf, 0x2d, 0x4a, 0x68,
27  0x62, 0xda,
28  0x45, 0x56,
29  0x8c, 0xc6,
30  0x38, 0xd1, 0xd5, 0x5b, 0x20, 0x74
31 };
32 
51 template<class SVT, class SQT, class TVT, class TQT>
53 public duds::hardware::devices::clocks::GenericClock<SVT, SQT, TVT, TQT> {
54 public:
56 private:
69  template <class Sample>
70  void setSample(Sample &dest, const timex &src,
71  const duds::data::int128_t &time
72  ) {
73  // check for an unsync'ed clock
74  if (src.status & STA_UNSYNC) {
75  // no clue if the time is right
76  dest.accuracy = dest.estError =
77  duds::data::unspecified<typename Sample::Quality>();
78  } else {
79  // provide info on the correctness of the time
81  dest.accuracy, src.maxerror);
83  dest.estError, src.esterror);
84  }
85  // additional quality data
87  dest.precision, src.precision);
88  dest.resolution = duds::data::unspecified<typename Sample::Quality>();
89  // the time
90  if (src.status & STA_NANO) {
92  dest.value, time);
93  } else {
95  dest.value, time);
96  }
97  // the origin
98  dest.origin = sens[0]->uuid();
99  }
107  static void doSample(timex &tx, duds::data::int128_t &time) {
108  // request the time
109  tx.modes = 0; // no time adjustment
110  int res = adjtimex(&tx);
111  // check for an error
112  if (res < 0) {
114  boost::errinfo_api_function("adjtimex") <<
115  boost::errinfo_errno(errno)
116  );
117  }
118  // have TAI offset?
119  if (tx.tai) {
120  // convert to TAI for a proper IST result
121  tx.time.tv_sec += tx.tai;
122  } else if (duds::time::planetary::earth) {
123  // attempt to add leap seconds from another source
124  tx.time.tv_sec += duds::time::planetary::earth->leaps.leapSeconds(
125  duds::time::interstellar::Seconds(tx.time.tv_sec)
126  ).count();
127  } // else, time is in UTC, leap seconds are unknown, so cannot make TAI
128  // compute the time; make it a single value
129  time = tx.time.tv_usec;
130  if (tx.status & STA_NANO) {
131  time += tx.time.tv_sec * std::nano::den;
132  } else {
133  time += tx.time.tv_sec * std::micro::den;
134  }
135  }
136  struct Token { };
137 public:
143  GenericClock<SVT, SQT, TVT, TQT>(LinuxClockDeviceId) { }
147  static std::shared_ptr< GenericLinuxClock <SVT, SQT, TVT, TQT> > make() {
148  return std::make_shared< GenericLinuxClock <SVT, SQT, TVT, TQT> >(Token());
149  }
150  virtual void sampleTime(typename Measurement::TimeSample &time) {
151  timex tx;
152  duds::data::int128_t total;
153  doSample(tx, total);
154  setSample(time, tx, total);
155  }
156  virtual void sample() {
157  timex tx;
158  duds::data::int128_t total;
159  std::shared_ptr<Measurement> m =
160  std::make_shared<Measurement>();
161  doSample(tx, total);
162  setSample(m->measured, tx, total);
163  // no timestamp
164  m->timestamp.clear();
165  // store the measurement
167  }
168  virtual void sample(const ClockSptr &clock) {
169  timex tx;
170  duds::data::int128_t total;
171  std::shared_ptr<Measurement> m =
172  std::make_shared<Measurement>();
173  doSample(tx, total);
174  setSample(m->measured, tx, total);
175  // if the supplied clock driver is this clock driver . . .
176  if (this == clock.get()) {
177  // use the same time
178  setSample(m->timestamp, tx, total);
179  } else if (clock) {
180  // sample the other clock
181  clock->sampleTime(m->timestamp);
182  } else {
183  // no timestamp
184  m->timestamp.clear();
185  }
186  // store the measurement
188  }
189  virtual bool unambiguous() const noexcept {
190  return true;
191  }
192 };
193 
197 typedef GenericLinuxClock<
199  double,
201  float
203 
204 typedef std::shared_ptr<LinuxClock> LinuxClockSptr;
205 
206 } } } }
207 
208 
209 #endif // #ifndef LINUXCLOCK_HPP
boost::variant< std::string, duds::general::LanguageTaggedString, std::array< std::int32_t, 4 >, std::array< std::int64_t, 2 >, duds::data::int128_w, std::array< float, 4 >, std::array< double, 2 >, double, duds::data::Quantity, boost::recursive_wrapper< duds::data::QuantityNddArray >, duds::time::interstellar::Femtoseconds, duds::time::interstellar::Nanoseconds, duds::time::interstellar::FemtoTime, duds::time::interstellar::NanoTime, boost::uuids::uuid, boost::recursive_wrapper< duds::data::GenericValueTable >, std::shared_ptr< std::vector< char > >> GenericValue
A general value of a type can be serialized for transmission over a network and can be used with a re...
void setSample(Sample &dest, const timex &src, const duds::data::int128_t &time)
Takes a partially converted time from adjtimex(), completes the conversion, and places it in the dest...
Definition: LinuxClock.hpp:70
boost::multiprecision::int128_t int128_t
The type used for 128-bit integers.
Definition: Int128.hpp:66
GenericLinuxClock< duds::data::GenericValue, double, duds::time::interstellar::NanoTime, float > LinuxClock
General use Linux clock driver type.
Definition: LinuxClock.hpp:202
std::chrono::duration< std::int64_t > Seconds
Stores a duration in seconds.
The base type for errors from clocks.
Definition: Clock.hpp:64
move_impl move(unsigned int c, unsigned int r)
Display stream manipulator that moves the display cursor to the given location.
std::vector< SensorSptr > sens
Contains Sensor objects to represent all the kinds of data this device can collect.
Definition: Device.hpp:99
virtual void sample(const ClockSptr &clock)
Samples the time from this clock and the given clock, then stores the measurement.
Definition: LinuxClock.hpp:168
Represents something with one or more sensors that are sampled through the same hardware.
Definition: Device.hpp:34
GenericSample< GenericValue, double > Sample
A sample type that is good for general purpose use.
Definition: Sample.hpp:166
virtual void sampleTime(typename Measurement::TimeSample &time)
Samples the time from the clock device without storing the result in the clock&#39;s sensor object...
Definition: LinuxClock.hpp:150
GenericLinuxClock(Token)
Constructs a new clock device with its UUID.
Definition: LinuxClock.hpp:142
std::shared_ptr< GenericClock< SVT, SQT, TVT, TQT > > ClockSptr
Definition: Clock.hpp:84
std::shared_ptr< LinuxClock > LinuxClockSptr
Definition: LinuxClock.hpp:204
Uses the Linux specific adjtimex() function to query for the time and the quailty of the time sample...
Definition: LinuxClock.hpp:52
static void doSample(timex &tx, duds::data::int128_t &time)
Samples the time by calling adjtimex() and computes the time in either microseconds or nanoseconds (w...
Definition: LinuxClock.hpp:107
static std::shared_ptr< GenericLinuxClock< SVT, SQT, TVT, TQT > > make()
Makes a new clock device object.
Definition: LinuxClock.hpp:147
The foundation to a clock driver.
Definition: Clock.hpp:78
Stores a sample of something along with a timestamp stored as a sample from a clock.
Definition: Measurement.hpp:24
virtual void sample()
Samples the time from this clock stores it in the measured field of the Measurement object of the dev...
Definition: LinuxClock.hpp:156
constexpr boost::uuids::uuid LinuxClockDeviceId
The UUID for the Linux clock device.
Definition: LinuxClock.hpp:25
unique_ptr< Earth > earth
Definition: Planetary.cpp:18
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48
virtual bool unambiguous() const noexcept
Returns true if the clock properly reports the time during a leap second.
Definition: LinuxClock.hpp:189
NanoClock::time_point NanoTime
A point in time in Interstellar Time stored in Nanoseconds.
duds::data::GenericMeasurement< SVT, SQT, TVT, TQT > Measurement
Definition: LinuxClock.hpp:55
void setMeasurement(const ConstMeasurementSptr &store, int sIdx=0) const
Updates the current measurement of a member sensor.
Definition: Device.hpp:105