From a6045c9ea52a4d7f84fc3bcf52328f4896b0cace Mon Sep 17 00:00:00 2001 From: rakshasa Date: Thu, 27 Mar 2008 15:41:11 +0000 Subject: [PATCH] * Made the signal in View trigger using a task, thus avoiding bad recursions and wrongly orderer commands. This should fix some problems with hash checking returning errno 0. * More changes to View usage. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1048 e378c898-3ddf-0310-93e7-cc216c733640 --- src/command_helpers.cc | 2 ++ src/command_helpers.h | 4 +-- src/command_ui.cc | 18 +++++++++++- src/control.cc | 2 +- src/core/download.cc | 2 ++ src/core/download_factory.cc | 36 +++++++++++------------ src/core/download_list.cc | 8 ++++++ src/core/manager.h | 1 - src/core/view.cc | 56 +++++++++++++++++++----------------- src/core/view.h | 11 +++---- src/core/view_manager.cc | 8 +----- src/core/view_manager.h | 2 +- src/ui/download.cc | 3 +- 13 files changed, 88 insertions(+), 65 deletions(-) diff --git a/src/command_helpers.cc b/src/command_helpers.cc index a9c5cd93..5d877fea 100644 --- a/src/command_helpers.cc +++ b/src/command_helpers.cc @@ -87,6 +87,7 @@ initialize_commands() { commandVariablesItr > commandVariables + COMMAND_VARIABLES_SIZE || commandDownloadSlotsItr > commandDownloadSlots + COMMAND_DOWNLOAD_SLOTS_SIZE || commandFileSlotsItr > commandFileSlots + COMMAND_FILE_SLOTS_SIZE || + commandFileItrSlotsItr > commandFileItrSlots + COMMAND_FILE_ITR_SLOTS_SIZE || commandPeerSlotsItr > commandPeerSlots + COMMAND_PEER_SLOTS_SIZE || commandTrackerSlotsItr > commandTrackerSlots + COMMAND_TRACKER_SLOTS_SIZE || commandAnySlotsItr > commandAnySlots + COMMAND_ANY_SLOTS_SIZE) @@ -95,6 +96,7 @@ initialize_commands() { commandVariablesItr != commandVariables + COMMAND_VARIABLES_SIZE || commandDownloadSlotsItr != commandDownloadSlots + COMMAND_DOWNLOAD_SLOTS_SIZE || commandFileSlotsItr != commandFileSlots + COMMAND_FILE_SLOTS_SIZE || + commandFileItrSlotsItr != commandFileItrSlots + COMMAND_FILE_ITR_SLOTS_SIZE || commandPeerSlotsItr != commandPeerSlots + COMMAND_PEER_SLOTS_SIZE || commandTrackerSlotsItr != commandTrackerSlots + COMMAND_TRACKER_SLOTS_SIZE || commandAnySlotsItr != commandAnySlots + COMMAND_ANY_SLOTS_SIZE) diff --git a/src/command_helpers.h b/src/command_helpers.h index e22c4875..012d3067 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -46,14 +46,14 @@ namespace rpc { // By using a static array we avoid allocating the variables on the // heap. This should reduce memory use and improve cache locality. -#define COMMAND_SLOTS_SIZE 150 +#define COMMAND_SLOTS_SIZE 200 #define COMMAND_VARIABLES_SIZE 100 #define COMMAND_DOWNLOAD_SLOTS_SIZE 150 #define COMMAND_FILE_SLOTS_SIZE 30 #define COMMAND_FILE_ITR_SLOTS_SIZE 10 #define COMMAND_PEER_SLOTS_SIZE 20 #define COMMAND_TRACKER_SLOTS_SIZE 15 -#define COMMAND_ANY_SLOTS_SIZE 20 +#define COMMAND_ANY_SLOTS_SIZE 50 #define ADDING_COMMANDS diff --git a/src/command_ui.cc b/src/command_ui.cc index 7db7f2c3..0b32a9e6 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -392,6 +392,20 @@ cmd_view_filter_download(core::Download* download, const torrent::Object& rawArg return torrent::Object(); } +torrent::Object +cmd_view_set_visible(core::Download* download, const torrent::Object& rawArgs) { + (*control->view_manager()->find_throw(rawArgs.as_string()))->set_visible(download); + + return torrent::Object(); +} + +torrent::Object +cmd_view_set_not_visible(core::Download* download, const torrent::Object& rawArgs) { + (*control->view_manager()->find_throw(rawArgs.as_string()))->set_not_visible(download); + + return torrent::Object(); +} + void initialize_command_ui() { ADD_VARIABLE_STRING("key_layout", "qwerty"); @@ -412,7 +426,9 @@ initialize_command_ui() { // Cleanup and add . to view. - CMD_D_STRING("view.filter_download", rak::ptr_fn(&cmd_view_filter_download)); + CMD_D_STRING("view.filter_download", rak::ptr_fn(&cmd_view_filter_download)); + CMD_D_STRING("view.set_visible", rak::ptr_fn(&cmd_view_set_visible)); + CMD_D_STRING("view.set_not_visible", rak::ptr_fn(&cmd_view_set_not_visible)); // Commands that affect the default rtorrent UI. diff --git a/src/control.cc b/src/control.cc index 96db15a1..d20be124 100644 --- a/src/control.cc +++ b/src/control.cc @@ -74,7 +74,7 @@ Control::Control() : m_tick(0) { m_core = new core::Manager(); - m_viewManager = new core::ViewManager(m_core->download_list()); + m_viewManager = new core::ViewManager(); m_scheduler = new core::Scheduler(m_core->download_list()); m_dhtManager = new core::DhtManager(); diff --git a/src/core/download.cc b/src/core/download.cc index 42520742..4ac5d96e 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -156,6 +156,8 @@ Download::receive_chunk_failed(__UNUSED uint32_t idx) { void Download::set_root_directory(const std::string& path) { + control->core()->push_log_std("Pushed " + path); + torrent::FileList* fileList = m_download.file_list(); control->core()->download_list()->close_directly(this); diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index e70cf324..d4c3cd7c 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -261,6 +261,23 @@ DownloadFactory::receive_success() { if (m_manager->download_list()->find(infohash) == m_manager->download_list()->end()) throw torrent::input_error("The newly created download was removed."); + // When a download scheduler is implemented, this is handled by + // the above insertion into download list. + if (m_session) { + // This torrent was queued for hashing or hashing when the + // session file was saved. Or it was in a started state. + if (rpc::call_command_value("d.get_hashing", rpc::make_target(download)) != Download::variable_hashing_stopped || + rpc::call_command_value("d.get_state", rpc::make_target(download)) != 0) + m_manager->download_list()->resume(download); + + } else { + // Use the state thingie here, move below. + if (m_start) + m_manager->download_list()->start_normal(download); + + m_manager->download_store()->save(download); + } + } catch (torrent::input_error& e) { std::string msg = "Command on torrent creation failed: " + std::string(e.what()); @@ -275,25 +292,6 @@ DownloadFactory::receive_success() { download->set_message(msg); // m_manager->download_list()->erase(m_manager->download_list()->find(infohash.data())); } - - return m_slotFinished(); - } - - // When a download scheduler is implemented, this is handled by the - // above insertion into download list. - if (m_session) { - // This torrent was queued for hashing or hashing when the session - // file was saved. Or it was in a started state. - if (rpc::call_command_value("d.get_hashing", rpc::make_target(download)) != Download::variable_hashing_stopped || - rpc::call_command_value("d.get_state", rpc::make_target(download)) != 0) - m_manager->download_list()->resume(download); - - } else { - // Use the state thingie here, move below. - if (m_start) - m_manager->download_list()->start_normal(download); - - m_manager->download_store()->save(download); } m_slotFinished(); diff --git a/src/core/download_list.cc b/src/core/download_list.cc index fca9cbe2..c7ebcb9e 100644 --- a/src/core/download_list.cc +++ b/src/core/download_list.cc @@ -329,6 +329,12 @@ DownloadList::start_normal(Download* download) { (*control->view_manager()->find_throw("stopped"))->set_not_visible(download); (*control->view_manager()->find_throw("started"))->set_visible(download); + +// try { +// rpc::parse_command_multiple(rpc::make_target(download), "d.set_state=1 ;view.set_not_visible=stopped ;view.set_visible=started"); +// } catch (torrent::local_error& e) { +// control->core()->push_log(e.what()); +// } } bool @@ -348,6 +354,8 @@ DownloadList::start_try(Download* download) { (*control->view_manager()->find_throw("stopped"))->set_not_visible(download); (*control->view_manager()->find_throw("started"))->set_visible(download); +// rpc::parse_command_multiple(rpc::make_target(download), "d.set_state=1 ;view.set_not_visible=stopped ;view.set_visible=started"); + return true; } diff --git a/src/core/manager.h b/src/core/manager.h index e656aa09..ad823923 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -125,7 +125,6 @@ private: void initialize_bencode(Download* d); void receive_http_failed(std::string msg); - void receive_hashing_changed(); DownloadList* m_downloadList; diff --git a/src/core/view.cc b/src/core/view.cc index 785c3bcf..7227d575 100644 --- a/src/core/view.cc +++ b/src/core/view.cc @@ -39,14 +39,16 @@ #include #include #include +#include #include #include #include #include +#include "control.h" #include "download.h" #include "download_list.h" - +#include "manager.h" #include "view.h" namespace core { @@ -63,7 +65,7 @@ struct view_downloads_compare : std::binary_function return rpc::parse_command_single(rpc::make_target_pair(d1, d2), m_command).as_value(); } catch (torrent::input_error& e) { -// control->core()->push_log(e.what()); + control->core()->push_log(e.what()); return false; } @@ -95,6 +97,8 @@ struct view_downloads_filter : std::unary_function { return true; } catch (torrent::input_error& e) { + control->core()->push_log(e.what()); + return false; } } @@ -102,15 +106,24 @@ struct view_downloads_filter : std::unary_function { const std::string& m_command; }; +inline void +View::emit_changed() { + priority_queue_erase(&taskScheduler, &m_delayChanged); + priority_queue_insert(&taskScheduler, &m_delayChanged, cachedTime); +} + 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(control->core()->download_list()->slot_map_begin(), control->core()->download_list()->slot_map_end(), + rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name)); + + priority_queue_erase(&taskScheduler, &m_delayChanged); } void -View::initialize(const std::string& name, core::DownloadList* dlist) { +View::initialize(const std::string& name) { if (!m_name.empty()) throw torrent::internal_error("View::initialize(...) called on an already initialized view."); @@ -118,35 +131,21 @@ View::initialize(const std::string& name, core::DownloadList* dlist) { throw torrent::internal_error("View::initialize(...) called with an empty name."); std::string key = "0_view_" + name; + core::DownloadList* dlist = control->core()->download_list(); if (dlist->has_slot_insert(key) || dlist->has_slot_erase(key)) throw torrent::internal_error("View::initialize(...) duplicate key name found in DownloadList."); m_name = name; - m_list = dlist; // Urgh, wrong. No filtering being done. - std::for_each(m_list->begin(), m_list->end(), rak::bind1st(std::mem_fun(&View::push_back), this)); + std::for_each(dlist->begin(), dlist->end(), rak::bind1st(std::mem_fun(&View::push_back), this)); m_size = base_type::size(); m_focus = 0; set_last_changed(rak::timer()); -} - -void -View::insert(Download* download) { -// if (view_downloads_filter(m_filter)(download)) { -// insert_visible(download); -// rpc::parse_command_multiple_d_nothrow(download, m_eventAdded); - -// } else { -// base_type::insert(end_filtered(), download); -// } - - // We can't make the download visible until after it has been added - // to every single View, as it might trigger a command too early. - base_type::insert(base_type::end(), download); + m_delayChanged.set_slot(rak::mem_fn(&m_signalChanged, &signal_type::operator())); } void @@ -201,7 +200,7 @@ View::next_focus() { return; m_focus = (m_focus + 1) % (size() + 1); - m_signalChanged.emit(); + emit_changed(); } void @@ -210,7 +209,7 @@ View::prev_focus() { return; m_focus = (m_focus - 1 + size() + 1) % (size() + 1); - m_signalChanged.emit(); + emit_changed(); } void @@ -221,7 +220,7 @@ View::sort() { std::stable_sort(begin(), end_visible(), view_downloads_compare(m_sortCurrent)); m_focus = position(std::find(begin(), end_visible(), curFocus)); - m_signalChanged.emit(); + emit_changed(); } void @@ -254,6 +253,8 @@ View::filter() { if (!m_eventAdded.empty()) std::for_each(splitChanged, changed.end(), rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_d_nothrow), m_eventAdded)); + + emit_changed(); } void @@ -290,7 +291,7 @@ View::filter_download(core::Download* download) { rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved); } - m_signalChanged.emit(); + emit_changed(); } void @@ -298,14 +299,15 @@ View::set_filter_on(int event) { if (event == DownloadList::SLOTS_INSERT || event == DownloadList::SLOTS_ERASE || event >= DownloadList::SLOTS_MAX_SIZE) throw torrent::internal_error("View::filter_on(...) invalid event."); - m_list->slots(event)["0_view_" + m_name] = "view.filter_download=" + m_name; + control->core()->download_list()->slots(event)["0_view_" + m_name] = "view.filter_download=" + m_name; } 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(control->core()->download_list()->slot_map_begin() + DownloadList::SLOTS_OPEN, control->core()->download_list()->slot_map_end(), + rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name)); } inline void diff --git a/src/core/view.h b/src/core/view.h index d6bfe629..eeabc91f 100644 --- a/src/core/view.h +++ b/src/core/view.h @@ -60,7 +60,6 @@ namespace core { class Download; -class DownloadList; class View : private std::vector { public: @@ -77,7 +76,7 @@ public: View() {} ~View(); - void initialize(const std::string& name, DownloadList* dlist); + void initialize(const std::string& name); const std::string& name() const { return m_name; } @@ -102,7 +101,7 @@ public: const_iterator focus() const { return begin() + m_focus; } void set_focus(iterator itr) { m_focus = position(itr); m_signalChanged.emit(); } - void insert(Download* download); + void insert(Download* download) { base_type::push_back(download); } void erase(Download* download); void set_visible(Download* download); @@ -150,14 +149,14 @@ private: inline void insert_visible(Download* d); inline void erase_internal(iterator itr); + inline void emit_changed(); + size_type position(const_iterator itr) const { return itr - begin(); } // An received thing for changed status so we can sort and filter. std::string m_name; - DownloadList* m_list; - size_type m_size; size_type m_focus; @@ -171,7 +170,9 @@ private: std::string m_eventRemoved; rak::timer m_lastChanged; + signal_type m_signalChanged; + rak::priority_item m_delayChanged; }; } diff --git a/src/core/view_manager.cc b/src/core/view_manager.cc index 1755c6b9..23a698a5 100644 --- a/src/core/view_manager.cc +++ b/src/core/view_manager.cc @@ -53,12 +53,6 @@ namespace core { -// Really need to implement a factory and allow options in the sort -// statements. -ViewManager::ViewManager(DownloadList* dl) : - m_list(dl) { -} - void ViewManager::clear() { std::for_each(begin(), end(), rak::call_delete()); @@ -72,7 +66,7 @@ ViewManager::insert(const std::string& name) { throw torrent::internal_error("ViewManager::insert(...) name already inserted."); View* view = new View(); - view->initialize(name, m_list); + view->initialize(name); return base_type::insert(end(), view); } diff --git a/src/core/view_manager.h b/src/core/view_manager.h index c0222318..60d0db4d 100644 --- a/src/core/view_manager.h +++ b/src/core/view_manager.h @@ -64,7 +64,7 @@ public: using base_type::empty; using base_type::size; - ViewManager(DownloadList* dl); + ViewManager() {} ~ViewManager() { clear(); } // Ffff... Just throwing together an interface, need to think some diff --git a/src/ui/download.cc b/src/ui/download.cc index f662d618..dac1dac3 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -153,7 +153,8 @@ Download::create_info() { element->push_column("Created:", te_command("cat=$to_date=$d.get_creation_date=,\" \",$to_time=$d.get_creation_date=")); element->push_back(""); - element->push_column("Directory:", te_command("d.get_base_path=")); + element->push_column("Directory:", te_command("d.get_directory=")); + element->push_column("Base Path:", te_command("d.get_base_path=")); element->push_column("Tied to file:", te_command("d.get_tied_to_file=")); element->push_column("File stats:", te_command("cat=$if=$d.is_multi_file=\\,multi\\,single,\" \",$d.get_size_files=,\" files\""));