dvcompute_dist/simulation/comm/
time.rs

1// Copyright (c) 2020-2022  David Sorokin <davsor@mail.ru>, based in Yoshkar-Ola, Russia
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use std::time::*;
8use std::ptr;
9use std::ffi::CString;
10use std::ffi::CStr;
11
12use libc::*;
13
14use dvcompute_network::network::*;
15
16/// The Time Server parameters.
17#[derive(Clone)]
18pub struct TimeServerParameters {
19
20    /// The logical process name.
21    pub name: String,
22
23    /// The timeout used for the time synchronization sessions.
24    pub sync_timeout: Duration,
25
26    /// The delay between the time synchronization sessions.
27    pub sync_delay: Duration,
28
29    /// The idle loop interval when processing the messages.
30    pub idle_loop_interval: Duration,
31
32    /// The test interval for network messages.
33    pub network_test_interval: Duration,
34
35    /// The threshold of network requests to test.
36    pub network_test_threshold: usize,
37
38    /// The threshold of network requests to wait.
39    pub network_wait_threshold: usize
40}
41
42impl TimeServerParameters {
43
44    /// Create new Time Server parameters.
45    pub fn new() -> TimeServerParameters {
46        TimeServerParameters {
47            name: String::from("TimeServer"),
48            sync_timeout: Duration::from_secs(60),
49            sync_delay: Duration::from_millis(100),
50            idle_loop_interval: Duration::from_millis(10),
51            network_test_interval: Duration::from_millis(10),
52            network_test_threshold: 256,
53            network_wait_threshold: 8192
54        }
55    }
56}
57
58/// A C-friendly representation of the time server parameters.
59#[repr(C)]
60pub struct TimeServerParametersRepr {
61
62    /// Delete the representation.
63    delete_repr: unsafe extern "C" fn(*mut TimeServerParametersRepr),
64
65    /// The time server name.
66    name: *mut c_char,
67
68    /// Delete the time server name.
69    delete_name: unsafe extern "C" fn(*mut c_char),
70
71    /// The timeout used for the time synchronization sessions.
72    sync_timeout: [u8; 16],
73
74    /// The delay between the time synchronization sessions.
75    sync_delay: [u8; 16],
76
77    /// The idle loop interval when processing the messages.
78    idle_loop_interval: [u8; 16],
79
80    /// The test interval for network messages.
81    network_test_interval: [u8; 16],
82
83    /// The threshold of network requests to test.
84    network_test_threshold: usize,
85
86    /// The threshold of network requests to wait.
87    network_wait_threshold: usize
88}
89
90impl TimeServerParametersRepr {
91
92    /// Convert to a C-friendly representation.
93    pub fn new(ps: TimeServerParameters) -> Self {
94        let name = CString::new(ps.name.clone()).expect("NulError");
95        let name = CString::into_raw(name);
96        TimeServerParametersRepr {
97            delete_repr: delete_ts_repr,
98            name: name,
99            delete_name: delete_ts_name,
100            sync_timeout: u128::to_ne_bytes(ps.sync_timeout.as_nanos()),
101            sync_delay: u128::to_ne_bytes(ps.sync_delay.as_nanos()),
102            idle_loop_interval: u128::to_ne_bytes(ps.idle_loop_interval.as_nanos()),
103            network_test_interval: u128::to_ne_bytes(ps.network_test_interval.as_nanos()),
104            network_test_threshold: ps.network_test_threshold,
105            network_wait_threshold: ps.network_wait_threshold
106        }
107    }
108}
109
110impl Drop for TimeServerParametersRepr {
111
112    fn drop(&mut self) {
113        unsafe {
114            (self.delete_name)(self.name);
115        }
116    }
117}
118
119unsafe extern "C" fn delete_ts_name(name: *mut c_char) {
120    if name != ptr::null_mut() {
121        let _ = CString::from_raw(name);
122    }
123}
124
125unsafe extern "C" fn delete_ts_repr(e: *mut TimeServerParametersRepr) {
126    if e != ptr::null_mut() {
127        let _ = Box::from_raw(e);
128    }
129}
130
131/// Convert the `TimeServerParametersRepr` referenced to by the FFI pointer to a `TimeServerParameters`.
132pub unsafe fn ffi_time_server_parameters_repr_into(ps: *mut TimeServerParametersRepr) -> TimeServerParameters {
133    let name = CStr::from_ptr((*ps).name);
134    let name = name.to_bytes().to_vec();
135    let name = String::from_utf8(name).expect("FromUtf8Error");
136    let xs   = TimeServerParameters {
137        name: name,
138        sync_timeout: Duration::from_nanos(u128::from_ne_bytes((*ps).sync_timeout) as u64),
139        sync_delay: Duration::from_nanos(u128::from_ne_bytes((*ps).sync_delay) as u64),
140        idle_loop_interval: Duration::from_nanos(u128::from_ne_bytes((*ps).idle_loop_interval) as u64),
141        network_test_interval: Duration::from_nanos(u128::from_ne_bytes((*ps).network_test_interval) as u64),
142        network_test_threshold: (*ps).network_test_threshold,
143        network_wait_threshold: (*ps).network_wait_threshold
144    };
145    ((*ps).delete_repr)(ps);
146    xs
147}
148
149/// Represents the Time Server.
150pub struct TimeServer {}
151
152impl TimeServer {
153
154    /// Run the Time Server.
155    pub fn run(network: NetworkSupport, init_quorum: usize, ps: TimeServerParameters) {
156        unsafe {
157            let ps = TimeServerParametersRepr::new(ps);
158            let ps = Box::new(ps);
159            let ps = Box::into_raw(ps);
160
161            run_extern_time_server(network, init_quorum, ps)
162        }
163    }
164}
165
166#[cfg(all(feature="dist_mode", not(feature="dist_core_mode")))]
167#[cfg_attr(windows, link(name = "dvcompute_core_dist.dll"))]
168#[cfg_attr(not(windows), link(name = "dvcompute_core_dist"))]
169extern {
170
171    /// Run the time server.
172    #[doc(hidden)]
173    pub fn run_extern_time_server(network: NetworkSupport, init_quorum: usize, ps: *mut TimeServerParametersRepr);
174}
175
176#[cfg(all(feature="dist_mode", feature="dist_core_mode"))]
177extern {
178
179    /// Run the time server.
180    #[doc(hidden)]
181    pub fn run_extern_time_server(network: NetworkSupport, init_quorum: usize, ps: *mut TimeServerParametersRepr);
182}