Browse Source

* A seperate variable for hashing state, now properly restarts hashing

after restart.

* Stop a torrent and show a message when it finishes the final
hash-check and finds some chunks incomplete. This prevents full disk
from causing a torrent to go into an infinit loop of re-downloading
the data.

* Moved various slots from core::Manager to core::DownloadList.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@679 e378c898-3ddf-0310-93e7-cc216c733640
pull/30/head
rakshasa 20 years ago
parent
commit
2b420e95a0
  1. 5
      src/control.cc
  2. 8
      src/core/download.cc
  3. 6
      src/core/download.h
  4. 13
      src/core/download_factory.cc
  5. 156
      src/core/download_list.cc
  6. 10
      src/core/download_list.h
  7. 3
      src/core/hash_queue.cc
  8. 14
      src/core/manager.cc
  9. 13
      src/core/manager.h
  10. 6
      src/core/poll_manager.cc
  11. 16
      src/main.cc
  12. 36
      src/option_handler_rules.cc
  13. 2
      src/ui/download_list.cc
  14. 10
      src/utils/variable_generic.cc
  15. 21
      src/utils/variable_generic.h
  16. 11
      src/utils/variable_map.cc
  17. 2
      src/utils/variable_map.h

5
src/control.cc

@ -41,6 +41,7 @@
#include <torrent/connection_manager.h>
#include "core/manager.h"
#include "core/download_store.h"
#include "core/view_manager.h"
#include "core/scheduler.h"
@ -110,7 +111,7 @@ Control::initialize() {
m_core->initialize_second();
m_core->listen_open();
m_core->download_store().enable(m_variables->get_value("session_lock"));
m_core->download_store()->enable(m_variables->get_value("session_lock"));
m_scheduler->set_view(*m_viewManager->find_throw("scheduler"));
@ -125,7 +126,7 @@ Control::cleanup() {
m_inputStdin->remove(m_core->get_poll_manager()->get_torrent_poll());
m_core->download_store().disable();
m_core->download_store()->disable();
m_ui->cleanup();
m_core->cleanup();

8
src/core/download.cc

@ -70,8 +70,16 @@ Download::Download(download_type d) :
m_variables.insert("connection_leech", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_LEECH)));
m_variables.insert("connection_seed", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_SEED)));
// 0 - stopped
// 1 - started
m_variables.insert("state", new utils::VariableObject(bencode(), "rtorrent", "state", torrent::Object::TYPE_VALUE));
m_variables.insert("complete", new utils::VariableObject(bencode(), "rtorrent", "complete", torrent::Object::TYPE_VALUE));
// 0 - Not hashing
// 1 - Normal hashing
// 2 - Download finished, hashing
m_variables.insert("hashing", new utils::VariableObject(bencode(), "rtorrent", "hashing", torrent::Object::TYPE_VALUE));
m_variables.insert("tied_to_file", new utils::VariableObject(bencode(), "rtorrent", "tied_to_file", torrent::Object::TYPE_STRING));
// The "state_changed" variable is required to be a valid unix time

6
src/core/download.h

@ -55,6 +55,10 @@ public:
typedef download_type::ConnectionType connection_type;
typedef utils::VariableMap variable_map_type;
static const int64_t variable_hashing_stopped = 0;
static const int64_t variable_hashing_started = 1;
static const int64_t variable_hashing_last = 2;
Download(download_type d);
~Download();
@ -73,7 +77,9 @@ public:
tracker_list_type* tracker_list() { return &m_trackerList; }
const std::string& info_hash() const { return m_download.info_hash(); }
const std::string& message() const { return m_message; }
void set_message(const std::string& msg) { m_message = msg; }
uint32_t chunks_failed() const { return m_chunksFailed; }

13
src/core/download_factory.cc

