示例#1
0
static ngx_int_t
ngx_http_ip_blacklist_manager(void)
{
    ngx_queue_t                               *node;
    ngx_queue_t                               *tmp;
    ngx_http_ip_blacklist_tree_t              *blacklist;
    ngx_http_ip_blacklist_t                   *bn;

    blacklist = ngx_http_ip_blacklist_shm_zone->data;

    ngx_shmtx_lock(&blacklist->shpool->mutex);

    if (ngx_queue_empty(&blacklist->garbage)) {
        goto out;
    }

    for (node = ngx_queue_head(&blacklist->garbage);
            node != ngx_queue_sentinel(&blacklist->garbage);
            node = ngx_queue_next(node)) {
        bn = ngx_queue_data(node, ngx_http_ip_blacklist_t, queue);
        if (bn->blacklist) {
            if (bn->timeout <= ngx_time()) {
                if (bn->ref != 0) {
                    /* wait for request cleanup handler to delete this */
                    bn->timed = 1;
                    bn->blacklist = 0;

                    goto out;
                }
                /* blacklist timed out */
                tmp = node;
                node = ngx_queue_prev(node);

                ngx_rbtree_delete(&blacklist->blacklist, &bn->node);
                ngx_queue_remove(tmp);
                ngx_slab_free_locked(blacklist->shpool, bn);
            }
        } else {
            if (bn->ref == 0) {
                tmp = node;
                node = ngx_queue_prev(node);

                ngx_rbtree_delete(&blacklist->blacklist, &bn->node);
                ngx_queue_remove(tmp);
                ngx_slab_free_locked(blacklist->shpool, bn);
            } else {
                /* wait for request cleanup handler to delete this */
                bn->timed = 1;
            }
        }
    }

out:
    ngx_shmtx_unlock(&blacklist->shpool->mutex);

    return NGX_OK;
}
示例#2
0
void ngx_event_expire_timers(void)
{
   ngx_event_t *ev;
   ngx_rbtree_node_t *node, *root, *sentinel;

   sentinel = ngx_event_timer_rbtree.sentinel;

   for (;;) {

      root = ngx_event_timer_rbtree.root;
      if (root == sentinel) {
         return;
      }

      node = ngx_rbtree_min(root, sentinel);

      /* node->key <= ngx_current_time */

      if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) {
         ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));

         ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);

         ev->timer_set = 0;

         ev->timedout = 1;

         ev->handler(ev);

         continue;
      }

      break;
   }
}
示例#3
0
static void
ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
     ngx_slab_pool_t *shpool, ngx_uint_t n)
{
    time_t              now, then;
    ngx_queue_t        *q;
    ngx_ssl_sess_id_t  *sess_id;

    now = ngx_time();

    while (n < 3) {
        
        if (ngx_queue_empty(&cache->expire_queue)) {
            return;
        }

        q = ngx_queue_last(&cache->expire_queue);

        sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);

        then = (time_t) sess_id->session->peer_cert;
        if (n++ != 0 && then > now) {
            return;
        }

        ngx_queue_remove(q);

        ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);

        ngx_slab_free_locked(shpool, sess_id->session);

        ngx_slab_free_locked(shpool, sess_id);
    }
}
示例#4
0
static void
ngx_http_ip_blacklist_cleanup(void *data)
{
    ngx_http_request_t           *r = data;
    ngx_http_ip_blacklist_t      *node;
    ngx_http_ip_blacklist_tree_t *blacklist;


    if (!r->ip_blacklist_node) {
        return;
    }

    node = r->ip_blacklist_node;

    blacklist = ngx_http_ip_blacklist_shm_zone->data;
    ngx_shmtx_lock(&blacklist->shpool->mutex);

    node->ref--;

    if (node->timed && node->ref == 0) {
        /* this means the node is timed out, delete it */
        ngx_rbtree_delete(&blacklist->blacklist, &node->node);
        ngx_queue_remove(&node->queue);
        ngx_slab_free_locked(blacklist->shpool, node);
    }

    ngx_shmtx_unlock(&blacklist->shpool->mutex);
    return;
}
static void
ngx_open_file_cache_remove(ngx_event_t *ev)
{
    ngx_cached_open_file_t       *file;
    ngx_open_file_cache_event_t  *fev;

    fev = ev->data;
    file = fev->file;

    ngx_queue_remove(&file->queue);

    ngx_rbtree_delete(&fev->cache->rbtree, &file->node);

    fev->cache->current--;

    /* NGX_ONESHOT_EVENT was already deleted */
    file->event = NULL;
    file->use_event = 0;

    file->close = 1;

    ngx_close_cached_file(fev->cache, file, 0, ev->log);

    /* free memory only when fev->cache and fev->file are already not needed */

    ngx_free(ev->data);
    ngx_free(ev);
}
static void
ngx_http_limit_speed_cleanup(void *data)
{
    ngx_http_limit_speed_cleanup_t  *lscln = data;

    ngx_slab_pool_t                 *shpool;
    ngx_rbtree_node_t               *node;
    ngx_http_limit_speed_ctx_t      *ctx;
    ngx_http_limit_speed_node_t     *ls;

    ctx = lscln->shm_zone->data;
    shpool = (ngx_slab_pool_t *) lscln->shm_zone->shm.addr;
    node = lscln->node;
    ls = (ngx_http_limit_speed_node_t *) &node->color;

    ngx_shmtx_lock(&shpool->mutex);

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lscln->shm_zone->shm.log, 0,
                   "limit speed cleanup: %08XD %d", node->key, ls->conn);

    ls->conn--;

    if (ls->conn == 0) {
        ngx_rbtree_delete(ctx->rbtree, node);
        ngx_slab_free_locked(shpool, node);
    }

    ngx_shmtx_unlock(&shpool->mutex);
}
static void
ngx_http_req_status_expire(void *conf)
{
    ngx_queue_t                     *q;
    ngx_http_req_status_zone_t      *ctx = conf;
    ngx_http_req_status_node_t      *ssn;

    if (ngx_queue_empty(&ctx->sh->queue)) {
        return;
    }

    if (ctx->sh->expire_lock > ngx_time()){
        return;
    }

    q =  ngx_queue_last(&ctx->sh->queue);

    ssn = ngx_queue_data(q, ngx_http_req_status_node_t, queue);

    if (!ssn->data.requests || (ngx_current_msec > ssn->last_traffic_update &&
                ngx_current_msec - ssn->last_traffic_update >= 10 * 1000)){
        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                "req-status, release node, zone = \"%V\", key = \"%s\"",
                &ctx->shm_zone->shm.name, ssn->key);

        ngx_queue_remove(q);

        ngx_rbtree_delete(&ctx->sh->rbtree, &ssn->node);

        ngx_slab_free_locked(ctx->shpool, ssn);
    }
}
static void
ngx_http_limit_conn_cleanup(void *data)
{
    syslog(LOG_INFO, "[%s:%s:%d]", __FILE__, __func__, __LINE__);
    ngx_http_limit_conn_cleanup_t  *lccln = data;

    ngx_slab_pool_t             *shpool;
    ngx_rbtree_node_t           *node;
    ngx_http_limit_conn_ctx_t   *ctx;
    ngx_http_limit_conn_node_t  *lc;

    ctx = lccln->shm_zone->data;
    shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
    node = lccln->node;
    lc = (ngx_http_limit_conn_node_t *) &node->color;

    ngx_shmtx_lock(&shpool->mutex);

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
                   "limit conn cleanup: %08XD %d", node->key, lc->conn);

    lc->conn--;

    if (lc->conn == 0) {
        ngx_rbtree_delete(ctx->rbtree, node);
        ngx_slab_free_locked(shpool, node);
    }

    ngx_shmtx_unlock(&shpool->mutex);
}
static void
ngx_http_limit_traffic_rate_filter_cleanup(void *data) {
    ngx_http_limit_traffic_rate_filter_cleanup_t  *lircln = data;

    ngx_slab_pool_t             *shpool;
    ngx_rbtree_node_t           *node;
    ngx_http_limit_traffic_rate_filter_ctx_t   *ctx;
    ngx_http_limit_traffic_rate_filter_node_t  *lir;

    ctx = lircln->shm_zone->data;
    shpool = (ngx_slab_pool_t *) lircln->shm_zone->shm.addr;
    node = lircln->node;
    lir = (ngx_http_limit_traffic_rate_filter_node_t *) &node->color;

    ngx_shmtx_lock(&shpool->mutex);

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lircln->shm_zone->shm.log, 0,
                   "limit traffic rate cleanup: %08XD %d", node->key, lir->conn);

    lir->conn--;

    if (lir->conn == 0) {
        ngx_rbtree_delete(ctx->rbtree, node);
        ngx_slab_free_locked(shpool, node);
    }

    ngx_shmtx_unlock(&shpool->mutex);
}
示例#10
0
static void
ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree)
{
    ngx_resolver_ctx_t   *ctx, *next;
    ngx_resolver_node_t  *rn;

    while (tree->root != tree->sentinel) {

        rn = (ngx_resolver_node_t *) ngx_rbtree_min(tree->root, tree->sentinel);

        ngx_queue_remove(&rn->queue);

        for (ctx = rn->waiting; ctx; ctx = next) {
            next = ctx->next;

            if (ctx->event) {
                ngx_resolver_free(r, ctx->event);
            }

            ngx_resolver_free(r, ctx);
        }

        ngx_rbtree_delete(tree, &rn->node);

        ngx_resolver_free_node(r, rn);
    }
}
示例#11
0
static void
ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
{
    time_t                now;
    ngx_uint_t            i;
    ngx_queue_t          *q;
    ngx_resolver_node_t  *rn;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver expire");

    now = ngx_time();

    for (i = 0; i < 2; i++) {
        if (ngx_queue_empty(queue)) {
            return;
        }

        q = ngx_queue_last(queue);

        rn = ngx_queue_data(q, ngx_resolver_node_t, queue);

        if (now <= rn->expire) {
            return;
        }

        ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
                       "resolver expire \"%*s\"", (size_t) rn->nlen, rn->name);

        ngx_queue_remove(q);

        ngx_rbtree_delete(tree, &rn->node);

        ngx_resolver_free_node(r, rn);
    }
}
static void
ngx_stream_limit_conn_cleanup(void *data)
{
    ngx_stream_limit_conn_cleanup_t  *lccln = data;

    ngx_slab_pool_t               *shpool;
    ngx_rbtree_node_t             *node;
    ngx_stream_limit_conn_ctx_t   *ctx;
    ngx_stream_limit_conn_node_t  *lc;

    ctx = lccln->shm_zone->data;
    shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
    node = lccln->node;
    lc = (ngx_stream_limit_conn_node_t *) &node->color;

    ngx_shmtx_lock(&shpool->mutex);

    ngx_log_debug2(NGX_LOG_DEBUG_STREAM, lccln->shm_zone->shm.log, 0,
                   "limit conn cleanup: %08Xi %d", node->key, lc->conn);

    lc->conn--;

    if (lc->conn == 0) {
        ngx_rbtree_delete(ctx->rbtree, node);
        ngx_slab_free_locked(shpool, node);
    }

    ngx_shmtx_unlock(&shpool->mutex);
}
void
ngx_http_tfs_rc_server_expire(ngx_http_tfs_rc_ctx_t *ctx)
{
    ngx_queue_t             *q, *kp_q;
    ngx_rbtree_node_t       *node;
    ngx_http_tfs_rcs_info_t *rc_info_node;

    if (ngx_queue_empty(&ctx->sh->queue)) {
        return;
    }

    q = ngx_queue_last(&ctx->sh->queue);

    rc_info_node = ngx_queue_data(q, ngx_http_tfs_rcs_info_t, queue);
    kp_q = &rc_info_node->kp_queue;

    ngx_queue_remove(q);
    ngx_queue_remove(kp_q);

    node = (ngx_rbtree_node_t *)
           ((u_char *) rc_info_node - offsetof(ngx_rbtree_node_t, color));

    ngx_rbtree_delete(&ctx->sh->rbtree, node);

    ngx_http_tfs_rc_server_destroy_node(ctx, rc_info_node);
}
示例#14
0
ngx_int_t rbtree_remove_node(rbtree_seed_t *seed, ngx_rbtree_node_t *node) {
  
  ngx_rbtree_delete(&seed->tree, node);
  DBG("Removed node %p", node);
  seed->active_nodes--;
  
#if NCHAN_RBTREE_DBG
  //assert(rbtree_find_node(seed, seed->id(rbtree_data_from_node(node))) == NULL);
  ngx_memset(node, 0x65, sizeof(*node));
  
  
  //super-heavy debugging
  /*
  ngx_int_t    i, max, removed = 0;
  ngx_rbtree_node_t *cur;
  max = sizeof(seed->actives)/sizeof(cur);
  
  assert(seed->active_nodes < max);
  
  for(i=0; i<max; i++){
    if(seed->actives[i] == node) {
      seed->actives[i]=NULL;
      removed = 1;
      break;
    }
  }
  assert(removed);
  
  */
  
#endif
  return NGX_OK;
}
示例#15
0
void
ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf)
{
    ngx_http_file_cache_t       *cache;
    ngx_http_file_cache_node_t  *fcn;

    if (c->updated || c->node == NULL) {
        return;
    }

    cache = c->file_cache;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
                   "http file cache free, fd: %d", c->file.fd);

    ngx_shmtx_lock(&cache->shpool->mutex);

    fcn = c->node;
    fcn->count--;

    if (c->updating) {
        fcn->updating = 0;
    }

    if (c->error) {
        fcn->error = c->error;

        if (c->valid_sec) {
            fcn->valid_sec = c->valid_sec;
            fcn->valid_msec = c->valid_msec;
        }

    } else if (!fcn->exists && fcn->count == 0 && c->min_uses == 1) {
        ngx_queue_remove(&fcn->queue);
        ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
        ngx_slab_free_locked(cache->shpool, fcn);
        c->node = NULL;
    }

    ngx_shmtx_unlock(&cache->shpool->mutex);

    c->updated = 1;
    c->updating = 0;

    if (c->temp_file) {
        if (tf && tf->file.fd != NGX_INVALID_FILE) {
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
                           "http file cache incomplete: \"%s\"",
                           tf->file.name.data);

            if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_CRIT, c->file.log, ngx_errno,
                              ngx_delete_file_n " \"%s\" failed",
                              tf->file.name.data);
            }
        }
    }
}
static void
ngx_http_limit_req2_expire(ngx_http_request_t *r, ngx_http_limit_req2_ctx_t *ctx,
    ngx_uint_t n)
{
    ngx_int_t                   excess;
    ngx_time_t                 *tp;
    ngx_msec_t                  now;
    ngx_queue_t                *q;
    ngx_msec_int_t              ms;
    ngx_rbtree_node_t          *node;
    ngx_http_limit_req2_node_t *lr;

    tp = ngx_timeofday();

    now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);

    /*
     * n == 1 deletes one or two zero rate entries
     * n == 0 deletes oldest entry by force
     *        and one or two zero rate entries
     */

    while (n < 3) {

        if (ngx_queue_empty(&ctx->sh->queue)) {
            return;
        }

        q = ngx_queue_last(&ctx->sh->queue);

        lr = ngx_queue_data(q, ngx_http_limit_req2_node_t, queue);

        if (n++ != 0) {

            ms = (ngx_msec_int_t) (now - lr->last);
            ms = ngx_abs(ms);

            if (ms < 60000) {
                return;
            }

            excess = lr->excess - ctx->rate * ms / 1000;

            if (excess > 0) {
                return;
            }
        }

        ngx_queue_remove(q);

        node = (ngx_rbtree_node_t *)
                   ((u_char *) lr - offsetof(ngx_rbtree_node_t, color));

        ngx_rbtree_delete(&ctx->sh->rbtree, node);

        ngx_slab_free_locked(ctx->shpool, node);
    }
}
示例#17
0
// 遍历定时器红黑树,找出所有过期的事件,调用handler处理超时
void
ngx_event_expire_timers(void)
{
    ngx_event_t        *ev;
    ngx_rbtree_node_t  *node, *root, *sentinel;

    // 红黑树的哨兵
    sentinel = ngx_event_timer_rbtree.sentinel;

    for ( ;; ) {
        // 红黑树的根
        root = ngx_event_timer_rbtree.root;

        // 红黑树已经空
        if (root == sentinel) {
            return;
        }

        // 取红黑树的最小节点
        node = ngx_rbtree_min(root, sentinel);

        /* node->key > ngx_current_time */

        // 与当前时间进行比较,>0即还没有超时

        // 没有了超时事件,循环退出
        if ((ngx_msec_int_t) (node->key - ngx_current_msec) > 0) {
            return;
        }

        // 此事件已经超时
        // 通过offsetof获得事件对象
        ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));

        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                       "event timer del: %d: %M",
                       ngx_event_ident(ev->data), ev->timer.key);

        // 事件从红黑树里移除
        ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);

