Beispiel #1
0
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));
  }
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}