IBR-DTNSuite  0.8
daemon/src/routing/RetransmissionExtension.cpp
Go to the documentation of this file.
00001 /*
00002  * RetransmissionExtension.cpp
00003  *
00004  *  Created on: 09.03.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "routing/RetransmissionExtension.h"
00009 #include "routing/RequeueBundleEvent.h"
00010 #include "core/TimeEvent.h"
00011 #include "core/BundleCore.h"
00012 #include "core/BundleExpiredEvent.h"
00013 #include "net/TransferAbortedEvent.h"
00014 #include "net/TransferCompletedEvent.h"
00015 
00016 #include <ibrdtn/utils/Clock.h>
00017 #include <ibrdtn/data/Exceptions.h>
00018 #include <ibrcommon/thread/MutexLock.h>
00019 
00020 
00021 namespace dtn
00022 {
00023         namespace routing
00024         {
00025                 RetransmissionExtension::RetransmissionExtension()
00026                 {
00027                 }
00028 
00029                 RetransmissionExtension::~RetransmissionExtension()
00030                 {
00031                 }
00032 
00033                 void RetransmissionExtension::notify(const dtn::core::Event *evt)
00034                 {
00035                         try {
00036                                 const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt);
00037 
00038                                 ibrcommon::MutexLock l(_mutex);
00039                                 if (!_queue.empty())
00040                                 {
00041                                         const RetransmissionData &data = _queue.front();
00042 
00043                                         if ( data.getTimestamp() <= time.getTimestamp() )
00044                                         {
00045                                                 // retransmit the bundle
00046                                                 dtn::core::BundleCore::getInstance().transferTo(data.destination, data);
00047 
00048                                                 // remove the item off the queue
00049                                                 _queue.pop();
00050                                         }
00051                                 }
00052                                 return;
00053                         } catch (const std::bad_cast&) { };
00054 
00055                         try {
00056                                 const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt);
00057 
00058                                 // remove the bundleid in our list
00059                                 RetransmissionData data(completed.getBundle(), completed.getPeer());
00060                                 _set.erase(data);
00061 
00062                                 return;
00063                         } catch (const std::bad_cast&) { };
00064 
00065                         try {
00066                                 const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt);
00067 
00068                                 // remove the bundleid in our list
00069                                 RetransmissionData data(aborted.getBundleID(), aborted.getPeer());
00070                                 _set.erase(data);
00071 
00072                                 return;
00073                         } catch (const std::bad_cast&) { };
00074 
00075                         try {
00076                                 const dtn::routing::RequeueBundleEvent &requeue = dynamic_cast<const dtn::routing::RequeueBundleEvent&>(*evt);
00077 
00078                                 const RetransmissionData data(requeue._bundle, requeue._peer);
00079 
00080                                 ibrcommon::MutexLock l(_mutex);
00081                                 std::set<RetransmissionData>::const_iterator iter = _set.find(data);
00082 
00083                                 if (iter != _set.end())
00084                                 {
00085                                         // increment the retry counter
00086                                         RetransmissionData data2 = (*iter);
00087                                         data2++;
00088 
00089                                         // remove the item
00090                                         _set.erase(data);
00091 
00092                                         if (data2.getCount() <= 8)
00093                                         {
00094                                                 // requeue the bundle
00095                                                 _set.insert(data2);
00096                                                 _queue.push(data2);
00097                                         }
00098                                         else
00099                                         {
00100                                                 dtn::net::TransferAbortedEvent::raise(requeue._peer, requeue._bundle, dtn::net::TransferAbortedEvent::REASON_RETRY_LIMIT_REACHED);
00101                                         }
00102                                 }
00103                                 else
00104                                 {
00105                                         // queue the bundle
00106                                         _set.insert(data);
00107                                         _queue.push(data);
00108                                 }
00109 
00110                                 return;
00111                         } catch (const std::bad_cast&) { };
00112 
00113                         try {
00114                                 const dtn::core::BundleExpiredEvent &expired = dynamic_cast<const dtn::core::BundleExpiredEvent&>(*evt);
00115 
00116                                 // delete all matching elements in the queue
00117                                 ibrcommon::MutexLock l(_mutex);
00118 
00119                                 size_t elements = _queue.size();
00120                                 for (size_t i = 0; i < elements; i++)
00121                                 {
00122                                         const RetransmissionData &data = _queue.front();
00123 
00124                                         if ((dtn::data::BundleID&)data == expired._bundle)
00125                                         {
00126                                                 dtn::net::TransferAbortedEvent::raise(data.destination, data, dtn::net::TransferAbortedEvent::REASON_BUNDLE_DELETED);
00127                                         }
00128                                         else
00129                                         {
00130                                                 _queue.push(data);
00131                                         }
00132 
00133                                         _queue.pop();
00134                                 }
00135 
00136                                 return;
00137                         } catch (const std::bad_cast&) { };
00138                 }
00139 
00140                 bool RetransmissionExtension::RetransmissionData::operator!=(const RetransmissionData &obj)
00141                 {
00142                         const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj);
00143                         const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this);
00144 
00145                         if (id1 != id2) return true;
00146                         if (obj.destination != destination) return true;
00147 
00148                         return false;
00149                 }
00150 
00151                 bool RetransmissionExtension::RetransmissionData::operator==(const RetransmissionData &obj)
00152                 {
00153                         const dtn::data::BundleID &id1 = dynamic_cast<const dtn::data::BundleID&>(obj);
00154                         const dtn::data::BundleID &id2 = dynamic_cast<const dtn::data::BundleID&>(*this);
00155 
00156                         if (id1 != id2) return false;
00157                         if (obj.destination != destination) return false;
00158 
00159                         return true;
00160                 }
00161 
00162                 size_t RetransmissionExtension::RetransmissionData::getCount() const
00163                 {
00164                         return _count;
00165                 }
00166 
00167                 size_t RetransmissionExtension::RetransmissionData::getTimestamp() const
00168                 {
00169                         return _timestamp;
00170                 }
00171 
00172                 RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++(int)
00173                 {
00174                         _count++;
00175                         _timestamp = dtn::utils::Clock::getTime();
00176                         size_t backoff = pow((float)retry, (int)_count -1);
00177                         _timestamp += backoff;
00178 
00179                         return (*this);
00180                 }
00181 
00182                 RetransmissionExtension::RetransmissionData& RetransmissionExtension::RetransmissionData::operator++()
00183                 {
00184                         _count++;
00185                         _timestamp = dtn::utils::Clock::getTime();
00186                         size_t backoff = pow((float)retry, (int)_count -1);
00187                         _timestamp += backoff;
00188 
00189                         return (*this);
00190                 }
00191 
00192                 RetransmissionExtension::RetransmissionData::RetransmissionData(const dtn::data::BundleID &id, dtn::data::EID d, size_t r)
00193                  : dtn::data::BundleID(id), destination(d), _timestamp(0), _count(0), retry(r)
00194                 {
00195                         (*this)++;
00196                 }
00197 
00198                 RetransmissionExtension::RetransmissionData::~RetransmissionData()
00199                 {
00200                 }
00201         }
00202 }