Annotation of embedaddon/nginx/src/http/ngx_http_busy_lock.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_http.h>
11:
12:
13:
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);
17:
18:
19: int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
20: {
21: if (bl->busy < bl->max_busy) {
22: bl->busy++;
23:
24: if (bc->time) {
25: bc->time = 0;
26: bl->waiting--;
27: }
28:
29: return NGX_OK;
30: }
31:
32: if (bc->time) {
33: if (bc->time < bl->timeout) {
34: ngx_add_timer(bc->event, 1000);
35: return NGX_AGAIN;
36: }
37:
38: bl->waiting--;
39: return NGX_DONE;
40:
41: }
42:
43: if (bl->timeout == 0) {
44: return NGX_DONE;
45: }
46:
47: if (bl->waiting < bl->max_waiting) {
48: bl->waiting++;
49:
50: #if 0
51: ngx_add_timer(bc->event, 1000);
52: bc->event->event_handler = bc->event_handler;
53: #endif
54:
55: /* TODO: ngx_handle_level_read_event() */
56:
57: return NGX_AGAIN;
58: }
59:
60: return NGX_ERROR;
61: }
62:
63:
64: int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
65: ngx_http_busy_lock_ctx_t *bc, int lock)
66: {
67: int rc;
68:
69: rc = ngx_http_busy_lock_look_cacheable(bl, bc, lock);
70:
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);
74:
75: if (rc == NGX_OK) { /* no the same request, there's free slot */
76: return NGX_OK;
77: }
78:
79: if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
80: return NGX_OK;
81: }
82:
83: /* rc == NGX_AGAIN: the same request */
84:
85: if (bc->time) {
86: if (bc->time < bl->timeout) {
87: ngx_add_timer(bc->event, 1000);
88: return NGX_AGAIN;
89: }
90:
91: bl->waiting--;
92: return NGX_DONE;
93:
94: }
95:
96: if (bl->timeout == 0) {
97: return NGX_DONE;
98: }
99:
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
106:
107: /* TODO: ngx_handle_level_read_event() */
108:
109: return NGX_AGAIN;
110: }
111:
112: return NGX_ERROR;
113: }
114:
115:
116: void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
117: ngx_http_busy_lock_ctx_t *bc)
118: {
119: if (bl == NULL) {
120: return;
121: }
122:
123: if (bl->md5) {
124: bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
125: bl->cacheable--;
126: }
127:
128: bl->busy--;
129: }
130:
131:
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)
135: {
136: int i, b, cacheable, free;
137: u_int mask;
138:
139: b = 0;
140: cacheable = 0;
141: free = -1;
142:
143: #if (NGX_SUPPRESS_WARN)
144: mask = 0;
145: #endif
146:
147: for (i = 0; i < bl->max_busy; i++) {
148:
149: if ((b & 7) == 0) {
150: mask = bl->md5_mask[i / 8];
151: }
152:
153: if (mask & 1) {
154: if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
155: return NGX_AGAIN;
156: }
157: cacheable++;
158:
159: } else if (free == -1) {
160: free = i;
161: }
162:
163: #if 1
164: if (cacheable == bl->cacheable) {
165: if (free == -1 && cacheable < bl->max_busy) {
166: free = i + 1;
167: }
168:
169: break;
170: }
171: #endif
172:
173: mask >>= 1;
174: b++;
175: }
176:
177: if (free == -1) {
178: return NGX_ERROR;
179: }
180:
181: if (lock) {
182: if (bl->busy == bl->max_busy) {
183: return NGX_ERROR;
184: }
185:
186: ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
187: bl->md5_mask[free / 8] |= 1 << (free & 7);
188: bc->slot = free;
189:
190: bl->cacheable++;
191: bl->busy++;
192: }
193:
194: return NGX_OK;
195: }
196:
197:
198: char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
199: void *conf)
200: {
201: char *p = conf;
202:
203: ngx_uint_t i, dup, invalid;
204: ngx_str_t *value, line;
205: ngx_http_busy_lock_t *bl, **blp;
206:
207: blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
208: if (*blp) {
209: return "is duplicate";
210: }
211:
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;
216: }
217: *blp = bl;
218:
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;
223: }
224:
225: dup = 0;
226: invalid = 0;
227: value = cf->args->elts;
228:
229: for (i = 1; i < cf->args->nelts; i++) {
230:
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;
235: }
236:
237: switch (value[i].data[0]) {
238:
239: case 'b':
240: if (bl->max_busy) {
241: dup = 1;
242: break;
243: }
244:
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;
249: }
250:
251: continue;
252:
253: case 'w':
254: if (bl->max_waiting) {
255: dup = 1;
256: break;
257: }
258:
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;
263: }
264:
265: continue;
266:
267: case 't':
268: if (bl->timeout) {
269: dup = 1;
270: break;
271: }
272:
273: line.len = value[i].len - 2;
274: line.data = value[i].data + 2;
275:
276: bl->timeout = ngx_parse_time(&line, 1);
277: if (bl->timeout == (time_t) NGX_ERROR) {
278: invalid = 1;
279: break;
280: }
281:
282: continue;
283:
284: default:
285: invalid = 1;
286: }
287:
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;
292: }
293:
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;
298: }
299: }
300:
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");
304: }
305:
306: return NGX_CONF_OK;
307: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>