replace num_blocks with parent block
This commit is contained in:
parent
736f08815e
commit
de6109c599
117
src/blocktree.rs
117
src/blocktree.rs
|
@ -23,7 +23,6 @@ use std::cell::RefCell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::iter::once;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
||||||
|
@ -131,12 +130,10 @@ pub struct SlotMeta {
|
||||||
pub consumed: u64,
|
pub consumed: u64,
|
||||||
// The entry height of the highest blob received for this slot.
|
// The entry height of the highest blob received for this slot.
|
||||||
pub received: u64,
|
pub received: u64,
|
||||||
// The number of ticks in the range [0..consumed]. Used to detect when
|
// The index of the blob that is flagged as the last blob for this slot
|
||||||
// a slot contains all expected ticks, so that components like repair/ReplayStage
|
pub last_index: u64,
|
||||||
// know to look at the next slot.
|
// The parent slot of this slot
|
||||||
pub consumed_ticks: u64,
|
pub parent_slot: u64,
|
||||||
// The number of blocks in this slot
|
|
||||||
pub num_blocks: u64,
|
|
||||||
// The list of slots that chains to this slot
|
// The list of slots that chains to this slot
|
||||||
pub next_slots: Vec<u64>,
|
pub next_slots: Vec<u64>,
|
||||||
// True if every block from 0..slot, where slot is the slot index of this slot
|
// True if every block from 0..slot, where slot is the slot index of this slot
|
||||||
|
@ -145,28 +142,19 @@ pub struct SlotMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SlotMeta {
|
impl SlotMeta {
|
||||||
pub fn contains_all_ticks(&self, blocktree: &Blocktree) -> bool {
|
pub fn contains_all_ticks(&self) -> bool {
|
||||||
if self.num_blocks == 0 {
|
self.consumed > self.last_index
|
||||||
// A placeholder slot does not contain all the ticks
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
self.num_expected_ticks(blocktree) <= self.consumed_ticks
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_expected_ticks(&self, blocktree: &Blocktree) -> u64 {
|
fn new(slot_height: u64, parent_slot: u64) -> Self {
|
||||||
blocktree.ticks_per_slot * self.num_blocks
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new(slot_height: u64, num_blocks: u64) -> Self {
|
|
||||||
SlotMeta {
|
SlotMeta {
|
||||||
slot_height,
|
slot_height,
|
||||||
consumed: 0,
|
consumed: 0,
|
||||||
received: 0,
|
received: 0,
|
||||||
consumed_ticks: 0,
|
parent_slot,
|
||||||
num_blocks,
|
|
||||||
next_slots: vec![],
|
next_slots: vec![],
|
||||||
is_trunk: slot_height == 0,
|
is_trunk: slot_height == 0,
|
||||||
|
last_index: std::u64::MAX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,15 +498,19 @@ impl Blocktree {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut b = entry.borrow().to_blob();
|
let mut b = entry.borrow().to_blob();
|
||||||
|
|
||||||
|
if entry.borrow().is_tick() {
|
||||||
|
remaining_ticks_in_slot -= 1;
|
||||||
|
if remaining_ticks_in_slot == 0 {
|
||||||
|
b.set_is_last_in_slot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b.set_index(current_index);
|
b.set_index(current_index);
|
||||||
b.set_slot(current_slot);
|
b.set_slot(current_slot);
|
||||||
blobs.push(b);
|
blobs.push(b);
|
||||||
|
|
||||||
current_index += 1;
|
current_index += 1;
|
||||||
|
|
||||||
if entry.borrow().is_tick() {
|
|
||||||
remaining_ticks_in_slot -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write_blobs(&blobs)
|
self.write_blobs(&blobs)
|
||||||
|
@ -539,6 +531,7 @@ impl Blocktree {
|
||||||
for blob in new_blobs.iter() {
|
for blob in new_blobs.iter() {
|
||||||
let blob = blob.borrow();
|
let blob = blob.borrow();
|
||||||
let blob_slot = blob.slot();
|
let blob_slot = blob.slot();
|
||||||
|
let parent_slot = blob.parent();
|
||||||
|
|
||||||
// Check if we've already inserted the slot metadata for this blob's slot
|
// Check if we've already inserted the slot metadata for this blob's slot
|
||||||
let entry = slot_meta_working_set.entry(blob_slot).or_insert_with(|| {
|
let entry = slot_meta_working_set.entry(blob_slot).or_insert_with(|| {
|
||||||
|
@ -548,13 +541,11 @@ impl Blocktree {
|
||||||
.get_slot_meta(blob_slot)
|
.get_slot_meta(blob_slot)
|
||||||
.expect("Expect database get to succeed")
|
.expect("Expect database get to succeed")
|
||||||
{
|
{
|
||||||
// If num_blocks == 0, then this is one of the dummy metadatas inserted
|
// If parent_slot == std::u64::MAX, then this is one of the dummy metadatas inserted
|
||||||
// during the chaining process, see the function find_slot_meta_in_cached_state()
|
// during the chaining process, see the function find_slot_meta_in_cached_state()
|
||||||
// for details
|
// for details
|
||||||
if meta.num_blocks == 0 {
|
if meta.parent_slot == std::u64::MAX {
|
||||||
// TODO: derive num_blocks for this metadata from the blob itself
|
meta.parent_slot = parent_slot;
|
||||||
// Issue: https://github.com/solana-labs/solana/issues/2459.
|
|
||||||
meta.num_blocks = 1;
|
|
||||||
// Set backup as None so that all the logic for inserting new slots
|
// Set backup as None so that all the logic for inserting new slots
|
||||||
// still runs, as this placeholder slot is essentially equivalent to
|
// still runs, as this placeholder slot is essentially equivalent to
|
||||||
// inserting a new slot
|
// inserting a new slot
|
||||||
|
@ -563,17 +554,17 @@ impl Blocktree {
|
||||||
(Rc::new(RefCell::new(meta.clone())), Some(meta))
|
(Rc::new(RefCell::new(meta.clone())), Some(meta))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: derive num_blocks for this metadata from the blob itself
|
(
|
||||||
// Issue: https://github.com/solana-labs/solana/issues/2459
|
Rc::new(RefCell::new(SlotMeta::new(blob_slot, parent_slot))),
|
||||||
(Rc::new(RefCell::new(SlotMeta::new(blob_slot, 1))), None)
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let slot_meta = &mut entry.0.borrow_mut();
|
let slot_meta = &mut entry.0.borrow_mut();
|
||||||
|
|
||||||
// This slot is full, skip the bogus blob
|
// This slot is full, skip the bogus blob
|
||||||
if slot_meta.contains_all_ticks(&self) {
|
if slot_meta.contains_all_ticks() {
|
||||||
info!("Slot is full, skipping the bogus blob");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -967,14 +958,13 @@ impl Blocktree {
|
||||||
.expect("Slot must exist in the working_set hashmap");
|
.expect("Slot must exist in the working_set hashmap");
|
||||||
{
|
{
|
||||||
let mut slot_meta = meta_copy.borrow_mut();
|
let mut slot_meta = meta_copy.borrow_mut();
|
||||||
assert!(slot_meta.num_blocks > 0);
|
|
||||||
|
|
||||||
// If:
|
// If:
|
||||||
// 1) This is a new slot
|
// 1) This is a new slot
|
||||||
// 2) slot_height != 0
|
// 2) slot_height != 0
|
||||||
// then try to chain this slot to a previous slot
|
// then try to chain this slot to a previous slot
|
||||||
if slot_height != 0 {
|
if slot_height != 0 {
|
||||||
let prev_slot_height = slot_height - slot_meta.num_blocks;
|
let prev_slot_height = slot_meta.parent_slot;
|
||||||
|
|
||||||
// Check if slot_meta is a new slot
|
// Check if slot_meta is a new slot
|
||||||
if meta_backup.is_none() {
|
if meta_backup.is_none() {
|
||||||
|
@ -1008,7 +998,7 @@ impl Blocktree {
|
||||||
current_slot.borrow_mut().is_trunk = true;
|
current_slot.borrow_mut().is_trunk = true;
|
||||||
|
|
||||||
let current_slot = &RefCell::borrow(&*current_slot);
|
let current_slot = &RefCell::borrow(&*current_slot);
|
||||||
if current_slot.contains_all_ticks(self) {
|
if current_slot.contains_all_ticks() {
|
||||||
for next_slot_index in current_slot.next_slots.iter() {
|
for next_slot_index in current_slot.next_slots.iter() {
|
||||||
let next_slot = self.find_slot_meta_else_create(
|
let next_slot = self.find_slot_meta_else_create(
|
||||||
working_set,
|
working_set,
|
||||||
|
@ -1031,7 +1021,7 @@ impl Blocktree {
|
||||||
current_slot: &mut SlotMeta,
|
current_slot: &mut SlotMeta,
|
||||||
) {
|
) {
|
||||||
prev_slot.next_slots.push(current_slot_height);
|
prev_slot.next_slots.push(current_slot_height);
|
||||||
current_slot.is_trunk = prev_slot.is_trunk && prev_slot.contains_all_ticks(self);
|
current_slot.is_trunk = prev_slot.is_trunk && prev_slot.contains_all_ticks();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_newly_completed_slot(
|
fn is_newly_completed_slot(
|
||||||
|
@ -1039,9 +1029,9 @@ impl Blocktree {
|
||||||
slot_meta: &SlotMeta,
|
slot_meta: &SlotMeta,
|
||||||
backup_slot_meta: &Option<SlotMeta>,
|
backup_slot_meta: &Option<SlotMeta>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
slot_meta.contains_all_ticks(self)
|
slot_meta.contains_all_ticks()
|
||||||
&& (backup_slot_meta.is_none()
|
&& (backup_slot_meta.is_none()
|
||||||
|| slot_meta.consumed_ticks != backup_slot_meta.as_ref().unwrap().consumed_ticks)
|
|| slot_meta.consumed != backup_slot_meta.as_ref().unwrap().consumed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1) Find the slot metadata in the cache of dirty slot metadata we've previously touched,
|
// 1) Find the slot metadata in the cache of dirty slot metadata we've previously touched,
|
||||||
|
@ -1073,13 +1063,12 @@ impl Blocktree {
|
||||||
insert_map.insert(slot_height, Rc::new(RefCell::new(slot)));
|
insert_map.insert(slot_height, Rc::new(RefCell::new(slot)));
|
||||||
Ok(insert_map.get(&slot_height).unwrap().clone())
|
Ok(insert_map.get(&slot_height).unwrap().clone())
|
||||||
} else {
|
} else {
|
||||||
// If this slot doesn't exist, make a dummy placeholder slot (denoted by passing
|
// If this slot doesn't exist, make a placeholder slot. This way we
|
||||||
// 0 for the num_blocks argument to the SlotMeta constructor). This way we
|
|
||||||
// remember which slots chained to this one when we eventually get a real blob
|
// remember which slots chained to this one when we eventually get a real blob
|
||||||
// for this slot
|
// for this slot
|
||||||
insert_map.insert(
|
insert_map.insert(
|
||||||
slot_height,
|
slot_height,
|
||||||
Rc::new(RefCell::new(SlotMeta::new(slot_height, 0))),
|
Rc::new(RefCell::new(SlotMeta::new(slot_height, std::u64::MAX))),
|
||||||
);
|
);
|
||||||
Ok(insert_map.get(&slot_height).unwrap().clone())
|
Ok(insert_map.get(&slot_height).unwrap().clone())
|
||||||
}
|
}
|
||||||
|
@ -1119,7 +1108,7 @@ impl Blocktree {
|
||||||
return Err(Error::BlocktreeError(BlocktreeError::BlobForIndexExists));
|
return Err(Error::BlocktreeError(BlocktreeError::BlobForIndexExists));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (new_consumed, new_consumed_ticks) = {
|
let new_consumed = {
|
||||||
if slot_meta.consumed == blob_index {
|
if slot_meta.consumed == blob_index {
|
||||||
let blob_datas = self.get_slot_consecutive_blobs(
|
let blob_datas = self.get_slot_consecutive_blobs(
|
||||||
blob_slot,
|
blob_slot,
|
||||||
|
@ -1132,26 +1121,11 @@ impl Blocktree {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let blob_to_insert = Cow::Borrowed(&blob_to_insert.data[..]);
|
let blob_to_insert = Cow::Borrowed(&blob_to_insert.data[..]);
|
||||||
let mut new_consumed_ticks = 0;
|
// Add one because we skipped this current blob when calling
|
||||||
// Check all the consecutive blobs for ticks
|
// get_slot_consecutive_blobs() earlier
|
||||||
for blob_data in once(&blob_to_insert).chain(blob_datas.iter()) {
|
slot_meta.consumed + blob_datas.len() as u64 + 1
|
||||||
let serialized_entry_data = &blob_data[BLOB_HEADER_SIZE..];
|
|
||||||
let entry: Entry = deserialize(serialized_entry_data).expect(
|
|
||||||
"Blob made it past validation, so must be deserializable at this point",
|
|
||||||
);
|
|
||||||
if entry.is_tick() {
|
|
||||||
new_consumed_ticks += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
|
||||||
// Add one because we skipped this current blob when calling
|
|
||||||
// get_slot_consecutive_blobs() earlier
|
|
||||||
slot_meta.consumed + blob_datas.len() as u64 + 1,
|
|
||||||
new_consumed_ticks,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(slot_meta.consumed, 0)
|
slot_meta.consumed
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1166,7 +1140,19 @@ impl Blocktree {
|
||||||
// so received = index + 1 for the same blob.
|
// so received = index + 1 for the same blob.
|
||||||
slot_meta.received = cmp::max(blob_index + 1, slot_meta.received);
|
slot_meta.received = cmp::max(blob_index + 1, slot_meta.received);
|
||||||
slot_meta.consumed = new_consumed;
|
slot_meta.consumed = new_consumed;
|
||||||
slot_meta.consumed_ticks += new_consumed_ticks;
|
slot_meta.last_index = {
|
||||||
|
// If the last slot hasn't been set before, then
|
||||||
|
// set it to this blob index
|
||||||
|
if slot_meta.last_index == std::u64::MAX {
|
||||||
|
if blob_to_insert.is_last_in_slot() {
|
||||||
|
blob_slot
|
||||||
|
} else {
|
||||||
|
std::u64::MAX
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
slot_meta.last_index
|
||||||
|
}
|
||||||
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,7 +1205,6 @@ impl Blocktree {
|
||||||
bootstrap_meta.consumed = last.index() + 1;
|
bootstrap_meta.consumed = last.index() + 1;
|
||||||
bootstrap_meta.received = last.index() + 1;
|
bootstrap_meta.received = last.index() + 1;
|
||||||
bootstrap_meta.is_trunk = true;
|
bootstrap_meta.is_trunk = true;
|
||||||
bootstrap_meta.consumed_ticks = num_ending_ticks;
|
|
||||||
|
|
||||||
let mut batch = WriteBatch::default();
|
let mut batch = WriteBatch::default();
|
||||||
batch.put_cf(
|
batch.put_cf(
|
||||||
|
|
|
@ -118,7 +118,7 @@ impl RepairService {
|
||||||
slot: &SlotMeta,
|
slot: &SlotMeta,
|
||||||
max_repairs: usize,
|
max_repairs: usize,
|
||||||
) -> Result<Vec<(u64, u64)>> {
|
) -> Result<Vec<(u64, u64)>> {
|
||||||
if slot.contains_all_ticks(blocktree) {
|
if slot.contains_all_ticks() {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
} else {
|
} else {
|
||||||
let num_unreceived_ticks = {
|
let num_unreceived_ticks = {
|
||||||
|
|
Loading…
Reference in New Issue