From 434eaffd4c7bee36a4634e22ca13ae7615cedd3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 21 Mar 2022 13:15:37 +0100 Subject: [PATCH] import-blocks: Do not read `stdin` to memory (#11072) * import-blocks: Do not read `stdin` to memory This fixes a bug with `import-blocks` reading the entire `stdin` before starting to import the blocks. However, for huge files that uses quite a lot of memory. We can just read from `stdin` step by step as we do it with a file. This ensures that we don't read the entire input at once into memory. * FMT * Fix warning --- .../client/cli/src/commands/import_blocks_cmd.rs | 8 ++------ .../client/service/src/chain_ops/import_blocks.rs | 15 ++++++++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/substrate/client/cli/src/commands/import_blocks_cmd.rs b/substrate/client/cli/src/commands/import_blocks_cmd.rs index fece33ba23..749824834b 100644 --- a/substrate/client/cli/src/commands/import_blocks_cmd.rs +++ b/substrate/client/cli/src/commands/import_blocks_cmd.rs @@ -72,13 +72,9 @@ impl ImportBlocksCmd { B: BlockT + for<'de> serde::Deserialize<'de>, IQ: sc_service::ImportQueue + 'static, { - let file: Box = match &self.input { + let file: Box = match &self.input { Some(filename) => Box::new(fs::File::open(filename)?), - None => { - let mut buffer = Vec::new(); - io::stdin().read_to_end(&mut buffer)?; - Box::new(io::Cursor::new(buffer)) - }, + None => Box::new(io::stdin()), }; import_blocks(client, import_queue, file, false, self.binary) diff --git a/substrate/client/service/src/chain_ops/import_blocks.rs b/substrate/client/service/src/chain_ops/import_blocks.rs index 9d74fa1c27..dc03cdceda 100644 --- a/substrate/client/service/src/chain_ops/import_blocks.rs +++ b/substrate/client/service/src/chain_ops/import_blocks.rs @@ -36,7 +36,7 @@ use sp_runtime::{ }; use std::{ convert::{TryFrom, TryInto}, - io::{Read, Seek}, + io::Read, pin::Pin, task::Poll, time::{Duration, Instant}, @@ -63,7 +63,7 @@ pub fn build_spec(spec: &dyn ChainSpec, raw: bool) -> error::Result { /// SignedBlock and return it. enum BlockIter where - R: std::io::Read + std::io::Seek, + R: std::io::Read, { Binary { // Total number of blocks we are expecting to decode. @@ -83,7 +83,7 @@ where impl BlockIter where - R: Read + Seek + 'static, + R: Read + 'static, B: BlockT + MaybeSerializeDeserialize, { fn new(input: R, binary: bool) -> Result { @@ -119,7 +119,7 @@ where impl Iterator for BlockIter where - R: Read + Seek + 'static, + R: Read + 'static, B: BlockT + MaybeSerializeDeserialize, { type Item = Result, String>; @@ -267,10 +267,11 @@ impl Speedometer { /// Different State that the `import_blocks` future could be in. enum ImportState where - R: Read + Seek + 'static, + R: Read + 'static, B: BlockT + MaybeSerializeDeserialize, { - /// We are reading from the BlockIter structure, adding those blocks to the queue if possible. + /// We are reading from the [`BlockIter`] structure, adding those blocks to the queue if + /// possible. Reading { block_iter: BlockIter }, /// The queue is full (contains at least MAX_PENDING_BLOCKS blocks) and we are waiting for it /// to catch up. @@ -291,7 +292,7 @@ where pub fn import_blocks( client: Arc, mut import_queue: IQ, - input: impl Read + Seek + Send + 'static, + input: impl Read + Send + 'static, force: bool, binary: bool, ) -> Pin> + Send>>