nchan_msg_t *nchan_msg_derive_stack(nchan_msg_t *parent, nchan_msg_t *child, int16_t *largetags) { nchan_msg_t *msg = msg_derive_init(parent, child, NCHAN_MSG_STACK); if(!msg || nchan_copy_msg_id(&msg->id, &parent->id, largetags) != NGX_OK) { return NULL; } return msg; }
void nchan_update_multi_msgid(nchan_msg_id_t *oldid, nchan_msg_id_t *newid) { if(newid->tagcount == 1) { //nice and simple *oldid = *newid; } else { //DBG("======= updating multi_msgid ======"); //DBG("======= old: %V", msgid_to_str(oldid)); //DBG("======= new: %V", msgid_to_str(newid)); if(newid->tagcount > NCHAN_MULTITAG_MAX && oldid->tagcount < newid->tagcount) { int16_t *oldtags, *old_largetags = NULL; int i; size_t sz = sizeof(*oldid->tag.allocd) * newid->tagcount; if(oldid->tagcount > NCHAN_MULTITAG_MAX) { old_largetags = oldid->tag.allocd; oldtags = old_largetags; } else { oldtags = oldid->tag.fixed; } oldid->tag.allocd = ngx_alloc(sz, ngx_cycle->log); for(i=0; i < newid->tagcount; i++) { oldid->tag.allocd[i] = (i < oldid->tagcount) ? oldtags[i] : -1; } if(old_largetags) { ngx_free(old_largetags); } } if(oldid->time != newid->time) { nchan_copy_msg_id(oldid, newid, NULL); } else { int i, max = newid->tagcount; int16_t *oldtags = oldid->tagcount <= NCHAN_MULTITAG_MAX ? oldid->tag.fixed : oldid->tag.allocd; int16_t *newtags = newid->tagcount <= NCHAN_MULTITAG_MAX ? newid->tag.fixed : newid->tag.allocd; assert(max == oldid->tagcount); for(i=0; i< max; i++) { //DEBUG CHECK -- REMOVE BEFORE RELEASE if(newid->tagactive == i && newtags[i] != -1 && oldtags[i] != -1) { assert(newtags[i] > oldtags[i]); } if (newtags[i] != -1) { oldtags[i] = newtags[i]; } } oldid->tagactive = newid->tagactive; } //DBG("=== updated: %V", msgid_to_str(oldid)); } }
static ngx_int_t spooler_respond_message(channel_spooler_t *self, nchan_msg_t *msg) { spooler_respond_data_t srdata; subscriber_pool_t *spool; ngx_int_t responded_subs = 0; srdata.min = msg->prev_id; srdata.max = msg->id; srdata.multi = msg->id.tagcount; srdata.overflow = NULL; srdata.msg = msg; srdata.n = 0; //find all spools between msg->prev_id and msg->id rbtree_conditional_walk(&self->spoolseed, (rbtree_walk_conditional_callback_pt )collect_spool_range_callback, &srdata); if(srdata.n == 0) { DBG("no spools in range %V -- ", msgid_to_str(&msg->prev_id)); DBG(" -- %V", msgid_to_str(&msg->id)); } while((spool = spoolcollector_unwind_nextspool(&srdata)) != NULL) { responded_subs += spool->sub_count; if(msg->id.tagcount > NCHAN_FIXED_MULTITAG_MAX) { assert(spool->id.tag.allocd != msg->id.tag.allocd); } spool_respond_general(spool, msg, 0, NULL, 0); if(msg->id.tagcount > NCHAN_FIXED_MULTITAG_MAX) { assert(spool->id.tag.allocd != msg->id.tag.allocd); } spool_nextmsg(spool, &msg->id); } spool = get_spool(self, &latest_msg_id); if(spool->sub_count > 0) { #if NCHAN_BENCHMARK responded_subs += spool->sub_count; #endif spool_respond_general(spool, msg, 0, NULL, 0); spool_nextmsg(spool, &msg->id); } nchan_copy_msg_id(&self->prev_msg_id, &msg->id, NULL); #if NCHAN_BENCHMARK self->last_responded_subscriber_count = responded_subs; #endif 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; }