added jointypes to the stages in the tpu involved in leader rotation

This commit is contained in:
Carl 2018-09-14 00:17:40 -07:00 committed by Greg Fitzgerald
parent 062f654fe0
commit 1fb1c0a681
4 changed files with 76 additions and 88 deletions

View File

@ -11,12 +11,12 @@ use clap::{App, Arg};
use solana::client::mk_client;
use solana::crdt::Node;
use solana::drone::DRONE_PORT;
use solana::fullnode::{Config, Fullnode};
use solana::fullnode::{Config, Fullnode, NodeRole};
use solana::logger;
use solana::metrics::set_panic_hook;
use solana::service::Service;
use solana::signature::{Keypair, KeypairUtil};
use solana::thin_client::poll_gossip_for_leader;
use solana::tpu::TpuReturnType;
use solana::wallet::request_airdrop;
use std::fs::File;
use std::net::{Ipv4Addr, SocketAddr};
@ -84,7 +84,7 @@ fn main() -> () {
let node_info = node.info.clone();
let pubkey = keypair.pubkey();
let fullnode = Fullnode::new(node, ledger_path, keypair, network, false);
let mut fullnode = Fullnode::new(node, ledger_path, keypair, network, false);
// airdrop stuff, probably goes away at some point
let leader = match network {
@ -124,18 +124,24 @@ fn main() -> () {
}
}
/*loop {
match fullnode.node_role {
NodeRole::Leader(leader_services) => {
// TODO: return an exit code that signals we should do a role switch
leader_services.join();
//fullnode.start_tvu();
},
NodeRole::Validator(validator_services) => {
validator_services.join();
loop {
let node_role = fullnode.node_role.take();
match node_role {
Some(NodeRole::Leader(leader_services)) => {
match leader_services.join() {
Ok(Some(TpuReturnType::LeaderRotation)) => (),
//fullnode.start_tvu();
Err(e) => {
eprintln!("Leader returned error: {:?}", e);
exit(1);
}
_ => (),
}
}
Some(NodeRole::Validator(validator_services)) => {
let _ = validator_services.join();
}
_ => (),
}
}*/
let _ = fullnode.join();
}
}

View File

