summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2011-04-04 12:50:30 +0000
committerJonathan Kolb <jon@b0g.us>2011-04-04 12:50:30 +0000
commitf241ce02a4e7971bf509ea005b4791812d54c522 (patch)
tree995761817026a7147e180731e9ccd2293326bfbb
parentbe28c50206ac6f3f1bbbede6a495f5d0b5abad70 (diff)
downloadnginx-0.9.tar.gz
Changes with nginx 0.9.7 04 Apr 2011v0.9.7nginx-0.9
*) Feature: now keepalive connections may be closed premature, if there are no free worker connections. Thanks to Maxim Dounin. *) Feature: the "rotate" parameter of the "image_filter" directive. Thanks to Adam Bocim. *) Bugfix: a case when a backend in "fastcgi_pass", "scgi_pass", or "uwsgi_pass" directives is given by expression and refers to a defined upstream.
-rw-r--r--CHANGES14
-rw-r--r--CHANGES.ru14
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_connection.c55
-rw-r--r--src/core/ngx_connection.h4
-rw-r--r--src/core/ngx_cycle.c3
-rw-r--r--src/core/ngx_cycle.h2
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c7
-rw-r--r--src/http/modules/ngx_http_image_filter_module.c104
-rw-r--r--src/http/modules/ngx_http_scgi_module.c7
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c7
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_request.c2
-rw-r--r--src/http/ngx_http_upstream.c8
14 files changed, 209 insertions, 24 deletions
diff --git a/CHANGES b/CHANGES
index ddd667c6e..5a4645d8e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,18 @@
+Changes with nginx 0.9.7 04 Apr 2011
+
+ *) Feature: now keepalive connections may be closed premature, if there
+ are no free worker connections.
+ Thanks to Maxim Dounin.
+
+ *) Feature: the "rotate" parameter of the "image_filter" directive.
+ Thanks to Adam Bocim.
+
+ *) Bugfix: a case when a backend in "fastcgi_pass", "scgi_pass", or
+ "uwsgi_pass" directives is given by expression and refers to a
+ defined upstream.
+
+
Changes with nginx 0.9.6 21 Mar 2011
*) Feature: the "map" directive supports regular expressions as value
diff --git a/CHANGES.ru b/CHANGES.ru
index 69b7fa65b..9cf6f4a20 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,18 @@
+Изменения в nginx 0.9.7 04.04.2011
+
+ *) Добавление: теперь соединения в состоянии keepalive могут быть
+ закрыты преждевременно, если у воркера нет свободных соединений.
+ Спасибо Максиму Дунину.
+
+ *) Добавление: параметр rotate директивы image_filter.
+ Спасибо Adam Bocim.
+
+ *) Исправление: ситуации, когда бэкенд в директивах fastcgi_pass,
+ scgi_pass или uwsgi_pass задан выражением и ссылается на описанный
+ upstream.
+
+
Изменения в nginx 0.9.6 21.03.2011
*) Добавление: директива map поддерживает регулярные выражения в
diff --git a/src/core/nginx.h b/src/core/nginx.h
index d69be08e2..d75d4e504 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 9006
-#define NGINX_VERSION "0.9.6"
+#define nginx_version 9007
+#define NGINX_VERSION "0.9.7"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index c495edd52..9f19fcc4f 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -12,6 +12,9 @@
ngx_os_io_t ngx_io;
+static void ngx_drain_connections(void);
+
+
ngx_listening_t *
ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)
{
@@ -719,6 +722,11 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
c = ngx_cycle->free_connections;
if (c == NULL) {
+ ngx_drain_connections();
+ c = ngx_cycle->free_connections;
+ }
+
+ if (c == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"%ui worker_connections are not enough",
ngx_cycle->connection_n);
@@ -861,6 +869,8 @@ ngx_close_connection(ngx_connection_t *c)
#endif
+ ngx_reusable_connection(c, 0);
+
log_error = c->log_error;
ngx_free_connection(c);
@@ -900,6 +910,51 @@ ngx_close_connection(ngx_connection_t *c)
}
+void
+ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
+{
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
+ "reusable connection: %ui", reusable);
+
+ if (c->reusable) {
+ ngx_queue_remove(&c->queue);
+ }
+
+ c->reusable = reusable;
+
+ if (reusable) {
+ /* need cast as ngx_cycle is volatile */
+
+ ngx_queue_insert_head(
+ (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
+ }
+}
+
+
+static void
+ngx_drain_connections(void)
+{
+ ngx_int_t i;
+ ngx_queue_t *q;
+ ngx_connection_t *c;
+
+ for (i = 0; i < 32; i++) {
+ if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) {
+ break;
+ }
+
+ q = ngx_queue_last(&ngx_cycle->reusable_connections_queue);
+ c = ngx_queue_data(q, ngx_connection_t, queue);
+
+ ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
+ "reusing connection");
+
+ c->close = 1;
+ c->read->handler(c->read);
+ }
+}
+
+
ngx_int_t
ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
ngx_uint_t port)
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 3837fd255..f9bf50401 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -135,6 +135,8 @@ struct ngx_connection_s {
ngx_buf_t *buffer;
+ ngx_queue_t queue;
+
ngx_atomic_uint_t number;
ngx_uint_t requests;
@@ -150,6 +152,7 @@ struct ngx_connection_s {
unsigned destroyed:1;
unsigned idle:1;
+ unsigned reusable:1;
unsigned close:1;
unsigned sendfile:1;
@@ -186,5 +189,6 @@ ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text);
ngx_connection_t *ngx_get_connection(ngx_socket_t s, ngx_log_t *log);
void ngx_free_connection(ngx_connection_t *c);
+void ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable);
#endif /* _NGX_CONNECTION_H_INCLUDED_ */
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 357c6b284..79867079d 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -181,6 +181,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
cycle->listening.pool = pool;
+ ngx_queue_init(&cycle->reusable_connections_queue);
+
+
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h
index d96c85ffa..e14983d6f 100644
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -44,6 +44,8 @@ struct ngx_cycle_s {
ngx_connection_t *free_connections;
ngx_uint_t free_connection_n;
+ ngx_queue_t reusable_connections_queue;
+
ngx_array_t listening;
ngx_array_t pathes;
ngx_list_t open_files;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 12a1e81d8..12d5b1d8f 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -636,12 +636,6 @@ ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
return NGX_ERROR;
}
- if (url.no_port) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no port in upstream \"%V\"", &url.url);
- return NGX_ERROR;
- }
-
u = r->upstream;
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
@@ -658,6 +652,7 @@ ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
} else {
u->resolved->host = url.host;
u->resolved->port = url.port;
+ u->resolved->no_port = url.no_port;
}
return NGX_OK;
diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c
index 37011f2be..de1634a86 100644
--- a/src/http/modules/ngx_http_image_filter_module.c
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -16,6 +16,7 @@
#define NGX_HTTP_IMAGE_SIZE 2
#define NGX_HTTP_IMAGE_RESIZE 3
#define NGX_HTTP_IMAGE_CROP 4
+#define NGX_HTTP_IMAGE_ROTATE 5
#define NGX_HTTP_IMAGE_START 0
@@ -38,12 +39,14 @@ typedef struct {
ngx_uint_t filter;
ngx_uint_t width;
ngx_uint_t height;
+ ngx_uint_t angle;
ngx_uint_t jpeg_quality;
ngx_flag_t transparency;
ngx_http_complex_value_t *wcv;
ngx_http_complex_value_t *hcv;
+ ngx_http_complex_value_t *acv;
ngx_http_complex_value_t *jqcv;
size_t buffer_size;
@@ -58,9 +61,9 @@ typedef struct {
ngx_uint_t width;
ngx_uint_t height;
-
ngx_uint_t max_width;
ngx_uint_t max_height;
+ ngx_uint_t angle;
ngx_uint_t phase;
ngx_uint_t type;
@@ -108,7 +111,7 @@ static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf);
static ngx_command_t ngx_http_image_filter_commands[] = {
{ ngx_string("image_filter"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13,
+ NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13|NGX_CONF_TAKE2,
ngx_http_image_filter,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -492,6 +495,17 @@ ngx_http_image_process(ngx_http_request_t *r)
return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL);
}
+ ctx->angle = ngx_http_image_filter_get_value(r, conf->acv, conf->angle);
+
+ if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
+
+ if (ctx->angle != 90 && ctx->angle != 180 && ctx->angle != 270) {
+ return NULL;
+ }
+
+ return ngx_http_image_resize(r, ctx);
+ }
+
ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width);
if (ctx->max_width == 0) {
return NULL;
@@ -506,6 +520,7 @@ ngx_http_image_process(ngx_http_request_t *r)
if (rc == NGX_OK
&& ctx->width <= ctx->max_width
&& ctx->height <= ctx->max_height
+ && ctx->angle == 0
&& !ctx->force)
{
return ngx_http_image_asis(r, ctx);
@@ -710,7 +725,7 @@ ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
{
int sx, sy, dx, dy, ox, oy, size,
colors, palette, transparent,
- red, green, blue;
+ red, green, blue, t;
u_char *out;
ngx_buf_t *b;
ngx_uint_t resize;
@@ -730,6 +745,7 @@ ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
if (!ctx->force
+ && ctx->angle == 0
&& (ngx_uint_t) sx <= ctx->max_width
&& (ngx_uint_t) sy <= ctx->max_height)
{
@@ -781,6 +797,10 @@ transparent:
resize = 1;
+ } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
+
+ resize = 0;
+
} else { /* NGX_HTTP_IMAGE_CROP */
resize = 0;
@@ -829,6 +849,38 @@ transparent:
dst = src;
}
+ if (ctx->angle) {
+ src = dst;
+
+ switch (ctx->angle) {
+
+ case 90:
+ case 270:
+ dst = ngx_http_image_new(r, dy, dx, palette);
+ if (dst == NULL) {
+ gdImageDestroy(src);
+ return NULL;
+ }
+ gdImageCopyRotated(dst, src, dy/2, dx/2, 0, 0, dx, dy, ctx->angle);
+ gdImageDestroy(src);
+ break;
+
+ case 180:
+ dst = ngx_http_image_new(r, dx, dy, palette);
+ if (dst == NULL) {
+ gdImageDestroy(src);
+ return NULL;
+ }
+ gdImageCopyRotated(dst, src, dx/2, dy/2, 0, 0, dx, dy, ctx->angle);
+ gdImageDestroy(src);
+ break;
+ }
+
+ t = dx;
+ dx = dy;
+ dy = t;
+ }
+
if (conf->filter == NGX_HTTP_IMAGE_CROP) {
src = dst;
@@ -1090,6 +1142,7 @@ ngx_http_image_filter_create_conf(ngx_conf_t *cf)
conf->filter = NGX_CONF_UNSET_UINT;
conf->jpeg_quality = NGX_CONF_UNSET_UINT;
+ conf->angle = NGX_CONF_UNSET_UINT;
conf->transparency = NGX_CONF_UNSET;
conf->buffer_size = NGX_CONF_UNSET_SIZE;
@@ -1124,6 +1177,11 @@ ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
conf->jqcv = prev->jqcv;
}
+ ngx_conf_merge_uint_value(conf->angle, prev->angle, 0);
+ if (conf->acv == NULL) {
+ conf->acv = prev->acv;
+ }
+
ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
@@ -1163,6 +1221,46 @@ ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
return NGX_CONF_OK;
+
+ } else if (cf->args->nelts == 3) {
+
+ if (ngx_strcmp(value[i].data, "rotate") == 0) {
+ imcf->filter = NGX_HTTP_IMAGE_ROTATE;
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[++i];
+ ccv.complex_value = &cv;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (cv.lengths == NULL) {
+ n = ngx_http_image_filter_value(&value[i]);
+
+ if (n != 90 && n != 180 && n != 270) {
+ goto failed;
+ }
+
+ imcf->angle = (ngx_uint_t) n;
+
+ } else {
+ imcf->acv = ngx_palloc(cf->pool,
+ sizeof(ngx_http_complex_value_t));
+ if (imcf->acv == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *imcf->acv = cv;
+ }
+
+ return NGX_CONF_OK;
+
+ } else {
+ goto failed;
+ }
}
if (ngx_strcmp(value[i].data, "resize") == 0) {
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index d831e27c2..d745551f2 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -458,12 +458,6 @@ ngx_http_scgi_eval(ngx_http_request_t *r, ngx_http_scgi_loc_conf_t * scf)
return NGX_ERROR;
}
- if (url.no_port) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no port in upstream \"%V\"", &url.url);
- return NGX_ERROR;
- }
-
u = r->upstream;
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
@@ -480,6 +474,7 @@ ngx_http_scgi_eval(ngx_http_request_t *r, ngx_http_scgi_loc_conf_t * scf)
} else {
u->resolved->host = url.host;
u->resolved->port = url.port;
+ u->resolved->no_port = url.no_port;
}
return NGX_OK;
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index a2529131b..cd3c7c124 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -491,12 +491,6 @@ ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
return NGX_ERROR;
}
- if (url.no_port) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no port in upstream \"%V\"", &url.url);
- return NGX_ERROR;
- }
-
u = r->upstream;
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
@@ -513,6 +507,7 @@ ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
} else {
u->resolved->host = url.host;
u->resolved->port = url.port;
+ u->resolved->no_port = url.no_port;
}
return NGX_OK;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index ed3a14eea..5e57fc746 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.9.6';
+our $VERSION = '0.9.7';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index bd51e061f..2cef4fa5b 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2594,6 +2594,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
#endif
c->idle = 1;
+ ngx_reusable_connection(c, 1);
if (rev->ready) {
ngx_post_event(rev, &ngx_posted_events);
@@ -2703,6 +2704,7 @@ ngx_http_keepalive_handler(ngx_event_t *rev)
c->log->action = "reading client request line";
c->idle = 0;
+ ngx_reusable_connection(c, 0);
ngx_http_init_request(rev);
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index e8d87738f..dc2d0c0fe 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -574,6 +574,14 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
}
}
+ if (u->resolved->port == 0) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "no port in upstream \"%V\"", host);
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
temp.name = *host;
ctx = ngx_resolve_start(clcf->resolver, &temp);