Parcourir la 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 il y a 12 ans
Parent
commit
81d23e3051
2 fichiers modifiés avec 57 ajouts et 8 suppressions
  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
 
 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 += $(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
 #define FAKE_RESOLUTION_H
 
+#include <exceptions/exceptions.h>
+
 #include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
 
+#include <utility>
+#include <vector>
+
 namespace isc {
 namespace resolver {
 namespace bench {
@@ -70,16 +75,35 @@ class FakeInterface;
 ///
 /// See naive_resolver.cc for example code how this could be done.
 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:
-    /// \brief Callback to signify a task has been performed.
-    typedef boost::function<void()> StepCallback;
     /// \brief Is work on the query completely done?
     ///
     /// If this returns true, do not call performTask or nextTask any more.
     /// The resolution is done.
     ///
     /// \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.
     ///
     /// 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
     ///     if an upstream query is still in progress (performTask was called
     ///     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.
     ///
     /// 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
     ///     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;
@@ -130,9 +166,19 @@ typedef boost::shared_ptr<FakeQuery> FakeQueryPtr;
 ///
 /// 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
-/// 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 {
+private:
+    friend class FakeQuery;
+    void scheduleUpstreamAnswer(FakeQuery* query,
+                                const FakeQuery::StepCallback& callback,
+                                size_t msec);
 public:
     /// \brief Wait for answers from upstream servers.
     ///