void qd_connection_manager_free(qd_connection_manager_t *cm)
{
    if (!cm) return;
    qd_listener_t *li = DEQ_HEAD(cm->listeners);
    while (li) {
        DEQ_REMOVE_HEAD(cm->listeners);
        qd_listener_decref(li);
        li = DEQ_HEAD(cm->listeners);
    }

    qd_connector_t *c = DEQ_HEAD(cm->connectors);
    while (c) {
        DEQ_REMOVE_HEAD(cm->connectors);
        qd_connector_decref(c);
        c = DEQ_HEAD(cm->connectors);
    }

    qd_config_ssl_profile_t *sslp = DEQ_HEAD(cm->config_ssl_profiles);
    while (sslp) {
        config_ssl_profile_free(cm, sslp);
        sslp = DEQ_HEAD(cm->config_ssl_profiles);
    }

    qd_config_sasl_plugin_t *saslp = DEQ_HEAD(cm->config_sasl_plugins);
    while (saslp) {
        config_sasl_plugin_free(cm, saslp);
        saslp = DEQ_HEAD(cm->config_sasl_plugins);
    }
}
void qd_connection_manager_free(qd_connection_manager_t *cm)
{
    if (!cm) return;
    qd_config_listener_t *cl = DEQ_HEAD(cm->config_listeners);
    while (cl) {
        DEQ_REMOVE_HEAD(cm->config_listeners);
        qd_server_config_free(&cl->configuration);
        qd_config_listener_free(cm, cl);
        cl = DEQ_HEAD(cm->config_listeners);
    }

    qd_config_connector_t *cc = DEQ_HEAD(cm->config_connectors);
    while (cc) {
        DEQ_REMOVE_HEAD(cm->config_connectors);
        qd_server_config_free(&cc->configuration);
        qd_config_connector_free(cm, cc);
        cc = DEQ_HEAD(cm->config_connectors);
    }

    qd_config_ssl_profile_t *sslp = DEQ_HEAD(cm->config_ssl_profiles);
    while (sslp) {
        qd_config_ssl_profile_free(cm, sslp);
        sslp = DEQ_HEAD(cm->config_ssl_profiles);
    }

    sys_mutex_free(cm->ssl_profile_lock);
}
void qd_connection_manager_free(qd_connection_manager_t *cm)
{
    if (!cm) return;
    qd_config_listener_t *cl = DEQ_HEAD(cm->config_listeners);
    while (cl) {
        DEQ_REMOVE_HEAD(cm->config_listeners);
        qd_server_listener_free(cl->listener);
        qd_server_config_free(&cl->configuration);
        free(cl);
        cl = DEQ_HEAD(cm->config_listeners);
    }

    qd_config_connector_t *cc = DEQ_HEAD(cm->config_connectors);
    while(cc) {
        DEQ_REMOVE_HEAD(cm->config_connectors);
        qd_server_connector_free(cc->connector);
        qd_server_config_free(&cc->configuration);
        free(cc);
        cc = DEQ_HEAD(cm->config_connectors);
    }

    qd_config_connector_t *odc = DEQ_HEAD(cm->on_demand_connectors);
    while(odc) {
        DEQ_REMOVE_HEAD(cm->on_demand_connectors);
        if (odc->connector)
            qd_server_connector_free(odc->connector);
        qd_server_config_free(&odc->configuration);
        free(odc);
        odc = DEQ_HEAD(cm->on_demand_connectors);
    }
}
Exemple #4
0
void dx_dealloc(dx_alloc_type_desc_t *desc, dx_alloc_pool_t **tpool, void *p)
{
    item_t          *item = ((item_t*) p) - 1;
    int              idx;

    //
    // If this is the thread's first pass through here, allocate the
    // thread-local pool for this type.
    //
    if (*tpool == 0) {
        *tpool = NEW(dx_alloc_pool_t);
        DEQ_INIT((*tpool)->free_list);
    }

    dx_alloc_pool_t *pool = *tpool;

    DEQ_INSERT_TAIL(pool->free_list, item);

    if (DEQ_SIZE(pool->free_list) <= desc->config->local_free_list_max)
        return;

    //
    // We've exceeded the maximum size of the local free list.  A batch must be
    // rebalanced back to the global list.
    //
    sys_mutex_lock(desc->lock);
    desc->stats->batches_rebalanced_to_global++;
    desc->stats->held_by_threads -= desc->config->transfer_batch_size;
    for (idx = 0; idx < desc->config->transfer_batch_size; idx++) {
        item = DEQ_HEAD(pool->free_list);
        DEQ_REMOVE_HEAD(pool->free_list);
        DEQ_INSERT_TAIL(desc->global_pool->free_list, item);
    }

    //
    // If there's a global_free_list size limit, remove items until the limit is
    // not exceeded.
    //
    if (desc->config->global_free_list_max != 0) {
        while (DEQ_SIZE(desc->global_pool->free_list) > desc->config->global_free_list_max) {
            item = DEQ_HEAD(desc->global_pool->free_list);
            DEQ_REMOVE_HEAD(desc->global_pool->free_list);
            free(item);
            desc->stats->total_free_to_heap++;
        }
    }

    sys_mutex_unlock(desc->lock);
}
Exemple #5
0
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);
    }
}
Exemple #7
0
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 void qd_iterator_free_hash_segments(qd_iterator_t *iter)
{
    qd_hash_segment_t *seg = DEQ_HEAD(iter->hash_segments);
    while (seg) {
        DEQ_REMOVE_HEAD(iter->hash_segments);
        free_qd_hash_segment_t(seg);
        seg = DEQ_HEAD(iter->hash_segments);
    }
}
Exemple #9
0
static int fire_head()
{
    sys_mutex_lock(lock);
    int         result = DEQ_SIZE(pending_timers);
    nx_timer_t *timer  = DEQ_HEAD(pending_timers);
    if (timer) {
        DEQ_REMOVE_HEAD(pending_timers);
        nx_timer_idle_LH(timer);
        fire_mask |= (unsigned long) timer->context;
    }
    sys_mutex_unlock(lock);
    return result;
}
Exemple #10
0
void qd_message_compose_3(qd_message_t *msg, qd_composed_field_t *field1, qd_composed_field_t *field2)
{
    qd_message_content_t *content        = MSG_CONTENT(msg);
    qd_buffer_list_t     *field1_buffers = qd_compose_buffers(field1);
    qd_buffer_list_t     *field2_buffers = qd_compose_buffers(field2);

    content->buffers = *field1_buffers;
    DEQ_INIT(*field1_buffers);

    qd_buffer_t *buf = DEQ_HEAD(*field2_buffers);
    while (buf) {
        DEQ_REMOVE_HEAD(*field2_buffers);
        DEQ_INSERT_TAIL(content->buffers, buf);
        buf = DEQ_HEAD(*field2_buffers);
    }
}
void *router_core_thread(void *arg)
{
    qdr_core_t        *core = (qdr_core_t*) arg;
    qdr_action_list_t  action_list;
    qdr_action_t      *action;

    qdr_forwarder_setup_CT(core);
    qdr_route_table_setup_CT(core);
    qdr_agent_setup_CT(core);

    qd_log(core->log, QD_LOG_INFO, "Router Core thread running. %s/%s", core->router_area, core->router_id);
    while (core->running) {
        //
        // Use the lock only to protect the condition variable and the action list
        //
        sys_mutex_lock(core->action_lock);

        //
        // Block on the condition variable when there is no action to do
        //
        while (core->running && DEQ_IS_EMPTY(core->action_list))
            sys_cond_wait(core->action_cond, core->action_lock);

        //
        // Move the entire action list to a private list so we can process it without
        // holding the lock
        //
        DEQ_MOVE(core->action_list, action_list);
        sys_mutex_unlock(core->action_lock);

        //
        // Process and free all of the action items in the list
        //
        action = DEQ_HEAD(action_list);
        while (action) {
            DEQ_REMOVE_HEAD(action_list);
            if (action->label)
                qd_log(core->log, QD_LOG_TRACE, "Core action '%s'%s", action->label, core->running ? "" : " (discard)");
            action->action_handler(core, action, !core->running);
            free_qdr_action_t(action);
            action = DEQ_HEAD(action_list);
        }
    }

    qd_log(core->log, QD_LOG_INFO, "Router Core thread exited");
    return 0;
}
Exemple #12
0
// Get events in the add/remove cache into a python list of (action, type, pointer)
// Locks the entity cache so entities can be updated safely (prevent entities from being deleted.)
// Do not processs any entities if return error code != 0
// Must call qd_entity_refresh_end when done, regardless of error code.
qd_error_t qd_entity_refresh_begin(PyObject *list) {
    if (!event_lock) return QD_ERROR_NONE;    /* Unit tests don't call qd_entity_cache_initialize */
    qd_error_clear();
    sys_mutex_lock(event_lock);
    entity_event_t *event = DEQ_HEAD(event_list);
    while (event) {
        PyObject *tuple = Py_BuildValue("(isl)", (int)event->action, event->type, (long)event->object);
        if (!tuple) { qd_error_py(); break; }
        int err = PyList_Append(list, tuple);
        Py_DECREF(tuple);
        if (err) { qd_error_py(); break; }
        DEQ_REMOVE_HEAD(event_list);
        free(event);
        event = DEQ_HEAD(event_list);
    }
    return qd_error_code();
}
Exemple #13
0
static void qdr_general_handler(void *context)
{
    qdr_core_t              *core = (qdr_core_t*) context;
    qdr_general_work_list_t  work_list;
    qdr_general_work_t      *work;

    sys_mutex_lock(core->work_lock);
    DEQ_MOVE(core->work_list, work_list);
    sys_mutex_unlock(core->work_lock);

    work = DEQ_HEAD(work_list);
    while (work) {
        DEQ_REMOVE_HEAD(work_list);
        work->handler(core, work);
        free_qdr_general_work_t(work);
        work = DEQ_HEAD(work_list);
    }
}
Exemple #14
0
void qd_hash_free(qd_hash_t *h)
{
    if (!h) return;
    qd_hash_item_t *item;
    int             idx;

    for (idx = 0; idx < h->bucket_count; idx++) {
        item = DEQ_HEAD(h->buckets[idx].items);
        while (item) {
            free(item->key);
            DEQ_REMOVE_HEAD(h->buckets[idx].items);
            free_qd_hash_item_t(item);
            item = DEQ_HEAD(h->buckets[idx].items);
        }
    }
    free(h->buckets);
    free(h);
}
Exemple #15
0
void work_queue_put(work_queue_t *w, pn_connector_t *conn)
{
    work_item_t *item;

    if (!w)
        return;
    if (DEQ_SIZE(w->free_list) == 0)
        allocate_batch(w);
    if (DEQ_SIZE(w->free_list) == 0)
        return;

    item = DEQ_HEAD(w->free_list);
    DEQ_REMOVE_HEAD(w->free_list);

    item->conn = conn;

    DEQ_INSERT_TAIL(w->items, item);
}
Exemple #16
0
pn_connector_t *work_queue_get(work_queue_t *w)
{
    work_item_t    *item;
    pn_connector_t *conn;

    if (!w)
        return 0;
    item = DEQ_HEAD(w->items);
    if (!item)
        return 0;

    DEQ_REMOVE_HEAD(w->items);
    conn = item->conn;
    item->conn = 0;

    DEQ_INSERT_TAIL(w->free_list, item);

    return conn;
}
Exemple #17
0
static void qdr_agent_response_handler(void *context)
{
    qdr_core_t  *core = (qdr_core_t*) context;
    qdr_query_t *query;
    bool         done = false;

    while (!done) {
        sys_mutex_lock(core->query_lock);
        query = DEQ_HEAD(core->outgoing_query_list);
        if (query)
            DEQ_REMOVE_HEAD(core->outgoing_query_list);
        done = DEQ_SIZE(core->outgoing_query_list) == 0;
        sys_mutex_unlock(core->query_lock);

        if (query) {
            bool more = query->more;
            core->agent_response_handler(query->context, &query->status, more);
            if (!more)
                qdr_query_free(query);
        }
    }
}
Exemple #18
0
void qd_parse_free(qd_parsed_field_t *field)
{
    if (!field)
        return;

    assert(field->parent == 0);
    if (field->raw_iter)
        qd_iterator_free(field->raw_iter);

    if (field->typed_iter)
        qd_iterator_free(field->typed_iter);

    qd_parsed_field_t *sub_field = DEQ_HEAD(field->children);
    while (sub_field) {
        qd_parsed_field_t *next = DEQ_NEXT(sub_field);
        DEQ_REMOVE_HEAD(field->children);
        sub_field->parent = 0;
        qd_parse_free(sub_field);
        sub_field = next;
    }

    free_qd_parsed_field_t(field);
}
Exemple #19
0
void qd_container_free(qd_container_t *container)
{
    if (!container) return;
    if (container->default_node)
        qd_container_destroy_node(container->default_node);

    qd_node_t *node = DEQ_HEAD(container->nodes);
    while (node) {
        qd_container_destroy_node(node);
        node = DEQ_HEAD(container->nodes);
    }

    qdc_node_type_t *nt = DEQ_HEAD(container->node_type_list);
    while (nt) {
        DEQ_REMOVE_HEAD(container->node_type_list);
        free(nt);
        nt = DEQ_HEAD(container->node_type_list);
    }
    qd_hash_free(container->node_map);
    qd_hash_free(container->node_type_map);
    sys_mutex_free(container->lock);
    free(container);
}
Exemple #20
0
/**
 * Outbound Delivery Handler
 */
