static char* test_view_address_with_space(void *context) { struct {const char *addr; const char *view;} cases[] = { {"amqp:/link-target", "M0test.vhost.link-target"}, {"amqp:/domain/link-target", "M0test.vhost.domain/link-target"}, {"domain/link-target", "M0test.vhost.domain/link-target"}, {"bbc79fb3-e1fd-4a08-92b2-9a2de232b558", "M0test.vhost.bbc79fb3-e1fd-4a08-92b2-9a2de232b558"}, {0, 0} }; int idx; for (idx = 0; cases[idx].addr; idx++) { qd_iterator_t *iter = qd_iterator_string(cases[idx].addr, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_space(iter, "test.vhost.", 11); if (!qd_iterator_equal(iter, (unsigned char*) cases[idx].view)) { char *got = (char*) qd_iterator_copy(iter); snprintf(fail_text, FAIL_TEXT_SIZE, "Addr '%s' failed. Expected '%s', got '%s'", cases[idx].addr, cases[idx].view, got); return fail_text; } if (qd_iterator_length(iter) != strlen(cases[idx].view)) { snprintf(fail_text, FAIL_TEXT_SIZE, "Addr '%s' failed. Length %d, iter_length returned %d", cases[idx].addr, (int) strlen(cases[idx].view), (int) qd_iterator_length(iter)); return fail_text; } qd_iterator_free(iter); } return 0; }
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; }
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 char* test_view_address_hash_override(void *context) { struct {const char *addr; const char *view;} cases[] = { {"amqp:/link-target", "Clink-target"}, {"amqp:/domain/link-target", "Cdomain/link-target"}, {"domain/link-target", "Cdomain/link-target"}, {"bbc79fb3-e1fd-4a08-92b2-9a2de232b558", "Cbbc79fb3-e1fd-4a08-92b2-9a2de232b558"}, {0, 0} }; int idx; for (idx = 0; cases[idx].addr; idx++) { qd_iterator_t *iter = qd_iterator_string(cases[idx].addr, ITER_VIEW_ADDRESS_HASH); qd_iterator_annotate_prefix(iter, 'C'); if (!qd_iterator_equal(iter, (unsigned char*) cases[idx].view)) { char *got = (char*) qd_iterator_copy(iter); snprintf(fail_text, FAIL_TEXT_SIZE, "Addr '%s' failed. Expected '%s', got '%s'", cases[idx].addr, cases[idx].view, got); return fail_text; } qd_iterator_free(iter); } return 0; }
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_core_remove_address_config(qdr_core_t *core, qdr_address_config_t *addr) { qd_iterator_t *pattern = qd_iterator_string(addr->pattern, ITER_VIEW_ALL); // Remove the address from the list and the parse tree DEQ_REMOVE(core->addr_config, addr); qd_parse_tree_remove_pattern(core->addr_parse_tree, pattern); addr->ref_count--; if (addr->ref_count == 0) free_address_config(addr); qd_iterator_free(pattern); }
void qdr_core_remove_address_config(qdr_core_t *core, qdr_address_config_t *addr) { qd_iterator_t *pattern = qd_iterator_string(addr->pattern, ITER_VIEW_ALL); // Remove the address from the list and the parse tree DEQ_REMOVE(core->addr_config, addr); qd_parse_tree_remove_pattern(core->addr_parse_tree, pattern); // Free resources associated with this address. if (addr->name) { free(addr->name); } qd_iterator_free(pattern); free(addr->pattern); free_qdr_address_config_t(addr); }
static char *test_trim(void *context) { qd_iterator_t *iter = qd_iterator_string("testing.trim", ITER_VIEW_ALL); qd_iterator_trim_view(iter, 7); if (!qd_iterator_equal(iter, (unsigned char*) "testing")) return "Trim on ITER_VIEW_ALL failed (1)"; qd_iterator_reset_view(iter, ITER_VIEW_ALL); if (!qd_iterator_equal(iter, (unsigned char*) "testing.trim")) return "Trim on ITER_VIEW_ALL failed (2)"; qd_iterator_advance(iter, 4); qd_iterator_trim_view(iter, 5); if (!qd_iterator_equal(iter, (unsigned char*) "ing.t")) return "Trim on ITER_VIEW_ALL failed (3)"; qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); qd_iterator_trim_view(iter, 9); if (!qd_iterator_equal(iter, (unsigned char*) "M0testing")) return "Trim on ITER_VIEW_ADDRESS_HASH failed"; qd_iterator_reset(iter); qd_iterator_annotate_space(iter, "my_space.", 9); qd_iterator_trim_view(iter, 18); if (!qd_iterator_equal(iter, (unsigned char*) "M0my_space.testing")) return "Trim on ITER_VIEW_ADDRESS_HASH (with space 1) failed"; qd_iterator_reset(iter); qd_iterator_trim_view(iter, 10); if (!qd_iterator_equal(iter, (unsigned char*) "M0my_space")) return "Trim on ITER_VIEW_ADDRESS_HASH (in space 1) failed"; qd_iterator_reset(iter); qd_iterator_trim_view(iter, 2); if (!qd_iterator_equal(iter, (unsigned char*) "M0")) return "Trim on ITER_VIEW_ADDRESS_HASH (in annotation 1) failed"; qd_iterator_reset(iter); qd_iterator_trim_view(iter, 1); if (!qd_iterator_equal(iter, (unsigned char*) "M")) return "Trim on ITER_VIEW_ADDRESS_HASH (in annotation 2) failed"; qd_iterator_free(iter); return 0; }
static char* test_view_global_no_host(void *context) { qd_iterator_t *iter = qd_iterator_string("global/sub", ITER_VIEW_ALL); if (!qd_iterator_equal(iter, (unsigned char*) "global/sub")) return "ITER_VIEW_ALL failed"; qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_NO_HOST); if (!qd_iterator_equal(iter, (unsigned char*) "global/sub")) return "ITER_VIEW_ADDRESS_NO_HOST failed"; qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); if (!qd_iterator_equal(iter, (unsigned char*) "M0global/sub")) return "ITER_VIEW_ADDRESS_HASH failed"; qd_iterator_free(iter); return 0; }
/** * 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); }
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; }
static char *test_sub_iterator(void *context) { qd_iterator_t *iter = qd_iterator_string("test_sub_iterator", ITER_VIEW_ALL); qd_iterator_t *sub1 = qd_iterator_sub(iter, qd_iterator_remaining(iter)); qd_iterator_advance(iter, 5); qd_iterator_t *sub2 = qd_iterator_sub(iter, qd_iterator_remaining(iter)); qd_iterator_t *sub3 = qd_iterator_sub(iter, 3); if (!qd_iterator_equal(sub1, (unsigned char*) "test_sub_iterator")) return "Sub Iterator failed - 1"; if (!qd_iterator_equal(sub2, (unsigned char*) "sub_iterator")) return "Sub Iterator failed - 2"; if (!qd_iterator_equal(sub3, (unsigned char*) "sub")) return "Sub Iterator failed - 3"; qd_iterator_free(iter); qd_iterator_free(sub1); qd_iterator_free(sub2); qd_iterator_free(sub3); return 0; }
static char* test_view_node_hash(void *context) { struct {const char *addr; const char *view;} cases[] = { {"area/router", "Aarea"}, {"my-area/router", "Rrouter"}, {"my-area/my-router", "Rmy-router"}, {0, 0} }; int idx; for (idx = 0; cases[idx].addr; idx++) { qd_iterator_t *iter = qd_iterator_string(cases[idx].addr, ITER_VIEW_NODE_HASH); if (!qd_iterator_equal(iter, (unsigned char*) cases[idx].view)) { char *got = (char*) qd_iterator_copy(iter); snprintf(fail_text, FAIL_TEXT_SIZE, "Addr '%s' failed. Expected '%s', got '%s'", cases[idx].addr, cases[idx].view, got); return fail_text; qd_iterator_free(iter); } qd_iterator_free(iter); } return 0; }
static char* test_view_address_hash(void *context) { struct {const char *addr; const char *view;} cases[] = { {"amqp:/_local/my-addr/sub", "Lmy-addr/sub"}, {"amqp:/_local/my-addr", "Lmy-addr"}, {"amqp:/_topo/area/router/local/sub", "Aarea"}, {"amqp:/_topo/my-area/router/local/sub", "Rrouter"}, {"amqp:/_topo/my-area/my-router/local/sub", "Llocal/sub"}, {"amqp:/_topo/area/all/local/sub", "Aarea"}, {"amqp:/_topo/my-area/all/local/sub", "Tlocal/sub"}, {"amqp:/_topo/all/all/local/sub", "Tlocal/sub"}, {"amqp://host:port/_local/my-addr", "Lmy-addr"}, {"_topo/area/router/my-addr", "Aarea"}, {"_topo/my-area/router/my-addr", "Rrouter"}, {"_topo/my-area/my-router/my-addr", "Lmy-addr"}, {"_topo/my-area/router", "Rrouter"}, {"amqp:/mobile", "M1mobile"}, {"mobile", "M1mobile"}, {"/mobile", "M1mobile"}, // Re-run the above tests to make sure trailing dots are ignored. {"amqp:/_local/my-addr/sub.", "Lmy-addr/sub"}, {"amqp:/_local/my-addr.", "Lmy-addr"}, {"amqp:/_topo/area/router/local/sub.", "Aarea"}, {"amqp:/_topo/my-area/router/local/sub.", "Rrouter"}, {"amqp:/_topo/my-area/my-router/local/sub.", "Llocal/sub"}, {"amqp:/_topo/area/all/local/sub.", "Aarea"}, {"amqp:/_topo/my-area/all/local/sub.", "Tlocal/sub"}, {"amqp:/_topo/all/all/local/sub.", "Tlocal/sub"}, {"amqp://host:port/_local/my-addr.", "Lmy-addr"}, {"_topo/area/router/my-addr.", "Aarea"}, {"_topo/my-area/router/my-addr.", "Rrouter"}, {"_topo/my-area/my-router/my-addr.", "Lmy-addr"}, {"_topo/my-area/router.", "Rrouter"}, {"_topo/my-area/router:", "Rrouter:"}, {0, 0} }; int idx; for (idx = 0; cases[idx].addr; idx++) { qd_iterator_t *iter = qd_iterator_string(cases[idx].addr, ITER_VIEW_ADDRESS_HASH); char *ret = view_address_hash(context, iter, cases[idx].addr, cases[idx].view); qd_iterator_free(iter); if (ret) return ret; } for (idx = 0; cases[idx].addr; idx++) { qd_buffer_list_t chain; DEQ_INIT(chain); build_buffer_chain(&chain, cases[idx].addr, 3); qd_iterator_t *iter = qd_iterator_buffer(DEQ_HEAD(chain), 0, strlen(cases[idx].addr), ITER_VIEW_ADDRESS_HASH); char *ret = view_address_hash(context, iter, cases[idx].addr, cases[idx].view); release_buffer_chain(&chain); if (ret) return ret; } return 0; }