/* * [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); } }
// 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); } }
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); } }
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 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; }
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; }
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_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); }
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); }
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_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 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 time_t ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) { u_char *name; size_t len; time_t wait; ngx_uint_t tries; ngx_path_t *path; ngx_queue_t *q; ngx_http_file_cache_node_t *fcn; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache forced expire"); path = cache->path; len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; name = ngx_alloc(len + 1, ngx_cycle->log); if (name == NULL) { return 10; } ngx_memcpy(name, path->name.data, path->name.len); wait = 10; tries = 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 file cache forced expire: #%d %d %02xd%02xd%02xd%02xd", fcn->count, fcn->exists, fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); if (fcn->count) { if (tries++ < 20) { continue; } wait = 1; break; } if (!fcn->exists) { ngx_queue_remove(q); ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); ngx_slab_free_locked(cache->shpool, fcn); break; } ngx_http_file_cache_delete(cache, q, name); break; } ngx_shmtx_unlock(&cache->shpool->mutex); ngx_free(name); return wait; }
static int ngx_proc_luashm_backup_backup(ngx_cycle_t *cycle,ngx_shm_zone_t *zone) { ngx_proc_luashm_backup_conf_t *pbcf; ngx_queue_t *q, *prev; ngx_http_lua_shdict_node_t *sd; ngx_http_lua_shdict_node_ext_t *extsd; ngx_http_lua_shdict_ctx_t *ctx; ngx_time_t *tp; int total = 0; uint64_t now; uint32_t content_size; size_t len; ngx_buf_t *buff; double *num_value; ngx_file_t file; u_char *shm_file_path; pbcf = ngx_proc_get_conf(cycle->conf_ctx, ngx_proc_luashm_backup_module); ctx = zone->data; buff = ngx_create_temp_buf(cycle->pool, zone->shm.size+65536); buff->last += sizeof(uint32_t); tp = ngx_timeofday(); now = (uint64_t) tp->sec * 1000 + tp->msec; ngx_shmtx_lock(&ctx->shpool->mutex); if (ngx_queue_empty(&ctx->sh->queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); return 1; } /* first run through: get total number of elements we need to allocate */ /* second run through: add keys to table */ total = 0; 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_http_lua_shdict_node_t, queue); if (sd->expires == 0 || ((int64_t)(sd->expires - now)) > 60000) { //lua_pushlstring(L, (char *) sd->data, sd->key_len); //lua_rawseti(L, -2, ++total); extsd = (ngx_http_lua_shdict_node_ext_t*)buff->last; extsd->key_len=sd->key_len; extsd->expires=sd->expires; extsd->value_type=sd->value_type; extsd->user_flags=sd->user_flags; len = sd->key_len+sd->value_len; ngx_memcpy(extsd->data,sd->data,len); buff->last += sizeof(ngx_http_lua_shdict_node_ext_t)+len; switch (sd->value_type) { case LUA_TSTRING: extsd->value_len=sd->value_len; break; case LUA_TNUMBER: extsd->value_len=sizeof(double); num_value = extsd->data+extsd->key_len; //ngx_memcpy(num_value, extsd->data+extsd->key_len, extsd->value_len); break; case LUA_TBOOLEAN: extsd->value_len=sizeof(u_char); break; } //dd("key:%s, key_len:%d,value:%f,value_len:%d,expires:%lu,now:%lu",extsd->data,extsd->key_len,*num_value,extsd->value_len,extsd->expires,now); } q = prev; } ngx_shmtx_unlock(&ctx->shpool->mutex); shm_file_path=ngx_palloc(cycle->pool,pbcf->path.len + 5+ zone->shm.name.len); ngx_sprintf(shm_file_path,"%s/%s.dat",pbcf->path.data,zone->shm.name.data); content_size = buff->last-buff->pos; ngx_log_error(NGX_LOG_INFO,cycle->log,0,"save file:%s, content_size:%l bytes, nowtime:%l", shm_file_path,content_size,now); if(content_size > sizeof(uint32_t)) ngx_memcpy(buff->pos,&content_size,sizeof(uint32_t)); file.fd = open((char*)shm_file_path, O_TRUNC|O_RDWR, S_IWUSR|S_IWGRP|S_IRGRP|S_IRUSR); if (file.fd == NGX_INVALID_FILE) { //ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,ngx_open_file_n " \"%s\" failed",filename->data); ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,ngx_open_file_n " \"%s\" failed",shm_file_path); ngx_pfree(cycle->pool,buff); ngx_pfree(cycle->pool,shm_file_path); return NGX_ERROR; } file.name.len = pbcf->path.len; file.name.data = pbcf->path.data; file.offset = 0; file.log = cycle->log; file.offset=0; ngx_write_file(&file,buff->pos,content_size,0); ngx_close_file(file.fd); /* table is at top of stack */ ngx_pfree(cycle->pool,shm_file_path); ngx_pfree(cycle->pool,buff->start); ngx_pfree(cycle->pool,buff); return 1; }
static ngx_int_t ngx_http_req_status_show_handler(ngx_http_request_t *r) { size_t size, item_size; u_char long_num, full_info, clear_status; ngx_int_t rc; ngx_buf_t *b; ngx_uint_t i; ngx_array_t items; ngx_queue_t *q; ngx_chain_t out; ngx_http_req_status_zone_t **pzone; ngx_http_req_status_node_t *rsn; ngx_http_req_status_main_conf_t *rmcf; ngx_http_req_status_print_item_t *item; static u_char header[] = "zone_name\tkey\tmax_active\tmax_bw\ttraffic\trequests\t" "active\tbandwidth\tresptime\n"; if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_set(&r->headers_out.content_type, "text/plain"); if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } #define NGX_STRCHR(s, u) \ (ngx_strlchr((s)->data, (s)->data + (s)->len, u) != NULL) full_info = NGX_STRCHR(&r->args, 'f'); long_num = NGX_STRCHR(&r->args, 'l'); clear_status = NGX_STRCHR(&r->args, 'c'); item_size = sizeof(ngx_http_req_status_print_item_t) + (clear_status ? sizeof(ngx_http_req_status_data_t) : 0); if (ngx_array_init(&items, r->pool, 40, item_size) != NGX_OK){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } size = sizeof(header) - 1; rmcf = ngx_http_get_module_main_conf(r, ngx_http_req_status_module); pzone = rmcf->zones.elts; for (i = 0; i < rmcf->zones.nelts; i++){ ngx_shmtx_lock(&pzone[i]->shpool->mutex); for (q = ngx_queue_last(&pzone[i]->sh->queue); q != ngx_queue_sentinel(&pzone[i]->sh->queue); q = ngx_queue_prev(q)) { rsn = ngx_queue_data(q, ngx_http_req_status_node_t, queue); if (!rsn->data.requests){ continue; } if (rsn->last_traffic){ if (ngx_current_msec > rsn->last_traffic_update && ngx_current_msec - rsn->last_traffic_update >= rmcf->interval){ rsn->last_traffic_start = 0; rsn->last_traffic = 0; rsn->data.bandwidth = 0; rsn->last_traffic_update = ngx_current_msec; } } size += pzone[i]->shm_zone->shm.name.len + rsn->len + (sizeof("\t") - 1) * 8 + (NGX_INT64_LEN) * 7; // 6 change to 7, for rt, if (full_info){ size += (NGX_INT64_LEN) * 3 + (sizeof("\t") - 1) * 3; } item = ngx_array_push(&items); if (item == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } item->zone_name = &pzone[i]->shm_zone->shm.name; item->node = rsn; if (clear_status){ item->pdata = NULL; ngx_memcpy(&item->data[0], &rsn->data, sizeof(ngx_http_req_status_data_t)); ngx_memzero(&rsn->data, sizeof(ngx_http_req_status_data_t)); } else { item->pdata = &rsn->data; } } pzone[i]->sh->expire_lock = ngx_time() + rmcf->lock_time; ngx_shmtx_unlock(&pzone[i]->shpool->mutex); } if (items.nelts > 1) { ngx_qsort(items.elts, (size_t) items.nelts, item_size, ngx_http_req_status_cmp_items); } b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); item = items.elts; for (i = 0; i < items.nelts; i++){ if (i) { item = (ngx_http_req_status_print_item_t *) ((u_char *)item + item_size); } /* set pdata here because of qsort above */ if (item->pdata == NULL){ item->pdata = &item->data[0]; } b->last = ngx_cpymem(b->last, item->zone_name->data, item->zone_name->len); *b->last ++ = '\t'; b->last = ngx_cpymem(b->last, item->node->key, item->node->len); *b->last ++ = '\t'; if (long_num){ b->last = ngx_sprintf(b->last, "%ui\t%ui\t%ui\t%ui\t%ui\t%ui\t%ui", item->pdata->max_active, item->pdata->max_bandwidth * 8, item->pdata->traffic * 8, item->pdata->requests, item->node->active, item->pdata->bandwidth * 8, item->pdata->rt); } else { b->last = ngx_sprintf(b->last, "%ui\t", item->pdata->max_active); b->last = ngx_http_req_status_format_size(b->last, item->pdata->max_bandwidth * 8); *b->last ++ = '\t'; b->last = ngx_http_req_status_format_size(b->last, item->pdata->traffic * 8); *b->last ++ = '\t'; b->last = ngx_sprintf(b->last, "%ui\t", item->pdata->requests); b->last = ngx_sprintf(b->last, "%ui\t", item->node->active); b->last = ngx_http_req_status_format_size(b->last, item->pdata->bandwidth * 8); *b->last ++ = '\t'; b->last = ngx_sprintf(b->last, "%ui", item->pdata->rt); } if (full_info){ b->last = ngx_sprintf(b->last, "\t%ui\t%ui\t%ui", item->node->last_traffic * 8, item->node->last_traffic_start, item->node->last_traffic_update); } *b->last ++ = '\n'; } out.buf = b; out.next = NULL; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = 1; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_http_req_status_show_json_handler(ngx_http_request_t *r) { size_t item_size; ngx_int_t rc; ngx_buf_t *b; ngx_uint_t i; ngx_array_t items; ngx_queue_t *q; ngx_chain_t out; ngx_http_req_status_zone_t **pzone; ngx_http_req_status_node_t *rsn; ngx_http_req_status_main_conf_t *rmcf; ngx_http_req_status_print_item_t *item; #define NGX_HTTP_REQ_STATUS_JSON_BUFFER_SIZE (int) 262144 #define NGX_HTTP_REQ_STATUS_JSON_FMT_S "{" #define NGX_HTTP_REQ_STATUS_JSON_FMT_E "}" #define NGX_HTTP_REQ_STATUS_JSON_FMT_NEXT "," #define NGX_HTTP_REQ_STATUS_JSON_FMT_ZONE_LIST_S "\"zone_list\":[" #define NGX_HTTP_REQ_STATUS_JSON_FMT_ZONE_LIST_E "]" #define NGX_HTTP_REQ_STATUS_JSON_FMT_STAT_ITEM \ "{" \ "\"zone_name\":\"%s\"," \ "\"key\":\"%s\"," \ "\"max_active\":%ui," \ "\"max_bw\":%ui," \ "\"traffic\":%ui," \ "\"requests\":%ui," \ "\"active\":%ui," \ "\"bandwith\":%ui" \ "}" if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_set(&r->headers_out.content_type, "application/json"); if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } item_size = sizeof(ngx_http_req_status_print_item_t); if (ngx_array_init(&items, r->pool, 40, item_size) != NGX_OK){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } rmcf = ngx_http_get_module_main_conf(r, ngx_http_req_status_module); pzone = rmcf->zones.elts; for (i = 0; i < rmcf->zones.nelts; i++){ ngx_shmtx_lock(&pzone[i]->shpool->mutex); for (q = ngx_queue_last(&pzone[i]->sh->queue); q != ngx_queue_sentinel(&pzone[i]->sh->queue); q = ngx_queue_prev(q)) { rsn = ngx_queue_data(q, ngx_http_req_status_node_t, queue); if (!rsn->data.requests){ continue; } if (rsn->last_traffic){ if (ngx_current_msec > rsn->last_traffic_update && ngx_current_msec - rsn->last_traffic_update >= rmcf->interval){ rsn->last_traffic_start = 0; rsn->last_traffic = 0; rsn->data.bandwidth = 0; rsn->last_traffic_update = ngx_current_msec; } } item = ngx_array_push(&items); if (item == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } item->zone_name = &pzone[i]->shm_zone->shm.name; item->node = rsn; item->pdata = &rsn->data; } pzone[i]->sh->expire_lock = ngx_time() + rmcf->lock_time; ngx_shmtx_unlock(&pzone[i]->shpool->mutex); } if (items.nelts > 1) { ngx_qsort(items.elts, (size_t) items.nelts, item_size, ngx_http_req_status_cmp_items); } b = ngx_create_temp_buf(r->pool, NGX_HTTP_REQ_STATUS_JSON_BUFFER_SIZE); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->last = ngx_sprintf(b->last, NGX_HTTP_REQ_STATUS_JSON_FMT_S); b->last = ngx_sprintf(b->last, NGX_HTTP_REQ_STATUS_JSON_FMT_ZONE_LIST_S); item = items.elts; for (i = 0; i < items.nelts; i++){ if (i) { item = (ngx_http_req_status_print_item_t *) ((u_char *)item + item_size); } /* set pdata here because of qsort above */ if (item->pdata == NULL){ item->pdata = &item->data[0]; } b->last = ngx_sprintf(b->last, NGX_HTTP_REQ_STATUS_JSON_FMT_STAT_ITEM, item->zone_name->data, item->node->key, item->pdata->max_active, item->pdata->max_bandwidth * 8, item->pdata->traffic * 8, item->pdata->requests, item->node->active, item->pdata->bandwidth * 8); if(i+1 != items.nelts) { b->last = ngx_sprintf(b->last, NGX_HTTP_REQ_STATUS_JSON_FMT_NEXT); } } b->last = ngx_sprintf(b->last, NGX_HTTP_REQ_STATUS_JSON_FMT_ZONE_LIST_E); b->last = ngx_sprintf(b->last, NGX_HTTP_REQ_STATUS_JSON_FMT_E); out.buf = b; out.next = NULL; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = 1; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static int ngx_tcp_lua_shdict_flush_expired(lua_State *L) { ngx_queue_t *q, *prev; ngx_tcp_lua_shdict_node_t *sd; ngx_tcp_lua_shdict_ctx_t *ctx; ngx_shm_zone_t *zone; ngx_time_t *tp; int freed = 0; int attempts = 0; ngx_rbtree_node_t *node; uint64_t now; int n; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting 1 or 2 argument(s), but saw %d", n); } luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } if (n == 2) { attempts = luaL_checkint(L, 2); } ctx = zone->data; ngx_shmtx_lock(&ctx->shpool->mutex); if (ngx_queue_empty(&ctx->sh->queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnumber(L, 0); return 1; } 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_tcp_lua_shdict_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); lua_pushnumber(L, freed); return 1; }
static int shared_dict_get2mqtt(lua_State * L) { ngx_http_lua_shdict_ctx_t *ctx; ngx_shm_zone_t *zone; ngx_queue_t *q, *prev; ngx_http_lua_shdict_node_t *sd; ngx_time_t *tp; int n; int total = 0; int attempts = 1024; uint64_t now; ngx_str_t zone_name,topic; double *num; bool is_expression; uint32_t hash; u_char c; n = lua_gettop(L); if (n != 2) { return luaL_error(L, "expecting 2 arguments, " "but only seen %d", n); } //zone = lua_touserdata(L, 1); //if (zone == NULL) { //return luaL_error(L, "bad \"zone\" argument"); //} zone_name.data = (u_char *) luaL_checklstring(L, 1, &zone_name.len); if (zone_name.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty zone_name"); return 2; } topic.data = (u_char *) luaL_checklstring(L, 2, &topic.len); if (topic.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty topic"); return 2; } zone = ngx_http_lua_find_zone(zone_name.data,zone_name.len); if (zone == NULL) { return luaL_error(L, "not found \"zone\" by argument: %s",zone_name.data); } ctx = zone->data; if (ctx == NULL) { return luaL_error(L, "bad \"ctx\" argument"); } tp = ngx_timeofday(); now = (uint64_t) tp->sec * 1000 + tp->msec; for(n=topic.len-1;n>=0;n--){ switch(topic.data[n]){ case '+': case '#': n=-1; is_expression=true; break; } } if(!is_expression) hash = ngx_crc32_short(topic.data, topic.len); //ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "is_expression %d,topic: %s",is_expression,topic.data); ngx_shmtx_lock(&ctx->shpool->mutex); if(!is_expression){ n = ngx_http_lua_shdict_lookup(zone, hash, topic.data, topic.len, &sd); ngx_shmtx_unlock(&ctx->shpool->mutex); if (n == NGX_OK) { lua_createtable(L, 1, 0); lua_pushlstring(L, sd->data, sd->key_len); num = (double *) (sd->data+sd->key_len); lua_pushnumber(L, *num); lua_rawset(L, -3); }else{ lua_createtable(L, 0, 0); } return 1; } if (ngx_queue_empty(&ctx->sh->queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_createtable(L, 0, 0); return 1; } lua_createtable(L, 10000, 0); total = 0; 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_http_lua_shdict_node_t, queue); if(ngx_mqtt_str_is_match(sd->data, sd->key_len,topic.data,topic.len)){ if (sd->expires == 0 || sd->expires > now) { lua_pushlstring(L, sd->data, sd->key_len); num = (double *) (sd->data+sd->key_len); lua_pushnumber(L, *num); //lua_rawseti(L, -3);//, ++total); lua_rawset(L, -3); } } q = prev; } ngx_shmtx_unlock(&ctx->shpool->mutex); return 1; }
static ngx_int_t ngx_http_push_stream_respond_to_subscribers(ngx_http_push_stream_channel_t *channel, ngx_http_push_stream_queue_elem_t *subscribers_sentinel, ngx_http_push_stream_msg_t *msg) { ngx_http_push_stream_queue_elem_t *cur = subscribers_sentinel; if (subscribers_sentinel == NULL) { return NGX_ERROR; } if (msg != NULL) { // now let's respond to some requests! while ((cur = (ngx_http_push_stream_queue_elem_t *) ngx_queue_next(&cur->queue)) != subscribers_sentinel) { ngx_http_push_stream_subscriber_t *subscriber = (ngx_http_push_stream_subscriber_t *) cur->value; if (subscriber->longpolling) { ngx_http_push_stream_queue_elem_t *prev = (ngx_http_push_stream_queue_elem_t *) ngx_queue_prev(&cur->queue); ngx_http_push_stream_add_response_header(subscriber->request, &NGX_HTTP_PUSH_STREAM_HEADER_TRANSFER_ENCODING, &NGX_HTTP_PUSH_STREAM_HEADER_CHUNCKED); ngx_http_push_stream_add_polling_headers(subscriber->request, msg->time, msg->tag, subscriber->request->pool); ngx_http_send_header(subscriber->request); //Adam Konrad: putting If-Modified-Since and etag to the response body ngx_http_push_stream_send_http_time( subscriber->request, msg->time, msg->tag, subscriber->request->pool); ngx_http_push_stream_send_response_content_header(subscriber->request, ngx_http_get_module_loc_conf(subscriber->request, ngx_http_push_stream_module)); ngx_http_push_stream_send_response_message(subscriber->request, channel, msg, 1, 0); ngx_http_push_stream_send_response_finalize(subscriber->request); cur = prev; } else { if (ngx_http_push_stream_send_response_message(subscriber->request, channel, msg, 0, 0) != NGX_OK) { ngx_http_push_stream_queue_elem_t *prev = (ngx_http_push_stream_queue_elem_t *) ngx_queue_prev(&cur->queue); ngx_http_push_stream_send_response_finalize(subscriber->request); cur = prev; } else { ngx_http_push_stream_subscriber_ctx_t *ctx = ngx_http_get_module_ctx(subscriber->request, ngx_http_push_stream_module); ngx_http_push_stream_loc_conf_t *pslcf = ngx_http_get_module_loc_conf(subscriber->request, ngx_http_push_stream_module); ngx_http_push_stream_timer_reset(pslcf->ping_message_interval, ctx->ping_timer); } } } } return NGX_OK; }
static int ngx_tcp_lua_shdict_get_keys(lua_State *L) { ngx_queue_t *q, *prev; ngx_tcp_lua_shdict_node_t *sd; ngx_tcp_lua_shdict_ctx_t *ctx; ngx_shm_zone_t *zone; ngx_time_t *tp; int total = 0; int attempts = 1024; uint64_t now; int n; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting 1 or 2 argument(s), " "but saw %d", n); } luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } if (n == 2) { attempts = luaL_checkint(L, 2); } ctx = zone->data; ngx_shmtx_lock(&ctx->shpool->mutex); if (ngx_queue_empty(&ctx->sh->queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_createtable(L, 0, 0); return 1; } tp = ngx_timeofday(); now = (uint64_t) tp->sec * 1000 + tp->msec; /* first run through: get total number of elements we need to allocate */ 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_tcp_lua_shdict_node_t, queue); if (sd->expires == 0 || sd->expires > now) { total++; if (attempts && total == attempts) { break; } } q = prev; } lua_createtable(L, total, 0); /* second run through: add keys to table */ total = 0; 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_tcp_lua_shdict_node_t, queue); if (sd->expires == 0 || sd->expires > now) { lua_pushlstring(L, (char *) sd->data, sd->key_len); lua_rawseti(L, -2, ++total); if (attempts && total == attempts) { break; } } q = prev; } ngx_shmtx_unlock(&ctx->shpool->mutex); /* table is at top of stack */ return 1; }
/* * 强制删除一个cache节点 */ static time_t ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) { u_char *name; size_t len; time_t wait; ngx_uint_t tries; ngx_path_t *path; ngx_queue_t *q; ngx_http_file_cache_node_t *fcn; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache forced expire"); path = cache->path; len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; // 文件的完整路径 // len + 1: 文件名包括"\0" name = ngx_alloc(len + 1, ngx_cycle->log); if (name == NULL) { return 10; } ngx_memcpy(name, path->name.data, path->name.len); wait = 10; tries = 20; 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 file cache forced expire: #%d %d %02xd%02xd%02xd%02xd", fcn->count, fcn->exists, fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); // cache节点引用计数等于0时,直接删除文件 if (fcn->count == 0) { ngx_http_file_cache_delete(cache, q, name); wait = 0; } else { // 尝试20次 if (--tries) { continue; } wait = 1; } break; } ngx_shmtx_unlock(&cache->shpool->mutex); ngx_free(name); return wait; }