core: global io_service and scheduler
Scheduler and time are imported from ndn-cpp-dev.
Forwarder is using the new scheduler API.
Face system is not transitioned yet.
refs #1290
Change-Id: I5679cb50bbf9890a105f663b038f13951403c2b6
diff --git a/daemon/core/global-io.cpp b/daemon/core/global-io.cpp
new file mode 100644
index 0000000..74f1dc5
--- /dev/null
+++ b/daemon/core/global-io.cpp
@@ -0,0 +1,35 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "global-io.hpp"
+
+namespace nfd {
+
+namespace scheduler {
+// defined in scheduler.cpp
+void
+resetGlobalScheduler();
+} // namespace scheduler
+
+static shared_ptr<boost::asio::io_service> g_ioService;
+
+boost::asio::io_service&
+getGlobalIoService()
+{
+ if (!static_cast<bool>(g_ioService)) {
+ g_ioService = make_shared<boost::asio::io_service>();
+ }
+ return *g_ioService;
+}
+
+void
+resetGlobalIoService()
+{
+ scheduler::resetGlobalScheduler();
+ g_ioService.reset();
+}
+
+} // namespace nfd
diff --git a/daemon/core/global-io.hpp b/daemon/core/global-io.hpp
new file mode 100644
index 0000000..7e961f1
--- /dev/null
+++ b/daemon/core/global-io.hpp
@@ -0,0 +1,30 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NFD_CORE_GLOBAL_IO_HPP
+#define NFD_CORE_GLOBAL_IO_HPP
+
+#include "common.hpp"
+
+namespace nfd {
+
+/** \return the global io_service instance
+ */
+boost::asio::io_service&
+getGlobalIoService();
+
+#ifdef WITH_TESTS
+/** \brief delete the global io_service instance
+ *
+ * It will be recreated at the next invocation of getGlobalIoService.
+ */
+void
+resetGlobalIoService();
+#endif
+
+} // namespace nfd
+
+#endif // NFD_CORE_GLOBAL_IO_HPP
diff --git a/daemon/core/monotonic_deadline_timer.hpp b/daemon/core/monotonic_deadline_timer.hpp
deleted file mode 100644
index c158fe4..0000000
--- a/daemon/core/monotonic_deadline_timer.hpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-/**
- * This code is based on https://svn.boost.org/trac/boost/attachment/ticket/3504/MonotonicDeadlineTimer.h
- */
-
-#ifndef NFD_CORE_MONOTONIC_DEADLINE_TIMER_HPP
-#define NFD_CORE_MONOTONIC_DEADLINE_TIMER_HPP
-
-#include "time.hpp"
-
-namespace boost {
-namespace asio {
-
-template <>
-struct time_traits<nfd::time::monotonic_clock>
-{
- typedef nfd::time::Point time_type;
- typedef nfd::time::Duration duration_type;
-
- static time_type
- now()
- {
- return nfd::time::now();
- }
-
- static time_type
- add(const time_type& time, const duration_type& duration)
- {
- return time + duration;
- }
-
- static duration_type
- subtract(const time_type& timeLhs, const time_type& timeRhs)
- {
- return timeLhs - timeRhs;
- }
-
- static bool
- less_than(const time_type& timeLhs, const time_type& timeRhs)
- {
- return timeLhs < timeRhs;
- }
-
- static boost::posix_time::time_duration
- to_posix_duration(const duration_type& duration)
- {
- return boost::posix_time::microseconds(duration/1000);
- }
-};
-
-typedef basic_deadline_timer<nfd::time::monotonic_clock> monotonic_deadline_timer;
-
-} // namespace asio
-} // namespace boost
-
-#endif // NFD_CORE_MONOTONIC_DEADLINE_TIMER_HPP
diff --git a/daemon/core/scheduler.cpp b/daemon/core/scheduler.cpp
index a1759ca..439b914 100644
--- a/daemon/core/scheduler.cpp
+++ b/daemon/core/scheduler.cpp
@@ -7,204 +7,24 @@
#include "scheduler.hpp"
namespace nfd {
+namespace scheduler {
-struct EventIdImpl
+static shared_ptr<Scheduler> g_scheduler;
+
+Scheduler&
+getGlobalScheduler()
{
- EventIdImpl(const Scheduler::EventQueue::iterator& event)
- : m_event(event)
- , m_isValid(true)
- {
+ if (!static_cast<bool>(g_scheduler)) {
+ g_scheduler = make_shared<Scheduler>(boost::ref(getGlobalIoService()));
}
-
- void
- invalidate()
- {
- m_isValid = false;
- }
-
- bool
- isValid() const
- {
- return m_isValid;
- }
-
- operator const Scheduler::EventQueue::iterator&() const
- {
- return m_event;
- }
-
- void
- reset(const Scheduler::EventQueue::iterator& newIterator)
- {
- m_event = newIterator;
- m_isValid = true;
- }
-
-private:
- Scheduler::EventQueue::iterator m_event;
- bool m_isValid;
-};
-
-Scheduler::EventInfo::EventInfo(const time::Duration& after,
- const time::Duration& period,
- const Event& event)
- : m_scheduledTime(time::now() + after)
- , m_period(period)
- , m_event(event)
-{
-}
-
-Scheduler::EventInfo::EventInfo(const time::Point& when, const EventInfo& previousEvent)
- : m_scheduledTime(when)
- , m_period(previousEvent.m_period)
- , m_event(previousEvent.m_event)
- , m_eventId(previousEvent.m_eventId)
-{
-}
-
-time::Duration
-Scheduler::EventInfo::expiresFromNow() const
-{
- time::Point now = time::now();
- if (now > m_scheduledTime)
- return time::seconds(0); // event should be scheduled ASAP
- else
- return m_scheduledTime - now;
-}
-
-
-Scheduler::Scheduler(boost::asio::io_service& ioService)
- : m_ioService(ioService)
- , m_scheduledEvent(m_events.end())
- , m_deadlineTimer(ioService)
- , m_isEventExecuting(false)
-{
-}
-
-EventId
-Scheduler::scheduleEvent(const time::Duration& after,
- const Event& event)
-{
- return schedulePeriodicEvent(after, time::nanoseconds(-1), event);
-}
-
-EventId
-Scheduler::schedulePeriodicEvent(const time::Duration& after,
- const time::Duration& period,
- const Event& event)
-{
- EventQueue::iterator i = m_events.insert(EventInfo(after, period, event));
- i->m_eventId = make_shared<EventIdImpl>(boost::cref(i));
-
- if (!m_isEventExecuting)
- {
- if (m_scheduledEvent == m_events.end() ||
- *i < *m_scheduledEvent)
- {
- m_deadlineTimer.expires_from_now(after);
- m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
- m_scheduledEvent = i;
- }
- }
-
- return i->m_eventId;
-}
-
-void
-Scheduler::cancelEvent(const EventId& eventId)
-{
- if (!static_cast<bool>(eventId) || !eventId->isValid())
- return; // event empty, already fired, or cancelled
-
- if (static_cast<EventQueue::iterator>(*eventId) != m_scheduledEvent) {
- m_events.erase(*eventId);
- eventId->invalidate();
- return;
- }
-
- m_deadlineTimer.cancel();
- m_events.erase(static_cast<EventQueue::iterator>(*eventId));
- eventId->invalidate();
-
- if (!m_isEventExecuting)
- {
- if (!m_events.empty())
- {
- m_deadlineTimer.expires_from_now(m_events.begin()->expiresFromNow());
- m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
- m_scheduledEvent = m_events.begin();
- }
- else
- {
- m_deadlineTimer.cancel();
- m_scheduledEvent = m_events.end();
- }
- }
+ return *g_scheduler;
}
void
-Scheduler::onEvent(const boost::system::error_code& error)
+resetGlobalScheduler()
{
- if (error) // e.g., cancelled
- {
- return;
- }
-
- m_isEventExecuting = true;
-
- // process all expired events
- time::Point now = time::now();
- while(!m_events.empty() && m_events.begin()->m_scheduledTime <= now)
- {
- EventQueue::iterator head = m_events.begin();
-
- Event event = head->m_event;
- if (head->m_period < 0)
- {
- head->m_eventId->invalidate();
- m_events.erase(head);
- }
- else
- {
- // "reschedule" and update EventId data of the event
- EventInfo event(now + head->m_period, *head);
- EventQueue::iterator i = m_events.insert(event);
- i->m_eventId->reset(i);
- m_events.erase(head);
- }
-
- try
- {
- event();
- }
- catch(...)
- {
- m_isEventExecuting = false;
- for (EventQueue::iterator i = m_events.begin();
- i != m_events.end();
- ++i)
- {
- i->m_eventId->invalidate();
- }
- m_events.clear();
-
- throw;
- }
- }
-
- if (!m_events.empty())
- {
- m_deadlineTimer.expires_from_now(m_events.begin()->m_scheduledTime - now);
- m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
- m_scheduledEvent = m_events.begin();
- }
- else
- {
- m_scheduledEvent = m_events.end();
- }
-
- m_isEventExecuting = false;
+ g_scheduler.reset();
}
-
+} // namespace scheduler
} // namespace nfd
diff --git a/daemon/core/scheduler.hpp b/daemon/core/scheduler.hpp
index a8e60bb..6ba4f80 100644
--- a/daemon/core/scheduler.hpp
+++ b/daemon/core/scheduler.hpp
@@ -7,95 +7,46 @@
#ifndef NFD_CORE_SCHEDULER_HPP
#define NFD_CORE_SCHEDULER_HPP
-#include "common.hpp"
-#include "monotonic_deadline_timer.hpp"
+#include "global-io.hpp"
+#include "time.hpp"
+#include <ndn-cpp-dev/util/scheduler.hpp>
namespace nfd {
+namespace scheduler {
-struct EventIdImpl; ///< \brief Private storage of information about the event
-/**
- * \brief Opaque type (shared_ptr) representing ID of the scheduled event
- */
-typedef shared_ptr<EventIdImpl> EventId;
+using ndn::Scheduler;
-/**
- * \brief Generic scheduler
+/** \class EventId
+ * \brief Opaque type (shared_ptr) representing ID of a scheduled event
*/
-class Scheduler
+using ndn::EventId;
+
+} // namespace scheduler
+
+// TODO delete this after transition
+using scheduler::Scheduler;
+
+using scheduler::EventId;
+
+namespace scheduler {
+
+// TODO delete this after transition
+Scheduler&
+getGlobalScheduler();
+
+inline EventId
+schedule(const time::Duration& after, const Scheduler::Event& event)
{
-public:
- typedef function<void()> Event;
+ return getGlobalScheduler().scheduleEvent(after, event);
+}
- Scheduler(boost::asio::io_service& ioService);
+inline void
+cancel(const EventId& eventId)
+{
+ getGlobalScheduler().cancelEvent(eventId);
+}
- /**
- * \brief Schedule one time event after the specified delay
- * \returns EventId that can be used to cancel the scheduled event
- */
- EventId
- scheduleEvent(const time::Duration& after, const Event& event);
-
- /**
- * \brief Schedule periodic event that should be fired every specified period.
- * First event will be fired after the specified delay.
- * \returns EventId that can be used to cancel the scheduled event
- */
- EventId
- schedulePeriodicEvent(const time::Duration& after,
- const time::Duration& period,
- const Event& event);
-
- /**
- * \brief Cancel scheduled event
- */
- void
- cancelEvent(const EventId& eventId);
-
-private:
- void
- onEvent(const boost::system::error_code& code);
-
-private:
- boost::asio::io_service& m_ioService;
-
- struct EventInfo
- {
- EventInfo(const time::Duration& after,
- const time::Duration& period,
- const Event& event);
- EventInfo(const time::Point& when, const EventInfo& previousEvent);
-
- bool
- operator <=(const EventInfo& other) const
- {
- return this->m_scheduledTime <= other.m_scheduledTime;
- }
-
- bool
- operator <(const EventInfo& other) const
- {
- return this->m_scheduledTime < other.m_scheduledTime;
- }
-
- time::Duration
- expiresFromNow() const;
-
- time::Point m_scheduledTime;
- time::Duration m_period;
- Event m_event;
- mutable EventId m_eventId;
- };
-
- typedef std::multiset<EventInfo> EventQueue;
- friend struct EventIdImpl;
-
- EventQueue m_events;
- EventQueue::iterator m_scheduledEvent;
- boost::asio::monotonic_deadline_timer m_deadlineTimer;
-
- bool m_isEventExecuting;
-};
-
+} // namespace scheduler
} // namespace nfd
#endif // NFD_CORE_SCHEDULER_HPP
diff --git a/daemon/core/time.cpp b/daemon/core/time.cpp
deleted file mode 100644
index c216df4..0000000
--- a/daemon/core/time.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-#include "time.hpp"
-#include <time.h>
-#include <stdexcept>
-#include <sys/time.h>
-
-namespace nfd {
-namespace time {
-
-Point
-now()
-{
-#ifdef HAVE_RT
-
- struct timespec t;
- int res = clock_gettime(CLOCK_MONOTONIC, &t);
-
- if (res == -1) {
- throw std::runtime_error("clock_gettime");
- }
-
- return Point(time::seconds(t.tv_sec) + time::nanoseconds(t.tv_nsec));
-
-#else
- // fallback to wall clock time
-
- struct timeval tv;
- int res = gettimeofday(&tv, 0);
-
- if (res == -1) {
- throw std::runtime_error("gettimeofday");
- }
-
- return Point(time::seconds(tv.tv_sec) + time::microseconds(tv.tv_usec));
-
-#endif
-}
-
-} // namespace time
-} // namespace nfd
diff --git a/daemon/core/time.hpp b/daemon/core/time.hpp
index 5efd082..2c9498f 100644
--- a/daemon/core/time.hpp
+++ b/daemon/core/time.hpp
@@ -8,152 +8,19 @@
#define NFD_CORE_TIME_H
#include "common.hpp"
+#include <ndn-cpp-dev/util/time.hpp>
namespace nfd {
namespace time {
-class monotonic_clock;
-
-/** \class Duration
- * \brief represents a time interval
- * Time unit is nanosecond.
- */
-class Duration
-{
-public:
- Duration()
- : m_value(0)
- {
- }
-
- explicit
- Duration(int64_t value)
- : m_value(value)
- {
- }
-
- operator int64_t&()
- {
- return m_value;
- }
-
- operator const int64_t&() const
- {
- return m_value;
- }
-
- Duration
- operator+(const Duration& other) const
- {
- return Duration(this->m_value + other.m_value);
- }
-
- Duration
- operator-(const Duration& other) const
- {
- return Duration(this->m_value - other.m_value);
- }
-
-private:
- int64_t m_value;
-};
-
-/** \class Point
- * \brief represents a point in time
- * This uses monotonic clock.
- */
-class Point
-{
-public:
- Point()
- : m_value(0)
- {
- }
-
- explicit
- Point(int64_t value)
- : m_value(value)
- {
- }
-
- operator int64_t&()
- {
- return m_value;
- }
-
- operator const int64_t&() const
- {
- return m_value;
- }
-
- Point
- operator+(const Duration& other) const
- {
- return Point(this->m_value + static_cast<int64_t>(other));
- }
-
- Duration
- operator-(const Point& other) const
- {
- return Duration(this->m_value - other.m_value);
- }
-
- Point
- operator-(const Duration& other) const
- {
- return Point(this->m_value - static_cast<int64_t>(other));
- }
-
-private:
- int64_t m_value;
-};
-
-/**
- * \brief Get current time
- * \return{ the current time in monotonic clock }
- */
-Point
-now();
-
-/**
- * \brief Get time::Duration for the specified number of seconds
- */
-template<class T>
-inline Duration
-seconds(T value)
-{
- return Duration(value * static_cast<int64_t>(1000000000));
-}
-
-/**
- * \brief Get time::Duration for the specified number of milliseconds
- */
-template<class T>
-inline Duration
-milliseconds(T value)
-{
- return Duration(value * static_cast<int64_t>(1000000));
-}
-
-/**
- * \brief Get time::Duration for the specified number of microseconds
- */
-template<class T>
-inline Duration
-microseconds(T value)
-{
- return Duration(value * static_cast<int64_t>(1000));
-}
-
-/**
- * \brief Get time::Duration for the specified number of nanoseconds
- */
-inline Duration
-nanoseconds(int64_t value)
-{
- return Duration(value);
-}
-
+using ndn::time::Duration;
+using ndn::time::Point;
+using ndn::time::monotonic_clock;
+using ndn::time::now;
+using ndn::time::seconds;
+using ndn::time::milliseconds;
+using ndn::time::microseconds;
+using ndn::time::nanoseconds;
} // namespace time
} // namespace nfd
diff --git a/daemon/face/tcp-channel.hpp b/daemon/face/tcp-channel.hpp
index db6521f..354c849 100644
--- a/daemon/face/tcp-channel.hpp
+++ b/daemon/face/tcp-channel.hpp
@@ -8,7 +8,8 @@
#define NFD_FACE_TCP_CHANNEL_HPP
#include "common.hpp"
-#include "core/monotonic_deadline_timer.hpp"
+#include "core/time.hpp"
+#include <ndn-cpp-dev/util/monotonic_deadline_timer.hpp>
#include "tcp-face.hpp"
namespace nfd {
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index 8f6f015..4cc93d0 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -14,10 +14,8 @@
const Name Forwarder::s_localhostName("ndn:/localhost");
-Forwarder::Forwarder(boost::asio::io_service& ioService)
- : m_scheduler(ioService)
- , m_lastFaceId(0)
- , m_measurements(ioService)
+Forwarder::Forwarder()
+ : m_lastFaceId(0)
{
m_strategy = make_shared<fw::BestRouteStrategy>(boost::ref(*this));
}
@@ -43,12 +41,12 @@
m_faces.erase(faceId);
face->setId(INVALID_FACEID);
NFD_LOG_INFO("removeFace id=" << faceId);
-
+
// XXX This clears all subscriptions, because EventEmitter
// does not support only removing Forwarder's subscription
face->onReceiveInterest.clear();
face->onReceiveData .clear();
-
+
m_fib.removeNextHopFromAllEntries(face);
}
@@ -77,7 +75,7 @@
// receive Interest
NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() << " interest=" << interest.getName());
const_cast<Interest&>(interest).setIncomingFaceId(inFace.getId());
-
+
// /localhost scope control
bool violatesLocalhost = !inFace.isLocal() &&
s_localhostName.isPrefixOf(interest.getName());
@@ -86,12 +84,12 @@
<< " interest=" << interest.getName() << " violates /localhost");
return;
}
-
+
// PIT insert
std::pair<shared_ptr<pit::Entry>, bool>
pitInsertResult = m_pit.insert(interest);
shared_ptr<pit::Entry> pitEntry = pitInsertResult.first;
-
+
// detect loop and record Nonce
bool isLoop = ! pitEntry->addNonce(interest.getNonce());
if (isLoop) {
@@ -99,13 +97,13 @@
this->onInterestLoop(inFace, interest, pitEntry);
return;
}
-
+
// cancel unsatisfy & straggler timer
this->cancelUnsatisfyAndStragglerTimer(pitEntry);
-
+
const pit::InRecordCollection& inRecords = pitEntry->getInRecords();
bool isPending = inRecords.begin() == inRecords.end();
-
+
if (!isPending) {
// CS lookup
const Data* csMatch = m_cs.find(interest);
@@ -117,23 +115,23 @@
return;
}
}
-
+
// insert InRecord
pit::InRecordCollection::iterator inRecordIt =
pitEntry->insertOrUpdateInRecord(inFace.shared_from_this(), interest);
-
+
// app chosen nexthops
bool isAppChosenNexthops = false; // TODO get from local control header
if (isAppChosenNexthops) {
// TODO foreach chosen nexthop: goto outgoing Interest pipeline
return;
}
-
+
// FIB lookup
shared_ptr<fib::Entry> fibEntry
= m_fib.findLongestPrefixMatch(interest.getName());
// TODO use Fib::findParent(pitEntry)
-
+
// dispatch to strategy
this->dispatchToStrategy(inFace, interest, fibEntry, pitEntry);
}
@@ -155,14 +153,14 @@
// pick Interest
const Interest& interest = pitEntry->getInterest();
// TODO pick the last incoming Interest
-
+
// insert OutRecord
pit::OutRecordCollection::iterator outRecordIt =
pitEntry->insertOrUpdateOutRecord(outFace.shared_from_this(), interest);
-
+
// set PIT unsatisfy timer
this->setUnsatisfyTimer(pitEntry);
-
+
// send Interest
outFace.sendInterest(interest);
}
@@ -183,7 +181,7 @@
// invoke PIT unsatisfied callback
// TODO
-
+
// PIT delete
m_pit.remove(pitEntry);
}
@@ -194,7 +192,7 @@
// receive Data
NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() << " data=" << data.getName());
const_cast<Data&>(data).setIncomingFaceId(inFace.getId());
-
+
// /localhost scope control
bool violatesLocalhost = !inFace.isLocal() &&
s_localhostName.isPrefixOf(data.getName());
@@ -203,7 +201,7 @@
<< " interest=" << data.getName() << " violates /localhost");
return;
}
-
+
// PIT match
shared_ptr<pit::DataMatchResult> pitMatches = m_pit.findAllDataMatches(data);
if (pitMatches->begin() == pitMatches->end()) {
@@ -211,20 +209,20 @@
this->onDataUnsolicited(inFace, data);
return;
}
-
+
// CS insert
m_cs.insert(data);
-
+
std::set<shared_ptr<Face> > pendingDownstreams;
// foreach PitEntry
for (pit::DataMatchResult::iterator it = pitMatches->begin();
it != pitMatches->end(); ++it) {
shared_ptr<pit::Entry> pitEntry = *it;
NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
-
+
// cancel unsatisfy & straggler timer
this->cancelUnsatisfyAndStragglerTimer(pitEntry);
-
+
// remember pending downstreams
const pit::InRecordCollection& inRecords = pitEntry->getInRecords();
for (pit::InRecordCollection::const_iterator it = inRecords.begin();
@@ -233,18 +231,18 @@
pendingDownstreams.insert(it->getFace());
}
}
-
+
// mark PIT satisfied
pitEntry->deleteInRecords();
pitEntry->deleteOutRecord(inFace.shared_from_this());
-
+
// set PIT straggler timer
this->setStragglerTimer(pitEntry);
-
+
// invoke PIT satisfy callback
// TODO
}
-
+
// foreach pending downstream
for (std::set<shared_ptr<Face> >::iterator it = pendingDownstreams.begin();
it != pendingDownstreams.end(); ++it) {
@@ -273,7 +271,7 @@
// traffic manager
// pass through
-
+
// send Data
outFace.sendData(data);
}
@@ -297,8 +295,8 @@
if (lastExpiryFromNow <= time::seconds(0)) {
// TODO all InRecords are already expired; will this happen?
}
-
- pitEntry->m_unsatisfyTimer = m_scheduler.scheduleEvent(lastExpiryFromNow,
+
+ pitEntry->m_unsatisfyTimer = scheduler::schedule(lastExpiryFromNow,
bind(&Forwarder::onInterestUnsatisfied, this, pitEntry));
}
@@ -306,16 +304,16 @@
Forwarder::setStragglerTimer(shared_ptr<pit::Entry> pitEntry)
{
time::Duration stragglerTime = time::milliseconds(100);
-
- pitEntry->m_stragglerTimer = m_scheduler.scheduleEvent(stragglerTime,
+
+ pitEntry->m_stragglerTimer = scheduler::schedule(stragglerTime,
bind(&Pit::remove, &m_pit, pitEntry));
}
void
Forwarder::cancelUnsatisfyAndStragglerTimer(shared_ptr<pit::Entry> pitEntry)
{
- m_scheduler.cancelEvent(pitEntry->m_unsatisfyTimer);
- m_scheduler.cancelEvent(pitEntry->m_stragglerTimer);
+ scheduler::cancel(pitEntry->m_unsatisfyTimer);
+ scheduler::cancel(pitEntry->m_stragglerTimer);
}
void
diff --git a/daemon/fw/forwarder.hpp b/daemon/fw/forwarder.hpp
index 6da99c7..51932d1 100644
--- a/daemon/fw/forwarder.hpp
+++ b/daemon/fw/forwarder.hpp
@@ -20,14 +20,13 @@
/**
* Forwarder is the main class of NFD.
- *
+ *
* It creates and owns a set of Face listeners
*/
class Forwarder
{
public:
- explicit
- Forwarder(boost::asio::io_service& ioService);
+ Forwarder();
void
addFace(shared_ptr<Face> face);
@@ -40,17 +39,17 @@
void
onData(Face& face, const Data& data);
-
+
public:
Fib&
getFib();
-
+
Pit&
getPit();
-
+
Cs&
getCs();
-
+
Measurements&
getMeasurements();
@@ -68,32 +67,32 @@
VIRTUAL_WITH_TESTS void
onInterestLoop(Face& inFace, const Interest& interest,
shared_ptr<pit::Entry> pitEntry);
-
+
/** \brief outgoing Interest pipeline
*/
VIRTUAL_WITH_TESTS void
onOutgoingInterest(shared_ptr<pit::Entry> pitEntry, Face& outFace);
-
+
/** \brief Interest rebuff pipeline
*/
VIRTUAL_WITH_TESTS void
onInterestRebuff(shared_ptr<pit::Entry> pitEntry);
-
+
/** \brief Interest unsatisfied pipeline
*/
VIRTUAL_WITH_TESTS void
onInterestUnsatisfied(shared_ptr<pit::Entry> pitEntry);
-
+
/** \brief incoming Data pipeline
*/
VIRTUAL_WITH_TESTS void
onIncomingData(Face& inFace, const Data& data);
-
+
/** \brief Data unsolicited pipeline
*/
VIRTUAL_WITH_TESTS void
onDataUnsolicited(Face& inFace, const Data& data);
-
+
/** \brief outgoing Data pipeline
*/
VIRTUAL_WITH_TESTS void
@@ -102,13 +101,13 @@
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
VIRTUAL_WITH_TESTS void
setUnsatisfyTimer(shared_ptr<pit::Entry> pitEntry);
-
+
VIRTUAL_WITH_TESTS void
setStragglerTimer(shared_ptr<pit::Entry> pitEntry);
-
+
VIRTUAL_WITH_TESTS void
cancelUnsatisfyAndStragglerTimer(shared_ptr<pit::Entry> pitEntry);
-
+
VIRTUAL_WITH_TESTS void
dispatchToStrategy(const Face& inFace,
const Interest& interest,
@@ -116,20 +115,18 @@
shared_ptr<pit::Entry> pitEntry);
private:
- Scheduler m_scheduler;
-
FaceId m_lastFaceId;
std::map<FaceId, shared_ptr<Face> > m_faces;
-
+
Fib m_fib;
Pit m_pit;
Cs m_cs;
Measurements m_measurements;
/// the active strategy (only one strategy in mock)
shared_ptr<fw::Strategy> m_strategy;
-
+
static const Name s_localhostName;
-
+
// allow Strategy (base class) to enter pipelines
friend class fw::Strategy;
};
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 226fbe6..46b5bd3 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -27,7 +27,7 @@
: m_endpoint(endpoint)
{
}
-
+
std::pair<std::string, std::string> m_endpoint;
std::vector<Name> m_prefixes;
};
@@ -38,7 +38,6 @@
std::string m_unixListen;
};
-static boost::asio::io_service g_ioService;
static ProgramOptions g_options;
static Forwarder* g_forwarder;
static FibManager* g_fibManager;
@@ -83,7 +82,7 @@
if (pos == std::string::npos) {
throw std::invalid_argument("ip:port");
}
-
+
return std::make_pair(s.substr(0, pos), s.substr(pos+1));
}
@@ -94,7 +93,7 @@
g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
g_options.m_unixListen = "/var/run/nfd.sock";
g_options.m_tcpOutgoings.clear();
-
+
while (1) {
int option_index = 0;
static ::option long_options[] = {
@@ -107,7 +106,7 @@
};
int c = getopt_long_only(argc, argv, "", long_options, &option_index);
if (c == -1) break;
-
+
switch (c) {
case 0:
switch (option_index) {
@@ -147,7 +146,7 @@
{
g_forwarder->addFace(newFace);
newFace->onFail += bind(&onFaceFail, newFace, _1);
-
+
// add nexthop on prefixes
if (prefixes != 0) {
Fib& fib = g_forwarder->getFib();
@@ -170,17 +169,17 @@
void
initializeTcp()
{
- g_tcpFactory = new TcpChannelFactory(g_ioService);
+ g_tcpFactory = new TcpChannelFactory(getGlobalIoService());
g_tcpChannel = g_tcpFactory->create(g_options.m_tcpListen.first,
g_options.m_tcpListen.second);
g_tcpChannel->listen(
bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
&onFaceError);
-
+
for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
g_options.m_tcpOutgoings.begin();
it != g_options.m_tcpOutgoings.end(); ++it) {
- g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
+ g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
}
}
@@ -189,7 +188,7 @@
void
initializeUnix()
{
- g_unixFactory = new UnixStreamChannelFactory(g_ioService);
+ g_unixFactory = new UnixStreamChannelFactory(getGlobalIoService());
g_unixChannel = g_unixFactory->create(g_options.m_unixListen);
g_unixChannel->listen(
@@ -224,8 +223,8 @@
usage(argv[0]);
return 0;
}
-
- g_forwarder = new Forwarder(g_ioService);
+
+ g_forwarder = new Forwarder();
initializeTcp();
#ifdef HAVE_UNIX_SOCKETS
initializeUnix();
@@ -233,14 +232,14 @@
initializeMgmt();
/// \todo Add signal processing to gracefully terminate the app
-
+
try {
- g_ioService.run();
+ getGlobalIoService().run();
} catch(std::exception& ex) {
NFD_LOG_ERROR(ex.what());
return 1;
}
-
+
return 0;
}
diff --git a/daemon/table/measurements.cpp b/daemon/table/measurements.cpp
index 705d3f1..ed01018 100644
--- a/daemon/table/measurements.cpp
+++ b/daemon/table/measurements.cpp
@@ -13,8 +13,7 @@
const time::Duration Measurements::s_defaultLifetime = time::seconds(4);
-Measurements::Measurements(boost::asio::io_service& ioService)
- : m_scheduler(ioService)
+Measurements::Measurements()
{
}
@@ -92,9 +91,9 @@
return;
}
- m_scheduler.cancelEvent(entry->m_cleanup);
+ scheduler::cancel(entry->m_cleanup);
entry->m_expiry = expiry;
- entry->m_cleanup = m_scheduler.scheduleEvent(lifetime,
+ entry->m_cleanup = scheduler::schedule(lifetime,
bind(&Measurements::cleanup, this, it));
}
diff --git a/daemon/table/measurements.hpp b/daemon/table/measurements.hpp
index 0fa24e0..4c6d946 100644
--- a/daemon/table/measurements.hpp
+++ b/daemon/table/measurements.hpp
@@ -20,8 +20,7 @@
class Measurements : noncopyable
{
public:
- explicit
- Measurements(boost::asio::io_service& ioService);
+ Measurements();
~Measurements();
@@ -71,7 +70,6 @@
private:
std::map<Name, shared_ptr<measurements::Entry> > m_table;
- Scheduler m_scheduler;
static const time::Duration s_defaultLifetime;
};
diff --git a/tests/core/scheduler.cpp b/tests/core/scheduler.cpp
index 77ca1e9..d6b51fa 100644
--- a/tests/core/scheduler.cpp
+++ b/tests/core/scheduler.cpp
@@ -21,7 +21,7 @@
, count4(0)
{
}
-
+
void
event1()
{
@@ -47,7 +47,7 @@
{
++count4;
}
-
+
int count1;
int count2;
int count3;
@@ -56,23 +56,23 @@
BOOST_FIXTURE_TEST_CASE(Events, SchedulerFixture)
{
- boost::asio::io_service io;
+ resetGlobalIoService();
- Scheduler scheduler(io);
- scheduler.scheduleEvent(time::seconds(0.5), bind(&SchedulerFixture::event1, this));
-
- EventId i = scheduler.scheduleEvent(time::seconds(1.0), bind(&SchedulerFixture::event2, this));
- scheduler.cancelEvent(i);
+ scheduler::schedule(time::seconds(0.5), bind(&SchedulerFixture::event1, this));
- scheduler.scheduleEvent(time::seconds(0.25), bind(&SchedulerFixture::event3, this));
+ EventId i = scheduler::schedule(time::seconds(1.0), bind(&SchedulerFixture::event2, this));
+ scheduler::cancel(i);
- i = scheduler.scheduleEvent(time::seconds(0.05), bind(&SchedulerFixture::event2, this));
- scheduler.cancelEvent(i);
+ scheduler::schedule(time::seconds(0.25), bind(&SchedulerFixture::event3, this));
- i = scheduler.schedulePeriodicEvent(time::seconds(0.3), time::seconds(0.1), bind(&SchedulerFixture::event4, this));
- scheduler.scheduleEvent(time::seconds(1), bind(&Scheduler::cancelEvent, &scheduler, i));
-
- io.run();
+ i = scheduler::schedule(time::seconds(0.05), bind(&SchedulerFixture::event2, this));
+ scheduler::cancel(i);
+
+ // TODO deprecate periodic event
+ i = scheduler::getGlobalScheduler().schedulePeriodicEvent(time::seconds(0.3), time::seconds(0.1), bind(&SchedulerFixture::event4, this));
+ scheduler::schedule(time::seconds(1), bind(&scheduler::cancel, i));
+
+ getGlobalIoService().run();
BOOST_CHECK_EQUAL(count1, 1);
BOOST_CHECK_EQUAL(count2, 0);
@@ -82,37 +82,29 @@
BOOST_AUTO_TEST_CASE(CancelEmptyEvent)
{
- boost::asio::io_service io;
- Scheduler scheduler(io);
-
EventId i;
- scheduler.cancelEvent(i);
+ scheduler::cancel(i);
}
struct SelfCancelFixture
{
- SelfCancelFixture()
- : m_scheduler(m_io)
- {
- }
-
void
cancelSelf()
{
- m_scheduler.cancelEvent(m_selfEventId);
+ scheduler::cancel(m_selfEventId);
}
-
- boost::asio::io_service m_io;
- Scheduler m_scheduler;
+
EventId m_selfEventId;
};
BOOST_FIXTURE_TEST_CASE(SelfCancel, SelfCancelFixture)
{
- m_selfEventId = m_scheduler.scheduleEvent(time::seconds(0.1),
- bind(&SelfCancelFixture::cancelSelf, this));
-
- BOOST_REQUIRE_NO_THROW(m_io.run());
+ resetGlobalIoService();
+
+ m_selfEventId = scheduler::schedule(time::seconds(0.1),
+ bind(&SelfCancelFixture::cancelSelf, this));
+
+ BOOST_REQUIRE_NO_THROW(getGlobalIoService().run());
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/core/time.cpp b/tests/core/time.cpp
deleted file mode 100644
index 6d0db3f..0000000
--- a/tests/core/time.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-#include "core/time.hpp"
-
-#include <boost/test/unit_test.hpp>
-
-namespace nfd {
-
-BOOST_AUTO_TEST_SUITE(CoreTime)
-
-BOOST_AUTO_TEST_CASE(Now)
-{
- time::Point p1 = time::now();
- time::Point p2 = time::now();
- BOOST_CHECK_LE(p1, p2);
-}
-
-BOOST_AUTO_TEST_CASE(Operations)
-{
- // helpers
- BOOST_CHECK_GT(time::seconds(1), time::milliseconds(1));
- BOOST_CHECK_GT(time::milliseconds(1), time::microseconds(1));
- BOOST_CHECK_GT(time::microseconds(1), time::nanoseconds(1));
-
- // duration operations + helpers
- BOOST_CHECK_EQUAL(time::seconds(8) + time::microseconds(101), time::nanoseconds(8000101000));
- BOOST_CHECK_EQUAL(time::seconds(7) - time::milliseconds(234), time::microseconds(6766000));
-
- // point operations
- time::Point p1 = time::now();
- time::Point p2 = p1 + time::milliseconds(10000);
- time::Point p3 = p2 - time::microseconds(5000000);
- BOOST_CHECK_LE(p1, p2);
- BOOST_CHECK_LE(p1, p3);
- BOOST_CHECK_LE(p3, p2);
-
- BOOST_CHECK_EQUAL(p2 - p1, time::seconds(10));
- BOOST_CHECK_EQUAL(p3 - p1, time::seconds(5));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace nfd
diff --git a/tests/fw/broadcast-strategy.cpp b/tests/fw/broadcast-strategy.cpp
index 3976f62..15928be 100644
--- a/tests/fw/broadcast-strategy.cpp
+++ b/tests/fw/broadcast-strategy.cpp
@@ -16,8 +16,8 @@
BOOST_AUTO_TEST_CASE(ForwardTwo)
{
- boost::asio::io_service io;
- Forwarder forwarder(io);
+ resetGlobalIoService();
+ Forwarder forwarder;
typedef StrategyTester<fw::BroadcastStrategy> BroadcastStrategyTester;
BroadcastStrategyTester strategy(forwarder);
@@ -60,8 +60,8 @@
BOOST_AUTO_TEST_CASE(Rebuff)
{
- boost::asio::io_service io;
- Forwarder forwarder(io);
+ resetGlobalIoService();
+ Forwarder forwarder;
typedef StrategyTester<fw::BroadcastStrategy> BroadcastStrategyTester;
BroadcastStrategyTester strategy(forwarder);
diff --git a/tests/fw/forwarder.cpp b/tests/fw/forwarder.cpp
index e066f52..daa80c7 100644
--- a/tests/fw/forwarder.cpp
+++ b/tests/fw/forwarder.cpp
@@ -18,14 +18,14 @@
: m_ioService(ioService)
{
}
-
+
virtual void
sendInterest(const Interest& interest)
{
m_sentInterests.push_back(interest);
m_ioService.stop();
}
-
+
virtual void
sendData(const Data& data)
{
@@ -43,7 +43,7 @@
{
onReceiveInterest(interest);
}
-
+
void
receiveData(const Data& data)
{
@@ -62,15 +62,15 @@
BOOST_AUTO_TEST_CASE(AddRemoveFace)
{
- boost::asio::io_service io;
- Forwarder forwarder(io);
-
+ resetGlobalIoService();
+ Forwarder forwarder;
+
shared_ptr<Face> face1 = make_shared<DummyFace>();
shared_ptr<Face> face2 = make_shared<DummyFace>();
-
+
BOOST_CHECK_EQUAL(face1->getId(), INVALID_FACEID);
BOOST_CHECK_EQUAL(face2->getId(), INVALID_FACEID);
-
+
forwarder.addFace(face1);
forwarder.addFace(face2);
@@ -87,34 +87,35 @@
BOOST_AUTO_TEST_CASE(SimpleExchange)
{
+ resetGlobalIoService();
+ boost::asio::io_service& io = getGlobalIoService();
+ Forwarder forwarder;
+
Name nameA ("ndn:/A");
Name nameAB ("ndn:/A/B");
Name nameABC("ndn:/A/B/C");
Interest interestAB(nameAB);
interestAB.setInterestLifetime(4000);
Data dataABC(nameABC);
-
- boost::asio::io_service io;
- Forwarder forwarder(io);
shared_ptr<ForwarderTestFace> face1 = make_shared<ForwarderTestFace>(boost::ref(io));
shared_ptr<ForwarderTestFace> face2 = make_shared<ForwarderTestFace>(boost::ref(io));
forwarder.addFace(face1);
forwarder.addFace(face2);
-
+
Fib& fib = forwarder.getFib();
std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
fib.insert(Name("ndn:/A"));
shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
fibEntry->addNextHop(face2, 0);
-
+
face1->receiveInterest(interestAB);
io.run();
io.reset();
BOOST_REQUIRE_EQUAL(face2->m_sentInterests.size(), 1);
BOOST_CHECK(face2->m_sentInterests[0].getName().equals(nameAB));
BOOST_CHECK_EQUAL(face2->m_sentInterests[0].getIncomingFaceId(), face1->getId());
-
+
face2->receiveData(dataABC);
io.run();
io.reset();
@@ -126,9 +127,7 @@
class ScopeLocalhostTestForwarder : public Forwarder
{
public:
- explicit
- ScopeLocalhostTestForwarder(boost::asio::io_service& ioService)
- : Forwarder(ioService)
+ ScopeLocalhostTestForwarder()
{
}
@@ -155,33 +154,33 @@
BOOST_AUTO_TEST_CASE(ScopeLocalhost)
{
- boost::asio::io_service io;
- ScopeLocalhostTestForwarder forwarder(io);
+ resetGlobalIoService();
+ ScopeLocalhostTestForwarder forwarder;
shared_ptr<DummyLocalFace> face1 = make_shared<DummyLocalFace>();
shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
forwarder.addFace(face1);
forwarder.addFace(face2);
-
+
// local face, /localhost: OK
forwarder.m_dispatchToStrategy_count = 0;
forwarder.onIncomingInterest(*face1, Interest(Name("/localhost/A1")));
BOOST_CHECK_EQUAL(forwarder.m_dispatchToStrategy_count, 1);
-
+
// non-local face, /localhost: violate
forwarder.m_dispatchToStrategy_count = 0;
forwarder.onIncomingInterest(*face2, Interest(Name("/localhost/A2")));
BOOST_CHECK_EQUAL(forwarder.m_dispatchToStrategy_count, 0);
-
+
// local face, non-/localhost: OK
forwarder.m_dispatchToStrategy_count = 0;
forwarder.onIncomingInterest(*face1, Interest(Name("/A3")));
BOOST_CHECK_EQUAL(forwarder.m_dispatchToStrategy_count, 1);
-
+
// non-local face, non-/localhost: OK
forwarder.m_dispatchToStrategy_count = 0;
forwarder.onIncomingInterest(*face2, Interest(Name("/A4")));
BOOST_CHECK_EQUAL(forwarder.m_dispatchToStrategy_count, 1);
-
+
// local face, /localhost: OK
forwarder.m_onDataUnsolicited_count = 0;
forwarder.onIncomingData(*face1, Data(Name("/localhost/B1")));
@@ -191,7 +190,7 @@
forwarder.m_onDataUnsolicited_count = 0;
forwarder.onIncomingData(*face2, Data(Name("/localhost/B2")));
BOOST_CHECK_EQUAL(forwarder.m_onDataUnsolicited_count, 0);
-
+
// local face, non-/localhost: OK
forwarder.m_onDataUnsolicited_count = 0;
forwarder.onIncomingData(*face1, Data(Name("/B3")));
diff --git a/tests/table/measurements-accessor.cpp b/tests/table/measurements-accessor.cpp
index 789d02a..9738701 100644
--- a/tests/table/measurements-accessor.cpp
+++ b/tests/table/measurements-accessor.cpp
@@ -21,10 +21,10 @@
: Strategy(forwarder)
{
}
-
+
virtual
~MeasurementsAccessorTestStrategy()
-
+
{
}
@@ -36,7 +36,7 @@
{
BOOST_ASSERT(false);
}
-
+
public: // accessors
MeasurementsAccessor&
getMeasurements_accessor()
@@ -47,36 +47,37 @@
BOOST_AUTO_TEST_CASE(Access)
{
- boost::asio::io_service ioService;
- Forwarder forwarder(ioService);
+ resetGlobalIoService();
+ Forwarder forwarder;
+
shared_ptr<MeasurementsAccessorTestStrategy> strategy1 =
make_shared<MeasurementsAccessorTestStrategy>(boost::ref(forwarder));
shared_ptr<MeasurementsAccessorTestStrategy> strategy2 =
make_shared<MeasurementsAccessorTestStrategy>(boost::ref(forwarder));
-
+
Name nameRoot("ndn:/");
Name nameA ("ndn:/A");
Name nameAB ("ndn:/A/B");
Name nameABC ("ndn:/A/B/C");
Name nameAD ("ndn:/A/D");
-
+
Fib& fib = forwarder.getFib();
fib.insert(nameRoot).first->setStrategy(strategy1);
fib.insert(nameA ).first->setStrategy(strategy2);
fib.insert(nameAB ).first->setStrategy(strategy1);
-
+
MeasurementsAccessor& accessor1 = strategy1->getMeasurements_accessor();
MeasurementsAccessor& accessor2 = strategy2->getMeasurements_accessor();
-
+
BOOST_CHECK_EQUAL(static_cast<bool>(accessor1.get(nameRoot)), true);
BOOST_CHECK_EQUAL(static_cast<bool>(accessor1.get(nameA )), false);
BOOST_CHECK_EQUAL(static_cast<bool>(accessor1.get(nameAB )), true);
BOOST_CHECK_EQUAL(static_cast<bool>(accessor1.get(nameABC )), true);
BOOST_CHECK_EQUAL(static_cast<bool>(accessor1.get(nameAD )), false);
-
+
shared_ptr<measurements::Entry> entryRoot = forwarder.getMeasurements().get(nameRoot);
BOOST_CHECK_NO_THROW(accessor1.getParent(entryRoot));
-
+
BOOST_CHECK_EQUAL(static_cast<bool>(accessor2.get(nameRoot)), false);
BOOST_CHECK_EQUAL(static_cast<bool>(accessor2.get(nameA )), true);
BOOST_CHECK_EQUAL(static_cast<bool>(accessor2.get(nameAB )), false);
diff --git a/tests/table/measurements.cpp b/tests/table/measurements.cpp
index 09874a0..4643fb8 100644
--- a/tests/table/measurements.cpp
+++ b/tests/table/measurements.cpp
@@ -14,13 +14,13 @@
BOOST_AUTO_TEST_CASE(Get_Parent)
{
+ resetGlobalIoService();
+ Measurements measurements;
+
Name name0;
Name nameA ("ndn:/A");
Name nameAB("ndn:/A/B");
- boost::asio::io_service ioService;
- Measurements measurements(ioService);
-
shared_ptr<measurements::Entry> entryAB = measurements.get(nameAB);
BOOST_REQUIRE(static_cast<bool>(entryAB));
BOOST_CHECK_EQUAL(entryAB->getName(), nameAB);