* 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:
rakshasa
2005-08-01 16:20:34 +00:00
parent 00e0da7aa5
commit 89a090111d
14 changed files with 109 additions and 103 deletions
+12 -13
View File
@@ -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
View File
@@ -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);
+18 -5
View File
@@ -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;
+7 -9
View File
@@ -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;
+14 -19
View File
@@ -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();
}
+1 -3
View File
@@ -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) {}
};
}
+11 -16
View File
@@ -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();
}
+1 -5
View File
@@ -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) {}
};
}