nginx-0.0.1-2003-11-27-10:45:22 import

This commit is contained in:
Igor Sysoev 2003-11-27 07:45:22 +00:00
parent c0f8d91bde
commit 0e499db3ed
14 changed files with 319 additions and 204 deletions

View File

@ -15,7 +15,7 @@ do
echo "printf(\"${FMT}\", ($NGX_TYPE) $NGX_MAX_SIZE);" >> autotest.c echo "printf(\"${FMT}\", ($NGX_TYPE) $NGX_MAX_SIZE);" >> autotest.c
echo "return 0; }" >> autotest.c echo "return 0; }" >> autotest.c
eval "$CC_WARN $CC_TEST_FLAGS -o autotest autotest.c > /dev/null 2>&1" eval "$CC_WARN $CC_TEST_FLAGS -o autotest autotest.c > $NGX_ERR 2>&1"
MAX_SIZE=`echo $NGX_MAX_SIZE | sed -e "s/L*\$//"` MAX_SIZE=`echo $NGX_MAX_SIZE | sed -e "s/L*\$//"`

View File

@ -1,13 +1,15 @@
echo "checking for $NGX_FUNC" echo "checking for $NGX_FUNC"
NGX_FOUND=NO
func=`echo $NGX_FUNC | sed -e 's/()$//' | tr '[a-z]' '[A-Z]'` func=`echo $NGX_FUNC | sed -e 's/()$//' | tr '[a-z]' '[A-Z]'`
echo "$NGX_UNISTD_H" > autotest.c echo "$NGX_UNISTD_H" > autotest.c
echo "$NGX_FUNC_INC" >> autotest.c echo "$NGX_FUNC_INC" >> autotest.c
echo "int main() { $NGX_FUNC_TEST; return 0; }" >> autotest.c echo "int main() { $NGX_FUNC_TEST; return 0; }" >> autotest.c
eval "$CC $CC_TEST_FLAGS -o autotest autotest.c > /dev/null 2>&1" eval "$CC $CC_TEST_FLAGS -o autotest autotest.c > $NGX_ERR 2>&1"
if [ -x autotest ]; then if [ -x autotest ]; then
echo " + $NGX_FUNC found" echo " + $NGX_FUNC found"
@ -16,6 +18,9 @@ if [ -x autotest ]; then
echo "#define HAVE_$func 1" >> $NGX_AUTO_CONFIG_H echo "#define HAVE_$func 1" >> $NGX_AUTO_CONFIG_H
echo "#endif" >> $NGX_AUTO_CONFIG_H echo "#endif" >> $NGX_AUTO_CONFIG_H
echo >> $NGX_AUTO_CONFIG_H echo >> $NGX_AUTO_CONFIG_H
NGX_FOUND=YES
else else
echo " + $NGX_FUNC not found" echo " + $NGX_FUNC not found"
fi fi

View File

@ -1,7 +1,9 @@
echo "checking for $NGX_INC" echo "checking for $NGX_INC"
inc=`echo $NGX_INC | sed -e 's/\./_/' | tr '[a-z]' '[A-Z]'` NGX_FOUND=NO
inc=`echo $NGX_INC | sed -e 's/\./_/' | sed -e 's/\//_/' | tr '[a-z]' '[A-Z]'`
echo "#include <$NGX_INC>" > autotest.c echo "#include <$NGX_INC>" > autotest.c
echo "int main() { return 0; }" >> autotest.c echo "int main() { return 0; }" >> autotest.c
@ -17,6 +19,7 @@ if [ -x autotest ]; then
echo >> $NGX_AUTO_CONFIG_H echo >> $NGX_AUTO_CONFIG_H
eval "NGX_$inc='#include <$NGX_INC>'" eval "NGX_$inc='#include <$NGX_INC>'"
NGX_FOUND=YES
else else
echo " + $NGX_INC not found" echo " + $NGX_INC not found"

View File

