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;
}
示例#2
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;
}
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 ngx_int_t
ngx_http_push_stream_send_response_all_channels_info_detailed(ngx_http_request_t *r, ngx_str_t *prefix)
{
    ngx_http_push_stream_main_conf_t         *mcf = ngx_http_get_module_main_conf(r, ngx_http_push_stream_module);
    ngx_queue_t                               queue_channel_info;
    ngx_http_push_stream_shm_data_t          *data = mcf->shm_data;
    ngx_queue_t                              *q;
    ngx_http_push_stream_channel_t           *channel;

    ngx_queue_init(&queue_channel_info);

    ngx_shmtx_lock(&data->channels_queue_mutex);
    for (q = ngx_queue_head(&data->channels_queue); q != ngx_queue_sentinel(&data->channels_queue); q = ngx_queue_next(q)) {
        channel = ngx_queue_data(q, ngx_http_push_stream_channel_t, queue);

        ngx_http_push_stream_channel_info_t *channel_info;

        if(!prefix || (ngx_strncmp(channel->id.data, prefix->data, prefix->len) == 0)) {

            if ((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);
            }

        }
    }
    ngx_shmtx_unlock(&data->channels_queue_mutex);

    return ngx_http_push_stream_send_response_channels_info(r, &queue_channel_info);
}
示例#5
0
文件: core.c 项目: anguskwan/libuv
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
  assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
  assert(0 != events);

  if (w->fd == -1)
    return;

  assert(w->fd >= 0);

  /* Happens when uv__io_stop() is called on a handle that was never started. */
  if ((unsigned) w->fd >= loop->nwatchers)
    return;

  w->pevents &= ~events;

  if (w->pevents == 0) {
    ngx_queue_remove(&w->watcher_queue);
    ngx_queue_init(&w->watcher_queue);

    if (loop->watchers[w->fd] != NULL) {
      assert(loop->watchers[w->fd] == w);
      assert(loop->nfds > 0);
      loop->watchers[w->fd] = NULL;
      loop->nfds--;
      w->events = 0;
    }
  }
  else if (ngx_queue_empty(&w->watcher_queue))
    ngx_queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);
}
static ngx_http_push_stream_pid_queue_t *
ngx_http_push_stream_create_worker_subscriber_channel_sentinel_locked(ngx_slab_pool_t *shpool, ngx_str_t *channel_id, ngx_log_t *log)
{
    ngx_http_push_stream_pid_queue_t     *worker_sentinel;
    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 NULL;
    }

    if ((worker_sentinel = ngx_slab_alloc_locked(shpool, sizeof(ngx_http_push_stream_pid_queue_t))) == NULL) {
        ngx_log_error(NGX_LOG_ERR, log, 0, "push stream module: unable to allocate worker subscriber queue marker in shared memory");
        return NULL;
    }

    // initialize
    ngx_queue_insert_tail(&channel->workers_with_subscribers, &worker_sentinel->queue);

    worker_sentinel->pid = ngx_pid;
    worker_sentinel->slot = ngx_process_slot;
    ngx_queue_init(&worker_sentinel->subscribers_sentinel.queue);

    return worker_sentinel;
}
示例#7
0
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
  assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
  assert(0 != events);
  assert(w->fd >= 0);
  assert(w->fd < INT_MAX);

  w->pevents |= events;
  maybe_resize(loop, w->fd + 1);

#if !defined(__sun)
  /* The event ports backend needs to rearm all file descriptors on each and
   * every tick of the event loop but the other backends allow us to
   * short-circuit here if the event mask is unchanged.
   */
  if (w->events == w->pevents) {
    if (w->events == 0 && !ngx_queue_empty(&w->watcher_queue)) {
      ngx_queue_remove(&w->watcher_queue);
      ngx_queue_init(&w->watcher_queue);
    }
    return;
  }
