示例#1
0
文件: spool.c 项目: tidatida/nchan
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;
}
示例#2
0
文件: spool.c 项目: tidatida/nchan
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;
}
示例#3
0
文件: spool.c 项目: valydvweb/nchan
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);
}
示例#4
0
文件: spool.c 项目: valydvweb/nchan
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;
}
示例#5
0
文件: spool.c 项目: valydvweb/nchan
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;
}
示例#6
0
文件: spool.c 项目: valydvweb/nchan
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;
}