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 {package_id:?}"
45 )
46 }
47 return Ok(Some(p.clone()));
48 }
49 if let Some(p) = store.get_object(package_id)? {
50 if p.is_package() {
51 let p = PackageObject::new(p);
52 self.cache.write().push(*package_id, p.clone());
53 Ok(Some(p))
54 } else {
55 Err(IotaError::UserInput {
56 error: UserInputError::MoveObjectAsPackage {
57 object_id: *package_id,
58 },
59 })
60 }
61 } else {
62 Ok(None)
63 }
64 }
65
66 pub fn force_reload_system_packages(
67 &self,
68 system_package_ids: impl IntoIterator<Item = ObjectID>,
69 store: &impl ObjectStore,
70 ) {
71 for package_id in system_package_ids {
72 if let Some(p) = store
73 .get_object(&package_id)
74 .expect("Failed to update system packages")
75 {
76 assert!(p.is_package());
77 self.cache.write().push(package_id, PackageObject::new(p));
78 }
79 }
83 }
84}