use std::thread;
use std::thread::JoinHandle;
use anyhow::Context;
use crossbeam::channel::{Receiver, Sender};
use crate::candidate_selection::hashing::{FileHasher, HashInstructions};
use crate::candidate_selection::messages::WorkerMessage::{HashComputed, NotHashable};
use crate::candidate_selection::messages::{
CoordinatorMessage, FileWithDescriptor, HashComputedResult, WorkerMessage,
};
pub struct Worker {
work_in: Receiver<CoordinatorMessage>,
work_out: Sender<WorkerMessage>,
file_hasher: FileHasher,
}
impl Worker {
pub fn new(
work_in: Receiver<CoordinatorMessage>,
work_out: Sender<WorkerMessage>,
buffer_size: usize,
) -> Self {
let file_hasher = FileHasher::new(buffer_size);
Worker {
work_in,
work_out,
file_hasher,
}
}
pub fn work(mut self) -> JoinHandle<::anyhow::Result<Worker>> {
thread::spawn(move || {
self.work_internal()?;
Ok(self)
})
}
fn work_internal(&mut self) -> ::anyhow::Result<()> {
while let Ok(CoordinatorMessage::HashCommand(file_with_handle, instructions)) =
self.work_in.recv()
{
self.hash(file_with_handle, instructions)?;
}
Ok(())
}
fn hash(
&mut self,
file_with_handle: FileWithDescriptor,
instructions: HashInstructions,
) -> ::anyhow::Result<()> {
let mut file_with_handle = file_with_handle;
match self
.file_hasher
.hash(&mut file_with_handle.file, &instructions)
{
Ok(hash) => {
let result = HashComputedResult { instructions, hash };
self.work_out
.send(HashComputed(file_with_handle, result))
.context("Worker failed to send hash result")
}
Err(_) => self
.work_out
.send(NotHashable(file_with_handle))
.context("Worker failed to send not hashable message"),
}?;
Ok(())
}
}