static void test_list_refcount(size_t capacity) { void *one = pn_class_new(PN_OBJECT, 0); void *two = pn_class_new(PN_OBJECT, 0); void *three = pn_class_new(PN_OBJECT, 0); void *four = pn_class_new(PN_OBJECT, 0); pn_list_t *list = pn_list(PN_OBJECT, 0); assert(!pn_list_add(list, one)); assert(!pn_list_add(list, two)); assert(!pn_list_add(list, three)); assert(!pn_list_add(list, four)); assert(pn_list_get(list, 0) == one); assert(pn_list_get(list, 1) == two); assert(pn_list_get(list, 2) == three); assert(pn_list_get(list, 3) == four); assert(pn_list_size(list) == 4); assert(pn_refcount(one) == 2); assert(pn_refcount(two) == 2); assert(pn_refcount(three) == 2); assert(pn_refcount(four) == 2); pn_list_del(list, 1, 2); assert(pn_list_size(list) == 2); assert(pn_refcount(one) == 2); assert(pn_refcount(two) == 1); assert(pn_refcount(three) == 1); assert(pn_refcount(four) == 2); assert(pn_list_get(list, 0) == one); assert(pn_list_get(list, 1) == four); assert(!pn_list_add(list, one)); assert(pn_list_size(list) == 3); assert(pn_refcount(one) == 3); pn_decref(list); assert(pn_refcount(one) == 1); assert(pn_refcount(two) == 1); assert(pn_refcount(three) == 1); assert(pn_refcount(four) == 1); pn_decref(one); pn_decref(two); pn_decref(three); pn_decref(four); }
void pn_selector_add(pn_selector_t *selector, pn_selectable_t *selectable) { assert(selector); assert(selectable); assert(pni_selectable_get_index(selectable) < 0); pn_socket_t sock = pn_selectable_get_fd(selectable); iocpdesc_t *iocpd = NULL; if (pni_selectable_get_index(selectable) < 0) { pn_list_add(selector->selectables, selectable); pn_list_add(selector->iocp_descriptors, NULL); size_t size = pn_list_size(selector->selectables); pni_selectable_set_index(selectable, size - 1); } pn_selector_update(selector, selectable); }
void pn_transform_rule(pn_transform_t *transform, const char *pattern, const char *substitution) { assert(transform); pn_rule_t *rule = pn_rule(pattern, substitution); pn_list_add(transform->rules, rule); pn_decref(rule); }
static void test_list(size_t capacity) { pn_list_t *list = pn_list(PN_WEAKREF, 0); assert(pn_list_size(list) == 0); assert(!pn_list_add(list, (void *) 0)); assert(!pn_list_add(list, (void *) 1)); assert(!pn_list_add(list, (void *) 2)); assert(!pn_list_add(list, (void *) 3)); assert(pn_list_get(list, 0) == (void *) 0); assert(pn_list_get(list, 1) == (void *) 1); assert(pn_list_get(list, 2) == (void *) 2); assert(pn_list_get(list, 3) == (void *) 3); assert(pn_list_size(list) == 4); pn_list_del(list, 1, 2); assert(pn_list_size(list) == 2); assert(pn_list_get(list, 0) == (void *) 0); assert(pn_list_get(list, 1) == (void *) 3); pn_decref(list); }
pn_connection_t *pn_reactor_connection(pn_reactor_t *reactor, pn_handler_t *handler) { assert(reactor); pn_connection_t *connection = pn_connection(); pn_record_t *record = pn_connection_attachments(connection); pn_record_set_handler(record, handler); pn_connection_collect(connection, pn_reactor_collector(reactor)); pn_list_add(pn_reactor_children(reactor), connection); pni_record_init_reactor(record, reactor); pn_decref(connection); return connection; }
static pn_list_t *iocp_map_close_all(iocp_t *iocp) { // Zombify stragglers, i.e. no pn_close() from the application. pn_list_t *externals = pn_list(PN_OBJECT, 0); for (pn_handle_t entry = pn_hash_head(iocp->iocpdesc_map); entry; entry = pn_hash_next(iocp->iocpdesc_map, entry)) { iocpdesc_t *iocpd = (iocpdesc_t *) pn_hash_value(iocp->iocpdesc_map, entry); // Just listeners first. if (is_listener(iocpd)) { if (iocpd->external) { // Owned by application, just keep a temporary reference to it. // iocp_result_t structs must not be free'd until completed or // the completion port is closed. if (iocpd->ops_in_progress) pn_list_add(externals, iocpd); pni_iocpdesc_map_del(iocp, iocpd->socket); } else { // Make it a zombie. pni_iocp_begin_close(iocpd); } } } pni_iocp_drain_completions(iocp); for (pn_handle_t entry = pn_hash_head(iocp->iocpdesc_map); entry; entry = pn_hash_next(iocp->iocpdesc_map, entry)) { iocpdesc_t *iocpd = (iocpdesc_t *) pn_hash_value(iocp->iocpdesc_map, entry); if (iocpd->external) { iocpd->read_closed = true; // Do not consume from read side iocpd->write_closed = true; // Do not shutdown write side if (iocpd->ops_in_progress) pn_list_add(externals, iocpd); pni_iocpdesc_map_del(iocp, iocpd->socket); } else { // Make it a zombie. pni_iocp_begin_close(iocpd); } } return externals; }
void test_list_compare(void) { pn_list_t *a = pn_list(PN_OBJECT, 0); pn_list_t *b = pn_list(PN_OBJECT, 0); assert(pn_equals(a, b)); void *one = pn_class_new(PN_OBJECT, 0); void *two = pn_class_new(PN_OBJECT, 0); void *three = pn_class_new(PN_OBJECT, 0); pn_list_add(a, one); assert(!pn_equals(a, b)); pn_list_add(b, one); assert(pn_equals(a, b)); pn_list_add(b, two); assert(!pn_equals(a, b)); pn_list_add(a, two); assert(pn_equals(a, b)); pn_list_add(a, three); assert(!pn_equals(a, b)); pn_list_add(b, three); assert(pn_equals(a, b)); pn_free(a); pn_free(b); pn_free(one); pn_free(two); pn_free(three); }
void pn_list_minpush(pn_list_t *list, void *value) { assert(list); pn_list_add(list, value); // we use one based indexing for the heap void **heap = list->elements - 1; int now = list->size; while (now > 1 && pn_class_compare(list->clazz, heap[now/2], value) > 0) { heap[now] = heap[now/2]; now /= 2; } heap[now] = value; }
static void test_map_iteration(int n) { pn_list_t *pairs = pn_list(PN_OBJECT, 2*n); for (int i = 0; i < n; i++) { void *key = pn_class_new(PN_OBJECT, 0); void *value = pn_class_new(PN_OBJECT, 0); pn_list_add(pairs, key); pn_list_add(pairs, value); pn_decref(key); pn_decref(value); } pn_map_t *map = pn_map(PN_OBJECT, PN_OBJECT, 0, 0.75); assert(pn_map_head(map) == 0); for (int i = 0; i < n; i++) { pn_map_put(map, pn_list_get(pairs, 2*i), pn_list_get(pairs, 2*i + 1)); } for (pn_handle_t entry = pn_map_head(map); entry; entry = pn_map_next(map, entry)) { void *key = pn_map_key(map, entry); void *value = pn_map_value(map, entry); ssize_t idx = pn_list_index(pairs, key); assert(idx >= 0); assert(pn_list_get(pairs, idx) == key); assert(pn_list_get(pairs, idx + 1) == value); pn_list_del(pairs, idx, 2); } assert(pn_list_size(pairs) == 0); pn_decref(map); pn_decref(pairs); }
static void complete_accept(accept_result_t *result, HRESULT status) { result->new_sock->ops_in_progress--; iocpdesc_t *ld = result->base.iocpd; if (ld->read_closed) { if (!result->new_sock->closing) pni_iocp_begin_close(result->new_sock); free(result); // discard reap_check(ld); } else { result->base.status = status; pn_list_add(ld->acceptor->accepts, result); pni_events_update(ld, ld->events | PN_READABLE); } }
static void zombie_list_add(iocpdesc_t *iocpd) { assert(iocpd->closing); if (!iocpd->ops_in_progress) { // No need to make a zombie. if (iocpd->socket != INVALID_SOCKET) { closesocket(iocpd->socket); iocpd->socket = INVALID_SOCKET; iocpd->read_closed = true; } return; } // Allow 2 seconds for graceful shutdown before releasing socket resource. iocpd->reap_time = pn_i_now() + 2000; pn_list_add(iocpd->iocp->zombie_list, iocpd); }
static void begin_accept(pni_acceptor_t *acceptor, accept_result_t *result) { if (acceptor->listen_sock->closing) { if (result) { free(result); acceptor->accept_queue_size--; } if (acceptor->accept_queue_size == 0) acceptor->signalled = true; return; } if (result) { reset_accept_result(result); } else { if (acceptor->accept_queue_size < IOCP_MAX_ACCEPTS && pn_list_size(acceptor->accepts) == acceptor->accept_queue_size ) { result = accept_result(acceptor->listen_sock); acceptor->accept_queue_size++; } else { // an async accept is still pending or max concurrent accepts already hit return; } } result->new_sock = create_same_type_socket(acceptor->listen_sock); if (result->new_sock) { // Not yet connected. result->new_sock->read_closed = true; result->new_sock->write_closed = true; bool success = acceptor->fn_accept_ex(acceptor->listen_sock->socket, result->new_sock->socket, result->address_buffer, 0, IOCP_SOCKADDRMAXLEN, IOCP_SOCKADDRMAXLEN, &result->unused, (LPOVERLAPPED) result); if (!success && WSAGetLastError() != ERROR_IO_PENDING) { result->base.status = WSAGetLastError(); pn_list_add(acceptor->accepts, result); pni_events_update(acceptor->listen_sock, acceptor->listen_sock->events | PN_READABLE); } else { acceptor->listen_sock->ops_in_progress++; // This socket is equally involved in the async operation. result->new_sock->ops_in_progress++; } } else { iocpdesc_fail(acceptor->listen_sock, WSAGetLastError(), "create accept socket"); } }
static pn_list_t *build_list(size_t capacity, ...) { pn_list_t *result = pn_list(PN_OBJECT, capacity); va_list ap; va_start(ap, capacity); while (true) { void *arg = va_arg(ap, void *); if (arg == END) { break; } pn_list_add(result, arg); pn_class_decref(PN_OBJECT, arg); } va_end(ap); return result; }
static void pn_event_finalize(pn_event_t *event) { // decref before adding to the free list if (event->clazz && event->context) { pn_class_decref(event->clazz, event->context); } pn_list_t *pool = event->pool; if (pool && pn_refcount(pool) > 1) { event->pool = NULL; event->type = PN_EVENT_NONE; event->clazz = NULL; event->context = NULL; event->next = NULL; pn_record_clear(event->attachments); pn_list_add(pool, event); } else { pn_decref(event->attachments); } pn_decref(pool); }
static void test_list_index(void) { pn_list_t *l = pn_list(PN_WEAKREF, 0); void *one = pn_string("one"); void *two = pn_string("two"); void *three = pn_string("three"); void *dup1 = pn_string("dup"); void *dup2 = pn_string("dup"); void *last = pn_string("last"); pn_list_add(l, one); pn_list_add(l, two); pn_list_add(l, three); pn_list_add(l, dup1); pn_list_add(l, dup2); pn_list_add(l, last); check_list_index(l, one, 0); check_list_index(l, two, 1); check_list_index(l, three, 2); check_list_index(l, dup1, 3); check_list_index(l, dup2, 3); check_list_index(l, last, 5); void *nonexistent = pn_string("nonexistent"); check_list_index(l, nonexistent, -1); pn_free(l); pn_free(one); pn_free(two); pn_free(three); pn_free(dup1); pn_free(dup2); pn_free(last); pn_free(nonexistent); }
void connection_dispatch(pn_handler_t *h, pn_event_t *event, pn_event_type_t type) { connection_context_t *cc = connection_context(h); bool replying = cc->global->opts->reply; switch (type) { case PN_LINK_REMOTE_OPEN: { pn_link_t *link = pn_event_link(event); if (pn_link_is_receiver(link)) { check(cc->recv_link == NULL, "Multiple incomming links on one connection"); cc->recv_link = link; pn_connection_t *conn = pn_event_connection(event); pn_list_add(cc->global->active_connections, conn); if (cc->global->shutting_down) { pn_connection_close(conn); break; } if (replying) { // Set up a reply link and defer granting credit to the incoming link pn_connection_t *conn = pn_session_connection(pn_link_session(link)); pn_session_t *ssn = pn_session(conn); pn_session_open(ssn); char name[100]; // prefer a multiplatform uuid generator sprintf(name, "reply_sender_%d", cc->connection_id); cc->reply_link = pn_sender(ssn, name); pn_link_open(cc->reply_link); } else { pn_flowcontroller_t *fc = pn_flowcontroller(1024); pn_handler_add(h, fc); pn_decref(fc); } } } break; case PN_LINK_FLOW: { if (replying) { pn_link_t *reply_link = pn_event_link(event); // pn_flowcontroller handles the non-reply case check(reply_link == cc->reply_link, "internal error"); // Grant the sender as much credit as just given to us for replies int delta = pn_link_credit(reply_link) - pn_link_credit(cc->recv_link); if (delta > 0) pn_link_flow(cc->recv_link, delta); } } break; case PN_DELIVERY: { pn_link_t *recv_link = pn_event_link(event); pn_delivery_t *dlv = pn_event_delivery(event); if (pn_link_is_receiver(recv_link) && !pn_delivery_partial(dlv)) { if (cc->global->received == 0) statistics_start(cc->global->stats); size_t encoded_size = pn_delivery_pending(dlv); cc->global->encoded_data = ensure_buffer(cc->global->encoded_data, encoded_size, &cc->global->encoded_data_size); check(cc->global->encoded_data, "decoding buffer realloc failure"); ssize_t n = pn_link_recv(recv_link, cc->global->encoded_data, encoded_size); check(n == (ssize_t) encoded_size, "message data read fail"); pn_message_t *msg = cc->global->message; int err = pn_message_decode(msg, cc->global->encoded_data, n); check(err == 0, "message decode error"); cc->global->received++; pn_delivery_settle(dlv); statistics_msg_received(cc->global->stats, msg); if (replying) { const char *reply_addr = pn_message_get_reply_to(msg); if (reply_addr) { pn_link_t *rl = cc->reply_link; check(pn_link_credit(rl) > 0, "message received without corresponding reply credit"); LOG("Replying to: %s\n", reply_addr ); pn_message_set_address(msg, reply_addr); pn_message_set_creation_time(msg, msgr_now()); char tag[8]; void *ptr = &tag; *((uint64_t *) ptr) = cc->global->sent; pn_delivery_t *dlv = pn_delivery(rl, pn_dtag(tag, 8)); size_t size = cc->global->encoded_data_size; int err = pn_message_encode(msg, cc->global->encoded_data, &size); check(err == 0, "message encoding error"); pn_link_send(rl, cc->global->encoded_data, size); pn_delivery_settle(dlv); cc->global->sent++; } } } if (cc->global->received >= cc->global->opts->msg_count) { global_shutdown(cc->global); } } break; case PN_CONNECTION_UNBOUND: { pn_connection_t *conn = pn_event_connection(event); pn_list_remove(cc->global->active_connections, conn); pn_connection_release(conn); } break; default: break; } }
void pn_list_fill(pn_list_t *list, void *value, int n) { for (int i = 0; i < n; i++) { pn_list_add(list, value); } }
void connection_dispatch ( pn_handler_t *h, pn_event_t *event, pn_event_type_t type ) { connection_context_t *cc = connection_context(h); switch ( type ) { case PN_LINK_REMOTE_OPEN: { pn_link_t *link = pn_event_link(event); if (pn_link_is_receiver(link)) { check(cc->recv_link == NULL, "Multiple incomming links on one connection"); cc->recv_link = link; pn_connection_t *conn = pn_event_connection(event); pn_list_add(cc->global->active_connections, conn); if (cc->global->shutting_down) { pn_connection_close(conn); break; } pn_flowcontroller_t *fc = pn_flowcontroller(1024); pn_handler_add(h, fc); pn_decref(fc); } } break; case PN_DELIVERY: { pn_link_t *recv_link = pn_event_link(event); pn_delivery_t *dlv = pn_event_delivery(event); if (pn_link_is_receiver(recv_link) && !pn_delivery_partial(dlv)) { if (cc->global->received == 0) statistics_start(cc->global->stats); size_t encoded_size = pn_delivery_pending(dlv); cc->global->encoded_data = ensure_buffer(cc->global->encoded_data, encoded_size, &cc->global->encoded_data_size); check(cc->global->encoded_data, "decoding buffer realloc failure"); /* If this was the first message received, initialize our reporting. */ if ( ! cc->global->received ) rr_init ( & cc->global->resource_reporter ); ssize_t n = pn_link_recv(recv_link, cc->global->encoded_data, encoded_size); check(n == (ssize_t) encoded_size, "message data read fail"); //fprintf ( stderr, "MDEBUG encoded_size == %d\n", encoded_size ); pn_message_t *msg = cc->global->message; int err = pn_message_decode ( msg, cc->global->encoded_data, n ); check ( err == 0, "message decode error" ); /* MICK -- annotate! ================================ */ if ( cc->global->opts->timestamping ) { double message_timestamp; if ( get_message_timestamp ( msg, & message_timestamp ) ) { double now = now_timestamp ( ); cc->global->total_latency += (now - message_timestamp); } else { fprintf ( stderr, "receiver: no timestamp at msg count %d.\n", cc->global->received ); exit ( 1 ); } } /* MICK -- end annotate! ============================= */ cc->global->received++; /*--------------------------------------- Do a report ---------------------------------------*/ if ( ! ( cc->global->received % cc->global->opts->report_frequency ) ) { static bool first_time = true; double cpu_percentage; int rss; double sslr = rr_seconds_since_last_report ( & cc->global->resource_reporter ); rr_report ( & cc->global->resource_reporter, & cpu_percentage, & rss ); double throughput = (double)(cc->global->opts->report_frequency) / sslr; if ( first_time ) { if ( cc->global->opts->timestamping ) { if ( cc->global->opts->print_message_size ) fprintf(cc->global->report_fp, "msg_size\trecv_msgs\tcpu\trss\tthroughput\tlatency\n"); else fprintf(cc->global->report_fp, "recv_msgs\tcpu\trss\tthroughput\tlatency\n"); } else { if ( cc->global->opts->print_message_size ) fprintf(cc->global->report_fp, "msg_size\trecv_msgs\tcpu\trss\tthroughput\n"); else fprintf(cc->global->report_fp, "recv_msgs\tcpu\trss\tthroughput\n"); } first_time = false; } if ( cc->global->opts->timestamping ) { double average_latency = cc->global->total_latency / cc->global->opts->report_frequency; average_latency *= 1000.0; // in msec. cc->global->total_latency = 0; fprintf ( cc->global->report_fp, "%d\t%lf\t%d\t%lf\t%lf\n", cc->global->received, cpu_percentage, rss, throughput, average_latency ); } else { // was: // "recv_msgs: %10d cpu: %5.1lf rss: %6d throughput: %8.0lf\n" if ( cc->global->opts->print_message_size ) { fprintf ( cc->global->report_fp, "%d\t%d\t%lf\t%d\t%lf\n", cc->global->opts->message_size, cc->global->received, cpu_percentage, rss, throughput ); } else { fprintf ( cc->global->report_fp, "%d\t%lf\t%d\t%lf\n", cc->global->received, cpu_percentage, rss, throughput ); } } } pn_delivery_settle(dlv); // move this up statistics_msg_received(cc->global->stats, msg); } if (cc->global->received >= cc->global->opts->msg_count) { global_shutdown(cc->global); } } break; case PN_CONNECTION_UNBOUND: { pn_connection_t *conn = pn_event_connection(event); pn_list_remove(cc->global->active_connections, conn); pn_connection_release(conn); } break; default: break; } }