qd_link_t *qd_link(qd_node_t *node, qd_connection_t *conn, qd_direction_t dir, const char* name) { qd_link_t *link = new_qd_link_t(); link->pn_sess = pn_session(qd_connection_pn(conn)); pn_session_set_incoming_capacity(link->pn_sess, 1000000); if (dir == QD_OUTGOING) link->pn_link = pn_sender(link->pn_sess, name); else link->pn_link = pn_receiver(link->pn_sess, name); link->direction = dir; link->context = node->context; link->node = node; link->drain_mode = pn_link_get_drain(link->pn_link); link->remote_snd_settle_mode = pn_link_remote_snd_settle_mode(link->pn_link); link->close_sess_with_link = true; // // Keep the borrowed references // pn_incref(link->pn_link); pn_incref(link->pn_sess); pn_link_set_context(link->pn_link, link); pn_session_open(link->pn_sess); return link; }
static void setup_outgoing_link(qd_container_t *container, pn_link_t *pn_link) { sys_mutex_lock(container->lock); qd_node_t *node = 0; const char *source = pn_terminus_get_address(pn_link_remote_source(pn_link)); qd_field_iterator_t *iter; // TODO - Extract the name from the structured source if (source) { iter = qd_address_iterator_string(source, ITER_VIEW_NODE_ID); qd_hash_retrieve(container->node_map, iter, (void*) &node); qd_field_iterator_free(iter); } sys_mutex_unlock(container->lock); if (node == 0) { if (container->default_node) node = container->default_node; else { pn_condition_t *cond = pn_link_condition(pn_link); pn_condition_set_name(cond, "amqp:not-found"); pn_condition_set_description(cond, "Source node does not exist"); pn_link_close(pn_link); return; } } qd_link_t *link = new_qd_link_t(); if (!link) { pn_condition_t *cond = pn_link_condition(pn_link); pn_condition_set_name(cond, "amqp:internal-error"); pn_condition_set_description(cond, "Insufficient memory"); pn_link_close(pn_link); return; } link->pn_sess = pn_link_session(pn_link); link->pn_link = pn_link; link->direction = QD_OUTGOING; link->context = 0; link->node = node; link->remote_snd_settle_mode = pn_link_remote_snd_settle_mode(pn_link); link->drain_mode = pn_link_get_drain(pn_link); link->close_sess_with_link = false; // // Keep the borrowed references // pn_incref(pn_link); pn_incref(link->pn_sess); pn_link_set_context(pn_link, link); node->ntype->outgoing_handler(node->context, link); }
/* Test waking up a connection that is idle */ static void test_connection_wake(test_t *t) { test_proactor_t tps[] = { test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) }; pn_proactor_t *client = tps[0].proactor; pn_listener_t *l = test_listen(&tps[1], ""); pn_connection_t *c = pn_connection(); pn_incref(c); /* Keep a reference for wake() after free */ pn_proactor_connect2(client, c, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); TEST_CHECK(t, pn_proactor_get(client) == NULL); /* Should be idle */ pn_connection_wake(c); TEST_ETYPE_EQUAL(t, PN_CONNECTION_WAKE, TEST_PROACTORS_RUN(tps)); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* Both ends */ /* The pn_connection_t is still valid so wake is legal but a no-op */ TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); TEST_ETYPE_EQUAL(t, PN_EVENT_NONE, TEST_PROACTORS_GET(tps)); /* No more wake */ /* Verify we don't get a wake after close even if they happen together */ pn_connection_t *c2 = pn_connection(); pn_proactor_connect2(client, c2, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); pn_connection_wake(c2); pn_proactor_disconnect(client, NULL); pn_connection_wake(c2); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, test_proactors_run(&tps[0], 1)); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, test_proactors_run(&tps[0], 1)); TEST_ETYPE_EQUAL(t, PN_EVENT_NONE, test_proactors_get(&tps[0], 1)); /* No late wake */ TEST_PROACTORS_DESTROY(tps); /* The pn_connection_t is still valid so wake is legal but a no-op */ pn_connection_wake(c); pn_decref(c); }
void connection_context_init(connection_context_t *cc, global_context_t *gc) { cc->global = gc; pn_incref(gc->listener_handler); cc->connection_id = gc->connections++; cc->recv_link = 0; cc->reply_link = 0; }
pn_event_t *pn_collector_put(pn_collector_t *collector, const pn_class_t *clazz, void *context, pn_event_type_t type) { if (!collector) { return NULL; } assert(context); if (collector->freed) { return NULL; } pn_event_t *tail = collector->tail; if (tail && tail->type == type && tail->context == context) { return NULL; } clazz = clazz->reify(context); pn_event_t *event = (pn_event_t *) pn_list_pop(collector->pool); if (!event) { event = pn_event(); } event->pool = collector->pool; pn_incref(event->pool); if (tail) { tail->next = event; collector->tail = event; } else { collector->tail = event; collector->head = event; } event->clazz = clazz; event->context = context; event->type = type; pn_class_incref(clazz, event->context); return event; }
static void test_refcounting(int refs) { void *obj = pn_class_new(PN_OBJECT, 0); assert(pn_refcount(obj) == 1); for (int i = 0; i < refs; i++) { pn_incref(obj); assert(pn_refcount(obj) == i + 2); } assert(pn_refcount(obj) == refs + 1); for (int i = 0; i < refs; i++) { pn_decref(obj); assert(pn_refcount(obj) == refs - i); } assert(pn_refcount(obj) == 1); pn_free(obj); }