
/*
 * Copyright (C) Igor Sysoev
 */


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>


static ngx_int_t ngx_poll_init(ngx_cycle_t *cycle);
static void ngx_poll_done(ngx_cycle_t *cycle);
static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags);
static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags);
static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle);
static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);


static struct pollfd  *event_list;
static int             nevents;

#if 0
static ngx_event_t   **ready_index;
#endif

static ngx_event_t    *accept_events;


static ngx_str_t    poll_name = ngx_string("poll");

ngx_event_module_t  ngx_poll_module_ctx = {
    &poll_name,
    NULL,                                  /* create configuration */
    ngx_poll_init_conf,                    /* init configuration */

    {
        ngx_poll_add_event,                /* add an event */
        ngx_poll_del_event,                /* delete an event */
        ngx_poll_add_event,                /* enable an event */
        ngx_poll_del_event,                /* disable an event */
        NULL,                              /* add an connection */
        NULL,                              /* delete an connection */
        NULL,                              /* process the changes */
        ngx_poll_process_events,           /* process the events */
        ngx_poll_init,                     /* init the events */
        ngx_poll_done                      /* done the events */
    }

};

ngx_module_t  ngx_poll_module = {
    NGX_MODULE_V1,
    &ngx_poll_module_ctx,                  /* module context */
    NULL,                                  /* module directives */
    NGX_EVENT_MODULE,                      /* module type */
    NULL,                                  /* init module */
    NULL                                   /* init process */
};



static ngx_int_t
ngx_poll_init(ngx_cycle_t *cycle)
{
    struct pollfd   *list;

    if (event_list == NULL) {
        nevents = 0;
    }

    if (ngx_process == NGX_PROCESS_WORKER
        || cycle->old_cycle == NULL
        || cycle->old_cycle->connection_n < cycle->connection_n)
    {
        list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
                         cycle->log);
        if (list == NULL) {
            return NGX_ERROR;
        }

        if (event_list) {
            ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
            ngx_free(event_list);
        }

        event_list = list;

#if 0
        if (ready_index) {
            ngx_free(ready_index);
        }

        ready_index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
                                cycle->log);
        if (ready_index == NULL) {
            return NGX_ERROR;
        }
#endif
    }

    ngx_io = ngx_os_io;

    ngx_event_actions = ngx_poll_module_ctx.actions;

    ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT;

    return NGX_OK;
}


static void
ngx_poll_done(ngx_cycle_t *cycle)
{
    ngx_free(event_list);
#if 0
    ngx_free(ready_index);
#endif

    event_list = NULL;
#if 0
    ready_index = NULL;
#endif
}


static ngx_int_t
ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags)
{
    ngx_event_t       *e;
    ngx_connection_t  *c;

    c = ev->data;

    ev->active = 1;

    if (ev->index != NGX_INVALID_INDEX) {
        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
                      "poll event fd:%d ev:%d is already set", c->fd, event);
        return NGX_OK;
    }

    if (event == NGX_READ_EVENT) {
        e = c->write;
#if (NGX_READ_EVENT != POLLIN)
        event = POLLIN;
#endif

    } else {
        e = c->read;
#if (NGX_WRITE_EVENT != POLLOUT)
        event = POLLOUT;
#endif
    }

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                   "poll add event: fd:%d ev:%d", c->fd, event);

    if (e == NULL || e->index == NGX_INVALID_INDEX) {
        event_list[nevents].fd = c->fd;
        event_list[nevents].events = event;
        event_list[nevents].revents = 0;

        ev->index = nevents;
        nevents++;

    } else {
        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                       "poll add index: %d", e->index);

        event_list[e->index].events |= event;
        ev->index = e->index;
    }

    ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;

    return NGX_OK;
}


