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}