@ -11,8 +11,24 @@ CC_TEST_FLAGS="-D_FILE_OFFSET_BITS=64"
CORE_LIBS="$CORE_LIBS -lsocket -lnsl" CORE_LIBS="$CORE_LIBS -lsocket -lnsl"
# STUB
CFLAGS="$CFLAGS -D HAVE_DEVPOLL=1" NGX_INC="sys/devpoll.h"; . auto/inc
EVENT_MODULES="$EVENT_MODULES $DEVPOLL_MODULE"
CORE_SRCS="$CORE_SRCS $DEVPOLL_SRCS" if [ $NGX_FOUND=YES ]; then
#CORE_SRCS="$CORE_SRCS $LINUX_SENDFILE_SRCS" CFLAGS="$CFLAGS -D HAVE_DEVPOLL=1"
EVENT_MODULES="$EVENT_MODULES $DEVPOLL_MODULE"
CORE_SRCS="$CORE_SRCS $DEVPOLL_SRCS"
fi
NGX_FUNC_INC="#include <sys/sendfile.h>"
NGX_FUNC_TEST="int fd = 1; sendfilevec_t vec[1];
size_t sent = 1; ssize_t n;
n = sendfilev(fd, vec, 1, &sent)"
NGX_FUNC="sendfilev()"; . auto/func
if [ $NGX_FOUND=YES ]; then
CFLAGS="$CFLAGS -D HAVE_SENDFILE=1"
CORE_SRCS="$CORE_SRCS $SOLARIS_SENDFILEV_SRCS"
CORE_LIBS="$CORE_LIBS -lsendfile"
fi

View File

@ -107,7 +107,7 @@ LINUX_SENDFILE_SRCS=src/os/unix/ngx_linux_sendfile_chain.c
SOLARIS_DEPS=src/os/unix/ngx_solaris_config.h SOLARIS_DEPS=src/os/unix/ngx_solaris_config.h
SOLARIS_SRCS=src/os/unix/ngx_solaris_init.c SOLARIS_SRCS=src/os/unix/ngx_solaris_init.c
SOLARIS_SENDFILE_SRCS=src/os/unix/ngx_solaris_sendfilev_chain.c SOLARIS_SENDFILEV_SRCS=src/os/unix/ngx_solaris_sendfilev_chain.c
WIN32_INCS="$CORE_INCS $EVENT_INCS -I src/os/win32" WIN32_INCS="$CORE_INCS $EVENT_INCS -I src/os/win32"

View File

