comparison src/http/ngx_http_busy_lock.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children 72eb30262aac
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10
11
12
13 static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
14 ngx_http_busy_lock_ctx_t *bc,
15 int lock);
16
17
18 int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
19 {
20 if (bl->busy < bl->max_busy) {
21 bl->busy++;
22
23 if (bc->time) {
24 bc->time = 0;
25 bl->waiting--;
26 }
27
28 return NGX_OK;
29 }
30
31 if (bc->time) {
32 if (bc->time < bl->timeout) {
33 ngx_add_timer(bc->event, 1000);
34 return NGX_AGAIN;
35 }
36
37 bl->waiting--;
38 return NGX_DONE;
39
40 }
41
42 if (bl->timeout == 0) {
43 return NGX_DONE;
44 }
45
46 if (bl->waiting < bl->max_waiting) {
47 bl->waiting++;
48
49 ngx_add_timer(bc->event, 1000);
50 bc->event->event_handler = bc->event_handler;
51
52 /* TODO: ngx_handle_level_read_event() */
53
54 return NGX_AGAIN;
55 }
56
57 return NGX_ERROR;
58 }
59
60
61 int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
62 ngx_http_busy_lock_ctx_t *bc, int lock)
63 {
64 int rc;
65
66 rc = ngx_http_busy_lock_look_cachable(bl, bc, lock);
67
68 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, bc->event->log, 0,
69 "http busylock: %d w:%d mw::%d",
70 rc, bl->waiting, bl->max_waiting);
71
72 if (rc == NGX_OK) { /* no the same request, there's free slot */
73 return NGX_OK;
74 }
75
76 if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
77 return NGX_OK;
78 }
79
80 /* rc == NGX_AGAIN: the same request */
81
82 if (bc->time) {
83 if (bc->time < bl->timeout) {
84 ngx_add_timer(bc->event, 1000);
85 return NGX_AGAIN;
86 }
87
88 bl->waiting--;
89 return NGX_DONE;
90
91 }
92
93 if (bl->timeout == 0) {
94 return NGX_DONE;
95 }
96
97 if (bl->waiting < bl->max_waiting) {
98 bl->waiting++;
99 ngx_add_timer(bc->event, 1000);
100 bc->event->event_handler = bc->event_handler;
101
102 /* TODO: ngx_handle_level_read_event() */
103
104 return NGX_AGAIN;
105 }
106
107 return NGX_ERROR;
108 }
109
110
111 void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
112 ngx_http_busy_lock_ctx_t *bc)
113 {
114 if (bl == NULL) {
115 return;
116 }
117
118 if (bl->md5) {
119 bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
120 bl->cachable--;
121 }
122
123 bl->busy--;
124 }
125
126
127 static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
128 ngx_http_busy_lock_ctx_t *bc,
129 int lock)
130 {
131 int i, b, cachable, free;
132 u_int mask;
133
134 b = 0;
135 cachable = 0;
136 free = -1;
137
138 #if (NGX_SUPPRESS_WARN)
139 mask = 0;
140 #endif
141
142 for (i = 0; i < bl->max_busy; i++) {
143
144 if ((b & 7) == 0) {
145 mask = bl->md5_mask[i / 8];
146 }
147
148 if (mask & 1) {
149 if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
150 return NGX_AGAIN;
151 }
152 cachable++;
153
154 } else if (free == -1) {
155 free = i;
156 }
157
158 #if 1
159 if (cachable == bl->cachable) {
160 if (free == -1 && cachable < bl->max_busy) {
161 free = i + 1;
162 }
163
164 break;
165 }
166 #endif
167
168 mask >>= 1;
169 b++;
170 }
171
172 if (free == -1) {
173 return NGX_ERROR;
174 }
175
176 if (lock) {
177 if (bl->busy == bl->max_busy) {
178 return NGX_ERROR;
179 }
180
181 ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
182 bl->md5_mask[free / 8] |= 1 << (free & 7);
183 bc->slot = free;
184
185 bl->cachable++;
186 bl->busy++;
187 }
188
189 return NGX_OK;
190 }
191
192
193 char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
194 void *conf)
195 {
196 char *p = conf;
197
198 ngx_uint_t i, dup, invalid;
199 ngx_str_t *value, line;
200 ngx_http_busy_lock_t *bl, **blp;
201
202 blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
203 if (*blp) {
204 return "is duplicate";
205 }
206
207 /* ngx_calloc_shared() */
208 if (!(bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t)))) {
209 return NGX_CONF_ERROR;
210 }
211 *blp = bl;
212
213 /* ngx_calloc_shared() */
214 if (!(bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t)))) {
215 return NGX_CONF_ERROR;
216 }
217
218 dup = 0;
219 invalid = 0;
220 value = cf->args->elts;
221
222 for (i = 1; i < cf->args->nelts; i++) {
223
224 if (value[i].data[1] != '=') {
225 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
226 "invalid value \"%s\"", value[i].data);
227 return NGX_CONF_ERROR;
228 }
229
230 switch (value[i].data[0]) {
231
232 case 'b':
233 if (bl->max_busy) {
234 dup = 1;
235 break;
236 }
237
238 bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
239 if (bl->max_busy == NGX_ERROR) {
240 invalid = 1;
241 break;
242 }
243
244 continue;
245
246 case 'w':
247 if (bl->max_waiting) {
248 dup = 1;
249 break;
250 }
251
252 bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
253 if (bl->max_waiting == NGX_ERROR) {
254 invalid = 1;
255 break;
256 }
257
258 continue;
259
260 case 't':
261 if (bl->timeout) {
262 dup = 1;
263 break;
264 }
265
266 line.len = value[i].len - 2;
267 line.data = value[i].data + 2;
268
269 bl->timeout = ngx_parse_time(&line, 1);
270 if (bl->timeout == NGX_ERROR) {
271 invalid = 1;
272 break;
273 }
274
275 continue;
276
277 default:
278 invalid = 1;
279 }
280
281 if (dup) {
282 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
283 "duplicate value \"%s\"", value[i].data);
284 return NGX_CONF_ERROR;
285 }
286
287 if (invalid) {
288 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
289 "invalid value \"%s\"", value[i].data);
290 return NGX_CONF_ERROR;
291 }
292 }
293
294 if (bl->timeout == 0 && bl->max_waiting) {
295 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
296 "busy lock waiting is useless with zero timeout, ignoring");
297 }
298
299 return NGX_CONF_OK;
300 }