Skip to main content

hst_deactivations/
file.rs

1use super::{DeactivationLog, Entry, Error};
2use chrono::{DateTime, Utc};
3use fd_lock::RwLock as FdLock;
4use std::collections::HashMap;
5use std::fs::File;
6use std::io::{Seek, Write};
7use std::ops::DerefMut;
8use std::path::Path;
9use std::sync::{Arc, Mutex, RwLock};
10
11#[derive(Clone, Debug)]
12pub struct DeactivationFile {
13    file: Arc<Mutex<FdLock<File>>>,
14    log: Arc<RwLock<DeactivationLog>>,
15}
16
17impl DeactivationFile {
18    pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
19        let file = File::options().read(true).write(true).open(&path)?;
20        let log = DeactivationLog::read(&file)?;
21
22        Ok(Self {
23            file: Arc::new(Mutex::new(FdLock::new(file))),
24            log: Arc::new(RwLock::new(log)),
25        })
26    }
27
28    pub fn log(&self) -> DeactivationLog {
29        let log = self.log.read().unwrap();
30        log.clone()
31    }
32
33    pub fn lookup(&self, user_id: u64) -> Option<Vec<Entry>> {
34        let log = self.log.read().unwrap();
35        log.lookup(user_id)
36    }
37
38    pub fn status(&self, user_id: u64) -> Option<u32> {
39        let log = self.log.read().unwrap();
40        log.status(user_id)
41    }
42
43    pub fn add(&self, user_id: u64, status: u32, observed: DateTime<Utc>) {
44        let mut log = self.log.write().unwrap();
45        log.add(user_id, status, observed);
46    }
47
48    pub fn add_all(&self, updates: HashMap<u64, (u32, DateTime<Utc>)>) {
49        let mut log = self.log.write().unwrap();
50        log.add_all(updates);
51    }
52
53    pub fn flush(&self) -> Result<(), Error> {
54        let log = self.log.read().unwrap();
55        let mut mutex = self.file.lock().unwrap();
56        let mut file = mutex.write()?;
57
58        file.set_len(0)?;
59        file.rewind()?;
60        log.write(file.deref_mut())?;
61        file.flush()?;
62
63        Ok(())
64    }
65}