Mercurial > hg > nginx-vendor-current
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 } |