mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-09 07:39:21 +00:00
* Added support for variable sized fd_set's, this should remove the FD_SETSIZE limit.
git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@512 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
+12
-13
@@ -67,42 +67,39 @@ connect_signal_tracker_log(Download* d, torrent::Download::SlotString s) {
|
||||
}
|
||||
|
||||
Manager::Manager() :
|
||||
m_pollManager(NULL),
|
||||
m_portRandom(false),
|
||||
m_portFirst(6890),
|
||||
m_portLast(6999),
|
||||
m_checkHash(true) {
|
||||
}
|
||||
|
||||
// Consider doing this somewhere else.
|
||||
void
|
||||
Manager::initialize_first() {
|
||||
if ((m_pollManager = PollManagerEPoll::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
||||
m_logImportant.push_front("Using 'epoll' 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");
|
||||
}
|
||||
|
||||
Manager::~Manager() {
|
||||
delete m_pollManager;
|
||||
// Need to initialize this before parseing options.
|
||||
torrent::initialize(m_pollManager->get_torrent_poll());
|
||||
}
|
||||
|
||||
void
|
||||
Manager::initialize() {
|
||||
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());
|
||||
|
||||
CurlStack::global_init();
|
||||
listen_open();
|
||||
|
||||
if (torrent::get_max_open_files() + torrent::get_max_open_sockets() + 32 > FD_SETSIZE) {
|
||||
m_logImportant.push_front("Warning: Max open sockets and files exceeds FD_SETSIZE");
|
||||
m_logComplete.push_front("Warning: Max open sockets and files exceeds FD_SETSIZE");
|
||||
if (torrent::get_max_open_files() + torrent::get_max_open_sockets() + 32 > m_pollManager->max_open_sockets()) {
|
||||
m_logImportant.push_front("Warning: Max open sockets and files exceeds poll manager's max open sockets");
|
||||
m_logComplete.push_front("Warning: Max open sockets and files exceeds poll manager's max open sockets");
|
||||
}
|
||||
|
||||
if (torrent::get_max_open_files() + torrent::get_max_open_sockets() + 32 > (unsigned int)sysconf(_SC_OPEN_MAX)) {
|
||||
m_logImportant.push_front("Warning: Max open sockets and files exceeds _SC_OPEN_MAX");
|
||||
m_logComplete.push_front("Warning: Max open sockets and files exceeds _SC_OPEN_MAX");
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -137,6 +134,8 @@ Manager::cleanup() {
|
||||
|
||||
torrent::cleanup();
|
||||
CurlStack::global_cleanup();
|
||||
|
||||
delete m_pollManager;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+3
-2
@@ -59,7 +59,6 @@ public:
|
||||
typedef sigc::slot0<void> SlotFailed;
|
||||
|
||||
Manager();
|
||||
~Manager();
|
||||
|
||||
DownloadList& get_download_list() { return m_downloadList; }
|
||||
DownloadStore& get_download_store() { return m_downloadStore; }
|
||||
@@ -75,7 +74,9 @@ public:
|
||||
|
||||
void set_check_hash(bool state) { m_checkHash = state; }
|
||||
|
||||
void initialize();
|
||||
// Really should find a more descriptive name.
|
||||
void initialize_first();
|
||||
void initialize_second();
|
||||
void cleanup();
|
||||
|
||||
void shutdown(bool force);
|
||||
|
||||
@@ -43,17 +43,30 @@
|
||||
|
||||
namespace core {
|
||||
|
||||
PollManager::PollManager(int maxOpenSockets) {
|
||||
// Add a hack here to create larger fd_set's, depending on a USE
|
||||
// flag.
|
||||
|
||||
m_maxOpenSockets = maxOpenSockets;
|
||||
PollManager::PollManager(torrent::Poll* poll) :
|
||||
m_poll(poll) {
|
||||
|
||||
if (m_poll == NULL)
|
||||
throw std::logic_error("PollManager::PollManager(...) received poll == NULL");
|
||||
|
||||
#if defined USE_VARIABLE_FDSET
|
||||
m_setSize = m_poll->max_open_sockets() / 8;
|
||||
m_readSet = (fd_set*)new char[m_setSize];
|
||||
m_writeSet = (fd_set*)new char[m_setSize];
|
||||
m_errorSet = (fd_set*)new char[m_setSize];
|
||||
#else
|
||||
if (m_poll->max_open_sockets() > FD_SETSIZE)
|
||||
throw std::logic_error("PollManager::PollManager(...) received a max open sockets >= FD_SETSIZE, but USE_VARIABLE_FDSET was not defined");
|
||||
|
||||
m_setSize = FD_SETSIZE / 8;
|
||||
m_readSet = new fd_set;
|
||||
m_writeSet = new fd_set;
|
||||
m_errorSet = new fd_set;
|
||||
#endif
|
||||
}
|
||||
|
||||
PollManager::~PollManager() {
|
||||
delete m_poll;
|
||||
delete m_readSet;
|
||||
delete m_writeSet;
|
||||
delete m_errorSet;
|
||||
|
||||
@@ -39,14 +39,11 @@
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sigc++/signal.h>
|
||||
#include <torrent/poll.h>
|
||||
|
||||
#include "curl_stack.h"
|
||||
#include "utils/timer.h"
|
||||
|
||||
namespace torrent {
|
||||
class Poll;
|
||||
}
|
||||
|
||||
namespace core {
|
||||
|
||||
// CurlStack really should be somewhere else, but that won't happen
|
||||
@@ -56,13 +53,13 @@ class PollManager {
|
||||
public:
|
||||
typedef sigc::signal0<void> Signal;
|
||||
|
||||
PollManager(int maxOpenSockets);
|
||||
PollManager(torrent::Poll* poll);
|
||||
virtual ~PollManager();
|
||||
|
||||
unsigned int get_max_open_sockets() const { return m_maxOpenSockets; }
|
||||
CurlStack* get_http_stack() { return &m_httpStack; }
|
||||
unsigned int max_open_sockets() const { return m_poll->max_open_sockets(); }
|
||||
|
||||
virtual torrent::Poll* get_torrent_poll() = 0;
|
||||
CurlStack* get_http_stack() { return &m_httpStack; }
|
||||
torrent::Poll* get_torrent_poll() { return m_poll; }
|
||||
|
||||
virtual void poll(utils::Timer timeout) = 0;
|
||||
|
||||
@@ -75,9 +72,10 @@ protected:
|
||||
|
||||
void check_error();
|
||||
|
||||
unsigned int m_maxOpenSockets;
|
||||
torrent::Poll* m_poll;
|
||||
CurlStack m_httpStack;
|
||||
|
||||
unsigned int m_setSize;
|
||||
fd_set* m_readSet;
|
||||
fd_set* m_writeSet;
|
||||
fd_set* m_errorSet;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <torrent/poll_epoll.h>
|
||||
#include <torrent/torrent.h>
|
||||
@@ -50,20 +51,11 @@ PollManagerEPoll::create(int maxOpenSockets) {
|
||||
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
PollManagerEPoll* manager = new PollManagerEPoll(maxOpenSockets);
|
||||
manager->m_poll = p;
|
||||
|
||||
return manager;
|
||||
else
|
||||
return new PollManagerEPoll(p);
|
||||
}
|
||||
|
||||
PollManagerEPoll::~PollManagerEPoll() {
|
||||
delete m_poll;
|
||||
}
|
||||
|
||||
torrent::Poll*
|
||||
PollManagerEPoll::get_torrent_poll() {
|
||||
return m_poll;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -73,17 +65,20 @@ PollManagerEPoll::poll(utils::Timer timeout) {
|
||||
if (m_httpStack.is_busy()) {
|
||||
// When we're using libcurl we need to use select, but as this is
|
||||
// inefficient we try avoiding it whenever possible.
|
||||
#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);
|
||||
FD_SET(m_poll->get_fd(), m_readSet);
|
||||
#endif
|
||||
FD_SET(static_cast<torrent::PollEPoll*>(m_poll)->get_fd(), m_readSet);
|
||||
|
||||
unsigned int maxFd = std::max((unsigned int)m_poll->get_fd(),
|
||||
unsigned int maxFd = std::max((unsigned int)static_cast<torrent::PollEPoll*>(m_poll)->get_fd(),
|
||||
m_httpStack.fdset(m_readSet, m_writeSet, m_errorSet));
|
||||
|
||||
if (maxFd >= m_maxOpenSockets)
|
||||
throw std::runtime_error("Error polling, maxFd >= m_maxOpenSockets");
|
||||
|
||||
timeval t = timeout.tval();
|
||||
|
||||
if (select(maxFd + 1, m_readSet, m_writeSet, m_errorSet, &t) == -1)
|
||||
@@ -91,7 +86,7 @@ PollManagerEPoll::poll(utils::Timer timeout) {
|
||||
|
||||
m_httpStack.perform();
|
||||
|
||||
if (!FD_ISSET(m_poll->get_fd(), m_readSet))
|
||||
if (!FD_ISSET(static_cast<torrent::PollEPoll*>(m_poll)->get_fd(), m_readSet))
|
||||
return;
|
||||
|
||||
// Clear the timeout since we've already used it in the select call.
|
||||
@@ -102,10 +97,10 @@ PollManagerEPoll::poll(utils::Timer timeout) {
|
||||
// function. ;)
|
||||
torrent::perform();
|
||||
|
||||
if (m_poll->poll(timeout.usec() / 1000) == -1)
|
||||
if (static_cast<torrent::PollEPoll*>(m_poll)->poll(timeout.usec() / 1000) == -1)
|
||||
return check_error();
|
||||
|
||||
m_poll->perform();
|
||||
static_cast<torrent::PollEPoll*>(m_poll)->perform();
|
||||
torrent::perform();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,7 @@ public:
|
||||
void poll(utils::Timer timeout);
|
||||
|
||||
private:
|
||||
PollManagerEPoll(int maxOpenSockets) : PollManager(maxOpenSockets) {}
|
||||
|
||||
torrent::PollEPoll* m_poll;
|
||||
PollManagerEPoll(torrent::Poll* p) : PollManager(p) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <torrent/poll_select.h>
|
||||
#include <torrent/torrent.h>
|
||||
@@ -50,38 +51,32 @@ PollManagerSelect::create(int maxOpenSockets) {
|
||||
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
PollManagerSelect* manager = new PollManagerSelect(maxOpenSockets);
|
||||
manager->m_poll = p;
|
||||
|
||||
return manager;
|
||||
else
|
||||
return new PollManagerSelect(p);
|
||||
}
|
||||
|
||||
PollManagerSelect::~PollManagerSelect() {
|
||||
delete m_poll;
|
||||
}
|
||||
|
||||
torrent::Poll*
|
||||
PollManagerSelect::get_torrent_poll() {
|
||||
return m_poll;
|
||||
}
|
||||
|
||||
void
|
||||
PollManagerSelect::poll(utils::Timer timeout) {
|
||||
timeout = std::min(timeout, utils::Timer(torrent::get_next_timeout()));
|
||||
|
||||
#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 = m_poll->fdset(m_readSet, m_writeSet, m_errorSet);
|
||||
unsigned int maxFd = static_cast<torrent::PollSelect*>(m_poll)->fdset(m_readSet, m_writeSet, m_errorSet);
|
||||
|
||||
if (m_httpStack.is_busy())
|
||||
maxFd = std::max(maxFd, m_httpStack.fdset(m_readSet, m_writeSet, m_errorSet));
|
||||
|
||||
if (maxFd >= m_maxOpenSockets)
|
||||
throw std::runtime_error("Error polling, maxFd >= m_maxOpenSockets");
|
||||
|
||||
timeval t = timeout.tval();
|
||||
|
||||
if (select(maxFd + 1, m_readSet, m_writeSet, m_errorSet, &t) == -1)
|
||||
@@ -91,7 +86,7 @@ PollManagerSelect::poll(utils::Timer timeout) {
|
||||
m_httpStack.perform();
|
||||
|
||||
torrent::perform();
|
||||
m_poll->perform(m_readSet, m_writeSet, m_errorSet);
|
||||
static_cast<torrent::PollSelect*>(m_poll)->perform(m_readSet, m_writeSet, m_errorSet);
|
||||
torrent::perform();
|
||||
}
|
||||
|
||||
|
||||
@@ -50,14 +50,10 @@ public:
|
||||
static PollManagerSelect* create(int maxOpenSockets);
|
||||
~PollManagerSelect();
|
||||
|
||||
torrent::Poll* get_torrent_poll();
|
||||
|
||||
void poll(utils::Timer timeout);
|
||||
|
||||
private:
|
||||
PollManagerSelect(int maxOpenSockets) : PollManager(maxOpenSockets) {}
|
||||
|
||||
torrent::PollSelect* m_poll;
|
||||
PollManagerSelect(torrent::Poll* p) : PollManager(p) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user