iota_storage/
package_object_cache.rs1use std::{num::NonZeroUsize, sync::Arc};
6
7use iota_types::{
8 base_types::ObjectID,
9 error::{IotaError, IotaResult, UserInputError},
10 storage::{ObjectStore, PackageObject},
11};
12use lru::LruCache;
13use parking_lot::RwLock;
14
15pub struct PackageObjectCache {
16 cache: RwLock<LruCache<ObjectID, PackageObject>>,
17}
18
19const CACHE_CAP: usize = 1024 * 1024;
20
21impl PackageObjectCache {
22 pub fn new() -> Arc<Self> {
23 Arc::new(Self {
24 cache: RwLock::new(LruCache::new(NonZeroUsize::new(CACHE_CAP).unwrap())),
25 })
26 }
27
28 pub fn get_package_object(
29 &self,
30 package_id: &ObjectID,
31 store: &impl ObjectStore,
32 ) -> IotaResult<Option<PackageObject>> {
33 if let Some(p) = self.cache.read().peek(package_id) {
39 #[cfg(debug_assertions)]
40 {
41 assert_eq!(
42 store.get_object(package_id).unwrap().unwrap().digest(),
43 p.object().digest(),
44 "Package object cache is inconsistent for package {:?}",
45 package_id
46 )
47 }
48 return Ok(Some(p.clone()));
49 }
50 if let Some(p) = store.get_object(package_id)? {
51 if p.is_package() {
52 let p = PackageObject::new(p);
53 self.cache.write().push(*package_id, p.clone());
54 Ok(Some(p))
55 } else {
56 Err(IotaError::UserInput {
57 error: UserInputError::MoveObjectAsPackage {
58 object_id: *package_id,
59 },
60 })
61 }
62 } else {
63 Ok(None)
64 }
65 }
66
67 pub fn force_reload_system_packages(
68 &self,
69 system_package_ids: impl IntoIterator<Item = ObjectID>,
70 store: &impl ObjectStore,
71 ) {
72 for package_id in system_package_ids {
73 if let Some(p) = store
74 .get_object(&package_id)
75 .expect("Failed to update system packages")
76 {
77 assert!(p.is_package());
78 self.cache.write().push(package_id, PackageObject::new(p));
79 }
80 }
84 }
85}