diff --git a/src/core/download_list.cc b/src/core/download_list.cc index 74a5a665..6d2cccba 100644 --- a/src/core/download_list.cc +++ b/src/core/download_list.cc @@ -56,6 +56,14 @@ namespace core { +inline void +DownloadList::check_contains(Download* d) { +#ifdef USE_EXTRA_DEBUG + if (std::find(begin(), end(), d) == end()) + throw torrent::internal_error("DownloadList::check_contains(...) failed."); +#endif +} + struct download_list_call { download_list_call(Download* d) : m_download(d) {} @@ -95,11 +103,11 @@ DownloadList::create(std::istream* str, bool printLog) { } DownloadList::iterator -DownloadList::insert(Download* d) { - iterator itr = base_type::insert(end(), d); +DownloadList::insert(Download* download) { + iterator itr = base_type::insert(end(), download); try { - (*itr)->download()->signal_download_done(sigc::bind(sigc::mem_fun(*this, &DownloadList::received_finished), d)); + (*itr)->download()->signal_download_done(sigc::bind(sigc::mem_fun(*this, &DownloadList::received_finished), download)); std::for_each(m_slotMapInsert.begin(), m_slotMapInsert.end(), download_list_call(*itr)); } catch (torrent::local_error& e) { @@ -112,8 +120,10 @@ DownloadList::insert(Download* d) { } void -DownloadList::erase(Download* d) { - erase(std::find(begin(), end(), d)); +DownloadList::erase(Download* download) { + check_contains(download); + + erase(std::find(begin(), end(), download)); } DownloadList::iterator @@ -123,7 +133,7 @@ DownloadList::erase(iterator itr) { // Make safe to erase active downloads. if ((*itr)->download()->is_active()) - throw std::logic_error("DownloadList::erase(...) called on an active download."); + throw torrent::internal_error("DownloadList::erase(...) called on an active download."); std::for_each(m_slotMapErase.begin(), m_slotMapErase.end(), download_list_call(*itr)); @@ -134,11 +144,10 @@ DownloadList::erase(iterator itr) { } void -DownloadList::open(Download* d) { +DownloadList::open(Download* download) { try { - if (!d->download()->is_open()) - std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(d)); + open_throw(download); } catch (torrent::local_error& e) { control->core()->push_log(e.what()); @@ -146,14 +155,22 @@ DownloadList::open(Download* d) { } void -DownloadList::close(Download* d) { +DownloadList::open_throw(Download* download) { + check_contains(download); + + if (download->download()->is_open()) + return; + + download->download()->open(); + + std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(download)); +} + +void +DownloadList::close(Download* download) { try { - if (d->download()->is_active()) - std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(d)); - - if (d->download()->is_open()) - std::for_each(m_slotMapClose.begin(), m_slotMapClose.end(), download_list_call(d)); + close_throw(download); } catch (torrent::local_error& e) { control->core()->push_log(e.what()); @@ -161,25 +178,49 @@ DownloadList::close(Download* d) { } void -DownloadList::start(Download* d) { - d->variable()->set("state", (int64_t)1); +DownloadList::close_throw(Download* download) { + check_contains(download); - resume(d); + if (!download->download()->is_open()) + return; + + if (download->download()->is_active()) + pause(download); + + control->core()->hash_queue()->remove(download); + download->download()->close(); + + std::for_each(m_slotMapClose.begin(), m_slotMapClose.end(), download_list_call(download)); } void -DownloadList::stop(Download* d) { - d->variable()->set("state", (int64_t)0); +DownloadList::start(Download* download) { + check_contains(download); - pause(d); + download->variable()->set("state", (int64_t)1); + + resume(download); +} + +void +DownloadList::stop(Download* download) { + check_contains(download); + + download->variable()->set("state", (int64_t)0); + + pause(download); } void DownloadList::resume(Download* download) { + check_contains(download); + try { - if (!download->download()->is_open()) - std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(download)); + if (download->download()->is_active()) + return; + + open_throw(download); if (download->download()->is_hash_checked()) { @@ -209,13 +250,17 @@ DownloadList::resume(Download* download) { void DownloadList::pause(Download* download) { + check_contains(download); + try { + if (!download->download()->is_active()) + return; + download->download()->stop(); download->download()->hash_resume_save(); - if (download->download()->is_active()) - std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(download)); + std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(download)); download->variable()->set("state_changed", cachedTime.seconds()); @@ -236,16 +281,26 @@ DownloadList::clear() { } void -DownloadList::check_hash(Download* d) { - close(d); - d->download()->hash_resume_clear(); - open(d); +DownloadList::check_hash(Download* download) { + check_contains(download); - control->core()->hash_queue()->insert(d); + try { + + close_throw(download); + download->download()->hash_resume_clear(); + open_throw(download); + + control->core()->hash_queue()->insert(download); + + } catch (torrent::local_error& e) { + control->core()->push_log(e.what()); + } } void DownloadList::hash_done(Download* download) { + check_contains(download); + if (!download->download()->is_hash_checked() || download->download()->is_hash_checking()) throw torrent::internal_error("DownloadList::hash_done(...) download in invalid state."); @@ -274,6 +329,8 @@ DownloadList::hash_done(Download* download) { void DownloadList::received_finished(Download* download) { + check_contains(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. @@ -287,6 +344,8 @@ DownloadList::received_finished(Download* download) { void DownloadList::confirm_finished(Download* download) { + check_contains(download); + // FIXME //torrent::download_set_priority(m_download, 2); diff --git a/src/core/download_list.h b/src/core/download_list.h index a8735820..88d1d269 100644 --- a/src/core/download_list.h +++ b/src/core/download_list.h @@ -83,7 +83,10 @@ public: iterator erase(iterator itr); void open(Download* d); + void open_throw(Download* d); + void close(Download* d); + void close_throw(Download* d); void start(Download* d); void stop(Download* d); @@ -124,6 +127,8 @@ public: bool has_slot_finished(const std::string& key) const { return m_slotMapFinished.find(key) != m_slotMapFinished.end(); } private: + inline void check_contains(Download* d); + void clear(); void received_finished(Download* d); diff --git a/src/core/manager.cc b/src/core/manager.cc index d3148403..fe1d6b3d 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -155,13 +155,6 @@ Manager::initialize_second() { m_downloadList->slot_map_erase()["1_hash_queue_remove"] = sigc::mem_fun(m_hashQueue, &HashQueue::remove); m_downloadList->slot_map_erase()["1_store_remove"] = sigc::mem_fun(m_downloadStore, &DownloadStore::remove); m_downloadList->slot_map_erase()["1_delete_tied"] = sigc::ptr_fun(&delete_tied); - - m_downloadList->slot_map_open()["1_download_open"] = sigc::mem_fun(&Download::call); - - // Currently does not call stop, might want to add a function that - // checks if we're running, and if so stop? - m_downloadList->slot_map_close()["1_hash_queue_remove"] = sigc::mem_fun(m_hashQueue, &HashQueue::remove); - m_downloadList->slot_map_close()["2_download_close"] = sigc::mem_fun(&Download::call); } void @@ -177,10 +170,16 @@ Manager::cleanup() { void Manager::shutdown(bool force) { + // This doesn't trigger a compiler error on gcc-3.4.5 for some reason. +// if (!force) +// std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::pause), &m_downloadList)); +// else +// std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList)); + if (!force) - std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::pause), &m_downloadList)); + std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::pause), m_downloadList)); else - std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList)); + std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::close), m_downloadList)); } void diff --git a/src/core/view.h b/src/core/view.h index 0108606f..3dd0e39c 100644 --- a/src/core/view.h +++ b/src/core/view.h @@ -41,7 +41,7 @@ // elements get accessed often but not modified, better with cache // locality. // -// ViewDownloads::m_size indicates the number of Download's that +// View::m_size indicates the number of Download's that // remain visible, e.g. has not been filtered out. The Download's that // were filtered are still in the underlying vector, but cannot be // accessed through the normal stl container functions. @@ -64,7 +64,7 @@ class DownloadList; class ViewSort; class ViewFilter; -class ViewDownloads : public std::vector { +class View : public std::vector { public: typedef std::vector base_type; typedef sigc::signal0 signal_type; @@ -81,8 +81,8 @@ public: using base_type::begin; using base_type::rbegin; - ViewDownloads() {} - ~ViewDownloads(); + View() {} + ~View(); void initialize(const std::string& name, core::DownloadList* list); @@ -130,8 +130,8 @@ public: signal_type& signal_changed() { return m_signalChanged; } private: - ViewDownloads(const ViewDownloads&); - void operator = (const ViewDownloads&); + View(const View&); + void operator = (const View&); void received_insert(core::Download* d); void received_erase(core::Download* d); diff --git a/src/core/view_manager.h b/src/core/view_manager.h index 9d49e1d7..da4bddf8 100644 --- a/src/core/view_manager.h +++ b/src/core/view_manager.h @@ -45,7 +45,6 @@ namespace core { -class View; class ViewSort; class ViewManager : public rak::unordered_vector {