3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
14 static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t
*bl
,
15 ngx_http_busy_lock_ctx_t
*bc
,
19 int ngx_http_busy_lock(ngx_http_busy_lock_t
*bl
, ngx_http_busy_lock_ctx_t
*bc
)
21 if (bl
->busy
< bl
->max_busy
) {
33 if (bc
->time
< bl
->timeout
) {
34 ngx_add_timer(bc
->event
, 1000);
43 if (bl
->timeout
== 0) {
47 if (bl
->waiting
< bl
->max_waiting
) {
51 ngx_add_timer(bc
->event
, 1000);
52 bc
->event
->event_handler
= bc
->event_handler
;
55 /* TODO: ngx_handle_level_read_event() */
64 int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t
*bl
,
65 ngx_http_busy_lock_ctx_t
*bc
, int lock
)
69 rc
= ngx_http_busy_lock_look_cacheable(bl
, bc
, lock
);
71 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, bc
->event
->log
, 0,
72 "http busylock: %d w:%d mw::%d",
73 rc
, bl
->waiting
, bl
->max_waiting
);
75 if (rc
== NGX_OK
) { /* no the same request, there's free slot */
79 if (rc
== NGX_ERROR
&& !lock
) { /* no the same request, no free slot */
83 /* rc == NGX_AGAIN: the same request */
86 if (bc
->time
< bl
->timeout
) {
87 ngx_add_timer(bc
->event
, 1000);
96 if (bl
->timeout
== 0) {
100 if (bl
->waiting
< bl
->max_waiting
) {
103 ngx_add_timer(bc
->event
, 1000);
104 bc
->event
->event_handler
= bc
->event_handler
;
107 /* TODO: ngx_handle_level_read_event() */
116 void ngx_http_busy_unlock(ngx_http_busy_lock_t
*bl
,
117 ngx_http_busy_lock_ctx_t
*bc
)
124 bl
->md5_mask
[bc
->slot
/ 8] &= ~(1 << (bc
->slot
& 7));
132 static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t
*bl
,
133 ngx_http_busy_lock_ctx_t
*bc
,
136 int i
, b
, cacheable
, free
;
143 #if (NGX_SUPPRESS_WARN)
147 for (i
= 0; i
< bl
->max_busy
; i
++) {
150 mask
= bl
->md5_mask
[i
/ 8];
154 if (ngx_memcmp(&bl
->md5
[i
* 16], bc
->md5
, 16) == 0) {
159 } else if (free
== -1) {
164 if (cacheable
== bl
->cacheable
) {
165 if (free
== -1 && cacheable
< bl
->max_busy
) {
182 if (bl
->busy
== bl
->max_busy
) {
186 ngx_memcpy(&bl
->md5
[free
* 16], bc
->md5
, 16);
187 bl
->md5_mask
[free
/ 8] |= 1 << (free
& 7);
198 char *ngx_http_set_busy_lock_slot(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
203 ngx_uint_t i
, dup
, invalid
;
204 ngx_str_t
*value
, line
;
205 ngx_http_busy_lock_t
*bl
, **blp
;
207 blp
= (ngx_http_busy_lock_t
**) (p
+ cmd
->offset
);
209 return "is duplicate";
212 /* ngx_calloc_shared() */
213 bl
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_busy_lock_t
));
215 return NGX_CONF_ERROR
;
219 /* ngx_calloc_shared() */
220 bl
->mutex
= ngx_pcalloc(cf
->pool
, sizeof(ngx_event_mutex_t
));
221 if (bl
->mutex
== NULL
) {
222 return NGX_CONF_ERROR
;
227 value
= cf
->args
->elts
;
229 for (i
= 1; i
< cf
->args
->nelts
; i
++) {
231 if (value
[i
].data
[1] != '=') {
232 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
233 "invalid value \"%s\"", value
[i
].data
);
234 return NGX_CONF_ERROR
;
237 switch (value
[i
].data
[0]) {
245 bl
->max_busy
= ngx_atoi(value
[i
].data
+ 2, value
[i
].len
- 2);
246 if (bl
->max_busy
== NGX_ERROR
) {
254 if (bl
->max_waiting
) {
259 bl
->max_waiting
= ngx_atoi(value
[i
].data
+ 2, value
[i
].len
- 2);
260 if (bl
->max_waiting
== NGX_ERROR
) {
273 line
.len
= value
[i
].len
- 2;
274 line
.data
= value
[i
].data
+ 2;
276 bl
->timeout
= ngx_parse_time(&line
, 1);
277 if (bl
->timeout
== (time_t) NGX_ERROR
) {
289 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
290 "duplicate value \"%s\"", value
[i
].data
);
291 return NGX_CONF_ERROR
;
295 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
296 "invalid value \"%s\"", value
[i
].data
);
297 return NGX_CONF_ERROR
;
301 if (bl
->timeout
== 0 && bl
->max_waiting
) {
302 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
303 "busy lock waiting is useless with zero timeout, ignoring");