IBR-DTN  1.0.0
ProphetRoutingExtension.cpp
Go to the documentation of this file.
1 /*
2  * ProphetRoutingExtension.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
24 
25 #include "core/BundleCore.h"
26 #include "core/EventDispatcher.h"
27 
28 #include <algorithm>
29 #include <memory>
30 #include <fstream>
31 
32 #include "core/BundleEvent.h"
33 
34 #include <ibrcommon/Logger.h>
35 #include <ibrcommon/thread/ThreadsafeReference.h>
36 
37 #include <ibrdtn/data/SDNV.h>
38 #include <ibrdtn/data/Exceptions.h>
39 #include <ibrdtn/utils/Clock.h>
40 
41 namespace dtn
42 {
43  namespace routing
44  {
45  const std::string ProphetRoutingExtension::TAG = "ProphetRoutingExtension";
46 
47  ProphetRoutingExtension::ProphetRoutingExtension(ForwardingStrategy *strategy, float p_encounter_max, float p_encounter_first, float p_first_threshold,
48  float beta, float gamma, float delta, ibrcommon::Timer::time_t time_unit, ibrcommon::Timer::time_t i_typ,
49  dtn::data::Timestamp next_exchange_timeout)
50  : _deliveryPredictabilityMap(time_unit, beta, gamma),
51  _forwardingStrategy(strategy), _next_exchange_timeout(next_exchange_timeout), _next_exchange_timestamp(0),
52  _p_encounter_max(p_encounter_max), _p_encounter_first(p_encounter_first),
53  _p_first_threshold(p_first_threshold), _delta(delta), _i_typ(i_typ)
54  {
55  // assign myself to the forwarding strategy
56  strategy->setProphetRouter(this);
57 
58  // set value for local EID to 1.0
59  _deliveryPredictabilityMap.set(core::BundleCore::local, 1.0);
60 
61  // define the first exchange timestamp
62  _next_exchange_timestamp = dtn::utils::Clock::getMonotonicTimestamp() + _next_exchange_timeout;
63 
64  try {
65  // set file to store prophet data
66  ibrcommon::File routing_d = dtn::daemon::Configuration::getInstance().getPath("storage").get("routing");
67 
68  // create directory if necessary
69  if (!routing_d.isDirectory()) ibrcommon::File::createDirectory(routing_d);
70 
71  // assign file within the routing data directory
72  _persistent_file = routing_d.get("prophet.dat");
74  // no path set
75  }
76 
77  // write something to the syslog
78  IBRCOMMON_LOGGER_TAG(ProphetRoutingExtension::TAG, info) << "Initializing PRoPHET routing module" << IBRCOMMON_LOGGER_ENDL;
79  }
80 
82  {
83  stop();
84  join();
85  delete _forwardingStrategy;
86  }
87 
89  {
92 
93  // request summary vector to exclude bundles known by the peer
95  }
96 
98  {
100  {
101  ibrcommon::MutexLock l(_deliveryPredictabilityMap);
102  age();
103  response.addItem(new DeliveryPredictabilityMap(_deliveryPredictabilityMap));
104  }
106  {
107  ibrcommon::MutexLock l(_acknowledgementSet);
108  response.addItem(new AcknowledgementSet(_acknowledgementSet));
109  }
110  }
111 
113  {
114  /* ignore neighbors, that have our EID */
115  if (neighbor.sameHost(dtn::core::BundleCore::local)) return;
116 
117  try {
118  const DeliveryPredictabilityMap& neighbor_dp_map = response.get<DeliveryPredictabilityMap>();
119 
120  // strip possible application part off the neighbor EID
121  const dtn::data::EID neighbor_node = neighbor.getNode();
122 
123  IBRCOMMON_LOGGER_DEBUG_TAG(ProphetRoutingExtension::TAG, 10) << "delivery predictability map received from " << neighbor_node.getString() << IBRCOMMON_LOGGER_ENDL;
124 
125  // store a copy of the map in the neighbor database
126  try {
127  NeighborDatabase &db = (**this).getNeighborDB();
128  NeighborDataset ds(new DeliveryPredictabilityMap(neighbor_dp_map));
129 
130  ibrcommon::MutexLock l(db);
131  db.get(neighbor_node).putDataset(ds);
132  } catch (const NeighborDatabase::EntryNotFoundException&) { };
133 
134  /* update predictability for this neighbor */
135  updateNeighbor(neighbor_node, neighbor_dp_map);
136  } catch (std::exception&) { }
137 
138  try {
139  const AcknowledgementSet& neighbor_ack_set = response.get<AcknowledgementSet>();
140 
141  IBRCOMMON_LOGGER_DEBUG_TAG(ProphetRoutingExtension::TAG, 10) << "ack'set received from " << neighbor.getString() << IBRCOMMON_LOGGER_ENDL;
142 
143  // merge ack'set into the known bundles
144  for (AcknowledgementSet::const_iterator it = neighbor_ack_set.begin(); it != neighbor_ack_set.end(); ++it) {
145  (**this).setKnown(*it);
146  }
147 
148  // merge the received ack set with the local one
149  {
150  ibrcommon::MutexLock l(_acknowledgementSet);
151  _acknowledgementSet.merge(neighbor_ack_set);
152  }
153 
154  /* remove acknowledged bundles from bundle store if we do not have custody */
155  dtn::storage::BundleStorage &storage = (**this).getStorage();
156 
158  {
159  public:
160  BundleFilter(const AcknowledgementSet& neighbor_ack_set)
161  : _ackset(neighbor_ack_set)
162  {}
163 
164  virtual ~BundleFilter() {}
165 
166  virtual dtn::data::Size limit() const throw () { return 0; }
167 
168  virtual bool shouldAdd(const dtn::data::MetaBundle &meta) const throw (dtn::storage::BundleSelectorException)
169  {
170  // do not delete any bundles with
172  return false;
173 
174  if(!_ackset.has(meta))
175  return false;
176 
177  return true;
178  }
179 
180  private:
181  const AcknowledgementSet& _ackset;
182  } filter(neighbor_ack_set);
183 
185  storage.get(filter, removeList);
186 
187  for (std::list<dtn::data::MetaBundle>::const_iterator it = removeList.begin(); it != removeList.end(); ++it)
188  {
189  const dtn::data::MetaBundle &meta = (*it);
190 
192  {
194  IBRCOMMON_LOGGER_DEBUG_TAG(ProphetRoutingExtension::TAG, 10) << "Bundle removed due to prophet ack: " << meta.toString() << IBRCOMMON_LOGGER_ENDL;
195  }
196  else
197  {
198  IBRCOMMON_LOGGER_TAG(ProphetRoutingExtension::TAG, warning) << neighbor.getString() << " requested to purge a bundle with a non-singleton destination: " << meta.toString() << IBRCOMMON_LOGGER_ENDL;
199  }
200 
201  /* generate a report */
203  }
204  } catch (const dtn::storage::NoBundleFoundException&) {
205  } catch (std::exception&) { }
206  }
207 
209  {
210  // transfer the next bundle to this destination
211  _taskqueue.push( new SearchNextBundleTask( peer ) );
212  }
213 
215  {
216  // add forwarded entry to GTMX strategy
217  try {
218  GTMX_Strategy &gtmx = dynamic_cast<GTMX_Strategy&>(*_forwardingStrategy);
219  gtmx.addForward(meta);
220  } catch (const std::bad_cast &ex) { };
221  }
222 
224  {
225  // new bundles trigger a recheck for all neighbors
226  const std::set<dtn::core::Node> nl = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
227 
228  for (std::set<dtn::core::Node>::const_iterator iter = nl.begin(); iter != nl.end(); ++iter)
229  {
230  const dtn::core::Node &n = (*iter);
231 
232  if (n.getEID() != peer)
233  {
234  // trigger all routing modules to search for bundles to forward
235  eventDataChanged(n.getEID());
236  }
237  }
238  }
239 
241  {
242  // expire bundles in the acknowledgment set
243  {
244  ibrcommon::MutexLock l(_acknowledgementSet);
245  _acknowledgementSet.expire(time.getTimestamp());
246  }
247 
248  if ((time.getTimestamp().get<size_t>() % 60) == 0)
249  {
250  // store persistent data to disk
251  if (_persistent_file.isValid()) store(_persistent_file);
252  }
253 
254  ibrcommon::MutexLock l(_next_exchange_mutex);
256 
257  if ((_next_exchange_timestamp > 0) && (_next_exchange_timestamp < now))
258  {
259  _taskqueue.push( new NextExchangeTask() );
260 
261  // define the next exchange timestamp
262  _next_exchange_timestamp = now + _next_exchange_timeout;
263  }
264  }
265 
267  {
268  if (handshake.state == NodeHandshakeEvent::HANDSHAKE_COMPLETED)
269  {
270  // transfer the next bundle to this destination
271  _taskqueue.push( new SearchNextBundleTask( handshake.peer ) );
272  }
273  }
274 
276  {
277  if (purge.reason == dtn::core::BundlePurgeEvent::DELIVERED)
278  {
279  /* the bundle was finally delivered, mark it as acknowledged */
280  ibrcommon::MutexLock l(_acknowledgementSet);
281  _acknowledgementSet.add(purge.bundle);
282  }
283  }
284 
286  {
290 
291  // reset task queue
292  _taskqueue.reset();
293 
294  // restore persistent routing data
295  if (_persistent_file.exists()) restore(_persistent_file);
296 
297  // routine checked for throw() on 15.02.2013
298  try {
299  // run the thread
300  start();
301  } catch (const ibrcommon::ThreadException &ex) {
302  IBRCOMMON_LOGGER_TAG(ProphetRoutingExtension::TAG, error) << "componentUp failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
303  }
304  }
305 
307  {
311 
312  // store persistent routing data
313  if (_persistent_file.isValid()) store(_persistent_file);
314 
315  try {
316  // stop the thread
317  stop();
318  join();
319  } catch (const ibrcommon::ThreadException &ex) {
320  IBRCOMMON_LOGGER_TAG(ProphetRoutingExtension::TAG, error) << "componentDown failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
321  }
322  }
323 
324  const std::string ProphetRoutingExtension::getTag() const throw ()
325  {
326  return "prophet";
327  }
328 
329  ibrcommon::ThreadsafeReference<DeliveryPredictabilityMap> ProphetRoutingExtension::getDeliveryPredictabilityMap()
330  {
331  {
332  ibrcommon::MutexLock l(_deliveryPredictabilityMap);
333  age();
334  }
335  return ibrcommon::ThreadsafeReference<DeliveryPredictabilityMap>(_deliveryPredictabilityMap, _deliveryPredictabilityMap);
336  }
337 
338  ibrcommon::ThreadsafeReference<const DeliveryPredictabilityMap> ProphetRoutingExtension::getDeliveryPredictabilityMap() const
339  {
340  return ibrcommon::ThreadsafeReference<const DeliveryPredictabilityMap>(_deliveryPredictabilityMap, const_cast<DeliveryPredictabilityMap&>(_deliveryPredictabilityMap));
341  }
342 
343  ibrcommon::ThreadsafeReference<const AcknowledgementSet> ProphetRoutingExtension::getAcknowledgementSet() const
344  {
345  return ibrcommon::ThreadsafeReference<const AcknowledgementSet>(_acknowledgementSet, const_cast<AcknowledgementSet&>(_acknowledgementSet));
346  }
347 
348  void ProphetRoutingExtension::ProphetRoutingExtension::run() throw ()
349  {
351  {
352  public:
353  BundleFilter(const NeighborDatabase::NeighborEntry &entry, ForwardingStrategy &strategy, const DeliveryPredictabilityMap &dpm, const std::set<dtn::core::Node> &neighbors, const dtn::core::FilterContext &context, const dtn::net::ConnectionManager::protocol_list &plist)
354  : _entry(entry), _strategy(strategy), _dpm(dpm), _neighbors(neighbors), _plist(plist), _context(context)
355  { };
356 
357  virtual ~BundleFilter() {};
358 
359  virtual dtn::data::Size limit() const throw () { return _entry.getFreeTransferSlots(); };
360 
361  virtual bool addIfSelected(dtn::storage::BundleResult &result, const dtn::data::MetaBundle &meta) const throw (dtn::storage::BundleSelectorException)
362  {
363  // check Scope Control Block - do not forward bundles with hop limit == 0
364  if (meta.hopcount == 0)
365  {
366  return false;
367  }
368 
369  // do not forward local bundles
370  if ((meta.destination.getNode() == dtn::core::BundleCore::local)
372  )
373  {
374  return false;
375  }
376 
377  // check Scope Control Block - do not forward non-group bundles with hop limit <= 1
378  if ((meta.hopcount <= 1) && (meta.get(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON)))
379  {
380  return false;
381  }
382 
383  // do not forward bundles addressed to this neighbor,
384  // because this is handled by neighbor routing extension
385  if (_entry.eid == meta.destination.getNode())
386  {
387  return false;
388  }
389 
390  // if this is a singleton bundle ...
392  {
393  const dtn::core::Node n(meta.destination.getNode());
394 
395  // do not forward the bundle if the final destination is available
396  if (_neighbors.find(n) != _neighbors.end())
397  {
398  return false;
399  }
400 
401  // check if the neighbor data is up-to-date
402  if (!_entry.isFilterValid()) throw dtn::storage::BundleSelectorException();
403  }
404  else
405  {
406  // check if the neighbor data is up-to-date
407  if (!_entry.isFilterValid()) throw dtn::storage::BundleSelectorException();
408 
409  // if this is a non-singleton, check if the peer knows a way to the source
410  try {
411  if (_dpm.get(meta.source.getNode()) <= 0.0) return false;
413  return false;
414  }
415  }
416 
417  // do not forward bundles already known by the destination
418  // throws BloomfilterNotAvailableException if no filter is available or it is expired
419  try {
420  if (_entry.has(meta, true))
421  {
422  return false;
423  }
426  }
427 
428  // ask the routing strategy if this bundle should be selected
430  {
431  if (!_strategy.shallForward(_dpm, meta)) return false;
432  }
433 
434  // update filter context
435  dtn::core::FilterContext context = _context;
436  context.setMetaBundle(meta);
437 
438  // check bundle filter for each possible path
439  for (dtn::net::ConnectionManager::protocol_list::const_iterator it = _plist.begin(); it != _plist.end(); ++it)
440  {
441  const dtn::core::Node::Protocol &p = (*it);
442 
443  // update context with current protocol
444  context.setProtocol(p);
445 
446  // execute filtering
448 
450  {
451  // put the selected bundle with targeted interface into the result-set
452  static_cast<RoutingResult&>(result).put(meta, p);
453  return true;
454  }
455  }
456 
457  return false;
458  }
459 
460  private:
461  const NeighborDatabase::NeighborEntry &_entry;
462  const ForwardingStrategy &_strategy;
463  const DeliveryPredictabilityMap &_dpm;
464  const std::set<dtn::core::Node> &_neighbors;
466  const dtn::core::FilterContext &_context;
467  };
468 
469  // list for bundles
470  RoutingResult list;
471 
472  // set of known neighbors
473  std::set<dtn::core::Node> neighbors;
474 
475  while (true)
476  {
477  try {
478  Task *t = _taskqueue.poll();
479  std::auto_ptr<Task> killer(t);
480 
481  IBRCOMMON_LOGGER_DEBUG_TAG(ProphetRoutingExtension::TAG, 50) << "processing task " << t->toString() << IBRCOMMON_LOGGER_ENDL;
482 
483  try {
489  try {
490  SearchNextBundleTask &task = dynamic_cast<SearchNextBundleTask&>(*t);
491 
492  // clear the result list
493  list.clear();
494 
495  // lock the neighbor database while searching for bundles
496  try {
497  NeighborDatabase &db = (**this).getNeighborDB();
498 
499  ibrcommon::MutexLock l(db);
500  NeighborDatabase::NeighborEntry &entry = db.get(task.eid, true);
501 
502  // check if enough transfer slots available (threshold reached)
503  if (!entry.isTransferThresholdReached())
504  throw NeighborDatabase::NoMoreTransfersAvailable();
505 
506  // get the DeliveryPredictabilityMap of the potentially next hop
507  const DeliveryPredictabilityMap &dpm = entry.getDataset<DeliveryPredictabilityMap>();
508 
510  // get current neighbor list
512  } else {
513  // "prefer direct" option disabled - clear the list of neighbors
514  neighbors.clear();
515  }
516 
517  // get a list of protocols supported by both, the local BPA and the remote peer
520 
521  // create a filter context
522  dtn::core::FilterContext context;
523  context.setPeer(entry.eid);
524  context.setRouting(*this);
525 
526  // get the bundle filter of the neighbor
527  const BundleFilter filter(entry, *_forwardingStrategy, dpm, neighbors, context, plist);
528 
529  // some debug output
530  IBRCOMMON_LOGGER_DEBUG_TAG(ProphetRoutingExtension::TAG, 40) << "search some bundles not known by " << task.eid.getString() << IBRCOMMON_LOGGER_ENDL;
531 
532  // query some unknown bundle from the storage, the list contains max. 10 items.
533  (**this).getSeeker().get(filter, list);
534  } catch (const NeighborDatabase::DatasetNotAvailableException&) {
535  // if there is no DeliveryPredictabilityMap for the next hop
536  // perform a routing handshake with the peer
537  (**this).doHandshake(task.eid);
538  } catch (const dtn::storage::BundleSelectorException&) {
539  // query a new summary vector from this neighbor
540  (**this).doHandshake(task.eid);
541  }
542 
543  // send the bundles as long as we have resources
544  for (RoutingResult::const_iterator iter = list.begin(); iter != list.end(); ++iter)
545  {
546  try {
547  transferTo(task.eid, (*iter).first, (*iter).second);
548  } catch (const NeighborDatabase::AlreadyInTransitException&) { };
549  }
550  } catch (const NeighborDatabase::NoMoreTransfersAvailable &ex) {
551  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
552  } catch (const NeighborDatabase::EntryNotFoundException &ex) {
553  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
554  } catch (const NodeNotAvailableException &ex) {
555  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
556  } catch (const dtn::storage::NoBundleFoundException &ex) {
557  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
558  } catch (const std::bad_cast&) { }
559 
564  try {
565  dynamic_cast<NextExchangeTask&>(*t);
566 
567  std::set<dtn::core::Node> neighbors = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
568  std::set<dtn::core::Node>::const_iterator it;
569  for(it = neighbors.begin(); it != neighbors.end(); ++it)
570  {
571  try{
572  (**this).doHandshake(it->getEID());
573  } catch (const ibrcommon::Exception &ex) { }
574  }
575  } catch (const std::bad_cast&) { }
576 
577  } catch (const ibrcommon::Exception &ex) {
578  IBRCOMMON_LOGGER_DEBUG_TAG(ProphetRoutingExtension::TAG, 20) << "task failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
579  }
580  } catch (const std::exception &ex) {
581  IBRCOMMON_LOGGER_DEBUG_TAG(ProphetRoutingExtension::TAG, 15) << "terminated due to " << ex.what() << IBRCOMMON_LOGGER_ENDL;
582  return;
583  }
584 
585  yield();
586  }
587  }
588 
590  {
591  _taskqueue.abort();
592  }
593 
594  float ProphetRoutingExtension::p_encounter(const dtn::data::EID &neighbor) const
595  {
596  age_map::const_iterator it = _ageMap.find(neighbor);
597  if(it == _ageMap.end())
598  {
599  /* In this case, we got a transitive update for the node we have not encountered before */
600  return _p_encounter_max;
601  }
602 
604  const dtn::data::Timestamp time_diff = currentTime - it->second;
605 #ifdef __DEVELOPMENT_ASSERTIONS__
606  assert(currentTime >= it->second && "the ageMap timestamp should be smaller than the current timestamp");
607 #endif
608  if(time_diff > _i_typ)
609  {
610  return _p_encounter_max;
611  }
612  else
613  {
614  return _p_encounter_max * time_diff.get<float>() / static_cast<float>(_i_typ);
615  }
616  }
617 
618  void ProphetRoutingExtension::updateNeighbor(const dtn::data::EID &neighbor, const DeliveryPredictabilityMap& neighbor_dp_map)
619  {
620  // update the encounter on every routing handshake
621  ibrcommon::MutexLock l(_deliveryPredictabilityMap);
622 
623  // remember the size of the map before it is altered
624  const size_t numOfItems = _deliveryPredictabilityMap.size();
625 
626  // age the local predictability map
627  age();
628 
632  try {
633  float neighbor_dp = _deliveryPredictabilityMap.get(neighbor);
634 
635  if (neighbor_dp < _p_first_threshold)
636  {
637  neighbor_dp = _p_encounter_first;
638  }
639  else
640  {
641  neighbor_dp += (1 - _delta - neighbor_dp) * p_encounter(neighbor);
642  }
643 
644  _deliveryPredictabilityMap.set(neighbor, neighbor_dp);
645  } catch (const DeliveryPredictabilityMap::ValueNotFoundException&) {
646  _deliveryPredictabilityMap.set(neighbor, _p_encounter_first);
647  }
648 
649  _ageMap[neighbor] = dtn::utils::Clock::getMonotonicTimestamp();
650 
651  /* update the dp_map */
652  _deliveryPredictabilityMap.update(neighbor, neighbor_dp_map, _p_encounter_first);
653 
654  // if the number of items has been increased by additional neighbors
655  if (numOfItems < _deliveryPredictabilityMap.size())
656  {
657  // then push a notification to all neighbors
658  (**this).pushHandshakeUpdated(NodeHandshakeItem::DELIVERY_PREDICTABILITY_MAP);
659  }
660  }
661 
662  void ProphetRoutingExtension::age()
663  {
664  _deliveryPredictabilityMap.age(_p_first_threshold);
665  }
666 
670  void ProphetRoutingExtension::store(const ibrcommon::File &target)
671  {
672  // open the file
673  std::ofstream output(target.getPath().c_str());
674 
675  // silently fail
676  if (!output.good()) return;
677 
678  // lock the predictability map
679  ibrcommon::MutexLock l(_deliveryPredictabilityMap);
680 
681  // store the predictability map
682  _deliveryPredictabilityMap.store(output);
683 
684  // store the ack'set
685  {
686  ibrcommon::MutexLock l(_acknowledgementSet);
687  output << _acknowledgementSet;
688  }
689 
690  // store the number of age-map entries
691  output << dtn::data::Number(_ageMap.size());
692 
693  // get the current monotonic time-stamp difference
695 
696  // store the age-map
697  for (age_map::const_iterator it = _ageMap.begin(); it != _ageMap.end(); ++it)
698  {
699  const dtn::data::EID &peer = it->first;
700  const dtn::data::Timestamp &monotonic_ts = it->second;
701 
702  // get a absolute time-stamp
703  const dtn::data::Timestamp ts = monotonic_diff + monotonic_ts;
704 
705  dtn::data::BundleString peer_entry(peer.getString());
706 
707  // write data
708  output << peer_entry << ts;
709  }
710  }
711 
715  void ProphetRoutingExtension::restore(const ibrcommon::File &source)
716  {
717  // open the file
718  std::ifstream input(source.getPath().c_str());
719 
720  // silently fail
721  if (!input.good()) return;
722 
723  // lock the predictability map
724  ibrcommon::MutexLock l(_deliveryPredictabilityMap);
725 
726  // restore the predictability map
727  _deliveryPredictabilityMap.restore(input);
728 
729  // restore the ack'set
730  {
731  ibrcommon::MutexLock l(_acknowledgementSet);
732  input >> _acknowledgementSet;
733  }
734 
735  // clear the age-map
736  _ageMap.clear();
737 
738  // get the number of age-map entries
739  dtn::data::Number num_entries;
740  input >> num_entries;
741 
742  // get the current monotonic time-stamp difference
745 
746  // restore the age-map
747  while (input.good() && num_entries > 0)
748  {
749  dtn::data::BundleString peer_entry;
751 
752  input >> peer_entry >> ts;
753 
754  // eliminate time-stamp which are in the future
755  if (monotonic_now >= (ts - monotonic_diff))
756  {
757  // add entry to the map
758  _ageMap[dtn::data::EID(peer_entry)] = ts - monotonic_diff;
759  }
760  else
761  {
762  // add entry to the map
763  _ageMap[dtn::data::EID(peer_entry)] = monotonic_now;
764  }
765 
766  num_entries--;
767  }
768 
769  // age the predictability map
770  age();
771  }
772 
773  ProphetRoutingExtension::SearchNextBundleTask::SearchNextBundleTask(const dtn::data::EID &eid)
774  : eid(eid)
775  {
776  }
777 
778  ProphetRoutingExtension::SearchNextBundleTask::~SearchNextBundleTask()
779  {
780  }
781 
782  std::string ProphetRoutingExtension::SearchNextBundleTask::toString() const
783  {
784  return "SearchNextBundleTask: " + eid.getString();
785  }
786 
787  ProphetRoutingExtension::NextExchangeTask::NextExchangeTask()
788  {
789  }
790 
791  ProphetRoutingExtension::NextExchangeTask::~NextExchangeTask()
792  {
793  }
794 
795  std::string ProphetRoutingExtension::NextExchangeTask::toString() const
796  {
797  return "NextExchangeTask";
798  }
799 
801  {
802  }
803 
805  {
806  }
807 
809  {
810  return neighborDPIsGreater(neighbor_dpm, bundle.destination);
811  }
812 
814  : _NF_max(NF_max)
815  {
816  }
817 
819  {
820  }
821 
823  {
824  nf_map::iterator nf_it = _NF_map.find(id);
825 
826  if (nf_it == _NF_map.end()) {
827  nf_it = _NF_map.insert(std::make_pair(id, 0)).first;
828  }
829 
830  ++nf_it->second;
831  }
832 
834  {
835  unsigned int NF = 0;
836 
837  nf_map::const_iterator nf_it = _NF_map.find(bundle);
838  if(nf_it != _NF_map.end()) {
839  NF = nf_it->second;
840  }
841 
842  if (NF > _NF_max) return false;
843 
844  return neighborDPIsGreater(neighbor_dpm, bundle.destination);
845  }
846 
847  } // namespace routing
848 } // namespace dtn
static Configuration & getInstance(bool reset=false)
std::string toString() const
Definition: BundleID.cpp:190
void update(const dtn::data::EID &origin, const DeliveryPredictabilityMap &dpm, const float &p_encounter_first)
const std::set< dtn::core::Node > getNeighbors()
virtual void eventDataChanged(const dtn::data::EID &peer)
static dtn::data::EID local
Definition: BundleCore.h:79
bool get(dtn::data::PrimaryBlock::FLAGS flag) const
Definition: MetaBundle.cpp:160
static void add(EventReceiver< E > *receiver)
bool sameHost(const std::string &other) const
Definition: EID.cpp:322
virtual void processHandshake(const dtn::data::EID &, NodeHandshake &)
std::list< dtn::core::Node::Protocol > protocol_list
void addItem(NodeHandshakeItem *item)
void set(const dtn::data::EID &neighbor, float value)
This class keeps track of the predictablities to see a specific EID.
virtual void eventTransferCompleted(const dtn::data::EID &peer, const dtn::data::MetaBundle &meta)
static void remove(const EventReceiver< E > *receiver)
NeighborDatabase::NeighborEntry & get(const dtn::data::EID &eid, bool noCached=false)
dtn::net::ConnectionManager & getConnectionManager()
Definition: BundleCore.cpp:260
static const dtn::data::Number identifier
bool hasRequest(const dtn::data::Number &identifier) const
BundleFilter::ACTION evaluate(BundleFilter::TABLE table, const FilterContext &context) const
Definition: BundleCore.cpp:617
void setProtocol(const dtn::core::Node::Protocol &protocol)
This class is a abstract base class for all prophet forwarding strategies.
const Configuration::Network & getNetwork() const
void setPeer(const dtn::data::EID &endpoint)
ibrcommon::File getPath(string name) const
const std::string TAG
Definition: dtnoutbox.cpp:62
virtual bool shallForward(const DeliveryPredictabilityMap &neighbor_dpm, const dtn::data::MetaBundle &bundle) const
Set of Acknowledgements, that can be serialized in node handshakes.
T get() const
Definition: SDNV.h:113
virtual void eventBundleQueued(const dtn::data::EID &peer, const dtn::data::MetaBundle &meta)
ibrcommon::ThreadsafeReference< const AcknowledgementSet > getAcknowledgementSet() const
void setMetaBundle(const dtn::data::MetaBundle &data)
static const dtn::data::Number identifier
Definition: NodeHandshake.h:66
The GTMX forwarding strategy. Using this strategy, packets are forwarding, if the neighbor has a high...
EID getNode() const
Definition: EID.cpp:528
ProphetRoutingExtension(ForwardingStrategy *strategy, float p_encounter_max, float p_encounter_first, float p_first_threshold, float beta, float gamma, float delta, size_t time_unit, size_t i_typ, dtn::data::Timestamp next_exchange_timeout)
const protocol_set getSupportedProtocols()
static dtn::data::Timestamp getTime()
Definition: Clock.cpp:167
dtn::data::EID destination
Definition: MetaBundle.h:60
virtual dtn::data::Bundle get(const dtn::data::BundleID &id)=0
virtual void responseHandshake(const dtn::data::EID &, const NodeHandshake &, NodeHandshake &)
virtual void requestHandshake(const dtn::data::EID &, NodeHandshake &) const
virtual const std::string getTag() const
virtual void raiseEvent(const dtn::routing::NodeHandshakeEvent &evt)
ibrcommon::ThreadsafeReference< DeliveryPredictabilityMap > getDeliveryPredictabilityMap()
void setProphetRouter(ProphetRoutingExtension *router)
size_t Size
Definition: Number.h:34
std::string getString() const
Definition: EID.cpp:374
void merge(const AcknowledgementSet &)
void age(const float &p_first_threshold)
dtn::data::BundleList::const_iterator const_iterator
static void raise(const dtn::data::MetaBundle &bundle, EventBundleAction action, dtn::data::StatusReportBlock::REASON_CODE reason=dtn::data::StatusReportBlock::NO_ADDITIONAL_INFORMATION)
Definition: BundleEvent.cpp:78
const dtn::data::EID & getEID() const
Definition: Node.cpp:406
static void raise(const dtn::data::MetaBundle &meta, REASON_CODE reason=DELIVERED)
void addRequest(const dtn::data::Number &identifier)
static dtn::data::Timestamp getMonotonicTimestamp()
Definition: Clock.cpp:175
dtn::data::SDNV< Size > Number
Definition: Number.h:38
float get(const dtn::data::EID &neighbor) const
void setRouting(const dtn::routing::RoutingExtension &routing)
virtual bool shallForward(const DeliveryPredictabilityMap &neighbor_dpm, const dtn::data::MetaBundle &bundle) const
static BundleCore & getInstance()
Definition: BundleCore.cpp:82