Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return loaded program entry from the cache after insert #30336

Merged
merged 2 commits into from
Feb 16, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 58 additions & 35 deletions program-runtime/src/loaded_programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,14 @@ impl solana_frozen_abi::abi_example::AbiExample for LoadedPrograms {
}
}

pub enum LoadedProgramEntry {
WasOccupied(Arc<LoadedProgram>),
WasVacant(Arc<LoadedProgram>),
}

impl LoadedPrograms {
/// Inserts a single entry
pub fn insert_entry(&mut self, key: Pubkey, entry: LoadedProgram) -> bool {
pub fn insert_entry(&mut self, key: Pubkey, entry: LoadedProgram) -> LoadedProgramEntry {
let second_level = self.entries.entry(key).or_insert_with(Vec::new);
let index = second_level
.iter()
Expand All @@ -154,11 +159,12 @@ impl LoadedPrograms {
if existing.deployment_slot == entry.deployment_slot
&& existing.effective_slot == entry.effective_slot
{
return false;
return LoadedProgramEntry::WasOccupied(existing.clone());
}
}
second_level.insert(index.unwrap_or(second_level.len()), Arc::new(entry));
true
let new_entry = Arc::new(entry);
second_level.insert(index.unwrap_or(second_level.len()), new_entry.clone());
LoadedProgramEntry::WasVacant(new_entry)
}

/// Before rerooting the blockstore this removes all programs of orphan forks
Expand Down Expand Up @@ -228,7 +234,8 @@ impl LoadedPrograms {
mod tests {
use {
crate::loaded_programs::{
BlockRelation, ForkGraph, LoadedProgram, LoadedProgramType, LoadedPrograms, WorkingSlot,
BlockRelation, ForkGraph, LoadedProgram, LoadedProgramEntry, LoadedProgramType,
LoadedPrograms, WorkingSlot,
},
solana_sdk::{clock::Slot, pubkey::Pubkey},
std::{
Expand Down Expand Up @@ -377,14 +384,14 @@ mod tests {
}
}

fn new_test_loaded_program(deployment_slot: Slot, effective_slot: Slot) -> Arc<LoadedProgram> {
Arc::new(LoadedProgram {
fn new_test_loaded_program(deployment_slot: Slot, effective_slot: Slot) -> LoadedProgram {
LoadedProgram {
program: LoadedProgramType::Invalid,
account_size: 0,
deployment_slot,
effective_slot,
usage_counter: AtomicU64::default(),
})
}
}

fn match_slot(
Expand Down Expand Up @@ -423,39 +430,55 @@ mod tests {
fork_graph.insert_fork(&[0, 5, 11, 25, 27]);

let program1 = Pubkey::new_unique();
cache.entries.insert(
program1,
vec![
new_test_loaded_program(0, 1),
new_test_loaded_program(10, 11),
new_test_loaded_program(20, 21),
],
);
assert!(matches!(
cache.insert_entry(program1, new_test_loaded_program(0, 1)),
LoadedProgramEntry::WasVacant(_)
));
assert!(matches!(
cache.insert_entry(program1, new_test_loaded_program(10, 11)),
LoadedProgramEntry::WasVacant(_)
));
assert!(matches!(
cache.insert_entry(program1, new_test_loaded_program(20, 21)),
LoadedProgramEntry::WasVacant(_)
));

// Test: inserting duplicate entry return pre existing entry from the cache
assert!(matches!(
cache.insert_entry(program1, new_test_loaded_program(20, 21)),
LoadedProgramEntry::WasOccupied(_)
));

let program2 = Pubkey::new_unique();
cache.entries.insert(
program2,
vec![
new_test_loaded_program(5, 6),
new_test_loaded_program(11, 12),
],
);
assert!(matches!(
cache.insert_entry(program2, new_test_loaded_program(5, 6)),
LoadedProgramEntry::WasVacant(_)
));
assert!(matches!(
cache.insert_entry(program2, new_test_loaded_program(11, 12)),
LoadedProgramEntry::WasVacant(_)
));

let program3 = Pubkey::new_unique();
cache
.entries
.insert(program3, vec![new_test_loaded_program(25, 26)]);
assert!(matches!(
cache.insert_entry(program3, new_test_loaded_program(25, 26)),
LoadedProgramEntry::WasVacant(_)
));

let program4 = Pubkey::new_unique();
cache.entries.insert(
program4,
vec![
new_test_loaded_program(0, 1),
new_test_loaded_program(5, 6),
// The following is a special case, where effective slot is 4 slots in the future
new_test_loaded_program(15, 19),
],
);
assert!(matches!(
cache.insert_entry(program4, new_test_loaded_program(0, 1)),
LoadedProgramEntry::WasVacant(_)
));
assert!(matches!(
cache.insert_entry(program4, new_test_loaded_program(5, 6)),
LoadedProgramEntry::WasVacant(_)
));
// The following is a special case, where effective slot is 4 slots in the future
assert!(matches!(
cache.insert_entry(program4, new_test_loaded_program(15, 19)),
LoadedProgramEntry::WasVacant(_)
));

// Current fork graph
// 0
Expand Down