Changeset 1561
- Timestamp:
- 02/01/2007 12:17:22 AM (19 months ago)
- Location:
- trunk
- Files:
-
- 14 modified
- 1 copied
-
configure.in (modified) (3 diffs)
-
src/CMakeLists.txt (modified) (6 diffs)
-
src/Makefile.am (modified) (4 diffs)
-
src/base.h (modified) (5 diffs)
-
src/chunk.c (modified) (2 diffs)
-
src/chunk.h (modified) (1 diff)
-
src/configfile.c (modified) (2 diffs)
-
src/network.c (modified) (3 diffs)
-
src/network_backends.h (modified) (1 diff)
-
src/network_gthread_aio.c (copied) (copied from trunk/src/network_posix_aio.c) (3 diffs)
-
src/network_linux_aio.c (modified) (2 diffs)
-
src/network_posix_aio.c (modified) (2 diffs)
-
src/response.c (modified) (2 diffs)
-
src/server.c (modified) (14 diffs)
-
src/stat_cache.c (modified) (18 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/configure.in
r1538 r1561 300 300 fi 301 301 302 dnl Check for gamin303 AC_MSG_CHECKING(for FAM)304 AC_ARG_WITH(fam, AC_HELP_STRING([--with-fam],[fam/gamin for reducing number of stat() calls]),305 [WITH_FAM=$withval],[WITH_FAM=no])306 AC_MSG_RESULT([$WITH_FAM])307 308 if test "$WITH_FAM" != "no"; then309 AC_CHECK_LIB(fam, FAMOpen2, [310 AC_CHECK_HEADERS([fam.h],[311 FAM_LIBS=-lfam312 AC_DEFINE([HAVE_LIBFAM], [1], [libfam])313 AC_DEFINE([HAVE_FAM_H], [1], [fam.h])314 ])315 ])316 if test "x$FAM_LIBS" = x; then317 PKG_CHECK_MODULES(FAM, gamin >= 0.1.0, [318 AC_DEFINE([HAVE_LIBFAM], [1], [libfam])319 AC_DEFINE([HAVE_FAM_H], [1], [fam.h])320 ])321 fi322 OLD_LIBS=$LIBS323 LIBS=$FAM_LIBS324 AC_CHECK_FUNCS([FAMNoExists])325 LIBS=$OLD_LIBS326 fi327 328 302 AC_MSG_CHECKING(for properties in mod_webdav) 329 303 AC_ARG_WITH(webdav-props, AC_HELP_STRING([--with-webdav-props],[properties in mod_webdav]), … … 407 381 AC_SUBST(LUA_LIBS) 408 382 fi 383 384 PKG_CHECK_MODULES(GTHREAD, gthread-2.0, [ 385 AC_DEFINE([HAVE_GTHREAD], [1], [libglib]) 386 AC_DEFINE([HAVE_GLIB_H], [1], [glib.h]) 387 ]) 409 388 410 389 dnl Check for libaio … … 665 644 fi 666 645 667 features="stat-cache-fam"668 if test ! "x$FAM_LIBS" = x; then669 enable_feature="$enable_feature $features"670 else671 disable_feature="$disable_feature $features"672 fi673 674 646 features="webdav-properties" 675 647 if test "x$XML_LIBS" \!= x -a "x$SQLITE_LIBS" \!= x; then -
trunk/src/CMakeLists.txt
r1560 r1561 19 19 OPTION(WITH_BZIP "with bzip2-support for mod_compress [default: off]") 20 20 OPTION(WITH_ZLIB "with deflate-support for mod_compress [default: on]" ON) 21 OPTION(WITH_FAM "with FAM-support for the stat-cache [default: off]")22 21 OPTION(WITH_LDAP "with LDAP-support for the mod_auth [default: off]") 23 22 OPTION(WITH_LIBAIO "with libaio for the linux [default: off]") … … 56 55 CHECK_INCLUDE_FILES(time.h HAVE_TIME_H) 57 56 57 INCLUDE_DIRECTORIES(/opt/gnome/include/glib-2.0 /opt/gnome/lib64/glib-2.0/include/) 58 58 59 IF(WITH_XATTR) 59 60 CHECK_INCLUDE_FILES(attr/attributes.h HAVE_ATTR_ATTRIBUTES_H) … … 85 86 CHECK_LIBRARY_EXISTS(bz2 BZ2_bzCompressInit "" HAVE_LIBBZ2) 86 87 ENDIF(WITH_BZIP) 87 IF(WITH_FAM) 88 CHECK_INCLUDE_FILES(fam.h HAVE_FAM_H) 89 ENDIF(WITH_FAM) 88 90 89 CHECK_INCLUDE_FILES(getopt.h HAVE_GETOPT_H) 91 90 CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H) … … 231 230 network_linux_aio.c 232 231 network_posix_aio.c 232 network_gthread_aio.c 233 233 http_resp.c 234 234 http_resp_parser.c … … 370 370 ENDIF(CMAKE_SYSTEM MATCHES "Linux") 371 371 372 TARGET_LINK_LIBRARIES(lighttpd glib-2.0 gthread-2.0) 373 SET_TARGET_PROPERTIES(lighttpd PROPERTIES LINK_FLAGS "-L/opt/gnome/lib64/ -pthread -lrt") 372 374 SET_TARGET_PROPERTIES(lighttpd PROPERTIES CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) 373 375 … … 383 385 TARGET_LINK_LIBRARIES(lighttpd pcre) 384 386 ENDIF(HAVE_PCRE_H) 385 386 IF(HAVE_FAM_H)387 TARGET_LINK_LIBRARIES(lighttpd fam)388 ENDIF(HAVE_FAM_H)389 387 390 388 IF(HAVE_LIBSSL AND HAVE_LIBCRYPTO) -
trunk/src/Makefile.am
r1538 r1561 1 AM_CFLAGS = $( FAM_CFLAGS)1 AM_CFLAGS = $(GTHREAD_CFLAGS) 2 2 3 3 noinst_PROGRAMS=proc_open lemon # simple-fcgi … … 71 71 network_linux_aio.c \ 72 72 network_posix_aio.c \ 73 network_gthread_aio.c \ 73 74 splaytree.c \ 74 75 http_resp.c http_resp_parser.c \ … … 124 125 mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB) 125 126 126 #lib_LTLIBRARIES += mod_cml.la127 #mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c128 #mod_cml_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS)129 #mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined130 #mod_cml_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) $(LUA_LIBS) -lm127 lib_LTLIBRARIES += mod_magnet.la 128 mod_magnet_la_SOURCES = mod_magnet.c mod_magnet_cache.c 129 mod_magnet_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS) 130 mod_magnet_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined 131 mod_magnet_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) $(LUA_LIBS) -lm 131 132 132 133 lib_LTLIBRARIES += mod_trigger_b4_dl.la … … 320 321 http_parser.h \ 321 322 ajp13.h \ 322 mod_proxy_core_protocol.h 323 mod_proxy_core_protocol.h \ 324 mod_magnet_cache.h 323 325 324 326 DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\"" 325 327 326 328 lighttpd_SOURCES = $(src) 327 lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS) $(AIO_LIB) $(POSIX_AIO_LIB) 329 lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS) $(AIO_LIB) $(POSIX_AIO_LIB) $(GTHREAD_LIBS) 328 330 lighttpd_LDFLAGS = -export-dynamic 329 331 lighttpd_CCPFLAGS = $(FAM_CFLAGS) -
trunk/src/base.h
r1558 r1561 49 49 #endif 50 50 51 #include <glib.h> 52 51 53 #ifndef O_BINARY 52 54 # define O_BINARY 0 … … 192 194 time_t stat_ts; 193 195 196 enum { 197 STAT_CACHE_ENTRY_UNSET, 198 STAT_CACHE_ENTRY_ASYNC_STAT, 199 STAT_CACHE_ENTRY_STAT_FINISHED 200 } state; 201 194 202 #ifdef HAVE_LSTAT 195 203 char is_symlink; 196 204 #endif 197 205 198 #if defined(HAVE_ FAM_H) || defined(HAVE_SYS_INOTIFY_H)199 int dir_version; 206 #if defined(HAVE_SYS_INOTIFY_H) 207 int dir_version; /* when this entry was created the dir had this version */ 200 208 int dir_ndx; 201 209 #endif … … 205 213 206 214 typedef struct { 207 splay_tree *files; /* the nodes of the tree are stat_cache_entries */ 208 209 buffer *dir_name; /* for building the dirname from the filename */ 210 buffer *hash_key; 211 212 #if defined(HAVE_FAM_H) || defined(HAVE_SYS_INOTIFY_H) 213 splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */ 214 215 iosocket *sock; 216 #endif 217 #if defined(HAVE_FAM_H) 218 FAMConnection *fam; 215 GHashTable *files; /* a HashTable of stat_cache_entries for the files */ 216 GHashTable *dirs; /* a HashTable of stat_cache_entries for the dirs */ 217 218 buffer *dir_name; /* for building the dirname from the filename */ 219 buffer *hash_key; /* tmp-buf for building the hash-key */ 220 221 #if defined(HAVE_SYS_INOTIFY_H) 222 iosocket *sock; /* socket to the inotify fd (this should be in a backend struct */ 219 223 #endif 220 224 } stat_cache; … … 481 485 buffer *errorlog_file; 482 486 unsigned short errorlog_use_syslog; 487 488 unsigned short max_stat_threads; 489 unsigned short max_write_threads; 483 490 } server_config; 484 491 … … 594 601 595 602 #ifdef HAVE_LIBAIO_H 596 #define LINUX_IO_MAX_IOCBS 128597 603 io_context_t linux_io_ctx; 598 604 599 struct iocb linux_io_iocbs[LINUX_IO_MAX_IOCBS];605 struct iocb *linux_io_iocbs; 600 606 601 607 #endif 602 608 #ifdef HAVE_AIO_H 603 #define POSIX_AIO_MAX_IOCBS 128 604 struct aiocb posix_aio_iocbs[POSIX_AIO_MAX_IOCBS]; 605 struct aiocb * posix_aio_iocbs_watch[POSIX_AIO_MAX_IOCBS]; 606 607 void *posix_aio_data[POSIX_AIO_MAX_IOCBS]; 608 #endif 609 609 struct aiocb *posix_aio_iocbs; 610 struct aiocb ** posix_aio_iocbs_watch; 611 612 void **posix_aio_data; 613 #endif 614 615 GAsyncQueue *stat_queue; /* send a stat_job into this queue and joblist_queue will get a wakeup when the stat is finished */ 616 GAsyncQueue *joblist_queue; 617 GAsyncQueue *aio_write_queue; 610 618 } server; 611 619 -
trunk/src/chunk.c
r1513 r1561 45 45 c->file.mmap.start = MAP_FAILED; 46 46 c->next = NULL; 47 48 c->async.written = -1; 47 49 48 50 return c; … … 86 88 c->file.copy.length = 0; 87 89 c->file.copy.offset = 0; 90 91 c->async.written = -1; 92 c->async.ret_val = 0; 88 93 } 89 94 -
trunk/src/chunk.h
r1502 r1561 37 37 - file-chunk: file.length 38 38 */ 39 40 struct { 41 off_t written; 42 int ret_val; 43 } async; 39 44 40 45 struct chunk *next; -
trunk/src/configfile.c
r1558 r1561 92 92 { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */ 93 93 { "server.use-noatime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 47 */ 94 { "server.max-stat-threads", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 48 */ 95 { "server.max-write-threads", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 49 */ 94 96 95 97 { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, … … 135 137 cv[12].destination = &(srv->srvconf.max_request_size); 136 138 cv[47].destination = &(srv->srvconf.use_noatime); 139 cv[48].destination = &(srv->srvconf.max_stat_threads); 140 cv[49].destination = &(srv->srvconf.max_write_threads); 137 141 138 142 srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); -
trunk/src/network.c
r1534 r1561 446 446 NETWORK_BACKEND_LINUX_AIO_SENDFILE, 447 447 NETWORK_BACKEND_POSIX_AIO, 448 NETWORK_BACKEND_GTHREAD_AIO, 448 449 449 450 NETWORK_BACKEND_FREEBSD_SENDFILE, … … 471 472 { NETWORK_BACKEND_LINUX_AIO_SENDFILE, "linux-aio-sendfile" }, 472 473 #endif 474 #if defined USE_FREEBSD_SENDFILE 475 { NETWORK_BACKEND_FREEBSD_SENDFILE, "freebsd-sendfile" }, 476 #endif 477 #if defined USE_SOLARIS_SENDFILEV 478 { NETWORK_BACKEND_SOLARIS_SENDFILEV, "solaris-sendfilev" }, 479 #endif 473 480 #if defined USE_POSIX_AIO 474 481 { NETWORK_BACKEND_POSIX_AIO, "posix-aio" }, 475 482 #endif 476 477 #if defined USE_FREEBSD_SENDFILE 478 { NETWORK_BACKEND_FREEBSD_SENDFILE, "freebsd-sendfile" }, 479 #endif 480 #if defined USE_SOLARIS_SENDFILEV 481 { NETWORK_BACKEND_SOLARIS_SENDFILEV, "solaris-sendfilev" }, 482 #endif 483 { NETWORK_BACKEND_GTHREAD_AIO, "gthread-aio" }, 483 484 #if defined USE_WRITEV 484 485 { NETWORK_BACKEND_WRITEV, "writev" }, … … 581 582 break; 582 583 #endif 583 584 case NETWORK_BACKEND_GTHREAD_AIO: 585 SET_NETWORK_BACKEND(read, gthreadaio); 586 break; 584 587 #ifdef USE_FREEBSD_SENDFILE 585 588 case NETWORK_BACKEND_FREEBSD_SENDFILE: -
trunk/src/network_backends.h
r1493 r1561 83 83 NETWORK_BACKEND_WRITE(linuxaiosendfile); 84 84 NETWORK_BACKEND_WRITE(posixaio); 85 NETWORK_BACKEND_WRITE(gthreadaio); 85 86 NETWORK_BACKEND_WRITE(freebsdsendfile); 86 87 NETWORK_BACKEND_WRITE(solarissendfilev); -
trunk/src/network_gthread_aio.c
r1556 r1561 37 37 #include "sys-files.h" 38 38 39 NETWORK_BACKEND_WRITE(posixaio) { 39 typedef struct { 40 chunk *c; 41 42 void *con; 43 44 int sock_fd; 45 } write_job; 46 47 write_job *write_job_init() { 48 write_job *wj = calloc(1, sizeof(*wj)); 49 50 return wj; 51 } 52 53 void write_job_free(write_job *wj) { 54 if (!wj) return; 55 56 free(wj); 57 } 58 59 gpointer aio_write_thread(gpointer _srv) { 60 server *srv = (server *)_srv; 61 write_job *wj = NULL; 62 63 /* take the stat-job-queue */ 64 GAsyncQueue * inq = g_async_queue_ref(srv->aio_write_queue); 65 GAsyncQueue * outq = g_async_queue_ref(srv->joblist_queue); 66 67 /* */ 68 while ((wj = g_async_queue_pop(inq))) { 69 /* let's see what we have to stat */ 70 ssize_t r; 71 off_t offset; 72 size_t toSend; 73 const off_t max_toSend = 2 * 256 * 1024; /** should be larger than the send buffer */ 74 chunk *c = wj->c; 75 int mmap_fd; 76 77 offset = c->file.start + c->offset; 78 79 toSend = c->file.length - c->offset > max_toSend ? 80 max_toSend : c->file.length - c->offset; 81 82 c->file.copy.offset = 0; 83 c->file.copy.length = toSend; 84 85 /* open a file in /dev/shm to write to */ 86 if (c->file.mmap.start == MAP_FAILED) { 87 if (-1 == (mmap_fd = open("/dev/zero", O_RDWR))) { 88 if (errno != EMFILE) { 89 TRACE("open(/dev/zero) returned: %d (%s), open fds: %d", 90 errno, strerror(errno), srv->cur_fds); 91 c->async.ret_val = NETWORK_STATUS_FATAL_ERROR; 92 } else { 93 c->async.ret_val = NETWORK_STATUS_WAIT_FOR_FD; 94 } 95 } else { 96 c->file.mmap.offset = 0; 97 c->file.mmap.length = c->file.copy.length; /* align to page-size */ 98 99 c->file.mmap.start = mmap(0, c->file.mmap.length, 100 PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, 0); 101 if (c->file.mmap.start == MAP_FAILED) { 102 c->async.ret_val = NETWORK_STATUS_FATAL_ERROR; 103 } 104 105 close(mmap_fd); 106 mmap_fd = -1; 107 } 108 } 109 110 if (c->file.mmap.start != MAP_FAILED) { 111 lseek(c->file.fd, c->file.start + c->offset, SEEK_SET); 112 113 if (-1 == (r = read(c->file.fd, c->file.mmap.start, c->file.copy.length))) { 114 switch(errno) { 115 default: 116 ERROR("reading file failed: %d (%s)", errno, strerror(errno)); 117 118 c->async.ret_val = NETWORK_STATUS_FATAL_ERROR; 119 } 120 } else if (r == 0) { 121 ERROR("read() returned 0 ... not good: %s", ""); 122 123 c->async.ret_val = NETWORK_STATUS_FATAL_ERROR; 124 } else if (r != c->file.copy.length) { 125 ERROR("read() returned %d instead of %d", r, c->file.copy.length); 126 127 c->async.ret_val = NETWORK_STATUS_FATAL_ERROR; 128 } 129 } 130 131 /* read async, write as usual */ 132 g_async_queue_push(outq, wj->con); 133 134 write_job_free(wj); 135 } 136 137 g_async_queue_unref(srv->aio_write_queue); 138 g_async_queue_unref(srv->joblist_queue); 139 140 return NULL; 141 142 } 143 144 145 NETWORK_BACKEND_WRITE(gthreadaio) { 40 146 chunk *c, *tc; 41 147 size_t chunks_written = 0; … … 70 176 break; 71 177 case FILE_CHUNK: { 178 stat_cache_entry *sce = NULL; 72 179 ssize_t r; 73 int rounds = 8; 180 181 /* we might be on our way back from the async request and have a status-code */ 182 if (c->async.ret_val != NETWORK_STATUS_UNSET) { 183 ret = c->async.ret_val; 184 185 c->async.ret_val = NETWORK_STATUS_UNSET; 186 187 return ret; 188 } 74 189 75 190 /* open file if not already opened */ 76 191 if (-1 == c->file.fd) { 77 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY | /* O_DIRECT | */(srv->srvconf.use_noatime ? O_NOATIME : 0)))) {192 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY /* | O_DIRECT */ | (srv->srvconf.use_noatime ? O_NOATIME : 0)))) { 78 193 ERROR("opening '%s' failed: %s", BUF_STR(c->file.name), strerror(errno)); 79 194 … … 88 203 } 89 204 90 do { 91 size_t toSend; 92 const size_t max_toSend = 2 * 256 * 1024; /** should be larger than the send buffer */ 93 off_t offset; 94 95 offset = c->file.start + c->offset; 96 97 toSend = c->file.length - c->offset > max_toSend ? 98 max_toSend : c->file.length - c->offset; 99 100 if (0 == c->file.copy.length) { 101 int async_error = 0; 102 103 size_t iocb_ndx; 104 105 106 c->file.copy.offset = 0; 107 c->file.copy.length = toSend; 108 109 if (c->file.copy.length == 0) { 110 async_error = 1; 111 } 112 113 /* if we reused the previous tmp-file we get overlaps 114 * 115 * 1 ... 3904 are ok 116 * 3905 ... 4096 are replaces by 8001 ... 8192 117 * 118 * somehow the second read writes into the mmap() before 119 * the sendfile is finished which is very strange. 120 * 121 * if someone finds the reason for this, feel free to remove 122 * this if again and number of reduce the syscalls a bit. 123 */ 124 if (-1 != c->file.copy.fd) { 125 munmap(c->file.mmap.start, c->file.mmap.length); 126 127 close(c->file.copy.fd); 128 c->file.copy.fd = -1; 129 } 130 131 /* do we have a IOCB we can use ? */ 132 133 for (iocb_ndx = 0; async_error == 0 && iocb_ndx < POSIX_AIO_MAX_IOCBS; iocb_ndx++) { 134 if (NULL == srv->posix_aio_data[iocb_ndx]) { 135 break; 136 } 137 } 138 139 if (iocb_ndx == POSIX_AIO_MAX_IOCBS) { 140 async_error = 1; 141 } 142 143 144 /* get mmap()ed mem-block in /dev/shm 145 * 146 * in case we don't have a iocb available, we still need the mmap() for the blocking 147 * read() 148 * */ 149 if (-1 == c->file.copy.fd ) { 150 int mmap_fd = -1; 151 152 /* open a file in /dev/shm to write to */ 153 if (-1 == (mmap_fd = open("/dev/zero", O_RDWR))) { 154 async_error = 1; 155 156 if (errno != EMFILE) { 157 TRACE("open(/dev/zero) returned: %d (%s), open fds: %d, falling back to sync-io", 158 errno, strerror(errno), srv->cur_fds); 159 } else { 160 return NETWORK_STATUS_WAIT_FOR_FD; 161 } 162 } else { 163 c->file.mmap.offset = 0; 164 c->file.mmap.length = c->file.copy.length; /* align to page-size */ 165 166 c->file.mmap.start = mmap(0, c->file.mmap.length, 167 PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, 0); 168 if (c->file.mmap.start == MAP_FAILED) { 169 async_error = 1; 170 } 171 172 close(mmap_fd); 173 mmap_fd = -1; 174 } 175 } 176 177 178 /* looks like we couldn't get a temp-file [disk-full] */ 179 if (async_error == 0 && c->file.mmap.start != MAP_FAILED) { 180 struct aiocb *iocb = NULL; 181 182 assert(c->file.copy.length > 0); 183 184 &n
