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; }
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; }
/** Register a map processor * * This should be called by every module that provides a map processing function. * * @param[in] mod_inst of module registering the map_proc. * @param[in] name of map processor. If processor already exists, it is replaced. * @param[in] evaluate Module's map processor function. * @param[in] escape function to sanitize any sub expansions in the map source query. * @param[in] instantiate function (optional). * @param[in] inst_size of talloc chunk to allocate for instance data (optional). * @return * - 0 on success. * - -1 on failure. */ int map_proc_register(void *mod_inst, char const *name, map_proc_func_t evaluate, xlat_escape_t escape, map_proc_instantiate_t instantiate, size_t inst_size) { map_proc_t *proc; rad_assert(name && name[0]); if (!map_proc_root) { map_proc_root = rbtree_create(NULL, map_proc_cmp, NULL, RBTREE_FLAG_REPLACE); if (!map_proc_root) { DEBUG("map_proc: Failed to create tree"); return -1; } } /* * If it already exists, replace it. */ proc = map_proc_find(name); if (!proc) { rbnode_t *node; proc = talloc_zero(mod_inst, map_proc_t); strlcpy(proc->name, name, sizeof(proc->name)); proc->length = strlen(proc->name); node = rbtree_insert_node(map_proc_root, proc); if (!node) { talloc_free(proc); return -1; } talloc_set_destructor(proc, _map_proc_unregister); } DEBUG3("map_proc_register: %s", proc->name); proc->mod_inst = mod_inst; proc->evaluate = evaluate; proc->escape = escape; proc->instantiate = instantiate; proc->inst_size = inst_size; return 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; }
/** Register an xlat function. * * @param[in] name xlat name. * @param[in] func xlat function to be called. * @param[in] escape function to sanitize any sub expansions passed to the xlat function. * @param[in] instance of module that's registering the xlat function. * @return 0 on success, -1 on failure */ int xlat_register(char const *name, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING escape, void *instance) { xlat_t *c; xlat_t my_xlat; rbnode_t *node; if (!name || !*name) { DEBUG("xlat_register: Invalid xlat name"); return -1; } /* * First time around, build up the tree... * * FIXME: This code should be hoisted out of this function, * and into a global "initialization". But it isn't critical... */ if (!xlat_root) { #ifdef WITH_UNLANG int i; #endif xlat_root = rbtree_create(xlat_cmp, NULL, 0); if (!xlat_root) { DEBUG("xlat_register: Failed to create tree"); return -1; } #ifdef WITH_UNLANG for (i = 0; xlat_foreach_names[i] != NULL; i++) { xlat_register(xlat_foreach_names[i], xlat_foreach, NULL, &xlat_inst[i]); c = xlat_find(xlat_foreach_names[i]); rad_assert(c != NULL); c->internal = true; } #endif #define XLAT_REGISTER(_x) xlat_register(STRINGIFY(_x), xlat_ ## _x, NULL, NULL); \ c = xlat_find(STRINGIFY(_x)); \ rad_assert(c != NULL); \ c->internal = true XLAT_REGISTER(integer); XLAT_REGISTER(strlen); XLAT_REGISTER(length); XLAT_REGISTER(hex); XLAT_REGISTER(string); XLAT_REGISTER(xlat); XLAT_REGISTER(module); XLAT_REGISTER(debug_attr); xlat_register("debug", xlat_debug, NULL, &xlat_inst[0]); c = xlat_find("debug"); rad_assert(c != NULL); c->internal = true; } /* * If it already exists, replace the instance. */ strlcpy(my_xlat.name, name, sizeof(my_xlat.name)); my_xlat.length = strlen(my_xlat.name); c = rbtree_finddata(xlat_root, &my_xlat); if (c) { if (c->internal) { DEBUG("xlat_register: Cannot re-define internal xlat"); return -1; } c->func = func; c->escape = escape; c->instance = instance; return 0; } /* * Doesn't exist. Create it. */ c = talloc_zero(xlat_root, xlat_t); c->func = func; c->escape = escape; strlcpy(c->name, name, sizeof(c->name)); c->length = strlen(c->name); c->instance = instance; node = rbtree_insert_node(xlat_root, c); if (!node) { talloc_free(c); return -1; } /* * Ensure that the data is deleted when the node is * deleted. * * @todo: Maybe this should be the other way around... * when a thing IN the tree is deleted, it's automatically * removed from the tree. But for now, this works. */ (void) talloc_steal(node, c); return 0; }
bool rbtree_insert(rbtree_t *tree, void *data) { if (rbtree_insert_node(tree, data)) return true; return false; }
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; }