#if (NGX_DEBUG)
        ev->timer.left = NULL;
        ev->timer.right = NULL;
        ev->timer.parent = NULL;
#endif

        // 定时器标志清零
        ev->timer_set = 0;

        // 设置超时标志
        ev->timedout = 1;

        // 调用事件的handler,里面检查timedout标志处理超时
        ev->handler(ev);
    }
}
static void
ngx_btt_free_torrent(ngx_btt_conf_t *bcf, ngx_btt_ctx_t *ctx,
    ngx_rbtree_t *tree, ngx_btt_torrent_t *t)
{
    ngx_rbtree_delete(tree, &t->node);
    ngx_queue_remove(&t->queue);

    ngx_queue_insert_head(&bcf->btt->free_torrents, &t->queue);
}
static int
ngx_tcp_lua_shdict_expire(ngx_tcp_lua_shdict_ctx_t *ctx, ngx_uint_t n)
{
    ngx_time_t                  *tp;
    uint64_t                     now;
    ngx_queue_t                 *q;
    int64_t                      ms;
    ngx_rbtree_node_t           *node;
    ngx_tcp_lua_shdict_node_t  *sd;
    int                          freed = 0;

    tp = ngx_timeofday();

    now = (uint64_t) tp->sec * 1000 + tp->msec;

    /*
     * n == 1 deletes one or two expired entries
     * n == 0 deletes oldest entry by force
     *        and one or two zero rate entries
     */

    while (n < 3) {

        if (ngx_queue_empty(&ctx->sh->queue)) {
            return freed;
        }

        q = ngx_queue_last(&ctx->sh->queue);

        sd = ngx_queue_data(q, ngx_tcp_lua_shdict_node_t, queue);

        if (n++ != 0) {

            if (sd->expires == 0) {
                return freed;
            }

            ms = sd->expires - now;
            if (ms > 0) {
                return freed;
            }
        }

        ngx_queue_remove(q);

        node = (ngx_rbtree_node_t *)
                   ((u_char *) sd - offsetof(ngx_rbtree_node_t, color));

        ngx_rbtree_delete(&ctx->sh->rbtree, node);

        ngx_slab_free_locked(ctx->shpool, node);

        freed++;
    }

    return freed;
}
示例#20
0
static void
ngx_http_ip_behavior_expire(ngx_http_ip_behavior_ctx_t *ctx, ngx_uint_t force)
{
    ngx_time_t                   *tp;
    ngx_msec_t                    now;
    ngx_msec_int_t                ms;
    ngx_queue_t                  *q;
    ngx_rbtree_node_t            *node;
    ngx_http_ip_behavior_node_t  *ibn;
    ngx_uint_t                    i;
    ngx_uint_t                    n;


    tp = ngx_timeofday();

    now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);

    /* delete at most 2 oldest nodes when a new request comes in
     * or
     * delete 10 oldest nodes ignoring the expires when "force" is set to 1
     */
    if (force) {
        n = 10;
    } else {
        n = 2;
    }

    for (i = 0; i < n; i++) {
        if (ngx_queue_empty(&ctx->sh->queue)) {
            return;
        }

        q = ngx_queue_last(&ctx->sh->queue);

        ibn = ngx_queue_data(q, ngx_http_ip_behavior_node_t, queue);

        if (!force) {
            ms = (ngx_msec_int_t) (now - ibn->last);
            ms = ngx_abs(ms);

            if (ms < ctx->sample_cycle) {
                /* the oldest is not expired, no need to check prev nodes */
                return;
            }
        }

        ngx_queue_remove(q);

        node = (ngx_rbtree_node_t *)
                   ((u_char *) ibn - offsetof(ngx_rbtree_node_t, color));

        ngx_rbtree_delete(&ctx->sh->rbtree, node);

        ngx_slab_free_locked(ctx->shpool, node);
    }
}
static void
ngx_open_file_cache_cleanup(void *data)
{
    ngx_open_file_cache_t  *cache = data;

    ngx_queue_t             *q;
    ngx_cached_open_file_t  *file;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                   "open file cache cleanup");

    for ( ;; ) {

        if (ngx_queue_empty(&cache->expire_queue)) {
            break;
        }

        q = ngx_queue_last(&cache->expire_queue);

        file = ngx_queue_data(q, ngx_cached_open_file_t, queue);

        ngx_queue_remove(q);

        ngx_rbtree_delete(&cache->rbtree, &file->node);

        cache->current--;

        ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                       "delete cached open file: %s", file->name);

        if (!file->err && !file->is_dir) {
            file->close = 1;
            file->count = 0;
            ngx_close_cached_file(cache, file, 0, ngx_cycle->log);

        } else {
            ngx_free(file->name);
            ngx_free(file);
        }
    }

    if (cache->current) {
        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                      "%ui items still leave in open file cache",
                      cache->current);
    }

    if (cache->rbtree.root != cache->rbtree.sentinel) {
        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                      "rbtree still is not empty in open file cache");

    }
}
示例#22
0
/* Note: must be called with the mutex locked */
static ngx_buffer_cache_entry_t*
ngx_buffer_cache_free_oldest_entry(ngx_buffer_cache_sh_t *cache, uint32_t expiration)
{
	ngx_buffer_cache_entry_t* entry;

	// verify we have an entry to free
	if (ngx_queue_empty(&cache->used_queue))
	{
		return NULL;
	}

	// verify the entry is not locked
	entry = container_of(ngx_queue_head(&cache->used_queue), ngx_buffer_cache_entry_t, queue_node);
	if (entry->ref_count > 0 &&
		ngx_time() < entry->access_time + ENTRY_LOCK_EXPIRATION)
	{
		return NULL;
	}

	// make sure the entry is expired, if that is the requirement
	if (expiration && ngx_time() < (time_t)(entry->write_time + expiration))
	{
		return NULL;
	}
	
	// update the state
	entry->state = CES_FREE;

	// remove from rb tree
	ngx_rbtree_delete(&cache->rbtree, &entry->node);

	// move from used_queue to free_queue
	ngx_queue_remove(&entry->queue_node);
	ngx_queue_insert_tail(&cache->free_queue, &entry->queue_node);

	if (ngx_queue_empty(&cache->used_queue))
	{
		// queue is empty reset the read/write pointers
		cache->buffers_read = cache->buffers_end;
		cache->buffers_write = cache->buffers_end;
	}
	else
	{
		// update the read buffer pointer
		cache->buffers_read = entry->start_offset;
	}

	// update stats
	cache->stats.evicted++;
	cache->stats.evicted_bytes += entry->buffer_size;

	return entry;
}
示例#23
0
int ngx_shmap_flush_expired(ngx_shm_zone_t* zone, int attempts)
{
    ngx_queue_t                 *q, *prev;
    ngx_shmap_node_t  *sd;
    ngx_shmap_ctx_t   *ctx;
    ngx_time_t                  *tp;
    int                          freed = 0;
    ngx_rbtree_node_t           *node;
    uint64_t                     now;
	assert(zone != NULL);

    ctx = zone->data;

    ngx_shmtx_lock(&ctx->shpool->mutex);

    if (ngx_queue_empty(&ctx->sh->queue)) {
        return 0;
    }

    tp = ngx_timeofday();

    now = (uint64_t) tp->sec * 1000 + tp->msec;

    q = ngx_queue_last(&ctx->sh->queue);

    while (q != ngx_queue_sentinel(&ctx->sh->queue)) {
        prev = ngx_queue_prev(q);

        sd = ngx_queue_data(q, ngx_shmap_node_t, queue);

        if (sd->expires != 0 && sd->expires <= now) {
            ngx_queue_remove(q);

            node = (ngx_rbtree_node_t *)
                ((u_char *) sd - offsetof(ngx_rbtree_node_t, color));

            ngx_rbtree_delete(&ctx->sh->rbtree, node);
            ngx_slab_free_locked(ctx->shpool, node);
            freed++;

            if (attempts && freed == attempts) {
                break;
            }
        }

        q = prev;
    }

    ngx_shmtx_unlock(&ctx->shpool->mutex);

    return freed;
}
static void
ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n,
    ngx_log_t *log)
{
    time_t                   now;
    ngx_queue_t             *q;
    ngx_cached_open_file_t  *file;

    now = ngx_time();

    /*
     * n == 1 deletes one or two inactive files
     * n == 0 deletes least recently used file by force
     *        and one or two inactive files
     */

    while (n < 3) {
		// 如果队列为空,则直接返回
        if (ngx_queue_empty(&cache->expire_queue)) {
            return;
        }
		// 取出最后一个文件,也就是可能需要被超时的文件
		// (因为尾部是最长时间没有操作的文件)
        q = ngx_queue_last(&cache->expire_queue);

        file = ngx_queue_data(q, ngx_cached_open_file_t, queue);
		// n是控制是强制超时,还是按inactive超时,后一个判断是判断是否超时
        if (n++ != 0 && now - file->accessed <= cache->inactive) {
            return;
        }
		// 如果有超时的,或者需要强制超时,则开始从队列和红黑树中移除
        ngx_queue_remove(q);

        ngx_rbtree_delete(&cache->rbtree, &file->node);

        cache->current--;

        ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
                       "expire cached open file: %s", file->name);

        if (!file->err && !file->is_dir) {
            file->close = 1;
			// 关闭文件
            ngx_close_cached_file(cache, file, 0, log);

        } else {
            ngx_free(file->name);
            ngx_free(file);
        }
    }
}
static void
ngx_btt_expire(ngx_event_t *ev)
{
#if 0
    time_t              now;
    ngx_uint_t          i;
    ngx_queue_t        *q;
#endif
    ngx_btt_conf_t     *bcf;
#if 0
    ngx_btt_torrent_t  *t;
#endif

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "btt expire");

    bcf = ev->data;

