void netloc_dc_pretty_print(netloc_data_collection_handle_t *handle)
{
    int p;
    struct netloc_dt_lookup_table_iterator *hti = NULL;
    const char * key = NULL;
    netloc_edge_t **path = NULL;
    int path_len;
    struct netloc_dt_lookup_table_iterator *htin = NULL;
    netloc_node_t *cur_node = NULL;

    htin = netloc_dt_lookup_table_iterator_t_construct(handle->node_list);
    while( !netloc_lookup_table_iterator_at_end(htin) ) {
        cur_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(htin);
        if( NULL == cur_node ) {
            break;
        }
        display_node(cur_node, strdup(""));

        printf("Physical Paths\n");
        printf("--------------\n");
        // Display all of the paths from this node to other nodes (if any)
        hti = netloc_dt_lookup_table_iterator_t_construct(cur_node->physical_paths);
        while( !netloc_lookup_table_iterator_at_end(hti) ) {
            key = netloc_lookup_table_iterator_next_key(hti);
            if( NULL == key ) {
                break;
            }
            path = (netloc_edge_t**)netloc_lookup_table_access(cur_node->physical_paths, key);
            path_len = 0;
            for(p = 0; NULL != path[p]; ++p) {
                ++path_len;
            }
            display_path(cur_node->physical_id,
                         key, path_len, path, strdup("\t"));
        }

        printf("Logical Paths\n");
        printf("--------------\n");
        // Display all of the paths from this node to other nodes (if any)
        hti = netloc_dt_lookup_table_iterator_t_construct(cur_node->logical_paths);
        while( !netloc_lookup_table_iterator_at_end(hti) ) {
            key = netloc_lookup_table_iterator_next_key(hti);
            if( NULL == key ) {
                break;
            }
            path = (netloc_edge_t**)netloc_lookup_table_access(cur_node->logical_paths, key);
            path_len = 0;
            for(p = 0; NULL != path[p]; ++p) {
                ++path_len;
            }
            display_path(cur_node->physical_id,
                         key, path_len, path, strdup("\t"));
        }
    }
    netloc_dt_lookup_table_iterator_t_destruct(htin);
}
/*************************************************************
 * Support Functionality
 *************************************************************/
