blob: 4bef15a609e11765f80ce9978021d68a2a1217ba [file] [log] [blame]
Igor Sysoev9cc1ace2003-11-04 22:12:39 +00001
2#include <ngx_config.h>
3#include <ngx_core.h>
4#include <ngx_http.h>
5
6
Igor Sysoev74e95c22003-11-09 20:03:38 +00007
8static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
9 ngx_http_busy_lock_ctx_t *bc,
10 int lock);
11
12
13int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
Igor Sysoeve8732b02003-11-05 17:03:41 +000014{
Igor Sysoev74e95c22003-11-09 20:03:38 +000015 if (bl->busy < bl->max_busy) {
16 bl->busy++;
17
18 if (bc->time) {
19 bc->time = 0;
20 bl->waiting--;
21 }
22
23 return NGX_OK;
24 }
25
26 if (bc->time) {
27 if (bc->time < bl->timeout) {
28 ngx_add_timer(bc->event, 1000);
29 return NGX_AGAIN;
30 }
31
32 bl->waiting--;
33 return NGX_DONE;
34
35 }
36
37 if (bl->timeout == 0) {
38 return NGX_DONE;
39 }
40
41 if (bl->waiting < bl->max_waiting) {
42 bl->waiting++;
Igor Sysoevd94049b2004-02-29 21:03:02 +000043
Igor Sysoev74e95c22003-11-09 20:03:38 +000044 ngx_add_timer(bc->event, 1000);
45 bc->event->event_handler = bc->event_handler;
46
47 /* TODO: ngx_handle_level_read_event() */
48
49 return NGX_AGAIN;
50 }
51
52 return NGX_ERROR;
53}
54
55
56int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
57 ngx_http_busy_lock_ctx_t *bc, int lock)
58{
59 int rc;
60
61 rc = ngx_http_busy_lock_look_cachable(bl, bc, lock);
62
Igor Sysoev54498db2004-02-11 17:08:49 +000063 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, bc->event->log, 0,
64 "http busylock: %d w:%d mw::%d",
65 rc, bl->waiting, bl->max_waiting);
Igor Sysoev74e95c22003-11-09 20:03:38 +000066
67 if (rc == NGX_OK) { /* no the same request, there's free slot */
68 return NGX_OK;
69 }
70
71 if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
72 return NGX_OK;
73 }
74
75 /* rc == NGX_AGAIN: the same request */
76
77 if (bc->time) {
78 if (bc->time < bl->timeout) {
79 ngx_add_timer(bc->event, 1000);
80 return NGX_AGAIN;
81 }
82
83 bl->waiting--;
84 return NGX_DONE;
85
86 }
87
88 if (bl->timeout == 0) {
89 return NGX_DONE;
90 }
91
92 if (bl->waiting < bl->max_waiting) {
93 bl->waiting++;
94 ngx_add_timer(bc->event, 1000);
95 bc->event->event_handler = bc->event_handler;
96
97 /* TODO: ngx_handle_level_read_event() */
98
99 return NGX_AGAIN;
100 }
101
102 return NGX_ERROR;
103}
104
105
Igor Sysoevd59a0472003-11-10 21:09:22 +0000106void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
107 ngx_http_busy_lock_ctx_t *bc)
Igor Sysoev74e95c22003-11-09 20:03:38 +0000108{
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000109 if (bl == NULL) {
110 return;
111 }
112
Igor Sysoevd59a0472003-11-10 21:09:22 +0000113 if (bl->md5) {
114 bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
115 bl->cachable--;
116 }
117
Igor Sysoev74e95c22003-11-09 20:03:38 +0000118 bl->busy--;
119}
120
121
122static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
123 ngx_http_busy_lock_ctx_t *bc,
124 int lock)
125{
126 int i, b, cachable, free;
Igor Sysoeve8732b02003-11-05 17:03:41 +0000127 u_int mask;
128
129 b = 0;
Igor Sysoev74e95c22003-11-09 20:03:38 +0000130 cachable = 0;
Igor Sysoeve8732b02003-11-05 17:03:41 +0000131 free = -1;
132
133#if (NGX_SUPPRESS_WARN)
134 mask = 0;
135#endif
136
Igor Sysoev74e95c22003-11-09 20:03:38 +0000137 for (i = 0; i < bl->max_busy; i++) {
Igor Sysoeve8732b02003-11-05 17:03:41 +0000138
139 if ((b & 7) == 0) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000140 mask = bl->md5_mask[i / 8];
Igor Sysoeve8732b02003-11-05 17:03:41 +0000141 }
142
143 if (mask & 1) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000144 if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
Igor Sysoeve8732b02003-11-05 17:03:41 +0000145 return NGX_AGAIN;
146 }
Igor Sysoev74e95c22003-11-09 20:03:38 +0000147 cachable++;
Igor Sysoeve8732b02003-11-05 17:03:41 +0000148
149 } else if (free == -1) {
150 free = i;
151 }
152
Igor Sysoev74e95c22003-11-09 20:03:38 +0000153#if 1
154 if (cachable == bl->cachable) {
155 if (free == -1 && cachable < bl->max_busy) {
Igor Sysoeve8732b02003-11-05 17:03:41 +0000156 free = i + 1;
157 }
158
159 break;
160 }
Igor Sysoev74e95c22003-11-09 20:03:38 +0000161#endif
Igor Sysoeve8732b02003-11-05 17:03:41 +0000162
163 mask >>= 1;
164 b++;
165 }
166
167 if (free == -1) {
168 return NGX_ERROR;
169 }
170
Igor Sysoev74e95c22003-11-09 20:03:38 +0000171 if (lock) {
172 if (bl->busy == bl->max_busy) {
173 return NGX_ERROR;
174 }
Igor Sysoeve8732b02003-11-05 17:03:41 +0000175
Igor Sysoev74e95c22003-11-09 20:03:38 +0000176 ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
177 bl->md5_mask[free / 8] |= 1 << (free & 7);
178 bc->slot = free;
179
180 bl->cachable++;
181 bl->busy++;
182 }
Igor Sysoeve8732b02003-11-05 17:03:41 +0000183
184 return NGX_OK;
185}
186
187
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000188char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
189 void *conf)
190{
191 char *p = conf;
192
Igor Sysoev10a543a2004-03-16 07:10:12 +0000193 ngx_uint_t i, dup, invalid;
Igor Sysoev74e95c22003-11-09 20:03:38 +0000194 ngx_str_t *value, line;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000195 ngx_http_busy_lock_t *bl, **blp;
196
197 blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
198 if (*blp) {
199 return "is duplicate";
200 }
201
202 /* ngx_calloc_shared() */
203 if (!(bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t)))) {
204 return NGX_CONF_ERROR;
205 }
206 *blp = bl;
207
Igor Sysoevd94049b2004-02-29 21:03:02 +0000208 /* ngx_calloc_shared() */
209 if (!(bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t)))) {
210 return NGX_CONF_ERROR;
211 }
212
Igor Sysoev74e95c22003-11-09 20:03:38 +0000213 dup = 0;
214 invalid = 0;
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000215 value = cf->args->elts;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000216
Igor Sysoev74e95c22003-11-09 20:03:38 +0000217 for (i = 1; i < cf->args->nelts; i++) {
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000218
Igor Sysoev74e95c22003-11-09 20:03:38 +0000219 if (value[i].data[1] != '=') {
220 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
221 "invalid value \"%s\"", value[i].data);
222 return NGX_CONF_ERROR;
223 }
224
225 switch (value[i].data[0]) {
226
227 case 'b':
228 if (bl->max_busy) {
229 dup = 1;
230 break;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000231 }
232
Igor Sysoev74e95c22003-11-09 20:03:38 +0000233 bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
234 if (bl->max_busy == NGX_ERROR) {
235 invalid = 1;
236 break;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000237 }
238
239 continue;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000240
Igor Sysoev74e95c22003-11-09 20:03:38 +0000241 case 'w':
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000242 if (bl->max_waiting) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000243 dup = 1;
244 break;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000245 }
246
247 bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
248 if (bl->max_waiting == NGX_ERROR) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000249 invalid = 1;
250 break;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000251 }
252
253 continue;
Igor Sysoev74e95c22003-11-09 20:03:38 +0000254
255 case 't':
256 if (bl->timeout) {
257 dup = 1;
258 break;
259 }
260
261 line.len = value[i].len - 2;
262 line.data = value[i].data + 2;
263
264 bl->timeout = ngx_parse_time(&line, 1);
265 if (bl->timeout == NGX_ERROR) {
266 invalid = 1;
267 break;
268 }
269
270 continue;
271
272 default:
273 invalid = 1;
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000274 }
275
Igor Sysoev74e95c22003-11-09 20:03:38 +0000276 if (dup) {
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000277 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev74e95c22003-11-09 20:03:38 +0000278 "duplicate value \"%s\"", value[i].data);
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000279 return NGX_CONF_ERROR;
280 }
281
Igor Sysoev74e95c22003-11-09 20:03:38 +0000282 if (invalid) {
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000283 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev74e95c22003-11-09 20:03:38 +0000284 "invalid value \"%s\"", value[i].data);
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000285 return NGX_CONF_ERROR;
286 }
287 }
288
Igor Sysoev74e95c22003-11-09 20:03:38 +0000289 if (bl->timeout == 0 && bl->max_waiting) {
290 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
Igor Sysoevea17edc2004-03-02 21:14:37 +0000291 "busy lock waiting is useless with zero timeout, ignoring");
Igor Sysoev74e95c22003-11-09 20:03:38 +0000292 }
293
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000294 return NGX_CONF_OK;
295}