#include "common.hh" #include "hash_method.hh" #include "hasher.hh" #include "io.hh" #include "logger.hh" #include "task_runner.hh" #include #include namespace { class HasherImpl : public Hasher { public: HasherImpl(std::shared_ptr logger, std::shared_ptr runner, size_t threads) : logger_(std::move(logger)), runner_(std::move(runner)), workers_(TaskRunner::create(threads)) { } void hash(std::filesystem::path path, std::function callback) override { workers_->post(std::bind(&HasherImpl::do_hash, this, path, callback)); } private: void do_hash(std::filesystem::path path, std::function callback) { auto fd = io::open(path, io::open_flags::rdonly); std::string result; uint64_t size = 0; if (fd) { auto method = HashMethod::sha256(); char buffer[1 * 1024 * 1024]; while (true) { auto got = io::read(fd.get(), buffer, sizeof(buffer)); if (got < 0) { logger_->warn("Error reading: %s: %s", path.c_str(), strerror(errno)); size = 0; break; } if (got == 0) { result = method->finish(); break; } size += got; method->update(buffer, got); } } else { logger_->warn("Unable to open: %s: %s", path.c_str(), strerror(errno)); } runner_->post(std::bind(callback, result, size)); } std::shared_ptr logger_; std::shared_ptr runner_; std::unique_ptr workers_; }; } // namespace std::unique_ptr Hasher::create(std::shared_ptr logger, std::shared_ptr runner, size_t threads) { return std::make_unique(std::move(logger), std::move(runner), threads); }