1use crate::fs_impl::Drive;
2use lb_rs::model::{file::File, work_unit::WorkUnit};
3use nfsserve::nfs::{fattr3, ftype3, nfstime3};
4use std::time::{Duration, SystemTime, UNIX_EPOCH};
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 let mode = if file.is_folder() { 0o755 } else { 0o644 };
18
19 let fileid = file.id.as_u64_pair().0;
20 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 ftype,
29 mode,
30 nlink: 1, uid: 501, gid: 20, size,
34 used: size, rdev: Default::default(), fsid: Default::default(), 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() -> u64 {
52 let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
53 time.as_millis() as u64
54 }
55}
56
57impl Drive {
58 pub async fn prepare_caches(&self) {
60 info!("performing startup sync");
61 self.lb.sync(Self::progress()).await.unwrap();
62
63 info!("preparing cache, are you release build?");
64 let sizes = self.lb.get_uncompressed_usage_breakdown().await.unwrap();
65 let files = self.lb.list_metadatas().await.unwrap();
66
67 let mut data = self.data.lock().await;
68 for file in files {
69 let id = file.id;
70 let entry =
71 FileEntry::from_file(file, sizes.get(&id).copied().unwrap_or_default() as u64);
72 data.insert(entry.fattr.fileid, entry);
73 }
74 info!("cache ready");
75 }
76
77 pub async fn sync(&self) {
78 let status = self.lb.sync(None).await.unwrap();
79 let mut data = self.data.lock().await;
80
81 for unit in status.work_units {
82 if let WorkUnit::ServerChange(dirty_id) = unit {
83 let file = self.lb.get_file_by_id(dirty_id).await.unwrap();
84 let size = if file.is_document() {
85 self.lb.read_document(dirty_id, false).await.unwrap().len()
86 } else {
87 0
88 };
89
90 let mut entry = FileEntry::from_file(file, size as u64);
91
92 let now = FileEntry::ts_from_u64(FileEntry::now());
93
94 entry.fattr.mtime = now;
95 entry.fattr.ctime = now;
96
97 data.insert(entry.fattr.fileid, entry);
98 }
99 }
100 }
101}