Skip to main content

lb_fs/
cache.rs

1use crate::{fs_impl::Drive, utils::file_id};
2use lb_rs::model::file::File;
3use nfs3_server::nfs3_types::nfs3::{fattr3, ftype3, nfstime3};
4use std::time::{Duration, SystemTime};
5use tracing::info;
6
7pub struct FileEntry {
8    pub file: File,
9    pub fattr: fattr3,
10}
11
12impl FileEntry {
13    pub fn from_file(file: File, size: u64) -> Self {
14        let ftype = if file.is_folder() { ftype3::NF3DIR } else { ftype3::NF3REG };
15
16        // todo this deserves some scrutiny and cross platform testing
17        let mode = if file.is_folder() { 0o755 } else { 0o644 };
18
19        let fileid = file_id(&file);
20        // interestingly a number of key read operations rely on this being correct
21        let size = if file.is_folder() { 0 } else { size };
22
23        let atime = Self::ts_from_u64(0);
24        let mtime = Self::ts_from_u64(file.last_modified);
25        let ctime = Self::ts_from_u64(file.last_modified);
26
27        let fattr = fattr3 {
28            type_: ftype,
29            mode,
30            nlink: 1, // hard links to this file
31            uid: 501, // todo: evaluate owner field? not resolved by this lib
32            gid: 20,  // group id
33            size,
34            used: size,               // ?
35            rdev: Default::default(), // ?
36            fsid: Default::default(), // file system id
37            fileid,
38            atime,
39            mtime,
40            ctime,
41        };
42
43        Self { file, fattr }
44    }
45
46    pub fn ts_from_u64(version: u64) -> nfstime3 {
47        let time = Duration::from_millis(version);
48        nfstime3 { seconds: time.as_secs() as u32, nseconds: time.subsec_nanos() }
49    }
50
51    pub fn now() -> nfstime3 {
52        SystemTime::now()
53            .try_into()
54            .expect("failed to get current time")
55    }
56}
57
58impl Drive {
59    // todo: probably need a variant of this that is more suitable post sync cache updates
60    pub async fn fill_cache(&self) {
61        info!("preparing cache, are you release build?");
62        let files = self.lb.list_metadatas().await.unwrap();
63
64        let mut data = self.data.lock().await;
65        data.clear();
66        for file in files {
67            let id = file.id;
68            let size = self
69                .lb
70                .read_document(id, false)
71                .await
72                .unwrap_or_default()
73                .len() as u64;
74            let entry = FileEntry::from_file(file, size);
75            data.insert(entry.file.id.into(), entry);
76        }
77        info!("cache ready");
78    }
79}