mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-03 05:17:24 +00:00
Remove blocking operations in SyncOracle implementation (#1852)
* remove blocking operations in SyncOracle implementation * docs * docs
This commit is contained in:
committed by
Gav Wood
parent
733ce7d616
commit
077ed00951
@@ -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,
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user