@ -20,6 +20,12 @@ use std::time::{Duration, Instant};
use timing::duration_as_ms;
use window::{self, SharedWindow, WindowIndex, WindowUtil, WINDOW_SIZE};
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum BroadcastStageReturnType {
LeaderRotation,
ChannelDisconnected,
}
fn broadcast(
node_info: &NodeInfo,
broadcast_table: &[NodeInfo],
@ -143,7 +149,7 @@ fn broadcast(
}
pub struct BroadcastStage {
thread_hdl: JoinHandle<()>,
thread_hdl: JoinHandle<BroadcastStageReturnType>,
}
impl BroadcastStage {
@ -154,7 +160,7 @@ impl BroadcastStage {
entry_height: u64,
recycler: &BlobRecycler,
receiver: &Receiver<Vec<Entry>>,
) {
) -> BroadcastStageReturnType {
let mut transmit_index = WindowIndex {
data: entry_height,
coding: entry_height,
@ -170,7 +176,7 @@ impl BroadcastStage {
// If the leader stays in power for the next
// round as well, then we don't exit. Otherwise, exit.
_ => {
return;
return BroadcastStageReturnType::LeaderRotation;
}
}
}
@ -187,7 +193,9 @@ impl BroadcastStage {
&mut receive_index,
) {
match e {
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => break,
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => {
return BroadcastStageReturnType::ChannelDisconnected
}
Error::RecvTimeoutError(RecvTimeoutError::Timeout) => (),
Error::CrdtError(CrdtError::NoPeers) => (), // TODO: Why are the unit-tests throwing hundreds of these?
_ => {
@ -218,17 +226,7 @@ impl BroadcastStage {
) -> Self {
let thread_hdl = Builder::new()
.name("solana-broadcaster".to_string())
.spawn(move || {
Self::run(
&sock,
&crdt,
&window,
entry_height,
&recycler,
&receiver,
exit_sender,
);
})
.spawn(move || Self::run(&sock, &crdt, &window, entry_height, &recycler, &receiver))
.unwrap();
BroadcastStage { thread_hdl }
@ -236,32 +234,26 @@ impl BroadcastStage {
}
impl Service for BroadcastStage {
type JoinReturnType = ();
type JoinReturnType = BroadcastStageReturnType;
fn join(self) -> thread::Result<()> {
self.thread_hdl.join()?;
Ok(())
fn join(self) -> thread::Result<BroadcastStageReturnType> {
self.thread_hdl.join()
}
}
#[cfg(test)]
mod tests {
use broadcast_stage::BroadcastStage;
use broadcast_stage::{BroadcastStage, BroadcastStageReturnType};
use crdt::{Crdt, Node, LEADER_ROTATION_INTERVAL};
use entry::Entry;
use hash::Hash;
use ledger::Block;
use mint::Mint;
use packet::BlobRecycler;
use recorder::Recorder;
use service::Service;
use signature::{Keypair, KeypairUtil, Pubkey};
use std::cmp;
use std::sync::mpsc::{channel, Receiver};
use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, RwLock};
use std::thread::sleep;
use std::time::Duration;
use streamer::BlobSender;
use window::{new_window_from_entries, SharedWindow};
fn setup_dummy_broadcast_stage() -> (
@ -269,11 +261,9 @@ mod tests {
Pubkey,
BroadcastStage,
SharedWindow,
BlobSender,
BlobRecycler,
Sender<Vec<Entry>>,
Arc<RwLock<Crdt>>,
Vec<Entry>,
Receiver<bool>,
) {
// Setup dummy leader info
let leader_keypair = Keypair::new();
@ -302,8 +292,7 @@ mod tests {
let shared_window = Arc::new(RwLock::new(window));
let (blob_sender, blob_receiver) = channel();
let (exit_sender, exit_receiver) = channel();
let (entry_sender, entry_receiver) = channel();
// Start up the broadcast stage
let broadcast_stage = BroadcastStage::new(
@ -312,8 +301,7 @@ mod tests {
shared_window.clone(),
entry_height,
blob_recycler.clone(),
blob_receiver,
exit_sender,
entry_receiver,
);
(
@ -321,11 +309,9 @@ mod tests {
buddy_id,
broadcast_stage,
shared_window,
blob_sender,
blob_recycler,
entry_sender,
crdt,
entries,
exit_receiver,
)
}
@ -342,17 +328,8 @@ mod tests {
#[test]
fn test_broadcast_stage_leader_rotation_exit() {
let (
id,
buddy_id,
broadcast_stage,
shared_window,
blob_sender,
blob_recycler,
crdt,
entries,
exit_receiver,
) = setup_dummy_broadcast_stage();
let (id, buddy_id, broadcast_stage, shared_window, entry_sender, crdt, entries) =
setup_dummy_broadcast_stage();
{
let mut wcrdt = crdt.write().unwrap();
// Set leader to myself
@ -371,8 +348,7 @@ mod tests {
for _ in genesis_len..LEADER_ROTATION_INTERVAL {
let new_entry = recorder.record(vec![]);
let blob = new_entry.to_blobs(&blob_recycler);
blob_sender.send(blob).unwrap();
entry_sender.send(new_entry).unwrap();
}
// Set the scheduled next leader in the crdt to the other buddy on the network
@ -385,23 +361,22 @@ mod tests {
// it's no longer the leader after checking the crdt, and exit
for _ in 0..LEADER_ROTATION_INTERVAL {
let new_entry = recorder.record(vec![]);
let blob = new_entry.to_blobs(&blob_recycler);
match blob_sender.send(blob) {
match entry_sender.send(new_entry) {
// We disconnected, break out of loop and check the results
Err(_) => break,
_ => (),
};
}
match exit_receiver.recv() {
Ok(x) if x == false => panic!("Unexpected value on exit channel for Broadcast stage"),
_ => (),
}
let highest_index = find_highest_window_index(&shared_window);
// TODO: 2 * LEADER_ROTATION_INTERVAL - 1 due to the same bug in
// index_blobs() as mentioned above
assert_eq!(highest_index, 2 * LEADER_ROTATION_INTERVAL - 1);
// Make sure the threads closed cleanly
broadcast_stage.join().unwrap();
assert_eq!(
broadcast_stage.join().unwrap(),
BroadcastStageReturnType::LeaderRotation
);
}
}

View File

@ -16,7 +16,7 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
use std::thread::Result;
use tpu::Tpu;
use tpu::{Tpu, TpuReturnType};
use tvu::Tvu;
use untrusted::Input;
use window;
@ -39,9 +39,9 @@ impl LeaderServices {
}
}
pub fn join(self) -> Result<()> {
self.tpu.join()?;
self.broadcast_stage.join()
pub fn join(self) -> Result<Option<TpuReturnType>> {
self.broadcast_stage.join()?;
self.tpu.join()
}
}
@ -59,7 +59,7 @@ impl ValidatorServices {
}
}
pub enum FullNodeReturnType {
pub enum FullnodeReturnType {
LeaderRotation,
}
@ -327,16 +327,16 @@ impl Fullnode {
self.exit.store(true, Ordering::Relaxed);
}
pub fn close(self) -> Result<(Option<FullNodeReturnType>)> {
pub fn close(self) -> Result<(Option<FullnodeReturnType>)> {
self.exit();
self.join()
}
}
impl Service for Fullnode {
type JoinReturnType = Option<FullNodeReturnType>;
type JoinReturnType = Option<FullnodeReturnType>;
fn join(self) -> Result<Option<FullNodeReturnType>> {
fn join(self) -> Result<Option<FullnodeReturnType>> {
self.rpu.join()?;
self.ncp.join()?;
self.rpc_service.join()?;
@ -346,7 +346,9 @@ impl Service for Fullnode {
validator_service.join()?;
}
Some(NodeRole::Leader(leader_service)) => {
leader_service.join()?;
if let Some(TpuReturnType::LeaderRotation) = leader_service.join()? {
return Ok(Some(FullnodeReturnType::LeaderRotation));
}
}
_ => (),
}

View File

@ -41,7 +41,11 @@ use std::sync::mpsc::Receiver;
use std::sync::{Arc, RwLock};
use std::thread;
use std::time::Duration;
use write_stage::WriteStage;
use write_stage::{WriteStage, WriteStageReturnType};
pub enum TpuReturnType {
LeaderRotation,
}
pub struct Tpu {
fetch_stage: FetchStage,
@ -103,22 +107,23 @@ impl Tpu {
(tpu, entry_forwarder)
}
pub fn close(self) -> thread::Result<()> {
pub fn close(self) -> thread::Result<Option<TpuReturnType>> {
self.fetch_stage.close();
self.join()
}
}
impl Service for Tpu {
type JoinReturnType = ();
type JoinReturnType = Option<TpuReturnType>;
fn join(self) -> thread::Result<()> {
fn join(self) -> thread::Result<(Option<TpuReturnType>)> {
self.fetch_stage.join()?;
self.sigverify_stage.join()?;
self.banking_stage.join()?;
self.record_stage.join()?;
self.write_stage.join()?;
Ok(())
match self.write_stage.join()? {
WriteStageReturnType::LeaderRotation => Ok(Some(TpuReturnType::LeaderRotation)),
_ => Ok(None),
}
}
}