qdr_field_t *qdr_field_from_iter(qd_iterator_t *iter) { if (!iter) return 0; qdr_field_t *field = new_qdr_field_t(); qd_buffer_t *buf; int remaining; int length; ZERO(field); qd_iterator_reset(iter); remaining = qd_iterator_remaining(iter); length = remaining; while (remaining) { buf = qd_buffer(); size_t cap = qd_buffer_capacity(buf); int copied = qd_iterator_ncopy(iter, qd_buffer_cursor(buf), cap); qd_buffer_insert(buf, copied); DEQ_INSERT_TAIL(field->buffers, buf); remaining = qd_iterator_remaining(iter); } field->iterator = qd_iterator_buffer(DEQ_HEAD(field->buffers), 0, length, ITER_VIEW_ALL); return field; }
qdr_field_t *qdr_field(const char *text) { size_t length = text ? strlen(text) : 0; size_t ilength = length; if (length == 0) return 0; qdr_field_t *field = new_qdr_field_t(); qd_buffer_t *buf; ZERO(field); while (length > 0) { buf = qd_buffer(); size_t cap = qd_buffer_capacity(buf); size_t copy = length > cap ? cap : length; memcpy(qd_buffer_cursor(buf), text, copy); qd_buffer_insert(buf, copy); length -= copy; text += copy; DEQ_INSERT_TAIL(field->buffers, buf); } field->iterator = qd_iterator_buffer(DEQ_HEAD(field->buffers), 0, ilength, ITER_VIEW_ALL); return field; }
const char *qd_parse_annotations_v1( bool strip_anno_in, qd_iterator_t *ma_iter_in, qd_parsed_field_t **ma_ingress, qd_parsed_field_t **ma_phase, qd_parsed_field_t **ma_to_override, qd_parsed_field_t **ma_trace, qd_iterator_pointer_t *blob_pointer, uint32_t *blob_item_count) { // Do full parse qd_iterator_reset(ma_iter_in); qd_parsed_turbo_list_t annos; uint32_t user_entries; uint32_t user_bytes; const char * parse_error = qd_parse_turbo(ma_iter_in, &annos, &user_entries, &user_bytes); if (parse_error) { return parse_error; } qd_parsed_turbo_t *anno; if (!strip_anno_in) { anno = DEQ_HEAD(annos); while (anno) { qd_iterator_t *key_iter = qd_iterator_buffer(anno->bufptr.buffer, anno->bufptr.cursor - qd_buffer_base(anno->bufptr.buffer), anno->size, ITER_VIEW_ALL); assert(key_iter); qd_parsed_field_t *key_field = qd_parse(key_iter); assert(key_field); qd_iterator_t *iter = qd_parse_raw(key_field); assert(iter); qd_parsed_turbo_t *anno_val = DEQ_NEXT(anno); assert(anno_val); qd_iterator_t *val_iter = qd_iterator_buffer(anno_val->bufptr.buffer, anno_val->bufptr.cursor - qd_buffer_base(anno_val->bufptr.buffer), anno_val->size, ITER_VIEW_ALL); assert(val_iter); qd_parsed_field_t *val_field = qd_parse(val_iter); assert(val_field); // Hoist the key name out of the buffers into a normal char array char key_name[QD_MA_MAX_KEY_LEN + 1]; (void)qd_iterator_strncpy(iter, key_name, QD_MA_MAX_KEY_LEN + 1); // transfer ownership of the extracted value to the message if (!strcmp(key_name, QD_MA_TRACE)) { *ma_trace = val_field; } else if (!strcmp(key_name, QD_MA_INGRESS)) { *ma_ingress = val_field; } else if (!strcmp(key_name, QD_MA_TO)) { *ma_to_override = val_field; } else if (!strcmp(key_name, QD_MA_PHASE)) { *ma_phase = val_field; } else { // TODO: this key had the QD_MA_PREFIX but it does not match // one of the actual fields. qd_parse_free(val_field); } qd_iterator_free(key_iter); qd_parse_free(key_field); qd_iterator_free(val_iter); // val_field is usually handed over to message_private and is freed anno = DEQ_NEXT(anno_val); } } anno = DEQ_HEAD(annos); while (anno) { DEQ_REMOVE_HEAD(annos); free_qd_parsed_turbo_t(anno); anno = DEQ_HEAD(annos); } // Adjust size of user annotation blob by the size of the router // annotations blob_pointer->remaining = user_bytes; assert(blob_pointer->remaining >= 0); *blob_item_count = user_entries; assert(*blob_item_count >= 0); return 0; }
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; }
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; }