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>
Added kqueue support. We use poll() for

View File

@ -38,9 +38,6 @@
#ifdef HAVE_IFADDRS_H
# include <ifaddrs.h>
#endif // HAVE_IFADDRS_H
#ifdef HAVE_PORT_H
# include <port.h>
#endif // HAVE_PORT_H
#include <cerrno>
#include <cstring>
@ -121,12 +118,6 @@ static const char *errorMsg()
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;
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()
{
#ifdef HAVE_EPOLL
_epfd = -1;
#endif // HAVE_EPOLL
#ifdef HAVE_PORT_ASSOCIATE
_portfd = -1;
#endif // HAVE_PORT_ASSOCIATE
blocking = true;
secure = 0;
@ -178,16 +162,6 @@ void SocketCore::init()
SocketCore::~SocketCore() {
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
delete [] peekBuf;
#endif // HAVE_LIBGNUTLS
@ -572,119 +546,47 @@ void SocketCore::closeConnection()
#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)
{
#ifdef HAVE_EPOLL
if(_pollMethod == SocketCore::POLL_METHOD_EPOLL) {
if(_epfd == -1) {
initEPOLL();
}
struct epoll_event epEvents[1];
int r;
while((r = epoll_wait(_epfd, epEvents, 1, timeout*1000)) == -1 &&
errno == EINTR);
if(r > 0) {
return epEvents[0].events&(EPOLLOUT|EPOLLHUP|EPOLLERR);
} else if(r == 0) {
#ifdef HAVE_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 // !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;
} 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
#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();
}
}
#endif // !HAVE_POLL
}
bool SocketCore::isReadable(time_t timeout)
@ -694,87 +596,44 @@ bool SocketCore::isReadable(time_t timeout)
return true;
}
#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
if(_pollMethod == SocketCore::POLL_METHOD_EPOLL) {
if(_epfd == -1) {
initEPOLL();
}
struct epoll_event epEvents[1];
int r;
while((r = epoll_wait(_epfd, epEvents, 1, timeout*1000)) == -1 &&
errno == EINTR);
struct timeval tv;
tv.tv_sec = timeout;
tv.tv_usec = 0;
if(r > 0) {
return epEvents[0].events&(EPOLLIN|EPOLLHUP|EPOLLERR);
} else if(r == 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());
throw DL_RETRY_EX
(StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
}
} else
#endif // HAVE_EPOLL
#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();
}
}
#endif // !HAVE_POLL
}
#ifdef HAVE_LIBSSL
@ -1320,32 +1179,6 @@ bool SocketCore::wantWrite() const
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)
{
std::vector<std::pair<struct sockaddr_storage, socklen_t> > bindAddrs;

View File

@ -37,10 +37,6 @@
#include "common.h"
#ifdef HAVE_EPOLL
# include <sys/epoll.h>
#endif // HAVE_EPOLL
#include <string>
#include <cstdlib>
#include <utility>
@ -78,28 +74,6 @@ private:
// socket endpoint descriptor
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 std::vector<std::pair<struct sockaddr_storage, socklen_t> > _bindAddrs;
@ -138,13 +112,6 @@ private:
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);
SocketCore(sock_t sockfd, int sockType);
@ -365,17 +332,6 @@ public:
*/
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
static void setTLSContext(const SharedHandle<TLSContext>& tlsContext);
#endif // ENABLE_SSL

View File

@ -186,32 +186,7 @@ downloadresultcode::RESULT main(int argc, char* argv[])
if(op->getAsBool(PREF_QUIET)) {
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;
Logger* logger = LogFactory::getInstance();
logger->info("<<--- --- --- ---");
logger->info(" --- --- --- ---");