void qd_message_free(qd_message_t *in_msg) { if (!in_msg) return; uint32_t rc; qd_message_pvt_t *msg = (qd_message_pvt_t*) in_msg; qd_buffer_list_free_buffers(&msg->ma_to_override); qd_buffer_list_free_buffers(&msg->ma_trace); qd_buffer_list_free_buffers(&msg->ma_ingress); qd_message_content_t *content = msg->content; sys_mutex_lock(content->lock); rc = --content->ref_count; sys_mutex_unlock(content->lock); if (rc == 0) { if (content->parsed_message_annotations) qd_parse_free(content->parsed_message_annotations); qd_buffer_t *buf = DEQ_HEAD(content->buffers); while (buf) { DEQ_REMOVE_HEAD(content->buffers); qd_buffer_free(buf); buf = DEQ_HEAD(content->buffers); } sys_mutex_free(content->lock); free_qd_message_content_t(content); } free_qd_message_t((qd_message_t*) msg); }
static void release_buffer_chain(qd_buffer_list_t *chain) { while (DEQ_SIZE(*chain)) { qd_buffer_t *buf = DEQ_HEAD(*chain); DEQ_REMOVE_HEAD(*chain); qd_buffer_free(buf); } }
void qd_buffer_list_free_buffers(qd_buffer_list_t *list) { qd_buffer_t *buf = DEQ_HEAD(*list); while (buf) { DEQ_REMOVE_HEAD(*list); qd_buffer_free(buf); buf = DEQ_HEAD(*list); } }
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; }
qd_message_t *qd_message_receive(pn_delivery_t *delivery) { pn_link_t *link = pn_delivery_link(delivery); ssize_t rc; qd_buffer_t *buf; qd_message_pvt_t *msg = (qd_message_pvt_t*) pn_delivery_get_context(delivery); // // If there is no message associated with the delivery, this is the first time // we've received anything on this delivery. Allocate a message descriptor and // link it and the delivery together. // if (!msg) { msg = (qd_message_pvt_t*) qd_message(); pn_delivery_set_context(delivery, (void*) msg); } // // Get a reference to the tail buffer on the message. This is the buffer into which // we will store incoming message data. If there is no buffer in the message, allocate // an empty one and add it to the message. // buf = DEQ_TAIL(msg->content->buffers); if (!buf) { buf = qd_buffer(); DEQ_INSERT_TAIL(msg->content->buffers, buf); } while (1) { // // Try to receive enough data to fill the remaining space in the tail buffer. // rc = pn_link_recv(link, (char*) qd_buffer_cursor(buf), qd_buffer_capacity(buf)); // // If we receive PN_EOS, we have come to the end of the message. // if (rc == PN_EOS) { // // If the last buffer in the list is empty, remove it and free it. This // will only happen if the size of the message content is an exact multiple // of the buffer size. // if (qd_buffer_size(buf) == 0) { DEQ_REMOVE_TAIL(msg->content->buffers); qd_buffer_free(buf); } pn_delivery_set_context(delivery, 0); char repr[qd_message_repr_len()]; qd_log(log_source, QD_LOG_TRACE, "Received %s on link %s", qd_message_repr((qd_message_t*)msg, repr, sizeof(repr)), pn_link_name(link)); return (qd_message_t*) msg; } if (rc > 0) { // // We have received a positive number of bytes for the message. Advance // the cursor in the buffer. // qd_buffer_insert(buf, rc); // // If the buffer is full, allocate a new empty buffer and append it to the // tail of the message's list. // if (qd_buffer_capacity(buf) == 0) { buf = qd_buffer(); DEQ_INSERT_TAIL(msg->content->buffers, buf); } } else // // We received zero bytes, and no PN_EOS. This means that we've received // all of the data available up to this point, but it does not constitute // the entire message. We'll be back later to finish it up. // break; } return 0; }