NetworkGraph.cpp

Go to the documentation of this file.
00001 /****************** <VPR heading BEGIN do not edit this line> *****************
00002  *
00003  * VR Juggler Portable Runtime
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Patrick Hartling, Kevin Meinert, Carolina Cruz-Neira
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile$
00010  * Date modified: $Date: 2005-01-17 22:34:01 -0600 (Mon, 17 Jan 2005) $
00011  * Version:       $Revision: 16635 $
00012  * -----------------------------------------------------------------
00013  *
00014  ****************** <VPR heading END do not edit this line> ******************/
00015 
00016 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00017  *
00018  * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
00019  *
00020  * Original Authors:
00021  *   Allen Bierbaum, Christopher Just,
00022  *   Patrick Hartling, Kevin Meinert,
00023  *   Carolina Cruz-Neira, Albert Baker
00024  *
00025  * This library is free software; you can redistribute it and/or
00026  * modify it under the terms of the GNU Library General Public
00027  * License as published by the Free Software Foundation; either
00028  * version 2 of the License, or (at your option) any later version.
00029  *
00030  * This library is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033  * Library General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU Library General Public
00036  * License along with this library; if not, write to the
00037  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00038  * Boston, MA 02111-1307, USA.
00039  *
00040  *************** <auto-copyright.pl END do not edit this line> ***************/
00041 
00042 #include <vpr/vprConfig.h>
00043 
00044 #include <fstream>
00045 #include <map>
00046 #include <boost/utility.hpp>
00047 #include <boost/graph/dijkstra_shortest_paths.hpp>
00048 #include <vpr/Util/Debug.h>
00049 #include <vpr/Util/Assert.h>
00050 
00051 #include <vpr/md/SIM/Network/NetworkGraph.h>
00052 
00053 
00054 namespace vpr
00055 {
00056 
00057 namespace sim
00058 {
00059 
00060 // Crummy helper for crappy C++ I/O.
00061 static void skipToEOL(std::istream& stream)
00062 {
00063    char c;
00064 
00065    while ( (c = stream.get()) != '\n' )
00066    {
00067       /* Loop. */ ;
00068    }
00069 }
00070 
00071 vpr::ReturnStatus NetworkGraph::construct(const std::string& path)
00072 {
00073    vpr::ReturnStatus status;
00074    std::ifstream input_file(path.c_str());
00075 
00076    if ( input_file.is_open() )
00077    {
00078       vpr::Uint32 node_count, full_edge_count, half_edge_count;
00079       std::map<int, boost::graph_traits<net_graph_t>::vertex_descriptor> vertex_map;
00080       std::string temp_str;
00081       vpr::Uint32 index, last_index, localhost_index;
00082       vpr::Uint16 node_type;
00083 
00084       input_file >> node_count;
00085 
00086       for ( vpr::Uint32 i = 0; i < node_count; ++i )
00087       {
00088          std::string node_ip;
00089 
00090          input_file >> index >> node_type >> node_ip;
00091          skipToEOL(input_file);
00092 
00093          // Now create the vertex and add it to the graph.
00094          NetworkNodePtr node_prop( new NetworkNode(index, node_type, node_ip) );
00095          vertex_map[index] = boost::add_vertex(NodeProperty( node_prop),
00096                                                mGraph);
00097       }
00098 
00099       // Add a node to the graph that will represent localhost.  It will have
00100       // an edge to the last node added to the graph.
00101       // index and node_type will have the values of the last vertex added to
00102       // the graph.  We will use this vertex to represent localhost.
00103       last_index      = index;
00104       localhost_index = last_index + 1;
00105       NetworkNodePtr node_prop(new NetworkNode(localhost_index, node_type,
00106                                                std::string("127.0.0.1")));
00107       vprASSERT(vertex_map.count(localhost_index) == 0 && "The index for localhost is already in use");
00108       vertex_map[localhost_index] = boost::add_vertex(NodeProperty(node_prop),
00109                                                       mGraph);
00110 
00111       input_file >> full_edge_count;
00112 
00113       // The file format tells us that there are twice as many edges as
00114       // actually listed--probably to indicate bidirectional links.
00115       half_edge_count = full_edge_count / 2;
00116 
00117       net_edge_t new_edge;
00118       bool added;
00119       boost::property_map<net_graph_t, boost::edge_weight_t>::type weight_map;
00120       weight_map = boost::get(boost::edge_weight_t(), mGraph);
00121 
00122       // This is outside the loop so that it can be used when making the
00123       // loopback link for localhost.
00124       vpr::Uint16 net_id;
00125 
00126       for ( vpr::Uint32 i = 0; i < full_edge_count; ++i )
00127       {
00128          double length, delay, bw;
00129          vpr::Uint32 from_node, to_node;
00130          std::string net_type, net_ip;
00131 
00132          input_file >> from_node >> to_node >> length >> delay >> bw
00133                     >> net_type >> net_id >> net_ip;
00134 
00135          // This is here mainly for debugging this clunky "parser".
00136          vprDEBUG(vprDBG_ALL, vprDBG_HVERB_LVL)
00137             << "Loading edge #" << i << ": (" << from_node << " --> "
00138             << to_node << ", " << length << " miles, " << delay << " us, "
00139             << bw << " Mbps, type: " << net_type << ", ID: " << net_id << ", "
00140             << net_ip << ")\n" << vprDEBUG_FLUSH;
00141 
00142          // Now add the edge to the graph.
00143          NetworkLine line(length, bw, delay, net_type, net_id, net_ip);
00144          boost::tie(new_edge, added) = boost::add_edge(vertex_map[from_node],
00145                                                        vertex_map[to_node],
00146                                                        LineProperty(line),
00147                                                        mGraph);
00148 
00149          if ( added )
00150          {
00151             weight_map[new_edge] = line.getWeight();
00152          }
00153 
00154          // Sanity check to ensure that we do not get stuck trying to read
00155          // bytes that aren't there.  This probably slows things down, but I
00156          // don't know of a better way to do this.
00157          if ( input_file.peek() == EOF && i + 1 < full_edge_count )
00158          {
00159             vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00160                << "WARNING: Expected " << full_edge_count
00161                << " edges, found " << i + 1 << std::endl << vprDEBUG_FLUSH;
00162             break;
00163          }
00164       }
00165 
00166       // Make a very, very short, very, very high-bandwidth link for the
00167       // localhost loopback.
00168       NetworkLine line(0.0000001f, 100000, 0.0000001f, std::string("LOOPBACK"),
00169                        net_id, std::string("127.0.0.0"));
00170       boost::tie(new_edge, added) = boost::add_edge(vertex_map[localhost_index],
00171                                                     vertex_map[last_index],
00172                                                     LineProperty(line),
00173                                                     mGraph);
00174       vprASSERT(added && "Addition of loopback line for localhost failed");
00175       weight_map[new_edge] = line.getWeight();
00176 
00177       mGraphValid = true;
00178    }
00179    else
00180    {
00181       vprDEBUG(vprDBG_ALL, vprDBG_CRITICAL_LVL)
00182          << "ERROR: Failed to open graph input file named " << path
00183          << std::endl << vprDEBUG_FLUSH;
00184       status.setCode(vpr::ReturnStatus::Fail);
00185    }
00186 
00187    return status;
00188 }
00189 
00190 vpr::sim::NetworkLine& NetworkGraph::getLineProperty(const NetworkGraph::net_edge_t& e)
00191 {
00192    // XXX: Need to make an assertion that e is in mGraph!
00193 //   vprASSERT(... && "Given edge not found in the graph!");
00194 
00195    boost::property_map<net_graph_t, network_line_t>::type line_prop_map;
00196 
00197    line_prop_map = boost::get(network_line_t(), mGraph);
00198 
00199    return line_prop_map[e];
00200 }
00201 
00202 void NetworkGraph::setLineProperty(const NetworkGraph::net_edge_t& e,
00203                                    const vpr::sim::NetworkLine& prop)
00204 {
00205    // XXX: Need to make an assertion that e is in mGraph!
00206 //   vprASSERT(... && "Given edge not found in the graph!");
00207 
00208    boost::property_map<net_graph_t, network_line_t>::type line_prop_map;
00209 
00210    line_prop_map    = boost::get(network_line_t(), mGraph);
00211    line_prop_map[e] = prop;
00212 }
00213 
00214 vpr::ReturnStatus NetworkGraph::getNodeWithAddr(const vpr::Uint32 addr,
00215                                                 NetworkGraph::net_vertex_t& node)
00216 {
00217    vprASSERT(isValid() && "Trying to use invalid graph");
00218 
00219    vpr::ReturnStatus status(vpr::ReturnStatus::Fail);
00220    boost::graph_traits<net_graph_t>::vertex_iterator vi, vi_end;
00221    NetworkNodePtr node_prop;
00222 
00223    boost::tie(vi, vi_end) = boost::vertices(mGraph);
00224 
00225    for ( ; vi != vi_end; ++vi )
00226    {
00227       node_prop = getNodeProperty(*vi);
00228 
00229       if ( node_prop->getIpAddress() == addr )
00230       {
00231          node = *vi;
00232          status.setCode(vpr::ReturnStatus::Succeed);
00233          break;
00234       }
00235    }
00236 
00237    return status;
00238 }
00239 
00240 vpr::sim::NetworkNodePtr NetworkGraph::getNodeProperty(const NetworkGraph::net_vertex_t& v)
00241 {
00242    // XXX: Need to make an assertion that v is in mGraph!
00243 //   vprASSERT(... && "Given vertex not found in the graph!");
00244 
00245    boost::property_map<net_graph_t, network_node_t>::type node_prop_map;
00246 
00247    node_prop_map = boost::get(network_node_t(), mGraph);
00248 
00249    return node_prop_map[v];
00250 }
00251 
00252 void NetworkGraph::setNodeProperty(const NetworkGraph::net_vertex_t& v,
00253                                    vpr::sim::NetworkNodePtr prop)
00254 {
00255    // XXX: Need to make an assertion that v is in mGraph!
00256 //   vprASSERT(... && "Given vertex not found in the graph!");
00257 
00258    boost::property_map<net_graph_t, network_node_t>::type node_prop_map;
00259 
00260    node_prop_map    = boost::get(network_node_t(), mGraph);
00261    node_prop_map[v] = prop;
00262 }
00263 
00264 NetworkGraph::VertexListPtr NetworkGraph::getShortestPath(const NetworkGraph::net_vertex_t& src,
00265                                                           const NetworkGraph::net_vertex_t& dest)
00266    const
00267 {
00268    NetworkGraph::VertexListPtr vlist(new NetworkGraph::VertexList);
00269    std::vector<int> dist(boost::num_vertices(mGraph));
00270    std::vector<net_vertex_t> pred(boost::num_vertices(mGraph));
00271    NetworkGraph::net_vertex_t p(dest), q;
00272    boost::property_map<net_graph_t, network_node_t>::const_type node_prop_map;
00273    boost::property_map<net_graph_t, boost::edge_weight_t>::const_type weight_map;
00274 
00275    // NOTE: There is no default constructor for this type.  The copy
00276    // constructor must be used.
00277    boost::property_map<net_graph_t, boost::vertex_index_t>::const_type vertex_map
00278       = boost::get(boost::vertex_index_t(), mGraph);
00279 
00280    node_prop_map = boost::get(network_node_t(), mGraph);
00281    weight_map    = boost::get(boost::edge_weight_t(), mGraph);
00282 
00283    vprASSERT(boost::out_degree(src, mGraph) > 0 && "No outgoing edges from source");
00284    vprASSERT(boost::out_degree(dest, mGraph) > 0 && "No outgoing edges from destination");
00285 
00286    vprDEBUG_BEGIN(vprDBG_ALL, vprDBG_STATE_LVL)
00287       << "NetworkGraph::getShortestPath(): Looking up the shortest path "
00288       << "between " << node_prop_map[src]->getIpAddressString() << " and "
00289       << node_prop_map[dest]->getIpAddressString() << "\n" << vprDEBUG_FLUSH;
00290 
00291 //   boost::dijkstra_shortest_paths(mGraph, src,
00292 //                                  boost::distance_map(&dist[0]).predecessor_map(&pred[0]));
00293    boost::dijkstra_shortest_paths(mGraph, src, &pred[0], &dist[0], weight_map,
00294                                   vertex_map, std::less<int>(),
00295                                   boost::closed_plus<int>(),
00296                                   std::numeric_limits<int>::max(), 0,
00297                                   boost::default_dijkstra_visitor());
00298 
00299    vlist->push_back(dest);
00300 
00301    vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL)
00302       << "Path (dest <-- src): " << node_prop_map[dest]->getIpAddressString()
00303       << vprDEBUG_FLUSH;
00304 
00305    // Put the vertices returned in the predecessor map into a stack so that
00306    // we can reverse the order and put them into vlist.
00307    while ( (q = pred[p]) != p )
00308    {
00309       vprDEBUG_CONT(vprDBG_ALL, vprDBG_VERB_LVL)
00310          << " <-- " << node_prop_map[q]->getIpAddressString()
00311          << vprDEBUG_FLUSH;
00312 
00313       vlist->push_back(q);
00314       p = q;
00315    }
00316 
00317    vprDEBUG_CONT_END(vprDBG_ALL, vprDBG_STATE_LVL) << "\n" << vprDEBUG_FLUSH;
00318    vprASSERT(p == src && "Destination is unreachable from source!");
00319 
00320    std::reverse(vlist->begin(), vlist->end());
00321 
00322    return vlist;
00323 }
00324 
00325 NetworkGraph::VertexListPtr NetworkGraph::reversePath(NetworkGraph::VertexListPtr path)
00326 {
00327    VertexListPtr new_path(new NetworkGraph::VertexList(path->size()));
00328 
00329    for ( vpr::Uint32 i = path->size(), j = 0; i > 0; i--, ++j )
00330    {
00331       (*new_path)[j] = (*path)[i - 1];
00332    }
00333 
00334    return new_path;
00335 }
00336 
00337 vpr::ReturnStatus NetworkGraph::getAllAddresses(NetworkGraph::AddressList& list)
00338 {
00339    vpr::ReturnStatus status;
00340    boost::graph_traits<net_graph_t>::vertex_iterator vi, vi_end;
00341    NetworkNodePtr node_prop;
00342 
00343    boost::tie(vi, vi_end) = boost::vertices(mGraph);
00344 
00345    for ( ; vi != vi_end; ++vi )
00346    {
00347       node_prop = getNodeProperty(*vi);
00348       list.push_back(std::pair<net_vertex_t, vpr::Uint32>(*vi,
00349                                                           node_prop->getIpAddress()));
00350    }
00351 
00352    return status;
00353 }
00354 
00355 } // End of sim namespace
00356 
00357 } // End of vpr namespace

Generated on Thu Jan 4 10:52:10 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1