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 qd_iterator_t *router_annotate_message(qd_router_t *router, qd_parsed_field_t *in_ma, qd_message_t *msg, qd_bitmask_t **link_exclusions, bool strip_inbound_annotations) { qd_iterator_t *ingress_iter = 0; qd_parsed_field_t *trace = 0; qd_parsed_field_t *ingress = 0; qd_parsed_field_t *to = 0; qd_parsed_field_t *phase = 0; *link_exclusions = 0; if (in_ma && !strip_inbound_annotations) { uint32_t count = qd_parse_sub_count(in_ma); bool done = false; for (uint32_t idx = 0; idx < count && !done; idx++) { qd_parsed_field_t *sub = qd_parse_sub_key(in_ma, idx); if (!sub) continue; qd_iterator_t *iter = qd_parse_raw(sub); if (!iter) continue; if (qd_iterator_equal(iter, (unsigned char*) QD_MA_TRACE)) { trace = qd_parse_sub_value(in_ma, idx); } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_INGRESS)) { ingress = qd_parse_sub_value(in_ma, idx); } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_TO)) { to = qd_parse_sub_value(in_ma, idx); } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_PHASE)) { phase = qd_parse_sub_value(in_ma, idx); } done = trace && ingress && to && phase; } } // // QD_MA_TRACE: // If there is a trace field, append this router's ID to the trace. // If the router ID is already in the trace the msg has looped. // qd_composed_field_t *trace_field = qd_compose_subfield(0); qd_compose_start_list(trace_field); if (trace) { if (qd_parse_is_list(trace)) { // // Create a link-exclusion map for the items in the trace. This map will // contain a one-bit for each link that leads to a neighbor router that // the message has already passed through. // *link_exclusions = qd_tracemask_create(router->tracemask, trace); // // Append this router's ID to the trace. // uint32_t idx = 0; qd_parsed_field_t *trace_item = qd_parse_sub_value(trace, idx); while (trace_item) { qd_iterator_t *iter = qd_parse_raw(trace_item); qd_iterator_reset_view(iter, ITER_VIEW_ALL); qd_compose_insert_string_iterator(trace_field, iter); idx++; trace_item = qd_parse_sub_value(trace, idx); } } } qd_compose_insert_string(trace_field, node_id); qd_compose_end_list(trace_field); qd_message_set_trace_annotation(msg, trace_field); // // QD_MA_TO: // Preserve the existing value. // if (to) { qd_composed_field_t *to_field = qd_compose_subfield(0); qd_compose_insert_string_iterator(to_field, qd_parse_raw(to)); qd_message_set_to_override_annotation(msg, to_field); } // // QD_MA_PHASE: // Preserve the existing value. // if (phase) { int phase_val = qd_parse_as_int(phase); qd_message_set_phase_annotation(msg, phase_val); } // // QD_MA_INGRESS: // If there is no ingress field, annotate the ingress as // this router else keep the original field. // qd_composed_field_t *ingress_field = qd_compose_subfield(0); if (ingress && qd_parse_is_scalar(ingress)) { ingress_iter = qd_parse_raw(ingress); qd_compose_insert_string_iterator(ingress_field, ingress_iter); } else qd_compose_insert_string(ingress_field, node_id); qd_message_set_ingress_annotation(msg, ingress_field); // // Return the iterator to the ingress field _if_ it was present. // If we added the ingress, return NULL. // return ingress_iter; }