changeset 205:4a9a2b1dd6fa

nginx-0.0.1-2003-12-04-17:53:00 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 04 Dec 2003 14:53:00 +0000
parents e0bcfb77d6c7
children 9aa426375256
files auto/sources src/core/ngx_core.h src/core/ngx_rbtree.c src/core/ngx_rbtree.h src/core/ngx_times.c src/core/ngx_times.h src/event/modules/ngx_kqueue_module.c src/event/ngx_event.c src/event/ngx_event.h src/event/ngx_event_accept.c src/event/ngx_event_timer.c src/event/ngx_event_timer.h src/http/ngx_http_core_module.c
diffstat 13 files changed, 498 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/auto/sources
+++ b/auto/sources
@@ -16,6 +16,7 @@ CORE_DEPS="src/core/nginx.h \
             src/core/ngx_file.h \
             src/core/ngx_crc.h \
             src/core/ngx_regex.h \
+            src/core/ngx_rbtree.h \
             src/core/ngx_times.h \
             src/core/ngx_connection.h \
             src/core/ngx_conf_file.h \
@@ -32,6 +33,7 @@ CORE_SRCS="src/core/nginx.c \
             src/core/ngx_inet.c \
             src/core/ngx_file.c \
             src/core/ngx_regex.c \
+            src/core/ngx_rbtree.c \
             src/core/ngx_times.c \
             src/core/ngx_conf_file.c \
             src/core/ngx_garbage_collector.c"
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -30,6 +30,7 @@ typedef struct ngx_connection_s  ngx_con
 #include <ngx_files.h>
 #include <ngx_crc.h>
 #include <ngx_regex.h>
