Browse Source

An interface change to pass back timeouts

This change will allow passing a timeout (and, in future, possibly more
errors) from UDPQuery. UDPQuery no longer needs a server to resume, it
can call anything that is passed there.

The interface change propagation is stopped directly above it by a hack.
Maybe it will propagate more or the Callback will be more general (not
just for UDPQuery).

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/vorner-recursor-timeouts@3393 e5f2f494-b856-4b98-b285-d166d9295462
Michal Vaner 14 years ago
parent
commit
bf38ef9caa
3 changed files with 43 additions and 14 deletions
  1. 17 1
      src/lib/asiolink/asiolink.cc
  2. 21 9
      src/lib/asiolink/internal/udpdns.h
  3. 5 4
      src/lib/asiolink/udpdns.cc

+ 17 - 1
src/lib/asiolink/asiolink.cc

@@ -227,6 +227,18 @@ RecursiveQuery::RecursiveQuery(DNSService& dns_service, const char& forward,
     dns_service_(dns_service), ns_addr_(&forward), port_(port) 
 {}
 
+namespace {
+
+// This is just temporary so the interface change does not propagate too far
+struct ServerNotify : public UDPQuery::Callback {
+    DNSServer *server;
+    virtual void operator()(UDPQuery::Result result) {
+        server->resume(result == UDPQuery::SUCCESS);
+    }
+};
+
+}
+
 void
 RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
                           DNSServer* server)
@@ -237,7 +249,11 @@ RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
     // UDP and then fall back to TCP on failure, but for the moment
     // we're only going to handle UDP.
     asio::io_service& io = dns_service_.get_io_service();
-    UDPQuery q(io, question, ns_addr_, port_, buffer, server);
+    boost::shared_ptr<ServerNotify> callback(new ServerNotify);
+    // FIXME This is said it does problems when it is shared pointer, as
+    // it is destroyed too soon. But who deletes it now?
+    callback->server = server->clone();
+    UDPQuery q(io, question, ns_addr_, port_, buffer, callback);
     io.post(q);
 }
 

+ 21 - 9
src/lib/asiolink/internal/udpdns.h

@@ -180,11 +180,28 @@ private:
 //
 class UDPQuery : public coroutine {
 public:
+    // TODO Maybe this should be more generic than just for UDPQuery?
+    /**
+     * \short Result of the query
+     *
+     * This is related only to contacting the remote server. If the answer
+     * indicates error, it is still counted as SUCCESS here, if it comes back.
+     */
+    enum Result {
+        SUCCESS,
+        TIME_OUT
+    };
+    /// Abstract callback for the UDPQuery.
+    class Callback {
+        public:
+            /// This will be called when the UDPQuery is completed
+            virtual void operator()(Result result) = 0;
+    };
     explicit UDPQuery(asio::io_service& io_service,
                       const isc::dns::Question& q,
                       const IOAddress& addr, uint16_t port,
                       isc::dns::OutputBufferPtr buffer,
-                      DNSServer* server);
+                      boost::shared_ptr<Callback> callback, int timeout = -1);
     void operator()(asio::error_code ec = asio::error_code(),
                     size_t length = 0); 
 private:
@@ -211,20 +228,15 @@ private:
 
     // The output buffer supplied by the caller.  The resposne frmo
     // the upstream server will be copied here.
-    isc::dns::OutputBufferPtr buffer_;;
+    isc::dns::OutputBufferPtr buffer_;
 
     // These are allocated for each new query and are stored as
     // shared pointers to minimize copy overhead.
     isc::dns::OutputBufferPtr msgbuf_;
     boost::shared_array<char> data_;
 
-    // The UDP or TCP Server object from which the query originated.
-    // Note: Using a shared_ptr for this can cause problems when
-    // control is being transferred from this coroutine to the server;
-    // the reference count can drop to zero and cause the server to be
-    // destroyed before it executes.  Consequently in this case it's
-    // safer to use a raw pointer.
-    DNSServer* server_;
+    // This will be called when we are done.
+    boost::shared_ptr<Callback> callback_;
 };
 }
 

+ 5 - 4
src/lib/asiolink/udpdns.cc

@@ -176,8 +176,9 @@ UDPServer::resume(const bool done) {
 /// The constructor
 UDPQuery::UDPQuery(io_service& io_service,
                    const Question& q, const IOAddress& addr, uint16_t port,
-                   OutputBufferPtr buffer, DNSServer* server) :
-    question_(q), buffer_(buffer), server_(server->clone())
+                   OutputBufferPtr buffer,
+                   boost::shared_ptr<Callback> callback, int timeout) :
+    question_(q), buffer_(buffer), callback_(callback)
 {
     udp proto = (addr.getFamily() == AF_INET) ? udp::v4() : udp::v6();
     socket_.reset(new udp::socket(io_service, proto));
@@ -232,8 +233,8 @@ UDPQuery::operator()(error_code ec, size_t length) {
         /// be unnecessary.)
         buffer_->writeData(data_.get(), length);
 
-        /// Signal the DNSServer object to resume processing.
-        server_->resume(true);
+        /// We are done
+        (*callback_)(SUCCESS);
     }
 }