Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit a2d6f6e

Browse files
committed
address review comments
1 parent c81967d commit a2d6f6e

File tree

4 files changed

+45
-40
lines changed

4 files changed

+45
-40
lines changed

program-runtime/src/executor_cache.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ impl TransactionExecutorCache {
4141
self.visible.get(key).cloned()
4242
}
4343

44-
pub fn set_tombstone(&mut self, key: Pubkey) {
44+
pub fn set_tombstone(&mut self, key: Pubkey, slot: Slot) {
4545
self.visible
46-
.insert(key, Arc::new(LoadedProgram::new_tombstone(0)));
46+
.insert(key, Arc::new(LoadedProgram::new_tombstone(slot)));
4747
}
4848

4949
pub fn set(
@@ -52,12 +52,13 @@ impl TransactionExecutorCache {
5252
executor: Arc<LoadedProgram>,
5353
upgrade: bool,
5454
delay_visibility_of_program_deployment: bool,
55+
slot: Slot,
5556
) {
5657
if upgrade {
5758
if delay_visibility_of_program_deployment {
5859
// Place a tombstone in the cache so that
5960
// we don't load the new version from the database as it should remain invisible
60-
self.set_tombstone(key);
61+
self.set_tombstone(key, slot);
6162
} else {
6263
self.visible.insert(key, executor.clone());
6364
}

program-runtime/src/loaded_programs.rs

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,12 @@ impl LoadedProgram {
180180
}
181181
}
182182

183-
pub fn new_tombstone(deployment_slot: Slot) -> Self {
183+
pub fn new_tombstone(slot: Slot) -> Self {
184184
Self {
185185
program: LoadedProgramType::Invalid,
186186
account_size: 0,
187-
deployment_slot,
188-
effective_slot: deployment_slot,
187+
deployment_slot: slot,
188+
effective_slot: slot,
189189
usage_counter: AtomicU64::default(),
190190
}
191191
}
@@ -219,8 +219,10 @@ pub enum LoadedProgramEntry {
219219
}
220220

221221
impl LoadedPrograms {
222-
/// Inserts a single entry
223-
pub fn insert_entry(&mut self, key: Pubkey, entry: Arc<LoadedProgram>) -> LoadedProgramEntry {
222+
/// Refill the cache with a single entry. It's typically called during transaction processing,
223+
/// when the cache doesn't contain the entry corresponding to program `key`.
224+
/// The function dedupes the cache, in case some other thread replenished the the entry in parallel.
225+
pub fn replenish(&mut self, key: Pubkey, entry: Arc<LoadedProgram>) -> LoadedProgramEntry {
224226
let second_level = self.entries.entry(key).or_insert_with(Vec::new);
225227
let index = second_level
226228
.iter()
@@ -239,29 +241,28 @@ impl LoadedPrograms {
239241
LoadedProgramEntry::WasVacant(entry)
240242
}
241243

242-
/// Insert or replace the current entry with a tombstone.
243-
/// This behaves differently than `insert_entry()` in case there's currently a program at the
244-
/// `deploytment_slot`. It'll replace the current entry with a tombstone, whereas `insert_entry()`
245-
/// would retain and return the current entry.
246-
pub fn set_tombstone(&mut self, key: Pubkey, deployment_slot: Slot) -> Arc<LoadedProgram> {
247-
let tombstone = Arc::new(LoadedProgram::new_tombstone(deployment_slot));
244+
/// Assign the program `entry` to the given `key` in the cache.
245+
/// This is typically called when a deployed program is managed (upgraded/un/reddeployed) via
246+
/// bpf loader instructions.
247+
/// The program management is not expected to overlap with initial program deployment slot.
248+
/// Note: Do not call this function to replenish cache with a missing entry. As that use-case can
249+
/// cause the cache to have duplicates. Use `replenish()` API for that use-case.
250+
pub fn assign_program(&mut self, key: Pubkey, entry: Arc<LoadedProgram>) -> Arc<LoadedProgram> {
248251
let second_level = self.entries.entry(key).or_insert_with(Vec::new);
249252
let index = second_level
250253
.iter()
251-
.position(|at| at.effective_slot >= tombstone.effective_slot);
254+
.position(|at| at.effective_slot >= entry.effective_slot);
252255
if let Some(index) = index {
253256
let existing = second_level
254257
.get(index)
255258
.expect("Missing entry, even though position was found");
256-
if existing.deployment_slot == tombstone.deployment_slot
257-
&& existing.effective_slot >= tombstone.effective_slot
258-
{
259-
second_level.splice(index..=index, [tombstone.clone()]);
260-
return tombstone;
261-
}
259+
assert!(
260+
existing.deployment_slot != entry.deployment_slot
261+
|| existing.effective_slot != entry.effective_slot
262+
);
262263
}
263-
second_level.insert(index.unwrap_or(second_level.len()), tombstone.clone());
264-
tombstone
264+
second_level.insert(index.unwrap_or(second_level.len()), entry.clone());
265+
entry
265266
}
266267

267268
/// Before rerooting the blockstore this removes all programs of orphan forks
@@ -369,7 +370,7 @@ mod tests {
369370

370371
let mut cache = LoadedPrograms::default();
371372
let program1 = Pubkey::new_unique();
372-
let tombstone = cache.set_tombstone(program1, 10);
373+
let tombstone = cache.assign_program(program1, 10);
373374
let second_level = &cache
374375
.entries
375376
.get(&program1)
@@ -382,7 +383,7 @@ mod tests {
382383
// Add a program at slot 50, and a tombstone for the program at slot 60
383384
let program2 = Pubkey::new_unique();
384385
assert!(matches!(
385-
cache.insert_entry(program2, new_test_builtin_program(50, 51)),
386+
cache.replenish(program2, new_test_builtin_program(50, 51)),
386387
LoadedProgramEntry::WasVacant(_)
387388
));
388389
let second_level = &cache
@@ -392,7 +393,7 @@ mod tests {
392393
assert_eq!(second_level.len(), 1);
393394
assert!(!second_level.get(0).unwrap().is_tombstone());
394395

395-
let tombstone = cache.set_tombstone(program2, 60);
396+
let tombstone = cache.assign_program(program2, 60);
396397
let second_level = &cache
397398
.entries
398399
.get(&program2)
@@ -405,7 +406,7 @@ mod tests {
405406
assert_eq!(tombstone.effective_slot, 60);
406407

407408
// Replace the program at slot 50 with a tombstone
408-
let tombstone = cache.set_tombstone(program2, 50);
409+
let tombstone = cache.assign_program(program2, 50);
409410
let second_level = &cache
410411
.entries
411412
.get(&program2)
@@ -604,52 +605,52 @@ mod tests {
604605

605606
let program1 = Pubkey::new_unique();
606607
assert!(matches!(
607-
cache.insert_entry(program1, new_test_loaded_program(0, 1)),
608+
cache.replenish(program1, new_test_loaded_program(0, 1)),
608609
LoadedProgramEntry::WasVacant(_)
609610
));
610611
assert!(matches!(
611-
cache.insert_entry(program1, new_test_loaded_program(10, 11)),
612+
cache.replenish(program1, new_test_loaded_program(10, 11)),
612613
LoadedProgramEntry::WasVacant(_)
613614
));
614615
assert!(matches!(
615-
cache.insert_entry(program1, new_test_loaded_program(20, 21)),
616+
cache.replenish(program1, new_test_loaded_program(20, 21)),
616617
LoadedProgramEntry::WasVacant(_)
617618
));
618619

619620
// Test: inserting duplicate entry return pre existing entry from the cache
620621
assert!(matches!(
621-
cache.insert_entry(program1, new_test_loaded_program(20, 21)),
622+
cache.replenish(program1, new_test_loaded_program(20, 21)),
622623
LoadedProgramEntry::WasOccupied(_)
623624
));
624625

625626
let program2 = Pubkey::new_unique();
626627
assert!(matches!(
627-
cache.insert_entry(program2, new_test_loaded_program(5, 6)),
628+
cache.replenish(program2, new_test_loaded_program(5, 6)),
628629
LoadedProgramEntry::WasVacant(_)
629630
));
630631
assert!(matches!(
631-
cache.insert_entry(program2, new_test_loaded_program(11, 12)),
632+
cache.replenish(program2, new_test_loaded_program(11, 12)),
632633
LoadedProgramEntry::WasVacant(_)
633634
));
634635

635636
let program3 = Pubkey::new_unique();
636637
assert!(matches!(
637-
cache.insert_entry(program3, new_test_loaded_program(25, 26)),
638+
cache.replenish(program3, new_test_loaded_program(25, 26)),
638639
LoadedProgramEntry::WasVacant(_)
639640
));
640641

641642
let program4 = Pubkey::new_unique();
642643
assert!(matches!(
643-
cache.insert_entry(program4, new_test_loaded_program(0, 1)),
644+
cache.replenish(program4, new_test_loaded_program(0, 1)),
644645
LoadedProgramEntry::WasVacant(_)
645646
));
646647
assert!(matches!(
647-
cache.insert_entry(program4, new_test_loaded_program(5, 6)),
648+
cache.replenish(program4, new_test_loaded_program(5, 6)),
648649
LoadedProgramEntry::WasVacant(_)
649650
));
650651
// The following is a special case, where effective slot is 4 slots in the future
651652
assert!(matches!(
652-
cache.insert_entry(program4, new_test_loaded_program(15, 19)),
653+
cache.replenish(program4, new_test_loaded_program(15, 19)),
653654
LoadedProgramEntry::WasVacant(_)
654655
));
655656

programs/bpf_loader/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ pub fn load_program_from_account(
258258
loaded_program.clone(),
259259
false,
260260
feature_set.is_active(&delay_visibility_of_program_deployment::id()),
261+
deployment_slot,
261262
);
262263
}
263264

@@ -291,6 +292,7 @@ macro_rules! deploy_program {
291292
Arc::new(executor),
292293
true,
293294
delay_visibility_of_program_deployment,
295+
$slot,
294296
);
295297
}};
296298
}
@@ -1183,10 +1185,11 @@ fn process_loader_upgradeable_instruction(
11831185
.feature_set
11841186
.is_active(&delay_visibility_of_program_deployment::id())
11851187
{
1188+
let clock = invoke_context.get_sysvar_cache().get_clock()?;
11861189
invoke_context
11871190
.tx_executor_cache
11881191
.borrow_mut()
1189-
.set_tombstone(program_key);
1192+
.set_tombstone(program_key, clock.slot);
11901193
}
11911194
}
11921195
_ => {

runtime/src/bank.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4375,7 +4375,7 @@ impl Bank {
43754375
.loaded_programs_cache
43764376
.write()
43774377
.unwrap()
4378-
.insert_entry(*pubkey, program)
4378+
.replenish(*pubkey, program)
43794379
{
43804380
LoadedProgramEntry::WasOccupied(entry) => {
43814381
loaded_programs_for_txs.insert(*pubkey, entry);
@@ -4393,7 +4393,7 @@ impl Bank {
43934393
.loaded_programs_cache
43944394
.write()
43954395
.unwrap()
4396-
.set_tombstone(*pubkey, self.slot);
4396+
.assign_program(*pubkey, Arc::new(LoadedProgram::new_tombstone(self.slot)));
43974397
loaded_programs_for_txs.insert(*pubkey, tombstone);
43984398
}
43994399
});

0 commit comments

Comments
 (0)