IBR-DTNSuite  0.8
daemon/src/routing/NeighborDatabase.cpp
Go to the documentation of this file.
00001 /*
00002  * NeighborDatabase.cpp
00003  *
00004  *  Created on: 23.07.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "routing/NeighborDatabase.h"
00009 #include <ibrdtn/utils/Clock.h>
00010 #include <ibrcommon/Logger.h>
00011 #include <limits>
00012 
00013 namespace dtn
00014 {
00015         namespace routing
00016         {
00017                 NeighborDatabase::NeighborEntry::NeighborEntry()
00018                  : eid(), _transit_max(5), _filter(), _filter_expire(0), _filter_state(FILTER_EXPIRED, FILTER_FINAL)
00019                 {};
00020 
00021                 NeighborDatabase::NeighborEntry::NeighborEntry(const dtn::data::EID &e)
00022                  : eid(e), _transit_max(5), _filter(), _filter_expire(0), _filter_state(FILTER_EXPIRED, FILTER_FINAL)
00023                 { }
00024 
00025                 NeighborDatabase::NeighborEntry::~NeighborEntry()
00026                 { }
00027 
00028                 void NeighborDatabase::NeighborEntry::update(const ibrcommon::BloomFilter &bf, const size_t lifetime)
00029                 {
00030                         ibrcommon::ThreadsafeState<FILTER_REQUEST_STATE>::Locked l = _filter_state.lock();
00031                         _filter = bf;
00032 
00033                         if (lifetime == 0)
00034                         {
00035                                 _filter_expire = std::numeric_limits<std::size_t>::max();
00036                         }
00037                         else
00038                         {
00039                                 _filter_expire = dtn::utils::Clock::getExpireTime(lifetime);
00040                         }
00041 
00042                         l = FILTER_AVAILABLE;
00043                 }
00044 
00045                 void NeighborDatabase::NeighborEntry::reset()
00046                 {
00047                         ibrcommon::ThreadsafeState<FILTER_REQUEST_STATE>::Locked l = _filter_state.lock();
00048 
00049                         l = FILTER_EXPIRED;
00050 
00051                         // do not expire again in the next 60 seconds
00052                         _filter_expire = dtn::utils::Clock::getTime() + 60;
00053                 }
00054 
00055                 void NeighborDatabase::NeighborEntry::add(const dtn::data::MetaBundle &bundle)
00056                 {
00057                         _summary.add(bundle);
00058                 }
00059 
00060                 bool NeighborDatabase::NeighborEntry::has(const dtn::data::BundleID &id, const bool require_bloomfilter) const
00061                 {
00062                         if (require_bloomfilter && (_filter_state != FILTER_AVAILABLE))
00063                                 throw BloomfilterNotAvailableException(eid);
00064 
00065                         if (_filter_state == FILTER_AVAILABLE)
00066                         {
00067                                 if (_filter.contains(id.toString()))
00068                                         return true;
00069                         }
00070 
00071                         if (_summary.contains(id))
00072                                 return true;
00073 
00074                         return false;
00075                 }
00076 
00077                 void NeighborDatabase::NeighborEntry::expire(const size_t timestamp)
00078                 {
00079                         {
00080                                 ibrcommon::ThreadsafeState<FILTER_REQUEST_STATE>::Locked l = _filter_state.lock();
00081 
00082                                 if ((_filter_expire > 0) && (_filter_expire < timestamp))
00083                                 {
00084                                         IBRCOMMON_LOGGER_DEBUG(15) << "summary vector of " << eid.getString() << " is expired" << IBRCOMMON_LOGGER_ENDL;
00085 
00086                                         // set the filter state to expired once
00087                                         l = FILTER_EXPIRED;
00088 
00089                                         // do not expire again in the next 60 seconds
00090                                         _filter_expire = timestamp + 60;
00091                                 }
00092                         }
00093 
00094                         _summary.expire(timestamp);
00095                 }
00096 
00097                 void NeighborDatabase::expire(const size_t timestamp)
00098                 {
00099                         for (std::map<dtn::data::EID, NeighborDatabase::NeighborEntry* >::const_iterator iter = _entries.begin(); iter != _entries.end(); iter++)
00100                         {
00101                                 (*iter).second->expire(timestamp);
00102                         }
00103                 }
00104 
00105                 void NeighborDatabase::NeighborEntry::acquireFilterRequest() throw (NoMoreTransfersAvailable)
00106                 {
00107                         ibrcommon::ThreadsafeState<FILTER_REQUEST_STATE>::Locked l = _filter_state.lock();
00108 
00109                         if (l != FILTER_EXPIRED)
00110                                 throw NoMoreTransfersAvailable();
00111 
00112                         // set the state to zero
00113                         l = FILTER_AWAITING;
00114                 }
00115 
00116                 void NeighborDatabase::NeighborEntry::acquireTransfer(const dtn::data::BundleID &id) throw (NoMoreTransfersAvailable, AlreadyInTransitException)
00117                 {
00118                         ibrcommon::MutexLock l(_transit_lock);
00119 
00120                         // check if the bundle is already in transit
00121                         if (_transit_bundles.find(id) != _transit_bundles.end()) throw AlreadyInTransitException();
00122 
00123                         // check if enough resources available to transfer the bundle
00124                         if (_transit_bundles.size() >= _transit_max) throw NoMoreTransfersAvailable();
00125 
00126                         // insert the bundle into the transit list
00127                         _transit_bundles.insert(id);
00128 
00129                         IBRCOMMON_LOGGER_DEBUG(20) << "acquire transfer of " << id.toString() << " (" << _transit_bundles.size() << " bundles in transit)" << IBRCOMMON_LOGGER_ENDL;
00130                 }
00131 
00132                 void NeighborDatabase::NeighborEntry::releaseTransfer(const dtn::data::BundleID &id)
00133                 {
00134                         ibrcommon::MutexLock l(_transit_lock);
00135                         _transit_bundles.erase(id);
00136 
00137                         IBRCOMMON_LOGGER_DEBUG(20) << "release transfer of " << id.toString() << " (" << _transit_bundles.size() << " bundles in transit)" << IBRCOMMON_LOGGER_ENDL;
00138                 }
00139 
00140                 NeighborDatabase::NeighborDatabase()
00141                 {
00142                 }
00143 
00144                 NeighborDatabase::~NeighborDatabase()
00145                 {
00146                         std::set<dtn::data::EID> ret;
00147 
00148                         for (std::map<dtn::data::EID, NeighborDatabase::NeighborEntry* >::const_iterator iter = _entries.begin(); iter != _entries.end(); iter++)
00149                         {
00150                                 delete (*iter).second;
00151                         }
00152                 }
00153 
00154                 NeighborDatabase::NeighborEntry& NeighborDatabase::create(const dtn::data::EID &eid)
00155                 {
00156                         if (_entries.find(eid) == _entries.end())
00157                         {
00158                                 NeighborEntry *entry = new NeighborEntry(eid);
00159                                 _entries[eid] = entry;
00160                         }
00161 
00162                         return (*_entries[eid]);
00163                 }
00164 
00165                 NeighborDatabase::NeighborEntry& NeighborDatabase::get(const dtn::data::EID &eid) throw (NeighborNotAvailableException)
00166                 {
00167                         if (_entries.find(eid) == _entries.end())
00168                         {
00169                                 throw NeighborNotAvailableException();
00170                         }
00171 
00172                         return (*_entries[eid]);
00173                 }
00174 
00175                 NeighborDatabase::NeighborEntry& NeighborDatabase::reset(const dtn::data::EID &eid)
00176                 {
00177                         NeighborDatabase::NeighborEntry &e = get(eid);
00178                         e.reset();
00179                         return e;
00180                 }
00181 
00182                 void NeighborDatabase::remove(const dtn::data::EID &eid)
00183                 {
00184                         _entries.erase(eid);
00185                 }
00186 
00187                 void NeighborDatabase::addBundle(const dtn::data::EID &neighbor, const dtn::data::MetaBundle &b)
00188                 {
00189                         try {
00190                                 NeighborDatabase::NeighborEntry &entry = get(neighbor);
00191                                 entry.add(b);
00192                         } catch (const NeighborDatabase::NeighborNotAvailableException&) { };
00193                 }
00194         }
00195 }