@ -54,6 +54,7 @@
#include "download.h"
#include "download_factory.h"
#include "download_store.h"
namespace core {
@ -103,7 +104,7 @@ DownloadFactory::receive_load() {
if (std::strncmp(m_uri.c_str(), "http://", 7) == 0) {
// Http handling here.
m_stream = new std::stringstream;
HttpQueue::iterator itr = m_manager->http_queue().insert(m_uri, m_stream);
HttpQueue::iterator itr = m_manager->http_queue()->insert(m_uri, m_stream);
(*itr)->signal_done().slots().push_front(sigc::mem_fun(*this, &DownloadFactory::receive_loaded));
(*itr)->signal_failed().slots().push_front(sigc::mem_fun(*this, &DownloadFactory::receive_failed));
@ -190,7 +191,10 @@ DownloadFactory::receive_success() {
else
download->variable()->set("directory", rtorrent->get_key("directory"));
if (download->variable()->get_value("state") == 1)
// This torrent was queued for hashing or hashing when the session
// file was saved. Or it was in a started state.
if (download->variable()->get_value("hashing") != Download::variable_hashing_stopped ||
download->variable()->get_value("state") != 0)
m_manager->download_list()->resume(download);
} else {
@ -203,7 +207,7 @@ DownloadFactory::receive_success() {
if (m_start)
m_manager->download_list()->start(download);
m_manager->download_store().save(download);
m_manager->download_store()->save(download);
}
m_slotFinished();
@ -237,6 +241,9 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
if (!rtorrent->has_key_value("complete"))
rtorrent->insert_key("complete", (int64_t)0);
if (!rtorrent->has_key_value("hashing"))
rtorrent->insert_key("hashing", Download::variable_hashing_stopped);
if (!rtorrent->has_key_string("tied_to_file"))
rtorrent->insert_key("tied_to_file", std::string());

156
src/core/download_list.cc

@ -74,6 +74,18 @@ struct download_list_call {
Download* m_download;
};
DownloadList::~DownloadList() {
std::for_each(begin(), end(), std::bind1st(std::mem_fun(&DownloadList::close), this));
std::for_each(begin(), end(), rak::call_delete<Download>());
base_type::clear();
}
void
DownloadList::session_save() {
std::for_each(begin(), end(), std::bind1st(std::mem_fun(&DownloadStore::save), control->core()->download_store()));
}
Download*
DownloadList::create(std::istream* str, bool printLog) {
torrent::Object* object = new torrent::Object;
@ -113,7 +125,7 @@ DownloadList::insert(Download* download) {
} catch (torrent::local_error& e) {
// Should perhaps relax this, just print an error and remove the
// downloads?
throw torrent::internal_error("Caught during DownloadList::insert part 2: " + std::string(e.what()));
throw torrent::internal_error("Caught during DownloadList::insert(...): " + std::string(e.what()));
}
return itr;
@ -131,9 +143,9 @@ DownloadList::erase(iterator itr) {
if (itr == end())
throw torrent::internal_error("DownloadList::erase(...) could not find download.");
// Make safe to erase active downloads.
if ((*itr)->download()->is_active())
throw torrent::internal_error("DownloadList::erase(...) called on an active download.");
close(*itr);
control->core()->download_store()->remove(*itr);
std::for_each(m_slotMapErase.begin(), m_slotMapErase.end(), download_list_call(*itr));
@ -187,7 +199,14 @@ DownloadList::close_throw(Download* download) {
if (download->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.
//
// Used to be in pause, but this was wrong for rehashing etc.
control->core()->download_store()->save(download);
control->core()->hash_queue()->remove(download);
download->download()->close();
std::for_each(m_slotMapClose.begin(), m_slotMapClose.end(), download_list_call(download));
@ -220,28 +239,43 @@ DownloadList::resume(Download* download) {
if (download->download()->is_active())
return;
open_throw(download);
// Properly escape when resume get's called during hashing. The
// 'state' is changed by the call to DownloadList::start so it
// will automagically start afterwards.
if (control->core()->hash_queue()->find(download) != control->core()->hash_queue()->end())
return;
if (download->download()->is_hash_checked()) {
download->variable()->set("state_changed", cachedTime.seconds());
if (download->is_done())
download->set_connection_type(download->variable()->get_string("connection_seed"));
else
download->set_connection_type(download->variable()->get_string("connection_leech"));
open_throw(download);
// Update the priority to ensure it has the correct
// seeding/unfinished modifiers.
download->set_priority(download->priority());
download->download()->start();
// Manual or end-of-download rehashing clears the resume data so
// we can just start the hashing again without clearing it again.
//
// It is also assumed the is_hash_checked flag gets cleared when
// 'hashing' was set.
if (!download->download()->is_hash_checked()) {
std::for_each(m_slotMapStart.begin(), m_slotMapStart.end(), download_list_call(download));
// Set 'hashing' to started if hashing wasn't started, else keep
// the old value.
if (download->variable()->get_value("hashing") == Download::variable_hashing_stopped)
download->variable()->set("hashing", Download::variable_hashing_started);
} else {
// TODO: This can cause infinit looping?
control->core()->hash_queue()->insert(download);
return;
}
download->variable()->set("state_changed", cachedTime.seconds());
if (download->is_done())
download->set_connection_type(download->variable()->get_string("connection_seed"));
else
download->set_connection_type(download->variable()->get_string("connection_leech"));
// Update the priority to ensure it has the correct
// seeding/unfinished modifiers.
download->set_priority(download->priority());
download->download()->start();
std::for_each(m_slotMapStart.begin(), m_slotMapStart.end(), download_list_call(download));
} catch (torrent::local_error& e) {
control->core()->push_log(e.what());
@ -254,6 +288,10 @@ DownloadList::pause(Download* download) {
try {
// Make sure we don't start hash checking a download that we won't
// start.
control->core()->hash_queue()->remove(download);
if (!download->download()->is_active())
return;
@ -266,7 +304,7 @@ DownloadList::pause(Download* download) {
// Save the state after all the slots, etc have been called so we
// include the modifications they may make.
control->core()->download_store().save(download);
//control->core()->download_store()->save(download);
} catch (torrent::local_error& e) {
control->core()->push_log(e.what());
@ -274,10 +312,8 @@ DownloadList::pause(Download* download) {
}
void
DownloadList::clear() {
std::for_each(begin(), end(), rak::call_delete<Download>());
base_type::clear();
DownloadList::save(Download* d) {
}
void
@ -286,17 +322,28 @@ DownloadList::check_hash(Download* download) {
try {
close_throw(download);
download->download()->hash_resume_clear();
open_throw(download);
control->core()->hash_queue()->insert(download);
download->variable()->set("hashing", Download::variable_hashing_started);
check_hash_throw(download);
} catch (torrent::local_error& e) {
control->core()->push_log(e.what());
}
}
// Throw in addition to not setting 'hashing'.
void
DownloadList::check_hash_throw(Download* download) {
check_contains(download);
close_throw(download);
download->download()->hash_resume_clear();
open_throw(download);
// If any more stuff is added here, make sure resume etc are still
// correct.
control->core()->hash_queue()->insert(download);
}
void
DownloadList::hash_done(Download* download) {
check_contains(download);
@ -313,18 +360,42 @@ DownloadList::hash_done(Download* download) {
// confirm all the data, avoiding large BW usage on f.ex. the
// ReiserFS bug with >4GB files.
// Use just is_done(), have another if statement inside.
if (download->is_done() && download->variable()->get_value("complete") == 0) {
int64_t hashing = download->variable()->get_value("hashing");
download->variable()->set("hashing", Download::variable_hashing_stopped);
if (control->variable()->get_value("session_on_completion"))
control->core()->download_store().save(download);
switch (hashing) {
case Download::variable_hashing_started:
// Normal re/hashing.
// Send a "truly finished message from here.
confirm_finished(download);
}
if (download->is_done())
download->variable()->set("complete", (int64_t)1);
if (download->variable()->get_value("state") == 1)
resume(download);
return;
case Download::variable_hashing_last:
if (download->variable()->get_value("state") == 1)
resume(download);
if (download->is_done()) {
confirm_finished(download);
if (download->variable()->get_value("state") == 1)
resume(download);
} else {
download->set_message("Hash check on download completion found bad chunks.");
}
return;
case Download::variable_hashing_stopped:
default:
// Either an error or someone wrote to the hashing variable...
download->set_message("Hash check completed but the \"hashing\" variable is in an invalid state.");
return;
}
}
void
@ -335,13 +406,15 @@ DownloadList::received_finished(Download* download) {
// Set some 'checking_finished_thingie' variable to make hash_done
// trigger correctly, also so it can bork on missing data.
check_hash(download);
download->variable()->set("hashing", Download::variable_hashing_last);
check_hash_throw(download);
} else {
confirm_finished(download);
}
}
// The download must be open when we call this function.
void
DownloadList::confirm_finished(Download* download) {
check_contains(download);
@ -354,6 +427,13 @@ DownloadList::confirm_finished(Download* download) {
download->download()->tracker_list().send_completed();
// Do this before the slots are called in case one of them closes
// the download.
if (!download->is_active() && control->variable()->get_value("session_on_completion") == 1) {
download->download()->hash_resume_save();
control->core()->download_store()->save(download);
}
std::for_each(m_slotMapFinished.begin(), m_slotMapFinished.end(), download_list_call(download));
}

10
src/core/download_list.h

@ -72,7 +72,9 @@ public:
using base_type::empty;
using base_type::size;
~DownloadList() { clear(); }
~DownloadList();
void session_save();
// Might move this to DownloadFactory.
Download* create(std::istream* str, bool printLog);
@ -95,7 +97,11 @@ public:
void resume(Download* d);
void pause(Download* d);
void save(Download* d);
void check_hash(Download* d);
void check_hash_throw(Download* d);
void hash_done(Download* d);
slot_map& slot_map_insert() { return m_slotMapInsert; }
@ -129,8 +135,6 @@ public:
private:
inline void check_contains(Download* d);
void clear();
void received_finished(Download* d);
void confirm_finished(Download* d);

3
src/core/hash_queue.cc

@ -49,8 +49,7 @@ namespace core {
void
HashQueue::insert(Download* download) {
if (download->download()->is_hash_checking() ||
find(download) != end())
if (download->download()->is_hash_checking() || find(download) != end())
return;
if (download->download()->is_hash_checked()) {

14
src/core/manager.cc

@ -59,7 +59,9 @@
#include "curl_get.h"
#include "download.h"
#include "download_factory.h"
#include "download_store.h"
#include "hash_queue.h"
#include "http_queue.h"
#include "manager.h"
#include "poll_manager_epoll.h"
#include "poll_manager_select.h"
@ -116,13 +118,19 @@ Manager::Manager() :
m_portFirst(6890),
m_portLast(6999) {
m_downloadStore = new DownloadStore();
m_downloadList = new DownloadList();
m_httpQueue = new HttpQueue();
m_hashQueue = new HashQueue(m_downloadList);
}
Manager::~Manager() {
delete m_hashQueue;
delete m_downloadList;
delete m_hashQueue;
delete m_downloadStore;
delete m_httpQueue;
}
void
@ -142,7 +150,7 @@ Manager::initialize_first() {
void
Manager::initialize_second() {
torrent::Http::set_factory(m_pollManager->get_http_stack()->get_http_factory());
m_httpQueue.slot_factory(m_pollManager->get_http_stack()->get_http_factory());
m_httpQueue->slot_factory(m_pollManager->get_http_stack()->get_http_factory());
CurlStack::global_init();
@ -152,8 +160,6 @@ Manager::initialize_second() {
m_downloadList->slot_map_insert()["1_connect_storage_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_storage_log), sigc::mem_fun(m_logComplete, &Log::push_front));
m_downloadList->slot_map_insert()["1_connect_tracker_dump"] = sigc::bind(sigc::ptr_fun(&connect_signal_tracker_dump), sigc::ptr_fun(&receive_tracker_dump));
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);
}

13
src/core/manager.h

@ -40,8 +40,6 @@
#include <iosfwd>
#include "download_list.h"
#include "download_store.h"
#include "http_queue.h"
#include "poll_manager.h"
#include "log.h"
@ -51,7 +49,9 @@ namespace torrent {
namespace core {
class DownloadStore;
class HashQueue;
class HttpQueue;
class Manager {
public:
@ -62,11 +62,12 @@ public:
Manager();
~Manager();
DownloadStore& download_store() { return m_downloadStore; }
HttpQueue& http_queue() { return m_httpQueue; }
DownloadList* download_list() { return m_downloadList; }
DownloadStore* download_store() { return m_downloadStore; }
HashQueue* hash_queue() { return m_hashQueue; }
HttpQueue* http_queue() { return m_httpQueue; }
PollManager* get_poll_manager() { return m_pollManager; }
Log& get_log_important() { return m_logImportant; }
@ -104,9 +105,9 @@ private:
void receive_http_failed(std::string msg);
DownloadList* m_downloadList;
DownloadStore m_downloadStore;
DownloadStore* m_downloadStore;
HashQueue* m_hashQueue;
HttpQueue m_httpQueue;
HttpQueue* m_httpQueue;
PollManager* m_pollManager;
Log m_logImportant;

6
src/core/poll_manager.cc

@ -36,8 +36,8 @@
#include "config.h"
#include <cerrno>
#include <stdexcept>
#include <rak/error_number.h>
#include "poll_manager.h"
@ -93,8 +93,8 @@ PollManager::~PollManager() {
void
PollManager::check_error() {
if (errno != EINTR)
throw std::runtime_error("Poll::work(): select error");
if (rak::error_number::current().value() != rak::error_number::e_intr)
throw std::runtime_error("Poll::work(): " + std::string(rak::error_number::current().c_str()));
}
}

16
src/main.cc

@ -50,6 +50,7 @@
#include "core/download.h"
#include "core/download_factory.h"
#include "core/download_store.h"
#include "core/manager.h"
#include "display/canvas.h"
#include "display/window.h"
@ -97,7 +98,7 @@ parse_options(Control* c, int argc, char** argv) {
void
load_session_torrents(Control* c) {
// Load session torrents.
std::list<std::string> l = c->core()->download_store().get_formated_entries().make_list();
std::list<std::string> l = c->core()->download_store()->get_formated_entries().make_list();
for (std::list<std::string>::iterator first = l.begin(), last = l.end(); first != last; ++first) {
core::DownloadFactory* f = new core::DownloadFactory(*first, c->core());
@ -164,8 +165,6 @@ main(int argc, char** argv) {
// Currently not doing any sorting on main.
control->variable()->process_command("view_add = main");
control->variable()->process_command("view_sort_new = main");
control->variable()->process_command("view_sort_current = main");
control->variable()->process_command("view_add = name");
control->variable()->process_command("view_sort_new = name,name");
@ -192,13 +191,14 @@ main(int argc, char** argv) {
control->variable()->process_command("view_sort_current = incomplete,state_changed_reverse");
control->variable()->process_command("schedule = view_main,10,10,view_sort=main,20");
control->variable()->process_command("schedule = view_name,10,10,view_sort=main,20");
control->variable()->process_command("schedule = view_started,10,10,view_sort=started,20");
control->variable()->process_command("schedule = view_stopped,10,10,view_sort=stopped,20");
control->variable()->process_command("schedule = view_complete,10,10,view_sort=complete,20");
control->variable()->process_command("schedule = view_incomplete,10,10,view_sort=incomplete,20");
control->variable()->process_command("schedule = view_name,10,10,view_sort=name,20");
control->variable()->process_command("schedule = view_started,10,10,view_sort=started,5");
control->variable()->process_command("schedule = view_stopped,10,10,view_sort=stopped,5");
control->variable()->process_command("schedule = view_complete,10,10,view_sort=complete,5");
control->variable()->process_command("schedule = view_incomplete,10,10,view_sort=incomplete,5");
//control->variable()->process_command("schedule = scheduler,10,10,download_scheduler=");
control->variable()->process_command("schedule = session_save,1800,1800,session_save=");
// Changing these will bork the (non-existant) scheduler.
control->variable()->process_command("view_add = scheduler");

36
src/option_handler_rules.cc

@ -52,6 +52,7 @@
#include <torrent/tracker_list.h>
#include "core/download.h"
#include "core/download_store.h"
#include "core/manager.h"
#include "core/scheduler.h"
#include "core/view_manager.h"
@ -97,7 +98,7 @@ apply_load_start(Control* m, const std::string& arg) {
}
void
apply_stop_untied(Control* m, __UNUSED const std::string& arg) {
apply_stop_untied(Control* m) {
core::Manager::DListItr itr = m->core()->download_list()->begin();
while ((itr = std::find_if(itr, m->core()->download_list()->end(),
@ -116,7 +117,7 @@ apply_stop_untied(Control* m, __UNUSED const std::string& arg) {
}
void
apply_remove_untied(Control* m, __UNUSED const std::string& arg) {
apply_remove_untied(Control* m) {
core::Manager::DListItr itr = m->core()->download_list()->begin();
while ((itr = std::find_if(itr, m->core()->download_list()->end(),
@ -272,8 +273,15 @@ apply_view_sort_new(Control* control, const std::string& arg) {
}
void
apply_download_scheduler(core::Scheduler* scheduler, __UNUSED const std::string& arg) {
scheduler->update();
apply_import(const std::string& path) {
if (!control->variable()->process_file(path))
throw torrent::input_error("Could not open option file: " + path);
}
void
apply_try_import(const std::string& path) {
if (!control->variable()->process_file(path))
control->core()->push_log("Could not read resource file: " + path);
}
void
@ -287,10 +295,11 @@ initialize_option_handler(Control* c) {
variables->insert("tracker_dump", new utils::VariableAny(std::string()));
variables->insert("session", new utils::VariableStringSlot(rak::mem_fn(&control->core()->download_store(), &core::DownloadStore::path),
rak::mem_fn(&control->core()->download_store(), &core::DownloadStore::set_path)));
variables->insert("session", new utils::VariableStringSlot(rak::mem_fn(control->core()->download_store(), &core::DownloadStore::path),
rak::mem_fn(control->core()->download_store(), &core::DownloadStore::set_path)));
variables->insert("session_lock", new utils::VariableBool(true));
variables->insert("session_on_completion", new utils::VariableBool(true));
variables->insert("session_save", new utils::VariableVoidSlot(rak::mem_fn(c->core()->download_list(), &core::DownloadList::session_save)));
variables->insert("connection_leech", new utils::VariableAny("leech"));
variables->insert("connection_seed", new utils::VariableAny("seed"));
@ -321,10 +330,8 @@ initialize_option_handler(Control* c) {
variables->insert("max_open_sockets", new utils::VariableValueSlot(rak::ptr_fn(&torrent::max_open_sockets), rak::ptr_fn(&torrent::set_max_open_sockets)));
variables->insert("print", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(control->core(), &core::Manager::push_log)));
variables->insert("import", new utils::VariableStringSlot(rak::value_fn(std::string()),
rak::mem_fn(control->variable(), &utils::VariableMap::process_file_throw)));
variables->insert("try_import", new utils::VariableStringSlot(rak::value_fn(std::string()),
rak::mem_fn(control->variable(), &utils::VariableMap::process_file_nothrow)));
variables->insert("import", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_import)));
variables->insert("try_import", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_try_import)));
variables->insert("view_add", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(c->view_manager(), &core::ViewManager::insert_throw)));
variables->insert("view_filter", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_filter, c)));
@ -333,12 +340,11 @@ initialize_option_handler(Control* c) {
variables->insert("view_sort_new", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort_new, c)));
variables->insert("view_sort_current", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort_current, c)));
variables->insert("schedule", new utils::VariableStringSlot(rak::value_fn(std::string()),
rak::mem_fn<const std::string&>(c->command_scheduler(), &CommandScheduler::parse)));
variables->insert("schedule", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(c->command_scheduler(), &CommandScheduler::parse)));
variables->insert("schedule_remove", new utils::VariableStringSlot(rak::value_fn(std::string()),
rak::mem_fn<const std::string&>(c->command_scheduler(), &CommandScheduler::erase)));
variables->insert("download_scheduler", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_download_scheduler, c->scheduler())));
variables->insert("download_scheduler", new utils::VariableVoidSlot(rak::mem_fn(control->scheduler(), &core::Scheduler::update)));
variables->insert("send_buffer_size", new utils::VariableValueSlot(rak::mem_fn(torrent::connection_manager(), &torrent::ConnectionManager::send_buffer_size),
rak::mem_fn(torrent::connection_manager(), &torrent::ConnectionManager::set_send_buffer_size)));
@ -357,8 +363,8 @@ initialize_option_handler(Control* c) {
variables->insert("load", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load, c)));
variables->insert("load_start", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load_start, c)));
variables->insert("stop_untied", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_stop_untied, c)));
variables->insert("remove_untied", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_remove_untied, c)));
variables->insert("stop_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_stop_untied, c)));
variables->insert("remove_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_remove_untied, c)));
variables->insert("enable_trackers", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_enable_trackers, c)));
variables->insert("encoding_list", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_encoding_list, c)));

2
src/ui/download_list.cc

@ -76,7 +76,7 @@ DownloadList::DownloadList(Control* c) :
m_window(c->display()->end()),
m_windowTitle(new WTitle("rTorrent " VERSION " - libTorrent " + std::string(torrent::version()))),
m_windowHttpQueue(new WHttp(&c->core()->http_queue())),
m_windowHttpQueue(new WHttp(c->core()->http_queue())),
m_uiDownload(NULL),

10
src/utils/variable_generic.cc

@ -155,6 +155,16 @@ VariableObject::set(const torrent::Object& arg) {
// New and prettified.
//
const torrent::Object&
VariableVoidSlot::get() {
return m_cache;
}
void
VariableVoidSlot::set(const torrent::Object& arg) {
m_slotSet();
}
const torrent::Object&
VariableValueSlot::get() {
m_cache = m_slotGet() / m_unit;

21
src/utils/variable_generic.h

@ -102,6 +102,26 @@ private:
// New and pretty.
//
class VariableVoidSlot : public Variable {
public:
typedef rak::function0<void> slot_set_type;
VariableVoidSlot(slot_set_type::base_type* slotSet) {
m_slotSet.set(slotSet);
}
virtual const torrent::Object& get();
virtual void set(const torrent::Object& arg);
private:
slot_set_type m_slotSet;
// Store the cache here to avoid unnessesary copying and such. This
// should not result in any unresonable memory usage since few
// strings will be very large.
torrent::Object m_cache;
};
class VariableValueSlot : public Variable {
public:
typedef rak::function0<value_type> slot_get_type;
@ -160,7 +180,6 @@ private:
torrent::Object m_cache;
};
}
#endif

11
src/utils/variable_map.cc

@ -198,15 +198,4 @@ VariableMap::process_file(const std::string& path) {
return true;
}
void
VariableMap::process_file_throw(const std::string& path) {
if (!process_file(path))
throw torrent::input_error("Could not open option file: " + path);
}
void
VariableMap::process_file_nothrow(const std::string& path) {
process_file(path);
}
}

2
src/utils/variable_map.h

@ -77,8 +77,6 @@ public:
void process_command(const std::string& command);
void process_stream(std::istream* str);
bool process_file(const std::string& path);
void process_file_throw(const std::string& path);
void process_file_nothrow(const std::string& path);
private:
VariableMap(const VariableMap&);

Loading…
Cancel
Save