static ngx_int_t
ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags)
{
    ngx_uint_t          i;
    ngx_cycle_t       **cycle;
    ngx_event_t        *e;
    ngx_connection_t   *c;

    c = ev->data;

    ev->active = 0;

    if (ev->index == NGX_INVALID_INDEX) {
        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
                      "poll event fd:%d ev:%d is already deleted",
                      c->fd, event);
        return NGX_OK;
    }

    if (event == NGX_READ_EVENT) {
        e = c->write;
#if (NGX_READ_EVENT != POLLIN)
        event = POLLIN;
#endif

    } else {
        e = c->read;
#if (NGX_WRITE_EVENT != POLLOUT)
        event = POLLOUT;
#endif
    }

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                   "poll del event: fd:%d ev:%d", c->fd, event);

    if (e == NULL || e->index == NGX_INVALID_INDEX) {
        nevents--;

        if (ev->index < (u_int) nevents) {

            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                           "index: copy event %d to %d", nevents, ev->index);

            event_list[ev->index] = event_list[nevents];

            c = &ngx_cycle->connections[event_list[nevents].fd];

            if (c->fd == -1) {
                cycle = ngx_old_cycles.elts;
                for (i = 0; i < ngx_old_cycles.nelts; i++) {
                    if (cycle[i] == NULL) {
                        continue;
                    }
                    c = &cycle[i]->connections[event_list[nevents].fd];
                    if (c->fd != -1) {
                        break;
                    }
                }
            }

            if (c->fd == -1) {
                ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
                              "unexpected last event");

            } else {
                if (c->read->index == (u_int) nevents) {
                    c->read->index = ev->index;
                }

                if (c->write->index == (u_int) nevents) {
                    c->write->index = ev->index;
                }
            }
        }

    } else {
        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                       "poll del index: %d", e->index);

        event_list[e->index].events &= ~event;
    }

    ev->index = NGX_INVALID_INDEX;

    return NGX_OK;
}


static ngx_int_t
ngx_poll_process_events(ngx_cycle_t *cycle)
{
    int                 ready, revents;
    ngx_int_t           i, nready;
    ngx_uint_t          n, found, lock, expire;
    ngx_msec_t          timer;
    ngx_err_t           err;
    ngx_cycle_t       **old_cycle;
    ngx_event_t        *ev;
    ngx_epoch_msec_t    delta;
    ngx_connection_t   *c;
    struct timeval      tv;

    for ( ;; ) {
        timer = ngx_event_find_timer();

        if (timer != 0) {
            break;
        }

        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "poll expired timer");

        ngx_event_expire_timers((ngx_msec_t)
                                (ngx_elapsed_msec - ngx_old_elapsed_msec));
    }

    /* NGX_TIMER_INFINITE == INFTIM */

    if (timer == NGX_TIMER_INFINITE) {
        expire = 0;

    } else {
        expire = 1;
    }

    ngx_old_elapsed_msec = ngx_elapsed_msec; 

#if (NGX_DEBUG0)
    if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
        for (i = 0; i < nevents; i++) {
            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "poll: %d: fd:%d ev:%04Xd",
                           i, event_list[i].fd, event_list[i].events);
        }
    }
#endif

    if (ngx_accept_mutex) {
        if (ngx_accept_disabled > 0) {
            ngx_accept_disabled--;

        } else {
            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
                return NGX_ERROR;
            }

            if (ngx_accept_mutex_held == 0
                && (timer == NGX_TIMER_INFINITE
                    || timer > ngx_accept_mutex_delay))
            { 
                timer = ngx_accept_mutex_delay;
                expire = 0;
            } 
        }
    }

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %d", timer);

    ready = poll(event_list, (u_int) nevents, (int) timer);

    if (ready == -1) {
        err = ngx_errno;
    } else {
        err = 0;
    }

    ngx_gettimeofday(&tv);
    ngx_time_update(tv.tv_sec);

    delta = ngx_elapsed_msec;
    ngx_elapsed_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000
                                          + tv.tv_usec / 1000 - ngx_start_msec;

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "poll ready %d of %d", ready, nevents);

    if (err) {
        ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
                      cycle->log, err, "poll() failed");
        ngx_accept_mutex_unlock();
        return NGX_ERROR;
    }

    if (timer != NGX_TIMER_INFINITE) {
        delta = ngx_elapsed_msec - delta;

        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "poll timer: %d, delta: %d", timer, (int) delta);
    } else {
        if (ready == 0) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "poll() returned no events without timeout");
            ngx_accept_mutex_unlock();
            return NGX_ERROR;
        }
    }

    if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
        ngx_accept_mutex_unlock();
        return NGX_ERROR;
    }

    lock = 1;
    nready = 0;

    for (i = 0; i < nevents && ready; i++) {

        revents = event_list[i].revents;

#if 0
        ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
                       i, event_list[i].fd, event_list[i].events, revents);
