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; }
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; } }
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); } }
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); }
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); } }
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); }
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; }
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); } }
// 遍历定时器红黑树,找出所有过期的事件,调用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; }
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"); } }
/* 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; }
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); }
// 取消定时器,调用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); }
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); }