tiger_pkg/manager/
lookup_cache.rs

1use itertools::MultiUnzip;
2use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
3use tracing::{debug_span, error, info};
4
5use super::{PackageManager, TagLookupIndex};
6use crate::{manager::HashTableEntryShort, Version};
7
8impl PackageManager {
9    // const LOOKUP_CACHE_VERSION: u32 = 1;
10
11    #[cfg(feature = "ignore_lookup_cache")]
12    pub(super) fn read_lookup_cache(&self) -> Option<TagLookupIndex> {
13        info!("Not loading tag cache: ignore_lookup_cache feature flag is set");
14        None
15    }
16
17    #[cfg(feature = "ignore_lookup_cache")]
18    pub(super) fn write_lookup_cache(&self) -> anyhow::Result<()> {
19        Ok(())
20    }
21
22    #[cfg(not(feature = "ignore_lookup_cache"))]
23    pub(super) fn read_lookup_cache(&self) -> Option<TagLookupIndex> {
24        use std::io::Read;
25
26        use crate::manager::path_cache::exe_relative_path;
27
28        let mut file = std::fs::File::open(exe_relative_path(&format!(
29            "lookup_cache_{}.bin",
30            self.cache_key()
31        )))
32        .ok()?;
33
34        let mut cache_data = Vec::new();
35        file.read_to_end(&mut cache_data).ok()?;
36
37        info!("Loading index cache");
38
39        let cache: Option<TagLookupIndex> =
40            bincode::decode_from_slice(&cache_data, bincode::config::standard())
41                .map(|(v, _)| v)
42                .ok();
43
44        cache
45    }
46
47    #[cfg(not(feature = "ignore_lookup_cache"))]
48    pub(super) fn write_lookup_cache(&self) -> anyhow::Result<()> {
49        use super::path_cache::exe_relative_path;
50
51        Ok(std::fs::write(
52            exe_relative_path(&format!("lookup_cache_{}.bin", self.cache_key())),
53            bincode::encode_to_vec(&self.lookup, bincode::config::standard())?,
54        )?)
55    }
56
57    pub fn build_lookup_tables(&mut self) {
58        let start = std::time::Instant::now();
59        let tables: Vec<_> = self
60            .package_paths
61            .par_iter()
62            .filter_map(|(_, p)| {
63                let _span = debug_span!("Read package tables", package = p.path).entered();
64                let pkg = match self.version.open(&p.path) {
65                    Ok(package) => package,
66                    Err(e) => {
67                        error!("Failed to open package '{}': {e}", p.filename);
68                        return None;
69                    }
70                };
71                let entries = (pkg.pkg_id(), pkg.entries().to_vec());
72
73                let collect = pkg
74                    .hash64_table()
75                    .iter()
76                    .map(|h| {
77                        (
78                            h.hash64,
79                            HashTableEntryShort {
80                                hash32: h.hash32,
81                                reference: h.reference,
82                            },
83                        )
84                    })
85                    .collect::<Vec<(u64, HashTableEntryShort)>>();
86                let hashes = collect;
87
88                let named_tags = pkg.named_tags();
89
90                Some((entries, hashes, named_tags))
91            })
92            .collect();
93
94        let (entries, hashes, named_tags): (_, Vec<_>, Vec<_>) = tables.into_iter().multiunzip();
95
96        self.lookup = TagLookupIndex {
97            tag32_entries_by_pkg: entries,
98            tag64_entries: hashes.into_iter().flatten().collect(),
99            named_tags: named_tags.into_iter().flatten().collect(),
100        };
101
102        info!(
103            "Built lookup table for {} packages in {:?}",
104            self.lookup.tag32_entries_by_pkg.len(),
105            start.elapsed()
106        );
107    }
108}