nginx-0.0.1-2003-10-12-20:49:16 import
diff --git a/src/event/modules/ngx_aio_module.c b/src/event/modules/ngx_aio_module.c
index cdfb1b0..4b89c2a 100644
--- a/src/event/modules/ngx_aio_module.c
+++ b/src/event/modules/ngx_aio_module.c
@@ -68,7 +68,7 @@
 
     ngx_io = ngx_os_aio;
 
-    ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_USE_AIO_EVENT;
+    ngx_event_flags = NGX_USE_AIO_EVENT;
     ngx_event_actions = ngx_aio_module_ctx.actions;
 
 
diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c
index e55f17c..c21abde 100644
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -173,7 +173,7 @@
 
     ngx_event_actions = ngx_devpoll_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT|NGX_USE_LEVEL_EVENT;
+    ngx_event_flags = NGX_USE_LEVEL_EVENT;
 
     return NGX_OK;
 }
diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c
index 2f31eb6..86d763b 100644
--- a/src/event/modules/ngx_iocp_module.c
+++ b/src/event/modules/ngx_iocp_module.c
@@ -105,7 +105,7 @@
 
     ngx_event_actions = ngx_iocp_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_HAVE_IOCP_EVENT;
+    ngx_event_flags = NGX_USE_AIO_EVENT|NGX_USE_IOCP_EVENT;
 
     return NGX_OK;
 }
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c
index d0a9d2e..14eb270 100644
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -151,10 +151,9 @@
 
     ngx_event_actions = ngx_kqueue_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
-                     |NGX_HAVE_ONESHOT_EVENT
+    ngx_event_flags = NGX_USE_ONESHOT_EVENT
 #if (HAVE_CLEAR_EVENT)
-                     |NGX_HAVE_CLEAR_EVENT
+                     |NGX_USE_CLEAR_EVENT
 #else
                      |NGX_USE_LEVEL_EVENT
 #endif
@@ -238,9 +237,11 @@
         return NGX_OK;
     }
 
-    /* when the file descriptor is closed a kqueue automatically deletes
-       its filters so we do not need to delete explicity the event
-       before the closing the file descriptor */
+    /*
+     * when the file descriptor is closed a kqueue automatically deletes
+     * its filters so we do not need to delete explicity the event
+     * before the closing the file descriptor.
+     */
 
     if (flags & NGX_CLOSE_EVENT) {
         return NGX_OK;
@@ -427,13 +428,17 @@
 
             if (ev->oneshot && ev->timer_set) {
                 ngx_del_timer(ev);
-                ev->timer_set = 0;
             }
 
-            /* fall through */
+            ev->ready = 1;
+
+            ev->event_handler(ev);
+
+            break;
 
         case EVFILT_AIO:
             ev->ready = 1;
+            ev->active = 0;
 
             ev->event_handler(ev);
 
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c
index 4d50b4a..9d2f8ac 100644
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -109,9 +109,7 @@
 
     ngx_event_actions = ngx_poll_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
-                      |NGX_HAVE_ONESHOT_EVENT
-                      |NGX_USE_LEVEL_EVENT;
+    ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT;
 
     return NGX_OK;
 }
