tiger_pkg/manager/
lookup_cache.rs

1use itertools::MultiUnzip;
2use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
3use tracing::{error, info};
4
5use super::{PackageManager, TagLookupIndex};
6use crate::{manager::HashTableEntryShort, TagHash64, 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 pkg = match self.version.open(&p.path) {
64                    Ok(package) => package,
65                    Err(e) => {
66                        error!("Failed to open package '{}': {e}", p.filename);
67                        return None;
68                    }
69                };
70                let entries = (pkg.pkg_id(), pkg.entries().to_vec());
71
72                let collect = pkg
73                    .hash64_table()
74                    .iter()
75                    .map(|h| {
76                        (
77                            h.hash64,
78                            HashTableEntryShort {
79                                hash32: h.hash32,
80                                reference: h.reference,
81                            },
82                        )
83                    })
84                    .collect::<Vec<(u64, HashTableEntryShort)>>();
85                let hashes = collect;
86
87                let named_tags = pkg.named_tags();
88
89                Some((entries, hashes, named_tags))
90            })
91            .collect();
92
93        let (entries, hashes, named_tags): (_, Vec<_>, Vec<_>) = tables.into_iter().multiunzip();
94
95        self.lookup = TagLookupIndex {
96            tag32_entries_by_pkg: entries,
97            tag32_to_tag64: hashes
98                .iter()
99                .flatten()
100                .map(|(h64, entry)| (entry.hash32, TagHash64(*h64)))
101                .collect(),
102            tag64_entries: hashes.into_iter().flatten().collect(),
103            named_tags: named_tags.into_iter().flatten().collect(),
104        };
105
106        info!(
107            "Built lookup table for {} packages in {:?}",
108            self.lookup.tag32_entries_by_pkg.len(),
109            start.elapsed()
110        );
111    }
112}