static void router_tx_handler(void* context, dx_link_t *link, pn_delivery_t *delivery)
{
    dx_router_t      *router  = (dx_router_t*) context;
    pn_link_t        *pn_link = pn_delivery_link(delivery);
    dx_router_link_t *rlink   = (dx_router_link_t*) dx_link_get_context(link);
    dx_message_t     *msg;
    size_t            size;

    sys_mutex_lock(router->lock);
    msg = DEQ_HEAD(rlink->out_fifo);
    if (!msg) {
        // TODO - Recind the delivery
        sys_mutex_unlock(router->lock);
        return;
    }

    DEQ_REMOVE_HEAD(rlink->out_fifo);
    size = (DEQ_SIZE(rlink->out_fifo));
    sys_mutex_unlock(router->lock);

    dx_message_send(msg, pn_link);

    //
    // If there is no incoming delivery, it was pre-settled.  In this case,
    // we must pre-settle the outgoing delivery as well.
    //
    if (dx_message_in_delivery(msg)) {
        pn_delivery_set_context(delivery, (void*) msg);
        dx_message_set_out_delivery(msg, delivery);
    } else {
        pn_delivery_settle(delivery);
        dx_free_message(msg);
    }

    pn_link_advance(pn_link);
    pn_link_offered(pn_link, size);
}
Exemple #21
0
void *dx_alloc(dx_alloc_type_desc_t *desc, dx_alloc_pool_t **tpool)
{
    int idx;

    //
    // If the descriptor is not initialized, set it up now.
    //
    if (!desc->global_pool)
        dx_alloc_init(desc);

    //
    // If this is the thread's first pass through here, allocate the
    // thread-local pool for this type.
    //
    if (*tpool == 0) {
        *tpool = NEW(dx_alloc_pool_t);
        DEQ_INIT((*tpool)->free_list);
    }

    dx_alloc_pool_t *pool = *tpool;

    //
    // Fast case: If there's an item on the local free list, take it off the
    // list and return it.  Since everything we've touched is thread-local,
    // there is no need to acquire a lock.
    //
    item_t *item = DEQ_HEAD(pool->free_list);
    if (item) {
        DEQ_REMOVE_HEAD(pool->free_list);
        return &item[1];
    }

    //
    // The local free list is empty, we need to either rebalance a batch
    // of items from the global list or go to the heap to get new memory.
    //
    sys_mutex_lock(desc->lock);
    if (DEQ_SIZE(desc->global_pool->free_list) >= desc->config->transfer_batch_size) {
        //
        // Rebalance a full batch from the global free list to the thread list.
        //
        desc->stats->batches_rebalanced_to_threads++;
        desc->stats->held_by_threads += desc->config->transfer_batch_size;
        for (idx = 0; idx < desc->config->transfer_batch_size; idx++) {
            item = DEQ_HEAD(desc->global_pool->free_list);
            DEQ_REMOVE_HEAD(desc->global_pool->free_list);
            DEQ_INSERT_TAIL(pool->free_list, item);
        }
    } else {
        //
        // Allocate a full batch from the heap and put it on the thread list.
        //
        for (idx = 0; idx < desc->config->transfer_batch_size; idx++) {
            item = (item_t*) malloc(sizeof(item_t) + desc->total_size);
            if (item == 0)
                break;
            DEQ_ITEM_INIT(item);
            item->desc = desc;
            DEQ_INSERT_TAIL(pool->free_list, item);
            desc->stats->held_by_threads++;
            desc->stats->total_alloc_from_heap++;
        }
    }
    sys_mutex_unlock(desc->lock);

    item = DEQ_HEAD(pool->free_list);
    if (item) {
        DEQ_REMOVE_HEAD(pool->free_list);
        return &item[1];
    }

    return 0;
}
Exemple #22
0
static void qd_log_source_free_lh(qd_log_source_t* src) {
    DEQ_REMOVE_HEAD(source_list);
    log_sink_free_lh(src->sink);
    free(src->module);
    free(src);
}
Exemple #23
0
static char* test_deq_basic(void *context)
{
    item_list_t  list;
    item_t       item[10];
    item_t      *ptr;
    int          idx;
    char        *subtest;

    DEQ_INIT(list);
    if (DEQ_SIZE(list) != 0) return "Expected zero initial size";

    for (idx = 0; idx < 10; idx++) {
        DEQ_ITEM_INIT(&item[idx]);
        item[idx].letter = 'A' + idx;
        DEQ_INSERT_TAIL(list, &item[idx]);
    }
    if (DEQ_SIZE(list) != 10) return "Expected 10 items in list";

    ptr = DEQ_HEAD(list);
    if (!ptr)               return "Expected valid head item";
    if (DEQ_PREV(ptr))      return "Head item has non-null previous link";
    if (ptr->letter != 'A') return "Expected item A at the head";
    if (DEQ_NEXT(ptr) == 0) return "Head item has null next link";
    subtest = list_well_formed(list, "ABCDEFGHIJ");
    if (subtest) return subtest;

    DEQ_REMOVE_HEAD(list);
    if (DEQ_SIZE(list) != 9) return "Expected 9 items in list";
    ptr = DEQ_HEAD(list);
    if (ptr->letter != 'B')  return "Expected item B at the head";
    subtest = list_well_formed(list, "BCDEFGHIJ");
    if (subtest) return subtest;

    DEQ_REMOVE_TAIL(list);
    if (DEQ_SIZE(list) != 8) return "Expected 8 items in list";
    ptr = DEQ_TAIL(list);
    if (ptr->letter != 'I')  return "Expected item I at the tail";
    subtest = list_well_formed(list, "BCDEFGHI");
    if (subtest) return subtest;

    DEQ_REMOVE(list, &item[4]);
    if (DEQ_SIZE(list) != 7) return "Expected 7 items in list";
    subtest = list_well_formed(list, "BCDFGHI");
    if (subtest) return subtest;

    DEQ_REMOVE(list, &item[1]);
    if (DEQ_SIZE(list) != 6) return "Expected 6 items in list";
    subtest = list_well_formed(list, "CDFGHI");
    if (subtest) return subtest;

    DEQ_REMOVE(list, &item[8]);
    if (DEQ_SIZE(list) != 5) return "Expected 5 items in list";
    subtest = list_well_formed(list, "CDFGH");
    if (subtest) return subtest;

    DEQ_INSERT_HEAD(list, &item[8]);
    if (DEQ_SIZE(list) != 6) return "Expected 6 items in list";
    ptr = DEQ_HEAD(list);
    if (ptr->letter != 'I')  return "Expected item I at the head";
    subtest = list_well_formed(list, "ICDFGH");
    if (subtest) return subtest;

    DEQ_INSERT_AFTER(list, &item[4], &item[7]);
    if (DEQ_SIZE(list) != 7) return "Expected 7 items in list";
    ptr = DEQ_TAIL(list);
    if (ptr->letter != 'E')  return "Expected item E at the head";
    subtest = list_well_formed(list, "ICDFGHE");
    if (subtest) return subtest;

    DEQ_INSERT_AFTER(list, &item[1], &item[5]);
    if (DEQ_SIZE(list) != 8) return "Expected 8 items in list";
    subtest = list_well_formed(list, "ICDFBGHE");
    if (subtest) return subtest;

    if (item[0].prev || item[0].next) return "Unlisted item A has non-null pointers";
    if (item[9].prev || item[9].next) return "Unlisted item J has non-null pointers";

    return 0;
}
Exemple #24
0
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;
}
Exemple #25
0
const char *qd_parse_turbo(qd_iterator_t          *iter,
                           qd_parsed_turbo_list_t *annos,
                           uint32_t               *user_entries,
                           uint32_t               *user_bytes)
{
    if (!iter || !annos || !user_entries || !user_bytes)
        return  "missing argument";

    DEQ_INIT(*annos);
    *user_entries = 0;
    *user_bytes = 0;

    // The iter is addressing the message-annotations map.
    // Open the field describing the map's items
    uint8_t  tag             = 0;
    uint32_t size            = 0;
    uint32_t count           = 0;
    uint32_t length_of_count = 0;
    uint32_t length_of_size  = 0;
    const char * parse_error = get_type_info(iter, &tag, &size, &count, &length_of_size, &length_of_count);

    if (parse_error)
        return parse_error;

    if (count == 0)
        return 0;

    int n_allocs = 0;

    // Do skeletal parse of each map element
    for (uint32_t idx = 0; idx < count; idx++) {
        qd_parsed_turbo_t *turbo;
        if (n_allocs < QD_MA_FILTER_LEN * 2) {
            turbo = new_qd_parsed_turbo_t();
            n_allocs++;

        } else {
            // Retire an existing element.
            // If there are this many in the list then this one cannot be a
            // router annotation and must be a user annotation.
            turbo = DEQ_HEAD(*annos);
            *user_entries += 1;
            *user_bytes += sizeof(turbo->tag) + turbo->size + turbo->length_of_size;
            DEQ_REMOVE_HEAD(*annos);
        }
        if (!turbo)
            return "failed to allocate qd_parsed_turbo_t";
        ZERO(turbo);

        // Get the buffer pointers for the map element
        qd_iterator_get_view_cursor(iter, &turbo->bufptr);

        // Get description of the map element
        parse_error = get_type_info(iter, &turbo->tag, &turbo->size, &turbo->count,
                                    &turbo->length_of_size, &turbo->length_of_count);
        if (parse_error) {
            return parse_error;
        }

        // Save parsed element
        DEQ_INSERT_TAIL(*annos, turbo);

        // Advance map iterator to next map element
        qd_iterator_advance(iter, turbo->size - turbo->length_of_count);
    }

    // remove leading annos in the queue if their prefix is not a match and
    // return them as part of the user annotations
    for (int idx=0; idx < n_allocs; idx += 2) {
        qd_parsed_turbo_t *turbo = DEQ_HEAD(*annos);
        assert(turbo);
        if (qd_iterator_prefix_ptr(&turbo->bufptr, turbo->length_of_size + 1, QD_MA_PREFIX))
            break;

        // leading anno is a user annotation map key
        // remove the key and value from the list and accumulate them as user items
        *user_bytes += sizeof(turbo->tag) + turbo->size + turbo->length_of_size;
        DEQ_REMOVE_HEAD(*annos);
        free_qd_parsed_turbo_t(turbo);

        turbo = DEQ_HEAD(*annos);
        assert(turbo);
        *user_bytes += sizeof(turbo->tag) + turbo->size + turbo->length_of_size;
        DEQ_REMOVE_HEAD(*annos);
        free_qd_parsed_turbo_t(turbo);

        *user_entries += 2;
    }
    return parse_error;
}
Exemple #26
0
void qdr_core_free(qdr_core_t *core)
{
    //
    // Stop and join the thread
    //
    core->running = false;
    sys_cond_signal(core->action_cond);
    sys_thread_join(core->thread);

    // Drain the general work lists
    qdr_general_handler(core);

    //
    // Free the core resources
    //
    sys_thread_free(core->thread);
    sys_cond_free(core->action_cond);
    sys_mutex_free(core->action_lock);
    sys_mutex_free(core->work_lock);
    sys_mutex_free(core->id_lock);
    qd_timer_free(core->work_timer);

    //we can't call qdr_core_unsubscribe on the subscriptions because the action processing thread has
    //already been shut down. But, all the action would have done at this point is free the subscriptions
    //so we just do that directly.
    free(core->agent_subscription_mobile);
    free(core->agent_subscription_local);

    for (int i = 0; i <= QD_TREATMENT_LINK_BALANCED; ++i) {
        if (core->forwarders[i]) {
            free(core->forwarders[i]);
        }
    }

    qdr_link_route_t *link_route = 0;
    while ( (link_route = DEQ_HEAD(core->link_routes))) {
        DEQ_REMOVE_HEAD(core->link_routes);
        qdr_core_delete_link_route(core, link_route);
    }

    qdr_auto_link_t *auto_link = 0;
    while ( (auto_link = DEQ_HEAD(core->auto_links))) {
        DEQ_REMOVE_HEAD(core->auto_links);
        qdr_core_delete_auto_link(core, auto_link);
    }

    qdr_exchange_free_all(core);

    qdr_address_t *addr = 0;
    while ( (addr = DEQ_HEAD(core->addrs)) ) {
        qdr_core_remove_address(core, addr);
    }
    qdr_address_config_t *addr_config = 0;
    while ( (addr_config = DEQ_HEAD(core->addr_config))) {
        qdr_core_remove_address_config(core, addr_config);
    }
    qd_hash_free(core->addr_hash);
    qd_parse_tree_free(core->addr_parse_tree);
    qd_parse_tree_free(core->link_route_tree[QD_INCOMING]);
    qd_parse_tree_free(core->link_route_tree[QD_OUTGOING]);

    qdr_node_t *rnode = 0;
    while ( (rnode = DEQ_HEAD(core->routers)) ) {
        qdr_router_node_free(core, rnode);
    }

    qdr_link_t *link = DEQ_HEAD(core->open_links);
    while (link) {
        DEQ_REMOVE_HEAD(core->open_links);
        if (link->core_endpoint)
            qdrc_endpoint_do_cleanup_CT(core, link->core_endpoint);
        qdr_del_link_ref(&link->conn->links, link, QDR_LINK_LIST_CLASS_CONNECTION);
        qdr_del_link_ref(&link->conn->links_with_work[link->priority], link, QDR_LINK_LIST_CLASS_WORK);
        free(link->name);
        free(link->disambiguated_name);
        free(link->terminus_addr);
        free(link->ingress_histogram);
        free(link->insert_prefix);
        free(link->strip_prefix);
        link->name = 0;
        free_qdr_link_t(link);
        link = DEQ_HEAD(core->open_links);
    }

    qdr_connection_t *conn = DEQ_HEAD(core->open_connections);
    while (conn) {
        DEQ_REMOVE_HEAD(core->open_connections);

        if (conn->conn_id) {
            qdr_del_connection_ref(&conn->conn_id->connection_refs, conn);
            qdr_route_check_id_for_deletion_CT(core, conn->conn_id);
        }

        qdr_connection_work_t *work = DEQ_HEAD(conn->work_list);
        while (work) {
            DEQ_REMOVE_HEAD(conn->work_list);
            qdr_connection_work_free_CT(work);
            work = DEQ_HEAD(conn->work_list);
        }

        qdr_connection_free(conn);
        conn = DEQ_HEAD(core->open_connections);
    }

    // at this point all the conn identifiers have been freed
    qd_hash_free(core->conn_id_hash);

    qdr_modules_finalize(core);

    if (core->query_lock)                sys_mutex_free(core->query_lock);
    if (core->routers_by_mask_bit)       free(core->routers_by_mask_bit);
    if (core->control_links_by_mask_bit) free(core->control_links_by_mask_bit);
    if (core->data_links_by_mask_bit)    free(core->data_links_by_mask_bit);
    if (core->neighbor_free_mask)        qd_bitmask_free(core->neighbor_free_mask);

    free(core);
}
Exemple #27
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;
}