From 70eacfe738be6a546c05ee7de7a1d0207cb6c3c2 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Wed, 21 Jun 2006 22:14:10 +0000 Subject: [PATCH] * Reworked how hashing is queued, state must 1 and removed the set_hash_failed hacks when closing, etc. * Changed the attributes of blocks in transfer view. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@727 e378c898-3ddf-0310-93e7-cc216c733640 --- src/core/download_factory.cc | 2 +- src/core/download_list.cc | 103 +++++++++---------- src/core/download_list.h | 8 +- src/core/manager.cc | 4 +- src/core/scheduler.cc | 2 +- src/core/view.cc | 14 ++- src/display/window_download_transfer_list.cc | 30 ++---- src/main.cc | 3 +- src/option_handler_rules.cc | 2 +- src/ui/download_list.cc | 2 +- 10 files changed, 75 insertions(+), 95 deletions(-) diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index d312a38a..3a330588 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -208,7 +208,7 @@ DownloadFactory::receive_success() { } else { // Use the state thingie here, move below. if (m_start) - m_manager->download_list()->start(download); + m_manager->download_list()->start_normal(download); m_manager->download_store()->save(download); } diff --git a/src/core/download_list.cc b/src/core/download_list.cc index 3e7f9e4c..abcd1cc4 100644 --- a/src/core/download_list.cc +++ b/src/core/download_list.cc @@ -160,19 +160,17 @@ DownloadList::erase(iterator itr) { return base_type::erase(itr); } -// void -// DownloadList::save(Download* d) { - -// } - -void +bool DownloadList::open(Download* download) { try { open_throw(download); + return true; + } catch (torrent::local_error& e) { control->core()->push_log(e.what()); + return false; } } @@ -203,14 +201,15 @@ void DownloadList::close_throw(Download* download) { check_contains(download); + // When pause gets called it will clear the initial hash check state + // and set hash failed. This should ensure hashing doesn't restart + // until resume gets called. + pause(download); + + // Check for is_open after pause due to hashing. if (!download->is_open()) return; - // When pause gets called it will clear the initial hash checking. - - if (download->is_active()) - pause(download); - // Save the torrent on close, this covers shutdown and if a torrent // is manually closed which would clear the progress data. For // better crash protection, save regulary in addition to this. @@ -220,39 +219,35 @@ DownloadList::close_throw(Download* download) { // Reconsider this save. Should be done explicitly when shutting down. //control->core()->download_store()->save(download); - // FIXME: Urgh, need to do something sane when closing a download - // that has been queued for hashing. ATM just close the torrent and - // call the hash_removed slots. This might open and restart the - // hashing of this torrent. - -// if (download->is_hash_checking()) { -// download->download()->close(); - -// // Hash removed slot must be called after close as we can't atm -// // stop already started hash checks except through close. -// std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download)); - -// } else { -// download->download()->close(); -// } - - // But this isn't correct either, i think... ATM do the borking - // thing, the hash queue won't be updated. Need to properly handle - // erasing a download. - - // Propably should do its own thingie in erase rather than calling - // close. - download->download()->close(); + if (!download->is_hash_failed() && + download->variable()->get_value("state") != 0 && + download->variable()->get_value("hashing") != Download::variable_hashing_stopped) + throw torrent::client_error("DownloadList::close_throw(...) called but we're going into a hashing loop."); + std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download)); std::for_each(slot_map_close().begin(), slot_map_close().end(), download_list_call(download)); } void -DownloadList::start(Download* download) { +DownloadList::start_normal(Download* download) { check_contains(download); + // Clear hash failed as we're doing a manual start and want to try + // hashing again. + download->set_hash_failed(false); + download->variable()->set("state", (int64_t)1); + + resume(download); +} + +void +DownloadList::start_try(Download* download) { + check_contains(download); + + // Don't clear the hash failed as this function is used by scripts, + // etc. download->variable()->set("state", (int64_t)1); resume(download); @@ -282,21 +277,20 @@ DownloadList::resume(Download* download) { // It is also assumed the is_hash_checked flag gets cleared when // 'hashing' was set. if (!download->is_hash_checked()) { - download->set_hash_failed(false); - - // Set 'hashing' to started if hashing wasn't started, else keep - // the old value. - if (download->variable()->get_value("hashing") == Download::variable_hashing_stopped) + // If the hash failed flag wasn't cleared then hashing won't be + // initiated. The check here is just for convenience so the hash + // queue doesn't need to check it. + if (!download->is_hash_failed() && download->variable()->get_value("hashing") == Download::variable_hashing_stopped) download->variable()->set("hashing", Download::variable_hashing_initial); std::for_each(slot_map_hash_queued().begin(), slot_map_hash_queued().end(), download_list_call(download)); return; } - download->variable()->set("state_changed", cachedTime.seconds()); - open_throw(download); + download->variable()->set("state_changed", cachedTime.seconds()); + if (download->is_done()) { download->set_connection_type(download->variable()->get_string("connection_seed")); } else { @@ -327,13 +321,10 @@ DownloadList::pause(Download* download) { try { - // Don't stop if we're doing the final hashing. - if (download->variable()->get_value("hashing") == Download::variable_hashing_initial) { + // Clear initial hashing, but retain the other types. + if (download->variable()->get_value("hashing") == Download::variable_hashing_initial) download->variable()->set("hashing", Download::variable_hashing_stopped); - std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download)); - } - if (!download->download()->is_active()) return; @@ -341,6 +332,7 @@ DownloadList::pause(Download* download) { download->download()->hash_resume_save(); std::for_each(slot_map_stop().begin(), slot_map_stop().end(), download_list_call(download)); + std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download)); download->variable()->set("state_changed", cachedTime.seconds()); @@ -359,8 +351,10 @@ DownloadList::check_hash(Download* download) { try { - download->variable()->set("hashing", Download::variable_hashing_rehash); - hash_clear(download); + if (download->variable()->get_value("hashing") != Download::variable_hashing_stopped) + return; + + hash_queue(download, Download::variable_hashing_rehash); } catch (torrent::local_error& e) { control->core()->push_log(e.what()); @@ -438,12 +432,11 @@ DownloadList::hash_done(Download* download) { } void -DownloadList::hash_clear(Download* download) { +DownloadList::hash_queue(Download* download, int type) { check_contains(download); - // Set hash failed so close_throw won't cause the hash queue to - // reopen this download. - download->set_hash_failed(true); + if (download->variable()->get_value("hashing") != Download::variable_hashing_stopped) + throw torrent::client_error("DownloadList::hash_queue(...) hashing already queued."); close_throw(download); download->download()->hash_resume_clear(); @@ -465,9 +458,7 @@ DownloadList::received_finished(Download* download) { if (control->variable()->get_value("check_hash")) { // Set some 'checking_finished_thingie' variable to make hash_done // trigger correctly, also so it can bork on missing data. - - download->variable()->set("hashing", Download::variable_hashing_last); - hash_clear(download); + hash_queue(download, Download::variable_hashing_last); } else { confirm_finished(download); diff --git a/src/core/download_list.h b/src/core/download_list.h index 52d4e068..d0662abb 100644 --- a/src/core/download_list.h +++ b/src/core/download_list.h @@ -86,16 +86,16 @@ public: //void save(Download* d); - void open(Download* d); + bool open(Download* d); void open_throw(Download* d); void close(Download* d); void close_throw(Download* d); - void start(Download* d); + void start_normal(Download* d); + void start_try(Download* d); void stop(Download* d); - // These do not change the rtorrent:state. void resume(Download* d); void pause(Download* d); @@ -169,7 +169,7 @@ public: private: void hash_done(Download* d); - void hash_clear(Download* d); + void hash_queue(Download* d, int type); inline void check_contains(Download* d); diff --git a/src/core/manager.cc b/src/core/manager.cc index faf4730a..bad24734 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -385,8 +385,8 @@ Manager::receive_hashing_changed() { try { - if ((*itr)->is_hash_checked()) - throw torrent::client_error("core::Manager::receive_hashing_changed() hash already checked."); + if ((*itr)->is_hash_checked() || (*itr)->is_hash_checking()) + throw torrent::client_error("core::Manager::receive_hashing_changed() hash already checked or checking."); if ((*itr)->is_hash_failed()) continue; diff --git a/src/core/scheduler.cc b/src/core/scheduler.cc index e7b6901d..a7791f66 100644 --- a/src/core/scheduler.cc +++ b/src/core/scheduler.cc @@ -97,7 +97,7 @@ Scheduler::update() { throw torrent::client_error("Scheduler::update() loop bork."); if (!(*itr)->is_active()) { - m_downloadList->resume(*itr); + m_downloadList->start_try(*itr); ++curActive; } } diff --git a/src/core/view.cc b/src/core/view.cc index 0a00e3e7..ebf23b7a 100644 --- a/src/core/view.cc +++ b/src/core/view.cc @@ -53,8 +53,7 @@ View::~View() { if (m_name.empty()) return; - std::for_each(m_list->slot_map_begin(), m_list->slot_map_end(), - rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name)); + std::for_each(m_list->slot_map_begin(), m_list->slot_map_end(), rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name)); } void @@ -115,9 +114,9 @@ struct view_downloads_compare : std::binary_function bool operator () (Download* d1, Download* d2) const { for (View::sort_list::const_iterator itr = m_sort.begin(), last = m_sort.end(); itr != last; ++itr) if ((**itr)(d1, d2)) - return true; + return true; else if ((**itr)(d2, d1)) - return false; + return false; // Since we're testing equivalence, return false if we're // equal. This is a requirement for the stl sorting algorithms. @@ -133,7 +132,7 @@ struct view_downloads_filter : std::unary_function { bool operator () (Download* d1) const { for (View::filter_list::const_iterator itr = m_filter.begin(), last = m_filter.end(); itr != last; ++itr) if (!(**itr)(d1)) - return false; + return false; // The default filter action is to return true, to not filter the // download out. @@ -176,8 +175,7 @@ void View::clear_filter_on() { // Don't clear insert and erase as these are required to keep the // View up-to-date with the available downloads. - std::for_each(m_list->slot_map_begin() + DownloadList::SLOTS_OPEN, m_list->slot_map_end(), - rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name)); + std::for_each(m_list->slot_map_begin() + DownloadList::SLOTS_OPEN, m_list->slot_map_end(), rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name)); } inline void @@ -239,7 +237,7 @@ View::received(core::Download* download, int event) { } else { if (itr >= begin_filtered()) - return; + return; erase(itr); base_type::push_back(download); diff --git a/src/display/window_download_transfer_list.cc b/src/display/window_download_transfer_list.cc index f4447e82..d036bc66 100644 --- a/src/display/window_download_transfer_list.cc +++ b/src/display/window_download_transfer_list.cc @@ -81,34 +81,24 @@ WindowDownloadTransferList::redraw() { char id; chtype attr = A_NORMAL; - if (bItr->transfers()->size() >= 1) { + if (bItr->is_finished()) { + attr = A_REVERSE; + id = key_id(bItr->leader()->const_peer_info()); - if (bItr->leader() != NULL) { - attr = A_REVERSE; - id = key_id(bItr->leader()->const_peer_info()); - } else { - attr = A_REVERSE | A_UNDERLINE; - id = key_id(bItr->transfers()->back()->const_peer_info()); - } - - if (bItr->transfers()->size() > 1) - attr = A_BOLD; + } else if (bItr->is_transfering()) { + attr = A_BOLD; + id = key_id(bItr->leader()->const_peer_info()); } else if (bItr->queued()->size() >= 1) { - id = key_id(bItr->queued()->back()->const_peer_info()); - - if (bItr->queued()->size() > 1) - attr = A_BOLD; - - } else if (bItr->is_finished()) { - // Temporary until we fix the code so transfers are kept - // around. - id = '*'; + id = std::tolower(key_id(bItr->queued()->back()->const_peer_info())); } else { id = '.'; } + if (bItr->size_all() > 1) + attr |= A_UNDERLINE; + m_canvas->print_char(attr | id); } } diff --git a/src/main.cc b/src/main.cc index 3f40320c..66f339b1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -196,8 +196,9 @@ main(int argc, char** argv) { control->variable()->process_command("view_sort_new = incomplete,state_changed"); control->variable()->process_command("view_sort_current = incomplete,state_changed_reverse"); + // The hashing view does not include stopped torrents. control->variable()->process_command("view_add = hashing"); - control->variable()->process_command("view_filter = hashing,hashing"); + control->variable()->process_command("view_filter = hashing,hashing,started"); control->variable()->process_command("view_filter_on = hashing,hash_queued,hash_removed,hash_done"); control->variable()->process_command("view_sort_new = hashing,state_changed"); control->variable()->process_command("view_sort_current = hashing,state_changed"); diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index e1296de8..3fb203ce 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -129,7 +129,7 @@ apply_start_tied(Control* m, const std::string& arg) { rak::equal(*itr, rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"))); if (dItr != m->core()->download_list()->end()) - m->core()->download_list()->start(*dItr); + m->core()->download_list()->start_try(*dItr); } } diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 4761bb2d..d5fdf3b7 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -200,7 +200,7 @@ DownloadList::receive_start_download() { if (m_view->focus() == m_view->end_visible()) return; - m_control->core()->download_list()->start(*m_view->focus()); + m_control->core()->download_list()->start_normal(*m_view->focus()); m_view->set_last_changed(); }