* 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:
rakshasa
2009-11-12 09:28:35 +00:00
parent a60c330d3b
commit 667c4c3562
25 changed files with 428 additions and 82 deletions
+7 -7
View File
@@ -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
View File
@@ -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
-3
View File
@@ -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;
};
+45
View File
@@ -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)
+3
View File
@@ -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&);
+12
View File
@@ -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();
}
}
+1
View File
@@ -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) {}
+12
View File
@@ -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();
}
}
+1
View File
@@ -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) {}
+24
View File
@@ -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);
}
}
+1
View File
@@ -51,6 +51,7 @@ public:
~PollManagerSelect();
void poll(rak::timer timeout);
void poll_simple(rak::timer timeout);
private:
PollManagerSelect(torrent::Poll* p);