mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 17:52:38 +08:00
Removed busy locks.
This commit is contained in:
parent
f8d10849ad
commit
babd64e344
@ -92,14 +92,12 @@ EVENT_INCS="src/event src/event/modules"
|
|||||||
EVENT_DEPS="src/event/ngx_event.h \
|
EVENT_DEPS="src/event/ngx_event.h \
|
||||||
src/event/ngx_event_timer.h \
|
src/event/ngx_event_timer.h \
|
||||||
src/event/ngx_event_posted.h \
|
src/event/ngx_event_posted.h \
|
||||||
src/event/ngx_event_busy_lock.h \
|
|
||||||
src/event/ngx_event_connect.h \
|
src/event/ngx_event_connect.h \
|
||||||
src/event/ngx_event_pipe.h"
|
src/event/ngx_event_pipe.h"
|
||||||
|
|
||||||
EVENT_SRCS="src/event/ngx_event.c \
|
EVENT_SRCS="src/event/ngx_event.c \
|
||||||
src/event/ngx_event_timer.c \
|
src/event/ngx_event_timer.c \
|
||||||
src/event/ngx_event_posted.c \
|
src/event/ngx_event_posted.c \
|
||||||
src/event/ngx_event_busy_lock.c \
|
|
||||||
src/event/ngx_event_accept.c \
|
src/event/ngx_event_accept.c \
|
||||||
src/event/ngx_event_connect.c \
|
src/event/ngx_event_connect.c \
|
||||||
src/event/ngx_event_pipe.c"
|
src/event/ngx_event_pipe.c"
|
||||||
@ -297,8 +295,7 @@ HTTP_DEPS="src/http/ngx_http.h \
|
|||||||
src/http/ngx_http_variables.h \
|
src/http/ngx_http_variables.h \
|
||||||
src/http/ngx_http_script.h \
|
src/http/ngx_http_script.h \
|
||||||
src/http/ngx_http_upstream.h \
|
src/http/ngx_http_upstream.h \
|
||||||
src/http/ngx_http_upstream_round_robin.h \
|
src/http/ngx_http_upstream_round_robin.h"
|
||||||
src/http/ngx_http_busy_lock.h"
|
|
||||||
|
|
||||||
HTTP_SRCS="src/http/ngx_http.c \
|
HTTP_SRCS="src/http/ngx_http.c \
|
||||||
src/http/ngx_http_core_module.c \
|
src/http/ngx_http_core_module.c \
|
||||||
@ -322,9 +319,6 @@ HTTP_SRCS="src/http/ngx_http.c \
|
|||||||
src/http/modules/ngx_http_headers_filter_module.c \
|
src/http/modules/ngx_http_headers_filter_module.c \
|
||||||
src/http/modules/ngx_http_not_modified_filter_module.c"
|
src/http/modules/ngx_http_not_modified_filter_module.c"
|
||||||
|
|
||||||
# STUB
|
|
||||||
HTTP_SRCS="$HTTP_SRCS src/http/ngx_http_busy_lock.c"
|
|
||||||
|
|
||||||
HTTP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c
|
HTTP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c
|
||||||
|
|
||||||
HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c
|
HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c
|
||||||
|
@ -27,14 +27,6 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ngx_uint_t lock;
|
|
||||||
|
|
||||||
ngx_event_t *events;
|
|
||||||
ngx_event_t *last;
|
|
||||||
} ngx_event_mutex_t;
|
|
||||||
|
|
||||||
|
|
||||||
struct ngx_event_s {
|
struct ngx_event_s {
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
@ -533,7 +525,6 @@ ngx_int_t ngx_send_lowat(ngx_connection_t *c, size_t lowat);
|
|||||||
|
|
||||||
#include <ngx_event_timer.h>
|
#include <ngx_event_timer.h>
|
||||||
#include <ngx_event_posted.h>
|
#include <ngx_event_posted.h>
|
||||||
#include <ngx_event_busy_lock.h>
|
|
||||||
|
|
||||||
#if (NGX_WIN32)
|
#if (NGX_WIN32)
|
||||||
#include <ngx_iocp_module.h>
|
#include <ngx_iocp_module.h>
|
||||||
|
@ -1,286 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) Igor Sysoev
|
|
||||||
* Copyright (C) Nginx, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <ngx_config.h>
|
|
||||||
#include <ngx_core.h>
|
|
||||||
#include <ngx_event.h>
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx);
|
|
||||||
static void ngx_event_busy_lock_handler(ngx_event_t *ev);
|
|
||||||
static void ngx_event_busy_lock_posted_handler(ngx_event_t *ev);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NGX_OK: the busy lock is held
|
|
||||||
* NGX_AGAIN: the all busy locks are held but we will wait the specified time
|
|
||||||
* NGX_BUSY: ctx->timer == 0: there are many the busy locks
|
|
||||||
* ctx->timer != 0: there are many the waiting locks
|
|
||||||
*/
|
|
||||||
|
|
||||||
ngx_int_t
|
|
||||||
ngx_event_busy_lock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
ngx_int_t rc;
|
|
||||||
|
|
||||||
ngx_mutex_lock(bl->mutex);
|
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
|
|
||||||
"event busy lock: b:%d mb:%d",
|
|
||||||
bl->busy, bl->max_busy);
|
|
||||||
|
|
||||||
if (bl->busy < bl->max_busy) {
|
|
||||||
bl->busy++;
|
|
||||||
|
|
||||||
rc = NGX_OK;
|
|
||||||
|
|
||||||
} else if (ctx->timer && bl->waiting < bl->max_waiting) {
|
|
||||||
bl->waiting++;
|
|
||||||
ngx_add_timer(ctx->event, ctx->timer);
|
|
||||||
ctx->event->handler = ngx_event_busy_lock_handler;
|
|
||||||
|
|
||||||
if (bl->events) {
|
|
||||||
bl->last->next = ctx;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
bl->events = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
bl->last = ctx;
|
|
||||||
|
|
||||||
rc = NGX_AGAIN;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rc = NGX_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_mutex_unlock(bl->mutex);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
|
||||||
ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
ngx_int_t rc;
|
|
||||||
|
|
||||||
ngx_mutex_lock(bl->mutex);
|
|
||||||
|
|
||||||
rc = ngx_event_busy_lock_look_cacheable(bl, ctx);
|
|
||||||
|
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
|
|
||||||
"event busy lock: %d w:%d mw:%d",
|
|
||||||
rc, bl->waiting, bl->max_waiting);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NGX_OK: no the same request, there is free slot and we locked it
|
|
||||||
* NGX_BUSY: no the same request and there is no free slot
|
|
||||||
* NGX_AGAIN: the same request is processing
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
|
||||||
|
|
||||||
if (ctx->timer && bl->waiting < bl->max_waiting) {
|
|
||||||
bl->waiting++;
|
|
||||||
ngx_add_timer(ctx->event, ctx->timer);
|
|
||||||
ctx->event->handler = ngx_event_busy_lock_handler;
|
|
||||||
|
|
||||||
if (bl->events == NULL) {
|
|
||||||
bl->events = ctx;
|
|
||||||
} else {
|
|
||||||
bl->last->next = ctx;
|
|
||||||
}
|
|
||||||
bl->last = ctx;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rc = NGX_BUSY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_mutex_unlock(bl->mutex);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
ngx_event_t *ev;
|
|
||||||
ngx_event_busy_lock_ctx_t *wakeup;
|
|
||||||
|
|
||||||
ngx_mutex_lock(bl->mutex);
|
|
||||||
|
|
||||||
if (bl->events) {
|
|
||||||
wakeup = bl->events;
|
|
||||||
bl->events = bl->events->next;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
wakeup = NULL;
|
|
||||||
bl->busy--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MP: all ctx's and their queue must be in shared memory,
|
|
||||||
* each ctx has pid to wake up
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (wakeup == NULL) {
|
|
||||||
ngx_mutex_unlock(bl->mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->md5) {
|
|
||||||
for (wakeup = bl->events; wakeup; wakeup = wakeup->next) {
|
|
||||||
if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
wakeup->handler = ngx_event_busy_lock_posted_handler;
|
|
||||||
wakeup->cache_updated = 1;
|
|
||||||
|
|
||||||
ev = wakeup->event;
|
|
||||||
|
|
||||||
ngx_post_event(ev, &ngx_posted_events);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_mutex_unlock(bl->mutex);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
bl->waiting--;
|
|
||||||
|
|
||||||
ngx_mutex_unlock(bl->mutex);
|
|
||||||
|
|
||||||
wakeup->handler = ngx_event_busy_lock_posted_handler;
|
|
||||||
wakeup->locked = 1;
|
|
||||||
|
|
||||||
ev = wakeup->event;
|
|
||||||
|
|
||||||
if (ev->timer_set) {
|
|
||||||
ngx_del_timer(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_post_event(ev, &ngx_posted_events);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
ngx_event_busy_lock_ctx_t *c, *p;
|
|
||||||
|
|
||||||
ngx_mutex_lock(bl->mutex);
|
|
||||||
|
|
||||||
bl->waiting--;
|
|
||||||
|
|
||||||
if (ctx == bl->events) {
|
|
||||||
bl->events = ctx->next;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
p = bl->events;
|
|
||||||
for (c = bl->events->next; c; c = c->next) {
|
|
||||||
if (c == ctx) {
|
|
||||||
p->next = ctx->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_mutex_unlock(bl->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
|
||||||
ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
ngx_int_t free;
|
|
||||||
ngx_uint_t i, bit, cacheable, mask;
|
|
||||||
|
|
||||||
bit = 0;
|
|
||||||
cacheable = 0;
|
|
||||||
free = -1;
|
|
||||||
|
|
||||||
#if (NGX_SUPPRESS_WARN)
|
|
||||||
mask = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < bl->max_busy; i++) {
|
|
||||||
|
|
||||||
if ((bit & 7) == 0) {
|
|
||||||
mask = bl->md5_mask[i / 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask & 1) {
|
|
||||||
if (ngx_memcmp(&bl->md5[i * 16], ctx->md5, 16) == 0) {
|
|
||||||
ctx->waiting = 1;
|
|
||||||
ctx->slot = i;
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
|
||||||
cacheable++;
|
|
||||||
|
|
||||||
} else if (free == -1) {
|
|
||||||
free = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cacheable == bl->cacheable) {
|
|
||||||
if (free == -1 && cacheable < bl->max_busy) {
|
|
||||||
free = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mask >>= 1;
|
|
||||||
bit++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (free == -1) {
|
|
||||||
return NGX_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (bl->busy == bl->max_busy) {
|
|
||||||
return NGX_BUSY;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ngx_memcpy(&bl->md5[free * 16], ctx->md5, 16);
|
|
||||||
bl->md5_mask[free / 8] |= 1 << (free & 7);
|
|
||||||
ctx->slot = free;
|
|
||||||
|
|
||||||
bl->cacheable++;
|
|
||||||
bl->busy++;
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ngx_event_busy_lock_handler(ngx_event_t *ev)
|
|
||||||
{
|
|
||||||
ev->handler = ngx_event_busy_lock_posted_handler;
|
|
||||||
|
|
||||||
ngx_post_event(ev, &ngx_posted_events);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ngx_event_busy_lock_posted_handler(ngx_event_t *ev)
|
|
||||||
{
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx;
|
|
||||||
|
|
||||||
ctx = ev->data;
|
|
||||||
ctx->handler(ev);
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) Igor Sysoev
|
|
||||||
* Copyright (C) Nginx, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _NGX_EVENT_BUSY_LOCK_H_INCLUDED_
|
|
||||||
#define _NGX_EVENT_BUSY_LOCK_H_INCLUDED_
|
|
||||||
|
|
||||||
|
|
||||||
#include <ngx_config.h>
|
|
||||||
#include <ngx_core.h>
|
|
||||||
#include <ngx_event.h>
|
|
||||||
|
|
||||||
typedef struct ngx_event_busy_lock_ctx_s ngx_event_busy_lock_ctx_t;
|
|
||||||
|
|
||||||
struct ngx_event_busy_lock_ctx_s {
|
|
||||||
ngx_event_t *event;
|
|
||||||
ngx_event_handler_pt handler;
|
|
||||||
void *data;
|
|
||||||
ngx_msec_t timer;
|
|
||||||
|
|
||||||
unsigned locked:1;
|
|
||||||
unsigned waiting:1;
|
|
||||||
unsigned cache_updated:1;
|
|
||||||
|
|
||||||
char *md5;
|
|
||||||
ngx_int_t slot;
|
|
||||||
|
|
||||||
ngx_event_busy_lock_ctx_t *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_char *md5_mask;
|
|
||||||
char *md5;
|
|
||||||
ngx_uint_t cacheable;
|
|
||||||
|
|
||||||
ngx_uint_t busy;
|
|
||||||
ngx_uint_t max_busy;
|
|
||||||
|
|
||||||
ngx_uint_t waiting;
|
|
||||||
ngx_uint_t max_waiting;
|
|
||||||
|
|
||||||
ngx_event_busy_lock_ctx_t *events;
|
|
||||||
ngx_event_busy_lock_ctx_t *last;
|
|
||||||
|
|
||||||
#if (NGX_OLD_THREADS)
|
|
||||||
ngx_mutex_t *mutex;
|
|
||||||
#endif
|
|
||||||
} ngx_event_busy_lock_t;
|
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t ngx_event_busy_lock(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx);
|
|
||||||
ngx_int_t ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx);
|
|
||||||
void ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx);
|
|
||||||
void ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl,
|
|
||||||
ngx_event_busy_lock_ctx_t *ctx);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_EVENT_BUSY_LOCK_H_INCLUDED_ */
|
|
@ -1,70 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) Igor Sysoev
|
|
||||||
* Copyright (C) Nginx, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <ngx_config.h>
|
|
||||||
#include <ngx_core.h>
|
|
||||||
#include <ngx_event.h>
|
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t ngx_event_mutex_timedlock(ngx_event_mutex_t *m, ngx_msec_t timer,
|
|
||||||
ngx_event_t *ev)
|
|
||||||
{
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
|
|
||||||
"lock event mutex %p lock:%XD", m, m->lock);
|
|
||||||
|
|
||||||
if (m->lock) {
|
|
||||||
|
|
||||||
if (m->events == NULL) {
|
|
||||||
m->events = ev;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
m->last->next = ev;
|
|
||||||
}
|
|
||||||
|
|
||||||
m->last = ev;
|
|
||||||
ev->next = NULL;
|
|
||||||
|
|
||||||
#if (NGX_OLD_THREADS0)
|
|
||||||
ev->light = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ngx_add_timer(ev, timer);
|
|
||||||
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
m->lock = 1;
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t ngx_event_mutex_unlock(ngx_event_mutex_t *m, ngx_log_t *log)
|
|
||||||
{
|
|
||||||
ngx_event_t *ev;
|
|
||||||
|
|
||||||
if (m->lock == 0) {
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, log, 0,
|
|
||||||
"tring to unlock the free event mutex %p", m);
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
|
|
||||||
"unlock event mutex %p, next event: %p", m, m->events);
|
|
||||||
|
|
||||||
m->lock = 0;
|
|
||||||
|
|
||||||
if (m->events) {
|
|
||||||
ev = m->events;
|
|
||||||
m->events = ev->next;
|
|
||||||
|
|
||||||
ev->next = ngx_posted_events;
|
|
||||||
ngx_posted_events = ev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
@ -36,7 +36,6 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r,
|
|||||||
#include <ngx_http_script.h>
|
#include <ngx_http_script.h>
|
||||||
#include <ngx_http_upstream.h>
|
#include <ngx_http_upstream.h>
|
||||||
#include <ngx_http_upstream_round_robin.h>
|
#include <ngx_http_upstream_round_robin.h>
|
||||||
#include <ngx_http_busy_lock.h>
|
|
||||||
#include <ngx_http_core_module.h>
|
#include <ngx_http_core_module.h>
|
||||||
|
|
||||||
#if (NGX_HTTP_SPDY)
|
#if (NGX_HTTP_SPDY)
|
||||||
|
@ -1,307 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) Igor Sysoev
|
|
||||||
* Copyright (C) Nginx, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <ngx_config.h>
|
|
||||||
#include <ngx_core.h>
|
|
||||||
#include <ngx_http.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
|
|
||||||
ngx_http_busy_lock_ctx_t *bc,
|
|
||||||
int lock);
|
|
||||||
|
|
||||||
|
|
||||||
int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
|
|
||||||
{
|
|
||||||
if (bl->busy < bl->max_busy) {
|
|
||||||
bl->busy++;
|
|
||||||
|
|
||||||
if (bc->time) {
|
|
||||||
bc->time = 0;
|
|
||||||
bl->waiting--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bc->time) {
|
|
||||||
if (bc->time < bl->timeout) {
|
|
||||||
ngx_add_timer(bc->event, 1000);
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
bl->waiting--;
|
|
||||||
return NGX_DONE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl->timeout == 0) {
|
|
||||||
return NGX_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl->waiting < bl->max_waiting) {
|
|
||||||
bl->waiting++;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
ngx_add_timer(bc->event, 1000);
|
|
||||||
bc->event->event_handler = bc->event_handler;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* TODO: ngx_handle_level_read_event() */
|
|
||||||
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
|
|
||||||
ngx_http_busy_lock_ctx_t *bc, int lock)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = ngx_http_busy_lock_look_cacheable(bl, bc, lock);
|
|
||||||
|
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, bc->event->log, 0,
|
|
||||||
"http busylock: %d w:%d mw::%d",
|
|
||||||
rc, bl->waiting, bl->max_waiting);
|
|
||||||
|
|
||||||
if (rc == NGX_OK) { /* no the same request, there's free slot */
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* rc == NGX_AGAIN: the same request */
|
|
||||||
|
|
||||||
if (bc->time) {
|
|
||||||
if (bc->time < bl->timeout) {
|
|
||||||
ngx_add_timer(bc->event, 1000);
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
bl->waiting--;
|
|
||||||
return NGX_DONE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl->timeout == 0) {
|
|
||||||
return NGX_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl->waiting < bl->max_waiting) {
|
|
||||||
#if 0
|
|
||||||
bl->waiting++;
|
|
||||||
ngx_add_timer(bc->event, 1000);
|
|
||||||
bc->event->event_handler = bc->event_handler;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* TODO: ngx_handle_level_read_event() */
|
|
||||||
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
|
|
||||||
ngx_http_busy_lock_ctx_t *bc)
|
|
||||||
{
|
|
||||||
if (bl == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl->md5) {
|
|
||||||
bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
|
|
||||||
bl->cacheable--;
|
|
||||||
}
|
|
||||||
|
|
||||||
bl->busy--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
|
|
||||||
ngx_http_busy_lock_ctx_t *bc,
|
|
||||||
int lock)
|
|
||||||
{
|
|
||||||
int i, b, cacheable, free;
|
|
||||||
u_int mask;
|
|
||||||
|
|
||||||
b = 0;
|
|
||||||
cacheable = 0;
|
|
||||||
free = -1;
|
|
||||||
|
|
||||||
#if (NGX_SUPPRESS_WARN)
|
|
||||||
mask = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < bl->max_busy; i++) {
|
|
||||||
|
|
||||||
if ((b & 7) == 0) {
|
|
||||||
mask = bl->md5_mask[i / 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask & 1) {
|
|
||||||
if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
|
||||||
cacheable++;
|
|
||||||
|
|
||||||
} else if (free == -1) {
|
|
||||||
free = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (cacheable == bl->cacheable) {
|
|
||||||
if (free == -1 && cacheable < bl->max_busy) {
|
|
||||||
free = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mask >>= 1;
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (free == -1) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lock) {
|
|
||||||
if (bl->busy == bl->max_busy) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
|
|
||||||
bl->md5_mask[free / 8] |= 1 << (free & 7);
|
|
||||||
bc->slot = free;
|
|
||||||
|
|
||||||
bl->cacheable++;
|
|
||||||
bl->busy++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
|
||||||
void *conf)
|
|
||||||
{
|
|
||||||
char *p = conf;
|
|
||||||
|
|
||||||
ngx_uint_t i, dup, invalid;
|
|
||||||
ngx_str_t *value, line;
|
|
||||||
ngx_http_busy_lock_t *bl, **blp;
|
|
||||||
|
|
||||||
blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
|
|
||||||
if (*blp) {
|
|
||||||
return "is duplicate";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ngx_calloc_shared() */
|
|
||||||
bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t));
|
|
||||||
if (bl == NULL) {
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
*blp = bl;
|
|
||||||
|
|
||||||
/* ngx_calloc_shared() */
|
|
||||||
bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t));
|
|
||||||
if (bl->mutex == NULL) {
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
dup = 0;
|
|
||||||
invalid = 0;
|
|
||||||
value = cf->args->elts;
|
|
||||||
|
|
||||||
for (i = 1; i < cf->args->nelts; i++) {
|
|
||||||
|
|
||||||
if (value[i].data[1] != '=') {
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
||||||
"invalid value \"%s\"", value[i].data);
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (value[i].data[0]) {
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
if (bl->max_busy) {
|
|
||||||
dup = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
|
|
||||||
if (bl->max_busy == NGX_ERROR) {
|
|
||||||
invalid = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
if (bl->max_waiting) {
|
|
||||||
dup = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
|
|
||||||
if (bl->max_waiting == NGX_ERROR) {
|
|
||||||
invalid = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case 't':
|
|
||||||
if (bl->timeout) {
|
|
||||||
dup = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
line.len = value[i].len - 2;
|
|
||||||
line.data = value[i].data + 2;
|
|
||||||
|
|
||||||
bl->timeout = ngx_parse_time(&line, 1);
|
|
||||||
if (bl->timeout == (time_t) NGX_ERROR) {
|
|
||||||
invalid = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
|
|
||||||
default:
|
|
||||||
invalid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dup) {
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
||||||
"duplicate value \"%s\"", value[i].data);
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invalid) {
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
||||||
"invalid value \"%s\"", value[i].data);
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl->timeout == 0 && bl->max_waiting) {
|
|
||||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
|
||||||
"busy lock waiting is useless with zero timeout, ignoring");
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) Igor Sysoev
|
|
||||||
* Copyright (C) Nginx, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _NGX_HTTP_BUSY_LOCK_H_INCLUDED_
|
|
||||||
#define _NGX_HTTP_BUSY_LOCK_H_INCLUDED_
|
|
||||||
|
|
||||||
|
|
||||||
#include <ngx_config.h>
|
|
||||||
#include <ngx_core.h>
|
|
||||||
#include <ngx_event.h>
|
|
||||||
#include <ngx_http.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_char *md5_mask;
|
|
||||||
char *md5;
|
|
||||||
int cacheable;
|
|
||||||
|
|
||||||
int busy;
|
|
||||||
int max_busy;
|
|
||||||
|
|
||||||
int waiting;
|
|
||||||
int max_waiting;
|
|
||||||
|
|
||||||
time_t timeout;
|
|
||||||
|
|
||||||
ngx_event_mutex_t *mutex;
|
|
||||||
} ngx_http_busy_lock_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
time_t time;
|
|
||||||
ngx_event_t *event;
|
|
||||||
void (*event_handler)(ngx_event_t *ev);
|
|
||||||
u_char *md5;
|
|
||||||
int slot;
|
|
||||||
} ngx_http_busy_lock_ctx_t;
|
|
||||||
|
|
||||||
|
|
||||||
int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc);
|
|
||||||
int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
|
|
||||||
ngx_http_busy_lock_ctx_t *bc, int lock);
|
|
||||||
void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
|
|
||||||
ngx_http_busy_lock_ctx_t *bc);
|
|
||||||
|
|
||||||
char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
|
||||||
void *conf);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_HTTP_BUSY_LOCK_H_INCLUDED_ */
|
|
@ -67,8 +67,5 @@ ngx_tid_t ngx_thread_tid(void);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ngx_mutex_lock(m)
|
|
||||||
#define ngx_mutex_unlock(m)
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_THREAD_H_INCLUDED_ */
|
#endif /* _NGX_THREAD_H_INCLUDED_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user