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 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; }
//free memory for a message. static ngx_inline void ngx_http_push_free_message_locked(ngx_http_push_msg_t *msg, ngx_slab_pool_t *shpool) { if(msg->buf->file!=NULL) { ngx_shmtx_unlock(&shpool->mutex); ngx_close_file(msg->buf->file->fd); //again, carest thou aboutst thine errorests? ngx_delete_file(msg->buf->file->name.data); //should I care about deletion errors? ngx_shmtx_lock(&shpool->mutex); } ngx_slab_free_locked(shpool, msg->buf); //separate block, remember? ngx_slab_free_locked(shpool, msg); }
//free memory for a message. static ngx_inline void ngx_http_push_free_message_locked(ngx_http_push_msg_t *msg, ngx_slab_pool_t *shpool) { if(msg->buf->file!=NULL) { // i'd like to release the shpool lock here while i do stuff to this file, but that // might unlock during channel rbtree traversal, which is Bad News. if(msg->buf->file->fd!=NGX_INVALID_FILE) { ngx_close_file(msg->buf->file->fd); } ngx_delete_file(msg->buf->file->name.data); //should I care about deletion errors? doubt it. } ngx_slab_free_locked(shpool, msg->buf); //separate block, remember? ngx_slab_free_locked(shpool, msg); }
//free memory for a message. static ngx_inline void ngx_http_push_free_message_locked(ngx_http_push_msg_t *msg, ngx_slab_pool_t *shpool) { if(msg->buf->file!=NULL) { ngx_shmtx_unlock(&shpool->mutex); if(msg->buf->file->fd!=NGX_INVALID_FILE) { ngx_close_file(msg->buf->file->fd); } ngx_delete_file(msg->buf->file->name.data); //should I care about deletion errors? doubt it. ngx_shmtx_lock(&shpool->mutex); } ngx_slab_free_locked(shpool, msg->buf); //separate block, remember? ngx_slab_free_locked(shpool, msg); }
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_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_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_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_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); }
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_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_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); } }
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); } } } }
// find a channel by id. if channel not found, make one, insert it, and return that. static ngx_http_push_stream_channel_t * ngx_http_push_stream_get_channel(ngx_str_t *id, ngx_log_t *log, ngx_http_push_stream_loc_conf_t *cf) { ngx_http_push_stream_main_conf_t *mcf = ngx_http_push_stream_module_main_conf; ngx_http_push_stream_shm_data_t *data = (ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data; ngx_http_push_stream_channel_t *channel; ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr; ngx_flag_t is_broadcast_channel = 0; channel = ngx_http_push_stream_find_channel(id, log); if (channel != NULL) { // we found our channel return channel; } ngx_shmtx_lock(&shpool->mutex); // check again to see if any other worker didn't create the channel channel = ngx_http_push_stream_find_channel(id, log); if (channel != NULL) { // we found our channel ngx_shmtx_unlock(&shpool->mutex); return channel; } if ((mcf->broadcast_channel_prefix.len > 0) && (ngx_strncmp(id->data, mcf->broadcast_channel_prefix.data, mcf->broadcast_channel_prefix.len) == 0)) { is_broadcast_channel = 1; } if (((!is_broadcast_channel) && (mcf->max_number_of_channels != NGX_CONF_UNSET_UINT) && (mcf->max_number_of_channels == data->channels)) || ((is_broadcast_channel) && (mcf->max_number_of_broadcast_channels != NGX_CONF_UNSET_UINT) && (mcf->max_number_of_broadcast_channels == data->broadcast_channels))) { ngx_shmtx_unlock(&shpool->mutex); return NGX_HTTP_PUSH_STREAM_NUMBER_OF_CHANNELS_EXCEEDED; } if ((channel = ngx_slab_alloc_locked(shpool, sizeof(ngx_http_push_stream_channel_t))) == NULL) { ngx_shmtx_unlock(&shpool->mutex); return NULL; } if ((channel->id.data = ngx_slab_alloc_locked(shpool, id->len + 1)) == NULL) { ngx_slab_free_locked(shpool, channel); ngx_shmtx_unlock(&shpool->mutex); return NULL; } channel->id.len = id->len; ngx_memcpy(channel->id.data, id->data, channel->id.len); channel->id.data[channel->id.len] = '\0'; channel->broadcast = is_broadcast_channel; ngx_http_push_stream_initialize_channel(channel); // initialize workers_with_subscribers queues only when a channel is created ngx_queue_init(&channel->workers_with_subscribers); ngx_shmtx_unlock(&shpool->mutex); return channel; }
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); } }
void ngx_http_session_shm_free_nolock(void *p) { ngx_http_session_list_t *session_list; session_list = ngx_http_session_shm_zone->data; ngx_slab_free_locked(session_list->shpool, p); return; }
/* nginx-style, _locked assumes you have the lock */ static void ngx_http_cloudrouter_clear_remotes_locked(ngx_http_cloudrouter_node_t* e, ngx_log_t *log) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "CloudRouter: clear_remotes"); while (e->remote != NULL) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "CloudRouter: clear_remotes: e->remote: %p", e->remote); ngx_http_cloudrouter_remote_t *remote = e->remote; e->remote = e->remote->next; ngx_slab_free_locked(ngx_http_cloudrouter_shpool, remote); } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "CloudRouter: clear_remotes done"); }
void ngx_http_statistics_server_del(ngx_cycle_t *cycle, ngx_str_t *name) { ngx_http_statistics_ctx_t *ctx; ngx_http_statistics_conf_t *smcf; ngx_http_statistics_server_t *server; uint32_t hash; smcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_statistics_module); if (smcf->enabled == 0) { return; } ctx = statistics_shm_zone->data; ngx_shmtx_lock(&ctx->shpool->mutex); hash = ngx_crc32_short(name->data, name->len); server = (ngx_http_statistics_server_t *) ngx_http_statistics_lookup( &ctx->sh->server_tree, name, hash); if (server != NULL) { /* found a server node */ ngx_log_error(NGX_LOG_DEBUG, cycle->log, 0, "server->ref: %i", server->ref); server->ref--; if (server->ref == 0) { ngx_rbtree_delete(&ctx->sh->server_tree, &server->node); ngx_queue_remove(&server->queue); ngx_slab_free_locked(ctx->shpool, server->name.data); ngx_slab_free_locked(ctx->shpool, server); } } ngx_shmtx_unlock(&ctx->shpool->mutex); }
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_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); }
void ngx_http_session_shm_free(void *p) { ngx_http_session_list_t *session_list; session_list = ngx_http_session_shm_zone->data; ngx_shmtx_lock(&session_list->shpool->mutex); ngx_slab_free_locked(session_list->shpool, p); ngx_shmtx_unlock(&session_list->shpool->mutex); return; }
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_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q, u_char *name) { u_char *p; size_t len; ngx_path_t *path; ngx_http_file_cache_node_t *fcn; fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); if (fcn->exists) { cache->sh->size -= fcn->fs_size; path = cache->path; p = name + path->name.len + 1 + path->len; p = ngx_hex_dump(p, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t)); len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); p = ngx_hex_dump(p, fcn->key, len); *p = '\0'; fcn->count++; fcn->deleting = 1; ngx_shmtx_unlock(&cache->shpool->mutex); len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; ngx_create_hashed_filename(path, name, len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache expire: \"%s\"", name); if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", name); } ngx_shmtx_lock(&cache->shpool->mutex); fcn->count--; fcn->deleting = 0; } if (fcn->count == 0) { ngx_queue_remove(q); ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); ngx_slab_free_locked(cache->shpool, fcn); } }
static ngx_int_t __ngx_http_session_delete(ngx_http_session_t *session) { ngx_int_t ret; ngx_http_session_list_t *session_list; session_list = ngx_http_session_shm_zone->data; if (!session->ref) { if (!session->next && !session->prev) { /* the only node in the chain */ *(session->slot) = NULL; } else if (!session->prev && session->next) { /* first node in the chain */ *(session->slot) = session->next; ((ngx_http_session_t *)(session->next))->prev = NULL; ((ngx_http_session_t *)(session->next))->slot = session->slot; } else if (session->next && session->prev) { /* node in the middle */ ((ngx_http_session_t *)(session->prev))->next = session->next; ((ngx_http_session_t *)(session->next))->prev = session->prev; } else if (session->prev && !session->next) { /* last node in the chain */ ((ngx_http_session_t *)(session->prev))->next = NULL; } session->next = session->prev = NULL; if (session->ev.timer_set) { ngx_del_timer(&session->ev); } if (!ngx_queue_empty(&session->redirect_queue_node)) { ngx_queue_remove(&session->redirect_queue_node); session_list->redirect_num--; } __ngx_http_session_ctx_delete(session); ngx_shmtx_destroy(&session->mutex); ngx_slab_free_locked(session_list->shpool, session); ret = NGX_OK; } else { ret = NGX_ERROR; } return ret; }
static ngx_int_t ngx_http_ip_blacklist_flush_handler(ngx_http_request_t *r) { ngx_http_ip_blacklist_main_conf_t *imcf; ngx_http_ip_blacklist_tree_t *blacklist; ngx_http_ip_blacklist_t *bn; ngx_queue_t *node; ngx_queue_t *tmp; imcf = ngx_http_get_module_main_conf(r, ngx_http_ip_blacklist_module); if (!imcf->enabled) { return NGX_HTTP_CLOSE; } blacklist = ngx_http_ip_blacklist_shm_zone->data; ngx_shmtx_lock(&blacklist->shpool->mutex); if (ngx_queue_empty(&blacklist->garbage)) { ngx_shmtx_unlock(&blacklist->shpool->mutex); return NGX_HTTP_CLOSE; } 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->ref != 0) { /* force node to time out */ bn->timed = 1; continue; } 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); } ngx_shmtx_unlock(&blacklist->shpool->mutex); return NGX_HTTP_CLOSE; }
static ngx_inline void ngx_http_push_stream_process_worker_message(void) { ngx_http_push_stream_worker_msg_t *worker_msg, *sentinel; ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr; ngx_http_push_stream_worker_data_t *workers_data = ((ngx_http_push_stream_shm_data_t *) ngx_http_push_stream_shm_zone->data)->ipc; ngx_http_push_stream_worker_data_t *thisworker_data = workers_data + ngx_process_slot; sentinel = thisworker_data->messages_queue; while ((worker_msg = (ngx_http_push_stream_worker_msg_t *) ngx_queue_next(&sentinel->queue)) != sentinel) { if (worker_msg->pid == ngx_pid) { // everything is okay ngx_http_push_stream_respond_to_subscribers(worker_msg->channel, worker_msg->subscribers_sentinel, worker_msg->msg); } else { // that's quite bad you see. a previous worker died with an undelivered message. // but all its subscribers' connections presumably got canned, too. so it's not so bad after all. ngx_http_push_stream_pid_queue_t *channel_worker_sentinel = &worker_msg->channel->workers_with_subscribers; ngx_http_push_stream_pid_queue_t *channel_worker_cur = channel_worker_sentinel; ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push stream module: worker %i intercepted a message intended for another worker process (%i) that probably died", ngx_pid, worker_msg->pid); // delete that invalid sucker while ((channel_worker_cur != NULL) && (channel_worker_cur = (ngx_http_push_stream_pid_queue_t *) ngx_queue_next(&channel_worker_cur->queue)) != channel_worker_sentinel) { if (channel_worker_cur->pid == worker_msg->pid) { ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "push stream module: reference to worker %i will be removed", worker_msg->pid); ngx_shmtx_lock(&shpool->mutex); ngx_queue_remove(&channel_worker_cur->queue); ngx_slab_free_locked(shpool, channel_worker_cur); ngx_shmtx_unlock(&shpool->mutex); channel_worker_cur = NULL; break; } } } // free worker_msg already sent ngx_shmtx_lock(&shpool->mutex); ngx_http_push_stream_free_worker_message_memory_locked(shpool, worker_msg); ngx_shmtx_unlock(&shpool->mutex); } }
static void ngx_http_session_store_expire(ngx_http_session_store_ctx_t *ctx, ngx_uint_t n) { time_t now; ngx_queue_t *q; ngx_rbtree_node_t *node; ngx_http_session_store_node_t *ssn; now = ngx_time(); /* * n == 1 deletes one or two entries * n == 0 deletes oldest entry by force * and one or two entries */ while (n < 3) { if (ngx_queue_empty(&ctx->sh->queue)) { return; } q = ngx_queue_last(&ctx->sh->queue); ssn = ngx_queue_data(q, ngx_http_session_store_node_t, queue); if (n++ != 0) { if (now < ssn->expire) { return; } } ngx_queue_remove(q); 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 int ngx_tcp_lua_shdict_set_helper(lua_State *L, int flags) { int i, n; ngx_str_t key; uint32_t hash; ngx_int_t rc; ngx_tcp_lua_shdict_ctx_t *ctx; ngx_tcp_lua_shdict_node_t *sd; ngx_str_t value; int value_type; double num; u_char c; lua_Number exptime = 0; u_char *p; ngx_rbtree_node_t *node; ngx_time_t *tp; ngx_shm_zone_t *zone; int forcible = 0; /* indicates whether to foricibly override other * valid entries */ int32_t user_flags = 0; n = lua_gettop(L); if (n != 3 && n != 4 && n != 5) { return luaL_error(L, "expecting 3, 4 or 5 arguments, " "but only seen %d", n); } zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad \"zone\" argument"); } ctx = zone->data; if (lua_isnil(L, 2)) { lua_pushnil(L); lua_pushliteral(L, "nil key"); return 2; } key.data = (u_char *) luaL_checklstring(L, 2, &key.len); if (key.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty key"); return 2; } if (key.len > 65535) { lua_pushnil(L); lua_pushliteral(L, "key too long"); return 2; } hash = ngx_crc32_short(key.data, key.len); value_type = lua_type(L, 3); switch (value_type) { case LUA_TSTRING: value.data = (u_char *) lua_tolstring(L, 3, &value.len); break; case LUA_TNUMBER: value.len = sizeof(double); num = lua_tonumber(L, 3); value.data = (u_char *) # break; case LUA_TBOOLEAN: value.len = sizeof(u_char); c = lua_toboolean(L, 3) ? 1 : 0; value.data = &c; break; case LUA_TNIL: if (flags & (NGX_TCP_LUA_SHDICT_ADD|NGX_TCP_LUA_SHDICT_REPLACE)) { lua_pushnil(L); lua_pushliteral(L, "attempt to add or replace nil values"); return 2; } ngx_str_null(&value); break; default: lua_pushnil(L); lua_pushliteral(L, "bad value type"); return 2; } if (n >= 4) { exptime = luaL_checknumber(L, 4); if (exptime < 0) { exptime = 0; } } if (n == 5) { user_flags = (uint32_t) luaL_checkinteger(L, 5); } ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 ngx_tcp_lua_shdict_expire(ctx, 1); #endif rc = ngx_tcp_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); dd("shdict lookup returned %d", (int) rc); if (flags & NGX_TCP_LUA_SHDICT_REPLACE) { if (rc == NGX_DECLINED || rc == NGX_DONE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "not found"); lua_pushboolean(L, forcible); return 3; } /* rc == NGX_OK */ goto replace; } if (flags & NGX_TCP_LUA_SHDICT_ADD) { if (rc == NGX_OK) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "exists"); lua_pushboolean(L, forcible); return 3; } if (rc == NGX_DONE) { /* exists but expired */ dd("go to replace"); goto replace; } /* rc == NGX_DECLINED */ dd("go to insert"); goto insert; } if (rc == NGX_OK || rc == NGX_DONE) { if (value_type == LUA_TNIL) { goto remove; } replace: if (value.data && value.len == (size_t) sd->value_len) { ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, "lua shared dict set: found old entry and value " "size matched, reusing it"); ngx_queue_remove(&sd->queue); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); sd->key_len = (u_short) key.len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) (exptime * 1000); } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) value.len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key.data, key.len); ngx_memcpy(p, value.data, value.len); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, forcible); return 3; } ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, "lua shared dict set: found old entry bug value size " "NOT matched, removing it first"); remove: ngx_queue_remove(&sd->queue); 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); } insert: /* rc == NGX_DECLINED or value size unmatch */ if (value.data == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, 0); return 3; } ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, "lua shared dict set: creating a new entry"); n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_tcp_lua_shdict_node_t, data) + key.len + value.len; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node == NULL) { if (flags & NGX_TCP_LUA_SHDICT_SAFE_STORE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "no memory"); return 2; } ngx_log_debug1(NGX_LOG_DEBUG_TCP, ctx->log, 0, "lua shared dict set: overriding non-expired items " "due to memory shortage for entry \"%V\"", &key); for (i = 0; i < 30; i++) { if (ngx_tcp_lua_shdict_expire(ctx, 0) == 0) { break; } forcible = 1; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node != NULL) { goto allocated; } } ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "no memory"); lua_pushboolean(L, forcible); return 3; } allocated: sd = (ngx_tcp_lua_shdict_node_t *) &node->color; node->key = hash; sd->key_len = (u_short) key.len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) (exptime * 1000); } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) value.len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key.data, key.len); ngx_memcpy(p, value.data, value.len); ngx_rbtree_insert(&ctx->sh->rbtree, node); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, forcible); return 3; }