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