neighbors.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003-2006 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,
00018 // Boston, MA  02110-1301, USA.
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 //       blocked_ = true;
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       } /* else {} */
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     // Simple validity checker
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     // Plain comparison operator
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     // Utility static method for the creation of dummy objects to search sets
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     } // namespace upd
00253 
00254     //********************************
00255     //*  The Neighbor class
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 //     Neighbor::linkset_t::const_iterator
00333 //     Neighbor::find_liface(const address_t& laddr) const {
00334 //       return const_cast<linkset_t&>(val_lset_).find(Link::make_key_local(laddr));
00335 //     }
00336 
00337 //     bool
00338 //     Neighbor::is_liface(const address_t& iaddr) const {
00339 //       return find_liface(iaddr) != const_cast<linkset_t&>(val_lset_).end();
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     } // namespace upd
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       // Insertion/search of the link and neighbor.
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       // Insertion/search of the link and neighbor.
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       // If the previous operation appears to have been an
00429       // insertion, insert the new neighbor into idx0_nset and
00430       // idx1_nset (the sets on which HELLO::dump() and TC::dump()
00431       // will actually iterate.
00432       // Otherwise, update validity and insert the link into the
00433       // "already known" neighbor.
00434 
00435       if (lp.second) { // link is new
00436         idx_lset_.insert(lp.first);
00437         if (np.second) { // neighbor is new
00438           idx_nset_.insert(np.first);
00439         } else
00440           const_cast<uneighbor_t&>(*np.first).insert(lp.first);
00441       } else { // link is not new
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       // Update L_ASYM_time
00455       l.set_asymtime(timeval_t::in(mh.validity));
00456 
00457       // Update L_SYM_time and L_time
00458       switch (linktype) {
00459       case LOST_LINK:
00460         l.set_symtime(timeval_t::now() - 1000); // expired
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       // neighborset_t is a MaskIterator, but we don't call check()
00491       // on return, because we assume it would never erase the
00492       // freshly created/update element.
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         // A node's weight is used by the Dijkstra algorithm to prefer
00516         // nodes with larger weight, in case of ties.  If the weight
00517         // is 0, then the relaxation is not performed at all, this is
00518         // used to forbid routing through nodes with willingness of
00519         // WILL_NEVER.  Those nodes have to be in path_net anyway,
00520         // just in case the willingness changes and all the 2-hop
00521         // neighbors going through it must be reachable again.
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       // The following loop has to be executed entirely without
00548       // breaking out as soon as a symmetric link is found (cleanup).
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       // Don't touch the graph here as it's taken care of in
00567       // {,un}set_{sym,mpr,mprsel} methods.
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       // This used to be an assertion, but ought to be a check.
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       //assert(pos->is_sym());
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 //       if (pos->is_used()) {
00698 // //   const NeighborUpdater&  nu = *pos->del_pos();
00699 // //   del_set.erase(pos->del_pos());
00700 // //   delete &nu;
00701 // //   del_set.shift();
00702 //      const_cast<nelem_&>(*pos).unuse();
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 //       const LinkUpdater&     lu = *pos->del_pos();
00740 //       del_set.erase(pos->del_pos());
00741 //       delete &lu;
00742       idx_lset_.erase(pos);
00743       lset_.erase(pos);
00744     }
00745 
00746     void
00747     CoherenceProxy::erase_from_all(nset_t::iterator pos) {
00748       // First call CoherenceProxy::unset_sym() to update counters
00749       // and remove the node from the graph.
00750       unset_sym(pos);
00751       // Second remove the neighbor from the indices.
00752       idx_nset_.erase(pos);
00753       // Third remove the node /per se/.
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            /* ++i */)
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     //* TwoHopNeighbor definition
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   } // namespace set
00873 
00874 } // namespace olsr
00875 
00876 #endif // ! QOLYESTER_DAEMON_SET_NEIGHBORS_HXX

Generated on Mon Sep 10 17:02:12 2007 for Qolyester daemon by  doxygen 1.5.1