/* * EMULAB-COPYRIGHT * Copyright (c) 2000-2003 University of Utah and the Flux Group. * All rights reserved. */ #include "port.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace boost; #include "common.h" #include "delay.h" #include "physical.h" #include "virtual.h" #include "vclass.h" #include "pclass.h" #include "score.h" #include "solution.h" #include "maps.h" #include "anneal.h" // Here we set up all our graphs. Need to create the graphs // themselves and then setup the property maps. tb_pgraph PG; tb_pgraph_vertex_pmap pvertex_pmap = get(vertex_data, PG); tb_pgraph_edge_pmap pedge_pmap = get(edge_data, PG); tb_sgraph SG; tb_sgraph_vertex_pmap svertex_pmap = get(vertex_data, SG); tb_sgraph_edge_pmap sedge_pmap = get(edge_data, SG); tb_vgraph VG; tb_vgraph_vertex_pmap vvertex_pmap = get(vertex_data, VG); tb_vgraph_edge_pmap vedge_pmap = get(edge_data, VG); // A simple list of physical types. name_count_map ptypes; // List of virtual types by name. name_count_map vtypes; name_list_map vclasses; // A list of all pclasses. pclass_list pclasses; // Map from a pnode* to the the corresponding pvertex. pnode_pvertex_map pnode2vertex; // Map of a type to a tt_entry, a vector of pclasses and the size of // the vector. pclass_types type_table; #ifdef PER_VNODE_TT pclass_types vnode_type_table; #endif // This datastructure contains all the information needed to calculate // the shortest path between any two switches. Indexed by svertex, // the value will be a predicate map (indexed by svertex as well) of // the shortest paths for the given vertex. switch_pred_map_map switch_preds; // Same, but for distances switch_dist_map_map switch_dist; // Time started, finished, and the time limit double timestart, timeend, timelimit, timetarget; // An amount to scale the neighborhood size by double scale_neighborhood = 1.0; #ifdef GNUPLOT_OUTPUT FILE *scoresout, *tempout, *deltaout; #endif // Whether or not assign is allowed to generate trivial links bool allow_trivial_links = true; // Whether or not assign should use pclasses bool disable_pclasses = false; // Whether or not assign should prune out pclasses that it knows can // never be used bool prune_pclasses = false; // Whether or not we should use the experimental support for dynamic pclasses bool dynamic_pclasses = false; // Whether or not to allow assign to temporarily over-subscribe pnodes bool allow_overload = false; // XXX - shouldn't be in this file double absbest; int absbestviolated, iters, iters_to_best; /* * Internal functions */ // Return the CPU time (in seconds) used by this process float used_time() { struct rusage ru; getrusage(RUSAGE_SELF,&ru); return ru.ru_utime.tv_sec+ru.ru_utime.tv_usec/1000000.0+ ru.ru_stime.tv_sec+ru.ru_stime.tv_usec/1000000.0; } // Read in the .ptop file void read_physical_topology(char *filename) { ifstream ptopfile; ptopfile.open(filename); if (!ptopfile.is_open()) { cerr << "Unable to open ptop file " << filename << endl; exit(2); } cout << "Physical Graph: " << parse_ptop(PG,SG,ptopfile) << endl; #ifdef DUMP_GRAPH { cout << "Physical Graph:" << endl; pvertex_iterator vit,vendit; tie(vit,vendit) = vertices(PG); for (;vit != vendit;vit++) { tb_pnode *p = get(pvertex_pmap,*vit); cout << *vit << "\t" << *p; } pedge_iterator eit,eendit; tie(eit,eendit) = edges(PG); for (;eit != eendit;eit++) { tb_plink *p = get(pedge_pmap,*eit); cout << *eit << " (" << source(*eit,PG) << " <-> " << target(*eit,PG) << ")\t" << *p; } } #endif // DUMP_GRAPH #ifdef GRAPH_DEBUG { cout << "Switch Graph:" << endl; svertex_iterator vit,vendit; tie(vit,vendit) = vertices(SG); for (;vit != vendit;vit++) { tb_switch *p = get(svertex_pmap,*vit); cout << *vit << "\t" << *p; } sedge_iterator eit,eendit; tie(eit,eendit) = edges(SG); for (;eit != eendit;eit++) { tb_slink *p = get(sedge_pmap,*eit); cout << *eit << " (" << source(*eit,SG) << " <-> " << target(*eit,SG) << ")\t" << *p; } } #endif // GRAPH_DEBUG // Set up pnode2vertex - a mapping between vertices in the physical graph and // the pnodes that we just read in from the ptop file pvertex_iterator pvit,pvendit; tie(pvit,pvendit) = vertices(PG); for (;pvit != pvendit;pvit++) { pnode2vertex[get(pvertex_pmap,*pvit)]=*pvit; } } // Calculate the minimum spanning tree for the switches - we only consider one // potential path between each pair of switches. void calculate_switch_MST() { cout << "Calculating shortest paths on switch fabric." << endl; // Set up the weight map for Dijkstra's tb_sgraph_weight_pmap sweight_pmap = get(edge_weight, SG); sedge_iterator seit,seendit; tie(seit,seendit) = edges(SG); for (;seit != seendit;seit++) { tb_slink *slink = get(sedge_pmap,*seit); // XXX should we make this more complicated depending on // latency/loss as well? put(sweight_pmap,*seit, 100000000-get(pedge_pmap,slink->mate)->delay_info.bandwidth); } // Let boost do the Disjktra's for us, from each switch svertex_iterator svit,svendit; tie(svit,svendit) = vertices(SG); for (;svit != svendit;svit++) { switch_preds[*svit] = new switch_pred_map(num_vertices(SG)); switch_dist[*svit] = new switch_dist_map(num_vertices(SG)); dijkstra_shortest_paths(SG,*svit, predecessor_map(&((*switch_preds[*svit])[0])). distance_map(&((*switch_dist[*svit])[0]))); } #ifdef GRAPH_DEBUG cout << "Shortest paths" << endl; tie(svit,svendit) = vertices(SG); for (;svit != svendit;svit++) { cout << *svit << ":" << endl; for (unsigned int i = 0;i " << target(*eit,VG) << ")\t" << *p; } } #endif } /* * Make a pass through the pclasses, looking for ones that no node can use, and * nuking them. */ void prune_unusable_pclasses() { cout << "Pruning pclasses." << endl; int pruned = 0; pclass_list::iterator pclass_iterator = pclasses.begin(); while (pclass_iterator != pclasses.end()) { if ((*pclass_iterator)->refcount == 0) { pclass_list::iterator nukeme = pclass_iterator; pclass_iterator++; #ifdef PCLASS_DEBUG cout << "Pruning " << (*nukeme)->name << endl; #endif pruned++; delete *nukeme; pclasses.erase(nukeme); } else { pclass_iterator++; } } cout << "pclass pruning complete: removed " << pruned << " pclasses, " << pclasses.size() << " remain." << endl; } void print_help() { cerr << "assign [options] ptopfile topfile [config params]" << endl; cerr << "Options: " << endl; #ifdef TIME_TERMINATE cerr << " -l