ngx_queue_t * ngx_queue_middle(ngx_queue_t *queue) { ngx_queue_t *middle, *next; middle = ngx_queue_head(queue); if (middle == ngx_queue_last(queue)) { return middle; } next = ngx_queue_head(queue); for ( ;; ) { middle = ngx_queue_next(middle); next = ngx_queue_next(next); if (next == ngx_queue_last(queue)) { return middle; } next = ngx_queue_next(next); if (next == ngx_queue_last(queue)) { return middle; } } }
// 参考:http://blog.csdn.net/livelylittlefish/article/details/6607324 // 获得队列的中间节点,(除头节点外)若队列有奇数个节点,则返回中间节点; // 若队列有偶数个节点,则返回后半个队列的第一个节点; ngx_queue_t * ngx_queue_middle(ngx_queue_t *queue) { ngx_queue_t *middle, *next; middle = ngx_queue_head(queue); //若只有一个元素 if (middle == ngx_queue_last(queue)) { return middle; } next = ngx_queue_head(queue); // 此循环中,next指针每次移动两个节点,而middle指针每次移动一个节点 for ( ;; ) { middle = ngx_queue_next(middle); next = ngx_queue_next(next); // 偶数个节点,在此返回后半个队列的第一个节点 if (next == ngx_queue_last(queue)) { return middle; } next = ngx_queue_next(next); // 奇数个节点,在此返回中间节点 if (next == ngx_queue_last(queue)) { return middle; } } }
int main() { ngx_pool_t* pool; yahoo_guy_t* guy; ngx_queue_t* q; yahoo_t* yahoo; pool = ngx_create_pool(1024*10, NULL); //初始化内存池 int i; // 构建队列 const ngx_str_t names[] = { ngx_string("rainx"), ngx_string("xiaozhe"), ngx_string("zhoujian") } ; const int ids[] = {4611, 8322, 6111}; yahoo = ngx_palloc(pool, sizeof(yahoo_t)); ngx_queue_init(&yahoo->queue); //初始化queue for(i = 0; i < 3; i++) { guy = (yahoo_guy_t*) ngx_palloc(pool, sizeof(yahoo_guy_t)); guy->id = ids[i]; //guy->name = (char*) ngx_palloc(pool, (size_t) (strlen(names[i]) + 1) ); guy->name = (u_char*) ngx_pstrdup(pool, (ngx_str_t*) &(names[i]) ); ngx_queue_init(&guy->queue); // 从头部进入队列 ngx_queue_insert_head(&yahoo->queue, &guy->queue); } // 从尾部遍历输出 for(q = ngx_queue_last(&yahoo->queue); q != ngx_queue_sentinel(&yahoo->queue); q = ngx_queue_prev(q) ) { guy = ngx_queue_data(q, yahoo_guy_t, queue); printf("No. %d guy in yahoo is %s \n", guy->id, guy->name); } // 排序从头部输出 ngx_queue_sort(&yahoo->queue, yahoo_no_cmp); printf("sorting....\n"); for(q = ngx_queue_prev(&yahoo->queue); q != ngx_queue_sentinel(&yahoo->queue); q = ngx_queue_last(q) ) { guy = ngx_queue_data(q, yahoo_guy_t, queue); printf("No. %d guy in yahoo is %s \n", guy->id, guy->name); } ngx_destroy_pool(pool); return 0; }
// cmp 指向函数的指针 // 队列排序采用的是稳定的简单插入排序方法,即从第一个节点开始遍历,依次将节点(q)插入前面已经排序好的队列(链表)中 // prev 为已经排序好的queue void ngx_queue_sort(ngx_queue_t *queue, ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *)) { ngx_queue_t *q, *prev, *next; q = ngx_queue_head(queue); // 若只有一个元素,则无须排序 if (q == ngx_queue_last(queue)) { return; } for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) { prev = ngx_queue_prev(q); // 也充当了循环条件 next = ngx_queue_next(q); ngx_queue_remove(q); do { // 指针函数调用 if (cmp(prev, q) <= 0) { break; } prev = ngx_queue_prev(prev); } while (prev != ngx_queue_sentinel(queue)); ngx_queue_insert_after(prev, q); } }
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_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream) { ngx_queue_t *q; ngx_http_v2_stream_t *s; if (stream->handled) { return; } stream->handled = 1; for (q = ngx_queue_last(&h2c->waiting); q != ngx_queue_sentinel(&h2c->waiting); q = ngx_queue_prev(q)) { s = ngx_queue_data(q, ngx_http_v2_stream_t, queue); if (s->node->rank < stream->node->rank || (s->node->rank == stream->node->rank && s->node->rel_weight >= stream->node->rel_weight)) { break; } } ngx_queue_insert_after(q, &stream->queue); }
void ngx_queue_sort(ngx_queue_t *queue, intptr_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *)) { ngx_queue_t *q, *prev, *next; q = ngx_queue_head(queue); if (q == ngx_queue_last(queue)) { return; } for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) { prev = ngx_queue_prev(q); next = ngx_queue_next(q); ngx_queue_remove(q); do { if (cmp(prev, q) <= 0) { break; } prev = ngx_queue_prev(prev); } while (prev != ngx_queue_sentinel(queue)); ngx_queue_insert_after(prev, q); } }
// free_connections 中没有可用的连接, 从reusable_connections_queue获取 static void ngx_drain_connections(void) { ngx_int_t i; ngx_queue_t *q; ngx_connection_t *c; // 清理32个keepalive连接,以回收一些连接池供新连接使用 for (i = 0; i < 32; i++) { if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) { break; } // reusable连接队列是从头插入的,意味着越靠近队列尾部的连接,空闲未被 // 使用的时间就越长,这种情况下,优先回收它,类似LRU q = ngx_queue_last(&ngx_cycle->reusable_connections_queue); c = ngx_queue_data(q, ngx_connection_t, queue); ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "reusing connection"); // 这里的handler是ngx_http_keepalive_handler,这函数里,由于close被置1, // 所以会执行ngx_http_close_connection来释放连接,这样也就发生了keepalive // 连接被强制断掉的现象了。 c->close = 1; c->read->handler(c->read); } }
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); } }
void ngx_queue_sort(ngx_queue_t *queue, ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *)) { ngx_queue_t *q, *prev, *next; q = ngx_queue_head(queue); if (q == ngx_queue_last(queue)) { return; } for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) { prev = ngx_queue_prev(q); next = ngx_queue_next(q); ngx_queue_remove(q); do { if (cmp(prev, q) <= 0) {/* 比较 */ break; } prev = ngx_queue_prev(prev); /* prev指针前移 */ } while (prev != ngx_queue_sentinel(queue)); ngx_queue_insert_after(prev, q);/* 将q插入prev节点之后(此处即为简单插入) */ } }
static void ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream) { ngx_queue_t *q; ngx_http_spdy_stream_t *s; if (stream->handled) { return; } stream->handled = 1; for (q = ngx_queue_last(&sc->waiting); q != ngx_queue_sentinel(&sc->waiting); q = ngx_queue_prev(q)) { s = ngx_queue_data(q, ngx_http_spdy_stream_t, queue); /* * NB: higher values represent lower priorities. */ if (stream->priority >= s->priority) { break; } } ngx_queue_insert_after(q, &stream->queue); }
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); }
static ngx_uint_t ngx_http_viewer_cache_node_count(ngx_http_file_cache_t *cache) { ngx_queue_t *q; ngx_uint_t count; ngx_http_file_cache_node_t *fcn; count = 0; ngx_shmtx_lock(&cache->shpool->mutex); for (q = ngx_queue_last(&cache->sh->queue); q != ngx_queue_sentinel(&cache->sh->queue); q = ngx_queue_prev(q)) { fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http viewer file cache: #%d %d %02xd%02xd%02xd%02xd", fcn->count, fcn->exists, fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); count++; } ngx_shmtx_unlock(&cache->shpool->mutex); return count; }
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); } }
/* * [analy] 队列排序采用的是稳定的简单插入排序方法,即从第一个节点开始遍历,依次将当前节点(q)插入前面已经排好序的队列(链表)中 * 由于排序仅简单的修改了指针指向的操作,所以效率较高的。 */ void ngx_queue_sort(ngx_queue_t *queue, ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *)) { ngx_queue_t *q, *prev, *next; q = ngx_queue_head(queue); if (q == ngx_queue_last(queue)) { // 第一个节点和最后一个节点相等,不需要排序(有0或1个节点) return; } for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) { prev = ngx_queue_prev(q); // 取当前节点的前一个节点 next = ngx_queue_next(q); // 取当前节点的后一个节点 ngx_queue_remove(q); // 删除当前节点 do { if (cmp(prev, q) <= 0) { break; } prev = ngx_queue_prev(prev); // 这里取前一个节点的目的是为了检查循环条件是否成立,如果成立说明头节点之后还有节点,需要继续比较 // 不成立,说明头结点之后已经无接点,直接插入到头结点后 } while (prev != ngx_queue_sentinel(queue)); ngx_queue_insert_after(prev, q); } }
//shpool is assumed to be locked. static ngx_http_push_msg_t *ngx_http_push_get_latest_message_locked(ngx_http_push_channel_t * channel) { ngx_queue_t *sentinel = &channel->message_queue->queue; if(ngx_queue_empty(sentinel)) { return NULL; } ngx_queue_t *qmsg = ngx_queue_last(sentinel); return ngx_queue_data(qmsg, ngx_http_push_msg_t, queue); }
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); } }
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_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q) { u_char *name; size_t len; ngx_queue_t *x, tail; ngx_http_location_queue_t *lq, *lx; if (q == ngx_queue_last(locations)) { return; } lq = (ngx_http_location_queue_t *) q; if (lq->inclusive == NULL) { ngx_http_create_locations_list(locations, ngx_queue_next(q)); return; } len = lq->name->len; name = lq->name->data; for (x = ngx_queue_next(q); x != ngx_queue_sentinel(locations); x = ngx_queue_next(x)) { lx = (ngx_http_location_queue_t *) x; if (len > lx->name->len || (ngx_strncmp(name, lx->name->data, len) != 0)) { break; } } q = ngx_queue_next(q); if (q == x) { ngx_http_create_locations_list(locations, x); return; } ngx_queue_split(locations, q, &tail); ngx_queue_add(&lq->list, &tail); if (x == ngx_queue_sentinel(locations)) { ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list)); return; } ngx_queue_split(&lq->list, x, &tail); ngx_queue_add(locations, &tail); ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list)); ngx_http_create_locations_list(locations, x); }
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); } }
void ngx_empty_into(ngx_queue_t *from,ngx_queue_t *to,int limit) { ngx_queue_t *q; while (!ngx_queue_empty(from) && limit-- != 0) { q = ngx_queue_last(from); ngx_queue_remove(q); ngx_queue_insert_head(to,q); } }
static max_connections_peer_data_t * queue_oldest (max_connections_srv_conf_t *maxconn_cf) { if(ngx_queue_empty(&maxconn_cf->waiting_requests)) return NULL; ngx_queue_t *last = ngx_queue_last(&maxconn_cf->waiting_requests); max_connections_peer_data_t *peer_data = ngx_queue_data(last, max_connections_peer_data_t, queue); return peer_data; }
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"); } }
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; }
void dump_queue_from_tail(ngx_queue_t *que) { ngx_queue_t *q = ngx_queue_last(que); printf("(0x%x: (0x%x, 0x%x)) <==> \n", que, que->prev, que->next); for (; q != ngx_queue_sentinel(que); q = ngx_queue_prev(q)) { my_point_queue_t *point = ngx_queue_data(q, my_point_queue_t, queue); printf("(0x%x: (%-2d, %-2d), 0x%x: (0x%x, 0x%x)) <==> \n", point, point->point.x, point->point.y, &point->queue, point->queue.prev, point->queue.next); } }
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); }
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 time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue) { time_t now; ngx_queue_t *q; ngx_resolver_node_t *rn; now = ngx_time(); for ( ;; ) { if (ngx_queue_empty(queue)) { return 0; } q = ngx_queue_last(queue); rn = ngx_queue_data(q, ngx_resolver_node_t, queue); if (now < rn->expire) { return rn->expire - now; } ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver resend \"%*s\" %p", (size_t) rn->nlen, rn->name, rn->waiting); ngx_queue_remove(q); if (rn->waiting) { if (ngx_resolver_send_query(r, rn) == NGX_OK) { rn->expire = now + r->resend_timeout; ngx_queue_insert_head(queue, &rn->queue); } continue; } ngx_rbtree_delete(tree, &rn->node); ngx_resolver_free_node(r, rn); } }