@ -39,12 +39,13 @@ ngx_module_t ngx_http_static_module = {
}; };
int ngx_http_static_translate_handler(ngx_http_request_t *r) ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r)
{ {
int rc, level; ngx_int_t rc, level;
uint32_t crc;
char *location, *last; char *location, *last;
ngx_err_t err; ngx_err_t err;
ngx_http_cache_ctx_t ctx; ngx_http_cache_t *cache;
ngx_http_cache_conf_t *ccf; ngx_http_cache_conf_t *ccf;
ngx_http_core_loc_conf_t *clcf; ngx_http_core_loc_conf_t *clcf;
@ -87,23 +88,16 @@ int ngx_http_static_translate_handler(ngx_http_request_t *r)
ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
/* STUB */
ccf = NULL;
ctx.key.len = 0;
#if 0
ccf = ngx_http_get_module_loc_conf(r, ngx_http_cache_module); ccf = ngx_http_get_module_loc_conf(r, ngx_http_cache_module);
if (ccf->open_files) { if (ccf->open_files) {
ctx->hash = ccf->open_files; cache = ngx_http_cache_get(ccf->open_files, &r->file.name, &crc);
ctx->key = r->file.name;
cache = ngx_http_cache_get_data(r, ctx); ngx_log_debug(r->connection->log, "cache get: %x" _ cache);
if (cache if (cache
&& ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)
|| ccf->hash->life_time >= ngx_time() - cache->updated)) || ccf->open_files->check_time >= ngx_time() - cache->updated))
{ {
cache->refs++; cache->refs++;
r->file.fd = cache->fd; r->file.fd = cache->fd;
@ -117,8 +111,6 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
cache = NULL; cache = NULL;
} }
#endif
#if (WIN9X) #if (WIN9X)
if (ngx_win32_version < NGX_WIN_NT) { if (ngx_win32_version < NGX_WIN_NT) {
@ -215,6 +207,23 @@ ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd);
r->file.info_valid = 1; r->file.info_valid = 1;
} }
if (ccf->open_files) {
if (cache == NULL) {
cache = ngx_http_cache_alloc(ccf->open_files, &r->file.name, crc,
r->connection->log);
}
ngx_log_debug(r->connection->log, "cache alloc: %x" _ cache);
if (cache) {
cache->fd = r->file.fd;
cache->data.size = ngx_file_size(&r->file.info);
cache->accessed = ngx_time();
cache->last_modified = ngx_file_mtime(&r->file.info);
cache->updated = ngx_time();
}
}
if (ngx_is_dir(&r->file.info)) { if (ngx_is_dir(&r->file.info)) {
ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);

View File

@ -6,9 +6,11 @@
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_garbage_collector.h> #include <ngx_garbage_collector.h>
typedef struct ngx_http_request_s ngx_http_request_t;
#include <ngx_http_cache.h>
#include <ngx_http_request.h> #include <ngx_http_request.h>
#include <ngx_http_config.h> #include <ngx_http_config.h>
#include <ngx_http_cache.h>
#include <ngx_http_busy_lock.h> #include <ngx_http_busy_lock.h>
#include <ngx_http_filter.h> #include <ngx_http_filter.h>
#include <ngx_http_log_handler.h> #include <ngx_http_log_handler.h>

View File

@ -80,81 +80,87 @@ ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data);
} }
int ngx_http_cache_get_data(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *cache,
ngx_str_t *key, uint32_t *crc)
{ {
ngx_uint_t n, i; ngx_uint_t i;
ngx_http_cache_t *c;
ctx->crc = ngx_crc(ctx->key.data, ctx->key.len); *crc = ngx_crc(key->data, key->len);
n = ctx->crc % ctx->hash->hash; c = cache->elts
for (i = 0; i < ctx->hash->nelts; i++) { + *crc % cache->hash * cache->nelts * sizeof(ngx_http_cache_t);
if (ctx->hash->cache[n][i].crc == ctx->crc
&& ctx->hash->cache[n][i].key.len == ctx->key.len for (i = 0; i < cache->nelts; i++) {
&& ngx_rstrncmp(ctx->hash->cache[n][i].key.data, ctx->key.data, if (c[i].crc == *crc
ctx->key.len) == 0) && c[i].key.len == key->len
&& ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0)
{ {
ctx->cache = ctx->hash->cache[n][i].data; c[i].refs++;
ctx->hash->cache[n][i].refs++; return &c[i];
return NGX_OK;
} }
} }
return NGX_DECLINED; return NULL;
} }
ngx_http_cache_entry_t *ngx_http_cache_get_entry(ngx_http_request_t *r, ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *cache,
ngx_http_cache_ctx_t *ctx) ngx_str_t *key, uint32_t crc,
ngx_log_t *log)
{ {
time_t old; time_t old;
ngx_uint_t n, i; ngx_uint_t i;
ngx_http_cache_entry_t *ce; ngx_http_cache_t *c, *found;
old = ngx_time() + 1; old = ngx_time() + 1;
ce = NULL; found = NULL;
n = ctx->crc % ctx->hash->hash; c = cache->elts
for (i = 0; i < ctx->hash->nelts; i++) { + crc % cache->hash * cache->nelts * sizeof(ngx_http_cache_t);
if (ctx->hash->cache[n][i].key.data == NULL) {
for (i = 0; i < cache->nelts; i++) {
if (c[i].key.data == NULL) {
/* a free entry is found */ /* a free entry is found */
ce = &ctx->hash->cache[n][i]; found = &c[i];
break; break;
} }
if (ctx->hash->cache[n][i].refs == 0 /* looking for the oldest cache entry that is not been using */
&& old > ctx->hash->cache[n][i].accessed)
{
/* looking for the oldest cache entry that is not used right now */
old = ctx->hash->cache[n][i].accessed; if (c[i].refs == 0 && old > c[i].accessed) {
ce = &ctx->hash->cache[n][i];
old = c[i].accessed;
found = &c[i];
} }
} }
if (ce) { if (found) {
if (ce->key.data) { if (found->key.data) {
if (ctx->key.len > ce->key.len) { if (key->len > found->key.len) {
ngx_free(ce->key.data); ngx_free(found->key.data);
ce->key.data = NULL; found->key.data = NULL;
} }
} }
if (ce->key.data) { if (found->key.data == NULL) {
ce->key.data = ngx_alloc(ctx->key.len, r->connection->log); found->key.data = ngx_alloc(key->len, log);
if (ce->key.data == NULL) { if (found->key.data == NULL) {
return NULL; return NULL;
} }
} }
ngx_memcpy(ce->key.data, ctx->key.data, ctx->key.len); ngx_memcpy(found->key.data, key->data, key->len);
ce->key.len = ctx->key.len; found->crc = crc;
ce->crc = ctx->crc; found->key.len = key->len;
found->refs = 1;
found->deleted = 0;
} }
return ce; return found;
} }
@ -373,24 +379,25 @@ static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
ngx_http_cache_conf_t *prev = parent; ngx_http_cache_conf_t *prev = parent;
ngx_http_cache_conf_t *conf = child; ngx_http_cache_conf_t *conf = child;
if (conf->hash == NULL) { if (conf->open_files == NULL) {
if (prev->hash) { if (prev->open_files) {
conf->hash = prev->hash; conf->open_files = prev->open_files;
} else { } else {
conf->hash = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_hash_t)); conf->open_files = ngx_pcalloc(cf->pool,
if (conf->hash == NULL) { sizeof(ngx_http_cache_hash_t));
if (conf->open_files == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
conf->hash->hash = NGX_HTTP_CACHE_HASH; conf->open_files->hash = NGX_HTTP_CACHE_HASH;
conf->hash->nelts = NGX_HTTP_CACHE_NELTS; conf->open_files->nelts = NGX_HTTP_CACHE_NELTS;
conf->hash->cache = ngx_pcalloc(cf->pool, conf->open_files->elts = ngx_pcalloc(cf->pool,
NGX_HTTP_CACHE_HASH NGX_HTTP_CACHE_HASH
* NGX_HTTP_CACHE_NELTS * NGX_HTTP_CACHE_NELTS
* sizeof(ngx_http_cache_entry_t)); * sizeof(ngx_http_cache_t));
if (conf->hash->cache == NULL) { if (conf->open_files->elts == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
} }
@ -398,103 +405,3 @@ static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
return NGX_CONF_OK; return NGX_CONF_OK;
} }
#if 0
/*
* small file in malloc()ed memory, mmap()ed file, file descriptor only,
* file access time only (to estimate could pages still be in memory),
* translated URI (ngx_http_index_hanlder),
* compiled script (ngx_http_ssi_filter).
*/
#define NGX_HTTP_CACHE_ENTRY_DELETED 0x00000001
#define NGX_HTTP_CACHE_ENTRY_MMAPED 0x00000002
/* "/" -> "/index.html" in ngx_http_index_handler */
#define NGX_HTTP_CACHE_ENTRY_URI 0x00000004
/* 301 location "/dir" -> "dir/" in ngx_http_core_handler */
/* compiled script in ngx_http_ssi_filter */
#define NGX_HTTP_CACHE_ENTRY_SCRIPT 0x00000008
#define NGX_HTTP_CACHE_FILTER_FLAGS 0xFFFF0000
typedef struct {
ngx_fd_t fd;
off_t size;
void *data;
time_t accessed;
time_t last_modified;
time_t updated; /* no needed with kqueue */
int refs;
int flags;
} ngx_http_cache_entry_t;
typedef struct {
uint32_t crc;
ngx_str_t uri;
ngx_http_cache_t *cache;
} ngx_http_cache_hash_entry_t;
typedef struct {
ngx_http_cache_t *cache;
uint32_t crc;
int n;
} ngx_http_cache_handle_t;
int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash,
ngx_str_t *uri, ngx_http_cache_handle_t *h)
{
int hi;
ngx_http_cache_hash_entry_t *entry;
h->crc = ngx_crc(uri->data, uri->len);
hi = h->crc % cache_hash->size;
entry = cache_hash[hi].elts;
for (i = 0; i < cache_hash[hi].nelts; i++) {
if (entry[i].crc == crc
&& entry[i].uri.len == uri->len
&& ngx_strncmp(entry[i].uri.data, uri->data, uri->len) == 0
{
h->cache = entry[i].cache;
h->cache->refs++;
h->n = hi;
return NGX_OK;
}
}
return NGX_ERROR;
}
/* 32-bit crc16 */
int ngx_crc(char *data, size_t len)
{
uint32_t sum;
for (sum = 0; len; len--) {
/*
* gcc 2.95.2 x86 and icc 7.1.006 compile that operator
* into the single rol opcode.
* msvc 6.0sp2 compiles it into four opcodes.
*/
sum = sum >> 1 | sum << 31;
sum += *data++;
}
return sum;
}
#endif

View File

@ -7,6 +7,26 @@
#include <ngx_http.h> #include <ngx_http.h>
typedef struct {
uint32_t crc;
ngx_str_t key;
time_t accessed;
unsigned refs:20; /* 1048576 references */
unsigned count:2; /* lazy allocation: the 4 uses */
unsigned deleted:1;
ngx_fd_t fd;
time_t last_modified;
time_t updated;
union {
off_t size;
ngx_str_t value;
} data;
} ngx_http_cache_t;
typedef struct { typedef struct {
time_t expires; time_t expires;
time_t last_modified; time_t last_modified;
@ -17,24 +37,11 @@ typedef struct {
} ngx_http_cache_header_t; } ngx_http_cache_header_t;
typedef struct { #define NGX_HTTP_CACHE_HASH 7
uint32_t crc;
ngx_str_t key;
ngx_fd_t fd;
off_t size;
void *data; /* mmap, memory */
time_t accessed;
time_t last_modified;
time_t updated; /* no needed with kqueue */
int refs;
int flags;
} ngx_http_cache_entry_t;
#define NGX_HTTP_CACHE_HASH 1021
#define NGX_HTTP_CACHE_NELTS 4 #define NGX_HTTP_CACHE_NELTS 4
typedef struct { typedef struct {
ngx_http_cache_entry_t **cache; ngx_http_cache_t *elts;
size_t hash; size_t hash;
size_t nelts; size_t nelts;
time_t life_time; time_t life_time;
@ -45,12 +52,7 @@ typedef struct {
typedef struct { typedef struct {
ngx_http_cache_hash_t *hash; ngx_http_cache_hash_t *hash;
} ngx_http_cache_conf_t; ngx_http_cache_t *cache;
typedef struct {
ngx_http_cache_hash_t *hash;
ngx_http_cache_entry_t *cache;
ngx_file_t file; ngx_file_t file;
ngx_str_t key; ngx_str_t key;
uint32_t crc; uint32_t crc;
@ -67,6 +69,11 @@ typedef struct {
} ngx_http_cache_ctx_t; } ngx_http_cache_ctx_t;
typedef struct {
ngx_http_cache_hash_t *open_files;
} ngx_http_cache_conf_t;
#define NGX_HTTP_CACHE_STALE 1 #define NGX_HTTP_CACHE_STALE 1
#define NGX_HTTP_CACHE_AGED 2 #define NGX_HTTP_CACHE_AGED 2
#define NGX_HTTP_CACHE_THE_SAME 3 #define NGX_HTTP_CACHE_THE_SAME 3
@ -74,11 +81,20 @@ typedef struct {
int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx); int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx);
int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq); int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq);
int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name,
ngx_dir_t *dir);
int ngx_http_cache_update_file(ngx_http_request_t *r,ngx_http_cache_ctx_t *ctx, int ngx_http_cache_update_file(ngx_http_request_t *r,ngx_http_cache_ctx_t *ctx,
ngx_str_t *temp_file); ngx_str_t *temp_file);
ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *cache,
ngx_str_t *key, uint32_t *crc);
ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *cache,
ngx_str_t *key, uint32_t crc,
ngx_log_t *log);
int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name,
ngx_dir_t *dir);
extern ngx_module_t ngx_http_cache_module;
#endif /* _NGX_HTTP_CACHE_H_INCLUDED_ */ #endif /* _NGX_HTTP_CACHE_H_INCLUDED_ */

