qd_router_t *qd_router(qd_dispatch_t *qd, qd_router_mode_t mode, const char *area, const char *id) { if (!type_registered) { type_registered = 1; qd_container_register_node_type(qd, &router_node); } size_t dplen = 9 + strlen(area) + strlen(id); node_id = (char*) malloc(dplen); strcpy(node_id, area); strcat(node_id, "/"); strcat(node_id, id); qd_router_t *router = NEW(qd_router_t); ZERO(router); router_node.type_context = router; qd->router = router; router->qd = qd; router->router_core = 0; router->log_source = qd_log_source("ROUTER"); router->router_mode = mode; router->router_area = area; router->router_id = id; router->node = qd_container_set_default_node_type(qd, &router_node, (void*) router, QD_DIST_BOTH); router->lock = sys_mutex(); router->timer = qd_timer(qd, qd_router_timer_handler, (void*) router); // // Inform the field iterator module of this router's id and area. The field iterator // uses this to offload some of the address-processing load from the router. // qd_iterator_set_address(area, id); // // Seed the random number generator // unsigned int seed = (unsigned int) time(0); srandom(seed); switch (router->router_mode) { case QD_ROUTER_MODE_STANDALONE: qd_log(router->log_source, QD_LOG_INFO, "Router started in Standalone mode"); break; case QD_ROUTER_MODE_INTERIOR: qd_log(router->log_source, QD_LOG_INFO, "Router started in Interior mode, area=%s id=%s", area, id); break; case QD_ROUTER_MODE_EDGE: qd_log(router->log_source, QD_LOG_INFO, "Router started in Edge mode"); break; case QD_ROUTER_MODE_ENDPOINT: qd_log(router->log_source, QD_LOG_INFO, "Router started in Endpoint mode"); break; } return router; }
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; }