* Don't show ETA on finished and stopped torrents.

* Added percentage completed to active unfinished torrents.

* Re-enabled different seeding and leeching priorities.

* Make a temporary container in AvailableList::insert(AddressList*)
when doing std::set_differernce. AvailableList's std::vector would
resize and cause invalidated iterators to be used.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@630 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2006-02-04 19:18:41 +00:00
parent d06ecda46a
commit 68502367ec
17 changed files with 184 additions and 91 deletions
+56 -19
View File
@@ -139,6 +139,21 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term>^O</term>
<listitem><para>
Change the destination directory of the download. The
torrent must be closed.
</para></listitem>
</varlistentry>
<varlistentry>
<term>+ | -</term>
<listitem><para>
Change the priority of the download.
</para></listitem>
</varlistentry>
<varlistentry>
<term>backspace</term>
<listitem><para>
@@ -155,6 +170,13 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term>^P</term>
<listitem><para>
Call commands or change settings.
</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
@@ -424,6 +446,11 @@ seconds, starting from <emphasis>start</emphasis>. An
<emphasis>start</emphasis> of zero calls it immediately. Currently
<emphasis>command</emphasis> is forwarded to the option handler.
<emphasis>start</emphasis> and <emphasis>interval</emphasis> may
optionally use a time format, <emphasis>dd:hh:mm:ss</emphasis>. F.ex to
start a task every day at <emphasis>18:00</emphasis>, use
<emphasis>18:00:00</emphasis>.
</para></listitem>
</varlistentry>
@@ -455,9 +482,8 @@ to the filename provided.
<term>remove_untied =</term>
<listitem><para>
Stop or remove the torrents that are tied to filenames that has been
deleted, the association is then cleared. Don't use
<emphasis>remove_untied</emphasis> as it crashes the client.
Stop or remove the torrents that are tied to filenames that have been
deleted, the association is then cleared.
</para></listitem>
</varlistentry>
@@ -530,23 +556,34 @@ deleted, the association is then cleared. Don't use
</para></listitem>
</varlistentry>
<!-- <varlistentry> -->
<!-- <term>throttle_interval = <replaceable>ms</replaceable></term> -->
<!-- <listitem><para> -->
<!-- Interval between throttle ticks in milli-seconds, must be -->
<!-- between <emphasis>1-5000</emphasis> and defaults to -->
<!-- <emphasis>1000</emphasis>. Shorter intervals will cause less -->
<!-- bandwidth usage spikes while requiring more CPU resources. -->
<!-- </para></listitem> -->
<!-- </varlistentry> -->
<varlistentry>
<term>working_directory = <replaceable>directory</replaceable></term>
<listitem><para>
<!-- <varlistentry> -->
<!-- <term>tracker_dump = <replaceable>yes | no</replaceable></term> -->
<!-- <listitem><para> -->
<!-- Dump data received from trackers to the files -->
<!-- "./tracker_dump.*". -->
<!-- </para></listitem> -->
<!-- </varlistentry> -->
Changes the working directory of the process using
<emphasis>chdir</emphasis>.
</para></listitem>
</varlistentry>
<varlistentry>
<term>session_on_completion = <replaceable>yes</replaceable></term>
<listitem><para>
Controls whetever the session torrent is updated when a torrent
finishes. By default on.
</para></listitem>
</varlistentry>
<varlistentry>
<term>session_lock = <replaceable>yes</replaceable></term>
<listitem><para>
Controls whetever a lock file is created in the session directory.
</para></listitem>
</varlistentry>
</variablelist>
+1 -2
View File
@@ -53,6 +53,7 @@
Control::Control() :
m_shutdownReceived(false),
m_shutdownQuick(false),
m_ui(new ui::Root()),
m_core(new core::Manager()),
@@ -92,8 +93,6 @@ Control::initialize() {
display::Window::slot_unschedule(rak::make_mem_fun(m_display, &display::Manager::unschedule));
display::Window::slot_adjust(rak::make_mem_fun(m_display, &display::Manager::adjust_layout));
// m_core->get_poll_manager()->signal_interrupted().connect(sigc::mem_fun(*m_inputStdin, &input::InputEvent::event_read));
// m_core->get_poll_manager()->signal_interrupted().connect(sigc::ptr_fun(display::Canvas::do_update));
m_core->get_poll_manager()->get_http_stack()->set_user_agent(std::string(PACKAGE "/" VERSION "/") + torrent::version());
m_core->initialize_second();
+1 -3
View File
@@ -152,9 +152,7 @@ CurlGet::perform(CURLMsg* msg) {
else
m_signalFailed.emit(curl_easy_strerror(msg->data.result));
if (m_handle != NULL)
throw std::logic_error("CurlGet::perform finished but the object wasn't closed.");
// Do nothing below after emitting the signals.
}
}
+11 -6
View File
@@ -97,14 +97,14 @@ Download::~Download() {
void
Download::start() {
if (is_done()) {
if (is_done())
m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_seed").as_string()));
torrent::download_set_priority(m_download, 2);
} else {
else
m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_leech").as_string()));
torrent::download_set_priority(m_download, 4);
}
// Update the priority to ensure it has the correct
// seeding/unfinished modifiers.
set_priority(priority());
m_download.start();
}
@@ -128,7 +128,12 @@ Download::set_priority(uint32_t p) {
if (p >= 4)
throw torrent::input_error("Priority out of range.");
torrent::download_set_priority(m_download, p * p);
// Seeding torrents get half the priority of unfinished torrents.
if (!is_done())
torrent::download_set_priority(m_download, p * p * 2);
else
torrent::download_set_priority(m_download, p * p);
get_bencode().get_key("rtorrent").insert_key("priority", (int64_t)p);
}
+1
View File
@@ -49,6 +49,7 @@
#include "globals.h"
#include "manager.h"
#include "download.h"
#include "download_factory.h"
namespace core {
+17 -7
View File
@@ -47,6 +47,16 @@
namespace core {
struct download_list_call {
download_list_call(Download* d) : m_download(d) {}
void operator () (const DownloadList::SlotMap::value_type& s) {
s.second(m_download);
}
Download* m_download;
};
DownloadList::iterator
DownloadList::insert(std::istream* str) {
torrent::Download d = torrent::download_add(str);
@@ -54,14 +64,14 @@ DownloadList::insert(std::istream* str) {
iterator itr = Base::insert(end(), new Download(d));
(*itr)->get_download().signal_download_done(sigc::bind(sigc::mem_fun(*this, &DownloadList::finished), *itr));
m_slotMapInsert.for_each(*itr);
std::for_each(m_slotMapInsert.begin(), m_slotMapInsert.end(), download_list_call(*itr));
return itr;
}
DownloadList::iterator
DownloadList::erase(iterator itr) {
m_slotMapErase.for_each(*itr);
std::for_each(m_slotMapErase.begin(), m_slotMapErase.end(), download_list_call(*itr));
torrent::download_remove((*itr)->get_download());
delete *itr;
@@ -74,7 +84,7 @@ DownloadList::open(Download* d) {
if (d->get_download().is_open())
return;
m_slotMapOpen.for_each(d);
std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(d));
}
void
@@ -83,7 +93,7 @@ DownloadList::close(Download* d) {
return;
stop(d);
m_slotMapClose.for_each(d);
std::for_each(m_slotMapClose.begin(), m_slotMapClose.end(), download_list_call(d));
}
void
@@ -93,7 +103,7 @@ DownloadList::start(Download* d) {
return;
open(d);
m_slotMapStart.for_each(d);
std::for_each(m_slotMapStart.begin(), m_slotMapStart.end(), download_list_call(d));
}
void
@@ -101,7 +111,7 @@ DownloadList::stop(Download* d) {
if (!d->get_download().is_active())
return;
m_slotMapStop.for_each(d);
std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(d));
}
void
@@ -113,7 +123,7 @@ DownloadList::clear() {
void
DownloadList::finished(Download* d) {
m_slotMapFinished.for_each(d);
std::for_each(m_slotMapFinished.begin(), m_slotMapFinished.end(), download_list_call(d));
}
}
+19 -17
View File
@@ -39,8 +39,9 @@
#include <iosfwd>
#include <list>
#include "download_slot_map.h"
#include <map>
#include <string>
#include <sigc++/slot.h>
namespace core {
@@ -52,7 +53,8 @@ class Download;
class DownloadList : private std::list<Download*> {
public:
typedef std::list<Download*> Base;
typedef std::list<Download*> Base;
typedef std::map<std::string, sigc::slot1<void, Download*> > SlotMap;
using Base::iterator;
using Base::const_iterator;
@@ -80,28 +82,28 @@ public:
void start(Download* d);
void stop(Download* d);
DownloadSlotMap& slot_map_insert() { return m_slotMapInsert; }
DownloadSlotMap& slot_map_erase() { return m_slotMapErase; }
DownloadSlotMap& slot_map_open() { return m_slotMapOpen; }
DownloadSlotMap& slot_map_close() { return m_slotMapClose; }
DownloadSlotMap& slot_map_start() { return m_slotMapStart; }
DownloadSlotMap& slot_map_stop() { return m_slotMapStop; }
SlotMap& slot_map_insert() { return m_slotMapInsert; }
SlotMap& slot_map_erase() { return m_slotMapErase; }
SlotMap& slot_map_open() { return m_slotMapOpen; }
SlotMap& slot_map_close() { return m_slotMapClose; }
SlotMap& slot_map_start() { return m_slotMapStart; }
SlotMap& slot_map_stop() { return m_slotMapStop; }
DownloadSlotMap& slot_map_finished() { return m_slotMapFinished; }
SlotMap& slot_map_finished() { return m_slotMapFinished; }
private:
void clear();
void finished(Download* d);
DownloadSlotMap m_slotMapInsert;
DownloadSlotMap m_slotMapErase;
DownloadSlotMap m_slotMapOpen;
DownloadSlotMap m_slotMapClose;
DownloadSlotMap m_slotMapStart;
DownloadSlotMap m_slotMapStop;
SlotMap m_slotMapInsert;
SlotMap m_slotMapErase;
SlotMap m_slotMapOpen;
SlotMap m_slotMapClose;
SlotMap m_slotMapStart;
SlotMap m_slotMapStop;
DownloadSlotMap m_slotMapFinished;
SlotMap m_slotMapFinished;
};
}
+1 -1
View File
@@ -65,7 +65,7 @@ DownloadStore::enable(bool lock) {
m_lockfile.set_path(std::string());
if (!m_lockfile.try_lock())
throw torrent::input_error("Could not lock session directory: \"" + m_path + "\".");
throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", held by \"" + m_lockfile.locked_by() + "\".");
}
void
-5
View File
@@ -67,11 +67,6 @@ connect_signal_network_log(Download* d, torrent::Download::SlotString s) {
d->get_download().signal_network_log(s);
}
// static void
// connect_signal_tracker_log(Download* d, torrent::Download::SlotString s) {
// d->get_download().signal_tracker_failed(s);
// }
static void
connect_signal_storage_log(Download* d, torrent::Download::SlotString s) {
d->get_download().signal_storage_error(s);
+21 -5
View File
@@ -164,12 +164,20 @@ print_download_info(char* first, char* last, core::Download* d) {
(double)d->get_download().bytes_done() / (double)(1 << 20),
(double)d->get_download().bytes_total() / (double)(1 << 20));
first = print_buffer(first, last, " Rate: %5.1f / %5.1f KB Uploaded: %7.1f MB ",
first = print_buffer(first, last, " Rate: %5.1f / %5.1f KB Uploaded: %7.1f MB",
(double)d->get_download().up_rate()->rate() / (1 << 10),
(double)d->get_download().down_rate()->rate() / (1 << 10),
(double)d->get_download().up_rate()->total() / (1 << 20));
first = print_download_time_left(first, last, d);
if (d->get_download().is_active() && !d->is_done()) {
first = print_buffer(first, last, " ");
first = print_download_percentage_done(first, last, d);
first = print_buffer(first, last, " ");
first = print_download_time_left(first, last, d);
} else {
first = print_buffer(first, last, " ");
}
if (d->priority() != 2)
first = print_buffer(first, last, " [%s]", core::Download::priority_to_string(d->priority()));
@@ -210,10 +218,9 @@ print_download_status(char* first, char* last, core::Download* d) {
char*
print_download_time_left(char* first, char* last, core::Download* d) {
uint32_t rate;
uint32_t rate = d->get_download().down_rate()->rate();
if (!d->get_download().is_active() ||
(rate = d->get_download().down_rate()->rate()) < 512)
if (rate < 512)
return print_buffer(first, last, "--:--:--");
time_t remaining = (d->get_download().bytes_total() - d->get_download().bytes_done()) / (rate & ~(uint32_t)(512 - 1));
@@ -221,6 +228,15 @@ print_download_time_left(char* first, char* last, core::Download* d) {
return print_ddhhmm(first, last, remaining);
}
char*
print_download_percentage_done(char* first, char* last, core::Download* d) {
if (!d->is_open() || d->is_done())
//return print_buffer(first, last, "[--%%]");
return print_buffer(first, last, " ");
else
return print_buffer(first, last, "[%2u%%]", (d->get_download().chunks_done() * 100) / d->get_download().chunks_total());
}
char*
print_status_info(char* first, char* last) {
if (torrent::up_throttle() == 0)
+1
View File
@@ -66,6 +66,7 @@ char* print_download_title(char* first, char* last, core::Download* d);
char* print_download_info(char* first, char* last, core::Download* d);
char* print_download_status(char* first, char* last, core::Download* d);
char* print_download_time_left(char* first, char* last, core::Download* d);
char* print_download_percentage_done(char* first, char* last, core::Download* d);
char* print_entry_tags(char* first, char* last);
char* print_entry_file(char* first, char* last, const torrent::Entry& entry);
+3 -2
View File
@@ -83,9 +83,10 @@ WindowPeerInfo::redraw() {
m_download->variables()->get("connection_current").as_string().c_str(),
m_download->variables()->get("connection_seed").as_string().c_str(),
m_download->variables()->get("connection_leech").as_string().c_str());
m_canvas->print(0, y++, "Priority: %u", torrent::download_priority(m_download->get_download()));
m_canvas->print(0, y++, "Directory: %s", m_download->variable_string("directory").c_str());
m_canvas->print(0, y++, "Tied to file: %s", m_download->variable_string("tied_to_file").c_str());
m_canvas->print(0, y++, "Directory: %s", m_download->variable_string("directory").c_str());
m_canvas->print(0, y++, "Tied to file: %s", m_download->variable_string("tied_to_file").c_str());
y++;
-16
View File
@@ -249,22 +249,6 @@ do_panic(int signum) {
exit(-1);
}
void
receive_tracker_dump(std::istream* s) {
std::stringstream filename;
filename << "./tracker_dump." << rak::timer::current().seconds();
std::fstream out(filename.str().c_str(), std::ios::out | std::ios::trunc);
if (!out.is_open())
return;
s->seekg(0);
std::copy(std::istream_iterator<char>(*s), std::istream_iterator<char>(),
std::ostream_iterator<char>(out));
}
void
print_help() {
std::cout << "Rakshasa's BitTorrent client version " VERSION "." << std::endl;
+2 -1
View File
@@ -47,6 +47,7 @@
#include <torrent/exceptions.h>
#include <torrent/torrent.h>
#include "core/download.h"
#include "core/manager.h"
#include "ui/root.h"
#include "utils/directory.h"
@@ -159,7 +160,7 @@ initialize_option_handler(Control* c) {
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_lock", new utils::VariableAny("no"));
variables->insert("session_on_completion", new utils::VariableAny("yes"));
variables->insert("connection_leech", new utils::VariableAny("leech"));
+1 -1
View File
@@ -124,7 +124,7 @@ DownloadList::activate() {
m_control->input()->push_front(m_bindings);
m_control->core()->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()["0_download_list"] = sigc::mem_fun(this, &DownloadList::receive_download_erased);
activate_display(DISPLAY_DOWNLOAD_LIST);
}
+38 -4
View File
@@ -36,9 +36,12 @@
#include "config.h"
#include <cctype>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "lockfile.h"
@@ -47,29 +50,60 @@ namespace utils {
bool
Lockfile::try_lock() {
if (m_path.empty()) {
m_id = "foo";
m_locked = true;
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);
int fd = ::open(m_path.c_str(), O_RDWR | O_CREAT | O_EXCL, 0444);
if (fd == -1)
return false;
m_id = "foo";
char buf[256];
int pos = ::gethostname(buf, 255);
if (pos == 0) {
::snprintf(buf + std::strlen(buf), 255, ":+%i\n", ::getpid());
::write(fd, buf, std::strlen(buf));
}
::close(fd);
m_locked = true;
return true;
}
bool
Lockfile::unlock() {
m_locked = false;
if (m_path.empty())
return true;
else
return ::unlink(m_path.c_str()) != -1;
}
struct lockfile_valid_char {
bool operator () (char c) {
return !std::isgraph(c);
}
};
std::string
Lockfile::locked_by() const {
int fd = ::open(m_path.c_str(), O_RDONLY);
if (fd < 0)
return "<error>";
char buf[256];
int pos = read(fd, buf, 255);
::close(fd);
return std::string(buf, std::find_if(buf, buf + std::max(pos, 0), lockfile_valid_char()));
}
}
+11 -2
View File
@@ -34,6 +34,12 @@
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// A simple, and not guaranteed atomic, lockfile implementation. It
// saves the hostname and pid in the lock file, which may be accessed
// by Lockfile::locked_by(). If the path is an empty string then no
// lockfile will be created when Lockfile::try_lock() is called, still
// it will set the locked state of the Lockfile instance.
#ifndef RTORRENT_UTILS_LOCKFILE_H
#define RTORRENT_UTILS_LOCKFILE_H
@@ -43,8 +49,9 @@ namespace utils {
class Lockfile {
public:
Lockfile() : m_locked(false) {}
bool is_locked() const { return !m_id.empty(); }
bool is_locked() const { return m_locked; }
// If the path is empty no lock file will be created, although
// is_locked() will return true.
@@ -54,9 +61,11 @@ public:
const std::string& path() const { return m_path; }
void set_path(const std::string& path) { m_path = path; }
std::string locked_by() const;
private:
std::string m_path;
std::string m_id;
bool m_locked;
};
}