View File

@ -144,8 +144,6 @@ typedef struct {
} ngx_http_headers_out_t; } ngx_http_headers_out_t;
typedef struct ngx_http_request_s ngx_http_request_t;
typedef int (*ngx_http_handler_pt)(ngx_http_request_t *r); typedef int (*ngx_http_handler_pt)(ngx_http_request_t *r);
struct ngx_http_request_s { struct ngx_http_request_s {
@ -156,6 +154,8 @@ struct ngx_http_request_s {
void **srv_conf; void **srv_conf;
void **loc_conf; void **loc_conf;
ngx_http_cache_t *cache;
ngx_file_t file; ngx_file_t file;
ngx_pool_t *pool; ngx_pool_t *pool;

View File

@ -192,7 +192,8 @@ ngx_log_debug(c->log, "NOPUSH");
if (err == NGX_EAGAIN || err == NGX_EINTR) { if (err == NGX_EAGAIN || err == NGX_EINTR) {
ngx_log_error(NGX_LOG_INFO, c->log, err, ngx_log_error(NGX_LOG_INFO, c->log, err,
"sendfile() sent only %qd bytes", sent); "sendfile() sent only " OFF_T_FMT " bytes",
sent);
} else { } else {
wev->error = 1; wev->error = 1;

View File

@ -0,0 +1,8 @@
#ifndef _NGX_SOLARIS_H_INCLUDED_
#define _NGX_SOLARIS_H_INCLUDED_
ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in);
#endif /* _NGX_SOLARIS_H_INCLUDED_ */

View File

@ -23,6 +23,7 @@
#include <sys/filio.h> /* FIONBIO */ #include <sys/filio.h> /* FIONBIO */
#include <sys/stropts.h> /* INFTIM */ #include <sys/stropts.h> /* INFTIM */
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sendfile.h>
#include <sys/systeminfo.h> #include <sys/systeminfo.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>

View File

@ -0,0 +1,147 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
{
int fd;
char *prev;
off_t fprev;
size_t sent;
ssize_t n;
ngx_int_t eintr;
sendfilevec_t *sfv;
ngx_array_t vec;
ngx_event_t *wev;
ngx_chain_t *cl;
wev = c->write;
if (!wev->ready) {
return in;
}
do {
fd = SFV_FD_SELF;
prev = NULL;
sfv = NULL;
eintr = 0;
sent = 0;
/* create the sendfilevec and coalesce the neighbouring hunks */
for (cl = in; cl; cl = cl->next) {
if (ngx_hunk_special(cl->hunk)) {
continue;
}
if (ngx_hunk_in_memory_only(cl->hunk)) {
fd = SFV_FD_SELF;
if (prev == cl->hunk->pos) {
sfv->sfv_len += cl->hunk->last - cl->hunk->pos;
} else {
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
sfv->sfv_fd = SFV_FD_SELF;
sfv->sfv_flag = 0;
sfv->sfv_off = cl->hunk->pos;
sfv->sfv_len = cl->hunk->last - cl->hunk->pos;
}
prev = cl->hunk->last;
} else {
prev = NULL;
if (fd == cl->hunk->file->fd && fprev == cl->hunk->file_pos) {
sfv->sfv_len += cl->hunk->file_last - cl->hunk->file_pos;
} else {
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
fd = cl->hunk->file->fd;
sfv->sfv_fd = fd;
sfv->sfv_flag = 0;
sfv->sfv_off = cl->hunk->file_pos;
sfv->sfv_len = cl->hunk->file_last - cl->hunk->file_pos;
}
fprev = cl->hunk->file_last;
}
}
n = sendfile(c->fd, vec->elts, vec->nelts, &sent);
if (n == -1) {
err = ngx_errno;
if (err == NGX_EINTR) {
eintr = 1;
}
if (err == NGX_EAGAIN || err == NGX_EINTR) {
ngx_log_error(NGX_LOG_INFO, c->log, err,
"sendfilev() sent only " SIZE_T_FMT " bytes",
sent);
} else {
wev->error = 1;
ngx_log_error(NGX_LOG_CRIT, c->log, err, "sendfilev() failed");
return NGX_CHAIN_ERROR;
}
}
#if (NGX_DEBUG_WRITE_CHAIN)
ngx_log_debug(c->log, "sendfilev: %d " SIZE_T_FMT ", n _ sent);
#endif
c->sent += sent;
for (cl = in; cl; cl = cl->next) {
if (ngx_hunk_special(cl->hunk)) {
continue;
}
if (sent == 0) {
break;
}
size = ngx_hunk_size(cl->hunk);
if (sent >= size) {
sent -= size;
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
cl->hunk->pos = cl->hunk->last;
}
if (cl->hunk->type & NGX_HUNK_FILE) {
cl->hunk->file_pos = cl->hunk->file_last;
}
continue;
}
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
cl->hunk->pos += sent;
}
if (cl->hunk->type & NGX_HUNK_FILE) {
cl->hunk->file_pos += sent;
}
break;
}
in = cl;
} while (eintr);
if (in) {
wev->ready = 0;
}
return in;
}