+#include <ngx_rbtree.h>
 #include <ngx_times.h>
 #include <ngx_inet.h>
 #include <ngx_conf_file.h>
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_rbtree.c
@@ -0,0 +1,296 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+/*
+ * The code is based on the algorithm described in the "Introduction
+ * to Algorithms" by Cormen, Leiserson and Rivest.
+ */
+
+#define ngx_rbt_red(node)           ((uintptr_t) (node)->data |= 1)
+#define ngx_rbt_black(node)         ((uintptr_t) (node)->data &= ~1)
+#define ngx_rbt_is_red(node)        ((uintptr_t) (node)->data & 1)
+#define ngx_rbt_is_black(node)      (!ngx_rbt_is_red(node))
+#define ngx_rbt_copy_color(n1, n2)                                            \
+                         ((uintptr_t) (n1)->data |= (uintptr_t) (n2)->data & 1)
+
+
+ngx_inline void ngx_rbtree_left_rotate(ngx_rbtree_t **root, ngx_rbtree_t *node);
+ngx_inline void ngx_rbtree_right_rotate(ngx_rbtree_t **root,
+                                        ngx_rbtree_t *node);
+
+ngx_rbtree_t  sentinel;
+
+
+void ngx_rbtree_insert(ngx_rbtree_t **root, ngx_rbtree_t *node)
+{
+    ngx_rbtree_t  *temp;
+
+    /* a binary tree insert */
+
+    if (*root == &sentinel) {
+        node->parent = &sentinel;
+        node->left = &sentinel;
+        node->right = &sentinel;
+        ngx_rbt_black(node);
+        *root = node;
+
+        return;
+    }
+
+    temp = *root;
+
+    for ( ;; ) {
+        if (node->key < temp->key) {
+            if (temp->left == &sentinel) {
+                temp->left = node;
+                break;
+            }
+
+            temp = temp->left;
+            continue;
+        }
+
+        if (temp->right == &sentinel) {
+            temp->right = node;
+            break;
+        }
+
+        temp = temp->right;
+        continue;
+    }
+
+    node->parent = temp;
+    node->left = &sentinel;
+    node->right = &sentinel;
+
+
+    /* re-balance tree */
+
+    ngx_rbt_red(node);
+
+    while (node->parent && ngx_rbt_is_red(node->parent)) {
+
+        if (node->parent == node->parent->parent->left) {
+            temp = node->parent->parent->right;
+
+            if (ngx_rbt_is_red(temp)) {
+                ngx_rbt_black(node->parent);
+                ngx_rbt_black(temp);
+                ngx_rbt_red(node->parent->parent);
+                node = node->parent->parent;
+
+            } else {
+                if (node == node->parent->right) {
+                    node = node->parent;
+                    ngx_rbtree_left_rotate(root, node);
+                }
+
+                ngx_rbt_black(node->parent);
+                ngx_rbt_red(node->parent->parent);
+                ngx_rbtree_right_rotate(root, node->parent->parent);
+            }
+
+        } else {
+            temp = node->parent->parent->left;
+
+            if (ngx_rbt_is_red(temp)) {
+                ngx_rbt_black(node->parent);
+                ngx_rbt_black(temp);
+                ngx_rbt_red(node->parent->parent);
+                node = node->parent->parent;
+
+            } else {
+                if (node == node->parent->left) {
+                    node = node->parent;
+                    ngx_rbtree_right_rotate(root, node);
+                }
+
+                ngx_rbt_black(node->parent);
+                ngx_rbt_red(node->parent->parent);
+                ngx_rbtree_left_rotate(root, node->parent->parent);
+            }
+        }
+
+    }
+
+    ngx_rbt_black(*root);
+}
+
+
+void ngx_rbtree_delete(ngx_rbtree_t **root, ngx_rbtree_t *node)
+{
+    ngx_rbtree_t  *subst, *temp, *w;
+
+    /* a binary tree delete */
+
+    if (node->left == &sentinel || node->right == &sentinel) {
+        subst = node;
+
+    } else {
+
+        /* find a node successor */
+
+        if (node->right == &sentinel) {
+            temp = node;
+            subst = node->parent;
+
+            while (subst != &sentinel && temp == subst->right) {
+                 temp = subst;
+                 subst = subst->parent;
+            }
+
+        } else {
+            subst = ngx_rbtree_min(node->right);
+        }
+    }
+
+    if (subst->left != &sentinel) {
+        temp = subst->left;
+    } else {
+        temp = subst->right;
+    }
+
+    temp->parent = subst->parent;
+
+    if (subst->parent == &sentinel) {
+        *root = temp;
+
+    } else if (subst == subst->parent->left) {
+        subst->parent->left = temp;
+
+    } else {
+        subst->parent->right = temp;
+    }
+
+    if (subst != node) {
+        node->key = subst->key;
+        node->data = subst->data;
+    }
+
+    if (ngx_rbt_is_red(subst)) {
+        return;
+    }
+
+    /* a delete fixup */
+
+    while (temp->parent != &sentinel && ngx_rbt_is_black(temp)) {
+        if (temp == temp->parent->left) {
+            w = temp->parent->right;
+
+            if (ngx_rbt_is_red(w)) {
+                ngx_rbt_black(w);
+                ngx_rbt_red(temp->parent);
+                ngx_rbtree_left_rotate(root, temp->parent);
+                w = temp->parent->right;
+            }
+
+            if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
+                ngx_rbt_red(w);
+                temp = temp->parent;
+
+            } else {
+                if (ngx_rbt_is_black(w->right)) {
+                    ngx_rbt_black(w->left);
+                    ngx_rbt_red(w);
+                    ngx_rbtree_right_rotate(root, w);
+                    w = temp->parent->right;
+                }
+
+                ngx_rbt_copy_color(w, temp->parent);
+                ngx_rbt_black(temp->parent);
+                ngx_rbt_black(w->right);
+                ngx_rbtree_left_rotate(root, temp->parent);
+                temp = *root;
+            }
+
+        } else {
+            w = temp->parent->left;
+
+            if (ngx_rbt_is_red(w)) {
+                ngx_rbt_black(w);
+                ngx_rbt_red(temp->parent);
+                ngx_rbtree_right_rotate(root, temp->parent);
+                w = temp->parent->left;
+            }
+
+            if (ngx_rbt_is_black(w->right) && ngx_rbt_is_black(w->left)) {
+                ngx_rbt_red(w);
+                temp = temp->parent;
+
+            } else {
+                if (ngx_rbt_is_black(w->left)) {
+                    ngx_rbt_black(w->right);
+                    ngx_rbt_red(w);
+                    ngx_rbtree_left_rotate(root, w);
+                    w = temp->parent->left;
+                }
+
+                ngx_rbt_copy_color(w, temp->parent);
+                ngx_rbt_black(temp->parent);
+                ngx_rbt_black(w->left);
+                ngx_rbtree_right_rotate(root, temp->parent);
+                temp = *root;
+            }
+        }
+    }
+
+    ngx_rbt_black(temp);
+}
+
+
+ngx_inline void ngx_rbtree_left_rotate(ngx_rbtree_t **root, ngx_rbtree_t *node)
+{
+    ngx_rbtree_t  *temp;
+
+    temp = node->right;
+    node->right = temp->left;
+
+    if (temp->left != &sentinel) {
+        temp->left->parent = node;
+    }
+
+    temp->parent = node->parent;
+
+    if (node->parent == &sentinel) {
+        *root = temp;
+
+    } else if (node == node->parent->left) {
+        node->parent->left = temp;
+
+    } else {
+        node->parent->right = temp;
+    }
+
+    temp->left = node;
+    node->parent = temp;
+}
+
+
+ngx_inline void ngx_rbtree_right_rotate(ngx_rbtree_t **root, ngx_rbtree_t *node)
+{
+    ngx_rbtree_t  *temp;
+
+    temp = node->left;
+    node->left = temp->right;
+
+    if (temp->right != &sentinel) {
+        temp->right->parent = node;
+    }
+
+    temp->parent = node->parent;
+
+    if (node->parent == &sentinel) {
+        *root = temp;
+
+    } else if (node == node->parent->right) {
+        node->parent->right = temp;
+
+    } else {
+        node->parent->left = temp;
+    }
+
+    temp->right = node;
+    node->parent = temp;
+}
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_rbtree.h
@@ -0,0 +1,36 @@
+#ifndef _NGX_RBTREE_H_INCLUDED_
+#define _NGX_RBTREE_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct ngx_rbtree_s  ngx_rbtree_t;
+
+struct ngx_rbtree_s {
+   ngx_int_t       key;
+   ngx_rbtree_t   *left;
+   ngx_rbtree_t   *right;
+   ngx_rbtree_t   *parent;
+   void           *data;
+};
+
+extern ngx_rbtree_t  sentinel;
+
+
+void ngx_rbtree_insert(ngx_rbtree_t **root, ngx_rbtree_t *node);
+void ngx_rbtree_delete(ngx_rbtree_t **root, ngx_rbtree_t *node);
+
+
+ngx_inline static ngx_rbtree_t *ngx_rbtree_min(ngx_rbtree_t *root)
+{
+   while (root->left != &sentinel) {
+       root = root->left;
+   }
+
+   return root;
+}
+
+
+#endif /* _NGX_RBTREE_H_INCLUDED_ */
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -3,9 +3,11 @@
 #include <ngx_core.h>
 
 
