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; }
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); }
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; }
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++; } }
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; }
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; }
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; }
/* 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); } } }
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; }
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; }
/* 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); }
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; }
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); }
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); } }
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++; } }
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; }
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; }