/*
 *	[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);					
    }
}
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节点之后(此处即为简单插入) */
    }
}
Exemple #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);
    }
}
Exemple #4
0
// cmp 指向函数的指针
// 队列排序采用的是稳定的简单插入排序方法,即从第一个节点开始遍历,依次将节点(q)插入前面已经排序好的队列(链表)中
// prev 为已经排序好的queue
void
ngx_queue_sort(ngx_queue_t *queue,
    ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
{
    ngx_queue_t  *q, *prev, *next;

    q = ngx_queue_head(queue);
    
    // 若只有一个元素,则无须排序
    if (q == ngx_queue_last(queue)) {
        return;
    }

    for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) {

        prev = ngx_queue_prev(q);
        // 也充当了循环条件
        next = ngx_queue_next(q);

        ngx_queue_remove(q);

        do {
            // 指针函数调用
            if (cmp(prev, q) <= 0) {
                break;
            }

            prev = ngx_queue_prev(prev);

        } while (prev != ngx_queue_sentinel(queue));

        ngx_queue_insert_after(prev, q);
    }
}
static ngx_inline void
ngx_http_push_stream_census_worker_subscribers(void)
{
    ngx_slab_pool_t                             *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
    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_worker_data_t          *workers_data = data->ipc;
    ngx_http_push_stream_worker_data_t          *thisworker_data = workers_data + ngx_process_slot;
    ngx_http_push_stream_queue_elem_t           *cur;
    ngx_http_push_stream_subscription_t         *cur_subscription;

    ngx_shmtx_lock(&shpool->mutex);

    cur = thisworker_data->subscribers_sentinel;
    while ((cur = (ngx_http_push_stream_queue_elem_t *) ngx_queue_next(&cur->queue)) != thisworker_data->subscribers_sentinel) {
        ngx_http_push_stream_subscriber_t *subscriber = (ngx_http_push_stream_subscriber_t *) cur->value;
        cur_subscription = &subscriber->subscriptions_sentinel;
        while ((cur_subscription = (ngx_http_push_stream_subscription_t *) ngx_queue_next(&cur_subscription->queue)) != &subscriber->subscriptions_sentinel) {
            cur_subscription->channel->subscribers++;
        }
        data->subscribers++;
        thisworker_data->subscribers++;
    }

    ngx_shmtx_unlock(&shpool->mutex);
}
//garbage-collecting slab allocator
void * ngx_http_push_slab_alloc_locked(size_t size) {
	void  *p;
	if((p = ngx_slab_alloc_locked(ngx_http_push_shpool, size))==NULL) {
		ngx_http_push_channel_queue_t *ccur, *cnext;
		ngx_uint_t                  collected = 0;
		//failed. emergency garbage sweep, then.
		
		//collect channels
		ngx_queue_init(&channel_gc_sentinel.queue);
		ngx_http_push_walk_rbtree(ngx_http_push_channel_collector);
		for(ccur=(ngx_http_push_channel_queue_t *)ngx_queue_next(&channel_gc_sentinel.queue); ccur != &channel_gc_sentinel; ccur=cnext) {
			cnext = (ngx_http_push_channel_queue_t *)ngx_queue_next(&ccur->queue);
			ngx_http_push_delete_channel_locked(ccur->channel);
			ngx_free(ccur);
			collected++;
		}
		
		//todo: collect worker messages maybe
		
		ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "push module: out of shared memory. emergency garbage collection deleted %ui unused channels.", collected);
		
		return ngx_slab_alloc_locked(ngx_http_push_shpool, size);
	}
	return p;
}
static void
ngx_http_push_stream_broadcast(ngx_http_push_stream_channel_t *channel, ngx_http_push_stream_msg_t *msg, ngx_log_t *log)
{
    // subscribers are queued up in a local pool. Queue heads, however, are located
    // in shared memory, identified by pid.
    ngx_http_push_stream_pid_queue_t        *sentinel = &channel->workers_with_subscribers;
    ngx_http_push_stream_pid_queue_t        *cur = sentinel;
    ngx_slab_pool_t                         *shpool = (ngx_slab_pool_t *) ngx_http_push_stream_shm_zone->shm.addr;
    ngx_flag_t                               queue_was_empty[NGX_MAX_PROCESSES];

    ngx_shmtx_lock(&shpool->mutex);
    while ((cur = (ngx_http_push_stream_pid_queue_t *) ngx_queue_next(&cur->queue)) != sentinel) {
        ngx_http_push_stream_send_worker_message_locked(channel, &cur->subscribers_sentinel, cur->pid, cur->slot, msg, &queue_was_empty[cur->slot], log);
    }
    ngx_shmtx_unlock(&shpool->mutex);

    cur = sentinel;
    while ((cur = (ngx_http_push_stream_pid_queue_t *) ngx_queue_next(&cur->queue)) != sentinel) {
        // interprocess communication breakdown
        if (queue_was_empty[cur->slot] && (ngx_http_push_stream_alert_worker_check_messages(cur->pid, cur->slot, log) != NGX_OK)) {
            ngx_log_error(NGX_LOG_ERR, log, 0, "push stream module: error communicating with worker process, pid: %P, slot: %d", cur->pid, cur->slot);
        }
    }

    if ((msg->queue.prev == NULL) && (msg->queue.next == NULL)) {
        ngx_shmtx_lock(&shpool->mutex);
        ngx_http_push_stream_mark_message_to_delete_locked(msg);
        ngx_shmtx_unlock(&shpool->mutex);
    }
}
ngx_queue_t *
ngx_queue_middle(ngx_queue_t *queue)
{
    ngx_queue_t  *middle, *next;

    middle = ngx_queue_head(queue);

    if (middle == ngx_queue_last(queue)) {
        return middle;
    }

    next = ngx_queue_head(queue);

    for ( ;; ) {
        middle = ngx_queue_next(middle);

        next = ngx_queue_next(next);

        if (next == ngx_queue_last(queue)) {
            return middle;
        }

        next = ngx_queue_next(next);

        if (next == ngx_queue_last(queue)) {
            return middle;
        }
    }
}
Exemple #9
0
// 参考:http://blog.csdn.net/livelylittlefish/article/details/6607324
// 获得队列的中间节点,(除头节点外)若队列有奇数个节点,则返回中间节点;
// 若队列有偶数个节点,则返回后半个队列的第一个节点;
ngx_queue_t *
ngx_queue_middle(ngx_queue_t *queue)
{
    ngx_queue_t  *middle, *next;

    middle = ngx_queue_head(queue);

    //若只有一个元素
    if (middle == ngx_queue_last(queue)) {
        return middle;
    }

    next = ngx_queue_head(queue);

    // 此循环中,next指针每次移动两个节点,而middle指针每次移动一个节点
    for ( ;; ) {
        middle = ngx_queue_next(middle);

        next = ngx_queue_next(next);

        // 偶数个节点,在此返回后半个队列的第一个节点
        if (next == ngx_queue_last(queue)) {
            return middle;
        }

        next = ngx_queue_next(next);

        // 奇数个节点,在此返回中间节点
        if (next == ngx_queue_last(queue)) {
            return middle;
        }
    }
}
Exemple #10
0
static void
ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
{
    u_char                     *name;
    size_t                      len;
    ngx_queue_t                *x, tail;
    ngx_http_location_queue_t  *lq, *lx;

    if (q == ngx_queue_last(locations)) {
        return;
    }

    lq = (ngx_http_location_queue_t *) q;

    if (lq->inclusive == NULL) {
        ngx_http_create_locations_list(locations, ngx_queue_next(q));
        return;
    }

    len = lq->name->len;
    name = lq->name->data;

    for (x = ngx_queue_next(q);
         x != ngx_queue_sentinel(locations);
         x = ngx_queue_next(x))
    {
        lx = (ngx_http_location_queue_t *) x;

        if (len > lx->name->len
            || (ngx_strncmp(name, lx->name->data, len) != 0))
        {
            break;
        }
    }

    q = ngx_queue_next(q);

    if (q == x) {
        ngx_http_create_locations_list(locations, x);
        return;
    }

    ngx_queue_split(locations, q, &tail);
    ngx_queue_add(&lq->list, &tail);

    if (x == ngx_queue_sentinel(locations)) {
        ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
        return;
    }

    ngx_queue_split(&lq->list, x, &tail);
    ngx_queue_add(locations, &tail);

    ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));

    ngx_http_create_locations_list(locations, x);
}
/** find message with entity tags matching those of the request r.
  * @param r subscriber request
  */