#if 0
    if (!ngx_shmtx_trylock(&bcf->pool->mutex)) {
        goto done;
    }

    now = ngx_time();

    for (i = 0; i < 2; i++) {
        if (ngx_queue_empty(&bcf->cache->queue)) {
            break;
        }

        q = ngx_queue_last(&bcf->cache->queue);
        code = ngx_queue_data(q, ngx_btt_torrent_t, queue);

        if (code->expire >= now) {
            break;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
                       "lua cache expire node \"%V\"", &code->path);

        ngx_queue_remove(&code->queue);
        ngx_rbtree_delete(&bcf->cache->rbtree, &code->node);
        ngx_slab_free_locked(bcf->pool, code);
    }

    ngx_shmtx_unlock(&bcf->pool->mutex);

done:
#endif

    ngx_add_timer(&bcf->event, bcf->expire * 1000 / 10);
}
示例#26
0
// 取消定时器,调用handler处理
void
ngx_event_cancel_timers(void)
{
    ngx_event_t        *ev;
    ngx_rbtree_node_t  *node, *root, *sentinel;

    // 红黑树的哨兵
    sentinel = ngx_event_timer_rbtree.sentinel;

    for ( ;; ) {
        // 红黑树的根
        root = ngx_event_timer_rbtree.root;

        // 红黑树已经空
        if (root == sentinel) {
            return;
        }

        // 取红黑树的最小节点
        node = ngx_rbtree_min(root, sentinel);

        // 通过offsetof获得事件对象
        ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));

        // 事件不能被取消
        if (!ev->cancelable) {
            return;
        }

        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                       "event timer cancel: %d: %M",
                       ngx_event_ident(ev->data), ev->timer.key);

        // 事件从红黑树里移除
        ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);

