/*
 *	[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);					
    }
}
Esempio n. 2
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);
    }
}
Esempio n. 3
0
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);
    }
}
Esempio n. 4
0
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节点之后(此处即为简单插入) */
    }
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 8
0
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);
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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);
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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;
}
Esempio n. 19
0
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;
}