void qdr_route_table_setup_CT(qdr_core_t *core) { DEQ_INIT(core->addrs); DEQ_INIT(core->routers); core->addr_hash = qd_hash(12, 32, 0); core->conn_id_hash = qd_hash(6, 4, 0); if (core->router_mode == QD_ROUTER_MODE_INTERIOR) { core->hello_addr = qdr_add_local_address_CT(core, 'L', "qdhello", QD_TREATMENT_MULTICAST_FLOOD); core->router_addr_L = qdr_add_local_address_CT(core, 'L', "qdrouter", QD_TREATMENT_MULTICAST_FLOOD); core->routerma_addr_L = qdr_add_local_address_CT(core, 'L', "qdrouter.ma", QD_TREATMENT_MULTICAST_ONCE); core->router_addr_T = qdr_add_local_address_CT(core, 'T', "qdrouter", QD_TREATMENT_MULTICAST_FLOOD); core->routerma_addr_T = qdr_add_local_address_CT(core, 'T', "qdrouter.ma", QD_TREATMENT_MULTICAST_ONCE); core->neighbor_free_mask = qd_bitmask(1); core->routers_by_mask_bit = NEW_PTR_ARRAY(qdr_node_t, qd_bitmask_width()); core->control_links_by_mask_bit = NEW_PTR_ARRAY(qdr_link_t, qd_bitmask_width()); core->data_links_by_mask_bit = NEW_PTR_ARRAY(qdr_link_t, qd_bitmask_width()); for (int idx = 0; idx < qd_bitmask_width(); idx++) { core->routers_by_mask_bit[idx] = 0; core->control_links_by_mask_bit[idx] = 0; core->data_links_by_mask_bit[idx] = 0; } } }
qd_message_t *qd_message() { qd_message_pvt_t *msg = (qd_message_pvt_t*) new_qd_message_t(); if (!msg) return 0; DEQ_ITEM_INIT(msg); DEQ_INIT(msg->ma_to_override); DEQ_INIT(msg->ma_trace); DEQ_INIT(msg->ma_ingress); msg->content = new_qd_message_content_t(); if (msg->content == 0) { free_qd_message_t((qd_message_t*) msg); return 0; } memset(msg->content, 0, sizeof(qd_message_content_t)); msg->content->lock = sys_mutex(); msg->content->ref_count = 1; msg->content->parse_depth = QD_DEPTH_NONE; msg->content->parsed_message_annotations = 0; return (qd_message_t*) msg; }
dx_router_t *dx_router(dx_dispatch_t *dx) { if (!type_registered) { type_registered = 1; dx_container_register_node_type(dx, &router_node); } dx_router_t *router = NEW(dx_router_t); dx_container_set_default_node_type(dx, &router_node, (void*) router, DX_DIST_BOTH); DEQ_INIT(router->in_links); DEQ_INIT(router->out_links); DEQ_INIT(router->in_fifo); router->dx = dx; router->lock = sys_mutex(); router->timer = dx_timer(dx, dx_router_timer_handler, (void*) router); dx_timer_schedule(router->timer, 0); // Immediate router->out_hash = hash(10, 32, 0); router->dtag = 1; return router; }
qdr_core_t *qdr_core(qd_dispatch_t *qd, qd_router_mode_t mode, const char *area, const char *id) { qdr_core_t *core = NEW(qdr_core_t); ZERO(core); core->qd = qd; core->router_mode = mode; core->router_area = area; core->router_id = id; // // Set up the logging sources for the router core // core->log = qd_log_source("ROUTER_CORE"); core->agent_log = qd_log_source("AGENT"); // // Report on the configuration for unsettled multicasts // qd_log(core->log, QD_LOG_INFO, "Allow Unsettled Multicast: %s", qd->allow_unsettled_multicast ? "yes" : "no"); // // Set up the threading support // core->action_cond = sys_cond(); core->action_lock = sys_mutex(); core->running = true; DEQ_INIT(core->action_list); core->work_lock = sys_mutex(); DEQ_INIT(core->work_list); core->work_timer = qd_timer(core->qd, qdr_general_handler, core); // // Set up the unique identifier generator // core->next_identifier = 1; core->id_lock = sys_mutex(); // // Launch the core thread // core->thread = sys_thread(router_core_thread, core); // // Perform outside-of-thread setup for the management agent // core->agent_subscription_mobile = qdr_core_subscribe(core, "$management", 'M', '0', QD_TREATMENT_ANYCAST_CLOSEST, qdr_management_agent_on_message, core); core->agent_subscription_local = qdr_core_subscribe(core, "$management", 'L', '0', QD_TREATMENT_ANYCAST_CLOSEST, qdr_management_agent_on_message, core); return core; }
work_queue_t *work_queue(void) { work_queue_t *w = NEW(work_queue_t); if (!w) return 0; DEQ_INIT(w->items); DEQ_INIT(w->free_list); allocate_batch(w); return w; }
qd_connection_manager_t *qd_connection_manager(qd_dispatch_t *qd) { qd_connection_manager_t *cm = NEW(qd_connection_manager_t); if (!cm) return 0; cm->log_source = qd_log_source("CONN_MGR"); cm->server = qd->server; DEQ_INIT(cm->config_listeners); DEQ_INIT(cm->config_connectors); DEQ_INIT(cm->on_demand_connectors); return cm; }
qd_connection_manager_t *qd_connection_manager(qd_dispatch_t *qd) { qd_connection_manager_t *cm = NEW(qd_connection_manager_t); if (!cm) return 0; cm->log_source = qd_log_source("CONN_MGR"); cm->ssl_profile_lock = sys_mutex(); cm->server = qd->server; DEQ_INIT(cm->config_listeners); DEQ_INIT(cm->config_connectors); DEQ_INIT(cm->config_ssl_profiles); return cm; }
static void dx_alloc_init(dx_alloc_type_desc_t *desc) { sys_mutex_lock(init_lock); desc->total_size = desc->type_size; if (desc->additional_size) desc->total_size += *desc->additional_size; //dx_log("ALLOC", LOG_TRACE, "Initialized Allocator - type=%s type-size=%d total-size=%d", // desc->type_name, desc->type_size, desc->total_size); if (!desc->global_pool) { if (desc->config == 0) desc->config = desc->total_size > 256 ? &dx_alloc_default_config_big : &dx_alloc_default_config_small; assert (desc->config->local_free_list_max >= desc->config->transfer_batch_size); desc->global_pool = NEW(dx_alloc_pool_t); DEQ_INIT(desc->global_pool->free_list); desc->lock = sys_mutex(); desc->stats = NEW(dx_alloc_stats_t); memset(desc->stats, 0, sizeof(dx_alloc_stats_t)); } item_t *type_item = NEW(item_t); DEQ_ITEM_INIT(type_item); type_item->desc = desc; DEQ_INSERT_TAIL(type_list, type_item); sys_mutex_unlock(init_lock); }
unsigned int qd_buffer_list_clone(qd_buffer_list_t *dst, const qd_buffer_list_t *src) { uint32_t len = 0; DEQ_INIT(*dst); qd_buffer_t *buf = DEQ_HEAD(*src); while (buf) { size_t to_copy = qd_buffer_size(buf); unsigned char *src = qd_buffer_base(buf); len += to_copy; while (to_copy) { qd_buffer_t *newbuf = qd_buffer(); size_t count = qd_buffer_capacity(newbuf); // default buffer capacity may have changed, // so don't assume it will fit: if (count > to_copy) count = to_copy; memcpy(qd_buffer_cursor(newbuf), src, count); qd_buffer_insert(newbuf, count); DEQ_INSERT_TAIL(*dst, newbuf); src += count; to_copy -= count; } buf = DEQ_NEXT(buf); } return len; }
/** * New Outgoing Link Handler */ static int router_outgoing_link_handler(void* context, dx_link_t *link) { dx_router_t *router = (dx_router_t*) context; pn_link_t *pn_link = dx_link_pn(link); const char *r_tgt = pn_terminus_get_address(pn_link_remote_target(pn_link)); sys_mutex_lock(router->lock); dx_router_link_t *rlink = new_dx_router_link_t(); rlink->link = link; DEQ_INIT(rlink->out_fifo); dx_link_set_context(link, rlink); dx_field_iterator_t *iter = dx_field_iterator_string(r_tgt, ITER_VIEW_NO_HOST); int result = hash_insert(router->out_hash, iter, rlink); dx_field_iterator_free(iter); if (result == 0) { pn_terminus_copy(pn_link_source(pn_link), pn_link_remote_source(pn_link)); pn_terminus_copy(pn_link_target(pn_link), pn_link_remote_target(pn_link)); pn_link_open(pn_link); sys_mutex_unlock(router->lock); dx_log(module, LOG_TRACE, "Registered new local address: %s", r_tgt); return 0; } dx_log(module, LOG_TRACE, "Address '%s' not registered as it already exists", r_tgt); pn_link_close(pn_link); sys_mutex_unlock(router->lock); return 0; }
void qd_message_compose_2(qd_message_t *msg, qd_composed_field_t *field) { qd_message_content_t *content = MSG_CONTENT(msg); qd_buffer_list_t *field_buffers = qd_compose_buffers(field); content->buffers = *field_buffers; DEQ_INIT(*field_buffers); // Zero out the linkage to the now moved buffers. }
qd_container_t *qd_container(qd_dispatch_t *qd) { qd_container_t *container = NEW(qd_container_t); container->qd = qd; container->log_source = qd_log_source("CONTAINER"); container->server = qd->server; container->node_type_map = qd_hash(6, 4, 1); // 64 buckets, item batches of 4 container->node_map = qd_hash(10, 32, 0); // 1K buckets, item batches of 32 container->lock = sys_mutex(); container->default_node = 0; DEQ_INIT(container->nodes); DEQ_INIT(container->node_type_list); qd_server_set_conn_handler(qd, handler, pn_event_handler, container); qd_log(container->log_source, QD_LOG_TRACE, "Container Initialized"); return container; }
void qd_log_initialize(void) { DEQ_INIT(entries); DEQ_INIT(source_list); DEQ_INIT(sink_list); // Set up level_names for use in error messages. ZERO((char*)level_names); char *begin = (char*)level_names, *end = (char*)level_names+sizeof(level_names); aprintf(&begin, end, "%s", levels[NONE].name); for (level_index_t i = NONE + 1; i < N_LEVELS; ++i) aprintf(&begin, end, ", %s", levels[i].name); log_lock = sys_mutex(); log_source_lock = sys_mutex(); default_log_source = qd_log_source(SOURCE_DEFAULT); default_log_source->mask = levels[INFO].mask; default_log_source->timestamp = true; default_log_source->source = 0; default_log_source->sink = log_sink_lh(SINK_STDERR); logging_log_source = qd_log_source(SOURCE_LOGGING); }
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); }
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); } }
int timer_tests(void) { int result = 0; fire_mask = 0; DEQ_INIT(pending_timers); lock = sys_mutex(); nx_timer_initialize(lock); time = 1; timers[0] = nx_timer(0, (void*) 0x00000001); timers[1] = nx_timer(0, (void*) 0x00000002); timers[2] = nx_timer(0, (void*) 0x00000004); timers[3] = nx_timer(0, (void*) 0x00000008); timers[4] = nx_timer(0, (void*) 0x00000010); timers[5] = nx_timer(0, (void*) 0x00000020); timers[6] = nx_timer(0, (void*) 0x00000040); timers[7] = nx_timer(0, (void*) 0x00000080); timers[8] = nx_timer(0, (void*) 0x00000100); timers[9] = nx_timer(0, (void*) 0x00000200); timers[10] = nx_timer(0, (void*) 0x00000400); timers[11] = nx_timer(0, (void*) 0x00000800); timers[12] = nx_timer(0, (void*) 0x00001000); timers[13] = nx_timer(0, (void*) 0x00002000); timers[14] = nx_timer(0, (void*) 0x00004000); timers[15] = nx_timer(0, (void*) 0x00008000); TEST_CASE(test_quiet, 0); TEST_CASE(test_immediate, 0); TEST_CASE(test_immediate_plus_delayed, 0); TEST_CASE(test_single, 0); TEST_CASE(test_two_inorder, 0); TEST_CASE(test_two_reverse, 0); TEST_CASE(test_two_duplicate, 0); TEST_CASE(test_separated, 0); TEST_CASE(test_big, 0); int i; for (i = 0; i < 16; i++) nx_timer_free(timers[i]); nx_timer_finalize(); return result; }
qd_field_iterator_t* qd_address_iterator_binary(const char *text, int length, qd_iterator_view_t view) { qd_field_iterator_t *iter = new_qd_field_iterator_t(); if (!iter) return 0; iter->start_pointer.buffer = 0; iter->start_pointer.cursor = (unsigned char*) text; iter->start_pointer.length = length; iter->phase = '0'; iter->prefix_override = '\0'; DEQ_INIT(iter->hash_segments); qd_address_iterator_reset_view(iter, view); return iter; }
qd_field_iterator_t *qd_address_iterator_buffer(qd_buffer_t *buffer, int offset, int length, qd_iterator_view_t view) { qd_field_iterator_t *iter = new_qd_field_iterator_t(); if (!iter) return 0; iter->start_pointer.buffer = buffer; iter->start_pointer.cursor = qd_buffer_base(buffer) + offset; iter->start_pointer.length = length; iter->phase = '0'; iter->prefix_override = '\0'; DEQ_INIT(iter->hash_segments); qd_address_iterator_reset_view(iter, view); return iter; }
hash_t *hash(int bucket_exponent, int batch_size, int value_is_const) { int i; hash_t *h = NEW(hash_t); if (!h) return 0; h->bucket_count = 1 << bucket_exponent; h->bucket_mask = h->bucket_count - 1; h->batch_size = batch_size; h->size = 0; h->is_const = value_is_const; h->buckets = NEW_ARRAY(bucket_t, h->bucket_count); for (i = 0; i < h->bucket_count; i++) { DEQ_INIT(h->buckets[i].items); } return h; }
qd_field_iterator_t *qd_field_iterator_sub(const qd_field_iterator_t *iter, uint32_t length) { qd_field_iterator_t *sub = new_qd_field_iterator_t(); if (!sub) return 0; sub->start_pointer = iter->pointer; sub->start_pointer.length = length; sub->view_start_pointer = sub->start_pointer; sub->pointer = sub->start_pointer; sub->view = iter->view; sub->mode = iter->mode; sub->state = STATE_IN_ADDRESS; sub->view_prefix = false; sub->prefix_override = '\0'; sub->phase = '0'; DEQ_INIT(sub->hash_segments); return sub; }
static qd_parsed_field_t *qd_parse_internal(qd_iterator_t *iter, qd_parsed_field_t *p) { qd_parsed_field_t *field = new_qd_parsed_field_t(); if (!field) return 0; DEQ_ITEM_INIT(field); DEQ_INIT(field->children); field->parent = p; field->raw_iter = 0; field->typed_iter = qd_iterator_dup(iter); uint32_t size = 0; uint32_t count = 0; uint32_t length_of_count = 0; uint32_t length_of_size = 0; field->parse_error = get_type_info(iter, &field->tag, &size, &count, &length_of_size, &length_of_count); if (!field->parse_error) { qd_iterator_trim_view(field->typed_iter, size + length_of_size + 1); // + 1 accounts for the tag length field->raw_iter = qd_iterator_sub(iter, size - length_of_count); qd_iterator_advance(iter, size - length_of_count); for (uint32_t idx = 0; idx < count; idx++) { qd_parsed_field_t *child = qd_parse_internal(field->raw_iter, field); DEQ_INSERT_TAIL(field->children, child); if (!qd_parse_ok(child)) { field->parse_error = child->parse_error; break; } } } return field; }
void qdr_agent_setup_CT(qdr_core_t *core) { DEQ_INIT(core->outgoing_query_list); core->query_lock = sys_mutex(); core->agent_timer = qd_timer(core->qd, qdr_agent_response_handler, core); }
void qd_message_send(qd_message_t *in_msg, qd_link_t *link, bool strip_annotations) { qd_message_pvt_t *msg = (qd_message_pvt_t*) in_msg; qd_message_content_t *content = msg->content; qd_buffer_t *buf = DEQ_HEAD(content->buffers); unsigned char *cursor; pn_link_t *pnl = qd_link_pn(link); char repr[qd_message_repr_len()]; qd_log(log_source, QD_LOG_TRACE, "Sending %s on link %s", qd_message_repr(in_msg, repr, sizeof(repr)), pn_link_name(pnl)); qd_buffer_list_t new_ma; DEQ_INIT(new_ma); if (strip_annotations || compose_message_annotations(msg, &new_ma)) { // // This is the case where the message annotations have been modified. // The message send must be divided into sections: The existing header; // the new message annotations; the rest of the existing message. // Note that the original message annotations that are still in the // buffer chain must not be sent. // // Start by making sure that we've parsed the message sections through // the message annotations // // ??? NO LONGER NECESSARY??? if (!qd_message_check(in_msg, QD_DEPTH_MESSAGE_ANNOTATIONS)) { qd_log(log_source, QD_LOG_ERROR, "Cannot send: %s", qd_error_message); return; } // // Send header if present // cursor = qd_buffer_base(buf); if (content->section_message_header.length > 0) { buf = content->section_message_header.buffer; cursor = content->section_message_header.offset + qd_buffer_base(buf); advance(&cursor, &buf, content->section_message_header.length + content->section_message_header.hdr_length, send_handler, (void*) pnl); } // // Send new message annotations // qd_buffer_t *da_buf = DEQ_HEAD(new_ma); while (da_buf) { pn_link_send(pnl, (char*) qd_buffer_base(da_buf), qd_buffer_size(da_buf)); da_buf = DEQ_NEXT(da_buf); } qd_buffer_list_free_buffers(&new_ma); // // Skip over replaced message annotations // if (content->section_message_annotation.length > 0) advance(&cursor, &buf, content->section_message_annotation.hdr_length + content->section_message_annotation.length, 0, 0); // // Send remaining partial buffer // if (buf) { size_t len = qd_buffer_size(buf) - (cursor - qd_buffer_base(buf)); advance(&cursor, &buf, len, send_handler, (void*) pnl); } // Fall through to process the remaining buffers normally // Note that 'advance' will have moved us to the next buffer in the chain. } while (buf) { pn_link_send(pnl, (char*) qd_buffer_base(buf), qd_buffer_size(buf)); buf = DEQ_NEXT(buf); } }
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; }
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_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; }
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; }
void dx_alloc_initialize(void) { init_lock = sys_mutex(); DEQ_INIT(type_list); }
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; }
void qd_entity_cache_initialize(void) { event_lock = sys_mutex(); DEQ_INIT(event_list); }