#endif

  if (ngx_queue_empty(&w->watcher_queue))
    ngx_queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);

  if (loop->watchers[w->fd] == NULL) {
    loop->watchers[w->fd] = w;
    loop->nfds++;
  }
}
示例#8
0
int main()
{
    ngx_qTest_t arr[5];
    ngx_queue_t head;
    ngx_queue_init(&head);
    int i=0;
    for( ; i<5; ++i)//初始化 队列
    {
        arr[i].key = i;
        sprintf(arr[i].name, "\"My key is:%d.\"", arr[i].key);
        if(i%2)
        {
            ngx_queue_insert_head(&head, &arr[i].link);
        }
        else
        {
            ngx_queue_insert_tail(&head, &arr[i].link);
        }
    }
    printf("*******************************\n");
    printf("Before sort:\n");
    print_queue(&head);
    ngx_queue_sort(&head, cmp);
    printf("*******************************\n");
    printf("After sort:\n");
    print_queue(&head);

    ngx_queue_t * midq = ngx_queue_middle(&head);
    ngx_qTest_t *mid_data = ngx_queue_data(midq, ngx_qTest_t, link);
    printf("*******************************\n");
    // 求取中间节点
    printf("%The middle key is %d.\n", mid_data->key);
    return 0;
}
示例#9
0
文件: udp.c 项目: 76765357/node
static int uv__send(uv_udp_send_t* req,
                    uv_udp_t* handle,
                    uv_buf_t bufs[],
                    int bufcnt,
                    struct sockaddr* addr,
                    socklen_t addrlen,
                    uv_udp_send_cb send_cb) {
  assert(bufcnt > 0);

  if (uv__udp_maybe_deferred_bind(handle, addr->sa_family))
    return -1;

  uv__req_init(handle->loop, req, UV_UDP_SEND);

  assert(addrlen <= sizeof(req->addr));
  memcpy(&req->addr, addr, addrlen);
  req->send_cb = send_cb;
  req->handle = handle;
  req->bufcnt = bufcnt;

  if (bufcnt <= (int) ARRAY_SIZE(req->bufsml)) {
    req->bufs = req->bufsml;
  }
  else if ((req->bufs = malloc(bufcnt * sizeof(bufs[0]))) == NULL) {
    uv__set_sys_error(handle->loop, ENOMEM);
    return -1;
  }

  memcpy(req->bufs, bufs, bufcnt * sizeof(bufs[0]));
  ngx_queue_insert_tail(&handle->write_queue, &req->queue);
  uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
  uv__handle_start(handle);

  return 0;
}
示例#10
0
文件: udp.c 项目: nuxleus/libuv
static int uv__udp_send(uv_udp_send_t* req,
                        uv_udp_t* handle,
                        uv_buf_t bufs[],
                        int bufcnt,
                        struct sockaddr* addr,
                        socklen_t addrlen,
                        uv_udp_send_cb send_cb) {
  if (uv__udp_maybe_deferred_bind(handle, addr->sa_family))
    return -1;

  uv__req_init(handle->loop, (uv_req_t*)req);

  memcpy(&req->addr, addr, addrlen);
  req->addrlen = addrlen;
  req->send_cb = send_cb;
  req->handle = handle;
  req->bufcnt = bufcnt;
  req->type = UV_UDP_SEND;

  if (bufcnt <= UV_REQ_BUFSML_SIZE) {
    req->bufs = req->bufsml;
  }
  else if ((req->bufs = malloc(bufcnt * sizeof(bufs[0]))) == NULL) {
    uv__set_sys_error(handle->loop, ENOMEM);
    return -1;
  }
  memcpy(req->bufs, bufs, bufcnt * sizeof(bufs[0]));

  ngx_queue_insert_tail(&handle->write_queue, &req->queue);
  uv__udp_start_write_watcher(handle);

  return 0;
}
示例#11
0
文件: uv-unix.c 项目: nekedos/node
/* The buffers to be written must remain valid until the callback is called.
 * This is not required for the uv_buf_t array.
 */
