1
0
Fork 0
mirror of https://github.com/KingDuckZ/dindexer.git synced 2024-11-29 01:33:46 +00:00

Improve progress output.

This commit is contained in:
King_DuckZ 2015-11-13 15:45:28 +00:00
parent 8d4e8b86b1
commit f48626960d
3 changed files with 89 additions and 17 deletions

View file

@ -23,7 +23,7 @@
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
#include <stdexcept>
#if defined(WITH_PROGRESS_FEEDBACK)
# include <atomic>
# include <condition_variable>
@ -31,6 +31,9 @@
#include <cstdint>
#include <ciso646>
#include <cassert>
#include <boost/iterator/filter_iterator.hpp>
#include <sstream>
#include <iterator>
#if defined(INDEXER_VERBOSE)
# include <iostream>
@ -65,7 +68,9 @@ namespace din {
};
namespace {
void hash_dir (std::vector<FileEntry>::iterator parEntry, std::vector<FileEntry>::iterator parEnd, const PathName& parCurrDir, std::function<void()> parItemDoneCallback) {
typedef std::vector<FileEntry>::iterator FileEntryIt;
void hash_dir (FileEntryIt parEntry, FileEntryIt parBegin, FileEntryIt parEnd, const PathName& parCurrDir, std::function<void(std::size_t)> parNextItemCallback) {
assert(parEntry != parEnd);
assert(parEntry->is_dir);
FileEntry& curr_entry = *parEntry;
@ -94,7 +99,7 @@ namespace din {
while (parEnd != it_entry and it_entry->level == curr_entry_it->level + 1 and parCurrDir == PathName(it_entry->path).pop_right()) {
PathName curr_subdir(it_entry->path);
if (it_entry->is_dir) {
hash_dir(it_entry, parEnd, curr_subdir, parItemDoneCallback);
hash_dir(it_entry, parBegin, parEnd, curr_subdir, parNextItemCallback);
std::string relpath = make_relative_path(parCurrDir, curr_subdir).path();
const auto old_size = dir_blob.size();
@ -136,8 +141,8 @@ namespace din {
#if defined(INDEXER_VERBOSE)
std::cout << "Hashing file " << it_entry->path << "...";
#endif
parNextItemCallback(it_entry - parBegin);
tiger_file(it_entry->path, it_entry->hash, curr_entry_it->hash, it_entry->file_size);
parItemDoneCallback();
#if defined(INDEXER_VERBOSE)
std::cout << ' ' << tiger_to_string(it_entry->hash) << '\n';
#endif
@ -148,8 +153,12 @@ namespace din {
#if defined(INDEXER_VERBOSE)
std::cout << "Final hash for dir " << parCurrDir << " is " << tiger_to_string(curr_entry_it->hash) << '\n';
#endif
//parItemDoneCallback();
}
template <bool FileTrue=true>
struct IsFile {
bool operator() ( const FileEntry& parEntry ) const { return parEntry.is_dir xor FileTrue; }
};
} //unnamed namespace
struct Indexer::LocalData {
@ -159,6 +168,7 @@ namespace din {
PathList paths;
#if defined(WITH_PROGRESS_FEEDBACK)
std::atomic<std::size_t> done_count;
std::atomic<std::size_t> processing_index;
std::condition_variable step_notify;
#endif
std::size_t file_count;
@ -198,6 +208,7 @@ namespace din {
#endif
#if defined(WITH_PROGRESS_FEEDBACK)
m_local_data->done_count = 0;
m_local_data->processing_index = 0;
#endif
m_local_data->file_count = 0;
m_local_data->db_settings = parDBSettings;
@ -237,11 +248,13 @@ namespace din {
#if defined(WITH_PROGRESS_FEEDBACK)
m_local_data->done_count = 0;
hash_dir(
m_local_data->paths.begin(),
m_local_data->paths.begin(),
m_local_data->paths.end(),
base_path,
[=]() {
[=](std::size_t parNext) {
++m_local_data->done_count;
m_local_data->processing_index = parNext;
m_local_data->step_notify.notify_all();
}
);
@ -249,10 +262,11 @@ namespace din {
assert(m_local_data->done_count == m_local_data->paths.size());
#else
hash_dir(
m_local_data->paths.begin(),
m_local_data->paths.begin(),
m_local_data->paths.end(),
base_path,
[]() {}
[](std::size_t) {}
);
#endif
@ -323,4 +337,28 @@ namespace din {
return m_local_data->step_notify;
}
#endif
#if defined(WITH_PROGRESS_FEEDBACK)
std::string Indexer::current_item() const {
if (m_local_data->paths.empty() or 0 == m_local_data->processing_index)
return std::string();
PathName base_path(m_local_data->paths.front().path);
PathName ret_path(m_local_data->paths[m_local_data->processing_index].path);
return make_relative_path(base_path, ret_path).path();
}
#endif
std::string Indexer::operator[] (std::size_t parIndex) const {
if (parIndex >= m_local_data->file_count) {
std::ostringstream oss;
oss << "Requested index " << parIndex << " is out of range: only " << m_local_data->file_count << " items are available";
throw std::out_of_range(oss.str());
}
auto it = boost::make_filter_iterator<IsFile<>>(m_local_data->paths.begin(), m_local_data->paths.end());
assert(not m_local_data->paths.empty());
std::advance(it, parIndex);
return make_relative_path(PathName(m_local_data->paths.front().path), PathName(it->path)).path();
}
} //namespace din

View file

@ -19,6 +19,7 @@
#define idE555EF56730442C1ADDC7B2AE7A9340E
#include <memory>
#include <string>
#if !defined(NDEBUG)
# define INDEXER_VERBOSE
@ -46,8 +47,10 @@ namespace din {
#endif
std::size_t total_items ( void ) const;
std::string operator[] ( std::size_t parIndex ) const;
#if defined(WITH_PROGRESS_FEEDBACK)
std::size_t processed_items ( void ) const;
std::string current_item ( void ) const;
std::condition_variable& step_notify ( void );
#endif
void calculate_hash ( void );

View file

@ -16,7 +16,11 @@
*/
#include <iostream>
#include <iomanip>
#include <ciso646>
#include <sstream>
#include <algorithm>
#include <iterator>
#if defined(WITH_PROGRESS_FEEDBACK)
# include <thread>
# include <mutex>
@ -49,6 +53,11 @@ int main (int parArgc, char* parArgv[]) {
return 2;
}
const std::string search_path(vm["search-path"].as<std::string>());
#if defined(WITH_PROGRESS_FEEDBACK)
const bool verbose = (0 == vm.count("quiet"));
#else
const bool verbose = false;
#endif
din::DinDBSettings settings;
{
@ -65,18 +74,19 @@ int main (int parArgc, char* parArgv[]) {
searcher.SetFollowSymlinks(true);
searcher.SetCallback(fastf::FileSearcher::CallbackType(std::bind(&din::Indexer::add_path, &indexer, _1, _2, _3, _4)));
searcher.Search(ext, ignore);
if (verbose) {
std::cout << "Fetching items list...\n";
}
if (indexer.empty()) {
std::cerr << "Nothing found at the given location, quitting\n";
return 1;
}
else {
#if defined(WITH_PROGRESS_FEEDBACK)
const bool verbose = (0 == vm.count("quiet"));
#else
const bool verbose = false;
#endif
run_hash_calculation(indexer, verbose);
if (verbose) {
std::cout << "Writing to database...\n";
}
indexer.add_to_db(vm["setname"].as<std::string>(), vm["type"].as<char>());
}
return 0;
@ -84,6 +94,10 @@ int main (int parArgc, char* parArgv[]) {
namespace {
void run_hash_calculation (din::Indexer& parIndexer, bool parShowProgress) {
if (parIndexer.empty()) {
return;
}
#if !defined(WITH_PROGRESS_FEEDBACK)
parShowProgress = false;
#endif
@ -92,16 +106,33 @@ namespace {
}
#if defined(WITH_PROGRESS_FEEDBACK)
else {
std::cout << "Fetching items list...\n";
typedef std::ostream_iterator<char> cout_iterator;
std::cout << "Processing";
std::cout.flush();
const auto total_items = parIndexer.total_items();
std::thread hash_thread(&din::Indexer::calculate_hash, &parIndexer);
std::mutex progress_print;
while (parIndexer.processed_items() != total_items) {
std::size_t clear_size = 0;
const auto digit_count = static_cast<std::size_t>(std::log10(static_cast<double>(total_items))) + 1;
do {
std::unique_lock<std::mutex> lk(progress_print);
parIndexer.step_notify().wait(lk);
std::cout << "Processed " << parIndexer.processed_items() << " of " << total_items << '\r';
std::cout.flush();
};
std::cout << '\r';
std::fill_n(cout_iterator(std::cout), clear_size, ' ');
std::cout << '\r';
{
std::ostringstream oss;
const auto item_index = std::min(total_items - 1, parIndexer.processed_items());
oss << "Processing file "
<< std::setw(digit_count) << std::setfill(' ') << (item_index + 1)
<< " of " << total_items << " \"" << parIndexer.current_item() << '"';
const auto msg(oss.str());
clear_size = msg.size();
std::cout << msg;
std::cout.flush();
}
} while (parIndexer.processed_items() != total_items);
hash_thread.join();
if (parIndexer.processed_items() > 0) {