2010-04-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

In SocketCore::isReadable()/isWritable(), use poll() if it is
	available otherwise use select(). Removed epoll/port from there
	because poll() does the good enough job for single socket event
	notification.
	* src/SocketCore.cc
	* src/SocketCore.h
	* src/main.cc
pull/1/head
Tatsuhiro Tsujikawa 2010-04-24 14:08:10 +00:00
parent 5d636df361
commit 5635190927
4 changed files with 78 additions and 304 deletions

View File

@ -1,3 +1,13 @@
2010-04-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
In SocketCore::isReadable()/isWritable(), use poll() if it is
available otherwise use select(). Removed epoll/port from there
because poll() does the good enough job for single socket event
notification.
* src/SocketCore.cc
* src/SocketCore.h
* src/main.cc
2010-04-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2010-04-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added kqueue support. We use poll() for Added kqueue support. We use poll() for

View File

@ -38,9 +38,6 @@
#ifdef HAVE_IFADDRS_H #ifdef HAVE_IFADDRS_H
# include <ifaddrs.h> # include <ifaddrs.h>
#endif // HAVE_IFADDRS_H #endif // HAVE_IFADDRS_H
#ifdef HAVE_PORT_H
# include <port.h>
#endif // HAVE_PORT_H
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
@ -121,12 +118,6 @@ static const char *errorMsg()
return errorMsg(SOCKET_ERRNO); return errorMsg(SOCKET_ERRNO);
} }
#ifdef HAVE_EPOLL
SocketCore::PollMethod SocketCore::_pollMethod = SocketCore::POLL_METHOD_EPOLL;
#else // !HAVE_EPOLL
SocketCore::PollMethod SocketCore::_pollMethod = SocketCore::POLL_METHOD_SELECT;
#endif // !HAVE_EPOLL
int SocketCore::_protocolFamily = AF_UNSPEC; int SocketCore::_protocolFamily = AF_UNSPEC;
std::vector<std::pair<struct sockaddr_storage, socklen_t> > std::vector<std::pair<struct sockaddr_storage, socklen_t> >
@ -151,13 +142,6 @@ SocketCore::SocketCore(sock_t sockfd, int sockType):_sockType(sockType), sockfd(
void SocketCore::init() void SocketCore::init()
{ {
#ifdef HAVE_EPOLL
_epfd = -1;
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
_portfd = -1;
#endif // HAVE_PORT_ASSOCIATE
blocking = true; blocking = true;
secure = 0; secure = 0;
@ -178,16 +162,6 @@ void SocketCore::init()
SocketCore::~SocketCore() { SocketCore::~SocketCore() {
closeConnection(); closeConnection();
#ifdef HAVE_EPOLL
if(_epfd != -1) {
CLOSE(_epfd);
}
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
if(_portfd != -1) {
CLOSE(_portfd);
}
#endif // HAVE_PORT_ASSOCIATE
#ifdef HAVE_LIBGNUTLS #ifdef HAVE_LIBGNUTLS
delete [] peekBuf; delete [] peekBuf;
#endif // HAVE_LIBGNUTLS #endif // HAVE_LIBGNUTLS
@ -572,119 +546,47 @@ void SocketCore::closeConnection()
#endif // HAVE_LIBGNUTLS #endif // HAVE_LIBGNUTLS
} }
#ifdef HAVE_EPOLL
void SocketCore::initEPOLL()
{
if((_epfd = epoll_create(1)) == -1) {
throw DL_RETRY_EX(StringFormat("epoll_create failed:%s", errorMsg()).str());
}
memset(&_epEvent, 0, sizeof(struct epoll_event));
_epEvent.events = EPOLLIN|EPOLLOUT;
_epEvent.data.fd = sockfd;
if(epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &_epEvent) == -1) {
throw DL_RETRY_EX(StringFormat("epoll_ctl failed:%s", errorMsg()).str());
}
}
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
void SocketCore::initPort()
{
if((_portfd = port_create()) == -1) {
throw DL_RETRY_EX(StringFormat("port_create failed:%s", errorMsg()).str());
}
if(port_associate(_portfd, PORT_SOURCE_FD, sockfd, POLLIN|POLLOUT, 0) == -1) {
throw DL_RETRY_EX
(StringFormat("port_associate failed:%s", errorMsg()).str());
}
}
#endif // HAVE_PORT_ASSOCIATE
bool SocketCore::isWritable(time_t timeout) bool SocketCore::isWritable(time_t timeout)
{ {
#ifdef HAVE_EPOLL #ifdef HAVE_POLL
if(_pollMethod == SocketCore::POLL_METHOD_EPOLL) { struct pollfd p;
if(_epfd == -1) { p.fd = sockfd;
initEPOLL(); p.events = POLLOUT;
} int r;
struct epoll_event epEvents[1]; while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR);
int r; if(r > 0) {
while((r = epoll_wait(_epfd, epEvents, 1, timeout*1000)) == -1 && return p.revents&(POLLOUT|POLLHUP|POLLERR);
errno == EINTR); } else if(r == 0) {
if(r > 0) { return false;
return epEvents[0].events&(EPOLLOUT|EPOLLHUP|EPOLLERR); } else {
} else if(r == 0) { throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str());
}
#else // !HAVE_POLL
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
struct timeval tv;
tv.tv_sec = timeout;
tv.tv_usec = 0;
int r = select(sockfd+1, NULL, &fds, NULL, &tv);
if(r == 1) {
return true;
} else if(r == 0) {
// time out
return false;
} else {
if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) {
return false; return false;
} else { } else {
throw DL_RETRY_EX(StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str()); throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str());
} }
} else }
#endif // HAVE_EPOLL #endif // !HAVE_POLL
#ifdef HAVE_PORT_ASSOCIATE
if(_pollMethod == SocketCore::POLL_METHOD_PORT) {
if(_portfd == -1) {
initPort();
}
struct timespec ts = { timeout, 0 };
port_event_t portEvent;
int r = port_get(_portfd, &portEvent, &ts);
if(r == 0) {
return portEvent.portev_events&(POLLOUT|POLLHUP|POLLERR);
} else if(r == -1 && (errno == ETIME || errno == EINTR)) {
return false;
} else {
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str());
}
} else
#endif // HAVE_PORT_ASSOCIATE
#ifdef HAVE_POLL
if(_pollMethod == SocketCore::POLL_METHOD_POLL) {
struct pollfd p;
p.fd = sockfd;
p.events = POLLOUT;
int r;
while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR);
if(r > 0) {
return p.revents&(POLLOUT|POLLHUP|POLLERR);
} else if(r == 0) {
return false;
} else {
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str());
}
} else
#endif // HAVE_POLL
if(_pollMethod == SocketCore::POLL_METHOD_SELECT) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
struct timeval tv;
tv.tv_sec = timeout;
tv.tv_usec = 0;
int r = select(sockfd+1, NULL, &fds, NULL, &tv);
if(r == 1) {
return true;
} else if(r == 0) {
// time out
return false;
} else {
if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) {
return false;
} else {
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str());
}
}
} else {
abort();
}
} }
bool SocketCore::isReadable(time_t timeout) bool SocketCore::isReadable(time_t timeout)
@ -694,87 +596,44 @@ bool SocketCore::isReadable(time_t timeout)
return true; return true;
} }
#endif // HAVE_LIBGNUTLS #endif // HAVE_LIBGNUTLS
#ifdef HAVE_POLL
struct pollfd p;
p.fd = sockfd;
p.events = POLLIN;
int r;
while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR);
if(r > 0) {
return p.revents&(POLLIN|POLLHUP|POLLERR);
} else if(r == 0) {
return false;
} else {
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
}
#else // !HAVE_POLL
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
#ifdef HAVE_EPOLL struct timeval tv;
if(_pollMethod == SocketCore::POLL_METHOD_EPOLL) { tv.tv_sec = timeout;
if(_epfd == -1) { tv.tv_usec = 0;
initEPOLL();
}
struct epoll_event epEvents[1];
int r;
while((r = epoll_wait(_epfd, epEvents, 1, timeout*1000)) == -1 &&
errno == EINTR);
if(r > 0) { int r = select(sockfd+1, &fds, NULL, NULL, &tv);
return epEvents[0].events&(EPOLLIN|EPOLLHUP|EPOLLERR); if(r == 1) {
} else if(r == 0) { return true;
} else if(r == 0) {
// time out
return false;
} else {
if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) {
return false; return false;
} else { } else {
throw DL_RETRY_EX(StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str()); throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
} }
} else }
#endif // HAVE_EPOLL #endif // !HAVE_POLL
#ifdef HAVE_PORT_ASSOCIATE
if(_pollMethod == SocketCore::POLL_METHOD_PORT) {
if(_portfd == -1) {
initPort();
}
struct timespec ts = { timeout, 0 };
port_event_t portEvent;
int r = port_get(_portfd, &portEvent, &ts);
if(r == 0) {
return portEvent.portev_events&(POLLIN|POLLHUP|POLLERR);
} else if(r == -1 && (errno == ETIME || errno == EINTR)) {
return false;
} else {
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
}
} else
#endif // HAVE_PORT_ASSOCIATE
#ifdef HAVE_POLL
if(_pollMethod == SocketCore::POLL_METHOD_POLL) {
struct pollfd p;
p.fd = sockfd;
p.events = POLLIN;
int r;
while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR);
if(r > 0) {
return p.revents&(POLLIN|POLLHUP|POLLERR);
} else if(r == 0) {
return false;
} else {
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
}
} else
#endif // HAVE_POLL
if(_pollMethod == SocketCore::POLL_METHOD_SELECT) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
struct timeval tv;
tv.tv_sec = timeout;
tv.tv_usec = 0;
int r = select(sockfd+1, &fds, NULL, NULL, &tv);
if(r == 1) {
return true;
} else if(r == 0) {
// time out
return false;
} else {
if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) {
return false;
} else {
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
}
}
} else {
abort();
}
} }
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
@ -1320,32 +1179,6 @@ bool SocketCore::wantWrite() const
return _wantWrite; return _wantWrite;
} }
#ifdef HAVE_EPOLL
void SocketCore::useEpoll()
{
_pollMethod = SocketCore::POLL_METHOD_EPOLL;
}
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
void SocketCore::usePort()
{
_pollMethod = SocketCore::POLL_METHOD_PORT;
}
#endif // HAVE_PORT_ASSOCIATE
#ifdef HAVE_POLL
void SocketCore::usePoll()
{
_pollMethod = SocketCore::POLL_METHOD_POLL;
}
#endif // HAVE_POLL
void SocketCore::useSelect()
{
_pollMethod = SocketCore::POLL_METHOD_SELECT;
}
void SocketCore::bindAddress(const std::string& iface) void SocketCore::bindAddress(const std::string& iface)
{ {
std::vector<std::pair<struct sockaddr_storage, socklen_t> > bindAddrs; std::vector<std::pair<struct sockaddr_storage, socklen_t> > bindAddrs;

View File

@ -37,10 +37,6 @@
#include "common.h" #include "common.h"
#ifdef HAVE_EPOLL
# include <sys/epoll.h>
#endif // HAVE_EPOLL
#include <string> #include <string>
#include <cstdlib> #include <cstdlib>
#include <utility> #include <utility>
@ -78,28 +74,6 @@ private:
// socket endpoint descriptor // socket endpoint descriptor
sock_t sockfd; sock_t sockfd;
#ifdef HAVE_EPOLL
// file descriptor used for epoll
int _epfd;
struct epoll_event _epEvent;
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
int _portfd;
#endif // HAVE_PORT_ASSOCIATE
enum PollMethod {
POLL_METHOD_EPOLL,
POLL_METHOD_PORT,
POLL_METHOD_POLL,
POLL_METHOD_SELECT
};
static PollMethod _pollMethod;
static int _protocolFamily; static int _protocolFamily;
static std::vector<std::pair<struct sockaddr_storage, socklen_t> > _bindAddrs; static std::vector<std::pair<struct sockaddr_storage, socklen_t> > _bindAddrs;
@ -138,13 +112,6 @@ private:
void bind(const struct sockaddr* addr, socklen_t addrlen); void bind(const struct sockaddr* addr, socklen_t addrlen);
#ifdef HAVE_EPOLL
void initEPOLL();
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
void initPort();
#endif // HAVE_PORT_ASSOCIATE
void setSockOpt(int level, int optname, void* optval, socklen_t optlen); void setSockOpt(int level, int optname, void* optval, socklen_t optlen);
SocketCore(sock_t sockfd, int sockType); SocketCore(sock_t sockfd, int sockType);
@ -365,17 +332,6 @@ public:
*/ */
bool wantWrite() const; bool wantWrite() const;
#ifdef HAVE_EPOLL
static void useEpoll();
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
static void usePort();
#endif // HAVE_PORT_ASSOCIATE
#ifdef HAVE_POLL
static void usePoll();
#endif // HAVE_POLL
static void useSelect();
#ifdef ENABLE_SSL #ifdef ENABLE_SSL
static void setTLSContext(const SharedHandle<TLSContext>& tlsContext); static void setTLSContext(const SharedHandle<TLSContext>& tlsContext);
#endif // ENABLE_SSL #endif // ENABLE_SSL

View File

@ -186,32 +186,7 @@ downloadresultcode::RESULT main(int argc, char* argv[])
if(op->getAsBool(PREF_QUIET)) { if(op->getAsBool(PREF_QUIET)) {
LogFactory::setConsoleOutput(false); LogFactory::setConsoleOutput(false);
} }
const std::string& pollMethod = op->get(PREF_EVENT_POLL);
#ifdef HAVE_EPOLL
if(pollMethod == V_EPOLL) {
SocketCore::useEpoll();
} else
#endif // HAVE_EPOLL
#ifdef HAVE_KQUEUE
if(pollMethod == V_KQUEUE) {
SocketCore::usePoll();
} else
#endif // HAVE_KQUEUE
#ifdef HAVE_PORT_ASSOCIATE
if(pollMethod == V_PORT) {
SocketCore::usePort();
} else
#endif // HAVE_PORT_ASSOCIATE
#ifdef HAVE_POLL
if(pollMethod == V_POLL) {
SocketCore::usePoll();
} else
#endif // HAVE_POLL
if(pollMethod == V_SELECT) {
SocketCore::useSelect();
}
downloadresultcode::RESULT exitStatus = downloadresultcode::FINISHED; downloadresultcode::RESULT exitStatus = downloadresultcode::FINISHED;
Logger* logger = LogFactory::getInstance(); Logger* logger = LogFactory::getInstance();
logger->info("<<--- --- --- ---"); logger->info("<<--- --- --- ---");
logger->info(" --- --- --- ---"); logger->info(" --- --- --- ---");