Remove blocking operations in SyncOracle implementation (#1852)

* remove blocking operations in SyncOracle implementation

* docs

* docs
This commit is contained in:
Gregory Terzian
2019-02-25 21:00:13 +08:00
committed by Gav Wood
parent 733ce7d616
commit 077ed00951
5 changed files with 178 additions and 42 deletions
+24 -7
View File
@@ -23,6 +23,7 @@ mod sync;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
@@ -44,7 +45,7 @@ use network_libp2p::{NodeIndex, ProtocolId};
use parity_codec::Encode;
use parking_lot::Mutex;
use primitives::{H256, Ed25519AuthorityId};
use crate::protocol::{Context, Protocol, ProtocolMsg, ProtocolStatus};
use crate::protocol::{Context, Protocol, ProtocolMsg};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor};
use runtime_primitives::Justification;
@@ -117,6 +118,8 @@ impl NetworkSpecialization<Block> for DummySpecialization {
pub type PeersClient = client::Client<test_client::Backend, test_client::Executor, Block, test_client::runtime::RuntimeApi>;
pub struct Peer<D> {
pub is_offline: Arc<AtomicBool>,
pub is_major_syncing: Arc<AtomicBool>,
client: Arc<PeersClient>,
pub protocol_sender: Sender<ProtocolMsg<Block, DummySpecialization>>,
@@ -130,6 +133,8 @@ pub struct Peer<D> {
impl<D> Peer<D> {
fn new(
is_offline: Arc<AtomicBool>,
is_major_syncing: Arc<AtomicBool>,
client: Arc<PeersClient>,
import_queue: Box<ImportQueue<Block>>,
protocol_sender: Sender<ProtocolMsg<Block, DummySpecialization>>,
@@ -139,6 +144,8 @@ impl<D> Peer<D> {
) -> Self {
let network_port = Mutex::new(network_port);
Peer {
is_offline,
is_major_syncing,
client,
protocol_sender,
import_queue,
@@ -179,6 +186,16 @@ impl<D> Peer<D> {
.send(ProtocolMsg::BlockImported(hash, header.clone()));
}
// SyncOracle: are we connected to any peer?
fn is_offline(&self) -> bool {
self.is_offline.load(Ordering::Relaxed)
}
// SyncOracle: are we in the process of catching-up with the chain?
fn is_major_syncing(&self) -> bool {
self.is_major_syncing.load(Ordering::Relaxed)
}
/// Called on connection to other indicated peer.
fn on_connect(&self, other: NodeIndex) {
let _ = self.protocol_sender.send(ProtocolMsg::PeerConnected(other, String::new()));
@@ -266,12 +283,6 @@ impl<D> Peer<D> {
let _ = self.protocol_sender.send(ProtocolMsg::Abort);
}
pub fn status(&self) -> ProtocolStatus<Block> {
let (sender, port) = channel::unbounded();
let _ = self.protocol_sender.send(ProtocolMsg::Status(sender));
port.recv().unwrap()
}
/// Push a message into the gossip network and relay to peers.
/// `TestNet::sync_step` needs to be called to ensure it's propagated.
pub fn gossip_message(&self, topic: <Block as BlockT>::Hash, engine_id: ConsensusEngineId, data: Vec<u8>) {
@@ -467,7 +478,11 @@ pub trait TestNetFactory: Sized {
let import_queue = Box::new(BasicQueue::new(verifier, block_import, justification_import));
let specialization = DummySpecialization {};
let is_offline = Arc::new(AtomicBool::new(true));
let is_major_syncing = Arc::new(AtomicBool::new(false));
let protocol_sender = Protocol::new(
is_offline.clone(),
is_major_syncing.clone(),
network_sender.clone(),
config.clone(),
client.clone(),
@@ -478,6 +493,8 @@ pub trait TestNetFactory: Sized {
).unwrap();
let peer = Arc::new(Peer::new(
is_offline,
is_major_syncing,
client,
import_queue,
protocol_sender,
+70 -3
View File
@@ -19,10 +19,78 @@ use client::blockchain::HeaderBackend as BlockchainHeaderBackend;
use crate::config::Roles;
use consensus::BlockOrigin;
use network_libp2p::NodeIndex;
use crate::sync::SyncState;
use std::collections::HashSet;
use std::thread;
use std::time::Duration;
use super::*;
#[test]
fn sync_cycle_from_offline_to_syncing_to_offline() {
let _ = ::env_logger::try_init();
let mut net = TestNet::new(3);
for peer in 0..3 {
// Offline, and not major syncing.
assert!(net.peer(peer).is_offline());
assert!(!net.peer(peer).is_major_syncing());
}
// Generate blocks.
net.peer(2).push_blocks(100, false);
net.start();
net.route_fast();
thread::sleep(Duration::from_millis(100));
net.route_fast();
for peer in 0..3 {
// Online
assert!(!net.peer(peer).is_offline());
if peer < 2 {
// Major syncing.
assert!(net.peer(peer).is_major_syncing());
}
}
net.sync();
for peer in 0..3 {
// All done syncing.
assert!(!net.peer(peer).is_major_syncing());
}
// Now disconnect them all.
for peer in 0..3 {
for other in 0..3 {
if other != peer {
net.peer(peer).on_disconnect(other);
}
}
thread::sleep(Duration::from_millis(100));
assert!(net.peer(peer).is_offline());
assert!(!net.peer(peer).is_major_syncing());
}
}
#[test]
fn syncing_node_not_major_syncing_when_disconnected() {
let _ = ::env_logger::try_init();
let mut net = TestNet::new(3);
// Generate blocks.
net.peer(2).push_blocks(100, false);
net.start();
net.route_fast();
thread::sleep(Duration::from_millis(100));
net.route_fast();
// Peer 1 is major-syncing.
assert!(net.peer(1).is_major_syncing());
// Disconnect peer 1 form everyone else.
net.peer(1).on_disconnect(0);
net.peer(1).on_disconnect(2);
thread::sleep(Duration::from_millis(100));
// Peer 1 is not major-syncing.
assert!(!net.peer(1).is_major_syncing());
}
#[test]
fn sync_from_two_peers_works() {
let _ = ::env_logger::try_init();
@@ -32,8 +100,7 @@ fn sync_from_two_peers_works() {
net.sync();
assert!(net.peer(0).client.backend().as_in_memory().blockchain()
.equals_to(net.peer(1).client.backend().as_in_memory().blockchain()));
let status = net.peer(0).status();
assert_eq!(status.sync.state, SyncState::Idle);
assert!(!net.peer(0).is_major_syncing());
}
#[test]