static subscriber_pool_t *get_spool(channel_spooler_t *spl, nchan_msg_id_t *id) { rbtree_seed_t *seed = &spl->spoolseed; ngx_rbtree_node_t *node; subscriber_pool_t *spool; if((node = rbtree_find_node(seed, id)) == NULL) { if((node = rbtree_create_node(seed, sizeof(*spool))) == NULL) { ERR("can't create rbtree node for spool"); return NULL; } // DBG("CREATED spool node %p for msgid %i:%i", node, id->time, id->tag); spool = (subscriber_pool_t *)rbtree_data_from_node(node); ngx_memzero(spool, sizeof(*spool)); spool->spooler = spl; spool->id = *id; spool->spooler = spl; spool->msg_status = MSG_INVALID; spool->msg = NULL; if(rbtree_insert_node(seed, node) != NGX_OK) { ERR("couldn't insert spool node"); rbtree_destroy_node(seed, node); return NULL; } } else { spool = (subscriber_pool_t *)rbtree_data_from_node(node); //DBG("found spool node %p with msgid %i:%i", node, id->time, id->tag); assert(spool->id.time == id->time); } return spool; }
static void rbtree_insert_generic(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { ngx_int_t offset = offsetof(rbtree_seed_t, sentinel); rbtree_seed_t *seed = (rbtree_seed_t *)((char *)sentinel - offset); ngx_int_t rc; void *id = seed->id(rbtree_data_from_node(node)); ngx_rbtree_node_t **p; for ( ;; ) { if (node->key != temp->key) { p = (node->key < temp->key) ? &temp->left : &temp->right; } else { rc = seed->compare(id, seed->id(rbtree_data_from_node(temp))); p = (rc < 0) ? &temp->left : &temp->right; } if (*p == sentinel) { break; } temp = *p; } *p = node; node->parent = temp; node->left = sentinel; node->right = sentinel; ngx_rbt_red(node); }
static ngx_rbtree_node_t * rbtree_find_node_generic(rbtree_seed_t *seed, void *id, uint32_t hash, ngx_rbtree_node_t **last_parent, ngx_int_t *last_compare) { ngx_rbtree_node_t *root = seed->tree.root; ngx_rbtree_node_t *node = root; ngx_rbtree_node_t *sentinel = seed->tree.sentinel; ngx_int_t rc; while (node != sentinel) { if (hash < node->key) { node = node->left; continue; } if (hash > node->key) { node = node->right; continue; } /* hash == node->key */ rc = seed->compare(id, seed->id(rbtree_data_from_node(node))); if (rc == 0) { return node; } node = (rc < 0) ? node->left : node->right; } /* not found */ return NULL; }
static ngx_inline void rbtree_conditional_walk_real(rbtree_seed_t *seed, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, rbtree_walk_conditional_callback_pt callback, void *data) { rbtree_walk_direction_t direction; if(node == sentinel || node == NULL) { return; } direction = callback(seed, rbtree_data_from_node(node), data); switch(direction) { case RBTREE_WALK_LEFT: rbtree_conditional_walk_real(seed, node->left, sentinel, callback, data); break; case RBTREE_WALK_RIGHT: rbtree_conditional_walk_real(seed, node->right, sentinel, callback, data); break; case RBTREE_WALK_LEFT_RIGHT: rbtree_conditional_walk_real(seed, node->left, sentinel, callback, data); rbtree_conditional_walk_real(seed, node->right, sentinel, callback, data); break; case RBTREE_WALK_STOP: //no more break; } }
ngx_int_t rbtree_insert_node(rbtree_seed_t *seed, ngx_rbtree_node_t *node) { void *id = seed->id(rbtree_data_from_node(node)); node->key = seed->hash(id); ngx_rbtree_insert(&seed->tree, node); seed->active_nodes++; #if NCHAN_RBTREE_DBG //assert(rbtree_find_node(seed, seed->id(rbtree_data_from_node(node))) == node); //super-heavy debugging /* ngx_int_t i, max, inserted = 0; ngx_rbtree_node_t *cur; max = sizeof(seed->actives)/sizeof(cur); assert(seed->active_nodes < max); for(i=0; i<max; i++){ if(seed->actives[i] == NULL) { seed->actives[i]=node; inserted = 1; break; } } assert(inserted); */ #endif DBG("inserted node %p", node); return NGX_OK; }
ngx_int_t stop_spooler(channel_spooler_t *spl, uint8_t dequeue_subscribers) { ngx_rbtree_node_t *cur, *sentinel; spooler_event_ll_t *ecur, *ecur_next; subscriber_pool_t *spool; rbtree_seed_t *seed = &spl->spoolseed; ngx_rbtree_t *tree = &seed->tree; ngx_int_t n=0; sentinel = tree->sentinel; fetchmsg_data_t *dcur; #if NCHAN_RBTREE_DBG ngx_int_t active_before = seed->active_nodes, allocd_before = seed->active_nodes; #endif if(spl->running) { for(ecur = spl->spooler_dependent_events; ecur != NULL; ecur = ecur_next) { ecur_next = ecur->next; if(ecur->cancel) { ecur->cancel(ecur->ev.data); } ngx_event_del_timer(&ecur->ev); ngx_free(ecur); } for(cur = tree->root; cur != NULL && cur != sentinel; cur = tree->root) { spool = (subscriber_pool_t *)rbtree_data_from_node(cur); if(dequeue_subscribers) { destroy_spool(spool); } else { remove_spool(spool); rbtree_destroy_node(seed, cur); } n++; } for(dcur = spl->fetchmsg_cb_data_list; dcur != NULL; dcur = dcur->next) { dcur->spooler = NULL; } DBG("stopped %i spools in SPOOLER %p", n, *spl); } else { DBG("SPOOLER %p not running", *spl); } #if NCHAN_RBTREE_DBG assert(active_before - n == 0); assert(allocd_before - n == 0); assert(seed->active_nodes == 0); assert(seed->allocd_nodes == 0); #endif nchan_free_msg_id(&spl->prev_msg_id); spl->running = 0; return NGX_OK; }
static ngx_inline void rbtree_walk_ordered_decr_real(rbtree_seed_t *seed, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, rbtree_walk_callback_pt callback, void *data) { ngx_rbtree_node_t *left, *right; if(node == sentinel || node == NULL) { return; } left = node->left; right = node->right; rbtree_walk_real(seed, right, sentinel, callback, data); callback(seed, rbtree_data_from_node(node), data); rbtree_walk_real(seed, left, sentinel, callback, data); }
static subscriber_pool_t *find_spool(channel_spooler_t *spl, nchan_msg_id_t *id) { rbtree_seed_t *seed = &spl->spoolseed; ngx_rbtree_node_t *node; if((node = rbtree_find_node(seed, id)) != NULL) { return (subscriber_pool_t *)rbtree_data_from_node(node); } else { return NULL; } }
unsigned rbtree_empty(rbtree_seed_t *seed, rbtree_walk_callback_pt callback, void *data) { ngx_rbtree_t *tree = &seed->tree; ngx_rbtree_node_t *cur, *sentinel = tree->sentinel; unsigned int n = 0; for(cur = tree->root; cur != NULL && cur != sentinel; cur = tree->root) { if(callback) { callback(seed, rbtree_data_from_node(cur), data); } rbtree_remove_node(seed, cur); rbtree_destroy_node(seed, cur); n++; } return n; }
static subscriber_pool_t *get_spool(channel_spooler_t *spl, nchan_msg_id_t *id) { rbtree_seed_t *seed = &spl->spoolseed; ngx_rbtree_node_t *node; subscriber_pool_t *spool; if(id->time == NCHAN_NEWEST_MSGID_TIME) { spool = &spl->current_msg_spool; spool->msg_status = MSG_EXPECTED; return &spl->current_msg_spool; } if((node = rbtree_find_node(seed, id)) == NULL) { if((node = rbtree_create_node(seed, sizeof(*spool))) == NULL) { ERR("can't create rbtree node for spool"); return NULL; } // DBG("CREATED spool node %p for msgid %V", node, msgid_to_str(id)); spool = (subscriber_pool_t *)rbtree_data_from_node(node); init_spool(spl, spool, id); if(rbtree_insert_node(seed, node) != NGX_OK) { ERR("couldn't insert spool node"); rbtree_destroy_node(seed, node); return NULL; } } else { spool = (subscriber_pool_t *)rbtree_data_from_node(node); DBG("found spool node %p with msgid %V", node, msgid_to_str(id)); assert(spool->id.time == id->time); } return spool; }
ngx_int_t stop_spooler(channel_spooler_t *spl, uint8_t dequeue_subscribers) { ngx_rbtree_node_t *cur, *sentinel; subscriber_pool_t *spool; rbtree_seed_t *seed = &spl->spoolseed; ngx_rbtree_t *tree = &seed->tree; ngx_int_t n=0; sentinel = tree->sentinel; #if NCHAN_RBTREE_DBG ngx_int_t active_before = seed->active_nodes, allocd_before = seed->active_nodes; #endif if(spl->running) { for(cur = tree->root; cur != NULL && cur != sentinel; cur = tree->root) { spool = (subscriber_pool_t *)rbtree_data_from_node(cur); if(dequeue_subscribers) { destroy_spool(spool); } else { remove_spool(spool); rbtree_destroy_node(seed, cur); } n++; } DBG("stopped %i spools in SPOOLER %p", n, *spl); } else { DBG("SPOOLER %p not running", *spl); } #if NCHAN_RBTREE_DBG assert(active_before - n == 0); assert(allocd_before - n == 0); assert(seed->active_nodes == 0); assert(seed->allocd_nodes == 0); #endif spl->running = 0; return NGX_OK; }