Beispiel #1
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;
  
  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;
}
Beispiel #2
0
bool
xlb_workq_pop_parallel(xlb_work_unit** wu, int** ranks, int work_type)
{
  //TODO: cache the minimum size of parallel task of each type
  TRACE_START;
  bool result = false;
  struct rbtree* T = &parallel_work[work_type];
  TRACE("type: %i tree_size: %i", work_type, rbtree_size(T));
  // Common case is empty: want to exit asap
  if (rbtree_size(T) != 0)
  {
    struct pop_parallel_data data = { -1, NULL, NULL, NULL };
    data.type = work_type;
    TRACE("iterator...");
    bool found = rbtree_iterator(T, pop_parallel_cb, &data);
    if (found)
    {
      TRACE("found...");
      *wu = data.wu;
      *ranks = data.ranks;
      result = true;
      // Release memory:
      rbtree_remove_node(T, data.node);
      TRACE("rbtree_removed: wu: %p node: %p...", wu, data.node);
      free(data.node);
      xlb_workq_parallel_task_count--;
    }
  }
  TRACE_END;
  return result;
}
Beispiel #3
0
/*! 
 * Remove an object from the tree [takes O(log n) operations]
 *
 * \param tree The tree
 *
 * \param object The object to be removed
 *
 * \pre The object should be contained in the tree
 */
void rbtree_remove
    (
    rbtree_t * tree, 
    void * object
    )
    {
    /* find the node */
    rbnode_t * node = rbtree_find(tree, object); 

    /* remove the node */

    if (node) 
        rbtree_remove_node(tree, node);
    }
Beispiel #4
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 #5
0
static ngx_int_t remove_spool(subscriber_pool_t *spool) {
  channel_spooler_t    *spl = spool->spooler;
  ngx_rbtree_node_t    *node = rbtree_node_from_data(spool);
  
  DBG("remove spool node %p", node);
  
  assert(spool->spooler->running);
  nchan_free_msg_id(&spool->id);
  rbtree_remove_node(&spl->spoolseed, rbtree_node_from_data(spool));

  //assert((node = rbtree_find_node(&spl->spoolseed, &spool->id)) == NULL);
  //double-check that it's gone 
  
  return NGX_OK;
}
Beispiel #6
0
static inline void vres_file_delete_file(const char *path)
{
    vres_file_t *file = NULL;
    rbtree_node_t *node = NULL;

    pthread_rwlock_wrlock(&vres_file_flock);
    if (!rbtree_find(&vres_file_ftree, path, &node)) {
        file = tree_entry(node, vres_file_t, f_node);
        rbtree_remove_node(&vres_file_ftree, node);
    }
    pthread_rwlock_unlock(&vres_file_flock);
    if (file)
        free(file);
    log_file_delete_file(path);
}
Beispiel #7
0
int vres_file_release_dir(vres_file_dir_t *dir)
{
    int ret = 0;

    pthread_rwlock_wrlock(&dir->d_lock);
    while (dir->d_count > 0) {
        char *name;
        size_t len;
        rbtree_node_t *node;
        vres_file_name_t *ptr;
        char path[FILE_PATH_MAX];

        node = dir->d_tree.root;
        if (!node) {
            log_err("invalid directory");
            ret = -1;
            goto out;
        }
        name = (char *)node->key;
        len = strlen(name);
        if (!len || (len >= FILE_PATH_MAX)) {
            log_err("invalid path");
            ret = -1;
            goto out;
        }
        ptr = tree_entry(node, vres_file_name_t, node);
        sprintf(path, "%s%s", dir->d_path, name);
        if (FILE_SEPARATOR == name[len - 1]) {
            if (vres_file_rmdir(path)) {
                log_err("failed to remove %s", path);
                ret = -1;
                goto out;
            }
        } else {
            vres_file_delete_file(path);
            rbtree_remove_node(&dir->d_tree, node);
            dir->d_count--;
            free(ptr);
        }
    }
    vres_file_delete_dir(dir->d_path);
out:
    pthread_rwlock_unlock(&dir->d_lock);
    if (!ret)
        free(dir);
    return ret;
}
Beispiel #8
0
static adlb_code
rbtree_steal_type(struct rbtree *q, int num, xlb_workq_steal_callback cb)
{
  assert(q->size >= num);
  for (int i = 0; i < num; i++)
  {
    struct rbtree_node* node = rbtree_random(q);
    assert(node != NULL);
    rbtree_remove_node(q, node);
    xlb_work_unit *wu = (xlb_work_unit*) node->data;
    free(node);

    adlb_code code = cb.f(cb.data, wu);

    ADLB_CHECK(code);
  }
  return ADLB_SUCCESS;
}
Beispiel #9
0
static inline int vres_file_pop(char *path)
{
    size_t len;
    char *filename;
    char dirname[FILE_PATH_MAX];

    if (vres_file_dirname(path, dirname)) {
        log_err("invalid path, path=%s", path);
        return -1;
    }
    filename = path + strlen(dirname);
    len = strlen(filename);
    if ((len > 0) && (len + filename - path < FILE_PATH_MAX)) {
        vres_file_dir_t *dir = vres_file_lookup_dir(dirname);

        if (!dir)
            return -1;
        pthread_rwlock_wrlock(&dir->d_lock);
        if (dir->d_count > 0) {
            rbtree_node_t *node = NULL;

            if (!rbtree_find(&dir->d_tree, filename, &node)) {
                vres_file_name_t *name = tree_entry(node, vres_file_name_t, node);

                rbtree_remove_node(&dir->d_tree, node);
                dir->d_count--;
                free(name);
            }
        }
        pthread_rwlock_unlock(&dir->d_lock);
    } else {
        log_err("invalid path, path=%s", path);
        return -1;
    }
    return 0;
}
Beispiel #10
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;
}