-time_t       ngx_cached_time;
+time_t            ngx_cached_time;
+ngx_epoch_msec_t  ngx_elapsed_msec;
+ngx_epoch_msec_t  ngx_start_msec;
 
-ngx_tm_t     ngx_cached_gmtime;
+ngx_tm_t          ngx_cached_gmtime;
 
 static char  cached_err_log_time[] = "1970/09/28 12:00:00";
 ngx_str_t    ngx_cached_err_log_time;
@@ -37,6 +39,9 @@ void ngx_time_init()
 
     ngx_gettimeofday(&tv);
     ngx_cached_time = tv.tv_sec;
+    ngx_start_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+    ngx_elapsed_msec = 0;
+
     ngx_time_update();
 }
 
--- a/src/core/ngx_times.h
+++ b/src/core/ngx_times.h
@@ -14,10 +14,13 @@ void ngx_gmtime(time_t t, ngx_tm_t *tp);
 #define ngx_time()   ngx_cached_time
 
 
-extern time_t     ngx_cached_time;
-extern ngx_str_t  ngx_cached_err_log_time;
-extern ngx_str_t  ngx_cached_http_time;
-extern ngx_str_t  ngx_cached_http_log_time;
+extern time_t            ngx_cached_time;
+extern ngx_epoch_msec_t  ngx_elapsed_msec;
+extern ngx_epoch_msec_t  ngx_start_msec;
+
+extern ngx_str_t         ngx_cached_err_log_time;
+extern ngx_str_t         ngx_cached_http_time;
+extern ngx_str_t         ngx_cached_http_log_time;
 
 
 #endif /* _NGX_TIMES_H_INCLUDED_ */
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -360,8 +360,10 @@ static int ngx_kqueue_process_events(ngx
         ts.tv_nsec = (timer % 1000) * 1000000;
         tp = &ts;
 
+#if 0
         ngx_gettimeofday(&tv);
         delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+#endif
 
     } else {
         delta = 0;
@@ -384,28 +386,31 @@ static int ngx_kqueue_process_events(ngx
 
     ngx_gettimeofday(&tv);
 
+#if 1
+    delta = ngx_elapsed_msec;
+#endif
+    ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
+
     if (ngx_cached_time != tv.tv_sec) {
         ngx_cached_time = tv.tv_sec;
         ngx_time_update();
     }
 
     if (timer) {
+        delta = ngx_elapsed_msec - delta;
+
+#if 0
         delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ (int) delta);
-#endif
-
-#if 0
         /*
          * The expired timers must be handled before a processing of the events
          * because the new timers can be added during a processing
          */
 
         ngx_event_expire_timers((ngx_msec_t) delta);
-#endif
 
         ngx_event_set_timer_delta((ngx_msec_t) delta);
+#endif
 
     } else {
         if (events == 0) {
@@ -413,11 +418,11 @@ static int ngx_kqueue_process_events(ngx
                           "kevent() returned no events without timeout");
             return NGX_ERROR;
         }
+    }
 
 #if (NGX_DEBUG_EVENT)
         ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ (int) delta);
 #endif
