Improve block and transaction propagation (#9954)

* Refactor sync to add priority tasks.

* Send priority tasks notifications.

* Propagate blocks, optimize transactions.

* Implement transaction propagation. Use sync_channel.

* Tone down info.

* Prevent deadlock by not waiting forever for sync lock.

* Fix lock order.

* Don't use sync_channel to prevent deadlocks.

* Fix tests.
This commit is contained in:
Tomasz Drwięga
2018-11-28 10:30:05 +00:00
committed by Afri Schoedon
parent 14c9cbd40e
commit 0b5bbf6048
18 changed files with 631 additions and 300 deletions

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc;
use std::sync::{Arc, mpsc};
use ethcore::client::BlockChainClient;
use sync::{self, AttachedProtocol, SyncConfig, NetworkConfiguration, Params, ConnectionFilter};
@@ -25,12 +25,17 @@ pub use sync::{EthSync, SyncProvider, ManageNetwork, PrivateTxHandler};
pub use ethcore::client::ChainNotify;
use ethcore_logger::Config as LogConfig;
pub type SyncModules = (Arc<SyncProvider>, Arc<ManageNetwork>, Arc<ChainNotify>);
pub type SyncModules = (
Arc<SyncProvider>,
Arc<ManageNetwork>,
Arc<ChainNotify>,
mpsc::Sender<sync::PriorityTask>,
);
pub fn sync(
sync_cfg: SyncConfig,
net_cfg: NetworkConfiguration,
client: Arc<BlockChainClient>,
config: SyncConfig,
network_config: NetworkConfiguration,
chain: Arc<BlockChainClient>,
snapshot_service: Arc<SnapshotService>,
private_tx_handler: Arc<PrivateTxHandler>,
provider: Arc<Provider>,
@@ -39,15 +44,20 @@ pub fn sync(
connection_filter: Option<Arc<ConnectionFilter>>,
) -> Result<SyncModules, sync::Error> {
let eth_sync = EthSync::new(Params {
config: sync_cfg,
chain: client,
provider: provider,
snapshot_service: snapshot_service,
config,
chain,
provider,
snapshot_service,
private_tx_handler,
network_config: net_cfg,
attached_protos: attached_protos,
network_config,
attached_protos,
},
connection_filter)?;
Ok((eth_sync.clone() as Arc<SyncProvider>, eth_sync.clone() as Arc<ManageNetwork>, eth_sync.clone() as Arc<ChainNotify>))
Ok((
eth_sync.clone() as Arc<SyncProvider>,
eth_sync.clone() as Arc<ManageNetwork>,
eth_sync.clone() as Arc<ChainNotify>,
eth_sync.priority_tasks()
))
}

View File

@@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::any::Any;
use std::sync::{Arc, Weak};
use std::sync::{Arc, Weak, atomic};
use std::time::{Duration, Instant};
use std::thread;
@@ -480,7 +480,6 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
cmd.gas_pricer_conf.to_gas_pricer(fetch.clone(), runtime.executor()),
&spec,
Some(account_provider.clone()),
));
miner.set_author(cmd.miner_extras.author, None).expect("Fails only if password is Some; password is None; qed");
miner.set_gas_range_target(cmd.miner_extras.gas_range_target);
@@ -637,7 +636,7 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
};
// create sync object
let (sync_provider, manage_network, chain_notify) = modules::sync(
let (sync_provider, manage_network, chain_notify, priority_tasks) = modules::sync(
sync_config,
net_conf.clone().into(),
client.clone(),
@@ -651,6 +650,18 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
service.add_notify(chain_notify.clone());
// Propagate transactions as soon as they are imported.
let tx = ::parking_lot::Mutex::new(priority_tasks);
let is_ready = Arc::new(atomic::AtomicBool::new(true));
miner.add_transactions_listener(Box::new(move |_hashes| {
// we want to have only one PendingTransactions task in the queue.
if is_ready.compare_and_swap(true, false, atomic::Ordering::SeqCst) {
let task = ::sync::PriorityTask::PropagateTransactions(Instant::now(), is_ready.clone());
// we ignore error cause it means that we are closing
let _ = tx.lock().send(task);
}
}));
// provider not added to a notification center is effectively disabled
// TODO [debris] refactor it later on
if cmd.private_tx_enabled {
@@ -737,7 +748,7 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
let secretstore_deps = secretstore::Dependencies {
client: client.clone(),
sync: sync_provider.clone(),
miner: miner,
miner: miner.clone(),
account_provider: account_provider,
accounts_passwords: &passwords,
};