diff --git a/src/concurrency.md b/src/concurrency.md index 56dfdfa..151e874 100644 --- a/src/concurrency.md +++ b/src/concurrency.md @@ -7,6 +7,7 @@ | [Generate jpg thumbnails in parallel][ex-rayon-thumbnails] | [![rayon-badge]][rayon] [![glob-badge]][glob] [![image-badge]][image] | [![cat-concurrency-badge]][cat-concurrency][![cat-filesystem-badge]][cat-filesystem] | | [Spawn a short-lived thread][ex-crossbeam-spawn] | [![crossbeam-badge]][crossbeam] | [![cat-concurrency-badge]][cat-concurrency] | | [Draw fractal dispatching work to a thread pool][ex-threadpool-fractal] | [![threadpool-badge]][threadpool] [![num-badge]][num] [![num_cpus-badge]][num_cpus] [![image-badge]][image] | [![cat-concurrency-badge]][cat-concurrency][![cat-science-badge]][cat-science][![cat-rendering-badge]][cat-rendering] | +| [Calculate SHA1 sum of *.iso files concurrently][threadpool-walk] | [![threadpool-badge]][threadpool] [![walkdir-badge]][walkdir] [![num_cpus-badge]][num_cpus] [![ring-badge]][ring] | [![cat-concurrency-badge]][cat-concurrency][![cat-filesystem-badge]][cat-filesystem] | [ex-rayon-iter-mut]: #ex-rayon-iter-mut @@ -315,6 +316,91 @@ fn run() -> Result<()> { # quick_main!(run); ``` +[threadpool-walk]: #threadpool-walk + + +## Calculate SHA1 sum of *.iso files concurrently + +[![threadpool-badge]][threadpool] [![num_cpus-badge]][num_cpus] [![walkdir-badge]][walkdir] [![ring-badge]][ring] [![cat-concurrency-badge]][cat-concurrency][![cat-filesystem-badge]][cat-filesystem] + +This example calculates the SHA1 for every file present in the current directory. A threadpool is created using the number of cpus present in the system with [`num_cpus::get`]. Then every returned by [`Walkdir::new`] is passed into this pool to perform the operations of reading and computing SHA1. At the end the program waits for all jobs to finish. To get better results, compile this program in release mode. + +```rust,no_run +# #[macro_use] +# extern crate error_chain; +extern crate walkdir; +extern crate ring; +extern crate num_cpus; +extern crate threadpool; + +# error_chain! { +# foreign_links { +# Io(std::io::Error); +# } +# } +# +use walkdir::WalkDir; +use std::fs::File; +use std::io::{BufReader, Read}; +use std::path::Path; +use threadpool::ThreadPool; +use std::sync::mpsc::channel; +use ring::digest::{Context, Digest, SHA1}; + +# // Verify the iso extension +# fn is_iso(entry: &Path) -> bool { +# match entry.extension() { +# Some(e) if e.to_string_lossy().to_lowercase() == "iso" => true, +# _ => false, +# } +# } +# +fn compute_digest>(filepath: P) -> Result<(Digest, P)> { + let mut buf_reader = BufReader::new(File::open(&filepath)?); + let mut context = Context::new(&SHA1); + let mut buffer = [0; 1024]; + + loop { + let count = buf_reader.read(&mut buffer)?; + if count == 0 { + break; + } + context.update(&buffer[..count]); + } + + Ok((context.finish(), filepath)) +} + +fn run() -> Result<()> { + let pool = ThreadPool::new(num_cpus::get()); + + let (tx, rx) = channel(); + + // Look in the current directory. + for entry in WalkDir::new("/home/user/Downloads") + .follow_links(true) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| !e.path().is_dir() && is_iso(e.path())) { + let path = entry.path().to_owned(); + let tx = tx.clone(); + pool.execute(move || { + let digest = compute_digest(path); + tx.send(digest).expect("Could not send data!"); + }); + } + + drop(tx); + for t in rx.iter() { + let (sha, path) = t?; + println!("{:?} {:?}", sha, path); + } + Ok(()) +} +# +# quick_main!(run); +``` + {{#include links.md}} @@ -337,6 +423,7 @@ fn run() -> Result<()> { [`par_iter`]: https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefIterator.html#tymethod.par_iter [`par_iter_mut`]: https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefMutIterator.html#tymethod.par_iter_mut [`par_sort_unstable`]: https://docs.rs/rayon/*/rayon/slice/trait.ParallelSliceMut.html#method.par_sort_unstable +[`Walkdir::new`]: https://docs.rs/walkdir/1.0.7/walkdir/struct.WalkDir.html#method.new diff --git a/src/intro.md b/src/intro.md index 591210d..36f5725 100644 --- a/src/intro.md +++ b/src/intro.md @@ -65,6 +65,7 @@ community. It needs and welcomes help. For details see | [Generate jpg thumbnails in parallel][ex-rayon-thumbnails] | [![rayon-badge]][rayon] [![glob-badge]][glob] [![image-badge]][image] | [![cat-concurrency-badge]][cat-concurrency][![cat-filesystem-badge]][cat-filesystem] | | [Spawn a short-lived thread][ex-crossbeam-spawn] | [![crossbeam-badge]][crossbeam] | [![cat-concurrency-badge]][cat-concurrency] | | [Draw fractal dispatching work to a thread pool][ex-threadpool-fractal] | [![threadpool-badge]][threadpool] [![num-badge]][num] [![num_cpus-badge]][num_cpus] [![image-badge]][image] | [![cat-concurrency-badge]][cat-concurrency][![cat-science-badge]][cat-science][![cat-rendering-badge]][cat-rendering] | +| [Calculate SHA1 sum of *.iso files concurrently][threadpool-walk] | [![threadpool-badge]][threadpool] [![walkdir-badge]][walkdir] [![num_cpus-badge]][num_cpus] [![ring-badge]][ring] | [![cat-concurrency-badge]][cat-concurrency][![cat-filesystem-badge]][cat-filesystem] | ## [Networking](net.html)