static ngx_http_push_msg_t * ngx_http_push_find_message_locked(ngx_http_push_channel_t *channel, ngx_http_request_t *r, ngx_int_t *status) {
	//TODO: consider using an RBTree for message storage.
	ngx_queue_t                    *sentinel = &channel->message_queue->queue;
	ngx_queue_t                    *cur = ngx_queue_head(sentinel);
	ngx_http_push_msg_t            *msg;
	ngx_int_t                       tag = -1;
	time_t                          time = (r->headers_in.if_modified_since == NULL) ? 0 : ngx_http_parse_time(r->headers_in.if_modified_since->value.data, r->headers_in.if_modified_since->value.len);
	
	//channel's message buffer empty?
	if(channel->messages==0) {
		*status=NGX_HTTP_PUSH_MESSAGE_EXPECTED; //wait.
		return NULL;
	}
	
	// do we want a future message?
	msg = ngx_queue_data(sentinel->prev, ngx_http_push_msg_t, queue); 
	if(time <= msg->message_time) { //that's an empty check (Sentinel's values are zero)
		if(time == msg->message_time) {
			if(tag<0) { tag = ngx_http_push_subscriber_get_etag_int(r); }
			if(tag >= msg->message_tag) {
				*status=NGX_HTTP_PUSH_MESSAGE_EXPECTED;
				return NULL;
			}
		}
	}
	else {
		*status=NGX_HTTP_PUSH_MESSAGE_EXPECTED;
		return NULL;
	}
	
	while(cur!=sentinel) {
		msg = ngx_queue_data(cur, ngx_http_push_msg_t, queue);
		if (time < msg->message_time) {
			*status = NGX_HTTP_PUSH_MESSAGE_FOUND;
			return msg;
		}
		else if(time == msg->message_time) {
			if(tag<0) { tag = ngx_http_push_subscriber_get_etag_int(r); }
			while (tag >= msg->message_tag  && time == msg->message_time && ngx_queue_next(cur)!=sentinel) {
				cur=ngx_queue_next(cur);
				msg = ngx_queue_data(cur, ngx_http_push_msg_t, queue);
			}
			if(time == msg->message_time && tag < msg->message_tag) {
				*status = NGX_HTTP_PUSH_MESSAGE_FOUND;
				return msg;
			}
			continue;
		}
		cur=ngx_queue_next(cur);
	}
	*status = NGX_HTTP_PUSH_MESSAGE_EXPIRED; //message too old and was not found.
	return NULL;
}
int main(int argc, char *argv[])
{
    ngx_int_t n;
    ngx_log_t * log;

    ngx_queue_t queue_container;
    ngx_queue_t *q;
    test_node node[5];
    test_node *ele_node;
    ngx_pagesize = getpagesize();
    n =  ngx_strerror_init();
    if (n == NGX_ERROR){
        return NGX_ERROR;
    }

    ngx_time_init();
    log =  ngx_log_init((u_char *)"./");
    ngx_use_stderr = 0;
    if (log == NULL){
        ngx_log_stderr(NGX_ERROR,(const char*)"can not init log ");
        return NGX_ERROR;
    }

    ngx_queue_init(&queue_container);

    for (n = 0;n < 5;n++){
        node[n].num = n;
    }

    ngx_queue_insert_tail(&queue_container,&node[0].queue);
    ngx_queue_insert_head(&queue_container,&node[1].queue);
    ngx_queue_insert_after(&queue_container,&node[2].queue);
    ngx_queue_insert_head(&queue_container,&node[3].queue);
    ngx_queue_insert_tail(&queue_container,&node[4].queue);

    for (q = ngx_queue_head(&queue_container);
         q != ngx_queue_sentinel(&queue_container);
         q = ngx_queue_next(q)){
        ele_node = ngx_queue_data(q,test_node,queue);
        printf("%d\n",ele_node->num);
    }

    ngx_queue_sort(&queue_container,cmp_test_node);
    for (q = ngx_queue_head(&queue_container);
         q != ngx_queue_sentinel(&queue_container);
         q = ngx_queue_next(q)){
        ele_node = ngx_queue_data(q,test_node,queue);
        printf("%d\n",ele_node->num);
    }


     return NGX_OK;
}
static void
ngx_http_push_stream_send_old_messages(ngx_http_request_t *r, ngx_http_push_stream_channel_t *channel, ngx_uint_t backtrack, time_t if_modified_since, ngx_int_t tag, time_t greater_message_time, ngx_int_t greater_message_tag, ngx_str_t *last_event_id)
{
    ngx_http_push_stream_msg_t *message;
    ngx_queue_t                *cur;

    if (ngx_http_push_stream_has_old_messages_to_send(channel, backtrack, if_modified_since, tag, greater_message_time, greater_message_tag, last_event_id)) {
        cur = &channel->message_queue;
        if (backtrack > 0) {
            ngx_uint_t qtd = (backtrack > channel->stored_messages) ? channel->stored_messages : backtrack;
            ngx_uint_t start = channel->stored_messages - qtd;
            // positioning at first message, and send the others
            while ((qtd > 0) && (cur = ngx_queue_next(cur)) && (cur != NULL) && (cur != &channel->message_queue)) {
                message = (ngx_http_push_stream_msg_t *) ngx_queue_data(cur, ngx_http_push_stream_msg_t, queue);
                if (message->deleted) {
                    break;
                }

                if (start == 0) {
                    ngx_http_push_stream_send_response_message(r, channel, message, 0, 1);
                    qtd--;
                } else {
                    start--;
                }
            }
        } else if ((last_event_id != NULL) || (if_modified_since >= 0)) {
            ngx_flag_t found = 0;
            while ((cur = ngx_queue_next(cur)) && (cur != NULL) && (cur != &channel->message_queue)) {
                message = (ngx_http_push_stream_msg_t *) ngx_queue_data(cur, ngx_http_push_stream_msg_t, queue);
                if (message->deleted) {
                    break;
                }

                if ((!found) && (last_event_id != NULL) && (message->event_id != NULL) && (ngx_memn2cmp(message->event_id->data, last_event_id->data, message->event_id->len, last_event_id->len) == 0)) {
                    found = 1;
                    continue;
                }

                if ((!found) && (last_event_id == NULL) && (if_modified_since >= 0) && ((message->time > if_modified_since) || ((message->time == if_modified_since) && (tag >= 0) && (message->tag >= tag)))) {
                    found = 1;
                    if ((message->time == if_modified_since) && (message->tag == tag)) {
                        continue;
                    }
                }

                if (found && (((greater_message_time == 0) && (greater_message_tag == -1)) || (greater_message_time > message->time) || ((greater_message_time == message->time) && (greater_message_tag >= message->tag)))) {
                    ngx_http_push_stream_send_response_message(r, channel, message, 0, 1);
                }
            }
        }
    }
}
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);
}
Exemple #15
0
void uv__cf_loop_cb(void* arg) {
  uv_loop_t* loop;
  ngx_queue_t* item;
  ngx_queue_t split_head;
  uv__cf_loop_signal_t* s;

  loop = arg;

  uv_mutex_lock(&loop->cf_mutex);
  ngx_queue_init(&split_head);
  if (!ngx_queue_empty(&loop->cf_signals)) {
    ngx_queue_t* split_pos = ngx_queue_next(&loop->cf_signals);
    ngx_queue_split(&loop->cf_signals, split_pos, &split_head);
  }
  uv_mutex_unlock(&loop->cf_mutex);

  while (!ngx_queue_empty(&split_head)) {
    item = ngx_queue_head(&split_head);

    s = ngx_queue_data(item, uv__cf_loop_signal_t, member);
    s->cb(s->arg);

    ngx_queue_remove(item);
    free(s);
  }
}
static void
ngx_http_gettoken_close_connection(ngx_http_gettoken_connection_t *c)
{
    ngx_queue_t *q;


    if (c->conn.connection) {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_gettoken: Closing connection (fd=%d)",
            c->conn.connection->fd);

        ngx_close_connection(c->conn.connection);
        c->conn.connection = NULL;
    }
    
    q = ngx_queue_head(&c->server->free_connections);
    while (q != ngx_queue_sentinel(&c->server->free_connections)) {
        if (q == &c->queue) {
            ngx_queue_remove(q);
            break;
        }
        q = ngx_queue_next(q);
    }
   
    c->rctx = NULL;
    if (c->state != STATE_DISCONNECTED) {
        c->state = STATE_DISCONNECTED;
        ngx_add_timer(&c->reconnect_event, c->server->reconnect_timeout);
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_gettoken: Connection scheduled for reconnection in %d ms", c->server->reconnect_timeout);
    }
}
Exemple #17
0
static void uv__cf_loop_cb(void* arg) {
  uv_loop_t* loop;
  ngx_queue_t* item;
  ngx_queue_t split_head;
  uv__cf_loop_signal_t* s;

  loop = arg;

  uv_mutex_lock(&loop->cf_mutex);
  ngx_queue_init(&split_head);
  if (!ngx_queue_empty(&loop->cf_signals)) {
    ngx_queue_t* split_pos = ngx_queue_next(&loop->cf_signals);
    ngx_queue_split(&loop->cf_signals, split_pos, &split_head);
  }
  uv_mutex_unlock(&loop->cf_mutex);

  while (!ngx_queue_empty(&split_head)) {
    item = ngx_queue_head(&split_head);

    s = ngx_queue_data(item, uv__cf_loop_signal_t, member);

    /* This was a termination signal */
    if (s->cb == NULL)
      CFRunLoopStop(loop->cf_loop);
    else
      s->cb(s->arg);

    ngx_queue_remove(item);
    free(s);
  }
}
Exemple #18
0
int ngx_shmap_foreach(ngx_shm_zone_t* zone, foreach_pt func, void* args)
{
    ngx_queue_t                 *q;
    ngx_shmap_node_t  *sd;
    ngx_shmap_ctx_t   *ctx;
	assert(zone != NULL);

    ctx = zone->data;

    int locked = ngx_shmtx_trylock(&ctx->shpool->mutex);
	if (!locked){
		return -1;
	}
	
    for (q = ngx_queue_head(&ctx->sh->queue);
         q != ngx_queue_sentinel(&ctx->sh->queue);
         q = ngx_queue_next(q))
    {
        sd = ngx_queue_data(q, ngx_shmap_node_t, queue);
   		func(sd, args);
    }

    ngx_shmtx_unlock(&ctx->shpool->mutex);

    return 0;
}
Exemple #19
0
int ngx_shmap_flush_all(ngx_shm_zone_t* zone)
{
    ngx_queue_t                 *q;
    ngx_shmap_node_t  *sd;
    ngx_shmap_ctx_t   *ctx;
	assert(zone != NULL);

    ctx = zone->data;

    ngx_shmtx_lock(&ctx->shpool->mutex);

    for (q = ngx_queue_head(&ctx->sh->queue);
         q != ngx_queue_sentinel(&ctx->sh->queue);
         q = ngx_queue_next(q))
    {
        sd = ngx_queue_data(q, ngx_shmap_node_t, queue);
        sd->expires = 1;
    }

    ngx_shmap_expire(ctx, 0);

    ngx_shmtx_unlock(&ctx->shpool->mutex);

    return 0;
}
int main(int argc, char const *argv[])
{
	
	ngx_queue_t queueContainer;
	ngx_queue_init(&queueContainer);

	int i = 0;
	my_queue node[5];
	for(;i < 5;++i){
		node[i].num = i;
	}
	ngx_queue_insert_tail(&queueContainer,&node[0].que);
	ngx_queue_insert_head(&queueContainer,&node[1].que);
	ngx_queue_insert_tail(&queueContainer,&node[2].que);
	ngx_queue_insert_after(&queueContainer,&node[3].que);
	ngx_queue_insert_tail(&queueContainer,&node[4].que);

	ngx_queue_sort(&queueContainer,compTestNode);

	ngx_queue_t *q;
	for(q = ngx_queue_head(&queueContainer);q != ngx_queue_sentinel(&queueContainer)
		;q = ngx_queue_next(q)){
		my_queue* eleNode = ngx_queue_data(q,my_queue,que);
		printf("%d\n",eleNode -> num );
	}


	
	return 0;
}
int
ngx_tcp_lua_ffi_shdict_flush_all(ngx_shm_zone_t *zone)
{
    ngx_queue_t                 *q;
    ngx_tcp_lua_shdict_node_t  *sd;
    ngx_tcp_lua_shdict_ctx_t   *ctx;

    ctx = zone->data;

    ngx_shmtx_lock(&ctx->shpool->mutex);

    for (q = ngx_queue_head(&ctx->sh->queue);
         q != ngx_queue_sentinel(&ctx->sh->queue);
         q = ngx_queue_next(q))
    {
        sd = ngx_queue_data(q, ngx_tcp_lua_shdict_node_t, queue);
        sd->expires = 1;
    }

    ngx_tcp_lua_shdict_expire(ctx, 0);

    ngx_shmtx_unlock(&ctx->shpool->mutex);

    return NGX_OK;
}
Exemple #22
0
static ngx_int_t
ngx_http_push_stream_assing_subscription_to_channel_locked(ngx_slab_pool_t *shpool, ngx_str_t *channel_id, ngx_http_push_stream_subscription_t *subscription, ngx_http_push_stream_subscription_t *subscriptions_sentinel, ngx_log_t *log)
{
    ngx_queue_t                                *cur_worker;
    ngx_http_push_stream_pid_queue_t           *worker, *worker_subscribers_sentinel = NULL;
    ngx_http_push_stream_channel_t             *channel;

    // check if channel still exists
    if ((channel = ngx_http_push_stream_find_channel(channel_id, log)) == NULL) {
        ngx_log_error(NGX_LOG_ERR, log, 0, "push stream module: something goes very wrong, arrived on ngx_http_push_stream_subscriber_assign_channel without created channel %s", channel_id->data);
        return NGX_ERROR;
    }

    cur_worker = &channel->workers_with_subscribers;
    while ((cur_worker = ngx_queue_next(cur_worker)) && (cur_worker != NULL) && (cur_worker != &channel->workers_with_subscribers)) {
        worker = ngx_queue_data(cur_worker, ngx_http_push_stream_pid_queue_t, queue);
        if (worker->pid == ngx_pid) {
            worker_subscribers_sentinel = worker;
            break;
        }
    }

    if (worker_subscribers_sentinel == NULL) { // found nothing
        worker_subscribers_sentinel = ngx_http_push_stream_create_worker_subscriber_channel_sentinel_locked(shpool, channel_id, log);
        if (worker_subscribers_sentinel == NULL) {
            return NGX_ERROR;
        }
    }

    channel->subscribers++; // do this only when we know everything went okay
    channel->last_activity_time = ngx_time();
    ngx_queue_insert_tail(&subscriptions_sentinel->queue, &subscription->queue);
    ngx_queue_insert_tail(&worker_subscribers_sentinel->subscriptions_queue, &subscription->channel_worker_queue);
    return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
{
    ngx_http_upstream_keepalive_peer_data_t  *kp = data;
    ngx_http_upstream_keepalive_cache_t      *item;

    ngx_int_t          rc;
    ngx_queue_t       *q, *cache;
    ngx_connection_t  *c;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                   "get keepalive peer");

    kp->failed = 0;

    /* ask balancer */

    rc = kp->original_get_peer(pc, kp->data);

    if (rc != NGX_OK) {
        return rc;
    }

    /* search cache for suitable connection */

    cache = &kp->conf->cache;

    for (q = ngx_queue_head(cache);
            q != ngx_queue_sentinel(cache);
            q = ngx_queue_next(q))
    {
        item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
        c = item->connection;

        if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr,
                         item->socklen, pc->socklen)
                == 0)
        {
            ngx_queue_remove(q);
            ngx_queue_insert_head(&kp->conf->free, q);

            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                           "get keepalive peer: using connection %p", c);

            c->idle = 0;
            c->log = pc->log;
            c->read->log = pc->log;
            c->write->log = pc->log;
            c->pool->log = pc->log;

            pc->connection = c;
            pc->cached = 1;

            return NGX_DONE;
        }
    }

    return NGX_OK;
}
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;
}
Exemple #25
0
void print_queue(ngx_queue_t *h)
{
    ngx_queue_t *t;
    for( t=ngx_queue_head(h); t != ngx_queue_sentinel(h);
    t = ngx_queue_next(t))
    {
        ngx_qTest_t *tmp = ngx_queue_data(t, ngx_qTest_t, link);
        printf("Key:%d, name:%s\n", tmp->key, tmp->name);
    }
}
static ngx_int_t
ngx_http_push_stream_channels_statistics_handler(ngx_http_request_t *r)
{
    ngx_http_push_stream_main_conf_t   *mcf = ngx_http_get_module_main_conf(r, ngx_http_push_stream_module);
    char                               *pos = NULL;

    ngx_http_push_stream_requested_channel_t       *channels_ids, *cur;

    ngx_http_push_stream_set_expires(r, NGX_HTTP_PUSH_STREAM_EXPIRES_EPOCH, 0);

    // only accept GET method
    if (!(r->method & NGX_HTTP_GET)) {
        ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ALLOW, &NGX_HTTP_PUSH_STREAM_ALLOW_GET);
        return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_NOT_ALLOWED, NULL);
    }

    ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_TAG, &NGX_HTTP_PUSH_STREAM_TAG);
    ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_COMMIT, &NGX_HTTP_PUSH_STREAM_COMMIT);

    //get channels ids
    channels_ids = ngx_http_push_stream_parse_channels_ids_from_path(r, r->pool);

    // if not specify a channel id, get info about all channels in a resumed way
    if ((channels_ids == NULL) || ngx_queue_empty(&channels_ids->queue)) {
        return ngx_http_push_stream_send_response_all_channels_info_summarized(r);
    }

    cur = channels_ids;
    while ((cur = (ngx_http_push_stream_requested_channel_t *) ngx_queue_next(&cur->queue)) != channels_ids) {
        // could not have a large size
        if ((mcf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (cur->id->len > mcf->max_channel_id_length)) {
            ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: channel id is larger than allowed %d", cur->id->len);
            return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_TOO_LARGE_CHANNEL_ID_MESSAGE);
        }

        if ((pos = ngx_strchr(cur->id->data, '*')) != NULL) {
            ngx_str_t *aux = NULL;
            if (pos != (char *) cur->id->data) {
                *pos = '\0';
                cur->id->len  = ngx_strlen(cur->id->data);
                aux = cur->id;
            }
            return ngx_http_push_stream_send_response_all_channels_info_detailed(r, aux);
        }

        // if specify a channel id equals to ALL, get info about all channels in a detailed way
        if (ngx_memn2cmp(cur->id->data, NGX_HTTP_PUSH_STREAM_ALL_CHANNELS_INFO_ID.data, cur->id->len, NGX_HTTP_PUSH_STREAM_ALL_CHANNELS_INFO_ID.len) == 0) {
            return ngx_http_push_stream_send_response_all_channels_info_detailed(r, NULL);
        }
    }

    // if specify a channels ids != ALL, get info about specified channels if they exists
    return ngx_http_push_stream_send_response_channels_info_detailed(r, channels_ids);
}
Exemple #27
0
void dump_queue_from_head(ngx_queue_t *que)
{
    ngx_queue_t *q = ngx_queue_head(que);
 
    printf("(0x%x: (0x%x, 0x%x)) <==> \n", que, que->prev, que->next);
 
    for (; q != ngx_queue_sentinel(que); q = ngx_queue_next(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 ngx_int_t
ngx_http_push_stream_send_response_channels_info_detailed(ngx_http_request_t *r, ngx_http_push_stream_requested_channel_t *requested_channels) {
    ngx_str_t                                *text;
    ngx_queue_t                               queue_channel_info;
    ngx_http_push_stream_main_conf_t         *mcf = ngx_http_get_module_main_conf(r, ngx_http_push_stream_module);
    ngx_slab_pool_t                          *shpool = mcf->shpool;
    ngx_http_push_stream_content_subtype_t   *subtype = ngx_http_push_stream_match_channel_info_format_and_content_type(r, 1);
    ngx_http_push_stream_channel_info_t      *channel_info;
    ngx_http_push_stream_channel_t           *channel = NULL;
    ngx_http_push_stream_requested_channel_t *requested_channel;
    ngx_queue_t                              *cur = &requested_channels->queue;
    ngx_uint_t                                qtd_channels = 0;

    ngx_queue_init(&queue_channel_info);

    ngx_shmtx_lock(&shpool->mutex);
    while ((cur = ngx_queue_next(cur)) != &requested_channels->queue) {
        requested_channel = ngx_queue_data(cur, ngx_http_push_stream_requested_channel_t, queue);

        // search for a existing channel with this id
        channel = ngx_http_push_stream_find_channel(requested_channel->id, r->connection->log, mcf);
        if ((channel != NULL) && ((channel_info = ngx_pcalloc(r->pool, sizeof(ngx_http_push_stream_channel_info_t))) != NULL)) {
            channel_info->id.data = channel->id.data;
            channel_info->id.len = channel->id.len;
            channel_info->published_messages = channel->last_message_id;
            channel_info->stored_messages = channel->stored_messages;
            channel_info->subscribers = channel->subscribers;

            ngx_queue_insert_tail(&queue_channel_info, &channel_info->queue);
            qtd_channels++;
        }
    }
    ngx_shmtx_unlock(&shpool->mutex);

    if (qtd_channels == 0) {
        return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_NOT_FOUND, NULL);
    }

    if (qtd_channels == 1) {
        channel_info = ngx_queue_data(ngx_queue_head(&queue_channel_info), ngx_http_push_stream_channel_info_t, queue);
        text = ngx_http_push_stream_channel_info_formatted(r->pool, subtype->format_item, &channel_info->id, channel_info->published_messages, channel_info->stored_messages, channel_info->subscribers);
        if (text == NULL) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        return ngx_http_push_stream_send_response(r, text, subtype->content_type, NGX_HTTP_OK);
    }

    return ngx_http_push_stream_send_response_channels_info(r, &queue_channel_info);
}
//temporary cheat
static ngx_int_t ngx_http_push_store_publish(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_int_t status_code, const ngx_str_t *status_line, ngx_log_t *log) {
 //subscribers are queued up in a local pool. Queue heads, however, are located
  //in shared memory, identified by pid.
  ngx_shmtx_lock(&ngx_http_push_shpool->mutex);
  ngx_http_push_pid_queue_t     *sentinel = &channel->workers_with_subscribers;
  ngx_http_push_pid_queue_t     *cur = sentinel;
  ngx_int_t                      received;
  received = channel->subscribers > 0 ? NGX_HTTP_PUSH_MESSAGE_RECEIVED : NGX_HTTP_PUSH_MESSAGE_QUEUED;

  if(msg!=NULL && received==NGX_HTTP_PUSH_MESSAGE_RECEIVED) {
    //just for now
    ngx_http_push_store_reserve_message_locked(channel, msg);
  }
  
  while((cur=(ngx_http_push_pid_queue_t *)ngx_queue_next(&cur->queue))!=sentinel) {
    pid_t           worker_pid  = cur->pid;
    ngx_int_t       worker_slot = cur->slot;
    ngx_http_push_subscriber_t *subscriber_sentinel= cur->subscriber_sentinel;
    /*
    each time all of a worker's subscribers are removed, so is the sentinel. 
    this is done to make garbage collection easier. Assuming we want to avoid
    placing the sentinel in shared memory (for now -- it's a little tricky
    to debug), the owner of the worker pool must be the one to free said sentinel.
    But channels may be deleted by different worker processes, and it seems unwieldy
    (for now) to do IPC just to delete one stinkin' sentinel. Hence a new sentinel
    is used every time the subscriber queue is emptied.
    */
    cur->subscriber_sentinel = NULL; //think about it it terms of garbage collection. it'll make sense. sort of.
    ngx_shmtx_unlock(&ngx_http_push_shpool->mutex);
    if(subscriber_sentinel != NULL) {
      if(worker_pid == ngx_pid) {
        //my subscribers
        ngx_http_push_respond_to_subscribers(channel, subscriber_sentinel, msg, status_code, status_line);
      }
      else {
        //some other worker's subscribers
        //interprocess communication breakdown
        if(ngx_http_push_send_worker_message(channel, subscriber_sentinel, worker_pid, worker_slot, msg, status_code, log) != NGX_ERROR) {
          ngx_http_push_alert_worker(worker_pid, worker_slot, log);
        }
        else {
          ngx_log_error(NGX_LOG_ERR, log, 0, "push module: error communicating with some other worker process");
        }
        
      }
    }
    ngx_shmtx_lock(&ngx_http_push_shpool->mutex);
  }
  ngx_shmtx_unlock(&ngx_http_push_shpool->mutex);
  return received;
}
ngx_int_t
ngx_http_drizzle_keepalive_get_peer_multi(ngx_peer_connection_t *pc,
    ngx_http_upstream_drizzle_peer_data_t *dp,
    ngx_http_upstream_drizzle_srv_conf_t *dscf)
{
    ngx_queue_t                             *q, *cache;
    ngx_http_drizzle_keepalive_cache_t      *item;
    ngx_connection_t                        *c;

    /* search cache for suitable connection */

    cache = &dscf->cache;

    for (q = ngx_queue_head(cache);
         q != ngx_queue_sentinel(cache);
         q = ngx_queue_next(q))
    {
        item = ngx_queue_data(q, ngx_http_drizzle_keepalive_cache_t, queue);
        c = item->connection;

        /* XXX maybe we should take dbname and user into account
         * as well? */
        if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr,
                         item->socklen, pc->socklen)
            == 0)
        {
            ngx_queue_remove(q);
            ngx_queue_insert_head(&dscf->free, q);

            c->idle = 0;
            c->log = pc->log;
            c->read->log = pc->log;
            c->write->log = pc->log;

            pc->connection = c;
            pc->cached = 1;

            /* we do not need to resume dp->name here because
             * it already takes the right value in the
             * ngx_http_upstream_drizzle_get_peer function */

            dp->drizzle_con = item->drizzle_con;
            dp->has_set_names = item->has_set_names;
            dp->used = item->used;

            return NGX_DONE;
        }
    }

    return NGX_DECLINED;
}