-    }
 
     if (err) {
         ngx_log_error(NGX_LOG_ALERT, log, err, "kevent() failed");
@@ -510,9 +515,15 @@ static int ngx_kqueue_process_events(ngx
         }
     }
 
+    if (timer && delta) {
+        ngx_event_expire_timers((ngx_msec_t) delta);
+    }
+
+#if 0
     if (timer) {
         ngx_event_expire_timers((ngx_msec_t) delta);
     }
+#endif
 
     return NGX_OK;
 }
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -200,21 +200,10 @@ ngx_log_debug(cycle->log, "TYPE: %d" _ e
         /* required by iocp in "c->write->active = 1" */
         c->write = wev;
 
-#if 0
-        ngx_test_null(rev->log, ngx_palloc(cycle->pool, sizeof(ngx_log_t)),
-                      NGX_ERROR);
-
-        ngx_memcpy(rev->log, c->log, sizeof(ngx_log_t));
-#endif
-
         rev->log = c->log;
         rev->data = c;
         rev->index = NGX_INVALID_INDEX;
 
-#if 0
-        rev->listening = 1;
-#endif
-
         rev->available = 0;
 
 #if (HAVE_DEFERRED_ACCEPT)
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -31,11 +31,14 @@ struct ngx_event_s {
     ngx_event_t     *prev;
     ngx_event_t     *next;
 
+    ngx_rbtree_t     rbtree;
+
+#if 0
     ngx_event_t     *timer_prev;
     ngx_event_t     *timer_next;
 
     ngx_msec_t       timer_delta;
-    ngx_msec_t       timer;
+#endif
 
     ngx_log_t       *log;
 
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -175,6 +175,9 @@ void ngx_event_accept(ngx_event_t *ev)
         rev->index = NGX_INVALID_INDEX;
         wev->index = NGX_INVALID_INDEX;
 
+        rev->rbtree.data = rev;
+        wev->rbtree.data = wev;
+
         rev->data = c;
         wev->data = c;
 
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -4,6 +4,81 @@
 #include <ngx_event.h>
 
 
+ngx_rbtree_t  *ngx_event_timer_rbtree;
+
+
+int ngx_event_timer_init(ngx_cycle_t *cycle)
+{
+    ngx_event_timer_rbtree = &sentinel;
+    sentinel.left = &sentinel;
+    sentinel.right = &sentinel;
+    sentinel.parent = &sentinel;
+
+    return NGX_OK;
+}
+
+
+void ngx_event_timer_done(ngx_cycle_t *cycle)
+{
+}
+
+
+int ngx_event_find_timer(void)
+{
+    ngx_rbtree_t  *node;
+
+    node = ngx_rbtree_min(ngx_event_timer_rbtree);
+
+    if (node == &sentinel) {
+        return 0;
+
+    } else {
+        return node->key * NGX_TIMER_RESOLUTION - ngx_elapsed_msec;
+    }
+}
+
+
+void ngx_event_expire_timers(ngx_msec_t timer)
+{
+    ngx_event_t   *ev;
+    ngx_rbtree_t  *node;
+
+    for ( ;; ) {
+        node = ngx_rbtree_min(ngx_event_timer_rbtree);
+
+        if (node == &sentinel) {
+            break;
+        }
+
+        if ((ngx_msec_t) node->key <=
+                             (ngx_elapsed_msec + timer) / NGX_TIMER_RESOLUTION)
+        {
+            ev = (ngx_event_t *)
+                               ((char *) node - offsetof(ngx_event_t, rbtree));
+
+            ngx_del_timer(ev);
+
+            if (ev->delayed) {
+                ev->delayed = 0;
+                if (ev->ready == 0) {
+                    continue;
+                }
+
+            } else {
+                ev->timedout = 1;
+            }
+
+            ev->event_handler(ev);
+            continue;
+        }
+
+        break;
+    }
+}
+
+
+#if 0
+
 /* TODO: in multithreaded enviroment all timer operations must be
    protected by the single mutex */
 
@@ -275,3 +350,6 @@ void ngx_event_expire_timers(ngx_msec_t 
     }
 #endif
 }
+
+
+#endif
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -7,14 +7,58 @@
 #include <ngx_event.h>
 
 
+/*
+ * 1 msec - 49 days
+ * 10 msec - 1 years 4 months
+ * 50 msec - 6 years 10 months
+ * 100 msec - 13 years 8 months
+ */
+
+#define NGX_TIMER_RESOLUTION  50
+
+
+int  ngx_event_timer_init(ngx_cycle_t *cycle);
+void ngx_event_timer_done(ngx_cycle_t *cycle);
+int  ngx_event_find_timer(void);
+void ngx_event_expire_timers(ngx_msec_t timer);
+
+#if 0
 int  ngx_event_timer_init(ngx_cycle_t *cycle);
 void ngx_event_timer_done(ngx_cycle_t *cycle);
 void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer);
 int  ngx_event_find_timer(void);
 void ngx_event_set_timer_delta(ngx_msec_t timer);
 void ngx_event_expire_timers(ngx_msec_t timer);
