00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef QOLYESTER_DAEMON_ALG_DIJKSTRA_HXX
00020 # define QOLYESTER_DAEMON_ALG_DIJKSTRA_HXX 1
00021
00022 # include <ext/hash_map>
00023
00024 # include "gra/graph.hh"
00025 # include "net/ipaddress.hh"
00026 # include "utl/comparator.hh"
00027 # include "utl/log.hh"
00028
00029 # include "dijkstra.hh"
00030
00031 namespace olsr {
00032
00033 extern debug_ostream_t debug;
00034 extern gra::AdjGraph path_net;
00035
00036 namespace alg {
00037
00038
00039
00040
00041
00042 typedef std::hash_map<address_t, unsigned> weightmap_t;
00043 typedef std::hash_map<address_t, address_t> nextmap_t;
00044 typedef std::hash_map<address_t, unsigned> hopsmap_t;
00045
00046
00047 struct sort_less {
00048
00049
00050 sort_less(const hopsmap_t& hm,
00051 const weightmap_t& wm)
00052 : _hm(hm),
00053 _wm(wm)
00054 {}
00055
00056 bool operator()(const gra::AdjNode* a, const gra::AdjNode* b) const {
00057
00058 weightmap_t::const_iterator wa = _wm.find(a->endpoint());
00059 weightmap_t::const_iterator wb = _wm.find(b->endpoint());
00060
00061 hopsmap_t::const_iterator ha = _hm.find(a->endpoint());
00062 hopsmap_t::const_iterator hb = _hm.find(b->endpoint());
00063
00064
00065
00066
00067 if (wb == _wm.end())
00068 if (wa == _wm.end())
00069 return a->endpoint() < b->endpoint();
00070 else
00071 return true;
00072
00073 if (wa == _wm.end())
00074 return false;
00075
00076 if (wa->second > wb->second)
00077 return true;
00078 else if (wa->second < wb->second)
00079 return false;
00080
00081 if (hb == _hm.end())
00082 if (ha == _hm.end())
00083 return a->endpoint() < b->endpoint();
00084 else
00085 return true;
00086
00087 if (ha == _hm.end())
00088 return false;
00089
00090
00091
00092
00093 if (ha->second < hb->second)
00094 return true;
00095 else if (hb->second < ha->second)
00096 return false;
00097
00098
00099 if (b->weight() < a->weight())
00100 return true;
00101 else if (a->weight() < b->weight())
00102 return false;
00103
00104
00105 return a->endpoint() < b->endpoint();
00106 }
00107 private:
00108 const hopsmap_t& _hm;
00109 const weightmap_t& _wm;
00110 };
00111
00112
00113 typedef std::hash_set<const gra::AdjNode*,
00114 gra::hash_AdjNode,
00115 utl::pequal_to<gra::AdjNode> > npset_t;
00116
00117
00118 typedef std::set<const gra::AdjNode*, sort_less> sortremaining_t;
00119
00120
00121
00122
00123 void dijkstra(rrouteset_t& routes,
00124 std::map<address_t, address_t>& sources_map) {
00125 nextmap_t next_map;
00126 hopsmap_t hops_map;
00127 weightmap_t weight_map;
00128
00129 debug << path_net << std::endl;
00130
00131 npset_t rem;
00132
00133
00134 for (gra::nodeset_t::const_iterator n = path_net.nodes().begin();
00135 n != path_net.nodes().end(); ++n)
00136 rem.insert(&*n);
00137
00138 debug << "dijkstra {\n";
00139
00140
00141
00142 debug << " sources {";
00143 for (std::map<address_t, address_t>::const_iterator s =
00144 sources_map.begin();
00145 s != sources_map.end(); ++s) {
00146 pathnet_t::nset_t::const_iterator n =
00147 path_net.nodes().find(gra::AdjNode::make_key(s->first));
00148 assert(n != path_net.nodes().end());
00149 debug << " " << s->first;
00150 next_map[s->first] = s->first;
00151 hops_map[s->first] = 0;
00152 weight_map[s->first] = n->weight();
00153 }
00154 debug << " }\n";
00155
00156
00157 while (!hops_map.empty()) {
00158 assert(!rem.empty());
00159
00160
00161 sortremaining_t srem(rem.begin(), rem.end(),
00162 sort_less(hops_map, weight_map));
00163
00164 debug << " round {\n";
00165 for (sortremaining_t::const_iterator i = srem.begin();
00166 i != srem.end(); ++i) {
00167 debug << " " << (*i)->endpoint() << " ";
00168 nextmap_t::const_iterator n = next_map.find((*i)->endpoint());
00169 hopsmap_t::const_iterator h = hops_map.find((*i)->endpoint());
00170 weightmap_t::const_iterator w = weight_map.find((*i)->endpoint());
00171 if (n == next_map.end())
00172 debug << "_ ";
00173 else
00174 debug << next_map[(*i)->endpoint()] << " ";
00175 if (h == hops_map.end())
00176 debug << "_ ";
00177 else
00178 debug << h->second << " ";
00179 if (w == weight_map.end())
00180 debug << "_\n";
00181 else
00182 debug << w->second << "\n";
00183 }
00184 debug << " }" << std::endl;
00185
00186
00187
00188
00189 const gra::AdjNode& closest = **srem.begin();
00190
00191
00192 rem.erase(&closest);
00193 srem.erase(&closest);
00194
00195
00196
00197 hopsmap_t::iterator hops = hops_map.find(closest.endpoint());
00198 nextmap_t::iterator next = next_map.find(closest.endpoint());
00199 weightmap_t::iterator weight = weight_map.find(closest.endpoint());
00200
00201 if (hops == hops_map.end() ||
00202 next == next_map.end() ||
00203 weight == weight_map.end())
00204 break;
00205
00206 unsigned next_hops = hops->second + 1;
00207
00208
00209 hops_map.erase(hops);
00210 weight_map.erase(weight);
00211
00212 if (closest.weight() == 0)
00213 continue;
00214
00215
00216
00217
00218 for (npset_t::const_iterator n = rem.begin(); n != rem.end(); ++n) {
00219
00220
00221 pathnet_t::aset_t::const_iterator a =
00222 path_net.arcs().find(gra::AdjInfo::make_key(closest.endpoint(),
00223 (*n)->endpoint(),
00224 topo));
00225
00226
00227
00228
00229 if (a == path_net.arcs().end() &&
00230 sources_map.find(closest.endpoint()) != sources_map.end())
00231 a = path_net.arcs().find(gra::AdjInfo::make_key(closest.endpoint(),
00232 (*n)->endpoint(),
00233 twohop));
00234
00235 if (a != path_net.arcs().end()) {
00236
00237
00238 unsigned next_weight = MAX(weight->second,
00239 (*n)->weight());
00240
00241 hopsmap_t::iterator h = hops_map.find((*n)->endpoint());
00242 weightmap_t::iterator w = weight_map.find((*n)->endpoint());
00243 if (((w == weight_map.end() || w->second <= next_weight) &&
00244 (h == hops_map.end() || h->second > next_hops)) ||
00245 ((w == weight_map.end() || w->second < next_weight) &&
00246 (h == hops_map.end() || h->second >= next_hops))) {
00247 weight_map[(*n)->endpoint()] = next_weight;
00248 hops_map[(*n)->endpoint()] = next_hops;
00249 next_map[(*n)->endpoint()] = next->second;
00250 }
00251 }
00252 }
00253 }
00254
00255
00256 for (std::map<address_t, address_t>::const_iterator s =
00257 sources_map.begin();
00258 s != sources_map.end(); ++s)
00259 next_map.erase(s->first);
00260
00261
00262 for (nextmap_t::const_iterator i = next_map.begin();
00263 i != next_map.end(); ++i) {
00264 debug << " route { " << i->first << " : " << i->second << " }\n";
00265
00266 std::map<address_t, address_t>::iterator m =
00267 sources_map.find(i->second);
00268 if (m != sources_map.end())
00269 routes.insert(net::RemoteRoute(i->first, ADDRESS_SIZE * 8,
00270 m->second));
00271 else
00272 routes.insert(net::RemoteRoute(i->first, ADDRESS_SIZE * 8,
00273 i->second));
00274 }
00275
00276 debug << "}" << std::endl;;
00277 }
00278
00279 }
00280
00281 }
00282
00283 #endif // !QOLYESTER_DAEMON_ALG_DIJKSTRA_HXX