Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / http / ngx_http_busy_lock.c
blob3b4b28c8b326b60cdae7e1a4e7cf543cd3956cdc
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
14 static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
15 ngx_http_busy_lock_ctx_t *bc,
16 int lock);
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) {
22 bl->busy++;
24 if (bc->time) {
25 bc->time = 0;
26 bl->waiting--;
29 return NGX_OK;
32 if (bc->time) {
33 if (bc->time < bl->timeout) {
34 ngx_add_timer(bc->event, 1000);
35 return NGX_AGAIN;
38 bl->waiting--;
39 return NGX_DONE;
43 if (bl->timeout == 0) {
44 return NGX_DONE;
47 if (bl->waiting < bl->max_waiting) {
48 bl->waiting++;
50 #if 0
51 ngx_add_timer(bc->event, 1000);
52 bc->event->event_handler = bc->event_handler;
53 #endif
55 /* TODO: ngx_handle_level_read_event() */
57 return NGX_AGAIN;
60 return NGX_ERROR;
64 int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
65 ngx_http_busy_lock_ctx_t *bc, int lock)
67 int rc;
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 */
76 return NGX_OK;
79 if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
80 return NGX_OK;
83 /* rc == NGX_AGAIN: the same request */
85 if (bc->time) {
86 if (bc->time < bl->timeout) {
87 ngx_add_timer(bc->event, 1000);
88 return NGX_AGAIN;
91 bl->waiting--;
92 return NGX_DONE;
96 if (bl->timeout == 0) {
97 return NGX_DONE;
100 if (bl->waiting < bl->max_waiting) {
101 #if 0
102 bl->waiting++;
103 ngx_add_timer(bc->event, 1000);
104 bc->event->event_handler = bc->event_handler;
105 #endif
107 /* TODO: ngx_handle_level_read_event() */
109 return NGX_AGAIN;
112 return NGX_ERROR;
116 void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
117 ngx_http_busy_lock_ctx_t *bc)
119 if (bl == NULL) {
120 return;
123 if (bl->md5) {
124 bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
125 bl->cacheable--;
128 bl->busy--;
132 static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
133 ngx_http_busy_lock_ctx_t *bc,
134 int lock)
136 int i, b, cacheable, free;
137 u_int mask;
139 b = 0;
140 cacheable = 0;
141 free = -1;
143 #if (NGX_SUPPRESS_WARN)
144 mask = 0;
145 #endif
147 for (i = 0; i < bl->max_busy; i++) {
149 if ((b & 7) == 0) {
150 mask = bl->md5_mask[i / 8];
153 if (mask & 1) {
154 if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
155 return NGX_AGAIN;
157 cacheable++;
159 } else if (free == -1) {
160 free = i;
163 #if 1
164 if (cacheable == bl->cacheable) {
165 if (free == -1 && cacheable < bl->max_busy) {
166 free = i + 1;
169 break;
171 #endif
173 mask >>= 1;
174 b++;
177 if (free == -1) {
178 return NGX_ERROR;
181 if (lock) {
182 if (bl->busy == bl->max_busy) {
183 return NGX_ERROR;
186 ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
187 bl->md5_mask[free / 8] |= 1 << (free & 7);
188 bc->slot = free;
190 bl->cacheable++;
191 bl->busy++;
194 return NGX_OK;
198 char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
199 void *conf)
201 char *p = conf;
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);
208 if (*blp) {
209 return "is duplicate";
212 /* ngx_calloc_shared() */
213 bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t));
214 if (bl == NULL) {
215 return NGX_CONF_ERROR;
217 *blp = bl;
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;
225 dup = 0;
226 invalid = 0;
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]) {
239 case 'b':
240 if (bl->max_busy) {
241 dup = 1;
242 break;
245 bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
246 if (bl->max_busy == NGX_ERROR) {
247 invalid = 1;
248 break;
251 continue;
253 case 'w':
254 if (bl->max_waiting) {
255 dup = 1;
256 break;
259 bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
260 if (bl->max_waiting == NGX_ERROR) {
261 invalid = 1;
262 break;
265 continue;
267 case 't':
268 if (bl->timeout) {
269 dup = 1;
270 break;
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) {
278 invalid = 1;
279 break;
282 continue;
284 default:
285 invalid = 1;
288 if (dup) {
289 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
290 "duplicate value \"%s\"", value[i].data);
291 return NGX_CONF_ERROR;
294 if (invalid) {
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");
306 return NGX_CONF_OK;