void qdra_address_get_CT(qdr_core_t *core, qd_field_iterator_t *name, qd_field_iterator_t *identity, qdr_query_t *query, const char *qdr_address_columns[]) { qdr_address_t *addr = 0; if (identity) //If there is identity, ignore the name qd_hash_retrieve(core->addr_hash, identity, (void*) &addr); else if (name) qd_hash_retrieve(core->addr_hash, name, (void*) &addr); if (addr == 0) { // Send back a 404 query->status = QD_AMQP_NOT_FOUND; } else { // // Write the columns of the address entity into the response body. // qdr_manage_write_address_map_CT(core, addr, query->body, qdr_address_columns); query->status = QD_AMQP_OK; } // // Enqueue the response. // qdr_agent_enqueue_response_CT(core, query); }
static qdr_conn_identifier_t *qdr_route_declare_id_CT(qdr_core_t *core, qd_iterator_t *container, qd_iterator_t *connection) { qdr_conn_identifier_t *cid = 0; if (container && connection) { qd_iterator_reset_view(container, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_prefix(container, CONTAINER_PREFIX); qd_hash_retrieve(core->conn_id_hash, container, (void**) &cid); if (!cid) { qd_iterator_reset_view(connection, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_prefix(connection, CONNECTION_PREFIX); qd_hash_retrieve(core->conn_id_hash, connection, (void**) &cid); } if (!cid) { cid = new_qdr_conn_identifier_t(); ZERO(cid); // // The container and the connection will represent the same connection. // qd_hash_insert(core->conn_id_hash, container, cid, &cid->container_hash_handle); qd_hash_insert(core->conn_id_hash, connection, cid, &cid->connection_hash_handle); } } else if (container) { qd_iterator_reset_view(container, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_prefix(container, CONTAINER_PREFIX); qd_hash_retrieve(core->conn_id_hash, container, (void**) &cid); if (!cid) { cid = new_qdr_conn_identifier_t(); ZERO(cid); qd_hash_insert(core->conn_id_hash, container, cid, &cid->container_hash_handle); } } else if (connection) { qd_iterator_reset_view(connection, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_prefix(connection, CONNECTION_PREFIX); qd_hash_retrieve(core->conn_id_hash, connection, (void**) &cid); if (!cid) { cid = new_qdr_conn_identifier_t(); ZERO(cid); qd_hash_insert(core->conn_id_hash, connection, cid, &cid->connection_hash_handle); } } return cid; }
qdr_address_t *qdr_add_mobile_address_CT(qdr_core_t *core, const char *prefix, const char *address, qd_address_treatment_t treatment, bool edge) { char addr_string_stack[1000]; char *addr_string = addr_string_stack; bool allocated = false; qdr_address_t *addr = 0; qd_iterator_t *iter = 0; size_t len = strlen(prefix) + strlen(address) + 3; if (len > sizeof(addr_string_stack)) { allocated = true; addr_string = (char*) malloc(len); } snprintf(addr_string, len, "%s%s%s", edge ? "H" : "M0", prefix, address); iter = qd_iterator_string(addr_string, ITER_VIEW_ALL); qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (!addr) { addr = qdr_address_CT(core, treatment, 0); if (addr) { qd_hash_insert(core->addr_hash, iter, addr, &addr->hash_handle); DEQ_INSERT_TAIL(core->addrs, addr); } } qd_iterator_free(iter); if (allocated) free(addr_string); return addr; }
qdr_auto_link_t *qdr_route_add_auto_link_CT(qdr_core_t *core, qd_iterator_t *name, qd_parsed_field_t *addr_field, qd_direction_t dir, int phase, qd_parsed_field_t *container_field, qd_parsed_field_t *connection_field, qd_parsed_field_t *external_addr) { qdr_auto_link_t *al = new_qdr_auto_link_t(); // // Set up the auto_link structure // ZERO(al); al->identity = qdr_identifier(core); al->name = name ? (char*) qd_iterator_copy(name) : 0; al->dir = dir; al->phase = phase; al->state = QDR_AUTO_LINK_STATE_INACTIVE; al->external_addr = external_addr ? (char*) qd_iterator_copy(qd_parse_raw(external_addr)) : 0; // // Find or create an address for the auto_link destination // qd_iterator_t *iter = qd_parse_raw(addr_field); qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_phase(iter, (char) phase + '0'); qd_hash_retrieve(core->addr_hash, iter, (void*) &al->addr); if (!al->addr) { al->addr = qdr_address_CT(core, qdr_treatment_for_address_CT(core, 0, iter, 0, 0)); DEQ_INSERT_TAIL(core->addrs, al->addr); qd_hash_insert(core->addr_hash, iter, al->addr, &al->addr->hash_handle); } al->addr->ref_count++; // // Find or create a connection identifier structure for this auto_link // if (container_field || connection_field) { al->conn_id = qdr_route_declare_id_CT(core, qd_parse_raw(container_field), qd_parse_raw(connection_field)); DEQ_INSERT_TAIL_N(REF, al->conn_id->auto_link_refs, al); qdr_connection_ref_t * cref = DEQ_HEAD(al->conn_id->connection_refs); while (cref) { qdr_auto_link_activate_CT(core, al, cref->conn); cref = DEQ_NEXT(cref); } } // // Add the auto_link to the core list // DEQ_INSERT_TAIL(core->auto_links, al); return al; }
qdr_link_route_t *qdr_route_add_link_route_CT(qdr_core_t *core, qd_iterator_t *name, qd_parsed_field_t *prefix_field, qd_parsed_field_t *container_field, qd_parsed_field_t *connection_field, qd_address_treatment_t treatment, qd_direction_t dir) { qdr_link_route_t *lr = new_qdr_link_route_t(); // // Set up the link_route structure // ZERO(lr); lr->identity = qdr_identifier(core); lr->name = name ? (char*) qd_iterator_copy(name) : 0; lr->dir = dir; lr->treatment = treatment; // // Find or create an address for link-attach routing // qd_iterator_t *iter = qd_parse_raw(prefix_field); qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_prefix(iter, dir == QD_INCOMING ? 'C' : 'D'); qd_hash_retrieve(core->addr_hash, iter, (void*) &lr->addr); if (!lr->addr) { lr->addr = qdr_address_CT(core, treatment); DEQ_INSERT_TAIL(core->addrs, lr->addr); qd_hash_insert(core->addr_hash, iter, lr->addr, &lr->addr->hash_handle); } lr->addr->ref_count++; // // Find or create a connection identifier structure for this link route // if (container_field || connection_field) { lr->conn_id = qdr_route_declare_id_CT(core, qd_parse_raw(container_field), qd_parse_raw(connection_field)); DEQ_INSERT_TAIL_N(REF, lr->conn_id->link_route_refs, lr); qdr_connection_ref_t * cref = DEQ_HEAD(lr->conn_id->connection_refs); while (cref) { qdr_link_route_activate_CT(core, lr, cref->conn); cref = DEQ_NEXT(cref); } } // // Add the link route to the core list // DEQ_INSERT_TAIL(core->link_routes, lr); return lr; }
static void setup_outgoing_link(qd_container_t *container, pn_link_t *pn_link) { sys_mutex_lock(container->lock); qd_node_t *node = 0; const char *source = pn_terminus_get_address(pn_link_remote_source(pn_link)); qd_field_iterator_t *iter; // TODO - Extract the name from the structured source if (source) { iter = qd_address_iterator_string(source, ITER_VIEW_NODE_ID); qd_hash_retrieve(container->node_map, iter, (void*) &node); qd_field_iterator_free(iter); } sys_mutex_unlock(container->lock); if (node == 0) { if (container->default_node) node = container->default_node; else { pn_condition_t *cond = pn_link_condition(pn_link); pn_condition_set_name(cond, "amqp:not-found"); pn_condition_set_description(cond, "Source node does not exist"); pn_link_close(pn_link); return; } } qd_link_t *link = new_qd_link_t(); if (!link) { pn_condition_t *cond = pn_link_condition(pn_link); pn_condition_set_name(cond, "amqp:internal-error"); pn_condition_set_description(cond, "Insufficient memory"); pn_link_close(pn_link); return; } link->pn_sess = pn_link_session(pn_link); link->pn_link = pn_link; link->direction = QD_OUTGOING; link->context = 0; link->node = node; link->remote_snd_settle_mode = pn_link_remote_snd_settle_mode(pn_link); link->drain_mode = pn_link_get_drain(pn_link); link->close_sess_with_link = false; // // Keep the borrowed references // pn_incref(pn_link); pn_incref(link->pn_sess); pn_link_set_context(pn_link, link); node->ntype->outgoing_handler(node->context, link); }
static void qdr_map_destination_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { // // TODO - handle the class-prefix and phase explicitly // int router_maskbit = action->args.route_table.router_maskbit; qdr_field_t *address = action->args.route_table.address; if (discard) { qdr_field_free(address); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "map_destination: 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, "map_destination: Router not found"); break; } qd_field_iterator_t *iter = address->iterator; qdr_address_t *addr = 0; qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (!addr) { addr = qdr_address_CT(core, qdr_treatment_for_address_hash_CT(core, iter)); qd_hash_insert(core->addr_hash, iter, addr, &addr->hash_handle); DEQ_ITEM_INIT(addr); DEQ_INSERT_TAIL(core->addrs, addr); } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; qd_bitmask_set_bit(addr->rnodes, router_maskbit); rnode->ref_count++; qdr_addr_start_inlinks_CT(core, addr); // // TODO - If this affects a waypoint, create the proper side effects // } while (false); qdr_field_free(address); }
/** * 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_unmap_destination_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; qdr_field_t *address = action->args.route_table.address; if (discard) { qdr_field_free(address); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "unmap_destination: 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, "unmap_destination: Router not found"); break; } qdr_node_t *rnode = core->routers_by_mask_bit[router_maskbit]; qd_field_iterator_t *iter = address->iterator; qdr_address_t *addr = 0; qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (!addr) { qd_log(core->log, QD_LOG_CRITICAL, "unmap_destination: Address not found"); break; } qd_bitmask_clear_bit(addr->rnodes, router_maskbit); rnode->ref_count--; // // TODO - If this affects a waypoint, create the proper side effects // qdr_check_addr_CT(core, addr, false); } while (false); qdr_field_free(address); }
static qdr_conn_identifier_t *qdr_route_declare_id_CT(qdr_core_t *core, qd_field_iterator_t *conn_id, bool is_container) { char prefix = is_container ? 'C' : 'L'; qdr_conn_identifier_t *cid = 0; qd_address_iterator_reset_view(conn_id, ITER_VIEW_ADDRESS_HASH); qd_address_iterator_override_prefix(conn_id, prefix); qd_hash_retrieve(core->conn_id_hash, conn_id, (void**) &cid); if (!cid) { cid = new_qdr_conn_identifier_t(); ZERO(cid); qd_hash_insert(core->conn_id_hash, conn_id, cid, &cid->hash_handle); } return cid; }
void qdra_address_get_next_CT(qdr_core_t *core, qdr_query_t *query) { qdr_address_t *addr = 0; // // Use the stored key to try to find the next entry in the table. // if (query->next_key) { qd_hash_retrieve(core->addr_hash, query->next_key->iterator, (void**) &addr); qdr_field_free(query->next_key); query->next_key = 0; } if (!addr) { // // If the address was removed in the time between this get and the previous one, // we need to use the saved offset, which is less efficient. // if (query->next_offset < DEQ_SIZE(core->addrs)) { addr = DEQ_HEAD(core->addrs); for (int i = 0; i < query->next_offset && addr; i++) addr = DEQ_NEXT(addr); } } if (addr) { // // Write the columns of the address entity into the response body. // qdr_manage_write_address_list_CT(core, query, addr); // // Advance to the next address // qdr_manage_advance_address_CT(query, addr); } else query->more = false; // // Enqueue the response. // qdr_agent_enqueue_response_CT(core, query); }
qdr_address_t *qdr_add_local_address_CT(qdr_core_t *core, char aclass, const char *address, qd_address_treatment_t treatment) { char addr_string[1000]; qdr_address_t *addr = 0; qd_iterator_t *iter = 0; snprintf(addr_string, sizeof(addr_string), "%c%s", aclass, address); iter = qd_iterator_string(addr_string, ITER_VIEW_ALL); qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (!addr) { addr = qdr_address_CT(core, treatment); qd_hash_insert(core->addr_hash, iter, addr, &addr->hash_handle); DEQ_INSERT_TAIL(core->addrs, addr); addr->block_deletion = true; addr->local = (aclass == 'L'); } qd_iterator_free(iter); return addr; }
qd_bitmask_t *qd_tracemask_create(qd_tracemask_t *tm, qd_parsed_field_t *tracelist) { qd_bitmask_t *bm = qd_bitmask(0); int idx = 0; assert(qd_parse_is_list(tracelist)); sys_rwlock_rdlock(tm->lock); qd_parsed_field_t *item = qd_parse_sub_value(tracelist, idx); qdtm_router_t *router = 0; while (item) { qd_field_iterator_t *iter = qd_parse_raw(item); qd_address_iterator_reset_view(iter, ITER_VIEW_NODE_HASH); qd_hash_retrieve(tm->hash, iter, (void*) &router); if (router && router->link_maskbit >= 0) qd_bitmask_set_bit(bm, router->link_maskbit); idx++; item = qd_parse_sub_value(tracelist, idx); } sys_rwlock_unlock(tm->lock); return bm; }
static void qdr_subscribe_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { qdr_field_t *address = action->args.io.address; qdr_subscription_t *sub = action->args.io.subscription; if (!discard) { char aclass = action->args.io.address_class; char phase = action->args.io.address_phase; qdr_address_t *addr = 0; char *astring = (char*) qd_field_iterator_copy(address->iterator); qd_log(core->log, QD_LOG_INFO, "In-process subscription %c/%s", aclass, astring); free(astring); qd_address_iterator_override_prefix(address->iterator, aclass); if (aclass == 'M') qd_address_iterator_set_phase(address->iterator, phase); qd_address_iterator_reset_view(address->iterator, ITER_VIEW_ADDRESS_HASH); qd_hash_retrieve(core->addr_hash, address->iterator, (void**) &addr); if (!addr) { addr = qdr_address_CT(core, action->args.io.treatment); qd_hash_insert(core->addr_hash, address->iterator, addr, &addr->hash_handle); DEQ_ITEM_INIT(addr); DEQ_INSERT_TAIL(core->addrs, addr); } sub->addr = addr; DEQ_ITEM_INIT(sub); DEQ_INSERT_TAIL(addr->subscriptions, sub); qdr_addr_start_inlinks_CT(core, addr); } else free(sub); qdr_field_free(address); }
static void qdr_add_router_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { int router_maskbit = action->args.route_table.router_maskbit; qdr_field_t *address = action->args.route_table.address; if (discard) { qdr_field_free(address); return; } do { if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) { qd_log(core->log, QD_LOG_CRITICAL, "add_router: 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, "add_router: Router maskbit already in use: %d", router_maskbit); break; } // // Hash lookup the address to ensure there isn't an existing router address. // qd_field_iterator_t *iter = address->iterator; qdr_address_t *addr; qd_address_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); qd_hash_retrieve(core->addr_hash, iter, (void**) &addr); if (addr) { qd_log(core->log, QD_LOG_CRITICAL, "add_router: Data inconsistency for router-maskbit %d", router_maskbit); assert(addr == 0); // Crash in debug mode. This should never happen break; } // // Create an address record for this router and insert it in the hash table. // This record will be found whenever a "foreign" topological address to this // remote router is looked up. // addr = qdr_address_CT(core, QD_TREATMENT_ANYCAST_CLOSEST); qd_hash_insert(core->addr_hash, iter, addr, &addr->hash_handle); DEQ_INSERT_TAIL(core->addrs, addr); // // Create a router-node record to represent the remote router. // qdr_node_t *rnode = new_qdr_node_t(); DEQ_ITEM_INIT(rnode); rnode->owning_addr = addr; rnode->mask_bit = router_maskbit; rnode->next_hop = 0; rnode->peer_control_link = 0; rnode->peer_data_link = 0; rnode->ref_count = 0; rnode->valid_origins = qd_bitmask(0); DEQ_INSERT_TAIL(core->routers, rnode); // // Link the router record to the address record. // qd_bitmask_set_bit(addr->rnodes, router_maskbit); // // Link the router record to the router address records. // Use the T-class addresses only. // qd_bitmask_set_bit(core->router_addr_T->rnodes, router_maskbit); qd_bitmask_set_bit(core->routerma_addr_T->rnodes, router_maskbit); // // Bump the ref-count by three for each of the above links. // rnode->ref_count += 3; // // Add the router record to the mask-bit index. // core->routers_by_mask_bit[router_maskbit] = rnode; } while (false); qdr_field_free(address); }