+#endif
+
+
+extern ngx_rbtree_t  *ngx_event_timer_rbtree;
+
+
+ngx_inline static void ngx_event_del_timer(ngx_event_t *ev)
+{
+    ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->rbtree);
+
+    ev->timer_set = 0;
+}
 
 
+ngx_inline static void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
+{
+    if (ev->timer_set) {
+        ngx_del_timer(ev);
+    }
+
+    ev->rbtree.key = (ngx_int_t)
+                             (ngx_elapsed_msec + timer) / NGX_TIMER_RESOLUTION;
+
+    ngx_rbtree_insert(&ngx_event_timer_rbtree, &ev->rbtree);
+
+    ev->timer_set = 1;
+}
+
+
+#if 0
 
 ngx_inline static void ngx_event_del_timer(ngx_event_t *ev)
 {
@@ -45,5 +89,7 @@ ngx_inline static void ngx_event_del_tim
     ev->timer_set = 0;
 }
 
+#endif
+
 
 #endif /* _NGX_EVENT_TIMER_H_INCLUDED_ */
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -514,13 +514,7 @@ ngx_log_debug(r->connection->log, "trans
     }
 
     if (clcf->handler) {
-        /*
-         * if the location already has content handler then skip
-         * the translation phase
-         */
-
         r->content_handler = clcf->handler;
-        r->phase++;
     }
 
     return NGX_OK;