1use std::marker::PhantomData;
25use std::path::Path;
28use std::sync::Arc;
29use std::time::SystemTime;
30
31
32use crate::a_sync::interface::{AsyncMutex, AsyncMutexGuard, MutexedCaches, UnifiedFs};
33#[cfg(feature = "built_in_async")]
34use crate::a_sync::{IoInterf};
35use crate::cfg_host_parser::HostConfig;
36use crate::cfg_resolv_parser::ResolveConfig;
37use crate::{error::*, internal_error, internal_error_map, write_error};
38
39use super::cfg_parsers::*;
40
41pub trait CacheOperations
45{
46 fn is_reload_allowed(&self) -> bool;
47}
48
49#[derive(Clone, Debug)]
50struct CacheTime<'cache, FS: UnifiedFs>
51{
52 path: &'cache Path,
53 last_modif: SystemTime,
54 _fs: PhantomData<FS>
55}
56
57impl<'cache, FS: UnifiedFs> CacheTime<'cache, FS>
58{
59 async
60 fn new(path: &'cache Path) -> CDnsResult<CacheTime<'cache, FS>>
61 {
62 return Ok(
63 CacheTime
64 {
65 path: path,
66 last_modif: Self::get_last_modified(path).await?,
67 _fs: PhantomData
68 }
69 );
70 }
71
72 fn fake(path: &'cache Path) -> Self
73 {
74 return
75 Self
76 {
77 path: path,
78 last_modif: SystemTime::now(),
79 _fs: PhantomData
80 };
81 }
82
83 async
84 fn get_last_modified(path: &'cache Path) -> CDnsResult<SystemTime>
85 {
86 let metadata =
87 FS::metadata(path)
88 .await
89 .map_err(|e|
90 internal_error_map!(CDnsErrorType::InternalError,
91 "fs::metadata::modified() not supported on this platform: '{}'", e)
92 )?;
93
94 let last_modif =
95 metadata
96 .modified()
97 .map_err(|e|
98 internal_error_map!(CDnsErrorType::InternalError,
99 "fs::metadata::modified() not supported on this platform: '{}'", e)
100 )?;
101
102 return Ok(last_modif);
103 }
104
105 async
106 fn check_modified(&mut self) -> CDnsResult<bool>
107 {
108 let last_modif =
110 match Self::get_last_modified(self.path).await
111 {
112 Ok(t) => t,
113 Err(e) => internal_error!(CDnsErrorType::InternalError, "{}", e),
114 };
115
116 return Ok(self.last_modif != last_modif);
117 }
118}
119
120#[derive(Clone, Debug)]
121pub struct CacheInstance<T: Default + ConfigParser<T> + CacheOperations, FS: UnifiedFs>
122{
123 last_modif: CacheTime<'static, FS>,
124 cache: Arc<T>,
125 _fs: PhantomData<FS>
126}
127
128impl<T: Default + ConfigParser<T> + CacheOperations, FS: UnifiedFs> Default for CacheInstance<T, FS>
129{
130 fn default() -> Self
131 {
132 return
133 Self
134 {
135 last_modif: CacheTime::fake(T::get_file_path()),
136 cache: Arc::new(T::default()),
137 _fs: PhantomData
138 };
140 }
141}
142
143impl<T: Default + ConfigParser<T> + CacheOperations, FS: UnifiedFs> CacheInstance<T, FS>
144{
145 async
146 fn new() -> CDnsResult<Self>
147 {
148 return Ok(
149 Self
150 {
151 last_modif: CacheTime::new(T::get_file_path()).await?,
152 cache: Arc::new(T::parse_config::<FS>().await?),
153 _fs: PhantomData
154 }
156 );
157 }
158
159 async
160 fn read_config() -> CDnsResult<Arc<T>>
161 {
162 return Ok(Arc::new(T::parse_config::<FS>().await?));
163 }
164
165 async
166 fn check_modified(&mut self) -> CDnsResult<()>
167 {
168 if self.cache.is_reload_allowed() == false
170 {
171 return Ok(());
173 }
174
175 if self.last_modif.check_modified().await? == true
176 {
177 self.cache = Self::read_config().await?;
179 }
180
181 return Ok(());
182 }
183
184 fn clone_cache(&self) -> Arc<T>
185 {
186 return self.cache.clone();
187 }
188}
189
190#[cfg(feature = "built_in_async")]
199#[derive(Debug)]
200pub struct CachesController<MC: MutexedCaches = IoInterf>
201{
202 resolv_cache: MC::ResolveCache,
203 host_cache: MC::HostCahae,
204 _p: PhantomData<MC>,
205}
206
207#[cfg(feature = "built_in_async")]
208impl CachesController<IoInterf>
209{
210 pub async
211 fn new() -> CDnsResult<Self>
212 {
213 return Ok(
214 CachesController
215 {
216 resolv_cache:
217 <IoInterf as MutexedCaches>::ResolveCache::a_new(CacheInstance::new().await?),host_cache:
219 <IoInterf as MutexedCaches>::HostCahae::a_new(CacheInstance::new().await?),_p:
221 PhantomData
222 }
223 );
224 }
225}
226
227#[cfg(not(feature = "built_in_async"))]
228#[derive(Debug)]
229pub struct CachesController<MC: MutexedCaches>
230{
231 resolv_cache: MC::ResolveCache,
232 host_cache: MC::HostCahae,
233 _p: PhantomData<MC>,
234}
235
236unsafe impl<MC: MutexedCaches> Sync for CachesController<MC>{}
237unsafe impl<MC: MutexedCaches> Send for CachesController<MC>{}
238
239impl<MC: MutexedCaches> CachesController<MC>
240{
241 pub async
243 fn new_custom() -> CDnsResult<Self>
244 {
245 return Ok(
275 CachesController
276 {
277 resolv_cache: MC::ResolveCache::a_new(CacheInstance::new().await?),host_cache: MC::HostCahae::a_new(CacheInstance::new().await?),_p: PhantomData
280 }
281 );
282 }
283
284 pub async
285 fn is_resolve_cached(&self) -> bool
286 {
287 return !self.resolv_cache.a_lock().await.guard().cache.is_default();
288 }
289
290 pub async
291 fn is_host_cached(&self) -> bool
292 {
293 return !self.host_cache.a_lock().await.guard().cache.is_default();
294 }
295
296 async
297 fn try_cache_resolve(&self) -> CDnsResult<Arc<ResolveConfig>>
298 {
299 let mut mutx_resolv = self.resolv_cache.a_lock().await;
300 mutx_resolv.guard_mut().check_modified().await?;
301
302 return Ok(mutx_resolv.guard().clone_cache());
303 }
304
305 pub async
306 fn clone_resolve_list(&self) -> CDnsResult<Arc<ResolveConfig>>
307 {
308 match self.try_cache_resolve().await
310 {
311 Ok(r) =>
312 return Ok(r),
313 Err(e) =>
314 {
315 write_error!(e);
316
317 return CacheInstance::<ResolveConfig, MC::MetadataFs>::read_config().await;
319 }
320 }
321 }
322
323 async
324 fn try_cache_host(&self) -> CDnsResult<Arc<HostConfig>>
325 {
326 let mut mutx_host = self.host_cache.a_lock().await;
327 mutx_host.guard_mut().check_modified().await?;
328
329 return Ok(mutx_host.guard().clone_cache());
330 }
331
332 pub async
333 fn clone_host_list(&self) -> CDnsResult<Arc<HostConfig>>
334 {
335 match self.try_cache_host().await
336 {
337 Ok(r) => return Ok(r),
338 Err(e) =>
339 {
340 write_error!(e);
341
342 return CacheInstance::<HostConfig, MC::MetadataFs>::read_config().await;
344 }
345 }
346 }
347}
348
349
350#[cfg(feature = "use_async_tokio_tls")]
351#[cfg(test)]
352mod tests
353{
354 use std::sync::Arc;
355
356 use crate::a_sync::CachesController;
357
358
359 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
360 async fn test_init()
361 {
362 let cache = Arc::new(CachesController::new().await.unwrap());
363
364 let res = cache.clone_resolve_list().await;
365 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
366
367 let res = res.unwrap();
368
369 println!("{:?}", res);
370
371 let res = cache.clone_host_list().await;
372 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
373
374 let res = res.unwrap();
375
376 println!("{:?}", res);
377 }
378}