#else
        if (revents) {
            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
                           i, event_list[i].fd, event_list[i].events, revents);
        }
#endif

        if (revents & POLLNVAL) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "poll() error fd:%d ev:%04Xd rev:%04Xd",
                          event_list[i].fd, event_list[i].events, revents);
        }

        if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
                          event_list[i].fd, event_list[i].events, revents);
        }

        if (event_list[i].fd == -1) {
            /*
             * the disabled event, a workaround for our possible bug,
             * see the comment below
             */
            continue;
        }

        c = &ngx_cycle->connections[event_list[i].fd];

        if (c->fd == -1) {
            old_cycle = ngx_old_cycles.elts;
            for (n = 0; n < ngx_old_cycles.nelts; n++) {
                if (old_cycle[n] == NULL) {
                    continue;
                }
                c = &old_cycle[n]->connections[event_list[i].fd];
                if (c->fd != -1) {
                    break;
                }
            }
        }

        if (c->fd == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");

            /*
             * it is certainly our fault and it should be investigated,
             * in the meantime we disable this event to avoid a CPU spinning
             */

            if (i == nevents - 1) {
                nevents--;
            } else {
                event_list[i].fd = -1;
            }

            continue;
        }

        if ((revents & (POLLERR|POLLHUP|POLLNVAL))
             && (revents & (POLLIN|POLLOUT)) == 0)
        {
            /*
             * if the error events were returned without POLLIN or POLLOUT,
             * then add these flags to handle the events at least in one
             * active handler
             */

            revents |= POLLIN|POLLOUT;
        }

        found = 0;

        if (revents & POLLIN) {
            found = 1;

            ev = c->read;
            ev->ready = 1;

            if (ev->oneshot) {
                if (ev->timer_set) {
                    ngx_del_timer(ev);
                }
                ngx_poll_del_event(ev, NGX_READ_EVENT, 0);
            }

            if (ev->accept) {
                ev->next = accept_events;
                accept_events = ev;
            } else {
                ngx_post_event(ev);
            }

#if 0
            ready_index[nready++] = c->read;
#endif
        }

        if (revents & POLLOUT) {
            found = 1;
            ev = c->write;
            ev->ready = 1;

            if (ev->oneshot) {
                if (ev->timer_set) {
                    ngx_del_timer(ev);
                }
                ngx_poll_del_event(ev, NGX_WRITE_EVENT, 0);
            }

            ngx_post_event(ev);
#if 0
            ready_index[nready++] = c->write;
#endif
        }

        if (found) {
            ready--;
            continue;
        }
    }

#if 0
    for (i = 0; i < nready; i++) {
        ev = ready_index[i];

        if (!ev->active) {
            continue;
        }

        ev->ready = 1;

        if (ev->oneshot) {
            if (ev->timer_set) {
                ngx_del_timer(ev);
            }

            if (ev->write) {
                ngx_poll_del_event(ev, NGX_WRITE_EVENT, 0);
            } else {
                ngx_poll_del_event(ev, NGX_READ_EVENT, 0);
            }
        }

        ev->handler(ev);
    }
#endif

    ev = accept_events;

    for ( ;; ) {

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                      "accept event %p", ev);

        if (ev == NULL) {
            break;
        }

        ngx_mutex_unlock(ngx_posted_events_mutex);

        ev->handler(ev);

        if (ngx_accept_disabled > 0) {
            lock = 0;
            break;
        }

        ev = ev->next;

        if (ev == NULL) {
            lock = 0;
            break;
        }

        if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
            ngx_accept_mutex_unlock();
            return NGX_ERROR;
        }

    }

    ngx_accept_mutex_unlock();
    accept_events = NULL;

    if (lock) {
        ngx_mutex_unlock(ngx_posted_events_mutex);
    }

    if (ready != 0) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
    }

    if (expire && delta) {
        ngx_event_expire_timers((ngx_msec_t) delta);
    }

    if (!ngx_threaded) {
        ngx_event_process_posted(cycle);
    }

    return nready;
}


static char *
ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
{
    ngx_event_conf_t  *ecf;

    ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);

    if (ecf->use != ngx_poll_module.ctx_index) {
        return NGX_CONF_OK;
    }

#if (NGX_THREADS)

    ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                  "poll() is not supported in the threaded mode");
    return NGX_CONF_ERROR;

#else

    return NGX_CONF_OK;

#endif
}
