drive/cache/
protocol_version.rs1use crate::drive::Drive;
2use crate::error::cache::CacheError;
3use crate::error::Error;
4use dpp::util::deserializer::ProtocolVersion;
5use grovedb::TransactionArg;
6use nohash_hasher::IntMap;
7use platform_version::version::drive_versions::DriveVersion;
8
9#[derive(Default)]
11pub struct ProtocolVersionsCache {
12 pub global_cache: IntMap<ProtocolVersion, u64>,
16 block_cache: IntMap<ProtocolVersion, u64>,
17 loaded: bool,
18 is_global_cache_blocked: bool,
19}
20
21#[cfg(feature = "server")]
22impl ProtocolVersionsCache {
23 pub fn new() -> Self {
25 Self::default()
26 }
27
28 pub fn load_if_needed(
30 &mut self,
31 drive: &Drive,
32 transaction: TransactionArg,
33 drive_version: &DriveVersion,
34 ) -> Result<(), Error> {
35 if !self.loaded {
36 self.global_cache = drive.fetch_versions_with_counter(transaction, drive_version)?;
37 self.loaded = true;
38 };
39 Ok(())
40 }
41
42 pub fn set_block_cache_version_count(&mut self, version: ProtocolVersion, count: u64) {
44 self.block_cache.insert(version, count);
45 }
46
47 pub fn get(&self, version: &ProtocolVersion) -> Result<Option<&u64>, Error> {
51 if self.is_global_cache_blocked {
52 return Err(Error::Cache(CacheError::GlobalCacheIsBlocked));
53 }
54
55 let counter = if let Some(count) = self.block_cache.get(version) {
56 Some(count)
57 } else {
58 self.global_cache.get(version)
59 };
60
61 Ok(counter)
62 }
63
64 pub fn block_global_cache(&mut self) {
67 self.is_global_cache_blocked = true;
68 }
69
70 pub fn unblock_global_cache(&mut self) {
73 self.is_global_cache_blocked = false;
74 }
75
76 pub fn merge_block_cache(&mut self) {
78 self.global_cache.extend(self.block_cache.drain());
79 }
80
81 pub fn clear_global_cache(&mut self) {
83 self.global_cache.clear();
84 }
85
86 pub fn clear_block_cache(&mut self) {
88 self.block_cache.clear()
89 }
90
91 pub fn versions_passing_threshold(&self, required_upgraded_hpmns: u64) -> Vec<ProtocolVersion> {
93 let mut cache = self.global_cache.clone();
94
95 cache.extend(self.block_cache.iter());
96 cache
97 .into_iter()
98 .filter_map(|(protocol_version, count)| {
99 if count >= required_upgraded_hpmns {
100 Some(protocol_version)
101 } else {
102 None
103 }
104 })
105 .collect::<Vec<ProtocolVersion>>()
106 }
107}