static void uv__write_callbacks(uv_tcp_t* tcp) { int callbacks_made = 0; ngx_queue_t* q; uv_write_t* req; while (!ngx_queue_empty(&tcp->write_completed_queue)) { /* Pop a req off write_completed_queue. */ q = ngx_queue_head(&tcp->write_completed_queue); assert(q); req = ngx_queue_data(q, struct uv_write_s, queue); ngx_queue_remove(q); /* NOTE: call callback AFTER freeing the request data. */ if (req->cb) { req->cb(req, 0); } callbacks_made++; } assert(ngx_queue_empty(&tcp->write_completed_queue)); /* Write queue drained. */ if (!uv_write_queue_head(tcp)) { uv__drain(tcp); } }
static void uv__cf_loop_cb(void* arg) { uv_loop_t* loop; ngx_queue_t* item; ngx_queue_t split_head; uv__cf_loop_signal_t* s; loop = arg; uv_mutex_lock(&loop->cf_mutex); ngx_queue_init(&split_head); if (!ngx_queue_empty(&loop->cf_signals)) { ngx_queue_t* split_pos = ngx_queue_next(&loop->cf_signals); ngx_queue_split(&loop->cf_signals, split_pos, &split_head); } uv_mutex_unlock(&loop->cf_mutex); while (!ngx_queue_empty(&split_head)) { item = ngx_queue_head(&split_head); s = ngx_queue_data(item, uv__cf_loop_signal_t, member); /* This was a termination signal */ if (s->cb == NULL) CFRunLoopStop(loop->cf_loop); else s->cb(s->arg); ngx_queue_remove(item); free(s); } }
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); assert(0 != events); assert(w->fd >= 0); assert(w->fd < INT_MAX); w->pevents |= events; maybe_resize(loop, w->fd + 1); #if !defined(__sun) /* The event ports backend needs to rearm all file descriptors on each and * every tick of the event loop but the other backends allow us to * short-circuit here if the event mask is unchanged. */ if (w->events == w->pevents) { if (w->events == 0 && !ngx_queue_empty(&w->watcher_queue)) { ngx_queue_remove(&w->watcher_queue); ngx_queue_init(&w->watcher_queue); } return; } #endif if (ngx_queue_empty(&w->watcher_queue)) ngx_queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); if (loop->watchers[w->fd] == NULL) { loop->watchers[w->fd] = w; loop->nfds++; } }
void uv__stream_destroy(uv_stream_t* stream) { uv_write_t* req; ngx_queue_t* q; assert(stream->flags & UV_CLOSED); while (!ngx_queue_empty(&stream->write_queue)) { q = ngx_queue_head(&stream->write_queue); ngx_queue_remove(q); req = ngx_queue_data(q, uv_write_t, queue); if (req->bufs != req->bufsml) free(req->bufs); if (req->cb) { uv__set_artificial_error(req->handle->loop, UV_EINTR); req->cb(req, -1); } } while (!ngx_queue_empty(&stream->write_completed_queue)) { q = ngx_queue_head(&stream->write_completed_queue); ngx_queue_remove(q); req = ngx_queue_data(q, uv_write_t, queue); if (req->cb) { uv__set_sys_error(stream->loop, req->error); req->cb(req, req->error ? -1 : 0); } } }
static void uv__write_callbacks(uv_stream_t* stream) { int callbacks_made = 0; ngx_queue_t* q; uv_write_t* req; while (!ngx_queue_empty(&stream->write_completed_queue)) { /* Pop a req off write_completed_queue. */ q = ngx_queue_head(&stream->write_completed_queue); assert(q); req = ngx_queue_data(q, struct uv_write_s, queue); ngx_queue_remove(q); /* NOTE: call callback AFTER freeing the request data. */ if (req->cb) { uv__set_artificial_error(stream->loop, req->error); req->cb(req, req->error ? -1 : 0); } callbacks_made++; } assert(ngx_queue_empty(&stream->write_completed_queue)); /* Write queue drained. */ if (!uv_write_queue_head(stream)) { uv__drain(stream); } }
void uv__cf_loop_cb(void* arg) { uv_loop_t* loop; ngx_queue_t* item; ngx_queue_t split_head; uv__cf_loop_signal_t* s; loop = arg; uv_mutex_lock(&loop->cf_mutex); ngx_queue_init(&split_head); if (!ngx_queue_empty(&loop->cf_signals)) { ngx_queue_t* split_pos = ngx_queue_next(&loop->cf_signals); ngx_queue_split(&loop->cf_signals, split_pos, &split_head); } uv_mutex_unlock(&loop->cf_mutex); while (!ngx_queue_empty(&split_head)) { item = ngx_queue_head(&split_head); s = ngx_queue_data(item, uv__cf_loop_signal_t, member); s->cb(s->arg); ngx_queue_remove(item); free(s); } }
void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream, uv_handle_type type) { uv__handle_init(loop, (uv_handle_t*)stream, type); loop->counters.stream_init++; stream->alloc_cb = NULL; stream->close_cb = NULL; stream->connection_cb = NULL; stream->connect_req = NULL; stream->accepted_fd = -1; stream->fd = -1; stream->delayed_error = 0; stream->blocking = 0; ngx_queue_init(&stream->write_queue); ngx_queue_init(&stream->write_completed_queue); stream->write_queue_size = 0; ev_init(&stream->read_watcher, uv__stream_io); stream->read_watcher.data = stream; ev_init(&stream->write_watcher, uv__stream_io); stream->write_watcher.data = stream; assert(ngx_queue_empty(&stream->write_queue)); assert(ngx_queue_empty(&stream->write_completed_queue)); assert(stream->write_queue_size == 0); }
static void uv__udp_sendmsg(EV_P_ ev_io* w, int revents) { uv_udp_t* handle; handle = container_of(w, uv_udp_t, write_watcher); assert(handle->type == UV_UDP); assert(revents & EV_WRITE); assert(!ngx_queue_empty(&handle->write_queue) || !ngx_queue_empty(&handle->write_completed_queue)); /* Write out pending data first. */ uv__udp_run_pending(handle); /* Drain 'request completed' queue. */ uv__udp_run_completed(handle); if (!ngx_queue_empty(&handle->write_completed_queue)) { /* Schedule completion callbacks. */ ev_feed_event(handle->loop->ev, &handle->write_watcher, EV_WRITE); } else if (ngx_queue_empty(&handle->write_queue)) { /* Pending queue and completion queue empty, stop watcher. */ uv__udp_stop_write_watcher(handle); } }
static void uv__udp_sendmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents) { uv_udp_t* handle; handle = container_of(w, uv_udp_t, io_watcher); assert(handle->type == UV_UDP); assert(revents & UV__POLLOUT); assert(!ngx_queue_empty(&handle->write_queue) || !ngx_queue_empty(&handle->write_completed_queue)); /* Write out pending data first. */ uv__udp_run_pending(handle); /* Drain 'request completed' queue. */ uv__udp_run_completed(handle); if (!ngx_queue_empty(&handle->write_completed_queue)) { /* Schedule completion callbacks. */ uv__io_feed(handle->loop, &handle->io_watcher); } else if (ngx_queue_empty(&handle->write_queue)) { /* Pending queue and completion queue empty, stop watcher. */ uv__io_stop(loop, &handle->io_watcher, UV__POLLOUT); if (!uv__io_active(&handle->io_watcher, UV__POLLIN)) uv__handle_stop(handle); } }
static void uv__write_callbacks(uv_stream_t* stream) { uv_write_t* req; ngx_queue_t* q; while (!ngx_queue_empty(&stream->write_completed_queue)) { /* Pop a req off write_completed_queue. */ q = ngx_queue_head(&stream->write_completed_queue); req = ngx_queue_data(q, uv_write_t, queue); ngx_queue_remove(q); uv__req_unregister(stream->loop, req); /* NOTE: call callback AFTER freeing the request data. */ if (req->cb) { uv__set_sys_error(stream->loop, req->error); req->cb(req, req->error ? -1 : 0); } } assert(ngx_queue_empty(&stream->write_completed_queue)); /* Write queue drained. */ if (!uv_write_queue_head(stream)) { uv__drain(stream); } }
int uv_tcp_init(uv_tcp_t* tcp) { uv__handle_init((uv_handle_t*)tcp, UV_TCP); uv_counters()->tcp_init++; tcp->alloc_cb = NULL; tcp->connect_req = NULL; tcp->accepted_fd = -1; tcp->fd = -1; tcp->delayed_error = 0; ngx_queue_init(&tcp->write_queue); ngx_queue_init(&tcp->write_completed_queue); tcp->write_queue_size = 0; ev_init(&tcp->read_watcher, uv__tcp_io); tcp->read_watcher.data = tcp; ev_init(&tcp->write_watcher, uv__tcp_io); tcp->write_watcher.data = tcp; assert(ngx_queue_empty(&tcp->write_queue)); assert(ngx_queue_empty(&tcp->write_completed_queue)); assert(tcp->write_queue_size == 0); return 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; }
void uv__stream_destroy(uv_stream_t* stream) { uv_write_t* req; ngx_queue_t* q; assert(!uv__io_active(&stream->io_watcher, UV__POLLIN | UV__POLLOUT)); assert(stream->flags & UV_CLOSED); if (stream->connect_req) { uv__req_unregister(stream->loop, stream->connect_req); uv__set_artificial_error(stream->loop, UV_ECANCELED); stream->connect_req->cb(stream->connect_req, -1); stream->connect_req = NULL; } while (!ngx_queue_empty(&stream->write_queue)) { q = ngx_queue_head(&stream->write_queue); ngx_queue_remove(q); req = ngx_queue_data(q, uv_write_t, queue); uv__req_unregister(stream->loop, req); if (req->bufs != req->bufsml) free(req->bufs); if (req->cb) { uv__set_artificial_error(req->handle->loop, UV_ECANCELED); req->cb(req, -1); } } while (!ngx_queue_empty(&stream->write_completed_queue)) { q = ngx_queue_head(&stream->write_completed_queue); ngx_queue_remove(q); req = ngx_queue_data(q, uv_write_t, queue); uv__req_unregister(stream->loop, req); if (req->cb) { uv__set_sys_error(stream->loop, req->error); req->cb(req, req->error ? -1 : 0); } } if (stream->shutdown_req) { uv__req_unregister(stream->loop, stream->shutdown_req); uv__set_artificial_error(stream->loop, UV_ECANCELED); stream->shutdown_req->cb(stream->shutdown_req, -1); stream->shutdown_req = NULL; } }
void ngx_postgres_keepalive_cleanup(void *data) { ngx_postgres_upstream_srv_conf_t *pgscf = data; ngx_postgres_keepalive_cache_t *item; ngx_queue_t *q; dd("entering"); /* ngx_queue_empty is broken when used on unitialized queue */ if (pgscf->cache.prev == NULL) { dd("returning"); return; } /* just to be on the safe-side */ pgscf->max_cached = 0; while (!ngx_queue_empty(&pgscf->cache)) { q = ngx_queue_head(&pgscf->cache); ngx_queue_remove(q); item = ngx_queue_data(q, ngx_postgres_keepalive_cache_t, queue); dd("postgres: disconnecting %p", item->connection); ngx_postgres_upstream_free_connection(item->connection->log, item->connection, item->pgconn, pgscf); } dd("returning"); }
void uv__udp_finish_close(uv_udp_t* handle) { uv_udp_send_t* req; ngx_queue_t* q; assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); assert(handle->io_watcher.fd == -1); uv__udp_run_completed(handle); while (!ngx_queue_empty(&handle->write_queue)) { q = ngx_queue_head(&handle->write_queue); ngx_queue_remove(q); req = ngx_queue_data(q, uv_udp_send_t, queue); uv__req_unregister(handle->loop, req); if (req->bufs != req->bufsml) free(req->bufs); req->bufs = NULL; if (req->send_cb) { uv__set_artificial_error(handle->loop, UV_ECANCELED); req->send_cb(req, -1); } } /* Now tear down the handle. */ handle->flags = 0; handle->recv_cb = NULL; handle->alloc_cb = NULL; /* but _do not_ touch close_cb */ }
void uv__loop_delete(uv_loop_t* loop) { uv__signal_loop_cleanup(loop); uv__platform_loop_delete(loop); ev_loop_destroy(loop->ev); if (loop->async_pipefd[0] != -1) { close(loop->async_pipefd[0]); loop->async_pipefd[0] = -1; } if (loop->async_pipefd[1] != -1) { close(loop->async_pipefd[1]); loop->async_pipefd[1] = -1; } if (loop->emfile_fd != -1) { close(loop->emfile_fd); loop->emfile_fd = -1; } uv_mutex_lock(&loop->wq_mutex); assert(ngx_queue_empty(&loop->wq) && "thread pool work queue not empty!"); uv_mutex_unlock(&loop->wq_mutex); uv_mutex_destroy(&loop->wq_mutex); }
static void uv__udp_run_completed(uv_udp_t* handle) { uv_udp_send_t* req; ngx_queue_t* q; while (!ngx_queue_empty(&handle->write_completed_queue)) { q = ngx_queue_head(&handle->write_completed_queue); ngx_queue_remove(q); req = ngx_queue_data(q, uv_udp_send_t, queue); uv__req_unregister(handle->loop, req); if (req->bufs != req->bufsml) free(req->bufs); req->bufs = NULL; if (req->send_cb == NULL) continue; /* req->status >= 0 == bytes written * req->status < 0 == errno */ if (req->status >= 0) { req->send_cb(req, 0); } else { uv__set_sys_error(handle->loop, -req->status); req->send_cb(req, -1); } } }
static ngx_btt_peer_t * ngx_btt_get_peer(ngx_btt_conf_t *bcf, ngx_btt_ctx_t *ctx, ngx_rbtree_t *tree, ngx_queue_t *queue) { ngx_queue_t *q; ngx_btt_peer_t *p; p = NULL; if (!ngx_queue_empty(&bcf->btt->free_peers)) { q = ngx_queue_head(&bcf->btt->free_peers); ngx_queue_remove(q); p = ngx_queue_data(q, ngx_btt_peer_t, queue); } if (p == NULL) { p = ngx_slab_alloc_locked(bcf->pool, sizeof(ngx_btt_peer_t)); if (p == NULL) { return NULL; } } /* TODO */ ngx_memcpy(&p->connection_id, &ctx->connection_id, sizeof(ctx->connection_id)); p->node.key = ngx_crc32_short((u_char *) &ctx->connection_id, sizeof(ctx->connection_id)); ngx_rbtree_insert(tree, &p->node); ngx_queue_insert_head(queue, &p->queue); return p; }
void uv__udp_finish_close(uv_udp_t* handle) { uv_udp_send_t* req; ngx_queue_t* q; assert(!ev_is_active(&handle->write_watcher)); assert(!ev_is_active(&handle->read_watcher)); assert(handle->fd == -1); uv__udp_run_completed(handle); while (!ngx_queue_empty(&handle->write_queue)) { q = ngx_queue_head(&handle->write_queue); ngx_queue_remove(q); req = ngx_queue_data(q, uv_udp_send_t, queue); if (req->send_cb) { /* FIXME proper error code like UV_EABORTED */ uv__set_artificial_error(handle->loop, UV_EINTR); req->send_cb(req, -1); } } /* Now tear down the handle. */ handle->flags = 0; handle->recv_cb = NULL; handle->alloc_cb = NULL; /* but _do not_ touch close_cb */ }
ngx_int_t ngx_http_drizzle_keepalive_get_peer_single(ngx_peer_connection_t *pc, ngx_http_upstream_drizzle_peer_data_t *dp, ngx_http_upstream_drizzle_srv_conf_t *dscf) { ngx_http_drizzle_keepalive_cache_t *item; ngx_queue_t *q; ngx_connection_t *c; if (! ngx_queue_empty(&dscf->cache)) { q = ngx_queue_head(&dscf->cache); ngx_queue_remove(q); item = ngx_queue_data(q, ngx_http_drizzle_keepalive_cache_t, queue); c = item->connection; ngx_queue_insert_head(&dscf->free, q); c->idle = 0; c->log = pc->log; c->read->log = pc->log; c->write->log = pc->log; pc->connection = c; pc->cached = 1; dp->name = &item->name; dp->drizzle_con = item->drizzle_con; return NGX_DONE; } return NGX_DECLINED; }
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); } }
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); }
void EIO_AfterWrite(uv_work_t* req) { QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data); WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton); v8::Handle<v8::Value> argv[2]; if(data->errorString[0]) { argv[0] = v8::Exception::Error(v8::String::New(data->errorString)); argv[1] = v8::Undefined(); } else { argv[0] = v8::Undefined(); argv[1] = v8::Int32::New(data->result); } v8::Function::Cast(*data->callback)->Call(v8::Context::GetCurrent()->Global(), 2, argv); uv_mutex_lock(&write_queue_mutex); ngx_queue_remove(&queuedWrite->queue); if (!ngx_queue_empty(&write_queue)) { // Always pull the next work item from the head of the queue ngx_queue_t* head = ngx_queue_head(&write_queue); QueuedWrite* nextQueuedWrite = ngx_queue_data(head, QueuedWrite, queue); uv_queue_work(uv_default_loop(), &nextQueuedWrite->req, EIO_Write, EIO_AfterWrite); } uv_mutex_unlock(&write_queue_mutex); data->buffer.Dispose(); data->callback.Dispose(); delete data; delete queuedWrite; }
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); assert(0 != events); if (w->fd == -1) return; assert(w->fd >= 0); /* Happens when uv__io_stop() is called on a handle that was never started. */ if ((unsigned) w->fd >= loop->nwatchers) return; w->pevents &= ~events; if (w->pevents == 0) { ngx_queue_remove(&w->watcher_queue); ngx_queue_init(&w->watcher_queue); if (loop->watchers[w->fd] != NULL) { assert(loop->watchers[w->fd] == w); assert(loop->nfds > 0); loop->watchers[w->fd] = NULL; loop->nfds--; w->events = 0; } } else if (ngx_queue_empty(&w->watcher_queue)) ngx_queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); }
/* The buffers to be written must remain valid until the callback is called. * This is not required for the uv_buf_t array. */ int uv_write(uv_req_t* req, uv_buf_t bufs[], int bufcnt) { uv_handle_t* handle = req->handle; assert(handle->fd >= 0); ngx_queue_init(&req->queue); req->type = UV_WRITE; /* TODO: Don't malloc for each write... */ req->bufs = malloc(sizeof(uv_buf_t) * bufcnt); memcpy(req->bufs, bufs, bufcnt * sizeof(uv_buf_t)); req->bufcnt = bufcnt; req->write_index = 0; handle->write_queue_size += uv__buf_count(bufs, bufcnt); /* Append the request to write_queue. */ ngx_queue_insert_tail(&handle->write_queue, &req->queue); assert(!ngx_queue_empty(&handle->write_queue)); assert(handle->write_watcher.cb == uv__tcp_io); assert(handle->write_watcher.data == handle); assert(handle->write_watcher.fd == handle->fd); ev_io_start(EV_DEFAULT_ &handle->write_watcher); return 0; }
/* Note: must be called with the mutex locked */ static ngx_buffer_cache_entry_t* ngx_buffer_cache_get_free_entry(ngx_buffer_cache_sh_t *cache) { ngx_buffer_cache_entry_t* entry; if (!ngx_queue_empty(&cache->free_queue)) { // return the free queue head return container_of(ngx_queue_head(&cache->free_queue), ngx_buffer_cache_entry_t, queue_node); } if ((u_char*)(cache->entries_end + 1) < cache->buffers_start) { // enlarge the entries buffer entry = cache->entries_end; cache->entries_end++; // initialize the state and add to free queue entry->state = CES_FREE; ngx_queue_insert_tail(&cache->free_queue, &entry->queue_node); return entry; } return ngx_buffer_cache_free_oldest_entry(cache, 0); }
static void uv__drain(uv_stream_t* stream) { uv_shutdown_t* req; assert(ngx_queue_empty(&stream->write_queue)); assert(stream->write_queue_size == 0); uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); /* Shutdown? */ if ((stream->flags & UV_STREAM_SHUTTING) && !(stream->flags & UV_CLOSING) && !(stream->flags & UV_STREAM_SHUT)) { assert(stream->shutdown_req); req = stream->shutdown_req; stream->shutdown_req = NULL; uv__req_unregister(stream->loop, req); if (shutdown(uv__stream_fd(stream), SHUT_WR)) { /* Error. Report it. User should call uv_close(). */ uv__set_sys_error(stream->loop, errno); if (req->cb) { req->cb(req, -1); } } else { uv__set_sys_error(stream->loop, 0); ((uv_handle_t*) stream)->flags |= UV_STREAM_SHUT; if (req->cb) { req->cb(req, 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); } }
// 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); } }