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