Run header sync only when stalled or complete ()

Header sync used to run when complete (right count of blocks
received) or every 10 sec regardless. Sometimes 10 secs is not
enough, especially when a big batch of blocks bodies is arriving
at the same time.

This tweaks the time-based heuristic just a bit to only ask for
headers when stalled, meaning that the header head has not
*progressed* for 10 seconds.

* Fix bad header sync timeout logic

* Improve stability of fast sync test
Adds regular pings so that the 2 test servers know each others'
heights (necessary to find most work peer). Stop mining on the
first server once the 2nd kicks in. Avoids chasing a fast moving
target on Cuckoo10.
This commit is contained in:
Ignotus Peverell 2018-08-22 19:51:25 -04:00 committed by GitHub
parent 7dfca6077c
commit 9554f93e1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 11 deletions
servers

View file

@ -264,6 +264,14 @@ impl Server {
Ok(())
}
/// Ping all peers, mostly useful for tests to have connected peers share
/// their heights
pub fn ping_peers(&self)-> Result<(), Error> {
let head = self.chain.head()?;
self.p2p.peers.check_all(head.total_difficulty, head.height);
Ok(())
}
/// Number of peers
pub fn peer_count(&self) -> u32 {
self.p2p.peers.peer_count()
@ -426,4 +434,9 @@ impl Server {
self.p2p.stop();
self.stop.store(true, Ordering::Relaxed);
}
/// Stops the test miner without stopping the p2p layer
pub fn stop_test_miner(&self) {
self.stop.store(true, Ordering::Relaxed);
}
}

View file

@ -439,7 +439,7 @@ fn get_locator_heights(height: u64) -> Vec<u64> {
// Utility struct to group what information the main sync loop has to track
struct SyncInfo {
prev_body_sync: (DateTime<Utc>, u64),
prev_header_sync: (DateTime<Utc>, u64),
prev_header_sync: (DateTime<Utc>, u64, u64),
prev_fast_sync: Option<DateTime<Utc>>,
highest_height: u64,
}
@ -449,7 +449,7 @@ impl SyncInfo {
let now = Utc::now();
SyncInfo {
prev_body_sync: (now.clone(), 0),
prev_header_sync: (now.clone(), 0),
prev_header_sync: (now.clone(), 0, 0),
prev_fast_sync: None,
highest_height: 0,
}
@ -457,16 +457,24 @@ impl SyncInfo {
fn header_sync_due(&mut self, header_head: &chain::Tip) -> bool {
let now = Utc::now();
let (prev_ts, prev_height) = self.prev_header_sync;
let (timeout, latest_height, prev_height) = self.prev_header_sync;
if header_head.height >= prev_height + (p2p::MAX_BLOCK_HEADERS as u64) - 4
|| now - prev_ts > Duration::seconds(10)
{
self.prev_header_sync = (now, header_head.height);
return true;
// received all necessary headers, can ask for more
let all_headers_received = header_head.height >= prev_height + (p2p::MAX_BLOCK_HEADERS as u64) - 4;
// no headers processed and we're past timeout, need to ask for more
let stalling = header_head.height == latest_height && now > timeout;
if all_headers_received || stalling {
self.prev_header_sync = (now + Duration::seconds(10), header_head.height, header_head.height);
true
} else {
// resetting the timeout as long as we progress
if header_head.height > latest_height {
self.prev_header_sync = (now + Duration::seconds(2), header_head.height, prev_height);
}
false
}
}
fn body_sync_due(&mut self, head: &chain::Tip) -> bool {
let now = Utc::now();

View file

@ -267,7 +267,7 @@ fn simulate_fast_sync() {
let s1 = servers::Server::new(framework::config(2000, "grin-fast", 2000)).unwrap();
s1.start_test_miner(None);
while s1.head().height < 21 {
while s1.head().height < 20 {
thread::sleep(time::Duration::from_millis(1_000));
}
@ -275,9 +275,12 @@ fn simulate_fast_sync() {
conf.archive_mode = Some(false);
let s2 = servers::Server::new(conf).unwrap();
while s2.head().height < 21 {
while s2.header_head().height < 1 {
s2.ping_peers();
thread::sleep(time::Duration::from_millis(1_000));
}
s1.stop_test_miner();
// Get the current header from s1.
let s1_header = s1.chain.head_header().unwrap();