mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-16 15:12:30 +00:00
* Created ThreadBase holding poll manager, etc, and added a this_thread global object.
* Cleaned up main initialization, SCGI and polling code. * Fixed a bug that would cause reading of a piece to hang if the incoming data contains only data up to the file boundary, but not the next file's data. The bug did not trigger if the file boundary and piece boundaries were the same. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1101 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
@@ -69,22 +69,22 @@ CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void*
|
||||
|
||||
if (socket == NULL) {
|
||||
socket = stack->new_socket(fd);
|
||||
control->poll()->open(socket);
|
||||
this_thread->poll()->open(socket);
|
||||
|
||||
// No interface for libcurl to signal when it's interested in error events.
|
||||
// Assume that hence it must always be interested in them.
|
||||
control->poll()->insert_error(socket);
|
||||
this_thread->poll()->insert_error(socket);
|
||||
}
|
||||
|
||||
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT)
|
||||
control->poll()->remove_read(socket);
|
||||
this_thread->poll()->remove_read(socket);
|
||||
else
|
||||
control->poll()->insert_read(socket);
|
||||
this_thread->poll()->insert_read(socket);
|
||||
|
||||
if (what == CURL_POLL_NONE || what == CURL_POLL_IN)
|
||||
control->poll()->remove_write(socket);
|
||||
this_thread->poll()->remove_write(socket);
|
||||
else
|
||||
control->poll()->insert_write(socket);
|
||||
this_thread->poll()->insert_write(socket);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ CurlSocket::close() {
|
||||
if (m_fileDesc == -1)
|
||||
throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1.");
|
||||
|
||||
control->poll()->closed(this);
|
||||
this_thread->poll()->closed(this);
|
||||
m_fileDesc = -1;
|
||||
}
|
||||
|
||||
|
||||
+3
-39
@@ -158,10 +158,9 @@ Manager::push_log(const char* msg) {
|
||||
}
|
||||
|
||||
Manager::Manager() :
|
||||
m_hashingView(NULL),
|
||||
|
||||
m_pollManager(NULL) {
|
||||
|
||||
m_hashingView(NULL)
|
||||
// m_pollManager(NULL) {
|
||||
{
|
||||
m_downloadStore = new DownloadStore();
|
||||
m_downloadList = new DownloadList();
|
||||
m_fileStatusCache = new FileStatusCache();
|
||||
@@ -216,40 +215,6 @@ Manager::get_address_throttle(const sockaddr* addr) {
|
||||
return m_addressThrottles.get(rak::socket_address::cast_from(addr)->sa_inet()->address_h(), torrent::ThrottlePair(NULL, NULL));
|
||||
}
|
||||
|
||||
void
|
||||
Manager::initialize_first() {
|
||||
const char* poll = getenv("RTORRENT_POLL");
|
||||
if (poll != NULL) {
|
||||
if (!strcmp(poll, "epoll"))
|
||||
m_pollManager = PollManagerEPoll::create(sysconf(_SC_OPEN_MAX));
|
||||
else if (!strcmp(poll, "kqueue"))
|
||||
m_pollManager = PollManagerKQueue::create(sysconf(_SC_OPEN_MAX));
|
||||
else if (!strcmp(poll, "select"))
|
||||
m_pollManager = PollManagerSelect::create(sysconf(_SC_OPEN_MAX));
|
||||
|
||||
if (m_pollManager == NULL)
|
||||
m_logImportant.push_front(std::string("Cannot enable '") + poll + "' based polling.");
|
||||
}
|
||||
|
||||
if (m_pollManager != NULL)
|
||||
m_logImportant.push_front(std::string("Using '") + poll + "' based polling.");
|
||||
|
||||
else if ((m_pollManager = PollManagerEPoll::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
||||
m_logImportant.push_front("Using 'epoll' based polling.");
|
||||
|
||||
else if ((m_pollManager = PollManagerKQueue::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
||||
m_logImportant.push_front("Using 'kqueue' based polling.");
|
||||
|
||||
else if ((m_pollManager = PollManagerSelect::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
||||
m_logImportant.push_front("Using 'select' based polling.");
|
||||
|
||||
else
|
||||
throw std::runtime_error("Could not create any PollManager.");
|
||||
|
||||
// Need to initialize this before parseing options.
|
||||
torrent::initialize(m_pollManager->get_torrent_poll());
|
||||
}
|
||||
|
||||
// Most of this should be possible to move out.
|
||||
void
|
||||
Manager::initialize_second() {
|
||||
@@ -276,7 +241,6 @@ Manager::cleanup() {
|
||||
delete m_httpStack;
|
||||
CurlStack::global_cleanup();
|
||||
|
||||
delete m_pollManager;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -85,7 +85,6 @@ public:
|
||||
View* hashing_view() { return m_hashingView; }
|
||||
void set_hashing_view(View* v);
|
||||
|
||||
PollManager* get_poll_manager() { return m_pollManager; }
|
||||
Log& get_log_important() { return m_logImportant; }
|
||||
Log& get_log_complete() { return m_logComplete; }
|
||||
|
||||
@@ -97,7 +96,6 @@ public:
|
||||
torrent::ThrottlePair get_address_throttle(const sockaddr* addr);
|
||||
|
||||
// Really should find a more descriptive name.
|
||||
void initialize_first();
|
||||
void initialize_second();
|
||||
void cleanup();
|
||||
|
||||
@@ -153,7 +151,6 @@ private:
|
||||
ThrottleMap m_throttles;
|
||||
AddressThrottleMap m_addressThrottles;
|
||||
|
||||
PollManager* m_pollManager;
|
||||
Log m_logImportant;
|
||||
Log m_logComplete;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,13 @@
|
||||
#include <stdexcept>
|
||||
#include <rak/error_number.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "control.h"
|
||||
#include "manager.h"
|
||||
#include "poll_manager.h"
|
||||
#include "poll_manager_epoll.h"
|
||||
#include "poll_manager_kqueue.h"
|
||||
#include "poll_manager_select.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -54,6 +60,45 @@ PollManager::~PollManager() {
|
||||
delete m_poll;
|
||||
}
|
||||
|
||||
PollManager*
|
||||
PollManager::create_poll_manager() {
|
||||
PollManager* pollManager = NULL;
|
||||
Log* log = &control->core()->get_log_important();
|
||||
|
||||
const char* poll = getenv("RTORRENT_POLL");
|
||||
|
||||
int maxOpen = sysconf(_SC_OPEN_MAX);
|
||||
|
||||
if (poll != NULL) {
|
||||
if (!strcmp(poll, "epoll"))
|
||||
pollManager = PollManagerEPoll::create(maxOpen);
|
||||
else if (!strcmp(poll, "kqueue"))
|
||||
pollManager = PollManagerKQueue::create(maxOpen);
|
||||
else if (!strcmp(poll, "select"))
|
||||
pollManager = PollManagerSelect::create(maxOpen);
|
||||
|
||||
if (pollManager == NULL)
|
||||
log->push_front(std::string("Cannot enable '") + poll + "' based polling.");
|
||||
}
|
||||
|
||||
if (pollManager != NULL)
|
||||
log->push_front(std::string("Using '") + poll + "' based polling.");
|
||||
|
||||
else if ((pollManager = PollManagerEPoll::create(maxOpen)) != NULL)
|
||||
log->push_front("Using 'epoll' based polling.");
|
||||
|
||||
else if ((pollManager = PollManagerKQueue::create(maxOpen)) != NULL)
|
||||
log->push_front("Using 'kqueue' based polling.");
|
||||
|
||||
else if ((pollManager = PollManagerSelect::create(maxOpen)) != NULL)
|
||||
log->push_front("Using 'select' based polling.");
|
||||
|
||||
else
|
||||
throw std::runtime_error("Could not create any PollManager.");
|
||||
|
||||
return pollManager;
|
||||
}
|
||||
|
||||
void
|
||||
PollManager::check_error() {
|
||||
if (rak::error_number::current().value() != rak::error_number::e_intr)
|
||||
|
||||
@@ -60,6 +60,9 @@ public:
|
||||
torrent::Poll* get_torrent_poll() { return m_poll; }
|
||||
|
||||
virtual void poll(rak::timer timeout) = 0;
|
||||
virtual void poll_simple(rak::timer timeout) = 0;
|
||||
|
||||
static PollManager* create_poll_manager();
|
||||
|
||||
protected:
|
||||
PollManager(const PollManager&);
|
||||
|
||||
@@ -74,4 +74,16 @@ PollManagerEPoll::poll(rak::timer timeout) {
|
||||
static_cast<torrent::PollEPoll*>(m_poll)->perform();
|
||||
}
|
||||
|
||||
void
|
||||
PollManagerEPoll::poll_simple(rak::timer timeout) {
|
||||
// Add 1ms to ensure we don't idle loop due to the lack of
|
||||
// resolution.
|
||||
timeout = timeout + 1000;
|
||||
|
||||
if (static_cast<torrent::PollEPoll*>(m_poll)->poll((timeout.usec() + 999) / 1000) == -1)
|
||||
return check_error();
|
||||
|
||||
static_cast<torrent::PollEPoll*>(m_poll)->perform();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
torrent::Poll* get_torrent_poll();
|
||||
|
||||
void poll(rak::timer timeout);
|
||||
void poll_simple(rak::timer timeout);
|
||||
|
||||
private:
|
||||
PollManagerEPoll(torrent::Poll* p) : PollManager(p) {}
|
||||
|
||||
@@ -75,4 +75,16 @@ PollManagerKQueue::poll(rak::timer timeout) {
|
||||
static_cast<torrent::PollKQueue*>(m_poll)->perform();
|
||||
}
|
||||
|
||||
void
|
||||
PollManagerKQueue::poll_simple(rak::timer timeout) {
|
||||
// Add 1ms to ensure we don't idle loop due to the lack of
|
||||
// resolution.
|
||||
timeout = std::min(timeout, rak::timer(torrent::next_timeout())) + 1000;
|
||||
|
||||
if (static_cast<torrent::PollKQueue*>(m_poll)->poll((timeout.usec() + 999) / 1000) == -1)
|
||||
return check_error();
|
||||
|
||||
static_cast<torrent::PollKQueue*>(m_poll)->perform();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
torrent::Poll* get_torrent_poll();
|
||||
|
||||
void poll(rak::timer timeout);
|
||||
void poll_simple(rak::timer timeout);
|
||||
|
||||
private:
|
||||
PollManagerKQueue(torrent::Poll* p) : PollManager(p) {}
|
||||
|
||||
@@ -120,4 +120,28 @@ PollManagerSelect::poll(rak::timer timeout) {
|
||||
static_cast<torrent::PollSelect*>(m_poll)->perform(m_readSet, m_writeSet, m_errorSet);
|
||||
}
|
||||
|
||||
void
|
||||
PollManagerSelect::poll_simple(rak::timer timeout) {
|
||||
timeout = timeout + 1000;
|
||||
|
||||
#if defined USE_VARIABLE_FDSET
|
||||
std::memset(m_readSet, 0, m_setSize);
|
||||
std::memset(m_writeSet, 0, m_setSize);
|
||||
std::memset(m_errorSet, 0, m_setSize);
|
||||
#else
|
||||
FD_ZERO(m_readSet);
|
||||
FD_ZERO(m_writeSet);
|
||||
FD_ZERO(m_errorSet);
|
||||
#endif
|
||||
|
||||
unsigned int maxFd = static_cast<torrent::PollSelect*>(m_poll)->fdset(m_readSet, m_writeSet, m_errorSet);
|
||||
|
||||
timeval t = timeout.tval();
|
||||
|
||||
if (select(maxFd + 1, m_readSet, m_writeSet, m_errorSet, &t) == -1)
|
||||
return check_error();
|
||||
|
||||
static_cast<torrent::PollSelect*>(m_poll)->perform(m_readSet, m_writeSet, m_errorSet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
~PollManagerSelect();
|
||||
|
||||
void poll(rak::timer timeout);
|
||||
void poll_simple(rak::timer timeout);
|
||||
|
||||
private:
|
||||
PollManagerSelect(torrent::Poll* p);
|
||||
|
||||
Reference in New Issue
Block a user