1
+ use chrono:: { DateTime , NaiveDateTime , Utc } ;
2
+ use cxx:: { self , SharedPtr } ;
1
3
///! Accurate distributed timestamps.
2
4
///!
3
5
///! Bindings to [clockkit](https://github.com/camilleg/clockkit).
4
- ///! Currently requires `nightly` for the use of `feature(atomic_mut_ptr)`.
5
6
///!
6
7
///! Clockkit provides timestamps to distributed networked PCs
7
8
///! with guaranteed bounds on latency and jitter, typically under 10 microseconds,
16
17
///! Originally created for a full-motion
17
18
///! [driving simulator](https://web.archive.org/web/20170517201424/http://www.isl.uiuc.edu/Labs/Driving%20Simulator/Driving%20Simulator.html)
18
19
///! with eye tracking and a quickly churning set of other sensors and outputs, for over a decade.
19
-
20
- use std:: { sync:: Mutex , thread:: JoinHandle , time:: Duration , path:: Path } ;
21
-
22
- use chrono:: { DateTime , NaiveDateTime , Utc } ;
23
- use cxx:: { self , SharedPtr } ;
20
+ use std:: { fmt:: Debug , path:: Path , sync:: Mutex , thread:: JoinHandle , time:: Duration } ;
24
21
use thiserror:: Error ;
25
22
26
23
/// Things that can go wrong.
@@ -36,8 +33,8 @@ pub enum Error {
36
33
#[ error( "Overflow" ) ]
37
34
Overflow ,
38
35
/// Invalid value.
39
- #[ error( "Invalid value" ) ]
40
- Invalid ,
36
+ #[ error( "Invalid value: {0} " ) ]
37
+ Invalid ( i64 ) ,
41
38
/// Could not read config file.
42
39
#[ error( "Could not read config file" ) ]
43
40
ConfigRead ( #[ from] std:: io:: Error ) ,
@@ -51,7 +48,6 @@ pub enum Error {
51
48
52
49
// Obviously invalid values. 9223372036854775807 usec, or 293,000 years.
53
50
const USEC_INVALID : i64 = i64:: MAX ;
54
- // constexpr tp tpInvalid = TpFromUsec(usecInvalid);
55
51
56
52
#[ cxx:: bridge]
57
53
mod ffi {
@@ -64,6 +60,7 @@ mod ffi {
64
60
/// .port(1234)
65
61
/// .build_clock();
66
62
#[ namespace = "bridge" ]
63
+ #[ derive( Debug ) ]
67
64
struct ConfigReader {
68
65
server : String ,
69
66
port : u16 ,
@@ -123,13 +120,14 @@ impl ffi::ConfigReader {
123
120
/// phasePanic:5000
124
121
/// updatePanic:5000000
125
122
/// ```
123
+ #[ cfg_attr( feature="tracing" , tracing:: instrument( level = "INFO" , fields( path=%path. as_ref( ) . display( ) ) ) ) ]
126
124
pub fn from_config_file ( path : impl AsRef < Path > ) -> Result < Self , Error > {
127
125
let mut res = Self :: default ( ) ;
128
126
129
127
let config = std:: fs:: read_to_string ( path. as_ref ( ) ) ?;
130
128
for line in config. lines ( ) {
131
129
if line. starts_with ( '#' ) {
132
- continue
130
+ continue ;
133
131
}
134
132
let mut parts = line. trim ( ) . splitn ( 2 , ':' ) ;
135
133
if let Some ( key) = parts. next ( ) {
@@ -149,6 +147,8 @@ impl ffi::ConfigReader {
149
147
}
150
148
}
151
149
}
150
+ #[ cfg( feature = "tracing" ) ]
151
+ tracing:: debug!( config=?res, "Read config from file" ) ;
152
152
Ok ( res)
153
153
}
154
154
@@ -206,9 +206,10 @@ pub struct PhaseLockedClock {
206
206
}
207
207
208
208
/// Helper function to create a NaiveDateTime from a timestamp in μs.
209
+ #[ cfg_attr( feature = "tracing" , tracing:: instrument( level = "DEBUG" ) ) ]
209
210
fn make_timestamp ( usec : i64 ) -> Result < NaiveDateTime , Error > {
210
211
if usec == USEC_INVALID {
211
- return Err ( Error :: Invalid ) ;
212
+ return Err ( Error :: Invalid ( usec ) ) ;
212
213
}
213
214
let sec: i64 = usec / 1_000_000 ;
214
215
let usec: Result < u32 , _ > = match ( usec % 1_000_000 ) . try_into ( ) {
@@ -232,19 +233,27 @@ impl PhaseLockedClock {
232
233
}
233
234
234
235
/// Run the PLC in its own thread
236
+ #[ cfg_attr( feature = "tracing" , tracing:: instrument( level = "INFO" , skip_all) ) ]
235
237
pub fn start ( & self ) {
236
238
if let Ok ( mut guard) = self . handle . lock ( ) {
237
239
// Only start the clock if there is no handle present, otherwise it's running.
238
240
if ( * guard) . is_none ( ) {
239
241
let plc = self . ptr . clone ( ) ;
240
- * guard = Some ( std:: thread:: spawn ( move || ffi:: run1 ( plc) ) )
242
+ * guard = Some ( std:: thread:: spawn ( move || ffi:: run1 ( plc) ) ) ;
243
+
244
+ #[ cfg( feature = "tracing" ) ]
245
+ tracing:: info!( "PhaseLockedClock started" ) ;
246
+ } else {
247
+ #[ cfg( feature = "tracing" ) ]
248
+ tracing:: warn!( "PhaseLockedClock is already running" ) ;
241
249
}
242
250
} else {
243
251
panic ! ( "Unable to start PhaseLockedClock due to poisened mutex" ) ;
244
252
} ;
245
253
}
246
254
247
255
/// Stop the PLC.
256
+ #[ cfg_attr( feature = "tracing" , tracing:: instrument( level = "INFO" , skip_all) ) ]
248
257
pub fn stop ( & self ) {
249
258
let plc = self . ptr . clone ( ) ;
250
259
ffi:: cancel ( plc) ;
@@ -255,6 +264,7 @@ impl PhaseLockedClock {
255
264
/// phasePanic: A PhaseLockedClock whose offset exceeds this,
256
265
/// relative to its reference clock, declares itself out of sync.
257
266
/// Default: 5ms
267
+ #[ cfg_attr( feature = "tracing" , tracing:: instrument( level = "INFO" , skip_all) ) ]
258
268
pub fn set_phase_panic ( & mut self , dur : Duration ) {
259
269
let dur = dur
260
270
. as_micros ( )
@@ -264,11 +274,12 @@ impl PhaseLockedClock {
264
274
ffi:: setPhasePanic ( plc, dur)
265
275
}
266
276
267
- /// Set the threshold for the update panic.
268
- ///
269
- /// updatePanic: A PhaseLockedClock that hasn't updated successfully
270
- /// for longer than this declares itself out of sync.
271
- /// Default: 5s
277
+ /// Set the threshold for the update panic.
278
+ ///
279
+ /// updatePanic: A PhaseLockedClock that hasn't updated successfully
280
+ /// for longer than this declares itself out of sync.
281
+ /// Default: 5s
282
+ #[ cfg_attr( feature = "tracing" , tracing:: instrument( level = "INFO" , skip_all) ) ]
272
283
pub fn set_update_panic ( & mut self , dur : Duration ) {
273
284
let dur = dur
274
285
. as_micros ( )
@@ -304,4 +315,3 @@ impl Drop for PhaseLockedClock {
304
315
unsafe impl Send for ffi:: PhaseLockedClock { }
305
316
306
317
unsafe impl Sync for ffi:: PhaseLockedClock { }
307
-
0 commit comments