IBR-DTNSuite 0.6

daemon/src/core/MemoryBundleStorage.cpp

Go to the documentation of this file.
00001 /*
00002  * MemoryBundleStorage.cpp
00003  *
00004  *  Created on: 22.11.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "core/MemoryBundleStorage.h"
00009 #include "core/TimeEvent.h"
00010 #include "core/GlobalEvent.h"
00011 #include "core/BundleExpiredEvent.h"
00012 #include "core/BundleEvent.h"
00013 
00014 #include <ibrcommon/Logger.h>
00015 #include <ibrcommon/thread/MutexLock.h>
00016 
00017 namespace dtn
00018 {
00019         namespace core
00020         {
00021                 MemoryBundleStorage::MemoryBundleStorage(size_t maxsize)
00022                  : _maxsize(maxsize), _currentsize(0)
00023                 {
00024                 }
00025 
00026                 MemoryBundleStorage::~MemoryBundleStorage()
00027                 {
00028                 }
00029 
00030                 void MemoryBundleStorage::componentUp()
00031                 {
00032                         bindEvent(TimeEvent::className);
00033                 }
00034 
00035                 void MemoryBundleStorage::componentDown()
00036                 {
00037                         unbindEvent(TimeEvent::className);
00038                 }
00039 
00040                 void MemoryBundleStorage::raiseEvent(const Event *evt)
00041                 {
00042                         try {
00043                                 const TimeEvent &time = dynamic_cast<const TimeEvent&>(*evt);
00044                                 if (time.getAction() == dtn::core::TIME_SECOND_TICK)
00045                                 {
00046                                         // do expiration of bundles
00047                                         ibrcommon::MutexLock l(_bundleslock);
00048                                         dtn::data::BundleList::expire(time.getTimestamp());
00049                                 }
00050                         } catch (const std::bad_cast&) { }
00051                 }
00052 
00053                 const std::string MemoryBundleStorage::getName() const
00054                 {
00055                         return "MemoryBundleStorage";
00056                 }
00057 
00058                 bool MemoryBundleStorage::empty()
00059                 {
00060                         ibrcommon::MutexLock l(_bundleslock);
00061                         return _bundles.empty();
00062                 }
00063 
00064                 void MemoryBundleStorage::releaseCustody(const dtn::data::EID&, const dtn::data::BundleID&)
00065                 {
00066                         // custody is successful transferred to another node.
00067                         // it is safe to delete this bundle now. (depending on the routing algorithm.)
00068                 }
00069 
00070                 unsigned int MemoryBundleStorage::count()
00071                 {
00072                         ibrcommon::MutexLock l(_bundleslock);
00073                         return _bundles.size();
00074                 }
00075 
00076                 const std::list<dtn::data::MetaBundle> MemoryBundleStorage::get(BundleFilterCallback &cb)
00077                 {
00078                         // result list
00079                         std::list<dtn::data::MetaBundle> result;
00080 
00081                         // we have to iterate through all bundles
00082                         ibrcommon::MutexLock l(_bundleslock);
00083 
00084                         for (std::set<dtn::data::MetaBundle>::const_iterator iter = _priority_index.begin(); (iter != _priority_index.end()) && (result.size() < cb.limit()); iter++)
00085                         {
00086                                 const dtn::data::MetaBundle &bundle = (*iter);
00087 
00088                                 if ( cb.shouldAdd(bundle) )
00089                                 {
00090                                         result.push_back(bundle);
00091                                 }
00092                         }
00093 
00094                         return result;
00095                 }
00096 
00097                 dtn::data::Bundle MemoryBundleStorage::get(const dtn::data::BundleID &id)
00098                 {
00099                         try {
00100                                 ibrcommon::MutexLock l(_bundleslock);
00101 
00102                                 for (std::set<dtn::data::Bundle>::const_iterator iter = _bundles.begin(); iter != _bundles.end(); iter++)
00103                                 {
00104                                         const dtn::data::Bundle &bundle = (*iter);
00105                                         if (id == bundle)
00106                                         {
00107                                                 return bundle;
00108                                         }
00109                                 }
00110                         } catch (const dtn::SerializationFailedException &ex) {
00111                                 // bundle loading failed
00112                                 IBRCOMMON_LOGGER(error) << "Error while loading bundle data: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
00113 
00114                                 // the bundle is broken, delete it
00115                                 remove(id);
00116 
00117                                 throw BundleStorage::BundleLoadException();
00118                         }
00119 
00120                         throw BundleStorage::NoBundleFoundException();
00121                 }
00122 
00123                 void MemoryBundleStorage::store(const dtn::data::Bundle &bundle)
00124                 {
00125                         ibrcommon::MutexLock l(_bundleslock);
00126 
00127                         // get size of the bundle
00128                         dtn::data::DefaultSerializer s(std::cout);
00129                         size_t size = s.getLength(bundle);
00130 
00131                         // check if this container is too big for us.
00132                         if ((_maxsize > 0) && (_currentsize + size > _maxsize))
00133                         {
00134                                 throw StorageSizeExeededException();
00135                         }
00136 
00137                         // increment the storage size
00138                         _currentsize += size;
00139                         _bundle_lengths[bundle] = size;
00140 
00141                         // insert Container
00142                         pair<set<dtn::data::Bundle>::iterator,bool> ret = _bundles.insert( bundle );
00143 
00144                         if (ret.second)
00145                         {
00146                                 dtn::data::BundleList::add(dtn::data::MetaBundle(bundle));
00147                                 _priority_index.insert( bundle );
00148                         }
00149                         else
00150                         {
00151                                 IBRCOMMON_LOGGER_DEBUG(5) << "Storage: got bundle duplicate " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00152                         }
00153                 }
00154 
00155                 void MemoryBundleStorage::remove(const dtn::data::BundleID &id)
00156                 {
00157                         ibrcommon::MutexLock l(_bundleslock);
00158 
00159                         for (std::set<dtn::data::Bundle>::const_iterator iter = _bundles.begin(); iter != _bundles.end(); iter++)
00160                         {
00161                                 if ( id == (*iter) )
00162                                 {
00163                                         // remove item in the bundlelist
00164                                         dtn::data::Bundle bundle = (*iter);
00165 
00166                                         // remove it from the bundle list
00167                                         _priority_index.erase(bundle);
00168                                         dtn::data::BundleList::remove(bundle);
00169 
00170                                         // get size of the bundle
00171                                         dtn::data::DefaultSerializer s(std::cout);
00172                                         size_t size = s.getLength(bundle);
00173 
00174                                         // decrement the storage size
00175                                         _currentsize -= size;
00176 
00177                                         // remove the container
00178                                         _bundles.erase(iter);
00179 
00180                                         return;
00181                                 }
00182                         }
00183 
00184                         throw BundleStorage::NoBundleFoundException();
00185                 }
00186 
00187                 dtn::data::MetaBundle MemoryBundleStorage::remove(const ibrcommon::BloomFilter &filter)
00188                 {
00189                         ibrcommon::MutexLock l(_bundleslock);
00190 
00191                         for (std::set<dtn::data::Bundle>::const_iterator iter = _bundles.begin(); iter != _bundles.end(); iter++)
00192                         {
00193                                 const dtn::data::Bundle &bundle = (*iter);
00194 
00195                                 if ( filter.contains(bundle.toString()) )
00196                                 {
00197                                         // remove it from the bundle list
00198                                         _priority_index.erase(bundle);
00199                                         dtn::data::BundleList::remove(bundle);
00200 
00201                                         // get size of the bundle
00202                                         dtn::data::DefaultSerializer s(std::cout);
00203 
00204                                         // decrement the storage size
00205                                         ssize_t len = _bundle_lengths[bundle];
00206                                         _bundle_lengths.erase(bundle);
00207                                         _currentsize -= len;
00208 
00209                                         // remove the container
00210                                         _bundles.erase(iter);
00211 
00212                                         return (MetaBundle)bundle;
00213                                 }
00214                         }
00215 
00216                         throw BundleStorage::NoBundleFoundException();
00217                 }
00218 
00219                 size_t MemoryBundleStorage::size() const
00220                 {
00221                         return _currentsize;
00222                 }
00223 
00224                 void MemoryBundleStorage::clear()
00225                 {
00226                         ibrcommon::MutexLock l(_bundleslock);
00227 
00228                         _bundles.clear();
00229                         _priority_index.clear();
00230                         dtn::data::BundleList::clear();
00231                         _bundle_lengths.clear();
00232 
00233                         // set the storage size to zero
00234                         _currentsize = 0;
00235                 }
00236 
00237                 void MemoryBundleStorage::eventBundleExpired(const ExpiringBundle &b)
00238                 {
00239                         for (std::set<dtn::data::Bundle>::const_iterator iter = _bundles.begin(); iter != _bundles.end(); iter++)
00240                         {
00241                                 if ( b.bundle == (*iter) )
00242                                 {
00243                                         dtn::data::Bundle bundle = (*iter);
00244 
00245                                         // get size of the bundle
00246                                         dtn::data::DefaultSerializer s(std::cout);
00247 
00248                                         // decrement the storage size
00249                                         ssize_t len = _bundle_lengths[bundle];
00250                                         _bundle_lengths.erase(bundle);
00251                                         _currentsize -= len;
00252 
00253                                         _priority_index.erase(bundle);
00254                                         _bundles.erase(iter);
00255                                         break;
00256                                 }
00257                         }
00258 
00259                         // raise bundle event
00260                         dtn::core::BundleEvent::raise( b.bundle, dtn::core::BUNDLE_DELETED, dtn::data::StatusReportBlock::LIFETIME_EXPIRED);
00261 
00262                         // raise an event
00263                         dtn::core::BundleExpiredEvent::raise( b.bundle );
00264                 }
00265         }
00266 }