~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http_busy_lock.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  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_cacheable(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 #if 0
 50         ngx_add_timer(bc->event, 1000);
 51         bc->event->event_handler = bc->event_handler;
 52 #endif
 53 
 54         /* TODO: ngx_handle_level_read_event() */
 55 
 56         return NGX_AGAIN;
 57     }
 58 
 59     return NGX_ERROR;
 60 }
 61 
 62 
 63 int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
 64                                  ngx_http_busy_lock_ctx_t *bc, int lock)
 65 {
 66     int  rc;
 67 
 68     rc = ngx_http_busy_lock_look_cacheable(bl, bc, lock);
 69 
 70     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, bc->event->log, 0,
 71                    "http busylock: %d w:%d mw::%d",
 72                    rc, bl->waiting, bl->max_waiting);
 73 
 74     if (rc == NGX_OK) {  /* no the same request, there's free slot */
 75         return NGX_OK;
 76     }
 77 
 78     if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
 79         return NGX_OK;
 80     }
 81 
 82     /* rc == NGX_AGAIN:  the same request */
 83 
 84     if (bc->time) {
 85         if (bc->time < bl->timeout) {
 86             ngx_add_timer(bc->event, 1000);
 87             return NGX_AGAIN;
 88         }
 89 
 90         bl->waiting--;
 91         return NGX_DONE;
 92 
 93     }
 94 
 95     if (bl->timeout == 0) {
 96         return NGX_DONE;
 97     }
 98 
 99     if (bl->waiting < bl->max_waiting) {
100 #if 0
101         bl->waiting++;
102         ngx_add_timer(bc->event, 1000);
103         bc->event->event_handler = bc->event_handler;
104 #endif
105 
106         /* TODO: ngx_handle_level_read_event() */
107 
108         return NGX_AGAIN;
109     }
110 
111     return NGX_ERROR;
112 }
113 
114 
115 void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
116                           ngx_http_busy_lock_ctx_t *bc)
117 {
118     if (bl == NULL) {
119         return;
120     }
121 
122     if (bl->md5) {
123         bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
124         bl->cacheable--;
125     }
126 
127     bl->busy--;
128 }
129 
130 
131 static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
132                                              ngx_http_busy_lock_ctx_t *bc,
133                                              int lock)
134 {
135     int    i, b, cacheable, free;
136     u_int  mask;
137 
138     b = 0;
139     cacheable = 0;
140     free = -1;
141 
142 #if (NGX_SUPPRESS_WARN)
143     mask = 0;
144 #endif
145 
146     for (i = 0; i < bl->max_busy; i++) {
147 
148         if ((b & 7) == 0) {
149             mask = bl->md5_mask[i / 8];
150         }
151 
152         if (mask & 1) {
153             if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
154                 return NGX_AGAIN;
155             }
156             cacheable++;
157 
158         } else if (free == -1) {
159             free = i;
160         }
161 
162 #if 1
163         if (cacheable == bl->cacheable) {
164             if (free == -1 && cacheable < bl->max_busy) {
165                 free = i + 1;
166             }
167 
168             break;
169         }
170 #endif
171 
172         mask >>= 1;
173         b++;
174     }
175 
176     if (free == -1) {
177         return NGX_ERROR;
178     }
179 
180     if (lock) {
181         if (bl->busy == bl->max_busy) {
182             return NGX_ERROR;
183         }
184 
185         ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
186         bl->md5_mask[free / 8] |= 1 << (free & 7);
187         bc->slot = free;
188 
189         bl->cacheable++;
190         bl->busy++;
191     }
192 
193     return NGX_OK;
194 }
195 
196 
197 char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
198                                   void *conf)
199 {
200     char  *p = conf;
201 
202     ngx_uint_t             i, dup, invalid;
203     ngx_str_t             *value, line;
204     ngx_http_busy_lock_t  *bl, **blp;
205 
206     blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
207     if (*blp) {
208         return "is duplicate";
209     }
210 
211     /* ngx_calloc_shared() */
212     bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t));
213     if (bl == NULL) {
214         return NGX_CONF_ERROR;
215     }
216     *blp = bl;
217 
218     /* ngx_calloc_shared() */
219     bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t));
220     if (bl->mutex == NULL) {
221         return NGX_CONF_ERROR;
222     }
223 
224     dup = 0;
225     invalid = 0;
226     value = cf->args->elts;
227 
228     for (i = 1; i < cf->args->nelts; i++) {
229 
230         if (value[i].data[1] != '=') {
231             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
232                            "invalid value \"%s\"", value[i].data);
233             return NGX_CONF_ERROR;
234         }
235 
236         switch (value[i].data[0]) {
237 
238         case 'b':
239             if (bl->max_busy) {
240                 dup = 1;
241                 break;
242             }
243 
244             bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
245             if (bl->max_busy == NGX_ERROR) {
246                 invalid = 1;
247                 break;
248             }
249 
250             continue;
251 
252         case 'w':
253             if (bl->max_waiting) {
254                 dup = 1;
255                 break;
256             }
257 
258             bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
259             if (bl->max_waiting == NGX_ERROR) {
260                 invalid = 1;
261                 break;
262             }
263 
264             continue;
265 
266         case 't':
267             if (bl->timeout) {
268                 dup = 1;
269                 break;
270             }
271 
272             line.len = value[i].len - 2;
273             line.data = value[i].data + 2;
274 
275             bl->timeout = ngx_parse_time(&line, 1);
276             if (bl->timeout == NGX_ERROR) {
277                 invalid = 1;
278                 break;
279             }
280 
281             continue;
282 
283         default:
284             invalid = 1;
285         }
286 
287         if (dup) {
288             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
289                                "duplicate value \"%s\"", value[i].data);
290             return NGX_CONF_ERROR;
291         }
292 
293         if (invalid) {
294             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
295                                "invalid value \"%s\"", value[i].data);
296             return NGX_CONF_ERROR;
297         }
298     }
299 
300     if (bl->timeout == 0 && bl->max_waiting) {
301         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
302                            "busy lock waiting is useless with zero timeout, ignoring");
303     }
304 
305     return NGX_CONF_OK;
306 }
307 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.