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 spooler_add_subscriber(channel_spooler_t *self, subscriber_t *sub) { nchan_msg_id_t *msgid = &sub->last_msg_id; subscriber_pool_t *spool; if(self->want_to_stop) { ERR("Not accepting new subscribers right now. want to stop."); return NGX_ERROR; } spool = get_spool(self, msgid); assert(spool->id.time == msgid->time); if(spool == NULL) { return NGX_ERROR; } if(spool_add_subscriber(spool, sub, 1) != NGX_OK) { ERR("couldn't add subscriber to spool %p", spool); return NGX_ERROR; } if(self->add_handler != NULL) { self->add_handler(self, sub, self->add_handler_privdata); } else { ERR("SPOOLER %p has no add_handler, couldn't add subscriber %p", self, sub); } switch(spool->msg_status) { case MSG_FOUND: assert(spool->msg); spool_respond_general(spool, spool->msg, 0, NULL); break; case MSG_INVALID: assert(spool->msg == NULL); spool_fetch_msg(spool); break; case MSG_CHANNEL_NOTREADY: case MSG_PENDING: case MSG_EXPECTED: //nothing to do but wait break; case MSG_EXPIRED: case MSG_NOTFOUND: //shouldn't happen assert(0); } return NGX_OK; }
static void spool_fetch_msg_noresponse_retry_callback(void *pd) { nomsg_retry_data_t *d = pd; subscriber_pool_t *spool = get_spool(d->spooler, &d->msg_id); if(spool && spool->msg_status == MSG_INVALID) { spool_fetch_msg(spool); } else if(!spool) { DBG("spool not found for spool_fetch_msg_noresponse_retry_callback"); } spool_fetch_msg_noresponse_retry_cancel(pd); }
static ngx_int_t its_time_for_a_spooling(rbtree_seed_t *seed, subscriber_pool_t *spool, void *data) { ngx_int_t rc; if(spool->msg_status == MSG_CHANNEL_NOTREADY) { spool->msg_status = MSG_INVALID; rc = spool_fetch_msg(spool); } else { rc = NGX_OK; } assert(rc == NGX_OK); return rc; }
static ngx_int_t spooler_add_subscriber(channel_spooler_t *self, subscriber_t *sub) { nchan_msg_id_t *msgid = &sub->last_msgid; subscriber_pool_t *spool; subscriber_type_t subtype; if(self->want_to_stop) { ERR("Not accepting new subscribers right now. want to stop."); return NGX_ERROR; } //validate_spooler(self, "before add_subscriber"); spool = get_spool(self, msgid); assert(spool->id.time == msgid->time); if(spool == NULL) { return NGX_ERROR; } subtype = sub->type; if(spool_add_subscriber(spool, sub, 1) != NGX_OK) { ERR("couldn't add subscriber to spool %p", spool); return NGX_ERROR; } self->handlers->add(self, sub, self->handlers_privdata); switch(spool->msg_status) { case MSG_FOUND: assert(spool->msg); spool_respond_general(spool, spool->msg, 0, NULL, 0); break; case MSG_INVALID: assert(spool->msg == NULL); spool_fetch_msg(spool); break; case MSG_CHANNEL_NOTREADY: case MSG_PENDING: //nothing to do break; case MSG_EXPECTED: //notify subscriber sub->fn->respond_status(sub, NGX_HTTP_NO_CONTENT, NULL); break; case MSG_EXPIRED: case MSG_NOTFOUND: case MSG_NORESPONSE: //shouldn't happen assert(0); } if(self->handlers->bulk_post_subscribe != NULL && subtype != INTERNAL) { self->handlers->bulk_post_subscribe(self, 1, self->handlers_privdata); } //validate_spooler(self, "after add_subscriber"); 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; }