1use crate::{fs_impl::Drive, utils::file_id};
2use lb_rs::model::file::File;
3use lb_rs::model::work_unit::WorkUnit;
4use nfs3_server::nfs3_types::nfs3::{fattr3, ftype3, nfstime3};
5use std::time::{Duration, SystemTime};
6use tracing::info;
7
8pub struct FileEntry {
9 pub file: File,
10 pub fattr: fattr3,
11}
12
13impl FileEntry {
14 pub fn from_file(file: File, size: u64) -> Self {
15 let ftype = if file.is_folder() { ftype3::NF3DIR } else { ftype3::NF3REG };
16
17 let mode = if file.is_folder() { 0o755 } else { 0o644 };
19
20 let fileid = file_id(&file);
21 let size = if file.is_folder() { 0 } else { size };
23
24 let atime = Self::ts_from_u64(0);
25 let mtime = Self::ts_from_u64(file.last_modified);
26 let ctime = Self::ts_from_u64(file.last_modified);
27
28 let fattr = fattr3 {
29 type_: ftype,
30 mode,
31 nlink: 1, uid: 501, gid: 20, size,
35 used: size, rdev: Default::default(), fsid: Default::default(), fileid,
39 atime,
40 mtime,
41 ctime,
42 };
43
44 Self { file, fattr }
45 }
46
47 pub fn ts_from_u64(version: u64) -> nfstime3 {
48 let time = Duration::from_millis(version);
49 nfstime3 { seconds: time.as_secs() as u32, nseconds: time.subsec_nanos() }
50 }
51
52 pub fn now() -> nfstime3 {
53 SystemTime::now()
54 .try_into()
55 .expect("failed to get current time")
56 }
57}
58
59impl Drive {
60 pub async fn prepare_caches(&self) {
62 info!("performing startup sync");
63 self.lb.sync(Self::progress()).await.unwrap();
64
65 info!("preparing cache, are you release build?");
66 let sizes = self.lb.get_uncompressed_usage_breakdown().await.unwrap();
67 let files = self.lb.list_metadatas().await.unwrap();
68
69 let mut data = self.data.lock().await;
70 for file in files {
71 let id = file.id;
72 let entry =
73 FileEntry::from_file(file, sizes.get(&id).copied().unwrap_or_default() as u64);
74 data.insert(entry.file.id.into(), entry);
75 }
76 info!("cache ready");
77 }
78
79 pub async fn sync(&self) {
80 let status = self.lb.sync(None).await.unwrap();
81 let mut data = self.data.lock().await;
82
83 for unit in status.work_units {
84 if let WorkUnit::ServerChange(dirty_id) = unit {
85 let file = self.lb.get_file_by_id(dirty_id).await.unwrap();
86 let size = if file.is_document() {
87 self.lb.read_document(dirty_id, false).await.unwrap().len()
88 } else {
89 0
90 };
91
92 let mut entry = FileEntry::from_file(file, size as u64);
93
94 let now = FileEntry::now();
95
96 entry.fattr.mtime = now;
97 entry.fattr.ctime = now;
98
99 data.insert(entry.file.id.into(), entry);
100 }
101 }
102 }
103}