00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef QOLYESTER_DAEMON_SET_NEIGHBORS_HXX
00021 # define QOLYESTER_DAEMON_SET_NEIGHBORS_HXX 1
00022
00023 # include "alg/mainaddrof.hh"
00024 # include "gra/graph.hh"
00025 # include "utl/mark.hh"
00026
00027 namespace olsr {
00028
00029 extern sched_t scheduler;
00030 extern utl::Mark mprset_recomp;
00031 extern utl::Mark advset_changed;
00032 extern pathnet_t path_net;
00033 extern cproxy_t cproxy;
00034
00035 namespace set {
00036
00037 # ifdef QOLYESTER_ENABLE_LINKHYS
00038 Link::LinkQuality::LinkQuality(Link& i, float v)
00039 : value_(v),
00040 instance_(i),
00041 expired_(0),
00042 blocked_(false) {
00043 assert(0.f <= v && v <= 1.f);
00044 }
00045
00046 Link::LinkQuality&
00047 Link::LinkQuality::operator++() {
00048
00049 debug << up << "LinkQuality::++(): "
00050 << instance_.local_addr() << " -> " << instance_.remote_addr()
00051 << ' ' << of(value_) << " -> ";
00052 value_ *= 1 - cst::hyst_scaling;
00053 value_ += cst::hyst_scaling;
00054 debug << of(value_) << std::endl << down;
00055 update();
00056 return *this;
00057 }
00058
00059 Link::LinkQuality&
00060 Link::LinkQuality::operator--() {
00061 if (blocked_) {
00062 debug << up << "LinkQuality::--(): "
00063 << instance_.local_addr() << " -> " << instance_.remote_addr()
00064 << ' ' << of(value_) << " not changed since blocked"
00065 << std::endl << down;
00066 blocked_ = false;
00067 return *this;
00068 }
00069
00070 debug << up << "LinkQuality::--(): "
00071 << instance_.local_addr() << " -> " << instance_.remote_addr()
00072 << ' ' << of(value_) << " -> ";
00073 value_ *= 1 - cst::hyst_scaling;
00074 debug << of(value_) << std::endl << down;
00075 update();
00076 return *this;
00077 }
00078
00079 void
00080 Link::LinkQuality:: update() {
00081 if (value_ > cst::hyst_threshold_high) {
00082 instance_.set_pending(false);
00083 instance_.set_losttime(timeval_t::now() - 1000);
00084 } else if (value_ < cst::hyst_threshold_low && !instance_.pending()) {
00085 instance_.set_pending(true);
00086 instance_.set_losttime(timeval_t::now() + cst::neighb_hold_time);
00087 if (instance_.time() < instance_.losttime())
00088 instance_.set_losttime(instance_.time());
00089 }
00090 }
00091
00092 Link::Link()
00093 : l_addr_(),
00094 r_addr_(),
00095 m_addr_(),
00096 asymtime_(0),
00097 symtime_(0),
00098 time_(0),
00099 was_sym_(false),
00100 losttime_(0),
00101 nexttime_(0),
00102 htime_(0),
00103 pending_(false),
00104 quality_(*this, 0),
00105 last_seqnum_(0)
00106 {}
00107
00108 Link::Link(const address_t& l, const address_t& r, const address_t& m,
00109 const timeval_t& v, const seqnum_t& s, const timeval_t& ht)
00110 : l_addr_(l),
00111 r_addr_(r),
00112 m_addr_(m),
00113 asymtime_(0),
00114 symtime_(timeval_t::now() - 1000),
00115 time_(timeval_t::in(v)),
00116 was_sym_(false),
00117 losttime_(timeval_t::now() - 1000),
00118 nexttime_(timeval_t::now() - 1000),
00119 htime_(ht),
00120 pending_(true),
00121 quality_(*this),
00122 last_seqnum_(s)
00123 {}
00124
00125 Link::Link(const This& other)
00126 : Super(other),
00127 l_addr_(other.l_addr_),
00128 r_addr_(other.r_addr_),
00129 m_addr_(other.m_addr_),
00130 asymtime_(other.asymtime_),
00131 symtime_(other.symtime_),
00132 time_(other.time_),
00133 was_sym_(other.was_sym_),
00134 losttime_(other.losttime_),
00135 nexttime_(other.nexttime_),
00136 htime_(other.htime_),
00137 pending_(other.pending_),
00138 quality_(*this, other.quality_),
00139 last_seqnum_(other.last_seqnum_)
00140 {}
00141
00142 void
00143 Link::set_last_seqnum(const seqnum_t& s) {
00144 if (s != ++last_seqnum_) {
00145 debug << "--quality(" << m_addr_ << "): lost packet (expected "
00146 << last_seqnum_ << ", but got " << s << ')' << std::endl;
00147 quality_.lost(s > last_seqnum_ ? s - last_seqnum_ : 0);
00148 --quality_;
00149 cproxy.update_state(main_addr());
00150 last_seqnum_ = s;
00151 } else
00152 quality_.lost(0);
00153
00154 ++quality_;
00155 cproxy.update_state(main_addr());
00156 }
00157 # else // !QOLYESTER_ENABLE_LINKHYS
00158 Link::Link()
00159 : l_addr_(),
00160 r_addr_(),
00161 m_addr_(),
00162 asymtime_(0),
00163 symtime_(0),
00164 time_(0),
00165 was_sym_(false)
00166 {}
00167
00168 Link::Link(const address_t& l, const address_t& r, const address_t& m,
00169 const timeval_t& v)
00170 : l_addr_(l),
00171 r_addr_(r),
00172 m_addr_(m),
00173 asymtime_(0),
00174 symtime_(timeval_t::now() - 1000),
00175 time_(timeval_t::in(v)),
00176 was_sym_(false)
00177 {}
00178
00179 Link::Link(const This& other)
00180 : Super(other),
00181 l_addr_(other.l_addr_),
00182 r_addr_(other.r_addr_),
00183 m_addr_(other.m_addr_),
00184 asymtime_(other.asymtime_),
00185 symtime_(other.symtime_),
00186 time_(other.time_),
00187 was_sym_(other.was_sym_)
00188 {}
00189 # endif
00190
00191
00192 bool
00193 Link::is_valid() const { return !time_.is_past(); }
00194
00195 bool
00196 Link::is_sym() const {
00197 # ifdef QOLYESTER_ENABLE_LINKHYS
00198 return losttime_.is_past() && !pending_ && !symtime_.is_past();
00199 # else // !QOLYESTER_ENABLE_LINKHYS
00200 return !symtime_.is_past();
00201 # endif
00202 }
00203
00204
00205 bool
00206 Link::operator<(const This& rhs) const {
00207 if (l_addr_ == rhs.l_addr_)
00208 return r_addr_ < rhs.r_addr_;
00209 return l_addr_ < rhs.l_addr_;
00210 }
00211
00212
00213 const Link&
00214 Link::make_key(const address_t& local, const address_t& remote) {
00215 const_cast<address_t&>(dummy_for_find_.l_addr_) = local;
00216 const_cast<address_t&>(dummy_for_find_.r_addr_) = remote;
00217 return dummy_for_find_;
00218 }
00219
00220 const Link&
00221 Link::make_key_local(const address_t& local) {
00222 const_cast<address_t&>(dummy_for_find_.l_addr_) = local;
00223 return dummy_for_find_;
00224 }
00225
00226 namespace upd {
00227
00228 void
00229 LinkUpdater::operator()() {
00230 # ifdef QOLYESTER_ENABLE_LINKHYS
00231 if (iter_->nexttime().is_past()) {
00232 debug << up << "--quality(" << iter_->main_addr()
00233 << "): expired nexttime by "
00234 << iter_->nexttime().diff() << std::endl << down;
00235 const_cast<elem_t&>(*iter_).quality().expire();
00236 --const_cast<elem_t&>(*iter_).quality();
00237 const_cast<elem_t&>(*iter_).set_nexttime(iter_->nexttime() +
00238 iter_->htime() *
00239 cst::hello_grace);
00240 }
00241 # endif // !QOLYESTER_ENABLE_LINKHYS
00242 if (iter_->is_valid()) {
00243 set_.update_state(iter_->main_addr());
00244 sch::TimedEvent* e = iter_->updater();
00245 scheduler.erase(e);
00246 e->set_next(min_time(*iter_));
00247 scheduler.insert(e);
00248 } else
00249 set_.erase(iter_);
00250 }
00251
00252 }
00253
00254
00255
00256
00257
00258 Neighbor::Neighbor()
00259 : m_addr_(),
00260 lset_(),
00261 val_lset_(*this, lset_),
00262 sym_(false),
00263 mpr_(false),
00264 mprsel_time_(0, 0),
00265 was_mprsel_(false),
00266 willingness_(0)
00267 {}
00268
00269 Neighbor::Neighbor(const address_t& maddr,
00270 const std::set<ulink_t>::iterator& i,
00271 unsigned w)
00272 : m_addr_(maddr),
00273 lset_(),
00274 val_lset_(*this, lset_),
00275 sym_(false),
00276 mpr_(false),
00277 mprsel_time_(timeval_t::now() - 1000),
00278 was_mprsel_(false),
00279 willingness_(w) {
00280 lset_.insert(i);
00281 }
00282
00283 Neighbor::Neighbor(const This& other)
00284 : Super(other),
00285 m_addr_(other.m_addr_),
00286 lset_(other.lset_),
00287 val_lset_(*this, lset_),
00288 sym_(other.sym_),
00289 mpr_(other.mpr_),
00290 mprsel_time_(other.mprsel_time_),
00291 was_mprsel_(other.was_mprsel_),
00292 willingness_(other.willingness_)
00293 {}
00294
00295 void
00296 Neighbor::set_willingness(unsigned w) {
00297 willingness_ = w;
00298 }
00299
00300 bool
00301 Neighbor::is_mprsel() const {
00302 return !mprsel_time_.is_past();
00303 }
00304
00305 bool
00306 Neighbor::was_mprsel() {
00307 if (was_mprsel_) {
00308 was_mprsel_ = false;
00309 return true;
00310 }
00311 return false;
00312 }
00313
00314 void
00315 Neighbor::set_mprsel(const timeval_t& validity) {
00316 mprsel_time_ = timeval_t::in(validity);
00317 if (is_mprsel())
00318 was_mprsel_ = true;
00319 }
00320
00321 void
00322 Neighbor::unset_mprsel() {
00323 mprsel_time_ = timeval_t::now() - 1000;
00324 }
00325
00326 std::pair<Neighbor::linkset_t::const_iterator,
00327 Neighbor::linkset_t::const_iterator>
00328 Neighbor::find_lifaces(const address_t& laddr) const {
00329 return const_cast<linkset_t&>(val_lset_).equal_range(Link::make_key_local(laddr));
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 void
00343 Neighbor::insert(const std::set<ulink_t>::iterator& pos) {
00344 lset_.insert(pos);
00345 }
00346
00347 void
00348 Neighbor::erase(const lset_t::iterator& pos) {
00349 lset_.erase(pos);
00350 }
00351
00352 void
00353 Neighbor::erase(const std::set<ulink_t>::iterator& pos) {
00354 lset_.erase(pos);
00355 }
00356
00357 bool
00358 Neighbor::operator<(const This& rhs) const {
00359 return m_addr_ < rhs.m_addr_;
00360 }
00361
00362 const Neighbor&
00363 Neighbor::make_key(const address_t& m) {
00364 const_cast<address_t&>(dummy_for_find_.m_addr_) = m;
00365 return dummy_for_find_;
00366 }
00367
00368 namespace upd {
00369
00370 void
00371 NeighborUpdater::operator()() {
00372 set_.unset_mprsel(iter_);
00373 }
00374
00375 }
00376
00377 CoherenceProxy::CoherenceProxy()
00378 : lset_(),
00379 nset_(),
00380 linkset_(lset_),
00381 idx_lset_(lset_),
00382 hello_linkset_(idx_lset_),
00383 neighborset_(*this, nset_),
00384 sym_neighborset_(neighborset_),
00385 idx_nset_(nset_),
00386 val_idx_nset_(*this, idx_nset_),
00387 tc_neighborset_(val_idx_nset_),
00388 advset_seqnum_(0),
00389 advset_changed_(false),
00390 sym_count_(0),
00391 mpr_count_(0),
00392 mprsel_empty_(true)
00393 {}
00394
00395 CoherenceProxy::~CoherenceProxy() {
00396 while (!lset_.empty())
00397 erase(lset_.begin());
00398 }
00399
00400 # ifdef QOLYESTER_ENABLE_LINKHYS
00401 std::pair<CoherenceProxy::neighborset_t::iterator, bool>
00402 CoherenceProxy::insert_link(const msg::Message::header& mh,
00403 const int linktype,
00404 const int will,
00405 const timeval_t& htime) {
00406
00407
00408 std::pair<lset_t::iterator, bool> lp =
00409 lset_.insert(Link(mh.receiver, mh.sender,
00410 mh.originator, mh.validity,
00411 mh.pseqnum, htime));
00412 # else // !QOLYESTER_ENABLE_LINKHYS
00413 std::pair<CoherenceProxy::neighborset_t::iterator, bool>
00414 CoherenceProxy::insert_link(const msg::Message::header& mh,
00415 const int linktype,
00416 const int will) {
00417
00418
00419 std::pair<lset_t::iterator, bool> lp =
00420 lset_.insert(Link(mh.receiver, mh.sender,
00421 mh.originator, mh.validity));
00422 # endif
00423 std::pair<nset_t::iterator, bool> np =
00424 nset_.insert(Neighbor(mh.originator, lp.first, will));
00425
00426 Link& l = const_cast<Link&>(static_cast<const Link&>(*lp.first));
00427
00428
00429
00430
00431
00432
00433
00434
00435 if (lp.second) {
00436 idx_lset_.insert(lp.first);
00437 if (np.second) {
00438 idx_nset_.insert(np.first);
00439 } else
00440 const_cast<uneighbor_t&>(*np.first).insert(lp.first);
00441 } else {
00442 # ifdef QOLYESTER_ENABLE_LINKHYS
00443 l.set_htime(htime);
00444 # endif // !QOLYESTER_ENABLE_LINKHYS
00445 }
00446
00447 # ifdef QOLYESTER_ENABLE_LINKHYS
00448 l.set_nexttime(timeval_t::in(htime * cst::hello_grace));
00449 # endif // !QOLYESTER_ENABLE_LINKHYS
00450
00451 if (!np.second)
00452 set_willingness(np.first, will);
00453
00454
00455 l.set_asymtime(timeval_t::in(mh.validity));
00456
00457
00458 switch (linktype) {
00459 case LOST_LINK:
00460 l.set_symtime(timeval_t::now() - 1000);
00461 break;
00462 case SYM_LINK:
00463 case ASYM_LINK:
00464 l.set_symtime(timeval_t::in(mh.validity));
00465 l.set_time(lp.first->symtime() + cst::neighb_hold_time);
00466 break;
00467 }
00468
00469 if (l.time() < l.asymtime())
00470 l.set_time(l.asymtime());
00471
00472 typedef upd::LinkUpdater lu_t;
00473
00474 sch::TimedEvent* e = lp.first->updater();
00475
00476 if (e == 0) {
00477 e = new link_updater_t(lu_t::min_time(l),
00478 lu_t(*this, lp.first));
00479 const_cast<ulink_t&>(*lp.first).set_updater(e);
00480 } else {
00481 scheduler.erase(e);
00482 e->set_next(lu_t::min_time(l));
00483 }
00484 scheduler.insert(e);
00485
00486 update_state(np.first);
00487
00488 typedef std::pair<neighborset_t::iterator, bool> ret_t;
00489
00490
00491
00492
00493 return ret_t(neighborset_t::iterator::
00494 build(neighborset_t::mask_iterator(np.first, nset_, *this)),
00495 np.second);
00496
00497 }
00498
00499 void
00500 CoherenceProxy::set_willingness(const nset_t::iterator& pos,
00501 unsigned w) {
00502 if (pos->willingness() != w) {
00503 mprset_recomp.set_mark();
00504 routes_recomp.set_mark();
00505 const_cast<uneighbor_t&>(*pos).set_willingness(w);
00506 update_graph(pos);
00507 }
00508 }
00509
00510 void
00511 CoherenceProxy::update_graph(const nset_t::iterator& pos) {
00512 unsigned w = pos->willingness();
00513 if (pos->is_sym()) {
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 unsigned new_weight =
00524 w != 0 ?
00525 w + (pos->is_mprsel() ? WILL_DEFAULT : 0) :
00526 0;
00527 std::pair<gra::AdjGraph::nset_t::const_iterator, bool> p =
00528 path_net.insert_node(gra::AdjNode(pos->main_addr(), new_weight));
00529 if (!p.second)
00530 const_cast<gra::AdjNode&>(*p.first).set_weight(new_weight);
00531 } else {
00532 gra::AdjGraph::nset_t::iterator x =
00533 gra::AdjGraph::nset_t::iterator::
00534 build(path_net.nodes().find(gra::AdjNode::
00535 make_key(pos->main_addr())));
00536 if (x != path_net.nodes().end()) {
00537 path_net.remove_node_if_alone(x);
00538 }
00539 }
00540 }
00541
00542 bool
00543 CoherenceProxy::update_state(const nset_t::iterator& pos) {
00544 assert(pos != nset_.end());
00545 bool sym = false;
00546 bool valid = false;
00547
00548
00549 for (Neighbor::linkset_t::iterator i =
00550 const_cast<uneighbor_t&>(*pos).linkset().begin();
00551 i != const_cast<uneighbor_t&>(*pos).linkset().end(); ++i) {
00552 bool link_sym = i->is_sym();
00553 valid = true;
00554 if (link_sym != i->was_sym()) {
00555 routes_recomp.set_mark();
00556 i->set_was_sym(link_sym);
00557 }
00558 if (link_sym && !sym)
00559 sym = true;
00560 }
00561 if (sym) {
00562 set_sym(pos);
00563 } else {
00564 unset_sym(pos);
00565 }
00566
00567
00568 return valid;
00569 }
00570
00571 void
00572 CoherenceProxy::update_state(const address_t& maddr) {
00573 nset_t::iterator x = nset_.find(Neighbor::make_key(maddr));
00574 if (x != nset_.end())
00575 update_state(x);
00576 }
00577
00578 void
00579 CoherenceProxy::set_sym(const nset_t::iterator& pos) {
00580 assert(pos != nset_.end());
00581 if (!pos->is_sym()) {
00582 ++sym_count_;
00583 const_cast<uneighbor_t&>(*pos).set_sym(true);
00584 mprset_recomp.set_mark();
00585 routes_recomp.set_mark();
00586 update_graph(pos);
00587 if (tc_redundancy == wholeset) {
00588 advset_changed_ = true;
00589 advset_changed.set_mark();
00590 }
00591 }
00592 }
00593
00594 void
00595 CoherenceProxy::unset_sym(const nset_t::iterator& pos) {
00596 assert(pos != nset_.end());
00597 if (pos->is_sym()) {
00598 unset_mpr(pos);
00599 unset_mprsel(pos);
00600 --sym_count_;
00601 const_cast<uneighbor_t&>(*pos).set_sym(false);
00602 mprset_recomp.set_mark();
00603 routes_recomp.set_mark();
00604 update_graph(pos);
00605 if (tc_redundancy == wholeset) {
00606 advset_changed_ = true;
00607 advset_changed.set_mark();
00608 }
00609 }
00610 }
00611
00612 void
00613 CoherenceProxy::set_mpr(const nset_t::iterator& pos) {
00614 assert(pos != nset_.end());
00615 assert(pos->is_sym());
00616 if (!pos->is_mpr()) {
00617 ++mpr_count_;
00618 const_cast<uneighbor_t&>(*pos).set_mpr(true);
00619 update_graph(pos);
00620 if (tc_redundancy >= mprselset_mprset) {
00621 advset_changed_ = true;
00622 advset_changed.set_mark();
00623 }
00624 }
00625 }
00626
00627 void
00628 CoherenceProxy::set_mpr(const sym_neighborset_t::iterator& pos) {
00629 set_mpr(pos.mask_super().mask_super());
00630 }
00631
00632 void
00633 CoherenceProxy::unset_mpr(const nset_t::iterator& pos) {
00634 assert(pos != nset_.end());
00635 assert(pos->is_sym());
00636 if (pos->is_mpr()) {
00637 --mpr_count_;
00638 const_cast<uneighbor_t&>(*pos).set_mpr(false);
00639 update_graph(pos);
00640 if (tc_redundancy >= mprselset_mprset) {
00641 advset_changed_ = true;
00642 advset_changed.set_mark();
00643 }
00644 }
00645 }
00646
00647 void
00648 CoherenceProxy::unset_mpr(const sym_neighborset_t::iterator& pos) {
00649 unset_mpr(pos.mask_super().mask_super());
00650 }
00651
00652 void
00653 CoherenceProxy::set_mprsel(const nset_t::iterator& pos,
00654 const timeval_t& v) {
00655 assert(pos != nset_.end());
00656
00657 if (!pos->is_sym())
00658 return;
00659 assert(timeval_t(0) < v);
00660 if (!pos->is_mprsel()) {
00661 mprsel_empty_ = false;
00662 advset_changed_ = true;
00663 advset_changed.set_mark();
00664 }
00665 const_cast<uneighbor_t&>(*pos).set_mprsel(v);
00666 typedef upd::NeighborUpdater nu_t;
00667 sch::TimedEvent* e = pos->updater();
00668 if (e == 0) {
00669 e = new neighbor_updater_t(timeval_t::in(v), nu_t(*this, pos));
00670 const_cast<uneighbor_t&>(*pos).set_updater(e);
00671 } else {
00672 scheduler.erase(e);
00673 e->set_next(timeval_t::in(v));
00674 }
00675 scheduler.insert(e);
00676 }
00677
00678 void
00679 CoherenceProxy::unset_mprsel(const nset_t::iterator& pos) {
00680 assert(pos != nset_.end());
00681
00682 sch::TimedEvent* e = pos->updater();
00683 if (pos->is_mprsel()) {
00684 assert(e != 0);
00685 scheduler.destroy(e);
00686 const_cast<uneighbor_t&>(*pos).set_updater(0);
00687 const_cast<uneighbor_t&>(*pos).unset_mprsel();
00688 } else if (e != 0) {
00689 scheduler.destroy(e);
00690 const_cast<uneighbor_t&>(*pos).set_updater(0);
00691 }
00692
00693 if (const_cast<uneighbor_t&>(*pos).was_mprsel()) {
00694 advset_changed_ = true;
00695 advset_changed.set_mark();
00696 }
00697
00698
00699
00700
00701
00702
00703
00704 }
00705
00706 bool
00707 CoherenceProxy::is_advset_empty() {
00708 if (mprsel_empty_)
00709 return true;
00710 mprsel_empty_ = true;
00711 for (sym_neighborset_t::iterator i = sym_neighborset_.begin();
00712 i != sym_neighborset_.end(); ++i)
00713 if (i->is_mprsel()) {
00714 mprsel_empty_ = false;
00715 break;
00716 }
00717 return mprsel_empty_;
00718 }
00719
00720 bool
00721 CoherenceProxy::is_valid(const nset_t::iterator& pos) {
00722 return update_state(pos);
00723 }
00724
00725 bool
00726 CoherenceProxy::is_valid(const idx_nset_t::iterator& pos) {
00727 return update_state(*pos.deref_super());
00728 }
00729
00730 void
00731 CoherenceProxy::erase(lset_t::iterator pos) {
00732 nset_t::iterator npos =
00733 nset_.find(Neighbor::make_key(pos->main_addr()));
00734 if (npos != nset_.end()) {
00735 const_cast<uneighbor_t&>(*npos).erase(pos);
00736 if (!is_valid(npos))
00737 erase_from_all(npos);
00738 }
00739
00740
00741
00742 idx_lset_.erase(pos);
00743 lset_.erase(pos);
00744 }
00745
00746 void
00747 CoherenceProxy::erase_from_all(nset_t::iterator pos) {
00748
00749
00750 unset_sym(pos);
00751
00752 idx_nset_.erase(pos);
00753
00754 nset_.erase(pos);
00755 }
00756
00757 void
00758 CoherenceProxy::add_interface(const address_t& a) {
00759 idx_lset_.add_key(a);
00760 idx_nset_.add_key(a);
00761 }
00762
00763 void
00764 CoherenceProxy::remove_interface(const address_t& a) {
00765 for (linkset_t::iterator i = linkset_.begin(); i != linkset_.end();
00766 )
00767 if (i->local_addr() == a) {
00768 linkset_t::iterator tmp = i++;
00769 erase(tmp);
00770 }
00771 idx_lset_.remove_key(a);
00772 idx_nset_.remove_key(a);
00773 }
00774
00775
00776
00777
00778
00779
00780 TwoHopNeighbor::TwoHopNeighbor() :
00781 mainaddr_(),
00782 twohopaddr_(),
00783 time_(0, 0)
00784 {}
00785
00786 TwoHopNeighbor::TwoHopNeighbor(const address_t& a,
00787 const address_t& tha,
00788 const timeval_t& validity) :
00789 mainaddr_(a),
00790 twohopaddr_(tha),
00791 time_(timeval_t::in(validity))
00792 {}
00793
00794 bool
00795 TwoHopNeighbor::operator<(const This& rhs) const {
00796 if (mainaddr_ == rhs.mainaddr_)
00797 return twohopaddr_ < rhs.twohopaddr_;
00798 return mainaddr_ < rhs.mainaddr_;
00799 }
00800
00801 TwoHopNeighbor&
00802 TwoHopNeighbor::operator=(const This& other) {
00803 assert(mainaddr_ == other.mainaddr_);
00804 assert(twohopaddr_ == other.twohopaddr_);
00805 time_ = other.time_;
00806 return *this;
00807 }
00808
00809 const TwoHopNeighbor&
00810 TwoHopNeighbor::make_key(const address_t& ma, const address_t& tha) {
00811 const_cast<address_t&>(dummy_for_find_.mainaddr_) = ma;
00812 const_cast<address_t&>(dummy_for_find_.twohopaddr_) = tha;
00813 return dummy_for_find_;
00814 }
00815
00816 TwoHopNeighborSet::TwoHopNeighborSet()
00817 : tset_(),
00818 thnset_(*this, tset_)
00819 {}
00820
00821 void
00822 TwoHopNeighborSet::insert(const TwoHopNeighbor& x) {
00823 std::pair<tset_t::iterator, bool> p = tset_.insert(x);
00824 if (!p.second) {
00825 sch::TimedEvent* e = p.first->updater();
00826 scheduler.erase(e);
00827 e->set_next(x.time());
00828 scheduler.insert(e);
00829
00830 const_cast<elem_t&>(*p.first).set_time(x.time());
00831 } else {
00832 if (cproxy.sym_neighborset().find(Neighbor::make_key(alg::main_addr_of(x.twohop_addr()))) == cproxy.sym_neighborset().end())
00833 mprset_recomp.set_mark();
00834 routes_recomp.set_mark();
00835 sch::TimedEvent* e = new updater_t(x.time(),
00836 eraser_t(*this, p.first));
00837 const_cast<elem_t&>(*p.first).set_updater(e);
00838 scheduler.insert(e);
00839 path_net.insert_node(gra::AdjNode(x.twohop_addr()));
00840 path_net.insert_arc(gra::AdjInfo(x.main_addr(),
00841 x.twohop_addr(),
00842 twohop));
00843 }
00844 }
00845
00846 void
00847 TwoHopNeighborSet::erase(const tset_t::iterator& pos) {
00848 assert(pos != tset_.end());
00849 bool is_1hop_sym =
00850 cproxy.sym_neighborset().find(Neighbor::make_key(pos->twohop_addr()))
00851 != cproxy.sym_neighborset().end();
00852 path_net.remove_arc(gra::AdjInfo::make_key(pos->main_addr(),
00853 pos->twohop_addr(),
00854 twohop));
00855 if (!is_1hop_sym)
00856 path_net.remove_node_if_alone(gra::AdjNode::make_key(pos->twohop_addr()));
00857 if (!is_1hop_sym)
00858 mprset_recomp.set_mark();
00859 routes_recomp.set_mark();
00860 sch::TimedEvent* e = pos->updater();
00861 tset_.erase(pos);
00862 scheduler.destroy(e);
00863 }
00864
00865 void
00866 TwoHopNeighborSet::erase(const tset_t::value_type& x) {
00867 tset_t::iterator pos = tset_.find(x);
00868 if (pos != tset_.end())
00869 erase(pos);
00870 }
00871
00872 }
00873
00874 }
00875
00876 #endif // ! QOLYESTER_DAEMON_SET_NEIGHBORS_HXX