1use std::path::Path;
27use std::sync::{Arc, LazyLock, Mutex};
28use std::time::SystemTime;
29use std::fs;
30
31
32use crate::cfg_host_parser::HostConfig;
33use crate::cfg_resolv_parser::ResolveConfig;
34use crate::{write_error, internal_error, internal_error_map, error::*};
35
36use super::cfg_parsers::*;
37
38pub static CACHE: LazyLock<CachesController> = LazyLock::new(|| { CachesController::new() });
39
40
41pub trait CacheOperations
42{
43 fn is_reload_allowed(&self) -> bool;
44}
45
46#[derive(Clone, Debug)]
47struct CacheTime<'cache>
48{
49 path: &'cache Path,
50 last_modif: SystemTime,
51}
52
53impl<'cache> CacheTime<'cache>
54{
55 fn new(path: &'cache Path) -> CDnsResult<Self>
56 {
57 return Ok(Self { path: path, last_modif: Self::get_last_modified(path)? });
58 }
59
60 fn fake(path: &'cache Path) -> Self
61 {
62 return Self { path: path, last_modif: SystemTime::now() };
63 }
64
65 fn get_last_modified(path: &'cache Path) -> CDnsResult<SystemTime>
66 {
67 let metadata = fs::metadata(path).map_err(|e|
68 internal_error_map!(CDnsErrorType::InternalError, "fs::metadata::modified() not supported on this platform: '{}'", e)
69 )?;
70
71 let last_modif =
72 metadata.modified().map_err(|e|
73 internal_error_map!(CDnsErrorType::InternalError, "fs::metadata::modified() not supported on this platform: '{}'", e)
74 )?;
75
76 return Ok(last_modif);
77 }
78
79 fn check_modified(&mut self) -> CDnsResult<bool>
80 {
81 let last_modif =
83 match Self::get_last_modified(self.path)
84 {
85 Ok(t) => t,
86 Err(e) => internal_error!(CDnsErrorType::InternalError, "{}", e),
87 };
88
89 return Ok(self.last_modif != last_modif);
90 }
104}
105
106#[derive(Clone, Debug)]
107pub struct CacheInstance<T: Default + ConfigParser<T> + CacheOperations>{
109 last_modif: CacheTime<'static>,
110 cache: Arc<T>,
111 }
113
114impl<T: Default + ConfigParser<T> + CacheOperations> Default for CacheInstance<T>
115{
116 fn default() -> Self
117 {
118 return
119 Self
120 {
121 last_modif: CacheTime::fake(T::get_file_path()),
122 cache: Arc::new(T::default()),
123 };
125 }
126}
127
128impl<T: Default + ConfigParser<T> + CacheOperations> CacheInstance<T>
129{
130 fn new() -> CDnsResult<Self>
131 {
132 return Ok(
133 Self
134 {
135 last_modif: CacheTime::new(T::get_file_path())?,
136 cache: Arc::new(T::parse_config()?),
137 }
139 );
140 }
141
142 fn read_config() -> CDnsResult<Arc<T>>
143 {
144 return Ok(Arc::new(T::parse_config()?));
145 }
146
147 fn check_modified(&mut self) -> CDnsResult<()>
148 {
149 if self.cache.is_reload_allowed() == false
151 {
152 return Ok(());
154 }
155
156 if self.last_modif.check_modified()? == true
157 {
158 self.cache = Self::read_config()?;
160 }
161
162 return Ok(());
163 }
164
165 fn clone_cache(&self) -> Arc<T>
166 {
167 return self.cache.clone();
168 }
169}
170
171pub struct CachesController
172{
173 resolv_cache: Mutex<CacheInstance<ResolveConfig>>,
174 host_cache: Mutex<CacheInstance<HostConfig>>
175}
176
177unsafe impl Sync for CachesController{}
178unsafe impl Send for CachesController{}
179
180impl CachesController
181{
182 fn new() -> Self
184 {
185 let resolve_cache_res = CacheInstance::<ResolveConfig>::new();
186
187 let host_cache_res = CacheInstance::<HostConfig>::new();
188
189 let resolve_cache =
190 match resolve_cache_res
191 {
192 Ok(r) => r,
193 Err(e) =>
194 {
195 write_error!("{}", e);
196
197 CacheInstance::default()
198 }
199 };
200
201 let host_cache =
202 match host_cache_res
203 {
204 Ok(r) => r,
205 Err(e) =>
206 {
207 write_error!("{}", e);
208
209 CacheInstance::default()
210 }
211 };
212
213
214 return
215 CachesController
216 {
217 resolv_cache: Mutex::new(resolve_cache),
218 host_cache: Mutex::new(host_cache),
219 };
220 }
221
222 pub
223 fn is_resolve_cached(&self) -> bool
224 {
225 return !self.resolv_cache.lock().unwrap().cache.is_default();
226 }
227
228 pub
229 fn is_host_cached(&self) -> bool
230 {
231 return !self.host_cache.lock().unwrap().cache.is_default();
232 }
233
234 fn try_cache_resolve(&self) -> CDnsResult<Arc<ResolveConfig>>
235 {
236 let mut mutx_resolv = self.resolv_cache.lock().unwrap();
237 mutx_resolv.check_modified()?;
238
239 return Ok(mutx_resolv.clone_cache());
240 }
241
242 pub
244 fn clone_resolve_list(&self) -> CDnsResult<Arc<ResolveConfig>>
245 {
246 match self.try_cache_resolve()
248 {
249 Ok(r) => return Ok(r),
250 Err(e) =>
251 {
252 write_error!("{}", e);
253
254 return CacheInstance::<ResolveConfig>::read_config();
256 }
257 }
258 }
259
260 fn try_cache_host(&self) -> CDnsResult<Arc<HostConfig>>
261 {
262 let mut mutx_host = self.host_cache.lock().unwrap();
263 mutx_host.check_modified()?;
264
265 return Ok(mutx_host.clone_cache());
266 }
267
268 pub
270 fn clone_host_list(&self) -> CDnsResult<Arc<HostConfig>>
271 {
272 match self.try_cache_host()
273 {
274 Ok(r) => return Ok(r),
275 Err(e) =>
276 {
277 write_error!("{}", e);
278
279 return CacheInstance::<HostConfig>::read_config();
281 }
282 }
283 }
284}
285
286
287#[test]
288fn test_init()
289{
290 let res = CACHE.clone_resolve_list();
291 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
292
293 let res = res.unwrap();
294
295 println!("{:?}", res);
296
297 let res = CACHE.clone_host_list();
298 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
299
300 let res = res.unwrap();
301
302 println!("{:?}", res);
303}