From 5d636df36192101573feae11f6097022c7adf7ed Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 24 Apr 2010 13:07:35 +0000 Subject: [PATCH] 2010-04-24 Tatsuhiro Tsujikawa Added kqueue support. We use poll() for SocketCore::isReadable()/isWritable() when kqueue is used. * configure.ac * src/DownloadEngineFactory.cc * src/KqueueEventPoll.cc * src/KqueueEventPoll.h * src/Makefile.am * src/Makefile.in * src/OptionHandlerFactory.cc * src/main.cc * src/prefs.cc * src/prefs.h --- ChangeLog | 15 ++ config.h.in | 6 + configure | 61 ++++++++ configure.ac | 20 +++ src/DownloadEngineFactory.cc | 42 +++-- src/KqueueEventPoll.cc | 294 +++++++++++++++++++++++++++++++++++ src/KqueueEventPoll.h | 134 ++++++++++++++++ src/Makefile.am | 4 + src/Makefile.in | 13 +- src/OptionHandlerFactory.cc | 5 + src/main.cc | 5 + src/prefs.cc | 1 + src/prefs.h | 1 + 13 files changed, 582 insertions(+), 19 deletions(-) create mode 100644 src/KqueueEventPoll.cc create mode 100644 src/KqueueEventPoll.h diff --git a/ChangeLog b/ChangeLog index 87d5c843..6d41af7d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2010-04-24 Tatsuhiro Tsujikawa + + Added kqueue support. We use poll() for + SocketCore::isReadable()/isWritable() when kqueue is used. + * configure.ac + * src/DownloadEngineFactory.cc + * src/KqueueEventPoll.cc + * src/KqueueEventPoll.h + * src/Makefile.am + * src/Makefile.in + * src/OptionHandlerFactory.cc + * src/main.cc + * src/prefs.cc + * src/prefs.h + 2010-04-23 Tatsuhiro Tsujikawa Added missing timespec.h to SRCS diff --git a/config.h.in b/config.h.in index 82492948..e9689bbc 100644 --- a/config.h.in +++ b/config.h.in @@ -205,6 +205,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_IO_H +/* Define to 1 if you have the `kqueue' function. */ +#undef HAVE_KQUEUE + /* Define if you have and nl_langinfo(CODESET). */ #undef HAVE_LANGINFO_CODESET @@ -557,6 +560,9 @@ /* Define if integer division by zero raises signal SIGFPE. */ #undef INTDIV0_RAISES_SIGFPE +/* Define to 1 if struct kevent.udata is intptr_t */ +#undef KEVENT_UDATA_INTPTR_T + /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #undef LSTAT_FOLLOWS_SLASHED_SYMLINK diff --git a/configure b/configure index 10b5591b..0c7b772e 100755 --- a/configure +++ b/configure @@ -600,6 +600,8 @@ ac_func_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS +HAVE_KQUEUE_FALSE +HAVE_KQUEUE_TRUE HAVE_PORT_ASSOCIATE_FALSE HAVE_PORT_ASSOCIATE_TRUE HAVE_TIMEGETTIME_FALSE @@ -15171,6 +15173,61 @@ else fi +for ac_func in kqueue +do : + ac_fn_cxx_check_func "$LINENO" "kqueue" "ac_cv_func_kqueue" +if test "x$ac_cv_func_kqueue" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_KQUEUE 1 +_ACEOF + have_kqueue=yes +fi +done + + if test "x$have_kqueue" = "xyes"; then + HAVE_KQUEUE_TRUE= + HAVE_KQUEUE_FALSE='#' +else + HAVE_KQUEUE_TRUE='#' + HAVE_KQUEUE_FALSE= +fi + +if test "x$have_kqueue" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct kevent.udata is intptr_t" >&5 +$as_echo_n "checking whether struct kevent.udata is intptr_t... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + +struct kevent event; +event.udata = reinterpret_cast(&event); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + kevent_udata_intptr_t=yes +else + kevent_udata_intptr_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $kevent_udata_intptr_t" >&5 +$as_echo "$kevent_udata_intptr_t" >&6; } + if test "x$kevent_udata_intptr_t" = "xyes"; then + +$as_echo "#define KEVENT_UDATA_INTPTR_T 1" >>confdefs.h + + fi +fi + ac_fn_cxx_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" "#include " if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = x""yes; then : @@ -15525,6 +15582,10 @@ if test -z "${HAVE_PORT_ASSOCIATE_TRUE}" && test -z "${HAVE_PORT_ASSOCIATE_FALSE as_fn_error "conditional \"HAVE_PORT_ASSOCIATE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HAVE_KQUEUE_TRUE}" && test -z "${HAVE_KQUEUE_FALSE}"; then + as_fn_error "conditional \"HAVE_KQUEUE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : ${CONFIG_STATUS=./config.status} ac_write_fail=0 diff --git a/configure.ac b/configure.ac index e564100b..96a61de2 100644 --- a/configure.ac +++ b/configure.ac @@ -417,6 +417,26 @@ esac AC_CHECK_FUNCS([port_associate], [have_port_associate=yes]) AM_CONDITIONAL([HAVE_PORT_ASSOCIATE], [test "x$have_port_associate" = "xyes"]) +AC_CHECK_FUNCS([kqueue], [have_kqueue=yes]) +AM_CONDITIONAL([HAVE_KQUEUE], [test "x$have_kqueue" = "xyes"]) +if test "x$have_kqueue" = "xyes"; then + AC_MSG_CHECKING([whether struct kevent.udata is intptr_t]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include +]], +[[ +struct kevent event; +event.udata = reinterpret_cast(&event); +]])], + [kevent_udata_intptr_t=yes], [kevent_udata_intptr_t=no]) + AC_MSG_RESULT([$kevent_udata_intptr_t]) + if test "x$kevent_udata_intptr_t" = "xyes"; then + AC_DEFINE([KEVENT_UDATA_INTPTR_T], [1], [Define to 1 if struct kevent.udata is intptr_t]) + fi +fi + AC_CHECK_MEMBER([struct sockaddr_in.sin_len], [AC_DEFINE([HAVE_SOCKADDR_IN_SIN_LEN],[1], [Define to 1 if struct sockaddr_in has sin_len member.])], diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc index dd75aa78..a623b2aa 100644 --- a/src/DownloadEngineFactory.cc +++ b/src/DownloadEngineFactory.cc @@ -64,6 +64,9 @@ #ifdef HAVE_PORT_ASSOCIATE # include "PortEventPoll.h" #endif // HAVE_PORT_ASSOCIATE +#ifdef HAVE_KQUEUE +# include "KqueueEventPoll.h" +#endif // HAVE_KQUEUE #include "PollEventPoll.h" #include "SelectEventPoll.h" #include "DlAbortEx.h" @@ -96,27 +99,38 @@ DownloadEngineFactory::newDownloadEngine } } else #endif // HAVE_EPLL -#ifdef HAVE_PORT_ASSOCIATE - if(pollMethod == V_PORT) { - SharedHandle pp(new PortEventPoll()); - if(pp->good()) { - eventPoll = pp; +#ifdef HAVE_KQUEUE + if(pollMethod == V_KQUEUE) { + SharedHandle kp(new KqueueEventPoll()); + if(kp->good()) { + eventPoll = kp; } else { - throw DL_ABORT_EX("Initializing PortEventPoll failed." + throw DL_ABORT_EX("Initializing KqueueEventPoll failed." " Try --event-poll=select"); } } else +#endif // HAVE_KQUEUE +#ifdef HAVE_PORT_ASSOCIATE + if(pollMethod == V_PORT) { + SharedHandle pp(new PortEventPoll()); + if(pp->good()) { + eventPoll = pp; + } else { + throw DL_ABORT_EX("Initializing PortEventPoll failed." + " Try --event-poll=select"); + } + } else #endif // HAVE_PORT_ASSOCIATE #ifdef HAVE_POLL - if(pollMethod == V_POLL) { - eventPoll.reset(new PollEventPoll()); - } else + if(pollMethod == V_POLL) { + eventPoll.reset(new PollEventPoll()); + } else #endif // HAVE_POLL - if(pollMethod == V_SELECT) { - eventPoll.reset(new SelectEventPoll()); - } else { - abort(); - } + if(pollMethod == V_SELECT) { + eventPoll.reset(new SelectEventPoll()); + } else { + abort(); + } DownloadEngineHandle e(new DownloadEngine(eventPoll)); e->option = op; diff --git a/src/KqueueEventPoll.cc b/src/KqueueEventPoll.cc new file mode 100644 index 00000000..1dc56e11 --- /dev/null +++ b/src/KqueueEventPoll.cc @@ -0,0 +1,294 @@ +/* */ +#include "KqueueEventPoll.h" + +#include +#include +#include + +#include "Command.h" +#include "LogFactory.h" +#include "Logger.h" + +#ifdef KEVENT_UDATA_INTPTR_T +# define PTR_TO_UDATA(X) (reinterpret_cast(X)) +#else // !KEVENT_UDATA_INTPTR_T +# define PTR_TO_UDATA(X) (X) +#endif // !KEVENT_UDATA_INTPTR_T + +namespace aria2 { + +KqueueEventPoll::KSocketEntry::KSocketEntry(sock_t s): + SocketEntry(s) {} + +int accumulateEvent(int events, const KqueueEventPoll::KEvent& event) +{ + return events|event.getEvents(); +} + +size_t KqueueEventPoll::KSocketEntry::getEvents +(struct kevent* eventlist) +{ + int events; +#ifdef ENABLE_ASYNC_DNS + events = + std::accumulate(_adnsEvents.begin(), + _adnsEvents.end(), + std::accumulate(_commandEvents.begin(), + _commandEvents.end(), 0, accumulateEvent), + accumulateEvent); +#else // !ENABLE_ASYNC_DNS + events = + std::accumulate(_commandEvents.begin(), _commandEvents.end(), 0, + accumulateEvent); +#endif // !ENABLE_ASYNC_DNS + EV_SET(&eventlist[0], _socket, EVFILT_READ, + EV_ADD|((events&KqueueEventPoll::IEV_READ)?EV_ENABLE:EV_DISABLE), + 0, 0, PTR_TO_UDATA(this)); + EV_SET(&eventlist[1], _socket, EVFILT_WRITE, + EV_ADD|((events&KqueueEventPoll::IEV_WRITE)?EV_ENABLE:EV_DISABLE), + 0, 0, PTR_TO_UDATA(this)); + return 2; +} + +KqueueEventPoll::KqueueEventPoll(): + _kqEventsSize(KQUEUE_EVENTS_MAX), + _kqEvents(new struct kevent[_kqEventsSize]), + _logger(LogFactory::getInstance()) +{ + _kqfd = kqueue(); +} + +KqueueEventPoll::~KqueueEventPoll() +{ + if(_kqfd != -1) { + int r; + while((r = close(_kqfd)) == -1 && errno == EINTR); + if(r == -1) { + _logger->error("Error occurred while closing kqueue file descriptor" + " %d: %s", + _kqfd, strerror(errno)); + } + } + delete [] _kqEvents; +} + +bool KqueueEventPoll::good() const +{ + return _kqfd != -1; +} + +void KqueueEventPoll::poll(const struct timeval& tv) +{ + struct timespec timeout = { tv.tv_sec, tv.tv_usec*1000 }; + int res; + while((res = kevent(_kqfd, _kqEvents, 0, _kqEvents, _kqEventsSize, &timeout)) + == -1 && errno == EINTR); + if(res > 0) { + for(int i = 0; i < res; ++i) { + KSocketEntry* p = reinterpret_cast(_kqEvents[i].udata); + int events = 0; + int filter = _kqEvents[i].filter; + if(filter == EVFILT_READ) { + events = KqueueEventPoll::IEV_READ; + } else if(filter == EVFILT_WRITE) { + events = KqueueEventPoll::IEV_WRITE; + } + p->processEvents(events); + } + } + +#ifdef ENABLE_ASYNC_DNS + // It turns out that we have to call ares_process_fd before ares's + // own timeout and ares may create new sockets or closes socket in + // their API. So we call ares_process_fd for all ares_channel and + // re-register their sockets. + for(std::deque >::iterator i = + _nameResolverEntries.begin(), eoi = _nameResolverEntries.end(); + i != eoi; ++i) { + (*i)->processTimeout(); + (*i)->removeSocketEvents(this); + (*i)->addSocketEvents(this); + } +#endif // ENABLE_ASYNC_DNS + + // TODO timeout of name resolver is determined in Command(AbstractCommand, + // DHTEntryPoint...Command) +} + +static int translateEvents(EventPoll::EventType events) +{ + int newEvents = 0; + if(EventPoll::EVENT_READ&events) { + newEvents |= KqueueEventPoll::IEV_READ; + } + if(EventPoll::EVENT_WRITE&events) { + newEvents |= KqueueEventPoll::IEV_WRITE; + } + return newEvents; +} + +bool KqueueEventPoll::addEvents +(sock_t socket, const KqueueEventPoll::KEvent& event) +{ + SharedHandle socketEntry(new KSocketEntry(socket)); + std::deque >::iterator i = + std::lower_bound(_socketEntries.begin(), _socketEntries.end(), socketEntry); + int r = 0; + struct timespec zeroTimeout = { 0, 0 }; + struct kevent changelist[2]; + size_t n; + if(i != _socketEntries.end() && (*i) == socketEntry) { + event.addSelf(*i); + n = (*i)->getEvents(changelist); + } else { + _socketEntries.insert(i, socketEntry); + if(_socketEntries.size() > _kqEventsSize) { + _kqEventsSize *= 2; + delete [] _kqEvents; + _kqEvents = new struct kevent[_kqEventsSize]; + } + event.addSelf(socketEntry); + n = socketEntry->getEvents(changelist); + } + r = kevent(_kqfd, changelist, n, changelist, 0, &zeroTimeout); + if(r == -1) { + if(_logger->debug()) { + _logger->debug("Failed to add socket event %d:%s", + socket, strerror(errno)); + } + return false; + } else { + return true; + } +} + +bool KqueueEventPoll::addEvents(sock_t socket, Command* command, + EventPoll::EventType events) +{ + int kqEvents = translateEvents(events); + return addEvents(socket, KCommandEvent(command, kqEvents)); +} + +#ifdef ENABLE_ASYNC_DNS +bool KqueueEventPoll::addEvents(sock_t socket, Command* command, int events, + const SharedHandle& rs) +{ + return addEvents(socket, KADNSEvent(rs, command, socket, events)); +} +#endif // ENABLE_ASYNC_DNS + +bool KqueueEventPoll::deleteEvents(sock_t socket, + const KqueueEventPoll::KEvent& event) +{ + SharedHandle socketEntry(new KSocketEntry(socket)); + std::deque >::iterator i = + std::lower_bound(_socketEntries.begin(), _socketEntries.end(), socketEntry); + if(i != _socketEntries.end() && (*i) == socketEntry) { + event.removeSelf(*i); + int r = 0; + struct timespec zeroTimeout = { 0, 0 }; + struct kevent changelist[2]; + size_t n = (*i)->getEvents(changelist); + r = kevent(_kqfd, changelist, n, changelist, 0, &zeroTimeout); + if((*i)->eventEmpty()) { + _socketEntries.erase(i); + } + if(r == -1) { + if(_logger->debug()) { + _logger->debug("Failed to delete socket event:%s", strerror(errno)); + } + return false; + } else { + return true; + } + } else { + if(_logger->debug()) { + _logger->debug("Socket %d is not found in SocketEntries.", socket); + } + return false; + } +} + +#ifdef ENABLE_ASYNC_DNS +bool KqueueEventPoll::deleteEvents(sock_t socket, Command* command, + const SharedHandle& rs) +{ + return deleteEvents(socket, KADNSEvent(rs, command, socket, 0)); +} +#endif // ENABLE_ASYNC_DNS + +bool KqueueEventPoll::deleteEvents(sock_t socket, Command* command, + EventPoll::EventType events) +{ + int kqEvents = translateEvents(events); + return deleteEvents(socket, KCommandEvent(command, kqEvents)); +} + +#ifdef ENABLE_ASYNC_DNS +bool KqueueEventPoll::addNameResolver +(const SharedHandle& resolver, Command* command) +{ + SharedHandle entry + (new KAsyncNameResolverEntry(resolver, command)); + std::deque >::iterator itr = + std::find(_nameResolverEntries.begin(), _nameResolverEntries.end(), entry); + if(itr == _nameResolverEntries.end()) { + _nameResolverEntries.push_back(entry); + entry->addSocketEvents(this); + return true; + } else { + return false; + } +} + +bool KqueueEventPoll::deleteNameResolver +(const SharedHandle& resolver, Command* command) +{ + SharedHandle entry + (new KAsyncNameResolverEntry(resolver, command)); + std::deque >::iterator itr = + std::find(_nameResolverEntries.begin(), _nameResolverEntries.end(), entry); + if(itr == _nameResolverEntries.end()) { + return false; + } else { + (*itr)->removeSocketEvents(this); + _nameResolverEntries.erase(itr); + return true; + } +} +#endif // ENABLE_ASYNC_DNS + +} // namespace aria2 diff --git a/src/KqueueEventPoll.h b/src/KqueueEventPoll.h new file mode 100644 index 00000000..80d2703b --- /dev/null +++ b/src/KqueueEventPoll.h @@ -0,0 +1,134 @@ +/* */ +#ifndef _D_KQUEUE_EVENT_POLL_H_ +#define _D_KQUEUE_EVENT_POLL_H_ + +#include "EventPoll.h" + +#include +#include +#include + +#include + +#include "Event.h" +#ifdef ENABLE_ASYNC_DNS +# include "AsyncNameResolver.h" +#endif // ENABLE_ASYNC_DNS + +namespace aria2 { + +class Logger; + +class KqueueEventPoll : public EventPoll { +private: + class KSocketEntry; + + typedef Event KEvent; + + typedef CommandEvent KCommandEvent; + typedef ADNSEvent KADNSEvent; + typedef AsyncNameResolverEntry KAsyncNameResolverEntry; + friend class AsyncNameResolverEntry; + + class KSocketEntry: + public SocketEntry { + public: + KSocketEntry(sock_t socket); + + // eventlist should be at least size 2. This function returns the + // number of filled struct kevent in eventlist. + size_t getEvents(struct kevent* eventlist); + }; + + friend int accumulateEvent(int events, const KEvent& event); + +private: + std::deque > _socketEntries; +#ifdef ENABLE_ASYNC_DNS + std::deque > _nameResolverEntries; +#endif // ENABLE_ASYNC_DNS + + int _kqfd; + + size_t _kqEventsSize; + + struct kevent* _kqEvents; + + static const size_t KQUEUE_EVENTS_MAX = 1024; + + Logger* _logger; + + bool addEvents(sock_t socket, const KEvent& event); + + bool deleteEvents(sock_t socket, const KEvent& event); + + bool addEvents(sock_t socket, Command* command, int events, + const SharedHandle& rs); + + bool deleteEvents(sock_t socket, Command* command, + const SharedHandle& rs); + +public: + KqueueEventPoll(); + + bool good() const; + + virtual ~KqueueEventPoll(); + + virtual void poll(const struct timeval& tv); + + virtual bool addEvents(sock_t socket, + Command* command, EventPoll::EventType events); + + virtual bool deleteEvents(sock_t socket, + Command* command, EventPoll::EventType events); +#ifdef ENABLE_ASYNC_DNS + + virtual bool addNameResolver(const SharedHandle& resolver, + Command* command); + virtual bool deleteNameResolver + (const SharedHandle& resolver, Command* command); +#endif // ENABLE_ASYNC_DNS + + static const int IEV_READ = POLLIN; + static const int IEV_WRITE = POLLOUT; + static const int IEV_ERROR = POLLERR; + static const int IEV_HUP = POLLHUP; +}; + +} // namespace aria2 + +#endif // _D_KQUEUE_EVENT_POLL_H_ diff --git a/src/Makefile.am b/src/Makefile.am index 3f694660..3320f13a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -535,6 +535,10 @@ if HAVE_PORT_ASSOCIATE SRCS += PortEventPoll.cc PortEventPoll.h endif # HAVE_PORT_ASSOCIATE +if HAVE_KQUEUE +SRCS += KqueueEventPoll.cc KqueueEventPoll.h +endif # HAVE_KQUEUE + noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ diff --git a/src/Makefile.in b/src/Makefile.in index 5bcbbb9e..dcd71234 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -281,6 +281,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @HAVE_MACH_ABSOLUTE_TIME_TRUE@am__append_28 = clock_gettime_osx.cc clock_gettime_osx.h @HAVE_POLL_TRUE@am__append_29 = PollEventPoll.cc PollEventPoll.h @HAVE_PORT_ASSOCIATE_TRUE@am__append_30 = PortEventPoll.cc PortEventPoll.h +@HAVE_KQUEUE_TRUE@am__append_31 = KqueueEventPoll.cc KqueueEventPoll.h subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -609,7 +610,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ timegm.c timegm.h daemon.cc daemon.h clock_gettime_mingw.cc \ clock_gettime_mingw.h clock_gettime_osx.cc clock_gettime_osx.h \ PollEventPoll.cc PollEventPoll.h PortEventPoll.cc \ - PortEventPoll.h + PortEventPoll.h KqueueEventPoll.cc KqueueEventPoll.h @ENABLE_XML_RPC_TRUE@am__objects_1 = \ @ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserController.$(OBJEXT) \ @ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserStateMachine.$(OBJEXT) \ @@ -792,7 +793,8 @@ am__objects_6 = @HAVE_MACH_ABSOLUTE_TIME_TRUE@ clock_gettime_osx.$(OBJEXT) @HAVE_POLL_TRUE@am__objects_29 = PollEventPoll.$(OBJEXT) @HAVE_PORT_ASSOCIATE_TRUE@am__objects_30 = PortEventPoll.$(OBJEXT) -am__objects_31 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ +@HAVE_KQUEUE_TRUE@am__objects_31 = KqueueEventPoll.$(OBJEXT) +am__objects_32 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ AbstractCommand.$(OBJEXT) \ InitiateConnectionCommandFactory.$(OBJEXT) \ DownloadCommand.$(OBJEXT) \ @@ -880,8 +882,8 @@ am__objects_31 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ $(am__objects_21) $(am__objects_22) $(am__objects_23) \ $(am__objects_24) $(am__objects_25) $(am__objects_26) \ $(am__objects_27) $(am__objects_28) $(am__objects_29) \ - $(am__objects_30) -am_libaria2c_a_OBJECTS = $(am__objects_31) + $(am__objects_30) $(am__objects_31) +am_libaria2c_a_OBJECTS = $(am__objects_32) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) @@ -1218,7 +1220,7 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ $(am__append_21) $(am__append_22) $(am__append_23) \ $(am__append_24) $(am__append_25) $(am__append_26) \ $(am__append_27) $(am__append_28) $(am__append_29) \ - $(am__append_30) + $(am__append_30) $(am__append_31) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @@ -1503,6 +1505,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiatorMSEHandshakeCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/KqueueEventPoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibgnutlsTLSContext.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibsslTLSContext.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@ diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 6187056b..afd88610 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -210,6 +210,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() #ifdef HAVE_EPOLL V_EPOLL, #endif // HAVE_EPOLL +#ifdef HAVE_KQUEUE + V_KQUEUE, +#endif // HAVE_KQUEUE #ifdef HAVE_PORT_ASSOCIATE V_PORT, #endif // HAVE_PORT_ASSOCIATE @@ -223,6 +226,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() TEXT_EVENT_POLL, #ifdef HAVE_EPOLL V_EPOLL, +#elif HAVE_KQUEUE + V_KQUEUE, #elif HAVE_PORT_ASSOCIATE V_PORT, #else diff --git a/src/main.cc b/src/main.cc index 63fc4c3e..6d633069 100644 --- a/src/main.cc +++ b/src/main.cc @@ -192,6 +192,11 @@ downloadresultcode::RESULT main(int argc, char* argv[]) 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(); diff --git a/src/prefs.cc b/src/prefs.cc index 9a71e97f..637d7a51 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -150,6 +150,7 @@ const std::string PREF_MAX_FILE_NOT_FOUND("max-file-not-found"); // value: epoll | select const std::string PREF_EVENT_POLL("event-poll"); const std::string V_EPOLL("epoll"); +const std::string V_KQUEUE("kqueue"); const std::string V_PORT("port"); const std::string V_POLL("poll"); const std::string V_SELECT("select"); diff --git a/src/prefs.h b/src/prefs.h index f8cf157a..2dfbf89d 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -154,6 +154,7 @@ extern const std::string PREF_MAX_FILE_NOT_FOUND; // value: epoll | select extern const std::string PREF_EVENT_POLL; extern const std::string V_EPOLL; +extern const std::string V_KQUEUE; extern const std::string V_PORT; extern const std::string V_POLL; extern const std::string V_SELECT;