@@ -364,7 +362,6 @@
         if (ev->oneshot) {
             if (ev->timer_set) {
                 ngx_del_timer(ev);
-                ev->timer_set = 0;
             }
 
             if (ev->write) {
diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c
index 1f8a5d9..7924766 100644
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -108,9 +108,7 @@
 
     ngx_event_actions = ngx_select_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
-                      |NGX_HAVE_ONESHOT_EVENT
-                      |NGX_USE_LEVEL_EVENT;
+    ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT;
 
 #if (WIN32)
     max_read = max_write = 0;
@@ -401,7 +399,6 @@
         if (ev->oneshot) {
             if (ev->timer_set) {
                 ngx_del_timer(ev);
-                ev->timer_set = 0;
             }
 
             if (ev->write) {
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 7c709e3..71bf45d 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -224,7 +224,7 @@
         /* required by poll */
         wev->index = NGX_INVALID_INDEX;
 
-        if ((ngx_event_flags & NGX_HAVE_IOCP_EVENT) == 0) {
+        if ((ngx_event_flags & NGX_USE_IOCP_EVENT) == 0) {
             if (s[i].remain) {
 
                 if (ngx_del_event(&cycle->old_cycle->read_events[fd],
@@ -238,7 +238,7 @@
 
 #if (WIN32)
 
-        if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+        if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
             rev->event_handler = &ngx_event_acceptex;
 
             if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 8bb2017..643ea2b 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -24,9 +24,6 @@
     void            *data;
     void           (*event_handler)(ngx_event_t *ev);
 
-#if 0
-    int            (*close_handler)(ngx_event_t *ev);
-#endif
     void            *context;
     char            *action;
 
@@ -35,9 +32,6 @@
     ngx_event_t     *prev;     /* queue in mutex(), aio_read(), aio_write()  */
     ngx_event_t     *next;     /*                                            */
 
-#if 0
-    int            (*timer_handler)(ngx_event_t *ev);
-#endif
     ngx_event_t     *timer_prev;
     ngx_event_t     *timer_next;
 
@@ -61,17 +55,26 @@
 #endif
     unsigned         write:1;
 
-    unsigned         instance:1;  /* used to detect stale events in kqueue,
-                                     rt signals and epoll */
+    /* used to detect stale events in kqueue, rt signals and epoll */
+    unsigned         instance:1;
 
+    /*
+     * event was passed or would be passed to a kernel;
+     * the posted aio operation.
+     */
     unsigned         active:1;
+
+    /* ready event; the complete aio operation */
     unsigned         ready:1;
+
     unsigned         timedout:1;
-    unsigned         blocked:1;
     unsigned         timer_set:1;
+
+#if 1
+    unsigned         blocked:1;
+#endif
     unsigned         delayed:1;
 
-    unsigned         process:1;
     unsigned         read_discarded:1;
 
     unsigned         ignore_econnreset:1;
@@ -156,50 +159,68 @@
 } ngx_event_actions_t;
 
 
-/* The event filter requires to read/write the whole data -
-   select, poll, /dev/poll, kqueue. */
-#define NGX_HAVE_LEVEL_EVENT    0x00000001
+/*
+ * The event filter requires to read/write the whole data -
+ * select, poll, /dev/poll, kqueue.
+ */
+#define NGX_USE_LEVEL_EVENT    0x00000001
 
-/* The event filter is deleted after a notification without an additional
-   syscall - select, poll, kqueue.  */
-#define NGX_HAVE_ONESHOT_EVENT  0x00000002
+/*
+ * The event filter is deleted after a notification without an additional
+ * syscall - select, poll, kqueue.
+ */
+#define NGX_USE_ONESHOT_EVENT  0x00000002
 
-/* The event filter notifies only the changes and an initial level - kqueue */
-#define NGX_HAVE_CLEAR_EVENT    0x00000004
+/*
+ *  The event filter notifies only the changes and an initial level - kqueue.
+ */
+#define NGX_USE_CLEAR_EVENT    0x00000004
 
-/* The event filter has kqueue features - the eof flag, errno,
-   available data, etc */
-#define NGX_HAVE_KQUEUE_EVENT   0x00000008
+/*
+ * The event filter has kqueue features - the eof flag, errno,
+ * available data, etc
+ */
+#define NGX_HAVE_KQUEUE_EVENT  0x00000008
 
-/* The event filter supports low water mark - kqueue's NOTE_LOWAT.
-   kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag */
-#define NGX_HAVE_LOWAT_EVENT    0x00000010
+/*
+ * The event filter supports low water mark - kqueue's NOTE_LOWAT.
+ * kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag.
+ */
+#define NGX_HAVE_LOWAT_EVENT   0x00000010
 
-/* The event filter notifies only the changes (the edges)
-   but not an initial level - epoll */
-#define NGX_HAVE_EDGE_EVENT     0x00000020
+/*
+ * The event filter notifies only the changes (the edges)
+ * but not an initial level - epoll.
+ */
+#define NGX_USE_EDGE_EVENT     0x00000020
 
-/* No need to add or delete the event filters - rt signals */
-#define NGX_HAVE_SIGIO_EVENT    0x00000040
+/*
+ * No need to add or delete the event filters - rt signals.
+ */
+#define NGX_USE_SIGIO_EVENT    0x00000040
 
-/* No need to add or delete the event filters - overlapped, aio_read, aioread */
-#define NGX_HAVE_AIO_EVENT      0x00000080
+/*
+ * No need to add or delete the event filters - overlapped, aio_read,
+ * aioread, io_submit.
+ */
+#define NGX_USE_AIO_EVENT      0x00000080
 
-/* Need to add socket or handle only once - i/o completion port.
-   It also requires HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT to be set */
-#define NGX_HAVE_IOCP_EVENT     0x00000100
+/*
+ * Need to add socket or handle only once - i/o completion port.
+ * It also requires HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT to be set.
+ */
+#define NGX_USE_IOCP_EVENT     0x00000100
 
 
-#define NGX_USE_LEVEL_EVENT     0x00010000
-#define NGX_USE_AIO_EVENT       0x00020000
 
-
-/* Event filter is deleted before closing file.
-   Has no meaning for select, poll, epoll.
-
-   kqueue:     kqueue deletes event filters for file that closed
-               so we need only to delete filters in user-level batch array
-   /dev/poll:  we need to flush POLLREMOVE event before closing file */
+/*
+ * The event filter is deleted before the closing file.
+ * Has no meaning for select, poll, epoll.
+ *
+ * kqueue:     kqueue deletes event filters for file that closed
+ *             so we need only to delete filters in user-level batch array
+ * /dev/poll:  we need to flush POLLREMOVE event before closing file
+ */
 
 #define NGX_CLOSE_EVENT         1
 
@@ -209,10 +230,12 @@
 #define NGX_READ_EVENT     EVFILT_READ
 #define NGX_WRITE_EVENT    EVFILT_WRITE
 
-/* NGX_CLOSE_EVENT is the module flag and it would not go into a kernel
-   so we need to choose the value that would not interfere with any existent
-   and future flags. kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR.
-   They are reserved and cleared on a kernel entrance */
+/*
+ * NGX_CLOSE_EVENT is the module flag and it would not go into a kernel
+ * so we need to choose the value that would not interfere with any existent
+ * and future flags.  kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR.
+ * They are reserved and cleared on a kernel entrance.
+ */
 #undef  NGX_CLOSE_EVENT
 #define NGX_CLOSE_EVENT    EV_FLAG1
 
@@ -383,14 +406,14 @@
 
 ngx_inline static int ngx_handle_read_event(ngx_event_t *rev)
 {
-    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+    if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_EDGE_EVENT)) {
 
         /* aio, iocp, epoll */
 
         return NGX_OK;
     }
 
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
+    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
         /* kqueue */
 
@@ -426,16 +449,41 @@
 }
 
 
+ngx_inline static int ngx_handle_level_read_event(ngx_event_t *rev)
+{
+    if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
+        if (!rev->active && !rev->ready) {
+            if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
+                                                                == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+
+        if (rev->active && rev->ready) {
+            if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
 ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, int lowat)
 {
-    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+    if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_EDGE_EVENT)) {
 
         /* aio, iocp, epoll */
 
         return NGX_OK;
     }
 
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
+    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
         /* kqueue */
 
@@ -478,6 +526,30 @@
 }
 
 
+ngx_inline static int ngx_handle_level_write_event(ngx_event_t *wev)
+{
+    if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
+        if (!wev->active && !wev->ready) {
+            if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
+                                                                == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+
+        if (wev->active && wev->ready) {
+            if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+    }
+
+    return NGX_OK;
+}
+
 
 /* ***************************** */
 
diff --git a/src/event/ngx_event_close.c b/src/event/ngx_event_close.c
index 06e9117..c57c195 100644
--- a/src/event/ngx_event_close.c
+++ b/src/event/ngx_event_close.c
@@ -20,12 +20,10 @@
 
     if (c->read->timer_set) {
         ngx_del_timer(c->read);
-        c->read->timer_set = 0;
     }
 
     if (c->write->timer_set) {
         ngx_del_timer(c->write);
-        c->write->timer_set = 0;
     }
 
     ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index 72031d9..b2b70d4 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -202,7 +202,7 @@
 
     /* TODO: epoll, aio, iocp */
 
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {     /* kqueue */
+    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {     /* kqueue */
         event = NGX_CLEAR_EVENT;
 
     } else {                                  /* select, poll, /dev/poll */
diff --git a/src/event/ngx_event_proxy.c b/src/event/ngx_event_proxy.c
index 71bae95..b49b6b9 100644
--- a/src/event/ngx_event_proxy.c
+++ b/src/event/ngx_event_proxy.c
@@ -584,7 +584,7 @@
 
 int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p)
 {
-    int           i, rc, size;
+    int           rc, size;
     ngx_hunk_t   *h;
     ngx_chain_t  *entry, *next, *saved_in, *saved_read;
 
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index b70bafb..53ca9cd 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -4,7 +4,7 @@
 #include <ngx_event.h>
 
 
-/* in multithreaded enviroment all timer operations must be
+/* TODO: in multithreaded enviroment all timer operations must be
    protected by the single mutex */
 
 
@@ -70,11 +70,18 @@
 void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
 {
     ngx_event_t  *e, *queue;
+#if (NGX_DEBUG_EVENT)
+    ngx_connection_t *c;
+#endif
+
+    if (ev->timer_set) {
+        ngx_del_timer(ev);
+    }
 
 #if (NGX_DEBUG_EVENT)
-    ngx_connection_t *c = ev->data;
-    ngx_log_debug(ev->log, "set timer: %d:%d, slot: %d" _
-                  c->fd _ timer _ ngx_timer_cur_queue);
+    c = ev->data;
+    ngx_log_debug(ev->log, "set timer: %d:%d:%d, slot: %d" _
+                  c->fd _ ev->write _ timer _ ngx_timer_cur_queue);
 #endif
 
     if (ev->timer_next || ev->timer_prev) {
@@ -107,6 +114,10 @@
 
     e->timer_prev->timer_next = ev;
     e->timer_prev = ev;
+
+    ev->timer_set = 1;
+
+    return;
 }
 
 
@@ -129,9 +140,9 @@
 
     if (timer == NGX_MAX_MSEC) {
         return 0;
-    } else {
-        return timer;
     }
+
+    return timer;
 }
 
 
@@ -190,6 +201,10 @@
         timer += ngx_temp_timer_queue.timer_next->timer_delta;
         ev = ngx_temp_timer_queue.timer_next;
 
+#if (NGX_DEBUG_EVENT)
+        ngx_log_debug(ev->log, "process temp timer queue");
+#endif
+
         ngx_del_timer(ev);
         ngx_add_timer(ev, timer);
     }
diff --git a/src/event/ngx_event_timer.h b/src/event/ngx_event_timer.h
index 7a6c52c..565b233 100644
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -19,7 +19,7 @@
 {
 #if (NGX_DEBUG_EVENT)
     ngx_connection_t *c = ev->data;
-    ngx_log_debug(ev->log, "del timer: %d" _ c->fd);
+    ngx_log_debug(ev->log, "del timer: %d:%d" _ c->fd _ ev->write);
 #endif
 
     if (!ev->timer_next || !ev->timer_prev) {
@@ -40,6 +40,8 @@
     if (ev->timer_prev) {
         ev->timer_prev = NULL;
     }
+
+    ev->timer_set = 0;
 }