From 7b24cae8b1d5c935efd18e6b25dcc1f989e15907 Mon Sep 17 00:00:00 2001 From: Leo-Besancon Date: Tue, 17 Dec 2024 09:57:53 +0100 Subject: [PATCH 1/7] Reset cache if version becomes active --- massa-execution-worker/src/execution.rs | 12 +++++++ massa-module-cache/src/controller.rs | 5 +++ massa-module-cache/src/hd_cache.rs | 42 +++++++++++++++++++++---- massa-module-cache/src/lru_cache.rs | 4 +++ 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index 1bcea890cf9..6ecabd6b84b 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -140,6 +140,7 @@ pub(crate) struct ExecutionState { pub(crate) execution_info: Arc>, #[cfg(feature = "dump-block")] block_storage_backend: Arc>, + cur_execution_version: u32, } impl ExecutionState { @@ -197,6 +198,11 @@ impl ExecutionState { execution_trail_hash, ))); + let cur_execution_version; + { + cur_execution_version = execution_context.lock().execution_component_version; + } + // Instantiate the interface providing ABI access to the VM, share the execution context with it let execution_interface = Box::new(InterfaceImpl::new( config.clone(), @@ -238,6 +244,7 @@ impl ExecutionState { config, #[cfg(feature = "dump-block")] block_storage_backend, + cur_execution_version, } } @@ -1488,6 +1495,11 @@ impl ExecutionState { ); let execution_version = execution_context.execution_component_version; + if self.cur_execution_version != execution_version { + // Reset the cache because a new execution version has become active + self.module_cache.write().reset(); + self.cur_execution_version = execution_version; + } let mut deferred_calls_slot_gas = 0; diff --git a/massa-module-cache/src/controller.rs b/massa-module-cache/src/controller.rs index ca877615410..c6605366ec0 100644 --- a/massa-module-cache/src/controller.rs +++ b/massa-module-cache/src/controller.rs @@ -39,6 +39,11 @@ impl ModuleCache { } } + pub fn reset(&mut self) { + self.lru_cache.reset(); + self.hd_cache.reset(); + } + /// Internal function to compile and build `ModuleInfo` fn compile_cached( &mut self, diff --git a/massa-module-cache/src/hd_cache.rs b/massa-module-cache/src/hd_cache.rs index b5a8ed91ff0..b4e70dfe75f 100644 --- a/massa-module-cache/src/hd_cache.rs +++ b/massa-module-cache/src/hd_cache.rs @@ -5,7 +5,7 @@ use massa_hash::Hash; use massa_sc_runtime::{CondomLimits, GasCosts, RuntimeModule}; use massa_serialization::{DeserializeError, Deserializer, Serializer}; use rand::RngCore; -use rocksdb::{Direction, IteratorMode, WriteBatch, DB}; +use rocksdb::{Direction, IteratorMode, Options, WriteBatch, DB}; use std::path::PathBuf; use tracing::debug; @@ -36,7 +36,7 @@ macro_rules! metadata_key { pub(crate) struct HDCache { /// RocksDB database - db: DB, + db: Option, /// How many entries are in the db. Count is initialized at creation time by iterating /// over all the entries in the db then it is maintained in memory entry_count: usize, @@ -63,7 +63,7 @@ impl HDCache { let entry_count = db.iterator(IteratorMode::Start).count(); Self { - db, + db: Some(db), entry_count, max_entry_count, snip_amount, @@ -72,6 +72,22 @@ impl HDCache { } } + pub fn reset(&mut self) { + let path = self.db.as_ref().unwrap().path().to_path_buf(); + + // Close the existing database + self.db.take(); + + // Destroy the database files + let opts = Options::default(); + DB::destroy(&opts, &path).expect("Failed to destroy the database"); + // Reopen the database + let db = DB::open_default(&path).expect(OPEN_ERROR); + let entry_count = db.iterator(IteratorMode::Start).count(); + self.db = Some(db); + self.entry_count = entry_count; + } + /// Insert a new module in the cache pub fn insert(&mut self, hash: Hash, module_info: ModuleInfo) { if self.entry_count >= self.max_entry_count { @@ -103,7 +119,11 @@ impl HDCache { let mut batch = WriteBatch::default(); batch.put(module_key!(hash), ser_module); batch.put(metadata_key!(hash), ser_metadata); - self.db.write(batch).expect(CRUD_ERROR); + self.db + .as_ref() + .expect(CRUD_ERROR) + .write(batch) + .expect(CRUD_ERROR); self.entry_count = self.entry_count.saturating_add(1); @@ -121,6 +141,8 @@ impl HDCache { .serialize(&ModuleMetadata::Delta(init_cost), &mut ser_metadata) .expect(DATA_SER_ERROR); self.db + .as_ref() + .expect(CRUD_ERROR) .put(metadata_key!(hash), ser_metadata) .expect(CRUD_ERROR); } @@ -132,6 +154,8 @@ impl HDCache { .serialize(&ModuleMetadata::Invalid(err_msg), &mut ser_metadata) .expect(DATA_SER_ERROR); self.db + .as_ref() + .expect(CRUD_ERROR) .put(metadata_key!(hash), ser_metadata) .expect(CRUD_ERROR); } @@ -145,6 +169,8 @@ impl HDCache { ) -> Option { let mut iterator = self .db + .as_ref() + .expect(CRUD_ERROR) .iterator(IteratorMode::From(&module_key!(hash), Direction::Forward)); if let (Some(Ok((key_1, ser_module))), Some(Ok((key_2, ser_metadata)))) = @@ -181,7 +207,7 @@ impl HDCache { /// Try to remove as much as `self.amount_to_snip` entries from the db fn snip(&mut self) { - let mut iter = self.db.raw_iterator(); + let mut iter = self.db.as_ref().expect(CRUD_ERROR).raw_iterator(); let mut batch = WriteBatch::default(); let mut snipped_count: usize = 0; @@ -218,7 +244,11 @@ impl HDCache { } // delete the key and reduce entry_count - self.db.write(batch).expect(CRUD_ERROR); + self.db + .as_ref() + .expect(CRUD_ERROR) + .write(batch) + .expect(CRUD_ERROR); self.entry_count -= snipped_count; } } diff --git a/massa-module-cache/src/lru_cache.rs b/massa-module-cache/src/lru_cache.rs index a6ea66eeea8..af810a8f71b 100644 --- a/massa-module-cache/src/lru_cache.rs +++ b/massa-module-cache/src/lru_cache.rs @@ -27,6 +27,10 @@ impl LRUCache { } } + pub fn reset(&mut self) { + self.cache.clear(); + } + /// If the module is contained in the cache: /// * retrieve a copy of it /// * move it up in the LRU cache From d7e2583021def985d61550d30946075498545865 Mon Sep 17 00:00:00 2001 From: Leo-Besancon Date: Tue, 17 Dec 2024 10:10:37 +0100 Subject: [PATCH 2/7] add &mut + cargo fmt --- massa-execution-worker/src/execution.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index 6ecabd6b84b..a2069fdd0f7 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -201,7 +201,7 @@ impl ExecutionState { let cur_execution_version; { cur_execution_version = execution_context.lock().execution_component_version; - } + } // Instantiate the interface providing ABI access to the VM, share the execution context with it let execution_interface = Box::new(InterfaceImpl::new( @@ -1465,7 +1465,7 @@ impl ExecutionState { /// # Returns /// An `ExecutionOutput` structure summarizing the output of the executed slot pub fn execute_slot( - &self, + &mut self, slot: &Slot, exec_target: Option<&(BlockId, ExecutionBlockMetadata)>, selector: Box, From e2ab744551bcc5799f96e44fc7133560b6d5806d Mon Sep 17 00:00:00 2001 From: Leo-Besancon Date: Wed, 18 Dec 2024 08:48:49 +0100 Subject: [PATCH 3/7] Update massa-execution-worker/src/execution.rs Co-authored-by: Modship --- massa-execution-worker/src/execution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index a2069fdd0f7..a7b886e01e8 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -198,7 +198,7 @@ impl ExecutionState { execution_trail_hash, ))); - let cur_execution_version; + let cur_execution_version = execution_context.lock().execution_component_version; { cur_execution_version = execution_context.lock().execution_component_version; } From 623c7a8f3688653b86d2d003abc64f4672ea3eaa Mon Sep 17 00:00:00 2001 From: Leo-Besancon Date: Wed, 18 Dec 2024 08:49:49 +0100 Subject: [PATCH 4/7] Update execution.rs --- massa-execution-worker/src/execution.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index a7b886e01e8..438f72f5f7c 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -199,9 +199,6 @@ impl ExecutionState { ))); let cur_execution_version = execution_context.lock().execution_component_version; - { - cur_execution_version = execution_context.lock().execution_component_version; - } // Instantiate the interface providing ABI access to the VM, share the execution context with it let execution_interface = Box::new(InterfaceImpl::new( From 7cdcbac3699b011b2d1822ffeb679fa5ca5fb5fd Mon Sep 17 00:00:00 2001 From: Leo-Besancon Date: Thu, 19 Dec 2024 11:40:10 +0100 Subject: [PATCH 5/7] Update hd_cache.rs --- massa-module-cache/src/hd_cache.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/massa-module-cache/src/hd_cache.rs b/massa-module-cache/src/hd_cache.rs index b4e70dfe75f..299029db095 100644 --- a/massa-module-cache/src/hd_cache.rs +++ b/massa-module-cache/src/hd_cache.rs @@ -75,17 +75,15 @@ impl HDCache { pub fn reset(&mut self) { let path = self.db.as_ref().unwrap().path().to_path_buf(); - // Close the existing database - self.db.take(); + // Close the existing database by dropping it + let _ = self.db.take(); // Destroy the database files - let opts = Options::default(); - DB::destroy(&opts, &path).expect("Failed to destroy the database"); + DB::destroy(&Options::default(), &path).expect("Failed to destroy the database"); // Reopen the database let db = DB::open_default(&path).expect(OPEN_ERROR); - let entry_count = db.iterator(IteratorMode::Start).count(); self.db = Some(db); - self.entry_count = entry_count; + self.entry_count = 0; } /// Insert a new module in the cache From b1c8da30b72d567c9c92094c26c1bdcc824e7cde Mon Sep 17 00:00:00 2001 From: Leo-Besancon Date: Thu, 19 Dec 2024 14:17:14 +0100 Subject: [PATCH 6/7] Avoid taking a lock --- massa-execution-worker/src/execution.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index 438f72f5f7c..c6b77608076 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -189,16 +189,16 @@ impl ExecutionState { }))); // Create an empty placeholder execution context, with shared atomic access - let execution_context = Arc::new(Mutex::new(ExecutionContext::new( + let unwrapped_execution_context = ExecutionContext::new( config.clone(), final_state.clone(), active_history.clone(), module_cache.clone(), mip_store.clone(), execution_trail_hash, - ))); - - let cur_execution_version = execution_context.lock().execution_component_version; + ); + let cur_execution_version = unwrapped_execution_context.execution_component_version; + let execution_context = Arc::new(Mutex::new(unwrapped_execution_context)); // Instantiate the interface providing ABI access to the VM, share the execution context with it let execution_interface = Box::new(InterfaceImpl::new( From 975f87f5b7a6437d932210790d52a639b5f6ca4e Mon Sep 17 00:00:00 2001 From: Leo-Besancon Date: Thu, 19 Dec 2024 18:22:30 +0100 Subject: [PATCH 7/7] Rename + add info!() on cache reset --- massa-execution-worker/src/execution.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index c6b77608076..2f59093083f 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -189,7 +189,7 @@ impl ExecutionState { }))); // Create an empty placeholder execution context, with shared atomic access - let unwrapped_execution_context = ExecutionContext::new( + let execution_context = ExecutionContext::new( config.clone(), final_state.clone(), active_history.clone(), @@ -197,8 +197,8 @@ impl ExecutionState { mip_store.clone(), execution_trail_hash, ); - let cur_execution_version = unwrapped_execution_context.execution_component_version; - let execution_context = Arc::new(Mutex::new(unwrapped_execution_context)); + let cur_execution_version = execution_context.execution_component_version; + let execution_context = Arc::new(Mutex::new(execution_context)); // Instantiate the interface providing ABI access to the VM, share the execution context with it let execution_interface = Box::new(InterfaceImpl::new( @@ -1494,6 +1494,7 @@ impl ExecutionState { let execution_version = execution_context.execution_component_version; if self.cur_execution_version != execution_version { // Reset the cache because a new execution version has become active + info!("A new execution version has become active! Resetting the module-cache."); self.module_cache.write().reset(); self.cur_execution_version = execution_version; }