Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

graph.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003, 2004, 2005 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 
00019 #ifndef QOLYESTER_DAEMON_GRA_GRAPH_HXX
00020 # define QOLYESTER_DAEMON_GRA_GRAPH_HXX 1
00021 
00022 # include "config.hh"
00023 # include <cassert>
00024 # include "graph.hh"
00025 # include "utl/mark.hh"
00026 
00027 namespace olsr {
00028 
00029   extern utl::Mark      routes_recomp;
00030 
00031   namespace gra {
00032 
00033     // The general ctors are pretty straightforward.
00034     AdjInfo::AdjInfo()
00035       : _ep1(),
00036         _ep2(),
00037         _tag(topo)
00038     {}
00039 
00040     AdjInfo::AdjInfo(const address_t& ep1, const address_t& ep2, AdjTag tag)
00041       : _ep1(ep1),
00042         _ep2(ep2),
00043         _tag(tag)
00044     {}
00045 
00046     // The equality operator simply compares endpoints' addresses.
00047     bool                
00048     AdjInfo::operator==(const This& rhs) const {
00049       return _ep1 == rhs._ep1 && _ep2 == rhs._ep2 && _tag == rhs._tag;
00050     }
00051     
00052     const AdjInfo&
00053     AdjInfo::make_key(const address_t& ep1, const address_t& ep2, AdjTag tag) {
00054       const_cast<address_t&>(_dummy_for_find._ep1) = ep1;
00055       const_cast<address_t&>(_dummy_for_find._ep2) = ep2;
00056       const_cast<AdjTag&>(_dummy_for_find._tag) = tag;
00057       return _dummy_for_find;
00058     }
00059 
00060     AdjInfo     
00061     AdjInfo::invert(const This& x) {
00062       return This(x._ep2, x._ep1, x._tag);
00063     }
00064 
00065     // Again, the straightforward ctors
00066     AdjNode::AdjNode() : _endpoint(), _weight(0) {}
00067   
00068     AdjNode::AdjNode(const address_t& ep, unsigned w)
00069       : _endpoint(ep),
00070         _weight(w)
00071     {}
00072 
00073     // The equality operator makes a node unique by its address.
00074     bool
00075     AdjNode::operator==(const This& rhs) const {
00076       return _endpoint == rhs._endpoint;
00077     }
00078 
00079     const AdjNode&
00080     AdjNode::make_key(const address_t& ep) {
00081       const_cast<address_t&>(_dummy_for_find._endpoint) = ep;
00082       return _dummy_for_find;
00083     }
00084 
00085     // Also straightforward graph ctors
00086     AdjGraph::AdjGraph()
00087       : _aset(),
00088         _nset(),
00089         _apset_map()
00090     {}
00091 
00092     AdjGraph::AdjGraph(const This& other)
00093       : _aset(other._aset),
00094         _nset(other._nset),
00095         _apset_map() {
00096       // Update apset_map
00097       build_asetmap();
00098     }
00099 
00100     AdjGraph&
00101     AdjGraph::operator=(const This& other) {
00102       _aset = other._aset;
00103       _nset = other._nset;
00104       _apset_map.clear();
00105       // Update apset_map
00106       build_asetmap();
00107       return *this;
00108     }
00109 
00110     std::pair<AdjGraph::nset_t::const_iterator, bool>
00111     AdjGraph::insert_node(const AdjNode& n) {
00112       // First, insert the node into the node set.
00113       std::pair<nset_t::iterator, bool> p =
00114         nset_t::iterator::build(_nset.insert(n));
00115       // Then, if the node wasn't already in the set, create a new entry
00116       // in the apset_map.
00117       if (p.second) {
00118 # ifndef NDEBUG
00119         assert(_apset_map.insert(apsetmap_t::value_type(&*p.first,
00120                                                         apset_t())).second);
00121 # else
00122         _apset_map.insert(apsetmap_t::value_type(&*p.first, apset_t()));
00123 # endif
00124       }
00125       // Ensure that the apset_map is not corrupted.
00126       assert(_apset_map.find(&*p.first) != _apset_map.end());
00127       return p;
00128     }
00129 
00130     std::pair<AdjGraph::aset_t::const_iterator, bool>
00131     AdjGraph::insert_arc(const AdjInfo& a) {
00132       // First, find the endpoints.
00133       nset_t::const_iterator n1 = _nset.find(AdjNode::make_key(a.endpoint1()));
00134       nset_t::const_iterator n2 = _nset.find(AdjNode::make_key(a.endpoint2()));
00135       // Ensure that the endpoints exist.
00136       assert(n1 != _nset.end());
00137       assert(n2 != _nset.end());
00138       // Insert the arc
00139       std::pair<aset_t::iterator, bool> p = _aset.insert(a);
00140       // If the arc wasn't already in the arc set, create two new
00141       // entries in the apset_map, one for each endpoint and mark the
00142       // routes for recalculation.
00143       if (p.second) {
00144         _apset_map[&*n1].insert(&*p.first);
00145         _apset_map[&*n2].insert(&*p.first);
00146       }
00147       return p;
00148     }      
00149 
00150     // This is a non-directed version, to quickly insert two arcs, one
00151     // in each direction.
00152     void
00153     AdjGraph::insert_edge(const AdjInfo& a) {
00154       insert_arc(a);
00155       insert_arc(AdjInfo::invert(a));
00156     }
00157 
00158     void
00159     AdjGraph::remove_arc(aset_t::iterator pos) {
00160       // Ensure that the iterator is not invalid (by far not exhaustive check).
00161       assert(pos != _aset.end());
00162       // Find the two endpoints.
00163       nset_t::const_iterator n1 = _nset.find(AdjNode::make_key(pos->endpoint1()));
00164       nset_t::const_iterator n2 = _nset.find(AdjNode::make_key(pos->endpoint2()));
00165       // Ensure that the enpoints exist.
00166       assert(n1 != _nset.end());
00167       assert(n2 != _nset.end());
00168       // Remove the arc from the apset_map.
00169       _apset_map[&*n1].erase(&*pos);
00170       _apset_map[&*n2].erase(&*pos);
00171       // Remove the arc from the arc set.
00172       _aset.erase(pos);
00173     }
00174 
00175     // This is a variant in case we don't have any iterator on the arc
00176     // we want to remove.
00177     void
00178     AdjGraph::remove_arc(const AdjInfo& a) {
00179       aset_t::iterator  pos = _aset.find(a);
00180       if (pos != _aset.end())
00181         remove_arc(pos);
00182     }
00183 
00184     // This is a non-directed version, to quickly remove two arcs, one
00185     // in each direction.
00186     void
00187     AdjGraph::remove_edge(aset_t::iterator pos) {
00188       remove_arc(AdjInfo::invert(*pos));
00189       remove_arc(pos);
00190     }
00191 
00192     // This is a variant in case we don't have any iterator on the arc
00193     // we want to remove.
00194     void
00195     AdjGraph::remove_edge(const AdjInfo& a) {
00196       remove_arc(a);
00197       remove_arc(AdjInfo::invert(a));
00198     }
00199 
00200     // Yet another variant of arc removal.  This time we want to remove
00201     // the endpoints if the removal of the arc leaves the node
00202     // unconnected.
00203     void
00204     AdjGraph::remove_arc_then_node(aset_t::iterator pos) {
00205       nset_t::iterator  n1 = _nset.find(AdjNode::make_key(pos->endpoint1()));
00206       nset_t::iterator  n2 = _nset.find(AdjNode::make_key(pos->endpoint2()));
00207       assert(n1 != _nset.end());
00208       assert(n2 != _nset.end());
00209       remove_arc(pos);
00210       if (_apset_map[&*n1].size() == 0)
00211         remove_node(n1);
00212       if (_apset_map[&*n2].size() == 0)
00213         remove_node(n2);
00214     }
00215 
00216     // A no-iterator variant of the yet-another-variant.
00217     void
00218     AdjGraph::remove_arc_then_node(const AdjInfo& a) {
00219       aset_t::iterator  pos = _aset.find(a);
00220       if (pos != _aset.end())
00221         remove_arc_then_node(pos);
00222     }
00223 
00224     // The non-directed variant of the yet-another-variant.
00225     void
00226     AdjGraph::remove_edge_then_node(aset_t::iterator pos) {
00227       remove_arc_then_node(AdjInfo::invert(*pos));
00228       remove_arc_then_node(pos);
00229     }
00230 
00231     // The non-directed-no-iterater one.
00232     void
00233     AdjGraph::remove_edge_then_node(const AdjInfo& a) {
00234       remove_arc_then_node(a);
00235       remove_arc_then_node(AdjInfo::invert(a));
00236     }
00237     
00238     // Node removal taking care of the removal of all the arcs which
00239     // endpoint was the removed node.
00240     void
00241     AdjGraph::remove_node(nset_t::iterator pos) {
00242       // Ensure the iterator is not invalid (by far not exhaustive check).
00243       assert(pos != _nset.end());  
00244       // Mark the routes to be recalculated.
00245       routes_recomp.set_mark();
00246       // Find the set of arcs which have the node as either endpoint.
00247       apsetmap_t::iterator      ap = _apset_map.find(&*pos);
00248       // Ensure that the apset_map is not corrupted.
00249       assert(ap != _apset_map.end());
00250       // Iterator over the set of arcs.
00251       apset_t&          pos_as = ap->second;
00252       for (apset_t::iterator i = pos_as.begin(); i != pos_as.end(); ++i) {
00253         // Get the other endpoint of the current arc.
00254         nset_t::const_iterator  other;
00255         if (pos->endpoint() == (*i)->endpoint1())
00256           other = _nset.find(AdjNode::make_key((*i)->endpoint2()));
00257         else
00258           other = _nset.find(AdjNode::make_key((*i)->endpoint1()));
00259         // Ensure that the other endpoint exists.
00260         assert(other != _nset.end());
00261         // Get the set of arcs of the other endpoint.
00262         apsetmap_t::iterator    ap2 = _apset_map.find(&*other);
00263         // Ensure that this set of arcs exists.
00264         assert(ap2 != _apset_map.end());
00265         // Remove the current arc from the other set.
00266         ap2->second.erase(*i);
00267         // Remove the current arc from the current set.
00268         _aset.erase(**i);
00269       }
00270       // Remove the node from the apset_map.
00271       _apset_map.erase(&*pos);
00272       // Remove the node from the node set.
00273       _nset.erase(pos);
00274     }
00275 
00276     // The no-iterator variant.
00277     void
00278     AdjGraph::remove_node(const AdjNode& n) {
00279       nset_t::iterator  pos = _nset.find(n);
00280       if (pos != _nset.end())
00281         remove_node(pos);
00282     }
00283 
00284     void
00285     AdjGraph::remove_node_if_alone(nset_t::iterator pos) {
00286       assert(pos != _nset.end());
00287       if (_apset_map[&*pos].empty())
00288         remove_node(pos);
00289     }
00290 
00291     // A convenience routine to remove a node if it is isolated.
00292     void
00293     AdjGraph::remove_node_if_alone(const AdjNode& n) {
00294       nset_t::iterator  pos = _nset.find(n);
00295       if (pos != _nset.end())
00296         remove_node_if_alone(pos);
00297     }
00298   
00299     // The routine to update the apset_map.
00300     void
00301     AdjGraph::build_asetmap() {
00302       // Iterate over the arc set.
00303       for (aset_t::const_iterator a = _aset.begin(); a != _aset.end(); ++a) {
00304         // Get the endpoints.
00305         nset_t::const_iterator n1 = _nset.find(AdjNode::make_key(a->endpoint1()));
00306         nset_t::const_iterator n2 = _nset.find(AdjNode::make_key(a->endpoint2()));
00307         // Ensure they exist.
00308         assert(n1 != _nset.end());
00309         assert(n2 != _nset.end());
00310         // Insert the arc into the apset_map for either endpoint.
00311         _apset_map[&*n1].insert(&*a);
00312         _apset_map[&*n2].insert(&*a);
00313       }
00314     }
00315 
00316   } // namespace gra
00317   
00318 } // namespace olsr
00319 
00320 #endif // ! QOLYESTER_DAEMON_GRA_GRAPH_HXX

Generated on Thu Jul 28 21:21:47 2005 for Qolyester daemon by  doxygen 1.4.1