static void qdr_set_valid_origins_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; qd_bitmask_t *valid_origins = action->args.route_table.router_set; if (discard) { qd_bitmask_free(valid_origins); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_valid_origins: Router maskbit out of range: %d", router_maskbit); break; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "set_valid_origins: Router not found"); break; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; if (rnode->valid_origins) qd_bitmask_free(rnode->valid_origins); rnode->valid_origins = valid_origins; valid_origins = 0; } while (false); if (valid_origins) qd_bitmask_free(valid_origins); }
void qdr_core_remove_address(qdr_core_t *core, qdr_address_t *addr) { // Remove the address from the list, hash index, and parse tree DEQ_REMOVE(core->addrs, addr); if (addr->hash_handle) { const char *a_str = (const char *)qd_hash_key_by_handle(addr->hash_handle); if (QDR_IS_LINK_ROUTE(a_str[0])) { qd_iterator_t *iter = qd_iterator_string(a_str, ITER_VIEW_ALL); qdr_link_route_unmap_pattern_CT(core, iter); qd_iterator_free(iter); } qd_hash_remove_by_handle(core->addr_hash, addr->hash_handle); qd_hash_handle_free(addr->hash_handle); } // Free resources associated with this address qd_bitmask_free(addr->rnodes); if (addr->treatment == QD_TREATMENT_ANYCAST_CLOSEST) { qd_bitmask_free(addr->closest_remotes); } else if (addr->treatment == QD_TREATMENT_ANYCAST_BALANCED) { free(addr->outstanding_deliveries); } free_qdr_address_t(addr); }
void qdr_core_remove_address(qdr_core_t *core, qdr_address_t *addr) { qdr_address_config_t *config = addr->config; if (config && --config->ref_count == 0) free_address_config(config); // Remove the address from the list, hash index, and parse tree DEQ_REMOVE(core->addrs, addr); if (addr->hash_handle) { const char *a_str = (const char *)qd_hash_key_by_handle(addr->hash_handle); if (QDR_IS_LINK_ROUTE(a_str[0])) { qd_iterator_t *iter = qd_iterator_string(a_str, ITER_VIEW_ALL); qdr_link_route_unmap_pattern_CT(core, iter); qd_iterator_free(iter); } qd_hash_remove_by_handle(core->addr_hash, addr->hash_handle); qd_hash_handle_free(addr->hash_handle); } // Free resources associated with this address DEQ_APPEND(addr->rlinks, addr->inlinks); qdr_link_ref_t *lref = DEQ_HEAD(addr->rlinks); while (lref) { qdr_link_t *link = lref->link; assert(link->owning_addr == addr); link->owning_addr = 0; qdr_del_link_ref(&addr->rlinks, link, QDR_LINK_LIST_CLASS_ADDRESS); lref = DEQ_HEAD(addr->rlinks); } qd_bitmask_free(addr->rnodes); if (addr->treatment == QD_TREATMENT_ANYCAST_CLOSEST) { qd_bitmask_free(addr->closest_remotes); } else if (addr->treatment == QD_TREATMENT_ANYCAST_BALANCED) { free(addr->outstanding_deliveries); } qdr_connection_ref_t *cr = DEQ_HEAD(addr->conns); while (cr) { qdr_del_connection_ref(&addr->conns, cr->conn); cr = DEQ_HEAD(addr->conns); } if (!!addr->fallback) { addr->fallback->fallback_for = 0; qdr_check_addr_CT(core, addr->fallback); } free(addr->add_prefix); free(addr->del_prefix); free_qdr_address_t(addr); }
void qdr_router_node_free(qdr_core_t *core, qdr_node_t *rnode) { qd_bitmask_free(rnode->valid_origins); DEQ_REMOVE(core->routers, rnode); core->routers_by_mask_bit[rnode->mask_bit] = 0; core->cost_epoch++; free_qdr_node_t(rnode); }
void qdr_core_remove_address(qdr_core_t *core, qdr_address_t *addr) { // Remove the address from the list and hash index qd_hash_remove_by_handle(core->addr_hash, addr->hash_handle); DEQ_REMOVE(core->addrs, addr); // Free resources associated with this address qd_hash_handle_free(addr->hash_handle); qd_bitmask_free(addr->rnodes); if (addr->treatment == QD_TREATMENT_ANYCAST_CLOSEST) { qd_bitmask_free(addr->closest_remotes); } else if (addr->treatment == QD_TREATMENT_ANYCAST_BALANCED) { free(addr->outstanding_deliveries); } free_qdr_address_t(addr); }
static PyObject* qd_set_valid_origins(PyObject *self, PyObject *args) { RouterAdapter *adapter = (RouterAdapter*) self; qd_router_t *router = adapter->router; int router_maskbit; PyObject *origin_list; Py_ssize_t idx; char *error = 0; if (!PyArg_ParseTuple(args, "iO", &router_maskbit, &origin_list)) return 0; do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { error = "Router bit mask out of range"; break; } if (!PyList_Check(origin_list)) { error = "Expected List as argument 2"; break; } Py_ssize_t origin_count = PyList_Size(origin_list); qd_bitmask_t *core_bitmask = qd_bitmask(0); int maskbit; for (idx = 0; idx < origin_count; idx++) { maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); if (maskbit >= qd_bitmask_width() || maskbit < 0) { error = "Origin bit mask out of range"; break; } } if (error == 0) { qd_bitmask_set_bit(core_bitmask, 0); // This router is a valid origin for all destinations for (idx = 0; idx < origin_count; idx++) { maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); qd_bitmask_set_bit(core_bitmask, maskbit); } } else { qd_bitmask_free(core_bitmask); break; } qdr_core_set_valid_origins(router->router_core, router_maskbit, core_bitmask); } while (0); if (error) { PyErr_SetString(PyExc_Exception, error); return 0; } Py_INCREF(Py_None); return Py_None; }
void qdr_core_free(qdr_core_t *core) { // // Stop and join the thread // core->running = false; sys_cond_signal(core->action_cond); sys_thread_join(core->thread); // // Free the core resources // sys_thread_free(core->thread); sys_cond_free(core->action_cond); sys_mutex_free(core->action_lock); sys_mutex_free(core->work_lock); sys_mutex_free(core->id_lock); qd_timer_free(core->work_timer); //we can't call qdr_core_unsubscribe on the subscriptions because the action processing thread has //already been shut down. But, all the action would have done at this point is free the subscriptions //so we just do that directly. free(core->agent_subscription_mobile); free(core->agent_subscription_local); for (int i = 0; i <= QD_TREATMENT_LINK_BALANCED; ++i) { if (core->forwarders[i]) { free(core->forwarders[i]); } } qdr_address_t *addr = 0; while ( (addr = DEQ_HEAD(core->addrs)) ) { qdr_core_remove_address(core, addr); } qdr_address_config_t *addr_config = 0; while ( (addr_config = DEQ_HEAD(core->addr_config))) { qdr_core_remove_address_config(core, addr_config); } qd_hash_free(core->addr_hash); qd_hash_free(core->conn_id_hash); //TODO what about the actual connection identifier objects? qdr_node_t *rnode = 0; while ( (rnode = DEQ_HEAD(core->routers)) ) { qdr_router_node_free(core, rnode); } if (core->query_lock) sys_mutex_free(core->query_lock); if (core->routers_by_mask_bit) free(core->routers_by_mask_bit); if (core->control_links_by_mask_bit) free(core->control_links_by_mask_bit); if (core->data_links_by_mask_bit) free(core->data_links_by_mask_bit); if (core->neighbor_free_mask) qd_bitmask_free(core->neighbor_free_mask); free(core); }
static void qdr_del_router_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "del_router: Router maskbit out of range: %d", router_maskbit); return; } if (core->routers_by_mask_bit[router_maskbit] == 0) { qd_log(core->log, QD_LOG_CRITICAL, "del_router: Deleting nonexistent router: %d", router_maskbit); return; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; qdr_address_t *oaddr = rnode->owning_addr; assert(oaddr); // // Unlink the router node from the address record // qd_bitmask_clear_bit(oaddr->rnodes, router_maskbit); qd_bitmask_clear_bit(core->router_addr_T->rnodes, router_maskbit); qd_bitmask_clear_bit(core->routerma_addr_T->rnodes, router_maskbit); rnode->ref_count -= 3; // // While the router node has a non-zero reference count, look for addresses // to unlink the node from. // qdr_address_t *addr = DEQ_HEAD(core->addrs); while (addr && rnode->ref_count > 0) { if (qd_bitmask_clear_bit(addr->rnodes, router_maskbit)) // // If the cleared bit was originally set, decrement the ref count // rnode->ref_count--; addr = DEQ_NEXT(addr); } assert(rnode->ref_count == 0); // // Free the router node and the owning address records. // qd_bitmask_free(rnode->valid_origins); DEQ_REMOVE(core->routers, rnode); free_qdr_node_t(rnode); qd_hash_remove_by_handle(core->addr_hash, oaddr->hash_handle); DEQ_REMOVE(core->addrs, oaddr); qd_hash_handle_free(oaddr->hash_handle); core->routers_by_mask_bit[router_maskbit] = 0; free_qdr_address_t(oaddr); }
void qdr_core_free(qdr_core_t *core) { // // Stop and join the thread // core->running = false; sys_cond_signal(core->action_cond); sys_thread_join(core->thread); // Drain the general work lists qdr_general_handler(core); // // Free the core resources // sys_thread_free(core->thread); sys_cond_free(core->action_cond); sys_mutex_free(core->action_lock); sys_mutex_free(core->work_lock); sys_mutex_free(core->id_lock); qd_timer_free(core->work_timer); //we can't call qdr_core_unsubscribe on the subscriptions because the action processing thread has //already been shut down. But, all the action would have done at this point is free the subscriptions //so we just do that directly. free(core->agent_subscription_mobile); free(core->agent_subscription_local); for (int i = 0; i <= QD_TREATMENT_LINK_BALANCED; ++i) { if (core->forwarders[i]) { free(core->forwarders[i]); } } qdr_link_route_t *link_route = 0; while ( (link_route = DEQ_HEAD(core->link_routes))) { DEQ_REMOVE_HEAD(core->link_routes); qdr_core_delete_link_route(core, link_route); } qdr_auto_link_t *auto_link = 0; while ( (auto_link = DEQ_HEAD(core->auto_links))) { DEQ_REMOVE_HEAD(core->auto_links); qdr_core_delete_auto_link(core, auto_link); } qdr_exchange_free_all(core); qdr_address_t *addr = 0; while ( (addr = DEQ_HEAD(core->addrs)) ) { qdr_core_remove_address(core, addr); } qdr_address_config_t *addr_config = 0; while ( (addr_config = DEQ_HEAD(core->addr_config))) { qdr_core_remove_address_config(core, addr_config); } qd_hash_free(core->addr_hash); qd_parse_tree_free(core->addr_parse_tree); qd_parse_tree_free(core->link_route_tree[QD_INCOMING]); qd_parse_tree_free(core->link_route_tree[QD_OUTGOING]); qdr_node_t *rnode = 0; while ( (rnode = DEQ_HEAD(core->routers)) ) { qdr_router_node_free(core, rnode); } qdr_link_t *link = DEQ_HEAD(core->open_links); while (link) { DEQ_REMOVE_HEAD(core->open_links); if (link->core_endpoint) qdrc_endpoint_do_cleanup_CT(core, link->core_endpoint); qdr_del_link_ref(&link->conn->links, link, QDR_LINK_LIST_CLASS_CONNECTION); qdr_del_link_ref(&link->conn->links_with_work[link->priority], link, QDR_LINK_LIST_CLASS_WORK); free(link->name); free(link->disambiguated_name); free(link->terminus_addr); free(link->ingress_histogram); free(link->insert_prefix); free(link->strip_prefix); link->name = 0; free_qdr_link_t(link); link = DEQ_HEAD(core->open_links); } qdr_connection_t *conn = DEQ_HEAD(core->open_connections); while (conn) { DEQ_REMOVE_HEAD(core->open_connections); if (conn->conn_id) { qdr_del_connection_ref(&conn->conn_id->connection_refs, conn); qdr_route_check_id_for_deletion_CT(core, conn->conn_id); } qdr_connection_work_t *work = DEQ_HEAD(conn->work_list); while (work) { DEQ_REMOVE_HEAD(conn->work_list); qdr_connection_work_free_CT(work); work = DEQ_HEAD(conn->work_list); } qdr_connection_free(conn); conn = DEQ_HEAD(core->open_connections); } // at this point all the conn identifiers have been freed qd_hash_free(core->conn_id_hash); qdr_modules_finalize(core); if (core->query_lock) sys_mutex_free(core->query_lock); if (core->routers_by_mask_bit) free(core->routers_by_mask_bit); if (core->control_links_by_mask_bit) free(core->control_links_by_mask_bit); if (core->data_links_by_mask_bit) free(core->data_links_by_mask_bit); if (core->neighbor_free_mask) qd_bitmask_free(core->neighbor_free_mask); free(core); }
static char *test_tracemask(void *context) { qd_bitmask_t *bm = NULL; qd_tracemask_t *tm = qd_tracemask(); qd_buffer_list_t list; static char error[1024]; error[0] = 0; qd_iterator_set_address(false, "0", "ROUTER"); qd_tracemask_add_router(tm, "amqp:/_topo/0/Router.A", 0); qd_tracemask_add_router(tm, "amqp:/_topo/0/Router.B", 1); qd_tracemask_add_router(tm, "amqp:/_topo/0/Router.C", 2); qd_tracemask_add_router(tm, "amqp:/_topo/0/Router.D", 3); qd_tracemask_add_router(tm, "amqp:/_topo/0/Router.E", 4); qd_tracemask_add_router(tm, "amqp:/_topo/0/Router.F", 5); qd_tracemask_set_link(tm, 0, 4); qd_tracemask_set_link(tm, 3, 10); qd_tracemask_set_link(tm, 4, 3); qd_tracemask_set_link(tm, 5, 2); qd_composed_field_t *comp = qd_compose_subfield(0); qd_compose_start_list(comp); qd_compose_insert_string(comp, "0/Router.A"); qd_compose_insert_string(comp, "0/Router.D"); qd_compose_insert_string(comp, "0/Router.E"); qd_compose_end_list(comp); DEQ_INIT(list); qd_compose_take_buffers(comp, &list); qd_compose_free(comp); int length = 0; qd_buffer_t *buf = DEQ_HEAD(list); while (buf) { length += qd_buffer_size(buf); buf = DEQ_NEXT(buf); } qd_iterator_t *iter = qd_iterator_buffer(DEQ_HEAD(list), 0, length, ITER_VIEW_ALL); qd_parsed_field_t *pf = qd_parse(iter); qd_iterator_free(iter); int ingress = -1; bm = qd_tracemask_create(tm, pf, &ingress); if (qd_bitmask_cardinality(bm) != 3) { sprintf(error, "Expected cardinality of 3, got %d", qd_bitmask_cardinality(bm)); goto cleanup; } if (ingress != 0) { sprintf(error, "(A) Expected ingress index of 0, got %d", ingress); goto cleanup; } int total = 0; int bit, c; for (QD_BITMASK_EACH(bm, bit, c)) { total += bit; } if (total != 17) { sprintf(error, "Expected total bit value of 17, got %d", total); goto cleanup; } qd_bitmask_free(bm); bm = 0; qd_tracemask_del_router(tm, 3); qd_tracemask_remove_link(tm, 0); ingress = -1; bm = qd_tracemask_create(tm, pf, &ingress); qd_parse_free(pf); pf = 0; if (qd_bitmask_cardinality(bm) != 1) { sprintf(error, "Expected cardinality of 1, got %d", qd_bitmask_cardinality(bm)); goto cleanup; } if (ingress != 0) { sprintf(error, "(B) Expected ingress index of 0, got %d", ingress); goto cleanup; } total = 0; for (QD_BITMASK_EACH(bm, bit, c)) { total += bit; } if (total != 3) { sprintf(error, "Expected total bit value of 3, got %d", total); // fallthrough } cleanup: qd_parse_free(pf); qd_tracemask_free(tm); qd_bitmask_free(bm); for (qd_buffer_t *buf = DEQ_HEAD(list); buf; buf = DEQ_HEAD(list)) { DEQ_REMOVE_HEAD(list); qd_buffer_free(buf); } return *error ? error : 0; }