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; }
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 = ¶llel_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; }
/*! * 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); }
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; }
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; }
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); }
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; }
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; }
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; }
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; }