Skip to main content

pagers_core/ops/
mod.rs

1mod evict;
2mod lock;
3mod lockall;
4mod process;
5mod query;
6mod touch;
7
8use std::fs::File;
9use std::path::Path;
10use std::sync::Arc;
11use std::sync::atomic::AtomicUsize;
12
13use memmap2::Mmap;
14
15use crate::mincore::{DefaultPageMap, PageMap};
16
17pub use evict::Evict;
18pub use lock::{Lock, LockedFile};
19pub use lockall::Lockall;
20pub use process::{CountsResult, FileProcessed, FullResult, SkipResult, file_info};
21pub(crate) use process::{PreparedFile, prepare_file};
22pub use query::Query;
23pub use touch::Touch;
24
25pub trait Op: Sync {
26    const LABEL: &str;
27    const MUTATES_RESIDENCY: bool = true;
28    /// Skip all residency checks; the after-state is known to be empty.
29    const SKIP_RESIDENCY: bool = false;
30    /// +1 for ops that add pages to cache (touch/lock), -1 for evict, 0 for query.
31    const ACTION_SIGN: isize = 0;
32
33    type Output: Send;
34    fn execute<PM: PageMap + Sync>(&self, ctx: &FileContext<'_, PM>)
35    -> crate::Result<Self::Output>;
36
37    fn finish(&self) -> crate::Result<()> {
38        Ok(())
39    }
40
41    fn action_pages(
42        _output: &Self::Output,
43        _total_pages: usize,
44        _pages_in_core_before: Option<usize>,
45        _pages_in_core_after: usize,
46    ) -> usize {
47        0
48    }
49}
50
51pub struct FileContext<'a, PM: PageMap = DefaultPageMap> {
52    pub file: &'a File,
53    pub path: &'a Path,
54    pub mmap: Arc<Mmap>,
55    pub offset: u64,
56    pub len: usize,
57    pub on_progress: Option<&'a (dyn Fn(usize, usize) + Sync)>,
58    pub residency: Option<&'a PM>,
59}
60
61impl<PM: PageMap> std::fmt::Debug for FileContext<'_, PM> {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        f.debug_struct("FileContext")
64            .field("path", &self.path)
65            .field("offset", &self.offset)
66            .field("len", &self.len)
67            .finish()
68    }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73pub struct FileRange {
74    pub offset: u64,
75    pub max_len: Option<u64>,
76}
77
78impl FileRange {
79    pub fn is_full_file(&self) -> bool {
80        self.offset == 0 && self.max_len.is_none()
81    }
82}
83
84#[derive(Debug, Clone, PartialEq)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
86pub struct FileInfo<PM = DefaultPageMap> {
87    pub total_pages: usize,
88    pub residency: PM,
89}
90
91#[derive(Debug)]
92pub struct Stats {
93    pub total_pages: AtomicUsize,
94    pub initial_pages_in_core: AtomicUsize,
95    pub action_pages: AtomicUsize,
96    pub total_files: AtomicUsize,
97    pub total_dirs: AtomicUsize,
98}
99
100impl Default for Stats {
101    fn default() -> Self {
102        Self::new()
103    }
104}
105
106impl Stats {
107    pub fn new() -> Self {
108        Self {
109            total_pages: AtomicUsize::new(0),
110            initial_pages_in_core: AtomicUsize::new(0),
111            action_pages: AtomicUsize::new(0),
112            total_files: AtomicUsize::new(0),
113            total_dirs: AtomicUsize::new(0),
114        }
115    }
116}