disklayer_sqlite/
auto_cache.rs1use crate::FormatParams;
8use crate::SqliteDiskLayer;
9use anyhow::Context;
10use disk_layered::LayerAttach;
11use disk_layered::LayerIo;
12use fs_err::PathExt;
13use std::path::PathBuf;
14
15pub struct AutoCacheSqliteDiskLayer {
16 path: PathBuf,
17 key: Option<String>,
18 read_only: bool,
19}
20
21impl AutoCacheSqliteDiskLayer {
22 pub fn new(path: PathBuf, key: Option<String>, read_only: bool) -> Self {
23 Self {
24 path,
25 key,
26 read_only,
27 }
28 }
29}
30
31impl LayerAttach for AutoCacheSqliteDiskLayer {
32 type Error = anyhow::Error;
33 type Layer = SqliteDiskLayer;
34
35 async fn attach(
36 self,
37 lower_layer_metadata: Option<disk_layered::DiskLayerMetadata>,
38 ) -> Result<Self::Layer, Self::Error> {
39 let metadata = lower_layer_metadata.context("no layer to cache")?;
40 let key = self.key.map_or_else(
41 || {
42 let disk_id = metadata
43 .disk_id
44 .context("cannot cache without a disk ID to use as a key")?;
45 Ok(disk_id.map(|b| format!("{b:2x}")).join(""))
46 },
47 anyhow::Ok,
48 )?;
49 if key.is_empty() {
50 anyhow::bail!("empty cache key");
51 }
52 let path = self.path.join(key).join("cache.dbhd");
53 let format_dbhd = if path.fs_err_try_exists()? || self.read_only {
54 None
55 } else {
56 fs_err::create_dir_all(path.parent().unwrap())?;
57 Some(FormatParams {
58 logically_read_only: true,
59 len: metadata.sector_count * metadata.sector_size as u64,
60 sector_size: metadata.sector_size,
61 })
62 };
63 let layer = SqliteDiskLayer::new(&path, self.read_only, format_dbhd)?;
64 if layer.sector_count() != metadata.sector_count {
65 anyhow::bail!(
66 "cache layer has different sector count: {} vs {}",
67 layer.sector_count(),
68 metadata.sector_count
69 );
70 }
71 Ok(layer)
72 }
73}