static void qdr_route_log_CT(qdr_core_t *core, const char *text, const char *name, uint64_t id, qdr_connection_t *conn) { const char *key = (const char*) qd_hash_key_by_handle(conn->conn_id->connection_hash_handle); if (!key) key = (const char*) qd_hash_key_by_handle(conn->conn_id->container_hash_handle); char id_string[64]; const char *log_name = name ? name : id_string; if (!name) snprintf(id_string, 64, "%"PRId64, id); qd_log(core->log, QD_LOG_INFO, "%s '%s' on %s %s", text, log_name, key[0] == 'L' ? "connection" : "container", &key[1]); }
void qdr_core_bind_address_link_CT(qdr_core_t *core, qdr_address_t *addr, qdr_link_t *link) { const char *key = (const char*) qd_hash_key_by_handle(addr->hash_handle); link->owning_addr = addr; if (key && (*key == QD_ITER_HASH_PREFIX_MOBILE)) link->phase = (int) (key[1] - '0'); if (link->link_direction == QD_OUTGOING) { qdr_add_link_ref(&addr->rlinks, link, QDR_LINK_LIST_CLASS_ADDRESS); if (DEQ_SIZE(addr->rlinks) == 1) { if (key && (*key == QD_ITER_HASH_PREFIX_EDGE_SUMMARY || *key == QD_ITER_HASH_PREFIX_MOBILE)) qdr_post_mobile_added_CT(core, key, addr->treatment); qdr_addr_start_inlinks_CT(core, addr); qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_BECAME_LOCAL_DEST, addr); } else if (DEQ_SIZE(addr->rlinks) == 2 && qd_bitmask_cardinality(addr->rnodes) == 0) qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_TWO_DEST, addr); } else { // link->link_direction == QD_INCOMING qdr_add_link_ref(&addr->inlinks, link, QDR_LINK_LIST_CLASS_ADDRESS); if (DEQ_SIZE(addr->inlinks) == 1) { qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_BECAME_SOURCE, addr); if (!!addr->fallback && !link->fallback) qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_BECAME_SOURCE, addr->fallback); } else if (DEQ_SIZE(addr->inlinks) == 2) { qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_TWO_SOURCE, addr); if (!!addr->fallback && !link->fallback) qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_TWO_SOURCE, addr->fallback); } } }
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); }
static void qdr_auto_link_activate_CT(qdr_core_t *core, qdr_auto_link_t *al, qdr_connection_t *conn) { const char *key; qdr_route_log_CT(core, "Auto Link Activated", al->name, al->identity, conn); if (al->addr) { qdr_terminus_t *source = 0; qdr_terminus_t *target = 0; qdr_terminus_t *term = qdr_terminus(0); if (al->dir == QD_INCOMING) source = term; else target = term; key = (const char*) qd_hash_key_by_handle(al->addr->hash_handle); if (key || al->external_addr) { if (al->external_addr) qdr_terminus_set_address(term, al->external_addr); else qdr_terminus_set_address(term, &key[2]); // truncate the "Mp" annotation (where p = phase) al->link = qdr_create_link_CT(core, conn, QD_LINK_ENDPOINT, al->dir, source, target); al->link->auto_link = al; al->state = QDR_AUTO_LINK_STATE_ATTACHING; } } }
void qdr_core_unbind_address_link_CT(qdr_core_t *core, qdr_address_t *addr, qdr_link_t *link) { link->owning_addr = 0; if (link->link_direction == QD_OUTGOING) { qdr_del_link_ref(&addr->rlinks, link, QDR_LINK_LIST_CLASS_ADDRESS); if (DEQ_SIZE(addr->rlinks) == 0) { const char *key = (const char*) qd_hash_key_by_handle(addr->hash_handle); if (key && (*key == QD_ITER_HASH_PREFIX_MOBILE || *key == QD_ITER_HASH_PREFIX_EDGE_SUMMARY)) qdr_post_mobile_removed_CT(core, key); qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_NO_LONGER_LOCAL_DEST, addr); } else if (DEQ_SIZE(addr->rlinks) == 1 && qd_bitmask_cardinality(addr->rnodes) == 0) qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_ONE_LOCAL_DEST, addr); } else { bool removed = qdr_del_link_ref(&addr->inlinks, link, QDR_LINK_LIST_CLASS_ADDRESS); if (removed) { if (DEQ_SIZE(addr->inlinks) == 0) { qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_NO_LONGER_SOURCE, addr); if (!!addr->fallback && !link->fallback) qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_NO_LONGER_SOURCE, addr->fallback); } else if (DEQ_SIZE(addr->inlinks) == 1) { qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_ONE_SOURCE, addr); if (!!addr->fallback && !link->fallback) qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_ONE_SOURCE, addr->fallback); } } } }
void qdr_core_unbind_address_conn_CT(qdr_core_t *core, qdr_address_t *addr, qdr_connection_t *conn) { qdr_del_connection_ref(&addr->conns, conn); if (DEQ_IS_EMPTY(addr->conns)) { const char *key = (const char*) qd_hash_key_by_handle(addr->hash_handle); qdr_post_mobile_removed_CT(core, key); qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_NO_LONGER_LOCAL_DEST, addr); } }
void qdr_core_bind_address_conn_CT(qdr_core_t *core, qdr_address_t *addr, qdr_connection_t *conn) { qdr_add_connection_ref(&addr->conns, conn); if (DEQ_SIZE(addr->conns) == 1) { const char *key = (const char*) qd_hash_key_by_handle(addr->hash_handle); qdr_post_mobile_added_CT(core, key, addr->treatment); qdrc_event_addr_raise(core, QDRC_EVENT_ADDR_BECAME_LOCAL_DEST, addr); } }
static void qdr_manage_advance_address_CT(qdr_query_t *query, qdr_address_t *addr) { query->next_offset++; addr = DEQ_NEXT(addr); if (addr) { query->more = true; query->next_key = qdr_field((const char*) qd_hash_key_by_handle(addr->hash_handle)); } else query->more = false; }
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); }
bool qdr_address_is_mobile_CT(qdr_address_t *addr) { if (!addr) return false; const char *addr_str = (const char *)qd_hash_key_by_handle(addr->hash_handle); if (addr_str && addr_str[0] == QD_ITER_HASH_PREFIX_MOBILE) return true; return false; }
static void qdr_link_route_deactivate_CT(qdr_core_t *core, qdr_link_route_t *lr, qdr_connection_t *conn) { const char *key; qdr_route_log_CT(core, "Link Route Deactivated", lr->name, lr->identity, conn); // // Deactivate the address(es) for link-routed destinations. // if (lr->addr) { qdr_del_connection_ref(&lr->addr->conns, conn); if (DEQ_IS_EMPTY(lr->addr->conns)) { key = (const char*) qd_hash_key_by_handle(lr->addr->hash_handle); if (key) qdr_post_mobile_removed_CT(core, key); } } }
/** * Search for, and possibly create, the fallback address based on the * fallback flag in the address's configuration. This will be used in * the forwarding paths to handle undeliverable messages with fallback destinations. */ void qdr_setup_fallback_address_CT(qdr_core_t *core, qdr_address_t *addr) { #define QDR_SETUP_FALLBACK_BUFFER_SIZE 256 char buffer[QDR_SETUP_FALLBACK_BUFFER_SIZE]; char *alt_text = buffer; bool buffer_on_heap = false; char *address_text = (char*) qd_hash_key_by_handle(addr->hash_handle); size_t alt_length = strlen(address_text) + 1; // // If this is a fallback address for a primary address that hasn't been seen // yet, simply exit without doing anything. // if (address_text[1] == QD_ITER_HASH_PHASE_FALLBACK) return; if (alt_length > QDR_SETUP_FALLBACK_BUFFER_SIZE) { alt_text = (char*) malloc(alt_length); buffer_on_heap = true; } strcpy(alt_text, address_text); alt_text[1] = QD_ITER_HASH_PHASE_FALLBACK; qd_iterator_t *alt_iter = qd_iterator_string(alt_text, ITER_VIEW_ALL); qdr_address_t *alt_addr = 0; qd_hash_retrieve(core->addr_hash, alt_iter, (void**) &alt_addr); if (!alt_addr) { alt_addr = qdr_address_CT(core, QD_TREATMENT_ANYCAST_BALANCED, 0); qd_hash_insert(core->addr_hash, alt_iter, alt_addr, &alt_addr->hash_handle); DEQ_INSERT_TAIL(core->addrs, alt_addr); } assert(alt_addr != addr); assert(alt_addr->fallback_for == 0); addr->fallback = alt_addr; alt_addr->fallback_for = addr; qd_iterator_free(alt_iter); if (buffer_on_heap) free(alt_text); }
static void qdr_link_route_activate_CT(qdr_core_t *core, qdr_link_route_t *lr, qdr_connection_t *conn) { const char *key; qdr_route_log_CT(core, "Link Route Activated", lr->name, lr->identity, conn); // // Activate the address for link-routed destinations. If this is the first // activation for this address, notify the router module of the added address. // if (lr->addr) { qdr_add_connection_ref(&lr->addr->conns, conn); if (DEQ_SIZE(lr->addr->conns) == 1) { key = (const char*) qd_hash_key_by_handle(lr->addr->hash_handle); if (key) qdr_post_mobile_added_CT(core, key); } } }
static const char *address_key(qdr_address_t *addr) { return addr && addr->hash_handle ? (const char*) qd_hash_key_by_handle(addr->hash_handle) : NULL; }
static void qdr_config_auto_link_insert_column_CT(qdr_auto_link_t *al, int col, qd_composed_field_t *body, bool as_map) { const char *text = 0; const char *key; char id_str[100]; if (as_map) qd_compose_insert_string(body, qdr_config_auto_link_columns[col]); switch(col) { case QDR_CONFIG_AUTO_LINK_NAME: if (al->name) qd_compose_insert_string(body, al->name); else qd_compose_insert_null(body); break; case QDR_CONFIG_AUTO_LINK_IDENTITY: snprintf(id_str, 100, "%"PRId64, al->identity); qd_compose_insert_string(body, id_str); break; case QDR_CONFIG_AUTO_LINK_TYPE: qd_compose_insert_string(body, CONFIG_AUTOLINK_TYPE); break; case QDR_CONFIG_AUTO_LINK_ADDR: key = (const char*) qd_hash_key_by_handle(al->addr->hash_handle); if (key && key[0] == 'M') qd_compose_insert_string(body, &key[2]); else qd_compose_insert_null(body); break; case QDR_CONFIG_AUTO_LINK_DIR: text = al->dir == QD_INCOMING ? "in" : "out"; qd_compose_insert_string(body, text); break; case QDR_CONFIG_AUTO_LINK_PHASE: qd_compose_insert_int(body, al->phase); break; case QDR_CONFIG_AUTO_LINK_CONNECTION: case QDR_CONFIG_AUTO_LINK_CONTAINER_ID: if (al->conn_id) { key = (const char*) qd_hash_key_by_handle(al->conn_id->hash_handle); if (key && key[0] == 'L' && col == QDR_CONFIG_AUTO_LINK_CONNECTION) { qd_compose_insert_string(body, &key[1]); break; } if (key && key[0] == 'C' && col == QDR_CONFIG_AUTO_LINK_CONTAINER_ID) { qd_compose_insert_string(body, &key[1]); break; } } qd_compose_insert_null(body); break; case QDR_CONFIG_AUTO_LINK_LINK_REF: if (al->link) { snprintf(id_str, 100, "%"PRId64, al->link->identity); qd_compose_insert_string(body, id_str); } else qd_compose_insert_null(body); break; case QDR_CONFIG_AUTO_LINK_OPER_STATUS: switch (al->state) { case QDR_AUTO_LINK_STATE_INACTIVE: text = "inactive"; break; case QDR_AUTO_LINK_STATE_ATTACHING: text = "attaching"; break; case QDR_AUTO_LINK_STATE_FAILED: text = "failed"; break; case QDR_AUTO_LINK_STATE_ACTIVE: text = "active"; break; case QDR_AUTO_LINK_STATE_QUIESCING: text = "quiescing"; break; case QDR_AUTO_LINK_STATE_IDLE: text = "idle"; break; } if (text) qd_compose_insert_string(body, text); else qd_compose_insert_null(body); break; case QDR_CONFIG_AUTO_LINK_LAST_ERROR: if (al->last_error) qd_compose_insert_string(body, al->last_error); else qd_compose_insert_null(body); break; } }
static void qdr_config_link_route_insert_column_CT(qdr_link_route_t *lr, int col, qd_composed_field_t *body, bool as_map) { const char *text = 0; const char *key; if (as_map) qd_compose_insert_string(body, qdr_config_link_route_columns[col]); switch(col) { case QDR_CONFIG_LINK_ROUTE_NAME: if (lr->name) qd_compose_insert_string(body, lr->name); else qd_compose_insert_null(body); break; case QDR_CONFIG_LINK_ROUTE_IDENTITY: { char id_str[100]; snprintf(id_str, 100, "%"PRId64, lr->identity); qd_compose_insert_string(body, id_str); break; } case QDR_CONFIG_LINK_ROUTE_TYPE: qd_compose_insert_string(body, "org.apache.qpid.dispatch.router.config.linkRoute"); break; case QDR_CONFIG_LINK_ROUTE_PREFIX: key = (const char*) qd_hash_key_by_handle(lr->addr->hash_handle); if (key && (key[0] == 'C' || key[0] == 'D')) qd_compose_insert_string(body, &key[1]); else qd_compose_insert_null(body); break; case QDR_CONFIG_LINK_ROUTE_DISTRIBUTION: switch (lr->treatment) { case QD_TREATMENT_LINK_BALANCED: text = "linkBalanced"; break; default: text = 0; } if (text) qd_compose_insert_string(body, text); else qd_compose_insert_null(body); break; case QDR_CONFIG_LINK_ROUTE_CONNECTION: case QDR_CONFIG_LINK_ROUTE_CONTAINER_ID: if (lr->conn_id) { key = (const char*) qd_hash_key_by_handle(lr->conn_id->hash_handle); if (key && key[0] == 'L' && col == QDR_CONFIG_LINK_ROUTE_CONNECTION) { qd_compose_insert_string(body, &key[1]); break; } if (key && key[0] == 'C' && col == QDR_CONFIG_LINK_ROUTE_CONTAINER_ID) { qd_compose_insert_string(body, &key[1]); break; } } qd_compose_insert_null(body); break; case QDR_CONFIG_LINK_ROUTE_DIR: text = lr->dir == QD_INCOMING ? "in" : "out"; qd_compose_insert_string(body, text); break; case QDR_CONFIG_LINK_ROUTE_OPER_STATUS: text = lr->active ? "active" : "inactive"; qd_compose_insert_string(body, text); break; } }
static void qdr_insert_address_columns_CT(qdr_core_t *core, qdr_address_t *addr, qd_composed_field_t *body, int column_index) { switch(column_index) { case QDR_ADDRESS_NAME: case QDR_ADDRESS_IDENTITY: case QDR_ADDRESS_KEY: if (addr->hash_handle) qd_compose_insert_string(body, (const char*) qd_hash_key_by_handle(addr->hash_handle)); else qd_compose_insert_null(body); break; case QDR_ADDRESS_TYPE: qd_compose_insert_string(body, "org.apache.qpid.dispatch.router.address"); break; case QDR_ADDRESS_DISTRIBUTION: { switch (addr->treatment) { case QD_TREATMENT_MULTICAST_FLOOD: qd_compose_insert_string(body, "flood"); break; case QD_TREATMENT_MULTICAST_ONCE: qd_compose_insert_string(body, "multicast"); break; case QD_TREATMENT_ANYCAST_CLOSEST: qd_compose_insert_string(body, "closest"); break; case QD_TREATMENT_ANYCAST_BALANCED: qd_compose_insert_string(body, "balanced"); break; case QD_TREATMENT_LINK_BALANCED: qd_compose_insert_string(body, "linkBalanced"); break; } break; } case QDR_ADDRESS_IN_PROCESS: qd_compose_insert_uint(body, DEQ_SIZE(addr->subscriptions)); break; case QDR_ADDRESS_SUBSCRIBER_COUNT: qd_compose_insert_uint(body, DEQ_SIZE(addr->rlinks)); break; case QDR_ADDRESS_REMOTE_COUNT: qd_compose_insert_uint(body, qd_bitmask_cardinality(addr->rnodes)); break; case QDR_ADDRESS_CONTAINER_COUNT: qd_compose_insert_uint(body, DEQ_SIZE(addr->conns)); break; case QDR_ADDRESS_REMOTE_HOST_ROUTERS: { qd_compose_start_list(body); int c; int bit; for (QD_BITMASK_EACH(addr->rnodes, bit, c)) { qdr_node_t *rnode = core->routers_by_mask_bit[bit]; if (rnode && rnode->owning_addr) { const char *ar = (char*) qd_hash_key_by_handle(rnode->owning_addr->hash_handle); qd_compose_insert_string(body, ar + 1); // Remove the 'R' prefix from the router address } } qd_compose_end_list(body); break; } case QDR_ADDRESS_DELIVERIES_INGRESS: qd_compose_insert_ulong(body, addr->deliveries_ingress); break; case QDR_ADDRESS_DELIVERIES_EGRESS: qd_compose_insert_ulong(body, addr->deliveries_egress); break; case QDR_ADDRESS_DELIVERIES_TRANSIT: qd_compose_insert_ulong(body, addr->deliveries_transit); break; case QDR_ADDRESS_DELIVERIES_TO_CONTAINER: qd_compose_insert_ulong(body, addr->deliveries_to_container); break; case QDR_ADDRESS_DELIVERIES_FROM_CONTAINER: qd_compose_insert_ulong(body, addr->deliveries_from_container); break; case QDR_ADDRESS_TRANSIT_OUTSTANDING: if (addr->outstanding_deliveries) { qd_compose_start_list(body); for (int i = 0; i < qd_bitmask_width(); i++) qd_compose_insert_long(body, addr->outstanding_deliveries[i]); qd_compose_end_list(body); } else qd_compose_insert_null(body); break; case QDR_ADDRESS_TRACKED_DELIVERIES: qd_compose_insert_long(body, addr->tracked_deliveries); break; default: qd_compose_insert_null(body); break; } }