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