diff 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
line wrap: on
line diff
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -4,42 +4,151 @@
 #include <ngx_http.h>
 
 
-int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5)
+
+static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
+                                            ngx_http_busy_lock_ctx_t *bc,
+                                            int lock);
+
+
+int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
+{
+    if (bl->busy < bl->max_busy) {
+        bl->busy++;
+
+        if (bc->time) {
+            bc->time = 0;
+            bl->waiting--;
+        }
+
+        return NGX_OK;
+    }
+
+    if (bc->time) {
+        if (bc->time < bl->timeout) {
+            ngx_add_timer(bc->event, 1000);
+            return NGX_AGAIN;
+        }
+
+        bl->waiting--;
+        return NGX_DONE;
+
+    }
+
+    if (bl->timeout == 0) {
+        return NGX_DONE;
+    }
+
+    if (bl->waiting < bl->max_waiting) {
+        bl->waiting++;
+        ngx_add_timer(bc->event, 1000);
+        bc->event->event_handler = bc->event_handler;
+
+        /* TODO: ngx_handle_level_read_event() */
+
+        return NGX_AGAIN;
+    }
+
+    return NGX_ERROR;
+}
+
+
+int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
+                                ngx_http_busy_lock_ctx_t *bc, int lock)
 {
-    int    i, b, busy, free;
+    int  rc;
+
+    rc = ngx_http_busy_lock_look_cachable(bl, bc, lock);
+
+ngx_log_debug(bc->event->log, "BUSYLOCK: %d" _ rc);
+
+    if (rc == NGX_OK) {  /* no the same request, there's free slot */
+        return NGX_OK;
+    }
+
+    if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
+        return NGX_OK;
+    }
+
+    /* rc == NGX_AGAIN:  the same request */
+
+    if (bc->time) {
+        if (bc->time < bl->timeout) {
+            ngx_add_timer(bc->event, 1000);
+            return NGX_AGAIN;
+        }
+
+        bl->waiting--;
+        return NGX_DONE;
+
+    }
+
+    if (bl->timeout == 0) {
+        return NGX_DONE;
+    }
+
+    if (bl->waiting < bl->max_waiting) {
+        bl->waiting++;
+        ngx_add_timer(bc->event, 1000);
+        bc->event->event_handler = bc->event_handler;
+
+        /* TODO: ngx_handle_level_read_event() */
+
+        return NGX_AGAIN;
+    }
+
+    return NGX_ERROR;
+}
+
+
+void ngx_http_busy_unlock_cachable(ngx_http_busy_lock_t *bl,
+                                   ngx_http_busy_lock_ctx_t *bc)
+{
+    bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
+    bl->cachable--;
+    bl->busy--;
+}
+
+
+static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
+                                            ngx_http_busy_lock_ctx_t *bc,
+                                            int lock)
+{
+    int    i, b, cachable, free;
     u_int  mask;
 
     b = 0;
-    busy = 0;
+    cachable = 0;
     free = -1;
 
 #if (NGX_SUPPRESS_WARN)
     mask = 0;
 #endif
 
-    for (i = 0; i < bl->max_conn; i++) {
+    for (i = 0; i < bl->max_busy; i++) {
 
         if ((b & 7) == 0) {
-            mask = bl->busy_mask[i / 8];
+            mask = bl->md5_mask[i / 8];
         }
 
         if (mask & 1) {
-            if (ngx_memcmp(&bl->busy[i * 16], md5, 16) == 0) {
+            if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
                 return NGX_AGAIN;
             }
-            busy++;
+            cachable++;
 
         } else if (free == -1) {
             free = i;
         }
 
-        if (busy == bl->busy_n) {
-            if (busy < bl->max_conn) {
+#if 1
+        if (cachable == bl->cachable) {
+            if (free == -1 && cachable < bl->max_busy) {
                 free = i + 1;
             }
 
             break;
         }
+#endif
 
         mask >>= 1;
         b++;
@@ -49,11 +158,18 @@ int ngx_http_busy_lock(ngx_http_busy_loc
         return NGX_ERROR;
     }
 
-    ngx_memcpy(&bl->busy[free * 16], md5, 16);
-    bl->busy_mask[free / 8] |= free % 8;
+    if (lock) {
+        if (bl->busy == bl->max_busy) {
+            return NGX_ERROR;
+        }
 
-    bl->busy_n++;
-    bl->conn_n++;
+        ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
+        bl->md5_mask[free / 8] |= 1 << (free & 7);
+        bc->slot = free;
+
+        bl->cachable++;
+        bl->busy++;
+    }
 
     return NGX_OK;
 }
@@ -64,8 +180,8 @@ char *ngx_http_set_busy_lock_slot(ngx_co
 {
     char  *p = conf;
 
-    int                    i;
-    ngx_str_t             *value;
+    int                    i, dup, invalid;
+    ngx_str_t             *value, line;
     ngx_http_busy_lock_t  *bl, **blp;
 
     blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
@@ -79,57 +195,86 @@ char *ngx_http_set_busy_lock_slot(ngx_co
     }
     *blp = bl;
 
+    dup = 0;
+    invalid = 0;
     value = (ngx_str_t *) cf->args->elts;
 
-    for (i = 1; i < 4; i++) {
+    for (i = 1; i < cf->args->nelts; i++) {
 
-        if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "c:", 2) == 0) {
-            if (bl->max_conn) {
-                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "duplicate \"%s\"", value[i].data);
-                return NGX_CONF_ERROR;
+        if (value[i].data[1] != '=') {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid value \"%s\"", value[i].data);
+            return NGX_CONF_ERROR;
+        }
+
+        switch (value[i].data[0]) {
+
+        case 'b':
+            if (bl->max_busy) {
+                dup = 1;
+                break;
             }
 
-            bl->max_conn = ngx_atoi(value[i].data + 2, value[i].len - 2);
-            if (bl->max_conn == NGX_ERROR) {
-                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid value \"%s\"", value[i].data);
-                return NGX_CONF_ERROR;
+            bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
+            if (bl->max_busy == NGX_ERROR) {
+                invalid = 1;
+                break;
             }
 
             continue;
-        }
 
-        if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "w:", 2) == 0) {
+        case 'w':
             if (bl->max_waiting) {
-                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "duplicate \"%s\"", value[i].data);
-                return NGX_CONF_ERROR;
+                dup = 1;
+                break;
             }
 
             bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
             if (bl->max_waiting == NGX_ERROR) {
-                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid value \"%s\"", value[i].data);
-                return NGX_CONF_ERROR;
+                invalid = 1;
+                break;
             }
 
             continue;
+
+        case 't':
+            if (bl->timeout) {
+                dup = 1;
+                break;
+            }
+
+            line.len = value[i].len - 2;
+            line.data = value[i].data + 2;
+
+            bl->timeout = ngx_parse_time(&line, 1);
+            if (bl->timeout == NGX_ERROR) {
+                invalid = 1;
+                break;
+            }
+
+            continue;
+
+        default:
+            invalid = 1;
         }
 
-        if (bl->timeout) {
+        if (dup) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "duplicate timeout \"%s\"", value[i].data);
+                               "duplicate value \"%s\"", value[i].data);
             return NGX_CONF_ERROR;
         }
 
-        bl->timeout = ngx_parse_time(&value[1], 1);
-        if (bl->timeout == NGX_ERROR) {
+        if (invalid) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid timeout \"%s\"", value[i].data);
+                               "invalid value \"%s\"", value[i].data);
             return NGX_CONF_ERROR;
         }
     }
 
+    if (bl->timeout == 0 && bl->max_waiting) {
+        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                           "busy lock waiting is useless with zero timeout");
+    }
+
     return NGX_CONF_OK;
 }