int uv_write(uv_req_t* req, uv_buf_t bufs[], int bufcnt) {
    uv_handle_t* handle = req->handle;
    assert(handle->fd >= 0);

    ngx_queue_init(&req->queue);
    req->type = UV_WRITE;

    /* TODO: Don't malloc for each write... */
    req->bufs = malloc(sizeof(uv_buf_t) * bufcnt);
    memcpy(req->bufs, bufs, bufcnt * sizeof(uv_buf_t));
    req->bufcnt = bufcnt;

    req->write_index = 0;
    handle->write_queue_size += uv__buf_count(bufs, bufcnt);

    /* Append the request to write_queue. */
    ngx_queue_insert_tail(&handle->write_queue, &req->queue);

    assert(!ngx_queue_empty(&handle->write_queue));
    assert(handle->write_watcher.cb == uv__tcp_io);
    assert(handle->write_watcher.data == handle);
    assert(handle->write_watcher.fd == handle->fd);

    ev_io_start(EV_DEFAULT_ &handle->write_watcher);

    return 0;
}
static ngx_http_push_stream_pid_queue_t *
ngx_http_push_stream_get_worker_subscriber_channel_sentinel_locked(ngx_slab_pool_t *shpool, ngx_http_push_stream_channel_t *channel, ngx_log_t *log)
{
    ngx_http_push_stream_pid_queue_t     *worker_sentinel;
    ngx_queue_t                          *q;

    for (q = ngx_queue_head(&channel->workers_with_subscribers); q != ngx_queue_sentinel(&channel->workers_with_subscribers); q = ngx_queue_next(q)) {
        worker_sentinel = ngx_queue_data(q, ngx_http_push_stream_pid_queue_t, queue);
        if (worker_sentinel->pid == ngx_pid) {
            return worker_sentinel;
        }
    }

    if ((worker_sentinel = ngx_slab_alloc(shpool, sizeof(ngx_http_push_stream_pid_queue_t))) == NULL) {
        ngx_log_error(NGX_LOG_ERR, log, 0, "push stream module: unable to allocate worker subscriber queue marker in shared memory");
        return NULL;
    }

    // initialize
    ngx_queue_insert_tail(&channel->workers_with_subscribers, &worker_sentinel->queue);

    worker_sentinel->subscribers = 0;
    worker_sentinel->pid = ngx_pid;
    worker_sentinel->slot = ngx_process_slot;
    ngx_queue_init(&worker_sentinel->subscriptions);

    return worker_sentinel;
}
static void
ngx_http_push_stream_rbtree_walker_channel_info_locked(ngx_rbtree_t *tree, ngx_pool_t *pool, ngx_rbtree_node_t *node, ngx_queue_t *queue_channel_info, ngx_str_t *prefix)
{
    ngx_rbtree_node_t   *sentinel = tree->sentinel;


    if (node != sentinel) {
        ngx_http_push_stream_channel_t *channel = (ngx_http_push_stream_channel_t *) node;
        ngx_http_push_stream_channel_info_t *channel_info;

        if(!prefix || (ngx_strncmp(channel->id.data, prefix->data, prefix->len) == 0)) {

            if ((channel_info = ngx_pcalloc(pool, sizeof(ngx_http_push_stream_channel_info_t))) == NULL) {
                return;
            }

            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);
        }

        if (node->left != NULL) {
            ngx_http_push_stream_rbtree_walker_channel_info_locked(tree, pool, node->left, queue_channel_info, prefix);
        }

        if (node->right != NULL) {
            ngx_http_push_stream_rbtree_walker_channel_info_locked(tree, pool, node->right, queue_channel_info, prefix);
        }
    }
}
示例#14
0
int pc_add_listener(pc_client_t *client, const char *event,
                    pc_event_cb event_cb) {
  if(PC_ST_CLOSED == client->state) {
    LOGD( "Pomelo client has closed.\n");
    return -1;
  }

  pc_listener_t *listener = pc_listener_new();
  if(listener == NULL) {
    LOGD( "Fail to create listener.\n");
    return -1;
  }
  listener->cb = event_cb;

  uv_mutex_lock(&client->listener_mutex);
  ngx_queue_t *head = pc_map_get(client->listeners, event);

  if(head == NULL) {
    head = (ngx_queue_t *)malloc(sizeof(ngx_queue_t));
    if(head == NULL) {
      LOGD( "Fail to create listener queue.\n");
      pc_listener_destroy(listener);
      return -1;
    }

    ngx_queue_init(head);

    pc_map_set(client->listeners, event, head);
  }

  ngx_queue_insert_tail(head, &listener->queue);
  uv_mutex_unlock(&client->listener_mutex);

  return 0;
}
/* Note: must be called with the mutex locked */
static ngx_buffer_cache_entry_t*
ngx_buffer_cache_get_free_entry(ngx_buffer_cache_sh_t *cache)
{
	ngx_buffer_cache_entry_t* entry;

	if (!ngx_queue_empty(&cache->free_queue))
	{
		// return the free queue head
		return container_of(ngx_queue_head(&cache->free_queue), ngx_buffer_cache_entry_t, queue_node);
	}
	
	if ((u_char*)(cache->entries_end + 1) < cache->buffers_start)
	{
		// enlarge the entries buffer
		entry = cache->entries_end;
		cache->entries_end++;

		// initialize the state and add to free queue
		entry->state = CES_FREE;
		ngx_queue_insert_tail(&cache->free_queue, &entry->queue_node);
		return entry;
	}
	
	return ngx_buffer_cache_free_oldest_entry(cache, 0);
}
static ngx_int_t
ngx_http_push_stream_registry_subscriber_locked(ngx_http_request_t *r, ngx_http_push_stream_subscriber_t *worker_subscriber)
{
    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             *thisworker_data = data->ipc + ngx_process_slot;
    ngx_http_push_stream_loc_conf_t                *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module);
    ngx_msec_t                                      connection_ttl = worker_subscriber->longpolling ? cf->longpolling_connection_ttl : cf->subscriber_connection_ttl;
    ngx_http_push_stream_queue_elem_t              *element_subscriber;
    ngx_http_push_stream_subscriber_ctx_t          *ctx = ngx_http_get_module_ctx(r, ngx_http_push_stream_module);

    if ((element_subscriber = ngx_palloc(r->pool, sizeof(ngx_http_push_stream_queue_elem_t))) == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to allocate subscriber reference");
        return NGX_ERROR;
    }
    element_subscriber->value = worker_subscriber;
    worker_subscriber->worker_subscriber_element_ref = element_subscriber;

    // adding subscriber to worker list of subscribers
    ngx_queue_insert_tail(&thisworker_data->subscribers_queue, &element_subscriber->queue);

    ctx->longpolling = worker_subscriber->longpolling;
    ctx->subscriber = worker_subscriber;

    if ((connection_ttl != NGX_CONF_UNSET_MSEC) || (cf->ping_message_interval != NGX_CONF_UNSET_MSEC)) {

        if (connection_ttl != NGX_CONF_UNSET_MSEC) {
            if ((ctx->disconnect_timer = ngx_pcalloc(worker_subscriber->request->pool, sizeof(ngx_event_t))) == NULL) {
                return NGX_ERROR;
            }
        }

        if ((!ctx->longpolling) && (cf->ping_message_interval != NGX_CONF_UNSET_MSEC)) {
            if ((ctx->ping_timer = ngx_pcalloc(worker_subscriber->request->pool, sizeof(ngx_event_t))) == NULL) {
                return NGX_ERROR;
            }
        }

        if (ctx->disconnect_timer != NULL) {
            ctx->disconnect_timer->handler = ngx_http_push_stream_disconnect_timer_wake_handler;
            ctx->disconnect_timer->data = worker_subscriber->request;
            ctx->disconnect_timer->log = worker_subscriber->request->connection->log;
            ngx_http_push_stream_timer_reset(connection_ttl, ctx->disconnect_timer);
        }

        if (ctx->ping_timer != NULL) {
            ctx->ping_timer->handler = ngx_http_push_stream_ping_timer_wake_handler;
            ctx->ping_timer->data = worker_subscriber->request;
            ctx->ping_timer->log = worker_subscriber->request->connection->log;
            ngx_http_push_stream_timer_reset(cf->ping_message_interval, ctx->ping_timer);
        }
    }

    // increment global subscribers count
    data->subscribers++;
    thisworker_data->subscribers++;

    return NGX_OK;
}
示例#17
0
文件: udp.c 项目: 76765357/node
static void uv__udp_run_pending(uv_udp_t* handle) {
  uv_udp_send_t* req;
  ngx_queue_t* q;
  struct msghdr h;
  ssize_t size;

  while (!ngx_queue_empty(&handle->write_queue)) {
    q = ngx_queue_head(&handle->write_queue);
    assert(q != NULL);

    req = ngx_queue_data(q, uv_udp_send_t, queue);
    assert(req != NULL);

    memset(&h, 0, sizeof h);
    h.msg_name = &req->addr;
    h.msg_namelen = (req->addr.sin6_family == AF_INET6 ?
      sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
    h.msg_iov = (struct iovec*)req->bufs;
    h.msg_iovlen = req->bufcnt;

    do {
      size = sendmsg(handle->io_watcher.fd, &h, 0);
    }
    while (size == -1 && errno == EINTR);

    /* TODO try to write once or twice more in the
     * hope that the socket becomes readable again?
     */
    if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
      break;

    req->status = (size == -1 ? -errno : size);

#ifndef NDEBUG
    /* Sanity check. */
    if (size != -1) {
      ssize_t nbytes;
      int i;

      for (nbytes = i = 0; i < req->bufcnt; i++)
        nbytes += req->bufs[i].len;

      assert(size == nbytes);
    }
#endif

    /* Sending a datagram is an atomic operation: either all data
     * is written or nothing is (and EMSGSIZE is raised). That is
     * why we don't handle partial writes. Just pop the request
     * off the write queue and onto the completed queue, done.
     */
    ngx_queue_remove(&req->queue);
    ngx_queue_insert_tail(&handle->write_completed_queue, &req->queue);
  }
}
static ngx_int_t
ngx_http_push_stream_registry_subscriber(ngx_http_request_t *r, ngx_http_push_stream_subscriber_t *worker_subscriber)
{
    ngx_http_push_stream_main_conf_t               *mcf = ngx_http_get_module_main_conf(r, ngx_http_push_stream_module);
    ngx_http_push_stream_loc_conf_t                *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module);
    ngx_http_push_stream_shm_data_t                *data = mcf->shm_data;
    ngx_http_push_stream_worker_data_t             *thisworker_data = &data->ipc[ngx_process_slot];
    ngx_msec_t                                      connection_ttl = worker_subscriber->longpolling ? cf->longpolling_connection_ttl : cf->subscriber_connection_ttl;
    ngx_http_push_stream_module_ctx_t              *ctx = ngx_http_get_module_ctx(r, ngx_http_push_stream_module);
    ngx_slab_pool_t                                *shpool = mcf->shpool;

    // adding subscriber to worker list of subscribers
    ngx_queue_insert_tail(&thisworker_data->subscribers_queue, &worker_subscriber->worker_queue);

    ctx->longpolling = worker_subscriber->longpolling;
    ctx->subscriber = worker_subscriber;

    if ((connection_ttl != NGX_CONF_UNSET_MSEC) || (cf->ping_message_interval != NGX_CONF_UNSET_MSEC)) {

        if (connection_ttl != NGX_CONF_UNSET_MSEC) {
            if ((ctx->disconnect_timer = ngx_pcalloc(worker_subscriber->request->pool, sizeof(ngx_event_t))) == NULL) {
                return NGX_ERROR;
            }
        }

        if ((!ctx->longpolling) && (cf->ping_message_interval != NGX_CONF_UNSET_MSEC)) {
            if ((ctx->ping_timer = ngx_pcalloc(worker_subscriber->request->pool, sizeof(ngx_event_t))) == NULL) {
                return NGX_ERROR;
            }
        }

        if (ctx->disconnect_timer != NULL) {
            ctx->disconnect_timer->handler = ngx_http_push_stream_disconnect_timer_wake_handler;
            ctx->disconnect_timer->data = worker_subscriber->request;
            ctx->disconnect_timer->log = worker_subscriber->request->connection->log;
            ngx_http_push_stream_timer_reset(connection_ttl, ctx->disconnect_timer);
        }

        if (ctx->ping_timer != NULL) {
            ctx->ping_timer->handler = ngx_http_push_stream_ping_timer_wake_handler;
            ctx->ping_timer->data = worker_subscriber->request;
            ctx->ping_timer->log = worker_subscriber->request->connection->log;
            ngx_http_push_stream_timer_reset(cf->ping_message_interval, ctx->ping_timer);
        }
    }

    // increment global subscribers count
    ngx_shmtx_lock(&shpool->mutex);
    data->subscribers++;
    ngx_shmtx_unlock(&shpool->mutex);
    thisworker_data->subscribers++;

    return NGX_OK;
}
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_http_push_stream_pid_queue_t           *cur, *worker_subscribers_sentinel = NULL;
    ngx_http_push_stream_channel_t             *channel;
    ngx_http_push_stream_queue_elem_t          *element_subscriber;

    // 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 = &channel->workers_with_subscribers;
    while ((cur = (ngx_http_push_stream_pid_queue_t *) ngx_queue_next(&cur->queue)) != &channel->workers_with_subscribers) {
        if (cur->pid == ngx_pid) {
            worker_subscribers_sentinel = cur;
            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;
        }
    }

    if ((element_subscriber = ngx_palloc(subscription->subscriber->request->pool, sizeof(ngx_http_push_stream_queue_elem_t))) == NULL) { // unable to allocate request queue element
        ngx_log_error(NGX_LOG_ERR, log, 0, "push stream module: unable to allocate subscriber reference");
        return NGX_ERROR;
    }
    element_subscriber->value = subscription->subscriber;
    subscription->channel_subscriber_element_ref = element_subscriber;

    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->subscribers_sentinel.queue, &element_subscriber->queue);
    return NGX_OK;
}
示例#20
0
/* Note: must be called with the mutex locked */
static ngx_buffer_cache_entry_t*
ngx_buffer_cache_free_oldest_entry(ngx_buffer_cache_sh_t *cache, uint32_t expiration)
{
	ngx_buffer_cache_entry_t* entry;

	// verify we have an entry to free
	if (ngx_queue_empty(&cache->used_queue))
	{
		return NULL;
	}

	// verify the entry is not locked
	entry = container_of(ngx_queue_head(&cache->used_queue), ngx_buffer_cache_entry_t, queue_node);
	if (entry->ref_count > 0 &&
		ngx_time() < entry->access_time + ENTRY_LOCK_EXPIRATION)
	{
		return NULL;
	}

	// make sure the entry is expired, if that is the requirement
	if (expiration && ngx_time() < (time_t)(entry->write_time + expiration))
	{
		return NULL;
	}
	
	// update the state
	entry->state = CES_FREE;

	// remove from rb tree
	ngx_rbtree_delete(&cache->rbtree, &entry->node);

	// move from used_queue to free_queue
	ngx_queue_remove(&entry->queue_node);
	ngx_queue_insert_tail(&cache->free_queue, &entry->queue_node);

	if (ngx_queue_empty(&cache->used_queue))
	{
		// queue is empty reset the read/write pointers
		cache->buffers_read = cache->buffers_end;
		cache->buffers_write = cache->buffers_end;
	}
	else
	{
		// update the read buffer pointer
		cache->buffers_read = entry->start_offset;
	}

	// update stats
	cache->stats.evicted++;
	cache->stats.evicted_bytes += entry->buffer_size;

	return entry;
}
static ngx_int_t ngx_http_push_channel_collector(ngx_http_push_channel_t * channel, ngx_slab_pool_t * shpool) {
	if((ngx_http_push_clean_channel_locked(channel))!=NULL) { //we're up for deletion
		ngx_http_push_channel_queue_t *trashy;
		if((trashy = ngx_alloc(sizeof(*trashy), ngx_cycle->log))!=NULL) {
			//yeah, i'm allocating memory during garbage collection. sue me.
			trashy->channel=channel;
			ngx_queue_insert_tail(&channel_gc_sentinel.queue, &trashy->queue);
			return NGX_OK;
		}
		return NGX_ERROR;
	}
	return NGX_OK;
}
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);
}
示例#23
0
v8::Handle<v8::Value> Write(const v8::Arguments& args) {
  v8::HandleScope scope;

  // file descriptor
  if(!args[0]->IsInt32()) {
    return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("First argument must be an int"))));
  }
  int fd = args[0]->ToInt32()->Int32Value();

  // buffer
  if(!args[1]->IsObject() || !node::Buffer::HasInstance(args[1])) {
    return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("Second argument must be a buffer"))));
  }
  v8::Persistent<v8::Object> buffer = v8::Persistent<v8::Object>::New(args[1]->ToObject());
  char* bufferData = node::Buffer::Data(buffer);
  size_t bufferLength = node::Buffer::Length(buffer);

  // callback
  if(!args[2]->IsFunction()) {
    return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("Third argument must be a function"))));
  }
  v8::Local<v8::Value> callback = args[2];

  WriteBaton* baton = new WriteBaton();
  memset(baton, 0, sizeof(WriteBaton));
  baton->fd = fd;
  baton->buffer = buffer;
  baton->bufferData = bufferData;
  baton->bufferLength = bufferLength;
  // baton->offset = 0;
  baton->callback = v8::Persistent<v8::Value>::New(callback);

  QueuedWrite* queuedWrite = new QueuedWrite();
  memset(queuedWrite, 0, sizeof(QueuedWrite));
  ngx_queue_init(&queuedWrite->queue);
  queuedWrite->baton = baton;
  queuedWrite->req.data = queuedWrite;

  uv_mutex_lock(&write_queue_mutex);
  bool empty = ngx_queue_empty(&write_queue);

  ngx_queue_insert_tail(&write_queue, &queuedWrite->queue);

  if (empty) {
    uv_queue_work(uv_default_loop(), &queuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite);
  }   
  uv_mutex_unlock(&write_queue_mutex);

  return scope.Close(v8::Undefined());
}
ngx_http_push_stream_requested_channel_t *
ngx_http_push_stream_parse_channels_ids_from_path(ngx_http_request_t *r, ngx_pool_t *pool) {
    ngx_http_push_stream_main_conf_t               *mcf = ngx_http_get_module_main_conf(r, ngx_http_push_stream_module);
    ngx_http_push_stream_loc_conf_t                *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module);
    ngx_http_variable_value_t                      *vv_channels_path = ngx_http_get_indexed_variable(r, cf->index_channels_path);
    ngx_http_push_stream_requested_channel_t       *channels_ids, *cur;
    ngx_str_t                                       aux;
    int                                             captures[15];
    ngx_int_t                                       n;

    if (vv_channels_path == NULL || vv_channels_path->not_found || vv_channels_path->len == 0) {
        return NULL;
    }

    if ((channels_ids = ngx_pcalloc(pool, sizeof(ngx_http_push_stream_requested_channel_t))) == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to allocate memory for channels_ids queue");
        return NULL;
    }

    ngx_queue_init(&channels_ids->queue);

    // doing the parser of given channel path
    aux.data = vv_channels_path->data;
    do {
        aux.len = vv_channels_path->len - (aux.data - vv_channels_path->data);
        if ((n = ngx_regex_exec(mcf->backtrack_parser_regex, &aux, captures, 15)) >= 0) {
            if ((cur = ngx_pcalloc(pool, sizeof(ngx_http_push_stream_requested_channel_t))) == NULL) {
                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to allocate memory for channel_id item");
                return NULL;
            }

            if ((cur->id = ngx_http_push_stream_create_str(pool, captures[0])) == NULL) {
                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to allocate memory for channel_id string");
                return NULL;
            }
            ngx_memcpy(cur->id->data, aux.data, captures[0]);
            cur->backtrack_messages = 0;
            if (captures[7] > captures[6]) {
                cur->backtrack_messages = ngx_atoi(aux.data + captures[6], captures[7] - captures[6]);
            }

            ngx_queue_insert_tail(&channels_ids->queue, &cur->queue);

            aux.data = aux.data + captures[1];
        }
    } while ((n != NGX_REGEX_NO_MATCHED) && (aux.data < (vv_channels_path->data + vv_channels_path->len)));

    return channels_ids;
}
static ngx_int_t
ngx_http_push_stream_assing_subscription_to_channel(ngx_slab_pool_t *shpool, ngx_http_push_stream_channel_t *channel, ngx_http_push_stream_subscription_t *subscription, ngx_queue_t *subscriptions, ngx_log_t *log)
{
    ngx_http_push_stream_main_conf_t           *mcf = ngx_http_get_module_main_conf(subscription->subscriber->request, ngx_http_push_stream_module);
    ngx_http_push_stream_pid_queue_t           *worker_subscribers_sentinel;

    ngx_shmtx_lock(channel->mutex);
    if ((worker_subscribers_sentinel = ngx_http_push_stream_get_worker_subscriber_channel_sentinel_locked(shpool, channel, log)) == NULL) {
        ngx_shmtx_unlock(channel->mutex);
        return NGX_ERROR;
    }

    channel->subscribers++; // do this only when we know everything went okay
    worker_subscribers_sentinel->subscribers++;
    channel->expires = ngx_time() + mcf->channel_inactivity_time;
    ngx_queue_insert_tail(subscriptions, &subscription->queue);
    ngx_queue_insert_tail(&worker_subscribers_sentinel->subscriptions, &subscription->channel_worker_queue);
    subscription->channel_worker_sentinel = worker_subscribers_sentinel;
    ngx_shmtx_unlock(channel->mutex);

    ngx_http_push_stream_send_event(mcf, log, channel, &NGX_HTTP_PUSH_STREAM_EVENT_TYPE_CLIENT_SUBSCRIBED, NULL);

    return NGX_OK;
}
示例#26
0
文件: stream.c 项目: Allan-Ngigi/node
static void uv__write_req_finish(uv_write_t* req) {
  uv_stream_t* stream = req->handle;

  /* Pop the req off tcp->write_queue. */
  ngx_queue_remove(&req->queue);
  if (req->bufs != req->bufsml) {
    free(req->bufs);
  }
  req->bufs = NULL;

  /* Add it to the write_completed_queue where it will have its
   * callback called in the near future.
   */
  ngx_queue_insert_tail(&stream->write_completed_queue, &req->queue);
  uv__io_feed(stream->loop, &stream->io_watcher);
}
示例#27
0
static ngx_inline void
ngx_http_v2_handle_stream(ngx_http_v2_connection_t *h2c,
    ngx_http_v2_stream_t *stream)
{
    ngx_event_t  *wev;

    if (stream->handled || stream->blocked || stream->exhausted) {
        return;
    }

    wev = stream->request->connection->write;

    if (!wev->delayed) {
        stream->handled = 1;
        ngx_queue_insert_tail(&h2c->posted, &stream->queue);
    }
}
示例#28
0
文件: core.c 项目: anguskwan/libuv
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
  assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
  assert(0 != events);
  assert(w->fd >= 0);
  assert(w->fd < INT_MAX);

  w->pevents |= events;
  maybe_resize(loop, w->fd + 1);

  if (ngx_queue_empty(&w->watcher_queue))
    ngx_queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);

  if (loop->watchers[w->fd] == NULL) {
    loop->watchers[w->fd] = w;
    loop->nfds++;
  }
}
示例#29
0
文件: ngx_http.c 项目: mlzboy/resys
ngx_int_t
ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
    ngx_http_core_loc_conf_t *clcf)
{
    ngx_http_location_queue_t  *lq;

    if (*locations == NULL) {
        *locations = ngx_palloc(cf->temp_pool,
                                sizeof(ngx_http_location_queue_t));
        if (*locations == NULL) {
            return NGX_ERROR;
        }

        ngx_queue_init(*locations);
    }

    lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
    if (lq == NULL) {
        return NGX_ERROR;
    }

    if (clcf->exact_match
#if (NGX_PCRE)
        || clcf->regex
#endif
        || clcf->named || clcf->noname)
    {
        lq->exact = clcf;
        lq->inclusive = NULL;

    } else {
        lq->exact = NULL;
        lq->inclusive = clcf;
    }

    lq->name = &clcf->name;
    lq->file_name = cf->conf_file->file.name.data;
    lq->line = cf->conf_file->line;

    ngx_queue_init(&lq->list);

    ngx_queue_insert_tail(*locations, &lq->queue);

    return NGX_OK;
}
示例#30
0
ngx_socket_t ngx_tcp_reuse_get_active_conn(ngx_log_t *log)
{
	ngx_socket_t fd = -1;
	ngx_err_t    err;
	u_char test[2];
	while (!ngx_queue_empty(&active_conns)) {
		ngx_queue_t *head_conn = ngx_queue_head(&active_conns);
		ngx_tcp_reuse_conn_t *active_conn = ngx_queue_data(head_conn, ngx_tcp_reuse_conn_t, q_elt);
		fd = active_conn->fd;
		if (active_conn->read.timer_set) {
			ngx_del_timer(&active_conn->read);
		}
		if (active_conn->write.timer_set) {
			ngx_del_timer(&active_conn->write);
		}
		if (active_conn->read.active) {
			ngx_del_event(&active_conn->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
		}
		if (active_conn->write.active) {
			ngx_del_event(&active_conn->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
		}
		ngx_queue_remove(&active_conn->q_elt);
		ngx_memzero(active_conn, sizeof(ngx_tcp_reuse_conn_t));
		ngx_queue_insert_tail(&empty_conns, &active_conn->q_elt);

		if (recv(fd, test, 0, 0) == 0) {
			ngx_log_debug(NGX_LOG_DEBUG_HTTP, log, 0, "0 : errno:%d, %s", ngx_socket_errno, strerror(errno));
			close(fd);
			fd = -1;
		} else {
			ngx_log_debug(NGX_LOG_DEBUG_HTTP, log, 0, "!0 : errno:%d, %s", ngx_socket_errno, strerror(errno));
			err = ngx_socket_errno;
			if (err == 11)
				break;
			else {
				close(fd);
				fd = -1;
			}
		}
		ngx_log_debug(NGX_LOG_DEBUG_HTTP, log, 0, "fd:%d", fd);

	}
	return fd;
}