static ngx_int_t remove_spool(subscriber_pool_t *spool) { channel_spooler_t *spl = spool->spooler; ngx_rbtree_node_t *node = rbtree_node_from_data(spool); DBG("remove spool node %p", node); assert(spool->spooler->running); nchan_free_msg_id(&spool->id); rbtree_remove_node(&spl->spoolseed, rbtree_node_from_data(spool)); //assert((node = rbtree_find_node(&spl->spoolseed, &spool->id)) == NULL); //double-check that it's gone return NGX_OK; }
static ngx_int_t spool_nextmsg(subscriber_pool_t *spool, nchan_msg_id_t *new_last_id) { subscriber_pool_t *newspool; channel_spooler_t *spl = spool->spooler; DBG("spool nextmsg %p (%i:%i) newid %i:%i", spool, spool->id.time, spool->id.tag, new_last_id->time, new_last_id->tag); assert(spool->id.time != new_last_id->time || spool->id.tag != new_last_id->tag); if((newspool = find_spool(spl, new_last_id)) != NULL) { assert(spool != newspool); spool_transfer_subscribers(spool, newspool, 0); destroy_spool(spool); } else { ngx_rbtree_node_t *node; node = rbtree_node_from_data(spool); rbtree_remove_node(&spl->spoolseed, node); spool->id = *new_last_id; rbtree_insert_node(&spl->spoolseed, node); spool->msg_status = MSG_INVALID; spool->msg = NULL; newspool = spool; /* newspool = get_spool(spl, new_last_id); assert(spool != newspool); spool_transfer_subscribers(spool, newspool, 0); destroy_spool(spool); */ } if(newspool->sub_count > 0 && newspool->msg_status == MSG_INVALID) { spool_fetch_msg(newspool); } return NGX_OK; }
static ngx_int_t destroy_spool(subscriber_pool_t *spool) { rbtree_seed_t *seed = &spool->spooler->spoolseed; spooled_subscriber_t *ssub; subscriber_t *sub; ngx_rbtree_node_t *node = rbtree_node_from_data(spool); remove_spool(spool); DBG("destroy spool node %p", node); for(ssub = spool->first; ssub!=NULL; ssub=ssub->next) { sub = ssub->sub; //DBG("dequeue sub %p in spool %p", sub, spool); sub->fn->dequeue(sub); } assert(spool->sub_count == 0); assert(spool->first == NULL); ngx_memset(spool, 0x42, sizeof(*spool)); //debug rbtree_destroy_node(seed, node); return NGX_OK; }
static ngx_int_t spool_nextmsg(subscriber_pool_t *spool, nchan_msg_id_t *new_last_id) { subscriber_pool_t *newspool; channel_spooler_t *spl = spool->spooler; ngx_int_t immortal_spool = spool->id.time == NCHAN_NEWEST_MSGID_TIME; int16_t largetags[NCHAN_MULTITAG_MAX]; nchan_msg_id_t new_id = NCHAN_ZERO_MSGID; nchan_copy_msg_id(&new_id, &spool->id, largetags); nchan_update_multi_msgid(&new_id, new_last_id, largetags); //ERR("spool %p nextmsg (%V) --", spool, msgid_to_str(&spool->id)); //ERR(" -- update with (%V) --", msgid_to_str(new_last_id)); //ERR(" -- newid %V", msgid_to_str(&new_id)); if(msg_ids_equal(&spool->id, &new_id)) { ERR("nextmsg id same as curmsg (%V)", msgid_to_str(&spool->id)); assert(0); } else { newspool = !immortal_spool ? find_spool(spl, &new_id) : get_spool(spl, &new_id); if(newspool != NULL) { assert(spool != newspool); spool_transfer_subscribers(spool, newspool, 0); if(!immortal_spool) destroy_spool(spool); } else { ngx_rbtree_node_t *node; assert(!immortal_spool); node = rbtree_node_from_data(spool); rbtree_remove_node(&spl->spoolseed, node); nchan_copy_msg_id(&spool->id, &new_id, NULL); rbtree_insert_node(&spl->spoolseed, node); spool->msg_status = MSG_INVALID; spool->msg = NULL; newspool = spool; /* newspool = get_spool(spl, &new_id); assert(spool != newspool); spool_transfer_subscribers(spool, newspool, 0); destroy_spool(spool); */ } if(newspool->non_internal_sub_count > 0 && spl->handlers->bulk_post_subscribe != NULL) { spl->handlers->bulk_post_subscribe(spl, newspool->non_internal_sub_count, spl->handlers_privdata); } if(newspool->sub_count > 0) { switch(newspool->msg_status) { case MSG_CHANNEL_NOTREADY: newspool->msg_status = MSG_INVALID; case MSG_INVALID: spool_fetch_msg(newspool); break; case MSG_EXPECTED: spool_respond_general(newspool, NULL, NGX_HTTP_NO_CONTENT, NULL, 0); break; default: break; } } } return NGX_OK; }