| 539 | } |
| 540 | |
| 541 | void node_impl::fetch_sync_items_loop() |
| 542 | { |
| 543 | VERIFY_CORRECT_THREAD(); |
| 544 | while( !_fetch_sync_items_loop_done.canceled() ) |
| 545 | { |
| 546 | _sync_items_to_fetch_updated = false; |
| 547 | dlog( "beginning another iteration of the sync items loop" ); |
| 548 | |
| 549 | if (!_suspend_fetching_sync_blocks) |
| 550 | { |
| 551 | std::map<peer_connection_ptr, std::vector<item_hash_t> > sync_item_requests_to_send; |
| 552 | |
| 553 | { |
| 554 | std::set<item_hash_t> sync_items_to_request; |
| 555 | |
| 556 | // for each idle peer that we're syncing with |
| 557 | fc::scoped_lock<fc::mutex> lock(_active_connections.get_mutex()); |
| 558 | for( const peer_connection_ptr& peer : _active_connections ) |
| 559 | { |
| 560 | if( peer->we_need_sync_items_from_peer && |
| 561 | // if we've already scheduled a request for this peer, don't consider scheduling another |
| 562 | sync_item_requests_to_send.find(peer) == sync_item_requests_to_send.end() && |
| 563 | peer->idle() ) |
| 564 | { |
| 565 | if (!peer->inhibit_fetching_sync_blocks) |
| 566 | { |
| 567 | // loop through the items it has that we don't yet have on our blockchain |
| 568 | for( const auto& item_to_potentially_request : peer->ids_of_items_to_get ) |
| 569 | { |
| 570 | // if we don't already have this item in our temporary storage |
| 571 | // and we haven't requested from another syncing peer |
| 572 | if( // already got it, but for some reson it's still in our list of items to fetch |
| 573 | !have_already_received_sync_item(item_to_potentially_request) && |
| 574 | // we have already decided to request it from another peer during this iteration |
| 575 | sync_items_to_request.find(item_to_potentially_request) == sync_items_to_request.end() && |
| 576 | // we've requested it in a previous iteration and we're still waiting for it to arrive |
| 577 | _active_sync_requests.find(item_to_potentially_request) == _active_sync_requests.end() ) |
| 578 | { |
| 579 | // then schedule a request from this peer |
| 580 | sync_item_requests_to_send[peer].push_back(item_to_potentially_request); |
| 581 | sync_items_to_request.insert( item_to_potentially_request ); |
| 582 | if (sync_item_requests_to_send[peer].size() >= _max_sync_blocks_per_peer) |
| 583 | break; |
| 584 | } |
| 585 | } |
| 586 | } |
| 587 | } |
| 588 | } |
| 589 | } // end non-preemptable section |
| 590 | |
| 591 | // make all the requests we scheduled in the loop above |
| 592 | for( auto sync_item_request : sync_item_requests_to_send ) |
| 593 | request_sync_items_from_peer( sync_item_request.first, sync_item_request.second ); |
| 594 | sync_item_requests_to_send.clear(); |
| 595 | } |
| 596 | else |
| 597 | dlog("fetch_sync_items_loop is suspended pending backlog processing"); |
| 598 | |