Browse Source

[2871] Implementation of the FakeQuery

The FakeQuery class is implemented. The FakeInterface is, however, still
missing, so it doesn't work (not even link).
Michal 'vorner' Vaner 12 years ago
parent
commit
81d23e3051
2 changed files with 57 additions and 8 deletions
  1. 4 1
      src/bin/resolver/bench/Makefile.am
  2. 53 7
      src/bin/resolver/bench/fake_resolution.h

+ 4 - 1
src/bin/resolver/bench/Makefile.am

@@ -15,5 +15,8 @@ CLEANFILES = *.gcno *.gcda
 noinst_PROGRAMS = resolver-bench
 noinst_PROGRAMS = resolver-bench
 
 
 resolver_bench_SOURCES = main.cc
 resolver_bench_SOURCES = main.cc
-resolver_bench_SOURCES += fake_resolution.h
+resolver_bench_SOURCES += fake_resolution.h fake_resolution.cc
+resolver_bench_SOURCES += dummy_work.h dummy_work.cc
+
 resolver_bench_LDADD  = $(GTEST_LDADD)
 resolver_bench_LDADD  = $(GTEST_LDADD)
+resolver_bench_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la

+ 53 - 7
src/bin/resolver/bench/fake_resolution.h

@@ -15,9 +15,14 @@
 #ifndef FAKE_RESOLUTION_H
 #ifndef FAKE_RESOLUTION_H
 #define FAKE_RESOLUTION_H
 #define FAKE_RESOLUTION_H
 
 
+#include <exceptions/exceptions.h>
+
 #include <boost/function.hpp>
 #include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/shared_ptr.hpp>
 
 
+#include <utility>
+#include <vector>
+
 namespace isc {
 namespace isc {
 namespace resolver {
 namespace resolver {
 namespace bench {
 namespace bench {
@@ -70,16 +75,35 @@ class FakeInterface;
 ///
 ///
 /// See naive_resolver.cc for example code how this could be done.
 /// See naive_resolver.cc for example code how this could be done.
 class FakeQuery {
 class FakeQuery {
+private:
+    // The queries come only through an interface. Don't let others create.
+    friend class FakeInterface;
+    /// \brief Constructor
+    FakeQuery(FakeInterface& interface);
+    // The scheduled steps for this task.
+    typedef std::pair<Task, size_t> Step;
+    // The scheduled steps. Reversed (first to be done at the end), so we can
+    // pop_back() the completed steps.
+    std::vector<Step> steps_;
+    // The interface to schedule timeouts on.
+    FakeInterface* interface_;
+    // Is an upstream query outstanding?
+    bool outstanding_;
 public:
 public:
-    /// \brief Callback to signify a task has been performed.
-    typedef boost::function<void()> StepCallback;
     /// \brief Is work on the query completely done?
     /// \brief Is work on the query completely done?
     ///
     ///
     /// If this returns true, do not call performTask or nextTask any more.
     /// If this returns true, do not call performTask or nextTask any more.
     /// The resolution is done.
     /// The resolution is done.
     ///
     ///
     /// \throw isc::InvalidOperation if upstream query is still in progress.
     /// \throw isc::InvalidOperation if upstream query is still in progress.
-    bool done() const;
+    bool done() const {
+        if (outstanding_) {
+            isc_throw(isc::InvalidOperation, "Upstream query outstanding");
+        }
+        return (steps_.empty());
+    }
+    /// \brief Callback to signify a task has been performed.
+    typedef boost::function<void()> StepCallback;
     /// \brief Perform next step in the resolution.
     /// \brief Perform next step in the resolution.
     ///
     ///
     /// Do whatever is needed to be done for the next step of resolution.
     /// Do whatever is needed to be done for the next step of resolution.
@@ -101,7 +125,13 @@ public:
     /// \throw isc::InvalidOperation if it is called when done() is true, or
     /// \throw isc::InvalidOperation if it is called when done() is true, or
     ///     if an upstream query is still in progress (performTask was called
     ///     if an upstream query is still in progress (performTask was called
     ///     before and the callback was not called by the query yet).
     ///     before and the callback was not called by the query yet).
-    Task nextTask() const;
+    Task nextTask() const {
+        // Will check for outstanding_ internally too
+        if (done()) {
+            isc_throw(isc::InvalidOperation, "We are done, no more tasks");
+        }
+        return (steps_.back().first);
+    }
     /// \brief Move network communication to different interface.
     /// \brief Move network communication to different interface.
     ///
     ///
     /// By default, a query does all the "communication" on the interface
     /// By default, a query does all the "communication" on the interface
@@ -113,7 +143,13 @@ public:
     ///
     ///
     /// \throw isc::InvalidOperation if it is called while an upstream query
     /// \throw isc::InvalidOperation if it is called while an upstream query
     ///     is in progress.
     ///     is in progress.
-    void migrateTo(FakeInterface& dst_interface);
+    void migrateTo(FakeInterface& dst_interface) {
+        if (outstanding_) {
+            isc_throw(isc::InvalidOperation,
+                      "Can't migrate in the middle of query");
+        }
+        interface_ = &dst_interface;
+    }
 };
 };
 
 
 typedef boost::shared_ptr<FakeQuery> FakeQueryPtr;
 typedef boost::shared_ptr<FakeQuery> FakeQueryPtr;
@@ -130,9 +166,19 @@ typedef boost::shared_ptr<FakeQuery> FakeQueryPtr;
 ///
 ///
 /// If the model simulated would share the same interface between multiple
 /// If the model simulated would share the same interface between multiple
 /// threads, it is better to have one in each thread as well, but lock
 /// threads, it is better to have one in each thread as well, but lock
-/// access so only one is used at once (no idea what happens if ASIO loop is
-/// accessed from multiple threads).
+/// access to receiveQuery() so only one is used at once (no idea what happens
+/// if ASIO loop is accessed from multiple threads).
+///
+/// Note that the creation of the queries is not thread safe (due to
+/// the random() function inside). The interface generates all its queries
+/// in advance, on creation time. But you need to create all the needed
+/// interfaces from single thread and then distribute them to your threads.
 class FakeInterface {
 class FakeInterface {
+private:
+    friend class FakeQuery;
+    void scheduleUpstreamAnswer(FakeQuery* query,
+                                const FakeQuery::StepCallback& callback,
+                                size_t msec);
 public:
 public:
     /// \brief Wait for answers from upstream servers.
     /// \brief Wait for answers from upstream servers.
     ///
     ///