IBR-DTNSuite  0.12
NeighborRoutingExtension.cpp
Go to the documentation of this file.
1 /*
2  * NeighborRoutingExtension.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 
22 #include "config.h"
25 #include "core/BundleCore.h"
28 #include "net/ConnectionEvent.h"
29 #include "core/NodeEvent.h"
30 #include "core/Node.h"
31 #include "net/ConnectionManager.h"
33 #include "storage/BundleStorage.h"
34 #include "core/BundleEvent.h"
35 #include <ibrcommon/Logger.h>
36 
37 #ifdef HAVE_SQLITE
39 #endif
40 
41 #include <functional>
42 #include <list>
43 #include <algorithm>
44 #include <typeinfo>
45 #include <memory>
46 
47 namespace dtn
48 {
49  namespace routing
50  {
51  const std::string NeighborRoutingExtension::TAG = "NeighborRoutingExtension";
52 
54  {
55  }
56 
58  {
59  join();
60  }
61 
63  {
64  _taskqueue.abort();
65  }
66 
68  {
69 #ifdef HAVE_SQLITE
71 #else
72  class BundleFilter : public dtn::storage::BundleSelector
73 #endif
74  {
75  public:
76  BundleFilter(NeighborRoutingExtension &e, const NeighborDatabase::NeighborEntry &entry)
77  : _extension(e), _entry(entry)
78  {};
79 
80  virtual ~BundleFilter() {};
81 
82  virtual dtn::data::Size limit() const throw () { return _entry.getFreeTransferSlots(); };
83 
84  virtual bool shouldAdd(const dtn::data::MetaBundle &meta) const throw (dtn::storage::BundleSelectorException)
85  {
86  return _extension.shouldRouteTo(meta, _entry);
87  };
88 
89 #ifdef HAVE_SQLITE
90  const std::string getWhere() const throw ()
91  {
92  return "destination LIKE ?";
93  };
94 
95  int bind(sqlite3_stmt *st, int offset) const throw ()
96  {
97  const std::string d = _entry.eid.getNode().getString() + "%";
98  sqlite3_bind_text(st, offset, d.c_str(), static_cast<int>(d.size()), SQLITE_TRANSIENT);
99  return offset + 1;
100  }
101 #endif
102 
103  private:
104  NeighborRoutingExtension &_extension;
105  const NeighborDatabase::NeighborEntry &_entry;
106  };
107 
109 
110  while (true)
111  {
112  NeighborDatabase &db = (**this).getNeighborDB();
113 
114  try {
115  Task *t = _taskqueue.getnpop(true);
116  std::auto_ptr<Task> killer(t);
117 
118  IBRCOMMON_LOGGER_DEBUG_TAG(NeighborRoutingExtension::TAG, 5) << "processing task " << t->toString() << IBRCOMMON_LOGGER_ENDL;
119 
125  try {
126  SearchNextBundleTask &task = dynamic_cast<SearchNextBundleTask&>(*t);
127 
128  // lock the neighbor database while searching for bundles
129  {
130  // this destination is not handles by any static route
131  ibrcommon::MutexLock l(db);
132  NeighborDatabase::NeighborEntry &entry = db.get(task.eid, true);
133 
134  // check if enough transfer slots available (threshold reached)
135  if (!entry.isTransferThresholdReached())
137 
138  // create a new bundle filter
139  BundleFilter filter(*this, entry);
140 
141  // query an unknown bundle from the storage, the list contains max. 10 items.
142  list.clear();
143  (**this).getSeeker().get(filter, list);
144  }
145 
146  IBRCOMMON_LOGGER_DEBUG_TAG(NeighborRoutingExtension::TAG, 5) << "got " << list.size() << " items to transfer to " << task.eid.getString() << IBRCOMMON_LOGGER_ENDL;
147 
148  // send the bundles as long as we have resources
149  for (std::list<dtn::data::MetaBundle>::const_iterator iter = list.begin(); iter != list.end(); ++iter)
150  {
151  try {
152  // transfer the bundle to the neighbor
153  transferTo(task.eid, *iter);
154  } catch (const NeighborDatabase::AlreadyInTransitException&) { };
155  }
156  } catch (const NeighborDatabase::NoMoreTransfersAvailable &ex) {
157  IBRCOMMON_LOGGER_DEBUG_TAG(NeighborRoutingExtension::TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
159  IBRCOMMON_LOGGER_DEBUG_TAG(NeighborRoutingExtension::TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
160  } catch (const dtn::storage::NoBundleFoundException &ex) {
161  IBRCOMMON_LOGGER_DEBUG_TAG(NeighborRoutingExtension::TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
162  } catch (const std::bad_cast&) { };
163 
167  try {
168  const ProcessBundleTask &task = dynamic_cast<ProcessBundleTask&>(*t);
169 
170  // lock the neighbor database while searching for bundles
171  {
172  // this destination is not handles by any static route
173  ibrcommon::MutexLock l(db);
174  NeighborDatabase::NeighborEntry &entry = db.get(task.nexthop, true);
175 
176  if (!shouldRouteTo(task.bundle, entry))
178  }
179 
180  // transfer the bundle to the neighbor
181  transferTo(task.nexthop, task.bundle);
182  } catch (const NeighborDatabase::AlreadyInTransitException &ex) {
183  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
184  } catch (const NeighborDatabase::NoMoreTransfersAvailable &ex) {
185  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
187  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
188  } catch (const NeighborDatabase::NoRouteKnownException &ex) {
189  // nothing to do here.
190  } catch (const std::bad_cast&) { };
191  } catch (const std::exception &ex) {
192  IBRCOMMON_LOGGER_DEBUG_TAG(NeighborRoutingExtension::TAG, 15) << "terminated due to " << ex.what() << IBRCOMMON_LOGGER_ENDL;
193  return;
194  }
195 
196  yield();
197  }
198  }
199 
200  bool NeighborRoutingExtension::shouldRouteTo(const dtn::data::MetaBundle &meta, const NeighborDatabase::NeighborEntry &n) const
201  {
202  // check Scope Control Block - do not forward bundles with hop limit == 0
203  if (meta.hopcount == 0)
204  {
205  return false;
206  }
207 
209  {
210  // do not forward local bundles
212  {
213  return false;
214  }
215 
216  // do not forward bundles for other nodes
217  if (!meta.destination.sameHost(n.eid))
218  {
219  return false;
220  }
221  }
222  else
223  {
224  // do not forward non-singleton bundles
225  return false;
226  }
227 
228  // do not forward bundles already known by the destination
229  if (n.has(meta))
230  {
231  return false;
232  }
233 
234  return true;
235  }
236 
238  {
239  // transfer the next bundle to this destination
240  _taskqueue.push( new SearchNextBundleTask( peer ) );
241  }
242 
244  {
245  // try to deliver new bundles to all neighbors
246  const std::set<dtn::core::Node> nl = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
247 
248  for (std::set<dtn::core::Node>::const_iterator iter = nl.begin(); iter != nl.end(); ++iter)
249  {
250  const dtn::core::Node &n = (*iter);
251 
252  if (n.getEID() != peer) {
253  // transfer the next bundle to this destination
254  _taskqueue.push( new ProcessBundleTask(meta, peer, n.getEID()) );
255  }
256  }
257  }
258 
260  {
261  // reset the task queue
262  _taskqueue.reset();
263 
264  // routine checked for throw() on 15.02.2013
265  try {
266  // run the thread
267  start();
268  } catch (const ibrcommon::ThreadException &ex) {
269  IBRCOMMON_LOGGER_TAG(NeighborRoutingExtension::TAG, error) << "componentUp failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
270  }
271  }
272 
274  {
275  // routine checked for throw() on 15.02.2013
276  try {
277  // stop the thread
278  stop();
279  join();
280  } catch (const ibrcommon::ThreadException &ex) {
281  IBRCOMMON_LOGGER_TAG(NeighborRoutingExtension::TAG, error) << "componentDown failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
282  }
283  }
284 
285  /****************************************/
286 
287  NeighborRoutingExtension::SearchNextBundleTask::SearchNextBundleTask(const dtn::data::EID &e)
288  : eid(e)
289  { }
290 
291  NeighborRoutingExtension::SearchNextBundleTask::~SearchNextBundleTask()
292  { }
293 
294  std::string NeighborRoutingExtension::SearchNextBundleTask::toString()
295  {
296  return "SearchNextBundleTask: " + eid.getString();
297  }
298 
299  /****************************************/
300 
301  NeighborRoutingExtension::ProcessBundleTask::ProcessBundleTask(const dtn::data::MetaBundle &meta, const dtn::data::EID &o, const dtn::data::EID &n)
302  : bundle(meta), origin(o), nexthop(n)
303  { }
304 
305  NeighborRoutingExtension::ProcessBundleTask::~ProcessBundleTask()
306  { }
307 
308  std::string NeighborRoutingExtension::ProcessBundleTask::toString()
309  {
310  return "ProcessBundleTask: " + bundle.toString();
311  }
312  }
313 }