Browse Source

add libev fdevent handler: server.event-handler = "libev"

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2754 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/lighttpd-1.4.27
Stefan Bühler 11 years ago
parent
commit
f8eb52ebda
  1. 1
      NEWS
  2. 70
      cmake/FindLibEV.cmake
  3. 37
      configure.ac
  4. 13
      src/CMakeLists.txt
  5. 10
      src/Makefile.am
  6. 2
      src/SConscript
  7. 3
      src/config.h.cmake
  8. 6
      src/configfile.c
  9. 26
      src/fdevent.c
  10. 46
      src/fdevent.h
  11. 168
      src/fdevent_libev.c

1
NEWS

@ -29,6 +29,7 @@ NEWS
* add check to stop loading plugins twice
* cleanup fdevent code, removed linux-rtsig handler, replaced some fprintf calls
* only require FDEVENT_IN bit to be set for listening connections (fixes #2227)
* add libev fdevent handler: server.event-handler = "libev"
- 1.4.26 - 2010-02-07
* Fix request parser to handle packets with splitted \r\n\r\n (fixes #2105)

70
cmake/FindLibEV.cmake

@ -0,0 +1,70 @@
SET(LIBEV_PATH "" CACHE PATH "Base path for include/ev.h and lib/libev*")
SET(LIBEV_INCLUDE_PATH "" CACHE PATH "Include path for ev.h")
SET(LIBEV_LIBDIR "" CACHE PATH "Path containing libev")
IF(LIBEV_PATH)
SET(LIBEV_INCLUDE_PATH "${LIBEV_PATH}/include" CACHE PATH "Include path for ev.h" FORCE)
SET(LIBEV_LIBDIR "${LIBEV_PATH}/lib" CACHE PATH "Path containing libev" FORCE)
ENDIF(LIBEV_PATH)
IF(LIBEV_INCLUDE_PATH)
INCLUDE_DIRECTORIES(${LIBEV_INCLUDE_PATH})
ENDIF(LIBEV_INCLUDE_PATH)
# Use cached result
IF(NOT LIBEV_FOUND)
UNSET(HAVE_EV_H)
UNSET(HAVE_LIBEV)
UNSET(HAVE_EV_H CACHE)
UNSET(HAVE_LIBEV CACHE)
UNSET(LIBEV_CFLAGS)
UNSET(LIBEV_LDFLAGS)
IF(LIBEV_INCLUDE_PATH OR LIBEV_LIBDIR)
SET(CMAKE_REQUIRED_INCLUDES ${LIBEV_INCLUDE_PATH})
# MESSAGE(STATUS "Looking for ev.h in ${CMAKE_REQUIRED_INCLUDES}")
CHECK_INCLUDE_FILES(ev.h HAVE_EV_H)
IF(HAVE_EV_H)
# MESSAGE(STATUS "Looking for lib ev in ${LIBEV_LIBDIR}")
CHECK_LIBRARY_EXISTS(ev ev_loop "${LIBEV_LIBDIR}" HAVE_LIBEV)
IF(HAVE_LIBEV)
SET(LIBEV_CFLAGS "" CACHE INTERNAL "")
SET(LIBEV_LDFLAGS "-L${LIBEV_LIBDIR} -lev" CACHE INTERNAL "")
SET(LIBEV_FOUND TRUE CACHE INTERNAL "Found libev" FORCE)
ELSE(HAVE_LIBEV)
MESSAGE(STATUS "Couldn't find lib ev in ${LIBEV_LIBDIR}")
ENDIF(HAVE_LIBEV)
ELSE(HAVE_EV_H)
MESSAGE(STATUS "Couldn't find <ev.h> in ${LIBEV_INCLUDE_PATH}")
ENDIF(HAVE_EV_H)
ELSE(LIBEV_INCLUDE_PATH OR LIBEV_LIBDIR)
pkg_check_modules(LIBEV libev)
IF(NOT LIBEV_FOUND)
# MESSAGE(STATUS "Looking for ev.h in ${CMAKE_REQUIRED_INCLUDES}")
CHECK_INCLUDE_FILES(ev.h HAVE_EV_H)
IF(HAVE_EV_H)
# MESSAGE(STATUS "Looking for lib ev")
CHECK_LIBRARY_EXISTS(ev ev_loop "" HAVE_LIBEV)
IF(HAVE_LIBEV)
SET(LIBEV_CFLAGS "" CACHE INTERNAL "")
SET(LIBEV_LDFLAGS "-lev" CACHE INTERNAL "")
SET(LIBEV_FOUND TRUE CACHE INTERNAL "Found libev" FORCE)
ELSE(HAVE_LIBEV)
MESSAGE(STATUS "Couldn't find lib ev")
ENDIF(HAVE_LIBEV)
ELSE(HAVE_EV_H)
MESSAGE(STATUS "Couldn't find <ev.h>")
ENDIF(HAVE_EV_H)
ENDIF(NOT LIBEV_FOUND)
ENDIF(LIBEV_INCLUDE_PATH OR LIBEV_LIBDIR)
ENDIF(NOT LIBEV_FOUND)
IF(NOT LIBEV_FOUND)
IF(LibEV_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find libev")
ENDIF(LibEV_FIND_REQUIRED)
ENDIF(NOT LIBEV_FOUND)
MARK_AS_ADVANCED(LIBEV_PATH LIBEV_INCLUDE_PATH LIBEV_LIBDIR)

37
configure.ac

@ -83,6 +83,43 @@ AC_FUNC_STAT
AC_FUNC_STRFTIME
AC_CHECK_FUNCS([issetugid inet_pton])
dnl checking for libev
AC_MSG_CHECKING(for libev support)
AC_ARG_WITH(libev,
AC_HELP_STRING([--with-libev@<:@=PATH@:>@],[Include libev support for fdevent handlers in PATH/include and PATH/lib]),
[WITH_LIBEV=$withval],[WITH_LIBEV=no])
LIBEV_CFLAGS=""
LIBEV_LIBS=""
if test "$WITH_LIBEV" != "no"; then
PKG_CHECK_MODULES(LIBEV, libev, [], [
dnl no pkg-config for libev, searching manually:
if test "$WITH_LIBEV" != "yes"; then
LIBEV_CFLAGS="-I$WITH_LIBEV/include"
LIBEV_LIBS="-L$WITH_LIBEV/lib -lev"
else
AC_CHECK_HEADERS([ev.h],[
AC_CHECK_LIB([ev], [ev_loop], [
LIBEV_CFLAGS=""
LIBEV_LIBS="-lev"
],[
AC_MSG_ERROR([libev not found])
]
)],[
AC_MSG_ERROR([libev not found])
]
)
fi
])
AC_DEFINE([HAVE_LIBEV], [1], [libev support])
fi
AC_SUBST(LIBEV_CFLAGS)
AC_SUBST(LIBEV_LIBS)
dnl Checks for database.
MYSQL_INCLUDE=""
MYSQL_LIBS=""

13
src/CMakeLists.txt

@ -28,6 +28,7 @@ OPTION(WITH_LUA "with lua 5.1 for mod_magnet [default: off]")
OPTION(WITH_FAM "fam/gamin for reducing number of stat() calls [default: off]")
OPTION(WITH_GDBM "gdbm storage for mod_trigger_b4_dl [default: off]")
OPTION(WITH_MEMCACHE "memcached storage for mod_trigger_b4_dl [default: off]")
OPTION(WITH_LIBEV "libev support for fdevent handlers [default: off]")
IF(CMAKE_COMPILER_IS_GNUCC)
OPTION(BUILD_EXTRA_WARNINGS "extra warnings")
@ -49,6 +50,11 @@ ELSE(BUILD_STATIC)
SET(CMAKE_SHARED_LIBRARY_PREFIX "")
ENDIF(BUILD_STATIC)
IF(WITH_LIBEV)
FIND_PACKAGE(LibEV REQUIRED)
SET(HAVE_LIBEV 1 FORCE)
ENDIF(WITH_LIBEV)
IF(WITH_WEBDAV_PROPS)
SET(WITH_XML 1)
SET(WITH_SQLITE3 1)
@ -409,7 +415,7 @@ SET(COMMON_SRC
stat_cache.c plugin.c joblist.c etag.c array.c
data_string.c data_count.c data_array.c
data_integer.c md5.c data_fastcgi.c
fdevent_select.c
fdevent_select.c fdevent_libev.c
fdevent_poll.c fdevent_linux_sysepoll.c
fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c
data_config.c bitset.c
@ -599,6 +605,11 @@ IF(HAVE_LIBSSL AND HAVE_LIBCRYPTO)
TARGET_LINK_LIBRARIES(lighttpd crypto)
ENDIF(HAVE_LIBSSL AND HAVE_LIBCRYPTO)
IF(WITH_LIBEV)
ADD_TARGET_PROPERTIES(lighttpd LINK_FLAGS ${LIBEV_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd COMPILE_FLAGS ${LIBEV_CFLAGS})
ENDIF(WITH_LIBEV)
IF(NOT WIN32)
INSTALL(TARGETS ${L_INSTALL_TARGETS}
RUNTIME DESTINATION ${SBINDIR}

10
src/Makefile.am

@ -62,7 +62,7 @@ common_src=buffer.c log.c \
stat_cache.c plugin.c joblist.c etag.c array.c \
data_string.c data_count.c data_array.c \
data_integer.c md5.c data_fastcgi.c \
fdevent_select.c \
fdevent_select.c fdevent_libev.c \
fdevent_poll.c fdevent_linux_sysepoll.c \
fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \
data_config.c bitset.c \
@ -86,9 +86,9 @@ if NO_RDYNAMIC
# everything
lib_LTLIBRARIES += liblightcomp.la
liblightcomp_la_SOURCES=$(common_src)
liblightcomp_la_CFLAGS=$(AM_CFLAGS)
liblightcomp_la_CFLAGS=$(AM_CFLAGS) $(LIBEV_CFLAGS)
liblightcomp_la_LDFLAGS = -avoid-version -no-undefined
liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS)
liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS) $(LIBEV_LIBS)
common_libadd = liblightcomp.la
else
src += $(common_src)
@ -283,9 +283,9 @@ hdr = server.h buffer.h network.h log.h keyvalue.h \
DEFS= @DEFS@ -DHAVE_VERSION_H -DLIBRARY_DIR="\"$(libdir)\"" -DSBIN_DIR="\"$(sbindir)\""
lighttpd_SOURCES = $(src)
lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS)
lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS) $(LIBEV_LIBS)
lighttpd_LDFLAGS = -export-dynamic
lighttpd_CCPFLAGS = $(FAM_CFLAGS)
lighttpd_CCPFLAGS = $(FAM_CFLAGS) $(LIBEV_CFLAGS)
proc_open_SOURCES = proc_open.c buffer.c
proc_open_CPPFLAGS= -DDEBUG_PROC_OPEN

2
src/SConscript

@ -10,7 +10,7 @@ common_src = Split("buffer.c log.c \
stat_cache.c plugin.c joblist.c etag.c array.c \
data_string.c data_count.c data_array.c \
data_integer.c md5.c data_fastcgi.c \
fdevent_select.c \
fdevent_select.c fdevent_libev.c \
fdevent_poll.c fdevent_linux_sysepoll.c \
fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \
data_config.c bitset.c \

3
src/config.h.cmake

@ -155,4 +155,7 @@
#cmakedefine HAVE_FASTCGI_H
#cmakedefine HAVE_FASTCGI_FASTCGI_H
/* libev */
#cmakedefine HAVE_LIBEV
#cmakedefine LIGHTTPD_STATIC

6
src/configfile.c

@ -1171,9 +1171,8 @@ int config_set_defaults(server *srv) {
struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
{
/* - poll is most reliable
/* - epoll is most reliable
* - select works everywhere
* - linux-* are experimental
*/
#ifdef USE_LINUX_EPOLL
{ FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
@ -1184,6 +1183,9 @@ int config_set_defaults(server *srv) {
#ifdef USE_SELECT
{ FDEVENT_HANDLER_SELECT, "select" },
#endif
#ifdef USE_LIBEV
{ FDEVENT_HANDLER_LIBEV, "libev" },
#endif
#ifdef USE_SOLARIS_DEVPOLL
{ FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
#endif

26
src/fdevent.c

@ -27,42 +27,49 @@ fdevents *fdevent_init(server *srv, size_t maxfds, fdevent_handler_t type) {
return NULL;
}
break;
return ev;
case FDEVENT_HANDLER_SELECT:
if (0 != fdevent_select_init(ev)) {
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"event-handler select failed");
return NULL;
}
break;
return ev;
case FDEVENT_HANDLER_LINUX_SYSEPOLL:
if (0 != fdevent_linux_sysepoll_init(ev)) {
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"");
return NULL;
}
break;
return ev;
case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
if (0 != fdevent_solaris_devpoll_init(ev)) {
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"");
return NULL;
}
break;
return ev;
case FDEVENT_HANDLER_FREEBSD_KQUEUE:
if (0 != fdevent_freebsd_kqueue_init(ev)) {
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"");
return NULL;
}
return ev;
case FDEVENT_HANDLER_LIBEV:
if (0 != fdevent_libev_init(ev)) {
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\"");
return NULL;
}
return ev;
case FDEVENT_HANDLER_UNSET:
break;
default:
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"");
return NULL;
}
return ev;
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"");
return NULL;
}
void fdevent_free(fdevents *ev) {
@ -104,6 +111,7 @@ int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
fdn->handler = handler;
fdn->fd = fd;
fdn->ctx = ctx;
fdn->handler_ctx = NULL;
ev->fdarray[fd] = fdn;

46
src/fdevent.h

@ -59,6 +59,11 @@
# include <sys/port.h>
#endif
#if defined HAVE_LIBEV
# define USE_LIBEV
# include <ev.h>
#endif
struct server;
typedef handler_t (*fdevent_handler)(struct server *srv, void *ctx, int revents);
@ -83,45 +88,26 @@ typedef enum { FD_EVENT_TYPE_UNSET = -1,
typedef enum { FDEVENT_HANDLER_UNSET,
FDEVENT_HANDLER_SELECT,
FDEVENT_HANDLER_POLL,
FDEVENT_HANDLER_LINUX_RTSIG,
FDEVENT_HANDLER_LINUX_SYSEPOLL,
FDEVENT_HANDLER_SOLARIS_DEVPOLL,
FDEVENT_HANDLER_FREEBSD_KQUEUE,
FDEVENT_HANDLER_SOLARIS_PORT
FDEVENT_HANDLER_SOLARIS_PORT,
FDEVENT_HANDLER_LIBEV
} fdevent_handler_t;
/**
* a mapping from fd to connection structure
*
*/
typedef struct {
int fd; /**< the fd */
void *conn; /**< a reference the corresponding data-structure */
fd_event_t fd_type; /**< type of the fd */
int events; /**< registered events */
int revents;
} fd_conn;
typedef struct {
fd_conn *ptr;
size_t size;
size_t used;
} fd_conn_buffer;
/**
* array of unused fd's
*
*/
typedef struct _fdnode {
fdevent_handler handler;
void *ctx;
void *handler_ctx;
int fd;
struct _fdnode *prev, *next;
} fdnode;
/**
* array of unused fd's
*
*/
typedef struct {
int *ptr;
@ -173,6 +159,9 @@ typedef struct fdevents {
#endif
#ifdef USE_SOLARIS_PORT
int port_fd;
#endif
#ifdef USE_LIBEV
struct ev_loop *libev_loop;
#endif
int (*reset)(struct fdevents *ev);
void (*free)(struct fdevents *ev);
@ -214,7 +203,6 @@ int fdevent_poll_init(fdevents *ev);
int fdevent_linux_sysepoll_init(fdevents *ev);
int fdevent_solaris_devpoll_init(fdevents *ev);
int fdevent_freebsd_kqueue_init(fdevents *ev);
int fdevent_libev_init(fdevents *ev);
#endif

168
src/fdevent_libev.c

@ -0,0 +1,168 @@
#include "fdevent.h"
#include "buffer.h"
#include "log.h"
#include <assert.h>
#ifdef USE_LIBEV
static void io_watcher_cb(struct ev_loop *loop, ev_io *w, int revents) {
fdevents *ev = w->data;
fdnode *fdn = ev->fdarray[w->fd];
int r = 0;
UNUSED(loop);
if (revents & EV_READ) r |= FDEVENT_IN;
if (revents & EV_WRITE) r |= FDEVENT_OUT;
if (revents & EV_ERROR) r |= FDEVENT_ERR;
switch (r = (*fdn->handler)(ev->srv, fdn->ctx, r)) {
case HANDLER_FINISHED:
case HANDLER_GO_ON:
case HANDLER_WAIT_FOR_EVENT:
case HANDLER_WAIT_FOR_FD:
break;
case HANDLER_ERROR:
/* should never happen */
SEGFAULT();
break;
default:
log_error_write(ev->srv, __FILE__, __LINE__, "d", r);
break;
}
}
static void fdevent_libev_free(fdevents *ev) {
UNUSED(ev);
}
static int fdevent_libev_event_del(fdevents *ev, int fde_ndx, int fd) {
fdnode *fdn;
ev_io *watcher;
if (-1 == fde_ndx) return -1;
fdn = ev->fdarray[fd];
watcher = fdn->handler_ctx;
if (!watcher) return -1;
ev_io_stop(ev->libev_loop, watcher);
free(watcher);
fdn->handler_ctx = NULL;
return -1;
}
static int fdevent_libev_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
fdnode *fdn = ev->fdarray[fd];
ev_io *watcher = fdn->handler_ctx;
int ev_events = 0;
UNUSED(fde_ndx);
if (events & FDEVENT_IN) ev_events |= EV_READ;
if (events & FDEVENT_OUT) ev_events |= EV_WRITE;
if (!watcher) {
fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io));
assert(watcher);
ev_io_init(watcher, io_watcher_cb, fd, ev_events);
watcher->data = ev;
ev_io_start(ev->libev_loop, watcher);
} else {
if ((watcher->events & ev_events) != ev_events) {
ev_io_stop(ev->libev_loop, watcher);
ev_io_set(watcher, watcher->fd, watcher->events | ev_events);
ev_io_start(ev->libev_loop, watcher);
}
}
return fd;
}
static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) {
UNUSED(loop);
UNUSED(w);
UNUSED(revents);
}
static int fdevent_libev_poll(fdevents *ev, int timeout_ms) {
ev_timer timeout_watcher;
ev_init(&timeout_watcher, timeout_watcher_cb);
ev_timer_set(&timeout_watcher, ((ev_tstamp) timeout_ms)/1000.0, 0.0);
ev_timer_start(ev->libev_loop, &timeout_watcher);
ev_loop(ev->libev_loop, EVLOOP_ONESHOT);
ev_timer_stop(ev->libev_loop, &timeout_watcher);
return 0;
}
static int fdevent_libev_event_get_revent(fdevents *ev, size_t ndx) {
UNUSED(ev);
UNUSED(ndx);
return 0;
}
static int fdevent_libev_event_get_fd(fdevents *ev, size_t ndx) {
UNUSED(ev);
UNUSED(ndx);
return -1;
}
static int fdevent_libev_event_next_fdndx(fdevents *ev, int ndx) {
UNUSED(ev);
UNUSED(ndx);
return -1;
}
static int fdevent_libev_reset(fdevents *ev) {
UNUSED(ev);
ev_default_fork();
return 0;
}
int fdevent_libev_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_LIBEV;
#define SET(x) \
ev->x = fdevent_libev_##x;
SET(free);
SET(poll);
SET(reset);
SET(event_del);
SET(event_add);
SET(event_next_fdndx);
SET(event_get_fd);
SET(event_get_revent);
if (NULL == (ev->libev_loop = ev_default_loop(0))) {
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
return 0;
}
#else
int fdevent_libev_init(fdevents *ev) {
UNUSED(ev);
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"libev not supported, try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
#endif
Loading…
Cancel
Save