From d414272ccc5456a03c7d14dac5c335cf7d4d4ce2 Mon Sep 17 00:00:00 2001 From: ganeshmurthy Date: Wed, 18 Nov 2015 16:10:17 -0500 Subject: [PATCH] DISPATCH-179 - Added boilerplate code to cover delete and create management operations --- include/qpid/dispatch/amqp.h | 2 + include/qpid/dispatch/router_core.h | 2 +- python/qpid_dispatch/management/qdrouter.json | 2 +- src/CMakeLists.txt | 1 + src/amqp.c | 2 + src/router_core/agent.c | 83 ++++++++- src/router_core/agent_address.c | 47 ++++- src/router_core/agent_address.h | 7 +- src/router_core/agent_waypoint.c | 175 ++++++++++++++++++ src/router_core/agent_waypoint.h | 39 ++++ src/router_core/management_agent.c | 52 +++++- src/router_core/router_core_private.h | 7 + 12 files changed, 394 insertions(+), 25 deletions(-) create mode 100644 src/router_core/agent_waypoint.c create mode 100644 src/router_core/agent_waypoint.h diff --git a/include/qpid/dispatch/amqp.h b/include/qpid/dispatch/amqp.h index 2beb69010c..8f239ae6b5 100644 --- a/include/qpid/dispatch/amqp.h +++ b/include/qpid/dispatch/amqp.h @@ -123,6 +123,8 @@ const char * const QD_INTERNODE_LINK_NAME_2; /** An AMQP error status code and string description */ typedef struct qd_amqp_error_t { int status; const char* description; } qd_amqp_error_t; extern const qd_amqp_error_t QD_AMQP_OK; +extern const qd_amqp_error_t QD_AMQP_CREATED; +extern const qd_amqp_error_t QD_AMQP_NO_CONTENT; extern const qd_amqp_error_t QD_AMQP_BAD_REQUEST; extern const qd_amqp_error_t QD_AMQP_NOT_FOUND; extern const qd_amqp_error_t QD_AMQP_NOT_IMPLEMENTED; diff --git a/include/qpid/dispatch/router_core.h b/include/qpid/dispatch/router_core.h index 4a22bcf798..99270a6346 100644 --- a/include/qpid/dispatch/router_core.h +++ b/include/qpid/dispatch/router_core.h @@ -262,7 +262,7 @@ void qdr_manage_create(qdr_core_t *core, void *context, qd_router_entity_type_t * @param identity The identity supplied with the request (or 0 if the name was supplied) */ void qdr_manage_delete(qdr_core_t *core, void *context, qd_router_entity_type_t type, - qd_field_iterator_t *name, qd_field_iterator_t *identity); + qd_field_iterator_t *name, qd_field_iterator_t *identity, qd_composed_field_t *body); /** * qdr_manage_read diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json index 00e247f51d..41b628ad4e 100644 --- a/python/qpid_dispatch/management/qdrouter.json +++ b/python/qpid_dispatch/management/qdrouter.json @@ -771,7 +771,7 @@ "waypoint": { "description":"A remote node that messages for an address pass through.", "extends": "configurationEntity", - "operations": ["CREATE"], + "operations": ["CREATE", "DELETE"], "attributes": { "address": { "description":"The AMQP address of the waypoint.", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4dd221adbe..62b61b8667 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,6 +67,7 @@ set(qpid_dispatch_SOURCES router_config.c router_core/agent.c router_core/agent_address.c + router_core/agent_waypoint.c router_core/agent_link.c router_core/connections.c router_core/router_core.c diff --git a/src/amqp.c b/src/amqp.c index 9ecb4cc72f..45639cfc65 100644 --- a/src/amqp.c +++ b/src/amqp.c @@ -33,6 +33,8 @@ const char * const QD_INTERNODE_LINK_NAME_1 = "qd.internode.1"; const char * const QD_INTERNODE_LINK_NAME_2 = "qd.internode.2"; const qd_amqp_error_t QD_AMQP_OK = { 200, "OK" }; +const qd_amqp_error_t QD_AMQP_CREATED = { 201, "Created" }; +const qd_amqp_error_t QD_AMQP_NO_CONTENT = { 204, "No Content" }; // This is the response code if the delete of a manageable entity was successful. const qd_amqp_error_t QD_AMQP_BAD_REQUEST = { 400, "Bad Request" }; const qd_amqp_error_t QD_AMQP_NOT_FOUND = { 404, "Not Found" }; const qd_amqp_error_t QD_AMQP_NOT_IMPLEMENTED = { 501, "Not Implemented"}; diff --git a/src/router_core/agent.c b/src/router_core/agent.c index e8e57611e6..d5d42814ed 100644 --- a/src/router_core/agent.c +++ b/src/router_core/agent.c @@ -19,6 +19,7 @@ #include #include "agent_address.h" +#include "agent_waypoint.h" #include "agent_link.h" #include "router_core_private.h" #include @@ -58,7 +59,8 @@ static const char *qdr_link_columns[] = #define QDR_LINK_COLUMN_COUNT 10 static void qdr_manage_read_CT(qdr_core_t *core, qdr_action_t *action, bool discard); - +static void qdr_manage_create_CT(qdr_core_t *core, qdr_action_t *action, bool discard); +static void qdr_manage_delete_CT(qdr_core_t *core, qdr_action_t *action, bool discard); //================================================================================== // Internal Functions @@ -130,15 +132,38 @@ static void qdr_agent_set_columns(qdr_query_t *query, qd_parsed_field_t *attribu // Interface Functions //================================================================================== -void qdr_manage_create(qdr_core_t *core, void *context, qd_router_entity_type_t type, - qd_field_iterator_t *name, qd_parsed_field_t *in_body, qd_composed_field_t *out_body) +void qdr_manage_create(qdr_core_t *core, + void *context, + qd_router_entity_type_t type, + qd_field_iterator_t *name, + qd_parsed_field_t *in_body, + qd_composed_field_t *out_body) { + qdr_action_t *action = qdr_action(qdr_manage_create_CT); + + // Create a query object here + action->args.agent.query = qdr_query(core, context, type, 0, out_body); + action->args.agent.name = name; + action->args.agent.in_body = in_body; + + qdr_action_enqueue(core, action); } -void qdr_manage_delete(qdr_core_t *core, void *context, qd_router_entity_type_t type, - qd_field_iterator_t *name, qd_field_iterator_t *identity) +void qdr_manage_delete(qdr_core_t *core, void *context, + qd_router_entity_type_t type, + qd_field_iterator_t *name, + qd_field_iterator_t *identity, + qd_composed_field_t *body) { + qdr_action_t *action = qdr_action(qdr_manage_delete_CT); + + // Create a query object here + action->args.agent.query = qdr_query(core, context, type, 0, body); + action->args.agent.name = name; + action->args.agent.identity = identity; + + qdr_action_enqueue(core, action); } @@ -159,10 +184,15 @@ void qdr_manage_read(qdr_core_t *core, void *context, } -void qdr_manage_update(qdr_core_t *core, void *context, qd_router_entity_type_t type, - qd_field_iterator_t *name, qd_field_iterator_t *identity, - qd_parsed_field_t *in_body, qd_composed_field_t *out_body) +void qdr_manage_update(qdr_core_t *core, + void *context, + qd_router_entity_type_t type, + qd_field_iterator_t *name, + qd_field_iterator_t *identity, + qd_parsed_field_t *in_body, + qd_composed_field_t *out_body) { + } @@ -305,7 +335,7 @@ static void qdr_manage_read_CT(qdr_core_t *core, qdr_action_t *action, bool disc switch (query->entity_type) { case QD_ROUTER_CONNECTION: break; case QD_ROUTER_LINK: break; - case QD_ROUTER_ADDRESS: qdra_address_get(core, name, identity, query, qdr_address_columns); break; + case QD_ROUTER_ADDRESS: qdra_address_get_CT(core, name, identity, query, qdr_address_columns); break; case QD_ROUTER_WAYPOINT: break; case QD_ROUTER_EXCHANGE: break; case QD_ROUTER_BINDING: break; @@ -313,6 +343,41 @@ static void qdr_manage_read_CT(qdr_core_t *core, qdr_action_t *action, bool disc } +static void qdr_manage_create_CT(qdr_core_t *core, qdr_action_t *action, bool discard) +{ + qd_field_iterator_t *name = action->args.agent.name; + qdr_query_t *query = action->args.agent.query; + qd_parsed_field_t *in_body = action->args.agent.in_body; + switch (query->entity_type) { + case QD_ROUTER_CONNECTION: break; + case QD_ROUTER_LINK: break; + case QD_ROUTER_ADDRESS: break; + case QD_ROUTER_WAYPOINT: qdra_waypoint_create_CT(core, name, query, in_body); break; + case QD_ROUTER_EXCHANGE: break; + case QD_ROUTER_BINDING: break; + } +} + + +static void qdr_manage_delete_CT(qdr_core_t *core, qdr_action_t *action, bool discard) +{ + qd_field_iterator_t *name = action->args.agent.name; + qd_field_iterator_t *identity = action->args.agent.identity; + qdr_query_t *query = action->args.agent.query; + + switch (query->entity_type) { + case QD_ROUTER_CONNECTION: break; + case QD_ROUTER_LINK: break; + case QD_ROUTER_ADDRESS: qdra_address_delete_CT(core, name, identity, query); break; + case QD_ROUTER_WAYPOINT: qdra_waypoint_delete_CT(core, name, identity, query); break; + case QD_ROUTER_EXCHANGE: break; + case QD_ROUTER_BINDING: break; + } +} + + + + static void qdrh_query_get_first_CT(qdr_core_t *core, qdr_action_t *action, bool discard) { qdr_query_t *query = action->args.agent.query; diff --git a/src/router_core/agent_address.c b/src/router_core/agent_address.c index fbbd7a0664..641aa73c28 100644 --- a/src/router_core/agent_address.c +++ b/src/router_core/agent_address.c @@ -37,7 +37,8 @@ static void qdr_insert_address_columns_CT(qdr_address_t *addr, qd_composed_field_t *body, - int column_index) { + int column_index) +{ switch(column_index) { case QDR_ADDRESS_NAME: case QDR_ADDRESS_IDENTITY: @@ -140,11 +141,11 @@ static void qdr_manage_advance_address_CT(qdr_query_t *query, qdr_address_t *add query->more = false; } -void qdra_address_get(qdr_core_t *core, - qd_field_iterator_t *name, - qd_field_iterator_t *identity, - qdr_query_t *query, - const char *qdr_address_columns[]) +void qdra_address_get_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qd_field_iterator_t *identity, + qdr_query_t *query, + const char *qdr_address_columns[]) { qdr_address_t *addr; @@ -258,3 +259,37 @@ void qdra_address_get_next_CT(qdr_core_t *core, qdr_query_t *query) qdr_agent_enqueue_response_CT(core, query); } +void qdra_address_delete_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qd_field_iterator_t *identity, + qdr_query_t *query) +{ + bool success = true; + + if (identity) {//If there is identity, ignore the name + //TOOD - do something here + } + else if (name) { + //TOOD - do something here + } + else { + query->status = &QD_AMQP_BAD_REQUEST; + success = false; + } + + + // TODO - Add more logic here. + if (success) { + // If the request was successful then the statusCode MUST be 204 (No Content). + query->status = &QD_AMQP_NO_CONTENT; + } + + // The body of the message MUST consist of an amqp-value section containing a Map with zero entries. + qd_compose_start_map(query->body); + qd_compose_end_map(query->body); + + // + // Enqueue the response. + // + qdr_agent_enqueue_response_CT(core, query); +} diff --git a/src/router_core/agent_address.h b/src/router_core/agent_address.h index 5a1a4f75e3..d2e9f8b9fa 100644 --- a/src/router_core/agent_address.h +++ b/src/router_core/agent_address.h @@ -24,12 +24,17 @@ void qdra_address_get_first_CT(qdr_core_t *core, qdr_query_t *query, int offset); void qdra_address_get_next_CT(qdr_core_t *core, qdr_query_t *query); -void qdra_address_get(qdr_core_t *core, +void qdra_address_get_CT(qdr_core_t *core, qd_field_iterator_t *name, qd_field_iterator_t *identity, qdr_query_t *query, const char *qdr_address_columns[]); +void qdra_address_delete_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qd_field_iterator_t *identity, + qdr_query_t *query); + #define QDR_ADDRESS_COLUMN_COUNT 13 diff --git a/src/router_core/agent_waypoint.c b/src/router_core/agent_waypoint.c new file mode 100644 index 0000000000..83642ae937 --- /dev/null +++ b/src/router_core/agent_waypoint.c @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "agent_waypoint.h" + +const char *address = "address"; +const char *connector = "connector"; +const char *inPhase = "inPhase"; +const char *outPhase = "outPhase"; +const char *mode = "mode"; + +#define QDR_WAYPOINT_NAME 0 +#define QDR_WAYPOINT_ADDRESS 1 +#define QDR_WAYPOINT_CONNECTOR 2 +#define QDR_WAYPOINT_INPHASE 3 +#define QDR_WAYPOINT_OUTPHASE 4 +#define QDR_WAYPOINT_MODE 5 + +#define QDR_WAYPOINT_COLUMN_COUNT 6 + +static const char *qdr_waypoint_columns[] = + {"name", + "address", + "connector", + "inPhase", + "outPhase", + "mode", + 0}; + +static void qdr_insert_waypoint_columns_CT(qd_composed_field_t *body, + int column_index) +{ + // TODO replace nulls with actual values. + switch(column_index) { + case QDR_WAYPOINT_NAME: + qd_compose_insert_null(body); + break; + + case QDR_WAYPOINT_ADDRESS: + qd_compose_insert_null(body); + break; + + case QDR_WAYPOINT_CONNECTOR: + qd_compose_insert_null(body); + break; + + case QDR_WAYPOINT_INPHASE: + qd_compose_insert_null(body); + break; + + case QDR_WAYPOINT_OUTPHASE: + qd_compose_insert_null(body); + break; + + case QDR_WAYPOINT_MODE: + qd_compose_insert_null(body); // TEMP + break; + + default: + qd_compose_insert_null(body); + break; + } + +} + +static void qdr_manage_write_response_map_CT(qd_composed_field_t *body) +{ + qd_compose_start_map(body); + + for(int i = 0; i < QDR_WAYPOINT_COLUMN_COUNT; i++) { + qd_compose_insert_string(body, qdr_waypoint_columns[i]); + qdr_insert_waypoint_columns_CT(body, i); + } + + qd_compose_end_map(body); +} + +void qdra_waypoint_create_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qdr_query_t *query, + qd_parsed_field_t *in_body) +{ + // Get the map fields from the body + if (qd_parse_is_map(in_body)) { + qd_parsed_field_t *address_field = qd_parse_value_by_key(in_body, address); + qd_parsed_field_t *connector_field = qd_parse_value_by_key(in_body, connector); + qd_parsed_field_t *inPhase_field = qd_parse_value_by_key(in_body, inPhase); + qd_parsed_field_t *outPhase_field = qd_parse_value_by_key(in_body, outPhase); + qd_parsed_field_t *mode_field = qd_parse_value_by_key(in_body, mode); + + if ( address_field && + connector_field && + inPhase_field && + outPhase_field && + mode_field) { + // TODO - Add code here that would actually create a waypoint. + // If the request was successful then the statusCode MUST be 201 (Created) and the body of the message + // MUST consist an amqp-value section that contains a Map containing the actual attributes of the entity created + qdr_manage_write_response_map_CT(query->body); + query->status = &QD_AMQP_CREATED; + } + else { + query->status = &QD_AMQP_BAD_REQUEST; + } + } + else { + query->status = &QD_AMQP_BAD_REQUEST; + } + + // + // Enqueue the response. + // + qdr_agent_enqueue_response_CT(core, query); + + +} + +void qdra_waypoint_delete_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qd_field_iterator_t *identity, + qdr_query_t *query) +{ + bool success = true; + + if (identity) {//If there is identity, ignore the name + //TOOD - do something here + } + else if (name) { + //TOOD - do something here + } + else { + query->status = &QD_AMQP_BAD_REQUEST; + success = false; + } + + + // TODO - Add more logic here. + if (success) { + // If the request was successful then the statusCode MUST be 204 (No Content). + query->status = &QD_AMQP_NO_CONTENT; + } + + // The body of the message MUST consist of an amqp-value section containing a Map with zero entries. + qd_compose_start_map(query->body); + qd_compose_end_map(query->body); + + // + // Enqueue the response. + // + qdr_agent_enqueue_response_CT(core, query); +} + + +void qdra_waypoint_update_CT(qdr_core_t *core, qd_field_iterator_t *name, qdr_query_t *query) +{ + +} + + diff --git a/src/router_core/agent_waypoint.h b/src/router_core/agent_waypoint.h new file mode 100644 index 0000000000..7abc38f9f9 --- /dev/null +++ b/src/router_core/agent_waypoint.h @@ -0,0 +1,39 @@ +#ifndef qdr_agent_waypoint +#define qdr_agent_waypoint 1 +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "router_core_private.h" + +void qdra_waypoint_create_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qdr_query_t *query, + qd_parsed_field_t *in_body); + +void qdra_waypoint_delete_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qd_field_iterator_t *identity, + qdr_query_t *query); + + +void qdra_waypoint_update_CT(qdr_core_t *core, + qd_field_iterator_t *name, + qdr_query_t *query); + +#endif diff --git a/src/router_core/management_agent.c b/src/router_core/management_agent.c index b45d7cd60f..4cb4d8c6be 100644 --- a/src/router_core/management_agent.c +++ b/src/router_core/management_agent.c @@ -40,6 +40,7 @@ const char *identity_key = "identity"; const char *operation_type_key = "operation"; const char *attribute_names_key = "attributeNames"; +const unsigned char *waypoint_entity_type = (unsigned char*) "org.apache.qpid.dispatch.waypoint"; const unsigned char *address_entity_type = (unsigned char*) "org.apache.qpid.dispatch.router.address"; const unsigned char *link_entity_type = (unsigned char*) "org.apache.qpid.dispatch.router.link"; @@ -251,22 +252,39 @@ static void qd_core_agent_read_handler(qd_dispatch_t *qd, // // Add the Body // - qd_composed_field_t *field = qd_compose(QD_PERFORMATIVE_BODY_AMQP_VALUE, 0); + qd_composed_field_t *body = qd_compose(QD_PERFORMATIVE_BODY_AMQP_VALUE, 0); // Set the callback function. qdr_manage_handler(core, qd_manage_response_handler); // Call local function that creates and returns a qd_management_context_t containing the values passed in. - qd_management_context_t *ctx = qd_management_context(qd_message(), msg, field, 0, qd, operation_type, 0); + qd_management_context_t *ctx = qd_management_context(qd_message(), msg, body, 0, qd, operation_type, 0); //Call the read API function - qdr_manage_read(core, ctx, entity_type, name_iter, identity_iter, field); + qdr_manage_read(core, ctx, entity_type, name_iter, identity_iter, body); } -static void qd_core_agent_create_handler() +static void qd_core_agent_create_handler(qd_dispatch_t *qd, + qd_message_t *msg, + qd_router_entity_type_t entity_type, + qd_router_operation_type_t operation_type, + qd_field_iterator_t *name_iter) { + qdr_core_t *core = qd_router_core(qd); + + // + // Add the Body + // + qd_composed_field_t *out_body = qd_compose(QD_PERFORMATIVE_BODY_AMQP_VALUE, 0); + + // Set the callback function. + qdr_manage_handler(core, qd_manage_response_handler); + + // Call local function that creates and returns a qd_management_context_t containing the values passed in. + qd_management_context_t *ctx = qd_management_context(qd_message(), msg, out_body, 0, qd, operation_type, 0); + qdr_manage_create(core, ctx, entity_type, name_iter, qd_parse(qd_message_field_iterator(msg, QD_FIELD_BODY)), out_body); } @@ -276,9 +294,27 @@ static void qd_core_agent_update_handler() } -static void qd_core_agent_delete_handler() +static void qd_core_agent_delete_handler(qd_dispatch_t *qd, + qd_message_t *msg, + qd_router_entity_type_t entity_type, + qd_router_operation_type_t operation_type, + qd_field_iterator_t *identity_iter, + qd_field_iterator_t *name_iter) { + qdr_core_t *core = qd_router_core(qd); + + // + // Add the Body + // + qd_composed_field_t *body = qd_compose(QD_PERFORMATIVE_BODY_AMQP_VALUE, 0); + + // Set the callback function. + qdr_manage_handler(core, qd_manage_response_handler); + + // Call local function that creates and returns a qd_management_context_t containing the values passed in. + qd_management_context_t *ctx = qd_management_context(qd_message(), msg, body, 0, qd, operation_type, 0); + qdr_manage_delete(core, ctx, entity_type, name_iter, identity_iter, body); } @@ -330,6 +366,8 @@ static bool qd_can_handle_request(qd_field_iterator_t *props, (*entity_type) = QD_ROUTER_ADDRESS; else if(qd_field_iterator_equal(qd_parse_raw(parsed_field), link_entity_type)) (*entity_type) = QD_ROUTER_LINK; + else if(qd_field_iterator_equal(qd_parse_raw(parsed_field), waypoint_entity_type)) + (*entity_type) = QD_ROUTER_WAYPOINT; else return false; @@ -397,7 +435,7 @@ void management_agent_handler(void *context, qd_message_t *msg, int link_id) qd_core_agent_query_handler(qd, entity_type, operation_type, msg, &count, &offset); break; case QD_ROUTER_OPERATION_CREATE: - qd_core_agent_create_handler(); + qd_core_agent_create_handler(qd, msg, entity_type, operation_type, name_iter); break; case QD_ROUTER_OPERATION_READ: qd_core_agent_read_handler(qd, msg, entity_type, operation_type, identity_iter, name_iter); @@ -406,7 +444,7 @@ void management_agent_handler(void *context, qd_message_t *msg, int link_id) qd_core_agent_update_handler(); break; case QD_ROUTER_OPERATION_DELETE: - qd_core_agent_delete_handler(); + qd_core_agent_delete_handler(qd, msg, entity_type, operation_type, identity_iter, name_iter); break; } } diff --git a/src/router_core/router_core_private.h b/src/router_core/router_core_private.h index 64253b1e77..0347fe03a8 100644 --- a/src/router_core/router_core_private.h +++ b/src/router_core/router_core_private.h @@ -95,6 +95,7 @@ struct qdr_action_t { int offset; qd_field_iterator_t *identity; qd_field_iterator_t *name; + qd_parsed_field_t *in_body; } agent; } args; @@ -303,6 +304,12 @@ struct qdr_core_t { qdr_link_t **data_links_by_mask_bit; }; +typedef enum { + PASSTHROUGH, + TAP, + BYPASS +} qdr_waypoint_mode_t; + void *router_core_thread(void *arg); void qdr_route_table_setup_CT(qdr_core_t *core); void qdr_agent_setup_CT(qdr_core_t *core);