mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-13 05:32:31 +00:00
* Added "working_directory" option that calls chdir.
* Added "session_on_completion" option which saves the session torrent when a download finishes. * Handle SIGTERM gracefully, saving session torrents etc. * Implemented session directory lockfile, use "session_lock" option to disable. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@629 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#include <cstdlib>
|
||||
#include <time.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "command_scheduler.h"
|
||||
@@ -114,6 +115,27 @@ CommandScheduler::call_item(value_type item) {
|
||||
item->enable(next);
|
||||
}
|
||||
|
||||
void
|
||||
CommandScheduler::parse(const std::string& arg) {
|
||||
char key[21];
|
||||
char bufAbsolute[21];
|
||||
char bufInterval[21];
|
||||
char command[2048];
|
||||
|
||||
if (std::sscanf(arg.c_str(), "%20[^,],%20[^,],%20[^,],%2047[^\n]", key, bufAbsolute, bufInterval, command) != 4)
|
||||
throw torrent::input_error("Invalid arguments to command.");
|
||||
|
||||
uint32_t absolute = parse_absolute(bufAbsolute);
|
||||
uint32_t interval = parse_interval(bufInterval);
|
||||
|
||||
CommandSchedulerItem* item = *insert(rak::trim(std::string(key)));
|
||||
|
||||
item->set_command(rak::trim(std::string(command)));
|
||||
item->set_interval(interval);
|
||||
|
||||
item->enable((cachedTime + rak::timer(absolute) * 1000000).round_seconds());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CommandScheduler::parse_absolute(const char* str) {
|
||||
Time result = parse_time(str);
|
||||
|
||||
@@ -69,6 +69,8 @@ public:
|
||||
void erase(iterator itr);
|
||||
void erase(const std::string& key) { erase(find(key)); }
|
||||
|
||||
void parse(const std::string& arg);
|
||||
|
||||
static uint32_t parse_absolute(const char* str);
|
||||
static uint32_t parse_interval(const char* str);
|
||||
|
||||
|
||||
+9
-7
@@ -67,7 +67,7 @@ Control::Control() :
|
||||
|
||||
m_inputStdin->slot_pressed(sigc::mem_fun(m_input, &input::Manager::pressed));
|
||||
|
||||
m_taskShutdown.set_slot(rak::mem_fn(this, &Control::receive_shutdown));
|
||||
m_taskShutdown.set_slot(rak::mem_fn(this, &Control::handle_shutdown));
|
||||
|
||||
m_commandScheduler->set_slot_command(rak::mem_fn(m_variables, &utils::VariableMap::process_command));
|
||||
m_commandScheduler->set_slot_error_message(rak::mem_fn(m_core, &core::Manager::push_log));
|
||||
@@ -98,6 +98,7 @@ Control::initialize() {
|
||||
|
||||
m_core->initialize_second();
|
||||
m_core->listen_open();
|
||||
m_core->download_store().enable(m_variables->get_string("session_lock") == "yes");
|
||||
|
||||
m_ui->init(this);
|
||||
|
||||
@@ -110,6 +111,8 @@ Control::cleanup() {
|
||||
|
||||
m_inputStdin->remove(m_core->get_poll_manager()->get_torrent_poll());
|
||||
|
||||
m_core->download_store().disable();
|
||||
|
||||
m_ui->cleanup();
|
||||
m_core->cleanup();
|
||||
|
||||
@@ -119,15 +122,11 @@ Control::cleanup() {
|
||||
display::Canvas::cleanup();
|
||||
}
|
||||
|
||||
// I think it should be safe to initiate the shutdown from anywhere,
|
||||
// but if it isn't, use a delay task.
|
||||
void
|
||||
Control::receive_shutdown() {
|
||||
if (!m_shutdownReceived) {
|
||||
Control::handle_shutdown() {
|
||||
if (!m_shutdownQuick) {
|
||||
torrent::listen_close();
|
||||
|
||||
m_core->shutdown(false);
|
||||
m_shutdownReceived = true;
|
||||
|
||||
if (!m_taskShutdown.is_queued())
|
||||
priority_queue_insert(&taskScheduler, &m_taskShutdown, cachedTime + 5 * 1000000);
|
||||
@@ -135,4 +134,7 @@ Control::receive_shutdown() {
|
||||
} else {
|
||||
m_core->shutdown(true);
|
||||
}
|
||||
|
||||
m_shutdownQuick = true;
|
||||
m_shutdownReceived = false;
|
||||
}
|
||||
|
||||
+6
-2
@@ -70,13 +70,16 @@ public:
|
||||
Control();
|
||||
~Control();
|
||||
|
||||
bool is_shutdown_completed() { return m_shutdownReceived && torrent::is_inactive(); }
|
||||
bool is_shutdown_completed() { return m_shutdownQuick && torrent::is_inactive(); }
|
||||
bool is_shutdown_received() { return m_shutdownReceived; }
|
||||
|
||||
void initialize();
|
||||
void cleanup();
|
||||
|
||||
void receive_shutdown();
|
||||
void handle_shutdown();
|
||||
|
||||
void receive_normal_shutdown() { m_shutdownReceived = true; }
|
||||
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; }
|
||||
|
||||
ui::Root* ui() { return m_ui; }
|
||||
core::Manager* core() { return m_core; }
|
||||
@@ -95,6 +98,7 @@ private:
|
||||
void operator = (const Control&);
|
||||
|
||||
bool m_shutdownReceived;
|
||||
bool m_shutdownQuick;
|
||||
|
||||
ui::Root* m_ui;
|
||||
core::Manager* m_core;
|
||||
|
||||
@@ -99,7 +99,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->get_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));
|
||||
@@ -139,7 +139,7 @@ DownloadFactory::receive_success() {
|
||||
|
||||
Manager::DListItr itr = m_manager->insert(m_stream, m_printLog);
|
||||
|
||||
if (itr == m_manager->get_download_list().end()) {
|
||||
if (itr == m_manager->download_list().end()) {
|
||||
// core::Manager should already have added the error message to
|
||||
// the log.
|
||||
m_slotFinished();
|
||||
@@ -206,7 +206,7 @@ DownloadFactory::receive_success() {
|
||||
if (m_start)
|
||||
m_manager->start(*itr, m_printLog);
|
||||
|
||||
m_manager->get_download_store().save(*itr);
|
||||
m_manager->download_store().save(*itr);
|
||||
}
|
||||
|
||||
m_slotFinished();
|
||||
|
||||
@@ -52,16 +52,44 @@
|
||||
namespace core {
|
||||
|
||||
void
|
||||
DownloadStore::use(const std::string& path) {
|
||||
m_path = path;
|
||||
DownloadStore::enable(bool lock) {
|
||||
if (is_enabled())
|
||||
throw torrent::input_error("Session directory already enabled.");
|
||||
|
||||
if (!m_path.empty() && *m_path.rbegin() != '/')
|
||||
m_path += '/';
|
||||
if (m_path.empty())
|
||||
return;
|
||||
|
||||
if (lock)
|
||||
m_lockfile.set_path(m_path + "rtorrent.lock");
|
||||
else
|
||||
m_lockfile.set_path(std::string());
|
||||
|
||||
if (!m_lockfile.try_lock())
|
||||
throw torrent::input_error("Could not lock session directory: \"" + m_path + "\".");
|
||||
}
|
||||
|
||||
void
|
||||
DownloadStore::disable() {
|
||||
if (!is_enabled())
|
||||
return;
|
||||
|
||||
m_lockfile.unlock();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadStore::set_path(const std::string& path) {
|
||||
if (is_enabled())
|
||||
throw torrent::input_error("Tried to change session directory while it is enabled.");
|
||||
|
||||
if (!path.empty() && *path.rbegin() != '/')
|
||||
m_path = path + '/';
|
||||
else
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
void
|
||||
DownloadStore::save(Download* d) {
|
||||
if (!is_active())
|
||||
if (!is_enabled())
|
||||
return;
|
||||
|
||||
std::fstream f((create_filename(d) + ".new").c_str(), std::ios::out | std::ios::trunc);
|
||||
@@ -92,7 +120,7 @@ DownloadStore::save(Download* d) {
|
||||
|
||||
void
|
||||
DownloadStore::remove(Download* d) {
|
||||
if (!is_active())
|
||||
if (!is_enabled())
|
||||
return;
|
||||
|
||||
::unlink(create_filename(d).c_str());
|
||||
@@ -100,7 +128,7 @@ DownloadStore::remove(Download* d) {
|
||||
|
||||
utils::Directory
|
||||
DownloadStore::get_formated_entries() {
|
||||
if (!is_active())
|
||||
if (!is_enabled())
|
||||
return utils::Directory();
|
||||
|
||||
utils::Directory d(m_path);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "utils/directory.h"
|
||||
#include "utils/lockfile.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -48,22 +49,26 @@ class Download;
|
||||
class DownloadStore {
|
||||
public:
|
||||
|
||||
// Disable by passing an empty string.
|
||||
void use(const std::string& path);
|
||||
bool is_enabled() { return m_lockfile.is_locked(); }
|
||||
|
||||
bool is_active() { return !m_path.empty(); }
|
||||
void enable(bool lock);
|
||||
void disable();
|
||||
|
||||
void save(Download* d);
|
||||
void remove(Download* d);
|
||||
const std::string& path() const { return m_path; }
|
||||
void set_path(const std::string& path);
|
||||
|
||||
void save(Download* d);
|
||||
void remove(Download* d);
|
||||
|
||||
// Currently shows all entries in the correct format.
|
||||
utils::Directory get_formated_entries();
|
||||
utils::Directory get_formated_entries();
|
||||
|
||||
private:
|
||||
static bool is_correct_format(std::string f);
|
||||
std::string create_filename(Download* d);
|
||||
static bool is_correct_format(std::string f);
|
||||
std::string create_filename(Download* d);
|
||||
|
||||
std::string m_path;
|
||||
std::string m_path;
|
||||
utils::Lockfile m_lockfile;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+6
-5
@@ -107,6 +107,7 @@ Manager::initialize_first() {
|
||||
torrent::initialize(m_pollManager->get_torrent_poll());
|
||||
}
|
||||
|
||||
// Most of this should be possible to move out.
|
||||
void
|
||||
Manager::initialize_second() {
|
||||
torrent::Http::set_factory(m_pollManager->get_http_stack()->get_http_factory());
|
||||
@@ -116,11 +117,8 @@ Manager::initialize_second() {
|
||||
|
||||
// Register slots to be called when a download is inserted/erased,
|
||||
// opened or closed.
|
||||
// m_downloadList.slot_map_insert()["0_initialize_bencode"] = sigc::mem_fun(*this, &Manager::initialize_bencode);
|
||||
m_downloadList.slot_map_insert()["1_connect_network_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_network_log), sigc::mem_fun(m_logComplete, &Log::push_front));
|
||||
// m_downloadList.slot_map_insert()["1_connect_tracker_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_tracker_log), sigc::mem_fun(m_logComplete, &Log::push_front));
|
||||
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_enable_udp_trackers"] = sigc::bind(sigc::mem_fun(&core::Download::enable_udp_trackers), true);
|
||||
|
||||
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);
|
||||
@@ -319,9 +317,12 @@ Manager::receive_download_done_hash_checked(Download* d) {
|
||||
if (!d->get_download().is_active())
|
||||
m_downloadList.start(d);
|
||||
|
||||
if (control->variables()->get_string("session_on_completion") == "yes")
|
||||
m_downloadStore.save(d);
|
||||
|
||||
// Don't send if we did a hash check and found incompelete chunks.
|
||||
//if (d->is_done())
|
||||
d->get_download().tracker_send_completed();
|
||||
if (d->is_done())
|
||||
d->get_download().tracker_send_completed();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+4
-4
@@ -60,10 +60,10 @@ public:
|
||||
|
||||
Manager();
|
||||
|
||||
DownloadList& get_download_list() { return m_downloadList; }
|
||||
DownloadStore& get_download_store() { return m_downloadStore; }
|
||||
HashQueue& get_hash_queue() { return m_hashQueue; }
|
||||
HttpQueue& get_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; }
|
||||
|
||||
+6
-15
@@ -77,19 +77,6 @@
|
||||
void do_panic(int signum);
|
||||
void print_help();
|
||||
|
||||
bool
|
||||
is_resized() {
|
||||
static int x = 0;
|
||||
static int y = 0;
|
||||
|
||||
bool r = display::Canvas::get_screen_width() != x || display::Canvas::get_screen_height() != y;
|
||||
|
||||
x = display::Canvas::get_screen_width();
|
||||
y = display::Canvas::get_screen_height();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
parse_options(Control* c, utils::VariableMap* optionHandler, int argc, char** argv) {
|
||||
try {
|
||||
@@ -116,7 +103,7 @@ parse_options(Control* c, utils::VariableMap* optionHandler, int argc, char** ar
|
||||
void
|
||||
load_session_torrents(Control* c) {
|
||||
// Load session torrents.
|
||||
std::list<std::string> l = c->core()->get_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());
|
||||
@@ -170,7 +157,8 @@ main(int argc, char** argv) {
|
||||
initialize_option_handler(control);
|
||||
|
||||
SignalHandler::set_ignore(SIGPIPE);
|
||||
SignalHandler::set_handler(SIGINT, sigc::mem_fun(control, &Control::receive_shutdown));
|
||||
SignalHandler::set_handler(SIGINT, sigc::mem_fun(control, &Control::receive_normal_shutdown));
|
||||
SignalHandler::set_handler(SIGTERM, sigc::mem_fun(control, &Control::receive_quick_shutdown));
|
||||
SignalHandler::set_handler(SIGWINCH, sigc::mem_fun(control->display(), &display::Manager::force_redraw));
|
||||
SignalHandler::set_handler(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV));
|
||||
SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS));
|
||||
@@ -198,6 +186,9 @@ main(int argc, char** argv) {
|
||||
control->display()->adjust_layout();
|
||||
|
||||
while (!control->is_shutdown_completed()) {
|
||||
if (control->is_shutdown_received())
|
||||
control->handle_shutdown();
|
||||
|
||||
control->inc_tick();
|
||||
|
||||
cachedTime = rak::timer::current();
|
||||
|
||||
+21
-61
@@ -37,9 +37,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <rak/file_stat.h>
|
||||
@@ -59,38 +57,18 @@
|
||||
#include "control.h"
|
||||
#include "option_handler_rules.h"
|
||||
#include "command_scheduler.h"
|
||||
#include "command_scheduler_item.h"
|
||||
|
||||
// void
|
||||
// OptionHandlerInt::process(const std::string& key, const std::string& arg) {
|
||||
// int a;
|
||||
|
||||
// if (std::sscanf(arg.c_str(), "%i", &a) != 1)
|
||||
// throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\", must be an integer.");
|
||||
|
||||
// m_apply(m_control, a);
|
||||
// }
|
||||
|
||||
// void
|
||||
// OptionHandlerOctal::process(const std::string& key, const std::string& arg) {
|
||||
// int a;
|
||||
|
||||
// if (std::sscanf(arg.c_str(), "%o", &a) != 1)
|
||||
// throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\", must be an octal.");
|
||||
|
||||
// m_apply(m_control, a);
|
||||
// }
|
||||
|
||||
// void
|
||||
// OptionHandlerString::process(const std::string& key, const std::string& arg) {
|
||||
// m_apply(m_control, arg);
|
||||
// }
|
||||
|
||||
void
|
||||
apply_umask(int arg) {
|
||||
umask(arg);
|
||||
}
|
||||
|
||||
void
|
||||
apply_working_directory(const std::string& path) {
|
||||
if (chdir(path.c_str()) != 0)
|
||||
throw torrent::input_error("Could not change working directory.");
|
||||
}
|
||||
|
||||
void
|
||||
apply_hash_read_ahead(Control* m, int arg) {
|
||||
torrent::set_hash_read_ahead(arg << 20);
|
||||
@@ -129,12 +107,12 @@ apply_load_start(Control* m, const std::string& arg) {
|
||||
|
||||
void
|
||||
apply_stop_untied(Control* m, const std::string& arg) {
|
||||
core::Manager::DListItr itr = m->core()->get_download_list().begin();
|
||||
core::Manager::DListItr itr = m->core()->download_list().begin();
|
||||
|
||||
while ((itr = std::find_if(itr, m->core()->get_download_list().end(),
|
||||
while ((itr = std::find_if(itr, m->core()->download_list().end(),
|
||||
rak::on(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"),
|
||||
std::not1(std::mem_fun_ref(&std::string::empty)))))
|
||||
!= m->core()->get_download_list().end()) {
|
||||
!= m->core()->download_list().end()) {
|
||||
rak::file_stat fs;
|
||||
|
||||
if (!fs.update((*itr)->variable_string("tied_to_file"))) {
|
||||
@@ -148,12 +126,12 @@ apply_stop_untied(Control* m, const std::string& arg) {
|
||||
|
||||
void
|
||||
apply_remove_untied(Control* m, const std::string& arg) {
|
||||
core::Manager::DListItr itr = m->core()->get_download_list().begin();
|
||||
core::Manager::DListItr itr = m->core()->download_list().begin();
|
||||
|
||||
while ((itr = std::find_if(itr, m->core()->get_download_list().end(),
|
||||
while ((itr = std::find_if(itr, m->core()->download_list().end(),
|
||||
rak::on(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"),
|
||||
std::not1(std::mem_fun_ref(&std::string::empty)))))
|
||||
!= m->core()->get_download_list().end()) {
|
||||
!= m->core()->download_list().end()) {
|
||||
rak::file_stat fs;
|
||||
|
||||
if (!fs.update((*itr)->variable_string("tied_to_file"))) {
|
||||
@@ -172,41 +150,23 @@ apply_encoding_list(Control* m, const std::string& arg) {
|
||||
torrent::encoding_list()->push_back(arg);
|
||||
}
|
||||
|
||||
void
|
||||
apply_schedule(Control* m, const std::string& arg) {
|
||||
char key[21];
|
||||
char bufAbsolute[21];
|
||||
char bufInterval[21];
|
||||
char command[2048];
|
||||
|
||||
if (std::sscanf(arg.c_str(), "%20[^,],%20[^,],%20[^,],%2047[^\n]", key, bufAbsolute, bufInterval, command) != 4)
|
||||
throw torrent::input_error("Invalid arguments to command.");
|
||||
|
||||
uint32_t absolute = CommandScheduler::parse_absolute(bufAbsolute);
|
||||
uint32_t interval = CommandScheduler::parse_interval(bufInterval);
|
||||
|
||||
CommandSchedulerItem* item = *m->command_scheduler()->insert(rak::trim(std::string(key)));
|
||||
|
||||
item->set_command(rak::trim(std::string(command)));
|
||||
item->set_interval(interval);
|
||||
|
||||
item->enable((cachedTime + rak::timer(absolute) * 1000000).round_seconds());
|
||||
}
|
||||
|
||||
void
|
||||
initialize_option_handler(Control* c) {
|
||||
utils::VariableMap* variables = control->variables();
|
||||
|
||||
// Cleaned up.
|
||||
variables->insert("check_hash", new utils::VariableAny("yes"));
|
||||
variables->insert("use_udp_trackers", new utils::VariableAny("yes"));
|
||||
variables->insert("port_random", new utils::VariableAny("yes"));
|
||||
variables->insert("session", new utils::VariableSlotString<>(NULL, rak::mem_fn(&control->core()->get_download_store(), &core::DownloadStore::use)));
|
||||
variables->insert("check_hash", new utils::VariableAny("yes"));
|
||||
variables->insert("use_udp_trackers", new utils::VariableAny("yes"));
|
||||
variables->insert("port_random", new utils::VariableAny("yes"));
|
||||
variables->insert("session", new utils::VariableSlotString<>(NULL, rak::mem_fn(&control->core()->download_store(), &core::DownloadStore::set_path)));
|
||||
variables->insert("session_lock", new utils::VariableAny("yes"));
|
||||
variables->insert("session_on_completion", new utils::VariableAny("yes"));
|
||||
|
||||
variables->insert("connection_leech", new utils::VariableAny("leech"));
|
||||
variables->insert("connection_seed", new utils::VariableAny("seed"));
|
||||
|
||||
variables->insert("directory", new utils::VariableAny("./"));
|
||||
variables->insert("working_directory", new utils::VariableSlotString<>(NULL, rak::ptr_fn(&apply_working_directory)));
|
||||
variables->insert("ip", new utils::VariableSlotString<>(NULL, rak::ptr_fn(&torrent::set_local_address)));
|
||||
variables->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::bind)));
|
||||
|
||||
@@ -223,6 +183,7 @@ initialize_option_handler(Control* c) {
|
||||
|
||||
variables->insert("print", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::push_log)));
|
||||
|
||||
variables->insert("schedule", new utils::VariableSlotString<>(NULL, rak::mem_fn<const std::string&>(c->command_scheduler(), &CommandScheduler::parse)));
|
||||
variables->insert("schedule_remove", new utils::VariableSlotString<>(NULL, rak::mem_fn<const std::string&>(c->command_scheduler(), &CommandScheduler::erase)));
|
||||
|
||||
// Old.
|
||||
@@ -241,5 +202,4 @@ initialize_option_handler(Control* c) {
|
||||
variables->insert("encoding_list", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_encoding_list, c)));
|
||||
|
||||
variables->insert("http_proxy", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_http_proxy, c)));
|
||||
variables->insert("schedule", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_schedule, c)));
|
||||
}
|
||||
|
||||
@@ -37,55 +37,8 @@
|
||||
#ifndef RTORRENT_OPTION_HANDLER_RULES_H
|
||||
#define RTORRENT_OPTION_HANDLER_RULES_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
class Control;
|
||||
|
||||
void initialize_option_handler(Control* c);
|
||||
|
||||
class OptionHandlerInt {
|
||||
public:
|
||||
typedef void (*Apply)(Control*, int);
|
||||
|
||||
OptionHandlerInt(Control* c, Apply a) :
|
||||
m_control(c), m_apply(a) {}
|
||||
|
||||
virtual void process(const std::string& key, const std::string& arg);
|
||||
|
||||
private:
|
||||
Control* m_control;
|
||||
Apply m_apply;
|
||||
};
|
||||
|
||||
class OptionHandlerOctal {
|
||||
public:
|
||||
typedef void (*Apply)(Control*, int);
|
||||
|
||||
OptionHandlerOctal(Control* c, Apply a) :
|
||||
m_control(c), m_apply(a) {}
|
||||
|
||||
virtual void process(const std::string& key, const std::string& arg);
|
||||
|
||||
private:
|
||||
Control* m_control;
|
||||
Apply m_apply;
|
||||
};
|
||||
|
||||
class OptionHandlerString {
|
||||
public:
|
||||
typedef void (*Apply)(Control*, const std::string&);
|
||||
|
||||
OptionHandlerString(Control* c, Apply a) :
|
||||
m_control(c), m_apply(a) {}
|
||||
|
||||
virtual void process(const std::string& key, const std::string& arg);
|
||||
|
||||
private:
|
||||
Control* m_control;
|
||||
Apply m_apply;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -73,11 +73,11 @@ 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()->get_http_queue())),
|
||||
m_windowHttpQueue(new WHttp(&c->core()->http_queue())),
|
||||
|
||||
m_uiDownload(NULL),
|
||||
|
||||
m_downloadList(&c->core()->get_download_list()),
|
||||
m_downloadList(&c->core()->download_list()),
|
||||
|
||||
m_control(c),
|
||||
m_bindings(new input::Bindings)
|
||||
@@ -124,7 +124,7 @@ DownloadList::activate() {
|
||||
|
||||
m_control->input()->push_front(m_bindings);
|
||||
|
||||
m_control->core()->get_download_list().slot_map_erase().insert("0_download_list", sigc::mem_fun(this, &DownloadList::receive_download_erased));
|
||||
m_control->core()->download_list().slot_map_erase().insert("0_download_list", sigc::mem_fun(this, &DownloadList::receive_download_erased));
|
||||
|
||||
activate_display(DISPLAY_DOWNLOAD_LIST);
|
||||
}
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ Root::setup_keys() {
|
||||
|
||||
//m_bindings[KEY_RESIZE] = sigc::mem_fun(*m_control->display(), &display::Manager::adjust_layout);
|
||||
m_bindings['\x0C'] = sigc::mem_fun(m_control->display(), &display::Manager::force_redraw);
|
||||
m_bindings['\x11'] = sigc::mem_fun(m_control, &Control::receive_shutdown);
|
||||
m_bindings['\x11'] = sigc::mem_fun(m_control, &Control::receive_normal_shutdown);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -4,6 +4,8 @@ libsub_utils_a_SOURCES = \
|
||||
directory.cc \
|
||||
directory.h \
|
||||
list_focus.h \
|
||||
lockfile.cc \
|
||||
lockfile.h \
|
||||
variable.h \
|
||||
variable_generic.cc \
|
||||
variable_generic.h \
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2006, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "lockfile.h"
|
||||
|
||||
namespace utils {
|
||||
|
||||
bool
|
||||
Lockfile::try_lock() {
|
||||
if (m_path.empty()) {
|
||||
m_id = "foo";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Just do a simple locking for now that isn't safe for network
|
||||
// devices.
|
||||
int fd = ::open(m_path.c_str(), O_RDWR | O_CREAT | O_EXCL);
|
||||
|
||||
if (fd == -1)
|
||||
return false;
|
||||
|
||||
m_id = "foo";
|
||||
::close(fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Lockfile::unlock() {
|
||||
if (m_path.empty())
|
||||
return true;
|
||||
else
|
||||
return ::unlink(m_path.c_str()) != -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2006, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_UTILS_LOCKFILE_H
|
||||
#define RTORRENT_UTILS_LOCKFILE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace utils {
|
||||
|
||||
class Lockfile {
|
||||
public:
|
||||
|
||||
bool is_locked() const { return !m_id.empty(); }
|
||||
|
||||
// If the path is empty no lock file will be created, although
|
||||
// is_locked() will return true.
|
||||
bool try_lock();
|
||||
bool unlock();
|
||||
|
||||
const std::string& path() const { return m_path; }
|
||||
void set_path(const std::string& path) { m_path = path; }
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
std::string m_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -37,6 +37,8 @@
|
||||
#ifndef RTORRENT_UTILS_VARIABLE_H
|
||||
#define RTORRENT_UTILS_VARIABLE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace torrent {
|
||||
class Bencode;
|
||||
}
|
||||
@@ -49,7 +51,7 @@ public:
|
||||
virtual ~Variable() {}
|
||||
|
||||
virtual const torrent::Bencode& get() = 0;
|
||||
virtual void set(const torrent::Bencode& arg) = 0;
|
||||
virtual void set(const torrent::Bencode& arg) = 0;
|
||||
|
||||
protected:
|
||||
Variable(const Variable&);
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// Parts of this seems ugly in an attempt to avoid copying
|
||||
// data. Propably need to rewrite torrent::Bencode.
|
||||
|
||||
#ifndef RTORRENT_UTILS_VARIABLE_GENERIC_H
|
||||
#define RTORRENT_UTILS_VARIABLE_GENERIC_H
|
||||
|
||||
@@ -56,7 +59,7 @@ public:
|
||||
virtual ~VariableAny();
|
||||
|
||||
virtual const torrent::Bencode& get();
|
||||
virtual void set(const torrent::Bencode& arg);
|
||||
virtual void set(const torrent::Bencode& arg);
|
||||
|
||||
private:
|
||||
torrent::Bencode m_variable;
|
||||
@@ -68,7 +71,7 @@ public:
|
||||
virtual ~VariableValue();
|
||||
|
||||
virtual const torrent::Bencode& get();
|
||||
virtual void set(const torrent::Bencode& arg);
|
||||
virtual void set(const torrent::Bencode& arg);
|
||||
|
||||
private:
|
||||
torrent::Bencode m_variable;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
// Consider taking char* start and finish instead of std::string to
|
||||
// avoid copying. Or make a view class.
|
||||
const mapped_type& get(const std::string& key);
|
||||
std::string get_string(const std::string& key);
|
||||
const std::string& get_string(const std::string& key) { return get(key).as_string(); }
|
||||
|
||||
void set(const std::string& key, const mapped_type& arg);
|
||||
void set_string(const std::string& key, const std::string& arg) { set(key, mapped_type(arg)); }
|
||||
@@ -74,16 +74,6 @@ private:
|
||||
void operator = (const VariableMap&);
|
||||
};
|
||||
|
||||
inline std::string
|
||||
VariableMap::get_string(const std::string& key) {
|
||||
const mapped_type& v = get(key);
|
||||
|
||||
if (v.get_type() == mapped_type::TYPE_NONE)
|
||||
return std::string();
|
||||
else
|
||||
return v.as_string();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user