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