netloc_node_t * netloc_dc_get_node_by_physical_id(netloc_data_collection_handle_t *handle, char * phy_id) { unsigned long key_int; if( NULL == phy_id ) { return NULL; } SUPPORT_CONVERT_ADDR_TO_INT(phy_id, handle->network->network_type, key_int); return netloc_lookup_table_access_with_int( handle->node_list, phy_id, key_int ); }
/************************************************************* * 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; }
int netloc_dc_append_edge_to_node(netloc_data_collection_handle_t *handle, netloc_node_t *node, netloc_edge_t *edge) { char *key = NULL; netloc_edge_t *found_edge = NULL; netloc_node_t *found_node = NULL; unsigned long key_int; bool is_cached = false; /* * Setup the table for the first edge */ if( NULL == handle->edges ) { handle->edges = calloc(1, sizeof(*handle->edges)); netloc_lookup_table_init(handle->edges, 1, 0); } /* * Setup the table for the first node */ if(NULL == handle->node_list) { handle->node_list = calloc(1, sizeof(*handle->node_list)); netloc_lookup_table_init(handle->node_list, 1, 0); } /* * Check to see if we have seen this edge before */ asprintf(&key, "%d", edge->edge_uid); found_edge = (netloc_edge_t*)netloc_lookup_table_access(handle->edges, key); free(key); key = NULL; // JJH: Should we be checking the contents of the edge, not just the key? /* * If not add it to the edges lookup table */ if( NULL == found_edge ) { found_edge = netloc_dt_edge_t_dup(edge); asprintf(&key, "%d", found_edge->edge_uid); netloc_lookup_table_append(handle->edges, key, found_edge); free(key); key = NULL; } /* * Update the edge links * if the node endpoint is not in the list, then add a stub */ if( NULL == edge->src_node_id ) { return NETLOC_ERROR_NOT_FOUND; } SUPPORT_CONVERT_ADDR_TO_INT(edge->src_node_id, handle->network->network_type, key_int); asprintf(&key, "%s", edge->src_node_id); found_node = netloc_lookup_table_access_with_int(handle->node_list, key, key_int); if( NULL == found_node ) { found_node = netloc_dt_node_t_construct(); found_node->physical_id = strdup(edge->src_node_id); found_node->physical_id_int = key_int; found_node->node_type = NETLOC_NODE_TYPE_INVALID; netloc_lookup_table_append_with_int(handle->node_list, key, key_int, found_node); } else { is_cached = true; } found_edge->src_node = found_node; free(key); key = NULL; if( NULL == edge->dest_node_id ) { return NETLOC_ERROR_NOT_FOUND; } asprintf(&key, "%s", edge->dest_node_id); SUPPORT_CONVERT_ADDR_TO_INT(edge->dest_node_id, handle->network->network_type, key_int); found_node = netloc_lookup_table_access_with_int(handle->node_list, key, key_int); if( NULL == found_node ) { found_node = netloc_dt_node_t_construct(); found_node->physical_id = strdup(edge->dest_node_id); found_node->physical_id_int = key_int; found_node->node_type = NETLOC_NODE_TYPE_INVALID; netloc_lookup_table_append_with_int(handle->node_list, key, key_int, found_node); } found_edge->dest_node = found_node; free(key); key = NULL; /* * Add the edge index to the node passed to us */ node->num_edge_ids++; node->edge_ids = (int*)realloc(node->edge_ids, sizeof(int) * node->num_edge_ids); node->edge_ids[node->num_edge_ids -1] = found_edge->edge_uid; node->num_edges++; node->edges = (netloc_edge_t**)realloc(node->edges, sizeof(netloc_edge_t*) * node->num_edges); node->edges[node->num_edges -1] = found_edge; /* * Update the cached version of this node */ if( is_cached ) { json_object_del(handle->node_data_acc, node->physical_id); json_object_set_new(handle->node_data_acc, node->physical_id, netloc_dt_node_t_json_encode(node)); } return NETLOC_SUCCESS; }
int netloc_dc_append_path(netloc_data_collection_handle_t *handle, const char * src_node_id, const char * dest_node_id, int num_edges, netloc_edge_t **edges, bool is_logical) { int i; netloc_node_t *node = NULL; int *edge_ids = NULL; unsigned long key_int; /* * Find the source Node */ SUPPORT_CONVERT_ADDR_TO_INT(src_node_id, handle->network->network_type, key_int); node = netloc_lookup_table_access_with_int( handle->node_list, src_node_id, key_int ); if( NULL == node ) { fprintf(stderr, "Error: node not found in the list (id = %s)\n", src_node_id); return NETLOC_ERROR; } /* * Copy the edge id's * Note: The 'path' storage is not a set of edge pointers, but edge ids. * It is assumed that the user will push paths into the data collection, but * not have to retrieve that path from the dc_handle. */ edge_ids = (int*)malloc(sizeof(int)* (num_edges+1)); if( NULL == edge_ids ) { return NETLOC_ERROR; } for(i = 0; i < num_edges; ++i) { if( NULL == edges[i] ) { edge_ids[i] = NETLOC_EDGE_UID_INVALID; } else { edge_ids[i] = edges[i]->edge_uid; } } // Null terminated array edge_ids[num_edges] = NETLOC_EDGE_UID_NULL; /* * Add the entry to the hash */ if( is_logical ) { if( NULL == node->logical_paths ) { node->logical_paths = calloc(1, sizeof(*node->logical_paths)); netloc_lookup_table_init(node->logical_paths, 1, 0); node->num_log_paths = 0; } node->num_log_paths += 1; netloc_lookup_table_append( node->logical_paths, dest_node_id, edge_ids); } else { if( NULL == node->physical_paths ) { node->physical_paths = calloc(1, sizeof(*node->physical_paths)); netloc_lookup_table_init(node->physical_paths, 1, 0); node->num_log_paths = 0; } node->num_log_paths += 1; netloc_lookup_table_append( node->physical_paths, dest_node_id, edge_ids); } return NETLOC_SUCCESS; }
int netloc_dc_append_node(netloc_data_collection_handle_t *handle, netloc_node_t *node) { char *key = NULL; netloc_node_t *cur_node = NULL; unsigned long key_int; /* * Setup the table for the first node */ if(NULL == handle->node_list) { handle->node_list = calloc(1, sizeof(*handle->node_list)); netloc_lookup_table_init(handle->node_list, 1, 0); } /* * Check to see if we have seen this node before */ SUPPORT_CONVERT_ADDR_TO_INT(node->physical_id, handle->network->network_type, key_int); asprintf(&key, "%s", node->physical_id); cur_node = netloc_lookup_table_access_with_int(handle->node_list, key, key_int); if( NULL != cur_node ) { if( NETLOC_NODE_TYPE_INVALID == cur_node->node_type ) { // JJH: We should be able to use 'replace' instead of 'remove' and 'append' // Need to double check ordering. netloc_lookup_table_remove_with_int(handle->node_list, key, key_int); } else { fprintf(stderr, "Warning: A version of this node has already been added to the data set!\n"); fprintf(stderr, "Warning: Support for updating nodes is not yet available\n"); // JJH: Delete the old cached version ? replace it? //json_object_del(handle->node_data_acc, node->physical_id); } } free(key); key = NULL; /* * Add the node to our list */ if( NULL == cur_node ) { cur_node = netloc_dt_node_t_dup(node); cur_node->__uid__ = 0; cur_node->physical_id_int = key_int; asprintf(&key, "%s", node->physical_id); netloc_lookup_table_append_with_int(handle->node_list, key, key_int, cur_node); /* * Encode the data: Physical ID is the key */ json_object_set_new(handle->node_data_acc, node->physical_id, netloc_dt_node_t_json_encode(node)); } else if( NETLOC_NODE_TYPE_INVALID == cur_node->node_type ) { netloc_dt_node_t_copy(node, cur_node); cur_node->__uid__ = 0; cur_node->physical_id_int = key_int; asprintf(&key, "%s", node->physical_id); netloc_lookup_table_append_with_int(handle->node_list, key, key_int, cur_node); /* * Encode the data: Physical ID is the key */ json_object_set_new(handle->node_data_acc, node->physical_id, netloc_dt_node_t_json_encode(node)); } else { /* * Replace the node? * The code below will fix the cache (node_data_acc), but the handle->node_list needs to also be updated. */ //json_object_del(handle->node_data_acc, node->physical_id); //json_object_set_new(handle->node_data_acc, node->physical_id, netloc_dt_node_t_json_encode(node)); return NETLOC_ERROR_NOT_IMPL; } return NETLOC_SUCCESS; }