leader slots in Blobs (#1732)

* add leader slot to Blobs
* remove get_X() methods in favor of X() methods for Blob
* add slot to get_scheduled_leader()
This commit is contained in:
Rob Walker 2018-11-07 13:18:14 -08:00 committed by GitHub
parent 3ccbf81646
commit 6c10458b5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 129 additions and 118 deletions

View File

@ -1417,9 +1417,11 @@ impl Bank {
subscriptions.remove(pubkey).is_some() subscriptions.remove(pubkey).is_some()
} }
pub fn get_current_leader(&self) -> Option<Pubkey> { pub fn get_current_leader(&self) -> Option<(Pubkey, u64)> {
let ls_lock = self.leader_scheduler.read().unwrap(); self.leader_scheduler
ls_lock.get_scheduled_leader(self.tick_height()) .read()
.unwrap()
.get_scheduled_leader(self.tick_height())
} }
pub fn tick_height(&self) -> u64 { pub fn tick_height(&self) -> u64 {

View File

@ -9,7 +9,7 @@ use influx_db_client as influxdb;
use ledger::Block; use ledger::Block;
use log::Level; use log::Level;
use metrics; use metrics;
use packet::SharedBlobs; use packet::{index_blobs, SharedBlobs};
use rayon::prelude::*; use rayon::prelude::*;
use result::{Error, Result}; use result::{Error, Result};
use service::Service; use service::Service;
@ -20,7 +20,7 @@ use std::sync::{Arc, RwLock};
use std::thread::{self, Builder, JoinHandle}; use std::thread::{self, Builder, JoinHandle};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use timing::duration_as_ms; use timing::duration_as_ms;
use window::{self, SharedWindow, WindowIndex, WindowUtil}; use window::{SharedWindow, WindowIndex, WindowUtil};
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum BroadcastStageReturnType { pub enum BroadcastStageReturnType {
@ -36,6 +36,7 @@ fn broadcast(
sock: &UdpSocket, sock: &UdpSocket,
transmit_index: &mut WindowIndex, transmit_index: &mut WindowIndex,
receive_index: &mut u64, receive_index: &mut u64,
leader_slot: u64,
) -> Result<()> { ) -> Result<()> {
let id = node_info.id; let id = node_info.id;
let timer = Duration::new(1, 0); let timer = Duration::new(1, 0);
@ -73,10 +74,7 @@ fn broadcast(
let blobs_len = blobs.len(); let blobs_len = blobs.len();
trace!("{}: broadcast blobs.len: {}", id, blobs_len); trace!("{}: broadcast blobs.len: {}", id, blobs_len);
// TODO: move all this into window.rs index_blobs(&blobs, &node_info.id, *receive_index, leader_slot);
// Index the blobs
window::index_blobs(node_info, &blobs, receive_index)
.expect("index blobs for initial window");
// keep the cache of blobs that are broadcast // keep the cache of blobs that are broadcast
inc_new_counter_info!("streamer-broadcast-sent", blobs.len()); inc_new_counter_info!("streamer-broadcast-sent", blobs.len());
@ -84,13 +82,13 @@ fn broadcast(
let mut win = window.write().unwrap(); let mut win = window.write().unwrap();
assert!(blobs.len() <= win.len()); assert!(blobs.len() <= win.len());
for b in &blobs { for b in &blobs {
let ix = b.read().unwrap().get_index().expect("blob index"); let ix = b.read().unwrap().index().expect("blob index");
let pos = (ix % window_size) as usize; let pos = (ix % window_size) as usize;
if let Some(x) = win[pos].data.take() { if let Some(x) = win[pos].data.take() {
trace!( trace!(
"{} popped {} at {}", "{} popped {} at {}",
id, id,
x.read().unwrap().get_index().unwrap(), x.read().unwrap().index().unwrap(),
pos pos
); );
} }
@ -98,7 +96,7 @@ fn broadcast(
trace!( trace!(
"{} popped {} at {}", "{} popped {} at {}",
id, id,
x.read().unwrap().get_index().unwrap(), x.read().unwrap().index().unwrap(),
pos pos
); );
} }
@ -106,7 +104,7 @@ fn broadcast(
trace!("{} null {}", id, pos); trace!("{} null {}", id, pos);
} }
for b in &blobs { for b in &blobs {
let ix = b.read().unwrap().get_index().expect("blob index"); let ix = b.read().unwrap().index().expect("blob index");
let pos = (ix % window_size) as usize; let pos = (ix % window_size) as usize;
trace!("{} caching {} at {}", id, ix, pos); trace!("{} caching {} at {}", id, ix, pos);
assert!(win[pos].data.is_none()); assert!(win[pos].data.is_none());
@ -188,6 +186,7 @@ impl BroadcastStage {
cluster_info: &Arc<RwLock<ClusterInfo>>, cluster_info: &Arc<RwLock<ClusterInfo>>,
window: &SharedWindow, window: &SharedWindow,
entry_height: u64, entry_height: u64,
leader_slot: u64,
receiver: &Receiver<Vec<Entry>>, receiver: &Receiver<Vec<Entry>>,
) -> BroadcastStageReturnType { ) -> BroadcastStageReturnType {
let mut transmit_index = WindowIndex { let mut transmit_index = WindowIndex {
@ -206,6 +205,7 @@ impl BroadcastStage {
&sock, &sock,
&mut transmit_index, &mut transmit_index,
&mut receive_index, &mut receive_index,
leader_slot,
) { ) {
match e { match e {
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => { Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => {
@ -242,6 +242,7 @@ impl BroadcastStage {
cluster_info: Arc<RwLock<ClusterInfo>>, cluster_info: Arc<RwLock<ClusterInfo>>,
window: SharedWindow, window: SharedWindow,
entry_height: u64, entry_height: u64,
leader_slot: u64,
receiver: Receiver<Vec<Entry>>, receiver: Receiver<Vec<Entry>>,
exit_sender: Arc<AtomicBool>, exit_sender: Arc<AtomicBool>,
) -> Self { ) -> Self {
@ -249,7 +250,14 @@ impl BroadcastStage {
.name("solana-broadcaster".to_string()) .name("solana-broadcaster".to_string())
.spawn(move || { .spawn(move || {
let _exit = Finalizer::new(exit_sender); let _exit = Finalizer::new(exit_sender);
Self::run(&sock, &cluster_info, &window, entry_height, &receiver) Self::run(
&sock,
&cluster_info,
&window,
entry_height,
leader_slot,
&receiver,
)
}).unwrap(); }).unwrap();
BroadcastStage { thread_hdl } BroadcastStage { thread_hdl }

View File

@ -539,7 +539,7 @@ impl ClusterInfo {
trace!( trace!(
"{}: BROADCAST idx: {} sz: {} to {},{} coding: {}", "{}: BROADCAST idx: {} sz: {} to {},{} coding: {}",
me.id, me.id,
blob.get_index().unwrap(), blob.index().unwrap(),
blob.meta.size, blob.meta.size,
v.id, v.id,
v.contact_info.tvu, v.contact_info.tvu,
@ -587,7 +587,7 @@ impl ClusterInfo {
}; };
blob.write() blob.write()
.unwrap() .unwrap()
.set_id(me.id) .set_id(&me.id)
.expect("set_id in pub fn retransmit"); .expect("set_id in pub fn retransmit");
let rblob = blob.read().unwrap(); let rblob = blob.read().unwrap();
let orders: Vec<_> = table let orders: Vec<_> = table
@ -617,7 +617,7 @@ impl ClusterInfo {
debug!( debug!(
"{}: retransmit blob {} to {} {}", "{}: retransmit blob {} to {} {}",
me.id, me.id,
rblob.get_index().unwrap(), rblob.index().unwrap(),
v.id, v.id,
v.contact_info.tvu, v.contact_info.tvu,
); );
@ -869,7 +869,7 @@ impl ClusterInfo {
let pos = (ix as usize) % window.read().unwrap().len(); let pos = (ix as usize) % window.read().unwrap().len();
if let Some(ref mut blob) = &mut window.write().unwrap()[pos].data { if let Some(ref mut blob) = &mut window.write().unwrap()[pos].data {
let mut wblob = blob.write().unwrap(); let mut wblob = blob.write().unwrap();
let blob_ix = wblob.get_index().expect("run_window_request get_index"); let blob_ix = wblob.index().expect("run_window_request index");
if blob_ix == ix { if blob_ix == ix {
let num_retransmits = wblob.meta.num_retransmits; let num_retransmits = wblob.meta.num_retransmits;
wblob.meta.num_retransmits += 1; wblob.meta.num_retransmits += 1;
@ -896,7 +896,7 @@ impl ClusterInfo {
outblob.meta.size = sz; outblob.meta.size = sz;
outblob.data[..sz].copy_from_slice(&wblob.data[..sz]); outblob.data[..sz].copy_from_slice(&wblob.data[..sz]);
outblob.meta.set_addr(from_addr); outblob.meta.set_addr(from_addr);
outblob.set_id(sender_id).expect("blob set_id"); outblob.set_id(&sender_id).expect("blob set_id");
} }
inc_new_counter_info!("cluster_info-window-request-pass", 1); inc_new_counter_info!("cluster_info-window-request-pass", 1);
@ -1735,7 +1735,7 @@ mod tests {
} else { } else {
mock_peer.id mock_peer.id
}; };
assert_eq!(blob.get_id().unwrap(), id); assert_eq!(blob.id().unwrap(), id);
} }
} }

View File

@ -108,7 +108,7 @@ impl Entry {
blob_w.set_index(idx).expect("set_index()"); blob_w.set_index(idx).expect("set_index()");
} }
if let Some(id) = id { if let Some(id) = id {
blob_w.set_id(id).expect("set_id()"); blob_w.set_id(&id).expect("set_id()");
} }
if let Some(addr) = addr { if let Some(addr) = addr {
blob_w.meta.set_addr(addr); blob_w.meta.set_addr(addr);

View File

@ -295,8 +295,8 @@ pub fn generate_coding(
if let Some(data) = &window[n].data { if let Some(data) = &window[n].data {
let data_rl = data.read().unwrap(); let data_rl = data.read().unwrap();
let index = data_rl.get_index().unwrap(); let index = data_rl.index().unwrap();
let id = data_rl.get_id().unwrap(); let id = data_rl.id().unwrap();
trace!( trace!(
"{} copying index {} id {:?} from data to coding", "{} copying index {} id {:?} from data to coding",
@ -305,7 +305,7 @@ pub fn generate_coding(
id id
); );
coding_wl.set_index(index).unwrap(); coding_wl.set_index(index).unwrap();
coding_wl.set_id(id).unwrap(); coding_wl.set_id(&id).unwrap();
} }
coding_wl.set_size(max_data_size); coding_wl.set_size(max_data_size);
if coding_wl.set_coding().is_err() { if coding_wl.set_coding().is_err() {
@ -351,7 +351,7 @@ pub fn generate_coding(
// false if slot has a blob with the right index // false if slot has a blob with the right index
fn is_missing(id: &Pubkey, idx: u64, window_slot: &mut Option<SharedBlob>, c_or_d: &str) -> bool { fn is_missing(id: &Pubkey, idx: u64, window_slot: &mut Option<SharedBlob>, c_or_d: &str) -> bool {
if let Some(blob) = window_slot.take() { if let Some(blob) = window_slot.take() {
let blob_idx = blob.read().unwrap().get_index().unwrap(); let blob_idx = blob.read().unwrap().index().unwrap();
if blob_idx == idx { if blob_idx == idx {
trace!("recover {}: idx: {} good {}", id, idx, c_or_d); trace!("recover {}: idx: {} good {}", id, idx, c_or_d);
// put it back // put it back
@ -553,7 +553,7 @@ pub fn recover(id: &Pubkey, window: &mut [WindowSlot], start_idx: u64, start: us
let mut data_size; let mut data_size;
if n < NUM_DATA { if n < NUM_DATA {
data_size = locks[n].get_data_size().unwrap() as usize; data_size = locks[n].data_size().unwrap() as usize;
data_size -= BLOB_HEADER_SIZE; data_size -= BLOB_HEADER_SIZE;
if data_size > BLOB_DATA_SIZE { if data_size > BLOB_DATA_SIZE {
error!("{} corrupt data blob[{}] data_size: {}", id, idx, data_size); error!("{} corrupt data blob[{}] data_size: {}", id, idx, data_size);
@ -591,15 +591,14 @@ pub fn recover(id: &Pubkey, window: &mut [WindowSlot], start_idx: u64, start: us
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use cluster_info;
use erasure; use erasure;
use logger; use logger;
use packet::{SharedBlob, BLOB_DATA_SIZE, BLOB_HEADER_SIZE, BLOB_SIZE}; use packet::{index_blobs, SharedBlob, BLOB_DATA_SIZE, BLOB_HEADER_SIZE, BLOB_SIZE};
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use signature::{Keypair, KeypairUtil}; use signature::{Keypair, KeypairUtil};
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
// use std::sync::{Arc, RwLock}; // use std::sync::{Arc, RwLock};
use window::{index_blobs, WindowSlot}; use window::WindowSlot;
#[test] #[test]
pub fn test_coding() { pub fn test_coding() {
@ -660,7 +659,7 @@ mod test {
let window_l2 = window_l1.read().unwrap(); let window_l2 = window_l1.read().unwrap();
print!( print!(
"data index: {:?} meta.size: {} data: ", "data index: {:?} meta.size: {} data: ",
window_l2.get_index(), window_l2.index(),
window_l2.meta.size window_l2.meta.size
); );
for i in 0..64 { for i in 0..64 {
@ -676,7 +675,7 @@ mod test {
let window_l2 = window_l1.read().unwrap(); let window_l2 = window_l1.read().unwrap();
print!( print!(
"coding index: {:?} meta.size: {} data: ", "coding index: {:?} meta.size: {} data: ",
window_l2.get_index(), window_l2.index(),
window_l2.meta.size window_l2.meta.size
); );
for i in 0..8 { for i in 0..8 {
@ -726,10 +725,9 @@ mod test {
blobs.push(b_); blobs.push(b_);
} }
let d = cluster_info::NodeInfo::new_localhost(Keypair::new().pubkey()); index_blobs(&blobs, &Keypair::new().pubkey(), offset as u64, 0);
assert!(index_blobs(&d, &blobs, &mut (offset as u64)).is_ok());
for b in blobs { for b in blobs {
let idx = b.read().unwrap().get_index().unwrap() as usize % WINDOW_SIZE; let idx = b.read().unwrap().index().unwrap() as usize % WINDOW_SIZE;
window[idx].data = Some(b); window[idx].data = Some(b);
} }
@ -815,7 +813,7 @@ mod test {
assert_eq!(window_l2.meta.port, ref_l2.meta.port); assert_eq!(window_l2.meta.port, ref_l2.meta.port);
assert_eq!(window_l2.meta.v6, ref_l2.meta.v6); assert_eq!(window_l2.meta.v6, ref_l2.meta.v6);
assert_eq!( assert_eq!(
window_l2.get_index().unwrap(), window_l2.index().unwrap(),
(erase_offset + WINDOW_SIZE) as u64 (erase_offset + WINDOW_SIZE) as u64
); );
} }
@ -850,7 +848,7 @@ mod test {
assert_eq!(window_l2.meta.port, ref_l2.meta.port); assert_eq!(window_l2.meta.port, ref_l2.meta.port);
assert_eq!(window_l2.meta.v6, ref_l2.meta.v6); assert_eq!(window_l2.meta.v6, ref_l2.meta.v6);
assert_eq!( assert_eq!(
window_l2.get_index().unwrap(), window_l2.index().unwrap(),
(erase_offset + WINDOW_SIZE) as u64 (erase_offset + WINDOW_SIZE) as u64
); );
} }
@ -896,7 +894,7 @@ mod test {
assert_eq!(window_l2.meta.port, ref_l2.meta.port); assert_eq!(window_l2.meta.port, ref_l2.meta.port);
assert_eq!(window_l2.meta.v6, ref_l2.meta.v6); assert_eq!(window_l2.meta.v6, ref_l2.meta.v6);
assert_eq!( assert_eq!(
window_l2.get_index().unwrap(), window_l2.index().unwrap(),
(erase_offset + WINDOW_SIZE) as u64 (erase_offset + WINDOW_SIZE) as u64
); );
} }

View File

@ -237,7 +237,7 @@ impl Fullnode {
} }
// Get the scheduled leader // Get the scheduled leader
let scheduled_leader = bank let (scheduled_leader, leader_slot) = bank
.get_current_leader() .get_current_leader()
.expect("Leader not known after processing bank"); .expect("Leader not known after processing bank");
@ -296,6 +296,7 @@ impl Fullnode {
cluster_info.clone(), cluster_info.clone(),
shared_window.clone(), shared_window.clone(),
entry_height, entry_height,
leader_slot,
entry_receiver, entry_receiver,
tpu_exit, tpu_exit,
); );
@ -354,7 +355,7 @@ impl Fullnode {
); );
let new_bank = Arc::new(new_bank); let new_bank = Arc::new(new_bank);
let scheduled_leader = new_bank let (scheduled_leader, _) = new_bank
.get_current_leader() .get_current_leader()
.expect("Scheduled leader should exist after rebuilding bank"); .expect("Scheduled leader should exist after rebuilding bank");
@ -446,6 +447,7 @@ impl Fullnode {
self.cluster_info.clone(), self.cluster_info.clone(),
self.shared_window.clone(), self.shared_window.clone(),
entry_height, entry_height,
0, // TODO: get real leader slot from leader_scheduler
blob_receiver, blob_receiver,
tpu_exit, tpu_exit,
); );

View File

@ -248,15 +248,15 @@ impl LeaderScheduler {
// Uses the schedule generated by the last call to generate_schedule() to return the // Uses the schedule generated by the last call to generate_schedule() to return the
// leader for a given PoH height in round-robin fashion // leader for a given PoH height in round-robin fashion
pub fn get_scheduled_leader(&self, height: u64) -> Option<Pubkey> { pub fn get_scheduled_leader(&self, height: u64) -> Option<(Pubkey, u64)> {
if self.use_only_bootstrap_leader { if self.use_only_bootstrap_leader {
return Some(self.bootstrap_leader); return Some((self.bootstrap_leader, 0));
} }
// This covers cases where the schedule isn't yet generated. // This covers cases where the schedule isn't yet generated.
if self.last_seed_height == None { if self.last_seed_height == None {
if height < self.bootstrap_height { if height < self.bootstrap_height {
return Some(self.bootstrap_leader); return Some((self.bootstrap_leader, 0));
} else { } else {
// If there's been no schedule generated yet before we reach the end of the // If there's been no schedule generated yet before we reach the end of the
// bootstrapping period, then the leader is unknown // bootstrapping period, then the leader is unknown
@ -273,9 +273,10 @@ impl LeaderScheduler {
} }
// Find index into the leader_schedule that this PoH height maps to // Find index into the leader_schedule that this PoH height maps to
let leader_slot = (height - self.bootstrap_height) / self.leader_rotation_interval + 1;
let index = (height - last_seed_height) / self.leader_rotation_interval; let index = (height - last_seed_height) / self.leader_rotation_interval;
let validator_index = index as usize % self.leader_schedule.len(); let validator_index = index as usize % self.leader_schedule.len();
Some(self.leader_schedule[validator_index]) Some((self.leader_schedule[validator_index], leader_slot))
} }
// TODO: We use a HashSet for now because a single validator could potentially register // TODO: We use a HashSet for now because a single validator could potentially register
@ -351,7 +352,7 @@ impl LeaderScheduler {
// If possible, try to avoid having the same leader twice in a row, but // If possible, try to avoid having the same leader twice in a row, but
// if there's only one leader to choose from, then we have no other choice // if there's only one leader to choose from, then we have no other choice
if validator_rankings.len() > 1 { if validator_rankings.len() > 1 {
let old_epoch_last_leader = self let (old_epoch_last_leader, _) = self
.get_scheduled_leader(height - 1) .get_scheduled_leader(height - 1)
.expect("Previous leader schedule should still exist"); .expect("Previous leader schedule should still exist");
let new_epoch_start_leader = validator_rankings[0]; let new_epoch_start_leader = validator_rankings[0];
@ -587,11 +588,11 @@ mod tests {
// be the bootstrap leader // be the bootstrap leader
assert_eq!( assert_eq!(
leader_scheduler.get_scheduled_leader(0), leader_scheduler.get_scheduled_leader(0),
Some(bootstrap_leader_id) Some((bootstrap_leader_id, 0))
); );
assert_eq!( assert_eq!(
leader_scheduler.get_scheduled_leader(bootstrap_height - 1), leader_scheduler.get_scheduled_leader(bootstrap_height - 1),
Some(bootstrap_leader_id) Some((bootstrap_leader_id, 0))
); );
assert_eq!( assert_eq!(
leader_scheduler.get_scheduled_leader(bootstrap_height), leader_scheduler.get_scheduled_leader(bootstrap_height),
@ -625,7 +626,7 @@ mod tests {
let mut start_leader_index = None; let mut start_leader_index = None;
for i in 0..num_rounds { for i in 0..num_rounds {
let begin_height = bootstrap_height + i * leader_rotation_interval; let begin_height = bootstrap_height + i * leader_rotation_interval;
let current_leader = leader_scheduler let (current_leader, slot) = leader_scheduler
.get_scheduled_leader(begin_height) .get_scheduled_leader(begin_height)
.expect("Expected a leader from scheduler"); .expect("Expected a leader from scheduler");
@ -645,10 +646,11 @@ mod tests {
let expected_leader = let expected_leader =
validators[(start_leader_index.unwrap() + i as usize) % num_validators]; validators[(start_leader_index.unwrap() + i as usize) % num_validators];
assert_eq!(current_leader, expected_leader); assert_eq!(current_leader, expected_leader);
assert_eq!(slot, i + 1);
// Check that the same leader is in power for the next leader_rotation_interval entries // Check that the same leader is in power for the next leader_rotation_interval entries
assert_eq!( assert_eq!(
leader_scheduler.get_scheduled_leader(begin_height + leader_rotation_interval - 1), leader_scheduler.get_scheduled_leader(begin_height + leader_rotation_interval - 1),
Some(current_leader) Some((current_leader, slot))
); );
} }
} }

View File

@ -508,9 +508,9 @@ pub fn reconstruct_entries_from_blobs(blobs: Vec<SharedBlob>) -> Result<Vec<Entr
for blob in blobs { for blob in blobs {
let entry = { let entry = {
let msg = blob.read().unwrap(); let blob = blob.read().unwrap();
let msg_size = msg.get_size()?; let blob_size = blob.size()?;
deserialize(&msg.data()[..msg_size]) deserialize(&blob.data()[..blob_size])
}; };
match entry { match entry {

View File

@ -250,7 +250,8 @@ pub fn to_blobs<T: Serialize>(rsps: Vec<(T, SocketAddr)>) -> Result<SharedBlobs>
Ok(blobs) Ok(blobs)
} }
const BLOB_INDEX_END: usize = size_of::<u64>(); const BLOB_SLOT_END: usize = size_of::<u64>();
const BLOB_INDEX_END: usize = BLOB_SLOT_END + size_of::<u64>();
const BLOB_ID_END: usize = BLOB_INDEX_END + size_of::<Pubkey>(); const BLOB_ID_END: usize = BLOB_INDEX_END + size_of::<Pubkey>();
const BLOB_FLAGS_END: usize = BLOB_ID_END + size_of::<u32>(); const BLOB_FLAGS_END: usize = BLOB_ID_END + size_of::<u32>();
const BLOB_SIZE_END: usize = BLOB_FLAGS_END + size_of::<u64>(); const BLOB_SIZE_END: usize = BLOB_FLAGS_END + size_of::<u64>();
@ -265,31 +266,42 @@ pub const BLOB_FLAG_IS_CODING: u32 = 0x1;
pub const BLOB_HEADER_SIZE: usize = align!(BLOB_SIZE_END, 64); pub const BLOB_HEADER_SIZE: usize = align!(BLOB_SIZE_END, 64);
impl Blob { impl Blob {
pub fn get_index(&self) -> Result<u64> { pub fn slot(&self) -> Result<u64> {
let mut rdr = io::Cursor::new(&self.data[0..BLOB_INDEX_END]); let mut rdr = io::Cursor::new(&self.data[0..BLOB_SLOT_END]);
let r = rdr.read_u64::<LittleEndian>()?;
Ok(r)
}
pub fn set_slot(&mut self, ix: u64) -> Result<()> {
let mut wtr = vec![];
wtr.write_u64::<LittleEndian>(ix)?;
self.data[..BLOB_SLOT_END].clone_from_slice(&wtr);
Ok(())
}
pub fn index(&self) -> Result<u64> {
let mut rdr = io::Cursor::new(&self.data[BLOB_SLOT_END..BLOB_INDEX_END]);
let r = rdr.read_u64::<LittleEndian>()?; let r = rdr.read_u64::<LittleEndian>()?;
Ok(r) Ok(r)
} }
pub fn set_index(&mut self, ix: u64) -> Result<()> { pub fn set_index(&mut self, ix: u64) -> Result<()> {
let mut wtr = vec![]; let mut wtr = vec![];
wtr.write_u64::<LittleEndian>(ix)?; wtr.write_u64::<LittleEndian>(ix)?;
self.data[..BLOB_INDEX_END].clone_from_slice(&wtr); self.data[BLOB_SLOT_END..BLOB_INDEX_END].clone_from_slice(&wtr);
Ok(()) Ok(())
} }
/// sender id, we use this for identifying if its a blob from the leader that we should /// sender id, we use this for identifying if its a blob from the leader that we should
/// retransmit. eventually blobs should have a signature that we can use ffor spam filtering /// retransmit. eventually blobs should have a signature that we can use ffor spam filtering
pub fn get_id(&self) -> Result<Pubkey> { pub fn id(&self) -> Result<Pubkey> {
let e = deserialize(&self.data[BLOB_INDEX_END..BLOB_ID_END])?; let e = deserialize(&self.data[BLOB_INDEX_END..BLOB_ID_END])?;
Ok(e) Ok(e)
} }
pub fn set_id(&mut self, id: Pubkey) -> Result<()> { pub fn set_id(&mut self, id: &Pubkey) -> Result<()> {
let wtr = serialize(&id)?; let wtr = serialize(id)?;
self.data[BLOB_INDEX_END..BLOB_ID_END].clone_from_slice(&wtr); self.data[BLOB_INDEX_END..BLOB_ID_END].clone_from_slice(&wtr);
Ok(()) Ok(())
} }
pub fn get_flags(&self) -> Result<u32> { pub fn flags(&self) -> Result<u32> {
let mut rdr = io::Cursor::new(&self.data[BLOB_ID_END..BLOB_FLAGS_END]); let mut rdr = io::Cursor::new(&self.data[BLOB_ID_END..BLOB_FLAGS_END]);
let r = rdr.read_u32::<LittleEndian>()?; let r = rdr.read_u32::<LittleEndian>()?;
Ok(r) Ok(r)
@ -303,15 +315,15 @@ impl Blob {
} }
pub fn is_coding(&self) -> bool { pub fn is_coding(&self) -> bool {
(self.get_flags().unwrap() & BLOB_FLAG_IS_CODING) != 0 (self.flags().unwrap() & BLOB_FLAG_IS_CODING) != 0
} }
pub fn set_coding(&mut self) -> Result<()> { pub fn set_coding(&mut self) -> Result<()> {
let flags = self.get_flags().unwrap(); let flags = self.flags().unwrap();
self.set_flags(flags | BLOB_FLAG_IS_CODING) self.set_flags(flags | BLOB_FLAG_IS_CODING)
} }
pub fn get_data_size(&self) -> Result<u64> { pub fn data_size(&self) -> Result<u64> {
let mut rdr = io::Cursor::new(&self.data[BLOB_FLAGS_END..BLOB_SIZE_END]); let mut rdr = io::Cursor::new(&self.data[BLOB_FLAGS_END..BLOB_SIZE_END]);
let r = rdr.read_u64::<LittleEndian>()?; let r = rdr.read_u64::<LittleEndian>()?;
Ok(r) Ok(r)
@ -330,8 +342,8 @@ impl Blob {
pub fn data_mut(&mut self) -> &mut [u8] { pub fn data_mut(&mut self) -> &mut [u8] {
&mut self.data[BLOB_HEADER_SIZE..] &mut self.data[BLOB_HEADER_SIZE..]
} }
pub fn get_size(&self) -> Result<usize> { pub fn size(&self) -> Result<usize> {
let size = self.get_data_size()? as usize; let size = self.data_size()? as usize;
if self.meta.size == size { if self.meta.size == size {
Ok(size - BLOB_HEADER_SIZE) Ok(size - BLOB_HEADER_SIZE)
} else { } else {
@ -406,6 +418,20 @@ impl Blob {
} }
} }
pub fn index_blobs(blobs: &[SharedBlob], id: &Pubkey, mut index: u64, slot: u64) {
// enumerate all the blobs, those are the indices
for b in blobs {
let mut blob = b.write().unwrap();
blob.set_index(index).expect("set_index");
blob.set_slot(slot).expect("set_slot");
blob.set_id(id).expect("set_id");
blob.set_flags(0).unwrap();
index += 1;
}
}
#[cfg(test)] #[cfg(test)]
pub fn make_consecutive_blobs( pub fn make_consecutive_blobs(
me_id: Pubkey, me_id: Pubkey,
@ -525,10 +551,10 @@ mod tests {
pub fn blob_test() { pub fn blob_test() {
let mut b = Blob::default(); let mut b = Blob::default();
b.set_index(<u64>::max_value()).unwrap(); b.set_index(<u64>::max_value()).unwrap();
assert_eq!(b.get_index().unwrap(), <u64>::max_value()); assert_eq!(b.index().unwrap(), <u64>::max_value());
b.data_mut()[0] = 1; b.data_mut()[0] = 1;
assert_eq!(b.data()[0], 1); assert_eq!(b.data()[0], 1);
assert_eq!(b.get_index().unwrap(), <u64>::max_value()); assert_eq!(b.index().unwrap(), <u64>::max_value());
assert_eq!(b.meta, Meta::default()); assert_eq!(b.meta, Meta::default());
} }

View File

@ -78,13 +78,13 @@ impl ReplicateStage {
let mut res = Ok(()); let mut res = Ok(());
let last_entry_id = { let last_entry_id = {
let mut num_entries_to_write = entries.len(); let mut num_entries_to_write = entries.len();
let current_leader = bank let (current_leader, _) = bank
.get_current_leader() .get_current_leader()
.expect("Scheduled leader id should never be unknown while processing entries"); .expect("Scheduled leader id should never be unknown while processing entries");
for (i, entry) in entries.iter().enumerate() { for (i, entry) in entries.iter().enumerate() {
res = bank.process_entry(&entry); res = bank.process_entry(&entry);
let my_id = keypair.pubkey(); let my_id = keypair.pubkey();
let scheduled_leader = bank let (scheduled_leader, _) = bank
.get_current_leader() .get_current_leader()
.expect("Scheduled leader id should never be unknown while processing entries"); .expect("Scheduled leader id should never be unknown while processing entries");
@ -164,7 +164,7 @@ impl ReplicateStage {
let mut entry_height_ = entry_height; let mut entry_height_ = entry_height;
let mut last_entry_id = None; let mut last_entry_id = None;
loop { loop {
let leader_id = bank let (leader_id, _) = bank
.get_current_leader() .get_current_leader()
.expect("Scheduled leader id should never be unknown at this point"); .expect("Scheduled leader id should never be unknown at this point");

View File

@ -279,7 +279,7 @@ pub mod tests {
let mut alice_ref_balance = starting_balance; let mut alice_ref_balance = starting_balance;
let mut msgs = Vec::new(); let mut msgs = Vec::new();
let mut cur_hash = Hash::default(); let mut cur_hash = Hash::default();
let mut blob_id = 0; let mut blob_idx = 0;
let num_transfers = 10; let num_transfers = 10;
let transfer_amount = 501; let transfer_amount = 501;
let bob_keypair = Keypair::new(); let bob_keypair = Keypair::new();
@ -306,9 +306,9 @@ pub mod tests {
let mut b = SharedBlob::default(); let mut b = SharedBlob::default();
{ {
let mut w = b.write().unwrap(); let mut w = b.write().unwrap();
w.set_index(blob_id).unwrap(); w.set_index(blob_idx).unwrap();
blob_id += 1; blob_idx += 1;
w.set_id(leader_id).unwrap(); w.set_id(&leader_id).unwrap();
let serialized_entry = serialize(&entry).unwrap(); let serialized_entry = serialize(&entry).unwrap();

View File

@ -52,12 +52,9 @@ pub fn create_new_signed_vote_blob(
} }
fn get_leader_tpu(bank: &Bank, cluster_info: &Arc<RwLock<ClusterInfo>>) -> Result<SocketAddr> { fn get_leader_tpu(bank: &Bank, cluster_info: &Arc<RwLock<ClusterInfo>>) -> Result<SocketAddr> {
let leader_id = { let leader_id = match bank.get_current_leader() {
if let Some(leader_id) = bank.get_current_leader() { Some((leader_id, _)) => leader_id,
leader_id None => return Err(Error::VoteError(VoteError::NoLeader)),
} else {
return Err(Error::VoteError(VoteError::NoLeader));
}
}; };
let rcluster_info = cluster_info.read().unwrap(); let rcluster_info = cluster_info.read().unwrap();

View File

@ -1,6 +1,6 @@
//! The `window` module defines data structure for storing the tail of the ledger. //! The `window` module defines data structure for storing the tail of the ledger.
//! //!
use cluster_info::{ClusterInfo, NodeInfo}; use cluster_info::ClusterInfo;
use counter::Counter; use counter::Counter;
use entry::Entry; use entry::Entry;
#[cfg(feature = "erasure")] #[cfg(feature = "erasure")]
@ -9,7 +9,6 @@ use leader_scheduler::LeaderScheduler;
use ledger::reconstruct_entries_from_blobs; use ledger::reconstruct_entries_from_blobs;
use log::Level; use log::Level;
use packet::SharedBlob; use packet::SharedBlob;
use result::Result;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use std::cmp; use std::cmp;
use std::mem; use std::mem;
@ -27,7 +26,7 @@ pub struct WindowSlot {
impl WindowSlot { impl WindowSlot {
fn blob_index(&self) -> Option<u64> { fn blob_index(&self) -> Option<u64> {
match self.data { match self.data {
Some(ref blob) => blob.read().unwrap().get_index().ok(), Some(ref blob) => blob.read().unwrap().index().ok(),
None => None, None => None,
} }
} }
@ -154,7 +153,7 @@ impl WindowUtil for Window {
ls_lock.max_height_for_leader(tick_height) ls_lock.max_height_for_leader(tick_height)
{ {
match ls_lock.get_scheduled_leader(next_leader_rotation_height) { match ls_lock.get_scheduled_leader(next_leader_rotation_height) {
Some(leader_id) if leader_id == *id => is_next_leader = true, Some((leader_id, _)) if leader_id == *id => is_next_leader = true,
// In the case that we are not in the current scope of the leader schedule // In the case that we are not in the current scope of the leader schedule
// window then either: // window then either:
// //
@ -296,7 +295,7 @@ impl WindowUtil for Window {
c_or_d: &str, c_or_d: &str,
) -> bool { ) -> bool {
if let Some(old) = mem::replace(window_slot, Some(blob)) { if let Some(old) = mem::replace(window_slot, Some(blob)) {
let is_dup = old.read().unwrap().get_index().unwrap() == pix; let is_dup = old.read().unwrap().index().unwrap() == pix;
trace!( trace!(
"{}: occupied {} window slot {:}, is_dup: {}", "{}: occupied {} window slot {:}, is_dup: {}",
id, id,
@ -341,7 +340,7 @@ impl WindowUtil for Window {
let k_data_blob; let k_data_blob;
let k_data_slot = &mut self[k].data; let k_data_slot = &mut self[k].data;
if let Some(blob) = k_data_slot { if let Some(blob) = k_data_slot {
if blob.read().unwrap().get_index().unwrap() < *consumed { if blob.read().unwrap().index().unwrap() < *consumed {
// window wrap-around, end of received // window wrap-around, end of received
break; break;
} }
@ -407,26 +406,6 @@ pub fn default_window() -> Window {
(0..2048).map(|_| WindowSlot::default()).collect() (0..2048).map(|_| WindowSlot::default()).collect()
} }
pub fn index_blobs(
node_info: &NodeInfo,
blobs: &[SharedBlob],
receive_index: &mut u64,
) -> Result<()> {
// enumerate all the blobs, those are the indices
trace!("{}: INDEX_BLOBS {}", node_info.id, blobs.len());
for (i, b) in blobs.iter().enumerate() {
// only leader should be broadcasting
let mut blob = b.write().unwrap();
blob.set_id(node_info.id)
.expect("set_id in pub fn broadcast");
blob.set_index(*receive_index + i as u64)
.expect("set_index in pub fn broadcast");
blob.set_flags(0).unwrap();
}
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use packet::{Blob, Packet, Packets, SharedBlob, PACKET_DATA_SIZE}; use packet::{Blob, Packet, Packets, SharedBlob, PACKET_DATA_SIZE};

View File

@ -59,17 +59,14 @@ fn add_block_to_retransmit_queue(
//we need to maintain a sequence window //we need to maintain a sequence window
trace!( trace!(
"idx: {} addr: {:?} id: {:?} leader: {:?}", "idx: {} addr: {:?} id: {:?} leader: {:?}",
p.get_index() p.index()
.expect("get_index in fn add_block_to_retransmit_queue"), .expect("get_index in fn add_block_to_retransmit_queue"),
p.get_id() p.id()
.expect("get_id in trace! fn add_block_to_retransmit_queue"), .expect("get_id in trace! fn add_block_to_retransmit_queue"),
p.meta.addr(), p.meta.addr(),
leader_id leader_id
); );
if p.get_id() if p.id().expect("get_id in fn add_block_to_retransmit_queue") == leader_id {
.expect("get_id in fn add_block_to_retransmit_queue")
== leader_id
{
//TODO //TODO
//need to copy the retransmitted blob //need to copy the retransmitted blob
//otherwise we get into races with which thread //otherwise we get into races with which thread
@ -202,7 +199,7 @@ fn recv_window(
for b in dq { for b in dq {
let (pix, meta_size) = { let (pix, meta_size) = {
let p = b.read().unwrap(); let p = b.read().unwrap();
(p.get_index()?, p.meta.size) (p.index()?, p.meta.size)
}; };
pixs.push(pix); pixs.push(pix);
@ -495,8 +492,8 @@ mod test {
{ {
let mut w = b.write().unwrap(); let mut w = b.write().unwrap();
w.set_index(i).unwrap(); w.set_index(i).unwrap();
w.set_id(me_id).unwrap(); w.set_id(&me_id).unwrap();
assert_eq!(i, w.get_index().unwrap()); assert_eq!(i, w.index().unwrap());
w.meta.size = PACKET_DATA_SIZE; w.meta.size = PACKET_DATA_SIZE;
w.meta.set_addr(&tn.info.contact_info.ncp); w.meta.set_addr(&tn.info.contact_info.ncp);
} }
@ -559,8 +556,8 @@ mod test {
{ {
let mut w = b.write().unwrap(); let mut w = b.write().unwrap();
w.set_index(i).unwrap(); w.set_index(i).unwrap();
w.set_id(me_id).unwrap(); w.set_id(&me_id).unwrap();
assert_eq!(i, w.get_index().unwrap()); assert_eq!(i, w.index().unwrap());
w.meta.size = PACKET_DATA_SIZE; w.meta.size = PACKET_DATA_SIZE;
w.meta.set_addr(&tn.info.contact_info.ncp); w.meta.set_addr(&tn.info.contact_info.ncp);
} }
@ -579,8 +576,8 @@ mod test {
{ {
let mut w = b.write().unwrap(); let mut w = b.write().unwrap();
w.set_index(i).unwrap(); w.set_index(i).unwrap();
w.set_id(me_id).unwrap(); w.set_id(&me_id).unwrap();
assert_eq!(i, w.get_index().unwrap()); assert_eq!(i, w.index().unwrap());
w.meta.size = PACKET_DATA_SIZE; w.meta.size = PACKET_DATA_SIZE;
w.meta.set_addr(&tn.info.contact_info.ncp); w.meta.set_addr(&tn.info.contact_info.ncp);
} }