Beispiel #1
0
static subscriber_pool_t *get_spool(channel_spooler_t *spl, nchan_msg_id_t *id) {
  rbtree_seed_t      *seed = &spl->spoolseed;
  ngx_rbtree_node_t  *node;
  subscriber_pool_t *spool;
  
  if((node = rbtree_find_node(seed, id)) == NULL) {
    
    if((node = rbtree_create_node(seed, sizeof(*spool))) == NULL) {
      ERR("can't create rbtree node for spool");
      return NULL;
    }
    
   // DBG("CREATED spool node %p for msgid %i:%i", node, id->time, id->tag);
    spool = (subscriber_pool_t *)rbtree_data_from_node(node);
    
    ngx_memzero(spool, sizeof(*spool));
    spool->spooler = spl;
    spool->id = *id;
    spool->spooler = spl;
    spool->msg_status = MSG_INVALID;
    spool->msg = NULL;
    
    if(rbtree_insert_node(seed, node) != NGX_OK) {
      ERR("couldn't insert spool node");
      rbtree_destroy_node(seed, node);
      return NULL;
    }
  }
  else {
    spool = (subscriber_pool_t *)rbtree_data_from_node(node);
    //DBG("found spool node %p with msgid %i:%i", node, id->time, id->tag);
    assert(spool->id.time == id->time);
  }
  return spool;
}
Beispiel #2
0
static void rbtree_insert_generic(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) {
  ngx_int_t         offset = offsetof(rbtree_seed_t, sentinel);
  rbtree_seed_t    *seed = (rbtree_seed_t *)((char *)sentinel - offset);
  ngx_int_t         rc;
  void             *id = seed->id(rbtree_data_from_node(node));
  
  ngx_rbtree_node_t  **p;
 
  for ( ;; ) {
    
    if (node->key != temp->key) {
      p = (node->key < temp->key) ? &temp->left : &temp->right;
    }
    else {
      rc = seed->compare(id, seed->id(rbtree_data_from_node(temp)));
      p = (rc < 0) ? &temp->left : &temp->right;
    }
    
    if (*p == sentinel) {
      break;
    }
    
    temp = *p;
  }

  *p = node;
  node->parent = temp;
  node->left = sentinel;
  node->right = sentinel;
  ngx_rbt_red(node);
}
Beispiel #3
0
static ngx_rbtree_node_t * rbtree_find_node_generic(rbtree_seed_t *seed, void *id, uint32_t hash, ngx_rbtree_node_t **last_parent, ngx_int_t *last_compare) {
  ngx_rbtree_node_t              *root = seed->tree.root;
  ngx_rbtree_node_t              *node = root;
  ngx_rbtree_node_t              *sentinel = seed->tree.sentinel;
  ngx_int_t                       rc;

  while (node != sentinel) {
    if (hash < node->key) {
      node = node->left;
      continue;
    }
    if (hash > node->key) {
      node = node->right;
      continue;
    }

    /* hash == node->key */
    rc = seed->compare(id, seed->id(rbtree_data_from_node(node)));
    if (rc == 0) {
      return node;
    }
    node = (rc < 0) ? node->left : node->right;
  }
  /* not found */

  return NULL;
}
Beispiel #4
0
static ngx_inline void rbtree_conditional_walk_real(rbtree_seed_t *seed, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, rbtree_walk_conditional_callback_pt callback, void *data) {
  rbtree_walk_direction_t    direction;
  
  if(node == sentinel || node == NULL) {
    return;
  }
  
  direction = callback(seed, rbtree_data_from_node(node), data);
  switch(direction) {
    case RBTREE_WALK_LEFT:
      rbtree_conditional_walk_real(seed, node->left, sentinel, callback, data);
      break;
    
    case RBTREE_WALK_RIGHT:
      rbtree_conditional_walk_real(seed, node->right, sentinel, callback, data);
      break;
    
    case RBTREE_WALK_LEFT_RIGHT:
      rbtree_conditional_walk_real(seed, node->left, sentinel, callback, data);
      rbtree_conditional_walk_real(seed, node->right, sentinel, callback, data);
      break;
    
    case RBTREE_WALK_STOP:
      //no more
      break;
  }
}
Beispiel #5
0
ngx_int_t rbtree_insert_node(rbtree_seed_t *seed, ngx_rbtree_node_t *node) {
  void  *id = seed->id(rbtree_data_from_node(node));
  node->key = seed->hash(id);
  ngx_rbtree_insert(&seed->tree, node);
  seed->active_nodes++;
  
#if NCHAN_RBTREE_DBG
  
  //assert(rbtree_find_node(seed, seed->id(rbtree_data_from_node(node))) == node);
  
  //super-heavy debugging
  /*
  ngx_int_t    i, max, inserted = 0;
  ngx_rbtree_node_t *cur;
  max = sizeof(seed->actives)/sizeof(cur);
  
  assert(seed->active_nodes < max);
  
  for(i=0; i<max; i++){
    if(seed->actives[i] == NULL) {
      seed->actives[i]=node;
      inserted = 1;
      break;
    }
  }
  assert(inserted);
  */
  
#endif
  DBG("inserted node %p", node);
  return NGX_OK;
}
Beispiel #6
0
ngx_int_t stop_spooler(channel_spooler_t *spl, uint8_t dequeue_subscribers) {
  ngx_rbtree_node_t    *cur, *sentinel;
  spooler_event_ll_t   *ecur, *ecur_next;
  subscriber_pool_t    *spool;
  rbtree_seed_t        *seed = &spl->spoolseed;
  ngx_rbtree_t         *tree = &seed->tree;
  ngx_int_t             n=0;
  sentinel = tree->sentinel;
  
  fetchmsg_data_t      *dcur;
#if NCHAN_RBTREE_DBG
  ngx_int_t active_before = seed->active_nodes, allocd_before = seed->active_nodes;
#endif
  if(spl->running) {
    
    for(ecur = spl->spooler_dependent_events; ecur != NULL; ecur = ecur_next) {
      ecur_next = ecur->next;
      if(ecur->cancel) {
        ecur->cancel(ecur->ev.data);
      }
      ngx_event_del_timer(&ecur->ev);
      
      ngx_free(ecur);
    }
    
    for(cur = tree->root; cur != NULL && cur != sentinel; cur = tree->root) {
      spool = (subscriber_pool_t *)rbtree_data_from_node(cur);
      if(dequeue_subscribers) {
        destroy_spool(spool);
      }
      else {
        remove_spool(spool);
        rbtree_destroy_node(seed, cur);
      }
      n++;
    }
    
    for(dcur = spl->fetchmsg_cb_data_list; dcur != NULL; dcur = dcur->next) {
      dcur->spooler = NULL;
    }
    
    DBG("stopped %i spools in SPOOLER %p", n, *spl);
  }
  else {
    DBG("SPOOLER %p not running", *spl);
  }
#if NCHAN_RBTREE_DBG
  assert(active_before - n == 0);
  assert(allocd_before - n == 0);
  assert(seed->active_nodes == 0);
  assert(seed->allocd_nodes == 0);
#endif
  nchan_free_msg_id(&spl->prev_msg_id);
  spl->running = 0;
  return NGX_OK;
}
Beispiel #7
0
static ngx_inline void rbtree_walk_ordered_decr_real(rbtree_seed_t *seed, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, rbtree_walk_callback_pt callback, void *data) {
  ngx_rbtree_node_t  *left, *right;
  if(node == sentinel || node == NULL) {
    return;
  }
  left = node->left;
  right = node->right;
  rbtree_walk_real(seed, right, sentinel, callback, data);
  callback(seed, rbtree_data_from_node(node), data);
  rbtree_walk_real(seed, left, sentinel, callback, data);
}
Beispiel #8
0
static subscriber_pool_t *find_spool(channel_spooler_t *spl, nchan_msg_id_t *id) {
  rbtree_seed_t      *seed = &spl->spoolseed;
  ngx_rbtree_node_t  *node;
  
  if((node = rbtree_find_node(seed, id)) != NULL) {
    return (subscriber_pool_t *)rbtree_data_from_node(node);
  }
  else {
    return NULL;
  }
}
Beispiel #9
0
unsigned rbtree_empty(rbtree_seed_t *seed, rbtree_walk_callback_pt callback, void *data) {
  ngx_rbtree_t         *tree = &seed->tree;
  ngx_rbtree_node_t    *cur, *sentinel = tree->sentinel;
  unsigned int          n = 0;
  
  for(cur = tree->root; cur != NULL && cur != sentinel; cur = tree->root) {
    if(callback) {
      callback(seed, rbtree_data_from_node(cur), data);
    }
    rbtree_remove_node(seed, cur);
    rbtree_destroy_node(seed, cur);
    n++;
  }
  return n;
}
Beispiel #10
0
static subscriber_pool_t *get_spool(channel_spooler_t *spl, nchan_msg_id_t *id) {
  rbtree_seed_t      *seed = &spl->spoolseed;
  ngx_rbtree_node_t  *node;
  subscriber_pool_t *spool;
  
  if(id->time == NCHAN_NEWEST_MSGID_TIME) {
    spool = &spl->current_msg_spool;
    spool->msg_status = MSG_EXPECTED;
    return &spl->current_msg_spool;
  }
  
  if((node = rbtree_find_node(seed, id)) == NULL) {
    
    if((node = rbtree_create_node(seed, sizeof(*spool))) == NULL) {
      ERR("can't create rbtree node for spool");
      return NULL;
    }
    
   // DBG("CREATED spool node %p for msgid %V", node, msgid_to_str(id));
    spool = (subscriber_pool_t *)rbtree_data_from_node(node);
    
    init_spool(spl, spool, id);
    
    if(rbtree_insert_node(seed, node) != NGX_OK) {
      ERR("couldn't insert spool node");
      rbtree_destroy_node(seed, node);
      return NULL;
    }
  }
  else {
    spool = (subscriber_pool_t *)rbtree_data_from_node(node);
    DBG("found spool node %p with msgid %V", node, msgid_to_str(id));
    assert(spool->id.time == id->time);
  }
  return spool;
}
Beispiel #11
0
ngx_int_t stop_spooler(channel_spooler_t *spl, uint8_t dequeue_subscribers) {
  ngx_rbtree_node_t    *cur, *sentinel;
  subscriber_pool_t    *spool;
  rbtree_seed_t        *seed = &spl->spoolseed;
  ngx_rbtree_t         *tree = &seed->tree;
  ngx_int_t             n=0;
  sentinel = tree->sentinel;
#if NCHAN_RBTREE_DBG
  ngx_int_t active_before = seed->active_nodes, allocd_before = seed->active_nodes;
#endif
  if(spl->running) {
    
    for(cur = tree->root; cur != NULL && cur != sentinel; cur = tree->root) {
      spool = (subscriber_pool_t *)rbtree_data_from_node(cur);
      if(dequeue_subscribers) {
        destroy_spool(spool);
      }
      else {
        remove_spool(spool);
        rbtree_destroy_node(seed, cur);
      }
      n++;
    }
    
    DBG("stopped %i spools in SPOOLER %p", n, *spl);
  }
  else {
    DBG("SPOOLER %p not running", *spl);
  }
#if NCHAN_RBTREE_DBG
  assert(active_before - n == 0);
  assert(allocd_before - n == 0);
  assert(seed->active_nodes == 0);
  assert(seed->allocd_nodes == 0);
#endif
  spl->running = 0;
  return NGX_OK;
}