static int compute_shortest_path_dijkstra(netloc_data_collection_handle_t *handle,
                                          netloc_node_t *src_node,
                                          netloc_node_t *dest_node,
                                          int *num_edges,
                                          netloc_edge_t ***edges)
{
    int exit_status = NETLOC_SUCCESS;
    int i;
    pq_queue_t *queue = NULL;
    int *distance = NULL;
    bool *not_seen = NULL;
    netloc_node_t *node_u = NULL;
    netloc_node_t *node_v = NULL;
    netloc_node_t **prev_node = NULL;
    netloc_edge_t **prev_edge = NULL;
    int alt;
    int idx_u, idx_v;

    int num_rev_edges;
    netloc_edge_t **rev_edges = NULL;

    struct netloc_dt_lookup_table_iterator *hti = NULL;
    netloc_node_t *cur_node = NULL;

    unsigned long key_int;

    // Just in case things go poorly below
    (*num_edges) = 0;
    (*edges) = NULL;


    /*
     * Allocate some data structures
     */
    queue = pq_queue_t_construct();
    if( NULL == queue ) {
        fprintf(stderr, "Error: Failed to allocate the queue\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    distance = (int*)malloc(sizeof(int) * netloc_lookup_table_size(handle->node_list));
    if( NULL == distance ) {
        fprintf(stderr, "Error: Failed to allocate the distance array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    not_seen = (bool*)malloc(sizeof(bool) * netloc_lookup_table_size(handle->node_list));
    if( NULL == not_seen ) {
        fprintf(stderr, "Error: Failed to allocate the 'not_seen' array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    prev_node = (netloc_node_t**)malloc(sizeof(netloc_node_t*) * netloc_lookup_table_size(handle->node_list));
    if( NULL == prev_node ) {
        fprintf(stderr, "Error: Failed to allocate the 'prev_node' array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    prev_edge = (netloc_edge_t**)malloc(sizeof(netloc_edge_t*) * netloc_lookup_table_size(handle->node_list));
    if( NULL == prev_edge ) {
        fprintf(stderr, "Error: Failed to allocate the 'prev_edge' array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    /*
     * Initialize the data structures
     */
    // Make sure to initialize the arrays
    for( i = 0; i < netloc_lookup_table_size(handle->node_list); ++i){
        distance[i] = INT_MAX;
        not_seen[i] = true;
        prev_node[i] = NULL;
        prev_edge[i] = NULL;
    }

    i = 0;
    hti = netloc_dt_lookup_table_iterator_t_construct(handle->node_list);
    while( !netloc_lookup_table_iterator_at_end(hti) ) {
        cur_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(hti);
        if( NULL == cur_node ) {
            break;
        }

        if( cur_node == src_node ) {
            pq_push(queue, 0, cur_node);
            distance[i] = 0;
        } else {
            pq_push(queue, INT_MAX, cur_node);
            distance[i] = INT_MAX;
        }

        not_seen[i] = true;

        prev_node[i] = NULL;
        prev_edge[i] = NULL;

        cur_node->__uid__ = i;
        ++i;
    }

    /*
     * Search
     */
    while( !pq_is_empty(queue) ) {
        //pq_dump(queue);

        // Grab the next hop
        node_u = pq_pop(queue);
        // Mark as seen
        idx_u = -1;
        i = 0;
        idx_u = node_u->__uid__;
        not_seen[idx_u] = false;

        // For all the edges from this node
        for(i = 0; i < node_u->num_edges; ++i ) {
            node_v = NULL;
            idx_v  = -1;

            // Lookup the "dest" node
            node_v = node_u->edges[i]->dest_node;
            idx_v = node_v->__uid__;

            // If the node has been seen, skip
            if( !not_seen[idx_v] ) {
                continue;
            }

            // Otherwise check to see if we found a shorter path
            // Future Work: Add a weight factor other than 1.
            //              Maybe calculated based on speed/width
            alt = distance[idx_u] + 1;
            if( alt < distance[idx_v] ) {
                distance[idx_v] = alt;
                prev_node[idx_v] = node_u;
                prev_edge[idx_v] = node_u->edges[i];

                // Adjust the priority queue as needed
                pq_reorder(queue, alt, node_v);
            }
        }
    }

    /*
     * Reconstruct the path by picking up the edges
     * The edges will be in reverse order (dest to source).
     */
    num_rev_edges = 0;
    rev_edges     = NULL;

    // Find last hop
    SUPPORT_CONVERT_ADDR_TO_INT(dest_node->physical_id,
                                handle->network->network_type,
                                key_int);
    node_u  = netloc_lookup_table_access_with_int( handle->node_list,
                                                   dest_node->physical_id,
                                                   key_int);
    idx_u = node_u->__uid__;

    node_v = NULL;
    idx_v  = -1;
    while( prev_node[idx_u] != NULL ) {
        // Find the linking edge
        if( node_u != dest_node) {
            for(i = 0; i < node_u->num_edges; ++i ) {
                if( node_v->physical_id_int == node_u->edges[i]->dest_node->physical_id_int ) {
                    ++num_rev_edges;
                    rev_edges = (netloc_edge_t**)realloc(rev_edges, sizeof(netloc_edge_t*) * num_rev_edges);
                    if( NULL == rev_edges ) {
                        fprintf(stderr, "Error: Failed to re-allocate the 'rev_edges' array with %d elements\n",
                                num_rev_edges);
                        exit_status = NETLOC_ERROR;
                        goto cleanup;
                    }
                    rev_edges[num_rev_edges-1] = node_u->edges[i];
                    break;
                }
            }
        }
        node_v = node_u;
        idx_v  = idx_u;

        // Find the next node
        SUPPORT_CONVERT_ADDR_TO_INT(prev_node[idx_u]->physical_id,
                                    handle->network->network_type,
                                    key_int);
        node_u = netloc_lookup_table_access_with_int( handle->node_list,
                                                      prev_node[idx_u]->physical_id,
                                                      key_int);
        idx_u = node_u->__uid__;
    }

    for(i = 0; i < src_node->num_edges; ++i ) {
        if( NULL == node_v ) {
            fprintf(stderr, "Error: This should never happen, but node_v is NULL at line %d in file %s\n",
                    __LINE__, __FILE__);
            exit_status = NETLOC_ERROR;
            goto cleanup;
        }
        if( node_v->physical_id_int == src_node->edges[i]->dest_node->physical_id_int ) {
            ++num_rev_edges;
            rev_edges = (netloc_edge_t**)realloc(rev_edges, sizeof(netloc_edge_t*) * num_rev_edges);
            if( NULL == rev_edges ) {
                fprintf(stderr, "Error: Failed to re-allocate the 'rev_edges' array with %d elements\n",
                        num_rev_edges);
                exit_status = NETLOC_ERROR;
                goto cleanup;
            }
            rev_edges[num_rev_edges-1] = node_u->edges[i];

            break;
        }
    }


    /*
     * Copy the edges back in correct order
     */
    (*num_edges) = num_rev_edges;
    (*edges) = (netloc_edge_t**)malloc(sizeof(netloc_edge_t*) * (*num_edges));
    if( NULL == (*edges) ) {
        fprintf(stderr, "Error: Failed to allocate the edges array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    for( i = 0; i < num_rev_edges; ++i ) {
        (*edges)[i] = rev_edges[num_rev_edges-1-i];
        //printf("DEBUG: \t Edge: %s\n", netloc_pretty_print_edge_t( (*edges)[i] ) );
    }


    /*
     * Cleanup
     */
 cleanup:
    if( NULL != queue ) {
        pq_queue_t_destruct(queue);
        queue = NULL;
    }

    if( NULL != rev_edges ) {
        free(rev_edges);
        rev_edges = NULL;
    }

    if( NULL != distance ) {
        free(distance);
        distance = NULL;
    }

    if( NULL != not_seen ) {
        free(not_seen);
        not_seen = NULL;
    }

    if( NULL != prev_node ) {
        free(prev_node);
        prev_node = NULL;
    }

    if( NULL != prev_edge ) {
        free(prev_edge);
        prev_edge = NULL;
    }

    netloc_dt_lookup_table_iterator_t_destruct(hti);

    return exit_status;
}
Esempio n. 3
0
int main(void) {
    int i, num_uris = 1;
    char **search_uris = NULL;
    int ret, exit_status = NETLOC_SUCCESS;
    int num_all_networks = 0;
    netloc_network_t **all_networks = NULL;

    netloc_topology_t topology;

    netloc_dt_lookup_table_t nodes = NULL;
    netloc_dt_lookup_table_iterator_t hti = NULL;
    netloc_node_t *node = NULL;

    /*
     * Where to search for network topology information.
     * Information generated from a netloc reader.
     */
    search_uris = (char**)malloc(sizeof(char*) * num_uris );
    if( NULL == search_uris ) {
        return NETLOC_ERROR;
    }
    search_uris[0] = strdup("file://data/netloc");

    /*
     * Find all of the networks in the specified serach URI locations
     */
    ret = netloc_foreach_network((const char * const *) search_uris,
                                 num_uris,
                                 NULL, // Callback function (NULL = include all networks)
                                 NULL, // Callback function data
                                 &num_all_networks,
                                 &all_networks);
    if( NETLOC_SUCCESS != ret ) {
        fprintf(stderr, "Error: netloc_foreach_network returned an error (%d)\n", ret);
        exit_status = ret;
        goto cleanup;
    }

    /*
     * For each of those networks access the detailed topology
     */
    for(i = 0; i < num_all_networks; ++i ) {
        // Pretty print the network for debugging purposes
        printf("\tIncluded Network: %s\n", netloc_pretty_print_network_t(all_networks[i]) );

        /*
         * Attach to the network
         */
        ret = netloc_attach(&topology, *(all_networks[i]));
        if( NETLOC_SUCCESS != ret ) {
            fprintf(stderr, "Error: netloc_attach returned an error (%d)\n", ret);
            return ret;
        }

        /*
         * Access all of the nodes in the topology
         */
        ret = netloc_get_all_nodes(topology, &nodes);
        if( NETLOC_SUCCESS != ret ) {
            fprintf(stderr, "Error: get_all_nodes returned %d\n", ret);
            return ret;
        }

        // Display all of the nodes found
        hti = netloc_dt_lookup_table_iterator_t_construct( nodes );
        while( !netloc_lookup_table_iterator_at_end(hti) ) {
            node = netloc_lookup_table_iterator_next_entry(hti);
            if( NULL == node ) {
                break;
            }
            if( NETLOC_NODE_TYPE_INVALID == node->node_type ) {
                fprintf(stderr, "Error: Returned unexpected node: %s\n", netloc_pretty_print_node_t(node));
                return NETLOC_ERROR;
            }

            printf("Found: %s\n", netloc_pretty_print_node_t(node));
        }

        /* Cleanup the lookup table objects */
        if( NULL != hti ) {
            netloc_dt_lookup_table_iterator_t_destruct(hti);
            hti = NULL;
        }
        if( NULL != nodes ) {
            netloc_lookup_table_destroy(nodes);
            free(nodes);
            nodes = NULL;
        }

        /*
         * Detach from the network
         */
        ret = netloc_detach(topology);
        if( NETLOC_SUCCESS != ret ) {
            fprintf(stderr, "Error: netloc_detach returned an error (%d)\n", ret);
            return ret;
        }
    }
    
    /*
     * Cleanup
     */
 cleanup:
    if( NULL != hti ) {
        netloc_dt_lookup_table_iterator_t_destruct(hti);
        hti = NULL;
    }
    if( NULL != nodes ) {
        netloc_lookup_table_destroy(nodes);
        free(nodes);
        nodes = NULL;
    }

    if( NULL != all_networks ) {
        for(i = 0; i < num_all_networks; ++i ) {
            netloc_dt_network_t_destruct(all_networks[i]);
            all_networks[i] = NULL;
        }
        free(all_networks);
        all_networks = NULL;
    }

    if( NULL != search_uris ) {
        for(i = 0; i < num_uris; ++i) {
            free(search_uris[i]);
            search_uris[i] = NULL;
        }
        free(search_uris);
        search_uris = NULL;
    }

    return NETLOC_SUCCESS;
}
int netloc_dt_data_collection_handle_t_destruct(netloc_data_collection_handle_t *handle)
{
    struct netloc_dt_lookup_table_iterator *hti = NULL;
    netloc_node_t *cur_node = NULL;
    netloc_edge_t *cur_edge = NULL;

    if( NULL != handle->network ) {
        netloc_dt_network_t_destruct(handle->network);
        handle->network      = NULL;
    }

    handle->is_open      = false;
    handle->is_read_only = false;

    if( NULL != handle->unique_id_str ) {
        free(handle->unique_id_str);
        handle->unique_id_str = NULL;
    }

    if( NULL != handle->data_uri ) {
        free(handle->data_uri);
        handle->data_uri = NULL;
    }

    if( NULL != handle->filename_nodes ) {
        free(handle->filename_nodes);
        handle->filename_nodes = NULL;
    }

    if( NULL != handle->filename_physical_paths ) {
        free(handle->filename_physical_paths);
        handle->filename_physical_paths = NULL;
    }

    if( NULL != handle->filename_logical_paths ) {
        free(handle->filename_logical_paths);
        handle->filename_logical_paths = NULL;
    }

    if( NULL != handle->node_list ) {
        // Make sure to free all of the nodes pointed to in the lookup table
        hti = netloc_dt_lookup_table_iterator_t_construct(handle->node_list);
        while( !netloc_lookup_table_iterator_at_end(hti) ) {
            cur_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(hti);
            if( NULL == cur_node ) {
                break;
            }
            netloc_dt_node_t_destruct(cur_node);
        }
        netloc_dt_lookup_table_iterator_t_destruct(hti);

        netloc_lookup_table_destroy(handle->node_list);
        free(handle->node_list);
        handle->node_list = NULL;
    }

    if( NULL != handle->edges ) {
        // Make sure to free all of the edges pointed to in the lookup table
        hti = netloc_dt_lookup_table_iterator_t_construct(handle->edges);
        while( !netloc_lookup_table_iterator_at_end(hti) ) {
            cur_edge = (netloc_edge_t*)netloc_lookup_table_iterator_next_entry(hti);
            if( NULL == cur_edge ) {
                break;
            }
            netloc_dt_edge_t_destruct(cur_edge);
        }
        netloc_dt_lookup_table_iterator_t_destruct(hti);

        netloc_lookup_table_destroy(handle->edges);
        free(handle->edges);
        handle->edges = NULL;
    }

    if( NULL != handle->node_data ) {
        json_decref(handle->node_data);
        handle->node_data = NULL;
        // Implied decref of handle->node_data_acc
    }

    if( NULL != handle->path_data ) {
        json_decref(handle->path_data);
        handle->path_data = NULL;
        // Implied decref of handle->path_data_acc
    }

    free( handle );

    return NETLOC_SUCCESS;
}
int netloc_dc_close(netloc_data_collection_handle_t *handle)
{
    int ret;

    /*
     * Sanity Checks
     */
    if( NULL == handle ) {
        fprintf(stderr, "Error: Null handle provided\n");
        return NETLOC_ERROR;
    }

    /*
     * If read only, then just close the fd
     */
    if( handle->is_read_only ) {
        handle->is_open = false;
        return NETLOC_SUCCESS;
    }


    /******************** Node and Edge Data **************************/

    json_object_set_new(handle->node_data, JSON_NODE_FILE_NODE_INFO, handle->node_data_acc);

    /*
     * Add the edge lookup table to the node data
     */
    json_object_set_new(handle->node_data, JSON_NODE_FILE_EDGE_INFO, netloc_dt_lookup_table_t_json_encode(handle->edges, &dc_encode_edge));
    //netloc_lookup_table_pretty_print(handle->edges);

    /*
     * If creating a new file, then write out the data (Node)
     */
    ret = json_dump_file(handle->node_data, handle->filename_nodes, JSON_COMPACT);
    if( 0 != ret ) {
        fprintf(stderr, "Error: Failed to write out node JSON file!\n");
        return NETLOC_ERROR;
    }

    json_decref(handle->node_data);
    handle->node_data = NULL;


    /******************** Physical Path Data **************************/
    struct netloc_dt_lookup_table_iterator *hti = NULL;
    netloc_node_t *cur_node = NULL;

    /*
     * Add path entries to the JSON file (physical path)
     */
    hti = netloc_dt_lookup_table_iterator_t_construct(handle->node_list);
    while( !netloc_lookup_table_iterator_at_end(hti) ) {
        cur_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(hti);
        if( NULL == cur_node ) {
            break;
        }

        json_object_set_new(handle->phy_path_data_acc,
                            cur_node->physical_id,
                            netloc_dt_node_t_json_encode_paths(cur_node, cur_node->physical_paths));
    }
    netloc_dt_lookup_table_iterator_t_destruct(hti);
    json_object_set_new(handle->phy_path_data, JSON_NODE_FILE_PATH_INFO, handle->phy_path_data_acc);

    /*
     * Write out path data
     */
    ret = json_dump_file(handle->phy_path_data, handle->filename_physical_paths, JSON_COMPACT);
    if( 0 != ret ) {
        fprintf(stderr, "Error: Failed to write out physical path JSON file!\n");
        return NETLOC_ERROR;
    }

    json_decref(handle->phy_path_data);
    handle->phy_path_data = NULL;


    /******************** Logical Path Data **************************/

    /*
     * Add path entries to the JSON file (logical path)
     */
    hti = netloc_dt_lookup_table_iterator_t_construct(handle->node_list);
    while( !netloc_lookup_table_iterator_at_end(hti) ) {
        cur_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(hti);
        if( NULL == cur_node ) {
            break;
        }

        json_object_set_new(handle->path_data_acc,
                            cur_node->physical_id,
                            netloc_dt_node_t_json_encode_paths(cur_node, cur_node->logical_paths));
    }
    netloc_dt_lookup_table_iterator_t_destruct(hti);
    json_object_set_new(handle->path_data, JSON_NODE_FILE_PATH_INFO, handle->path_data_acc);

    /*
     * Write out path data
     */
    ret = json_dump_file(handle->path_data, handle->filename_logical_paths, JSON_COMPACT);
    if( 0 != ret ) {
        fprintf(stderr, "Error: Failed to write out logical path JSON file!\n");
        return NETLOC_ERROR;
    }

    json_decref(handle->path_data);
    handle->path_data = NULL;

    /*
     * Mark file as closed
     */
    handle->is_open = false;

    return NETLOC_SUCCESS;
}
Esempio n. 6
0
static int compute_physical_paths(netloc_data_collection_handle_t *dc_handle)
{
    int ret;
    int src_idx, dst_idx;

    int num_edges = 0;
    netloc_edge_t **edges = NULL;

    netloc_dt_lookup_table_iterator_t hti_src = NULL;
    netloc_dt_lookup_table_iterator_t hti_dst = NULL;
    netloc_node_t *cur_src_node = NULL;
    netloc_node_t *cur_dst_node = NULL;

    printf("Status: Computing Physical Paths\n");

    /*
     * Calculate the path from all sources to all destinations
     */
    src_idx = 0;
    hti_src = netloc_dt_lookup_table_iterator_t_construct(dc_handle->node_list);
    hti_dst = netloc_dt_lookup_table_iterator_t_construct(dc_handle->node_list);

    netloc_lookup_table_iterator_reset(hti_src);
    while( !netloc_lookup_table_iterator_at_end(hti_src) ) {
        cur_src_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(hti_src);
        if( NULL == cur_src_node ) {
            break;
        }

        // JJH: For now limit to just the "host" nodes
        if( NETLOC_NODE_TYPE_HOST != cur_src_node->node_type ) {
            src_idx++;
            continue;
        }

#if 0
        printf("\tSource:      %s\n", netloc_pretty_print_node_t(cur_src_node));
#endif
        dst_idx = 0;
        netloc_lookup_table_iterator_reset(hti_dst);
        while( !netloc_lookup_table_iterator_at_end(hti_dst) ) {
            cur_dst_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(hti_dst);
            if( NULL == cur_dst_node ) {
                break;
            }

            // Skip path to self
            if( src_idx == dst_idx ) {
                dst_idx++;
                continue;
            }

            // JJH: For now limit to just the "host" nodes
            if( NETLOC_NODE_TYPE_HOST != cur_dst_node->node_type ) {
                dst_idx++;
                continue;
            }

#if 0
            printf("Computing a path between the following two nodes\n");
            printf("\tSource:      %s\n", netloc_pretty_print_node_t(cur_src_node));
            printf("\tDestination: %s\n", netloc_pretty_print_node_t(cur_dst_node));
#endif
            /*
             * Calculate the path between these nodes
             */
            ret = netloc_dc_compute_path_between_nodes(dc_handle,
                                                       cur_src_node,
                                                       cur_dst_node,
                                                       &num_edges,
                                                       &edges,
                                                       false);
            if( NETLOC_SUCCESS != ret ) {
                fprintf(stderr, "Error: Failed to compute a path between the following two nodes\n");
                fprintf(stderr, "Error: Source:      %s\n", netloc_pretty_print_node_t(cur_src_node));
                fprintf(stderr, "Error: Destination: %s\n", netloc_pretty_print_node_t(cur_dst_node));
                return ret;
            }


            /*
             * Store that path in the data collection
             */
            ret = netloc_dc_append_path(dc_handle,
                                        cur_src_node->physical_id,
                                        cur_dst_node->physical_id,
                                        num_edges,
                                        edges,
                                        false);
            if( NETLOC_SUCCESS != ret ) {
                fprintf(stderr, "Error: Could not append the physical path between the following two nodes\n");
                fprintf(stderr, "Error: Source:      %s\n", netloc_pretty_print_node_t(cur_src_node));
                fprintf(stderr, "Error: Destination: %s\n", netloc_pretty_print_node_t(cur_dst_node));
                return ret;
            }

            free(edges);

            dst_idx++;
        }

        src_idx++;
    }

    netloc_dt_lookup_table_iterator_t_destruct(hti_src);
    netloc_dt_lookup_table_iterator_t_destruct(hti_dst);

    return NETLOC_SUCCESS;
}