#if (NGX_DEBUG)
        ev->timer.left = NULL;
        ev->timer.right = NULL;
        ev->timer.parent = NULL;
#endif

        // 定时器标志清零
        ev->timer_set = 0;

        // 调用事件的handler
        ev->handler(ev);
    }
}
static void
ngx_http_limit_traffic_rate_filter_cleanup(void *data)
{
    ngx_http_limit_traffic_rate_filter_cleanup_t  *lircln = data;

    ngx_slab_pool_t             *shpool;
    ngx_rbtree_node_t           *node;
    ngx_http_limit_traffic_rate_filter_ctx_t   *ctx;
    ngx_http_limit_traffic_rate_filter_node_t  *lir;

    ctx = lircln->shm_zone->data;
    shpool = (ngx_slab_pool_t *) lircln->shm_zone->shm.addr;
    node = lircln->node;
    lir = (ngx_http_limit_traffic_rate_filter_node_t *) &node->color;

    ngx_shmtx_lock(&shpool->mutex);

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lircln->shm_zone->shm.log, 0,
                   "limit traffic rate cleanup: %08XD %d", node->key, lir->conn);

    lir->conn--;

    if (lir->conn == 0) {        
        ngx_queue_t *p = lir->rq_top.next;
        ngx_queue_t *c;
        ngx_http_limit_traffic_rate_filter_request_queue_t * tr;
        for(; p; ){
            c = p;
            p = ngx_queue_next(p);

            if(ngx_queue_next(c) && ngx_queue_prev(c)){
                ngx_queue_remove(c);
            }
            tr = ngx_queue_data(c, ngx_http_limit_traffic_rate_filter_request_queue_t, rq); 
            if (!tr->r){
                ngx_slab_free_locked(shpool, tr);
            }

            if(ngx_queue_last(&lir->rq_top) == p){
                break;
            }
        }

        ngx_rbtree_delete(ctx->rbtree, node);
        ngx_slab_free_locked(shpool, node);
    }

    ngx_shmtx_unlock(&shpool->mutex);
}
示例#28
0
static void
ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n,
    ngx_log_t *log)
{
    time_t                   now;
    ngx_queue_t             *q;
    ngx_cached_open_file_t  *file;

    now = ngx_time();

    /*
     * n == 1 deletes one or two inactive files
     * n == 0 deletes least recently used file by force
     *        and one or two inactive files
     */

    while (n < 3) {

        if (ngx_queue_empty(&cache->expire_queue)) {
            return;
        }

        q = ngx_queue_last(&cache->expire_queue);

        file = ngx_queue_data(q, ngx_cached_open_file_t, queue);

        if (n++ != 0 && now - file->accessed <= cache->inactive) {
            return;
        }

        ngx_queue_remove(q);

        ngx_rbtree_delete(&cache->rbtree, &file->node);

        cache->current--;

        ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
                       "expire cached open file: %s", file->name);

        if (!file->err && !file->is_dir) {
            file->close = 1;
            ngx_close_cached_file(cache, file, 0, log);

        } else {
            ngx_free(file->name);
            ngx_free(file);
        }
    }
}
static void
ngx_http_session_store_delete(ngx_http_session_store_ctx_t *ctx, 
        ngx_http_session_store_node_t  *ssn)
{
    ngx_rbtree_node_t              *node;

    ngx_queue_remove(&ssn->queue);

    node = (ngx_rbtree_node_t *)
        ((u_char *) ssn - offsetof(ngx_rbtree_node_t, color));

    ngx_rbtree_delete(&ctx->sh->rbtree, node);

    ngx_slab_free_locked(ctx->shpool, node);
}
static void
ngx_btt_free_peer(ngx_btt_conf_t *bcf, ngx_btt_ctx_t *ctx, ngx_rbtree_t *tree,
    ngx_btt_peer_t *p)
{
    if (p->peer_info != NULL) {
        ngx_btt_free_peer_info(bcf, ctx, p->peer_info);

        p->peer_info = NULL;
    }

    ngx_rbtree_delete(tree, &p->node);
    ngx_queue_remove(&p->queue);

    ngx_queue_insert_head(&bcf->btt->free_peers, &p->queue);
}