feat(cache): use modification date for updating cache

This commit is contained in:
Orhun Parmaksız 2021-12-03 16:45:58 +03:00
parent 6bbf04a3c1
commit ab747cbd37
No known key found for this signature in database
GPG key ID: F83424824B3E4B90
3 changed files with 49 additions and 14 deletions

View file

@ -1,11 +1,39 @@
use crate::error::{Error, Result};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::fs::{self, File};
use std::io::Write;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::time::SystemTime;
use systeroid_parser::reader;
/// Cache data to store on the file system.
#[derive(Debug, Serialize, Deserialize)]
pub struct CacheData<Data> {
/// Cache data.
pub data: Data,
/// Timestamp of the data.
pub timestamp: u64,
}
impl<Data> CacheData<Data> {
/// Constructs a new instance.
pub fn new(data: Data, path: &Path) -> Result<Self> {
Ok(Self {
data,
timestamp: Self::get_timestamp(path)?,
})
}
/// Returns the last modification date of given file as UNIX timestamp.
pub fn get_timestamp(path: &Path) -> Result<u64> {
Ok(fs::metadata(&path)?
.modified()?
.duration_since(SystemTime::UNIX_EPOCH)?
.as_secs())
}
}
/// Cache manager for handling the R/W operations of labeled data.
#[derive(Debug)]
pub struct Cache {
@ -37,19 +65,19 @@ impl Cache {
}
/// Reads the given labeled data from the cache.
pub fn read<Data: DeserializeOwned>(&self, label: &str) -> Result<Data> {
pub fn read<T: DeserializeOwned>(&self, label: &str) -> Result<CacheData<T>> {
let raw_data = reader::read_to_string(self.get_cache_path(label))?;
Ok(serde_json::from_str(&raw_data)?)
}
/// Writes the given data to the cache.
pub fn write<Data: ?Sized + Serialize>(&self, data: &Data, label: &str) -> Result<()> {
pub fn write<T: Serialize>(&self, data: CacheData<T>, label: &str) -> Result<()> {
let cache_path = self.get_cache_path(label);
if !cache_path.exists() {
fs::create_dir_all(self.cache_dir.join(env!("CARGO_PKG_NAME")))?;
};
let mut file = File::create(&cache_path)?;
file.write_all(serde_json::to_string(data)?.as_bytes())?;
file.write_all(serde_json::to_string(&data)?.as_bytes())?;
Ok(())
}
}

View file

@ -15,6 +15,9 @@ pub enum Error {
/// Error that may occur while de/serializing JSON data.
#[error("JSON de/serialization error: `{0}`")]
SerdeJsonError(#[from] serde_json::Error),
/// Error that may occur due to system time related anomalies.
#[error("System time error: `{0}`")]
SystemTimeError(#[from] std::time::SystemTimeError),
/// Error that may occur while parsing documents.
#[error("parser error: `{0}`")]
ParseError(#[from] systeroid_parser::error::Error),

View file

@ -2,11 +2,11 @@ use std::env;
use std::io::{self, Stdout};
use std::path::PathBuf;
use std::process::{Command, Stdio};
use systeroid_core::cache::Cache;
use systeroid_core::cache::{Cache, CacheData};
use systeroid_core::config::AppConfig;
use systeroid_core::error::Result;
use systeroid_core::parsers::KERNEL_DOCS_PATH;
use systeroid_core::sysctl::{Parameter, Sysctl};
use systeroid_core::sysctl::Sysctl;
/// Label for caching the kernel parameters.
const PARAMETERS_CACHE_LABEL: &str = "parameters";
@ -45,19 +45,23 @@ impl<'a> App<'a> {
/// Updates the documentation for kernel parameters.
pub fn update_documentation(&mut self, kernel_docs: Option<&PathBuf>) -> Result<()> {
if self.cache.exists(PARAMETERS_CACHE_LABEL) && kernel_docs.is_none() {
self.sysctl
.update_params(self.cache.read::<Vec<Parameter>>(PARAMETERS_CACHE_LABEL)?);
return Ok(());
}
let mut kernel_docs_path = KERNEL_DOCS_PATH.clone();
if let Some(path) = kernel_docs {
kernel_docs_path.insert(0, path);
}
if let Some(path) = kernel_docs_path.iter().find(|path| path.exists()) {
if self.cache.exists(PARAMETERS_CACHE_LABEL) && kernel_docs.is_none() {
let cache_data = self.cache.read(PARAMETERS_CACHE_LABEL)?;
if cache_data.timestamp == CacheData::<()>::get_timestamp(path)? {
self.sysctl.update_params(cache_data.data);
return Ok(());
}
}
self.sysctl.update_docs(path)?;
self.cache
.write(&self.sysctl.parameters, PARAMETERS_CACHE_LABEL)?;
self.cache.write(
CacheData::new(&self.sysctl.parameters, path)?,
PARAMETERS_CACHE_LABEL,
)?;
} else {
eprintln!("warning: `Linux kernel documentation cannot be found. Please specify a path via '-d' argument`",);
}