[svn] commit: r3708 - in /branches/trac408/src/lib/nsas: tests/zone_entry_unittest.cc zone_entry.cc zone_entry.h

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Dec 3 16:37:13 UTC 2010


Author: vorner
Date: Fri Dec  3 16:37:13 2010
New Revision: 3708

Log:
Pass another test

When there are no nameservers

Modified:
    branches/trac408/src/lib/nsas/tests/zone_entry_unittest.cc
    branches/trac408/src/lib/nsas/zone_entry.cc
    branches/trac408/src/lib/nsas/zone_entry.h

Modified: branches/trac408/src/lib/nsas/tests/zone_entry_unittest.cc
==============================================================================
--- branches/trac408/src/lib/nsas/tests/zone_entry_unittest.cc (original)
+++ branches/trac408/src/lib/nsas/tests/zone_entry_unittest.cc Fri Dec  3 16:37:13 2010
@@ -97,7 +97,7 @@
     shared_ptr<InheritedZoneEntry> zone(new InheritedZoneEntry(resolver_,
         EXAMPLE_CO_UK, RRClass::IN(), nameserver_table_, nameserver_lru_));
     // It should accept the callback
-    EXPECT_TRUE(zone->addCallback(callback_, ANY_OK, zone));
+    zone->addCallback(callback_, ANY_OK, zone);
     // Ask for the nameservers
     EXPECT_NO_THROW(resolver_->provideNS(0, rr_empty_));
     // And tell imediatelly that it is unreachable (when it has no nameservers)
@@ -112,14 +112,15 @@
     shared_ptr<InheritedZoneEntry> zone(new InheritedZoneEntry(resolver_,
         EXAMPLE_CO_UK, RRClass::IN(), nameserver_table_, nameserver_lru_));
     // It should accept the callback
-    EXPECT_TRUE(zone->addCallback(callback_, ANY_OK, zone));
+    zone->addCallback(callback_, ANY_OK, zone);
     EXPECT_NO_THROW(resolver_->provideNS(0, rr_empty_));
     // It should not be answered yet, it should ask for the IP addresses
     EXPECT_TRUE(callback_->successes_.empty());
     EXPECT_EQ(0, callback_->unreachable_count_);
     resolver_->asksIPs(ns_name_, 1, 2);
-    // It should reject another one, as it has zero TTL
-    EXPECT_FALSE(zone->addCallback(callback_, ANY_OK, zone));
+    // It should request the NSs again, as TTL is 0
+    zone->addCallback(callback_, ANY_OK, zone);
+    EXPECT_EQ(4, resolver_->requests.size());
 }
 
 // Check it answers callbacks when we give it addresses
@@ -129,7 +130,7 @@
     // It should be in NOT_ASKED state
     EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
     // It should accept the callback
-    EXPECT_TRUE(zone->addCallback(callback_, ANY_OK, zone));
+    zone->addCallback(callback_, ANY_OK, zone);
     EXPECT_NO_THROW(resolver_->provideNS(0, rr_empty_));
     // It should not be answered yet, it should ask for the IP addresses
     EXPECT_TRUE(callback_->successes_.empty());
@@ -138,8 +139,8 @@
     // We should be IN_PROGRESS
     EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
     // Give two more callbacks, with different address families
-    EXPECT_TRUE(zone->addCallback(callback_, V4_ONLY, zone));
-    EXPECT_TRUE(zone->addCallback(callback_, V6_ONLY, zone));
+    zone->addCallback(callback_, V4_ONLY, zone);
+    zone->addCallback(callback_, V6_ONLY, zone);
     // Nothing more is asked
     EXPECT_EQ(3, resolver_->requests.size());
     EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::A(),
@@ -161,7 +162,7 @@
     // It should think it is ready
     EXPECT_EQ(Fetchable::READY, zone->getState());
     // When we ask something more, it should be answered right away
-    EXPECT_TRUE(zone->addCallback(callback_, V4_ONLY, zone));
+    zone->addCallback(callback_, V4_ONLY, zone);
     EXPECT_EQ(3, resolver_->requests.size());
     ASSERT_EQ(4, callback_->successes_.size());
     EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[3]));
@@ -175,7 +176,7 @@
     // It should be in NOT_ASKED state
     EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
     // It should accept the callback
-    EXPECT_TRUE(zone->addCallback(callback_, ANY_OK, zone));
+    zone->addCallback(callback_, ANY_OK, zone);
     EXPECT_NO_THROW(resolver_->provideNS(0, rr_empty_));
     // It should not be answered yet, it should ask for the IP addresses
     EXPECT_TRUE(callback_->successes_.empty());
@@ -184,8 +185,8 @@
     // We should be IN_PROGRESS
     EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
     // Give two more callbacks, with different address families
-    EXPECT_TRUE(zone->addCallback(callback_, V4_ONLY, zone));
-    EXPECT_TRUE(zone->addCallback(callback_, V6_ONLY, zone));
+    zone->addCallback(callback_, V4_ONLY, zone);
+    zone->addCallback(callback_, V6_ONLY, zone);
     ASSERT_GE(resolver_->requests.size(), 3);
     resolver_->requests[2].second->failure();
     // One should be rejected, but two still stay, they have chance
@@ -202,13 +203,13 @@
     // Everything arriwed, so we are ready
     EXPECT_EQ(Fetchable::READY, zone->getState());
     // Try asking something more
-    EXPECT_TRUE(zone->addCallback(callback_, V4_ONLY, zone));
+    zone->addCallback(callback_, V4_ONLY, zone);
     EXPECT_EQ(3, resolver_->requests.size());
     ASSERT_EQ(3, callback_->successes_.size());
     EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[2]));
     EXPECT_EQ(1, callback_->unreachable_count_);
 
-    EXPECT_TRUE(zone->addCallback(callback_, V6_ONLY, zone));
+    zone->addCallback(callback_, V6_ONLY, zone);
     EXPECT_EQ(3, resolver_->requests.size());
     EXPECT_EQ(3, callback_->successes_.size());
     EXPECT_EQ(2, callback_->unreachable_count_);
@@ -221,7 +222,7 @@
     // It should be in NOT_ASKED state
     EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
     // It should accept the callback
-    EXPECT_TRUE(zone->addCallback(callback_, V4_ONLY, zone));
+    zone->addCallback(callback_, V4_ONLY, zone);
     EXPECT_NO_THROW(resolver_->provideNS(0, rr_empty_));
     EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
     // It asks a question (we do not know which nameserver)
@@ -246,15 +247,15 @@
     EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
     // And question for v6 or any should still wait while v4 should be failed
     // right away
-    EXPECT_TRUE(zone->addCallback(callback_, V6_ONLY, zone));
-    EXPECT_EQ(1, callback_->unreachable_count_);
-    EXPECT_EQ(0, callback_->successes_.size());
-
-    EXPECT_TRUE(zone->addCallback(callback_, ANY_OK, zone));
-    EXPECT_EQ(1, callback_->unreachable_count_);
-    EXPECT_EQ(0, callback_->successes_.size());
-
-    EXPECT_TRUE(zone->addCallback(callback_, V4_ONLY, zone));
+    zone->addCallback(callback_, V6_ONLY, zone);
+    EXPECT_EQ(1, callback_->unreachable_count_);
+    EXPECT_EQ(0, callback_->successes_.size());
+
+    zone->addCallback(callback_, ANY_OK, zone);
+    EXPECT_EQ(1, callback_->unreachable_count_);
+    EXPECT_EQ(0, callback_->successes_.size());
+
+    zone->addCallback(callback_, V4_ONLY, zone);
     EXPECT_EQ(2, callback_->unreachable_count_);
     EXPECT_EQ(0, callback_->successes_.size());
     // Answer the IPv6 one

Modified: branches/trac408/src/lib/nsas/zone_entry.cc
==============================================================================
--- branches/trac408/src/lib/nsas/zone_entry.cc (original)
+++ branches/trac408/src/lib/nsas/zone_entry.cc Fri Dec  3 16:37:13 2010
@@ -20,6 +20,7 @@
 
 #include <algorithm>
 #include <boost/foreach.hpp>
+#include <dns/rrttl.h>
 
 using namespace std;
 using namespace boost;
@@ -36,16 +37,121 @@
 typedef shared_ptr<AddressRequestCallback> CallbackPtr;
 }
 
-bool
-ZoneEntry::addCallback(CallbackPtr callback,  AddressFamily family,
+// A struct, the class is unaccessible anyway and is ours
+struct ZoneEntry::ResolverCallback : public ResolverInterface::Callback {
+    ResolverCallback(shared_ptr<ZoneEntry> entry) :
+        entry_(entry)
+    { }
+    virtual void success(shared_ptr<AbstractRRset> answer) {
+        Lock lock(entry_->mutex_);
+        RdataIteratorPtr iterator(answer->getRdataIterator());
+        iterator->first();
+        // If there are no data
+        if (iterator->isLast()) {
+            failureInternal(lock, answer->getTTL().getValue());
+            return;
+        }
+    }
+    virtual void failure() {
+        Lock lock(entry_->mutex_);
+        /*
+         * FIXME: That 5 minutes is just made up and wrong.
+         * Where is the correct place to get the correct number?
+         */
+        failureInternal(lock, 300);
+    }
+    void failureInternal(Lock& lock, time_t ttl) {
+        entry_->setState(UNREACHABLE);
+        entry_->expiry_ = ttl + time(NULL);
+        // Process all three callback lists and tell them KO
+        // We put them into one set and call that one, so they are
+        // taken out atomicaly
+        entry_->callbacks_[ANY_OK].insert(entry_->callbacks_[ANY_OK].end(),
+            entry_->callbacks_[V4_ONLY].begin(),
+            entry_->callbacks_[V4_ONLY].end());
+        entry_->callbacks_[V4_ONLY].clear();
+        entry_->callbacks_[ANY_OK].insert(entry_->callbacks_[ANY_OK].end(),
+            entry_->callbacks_[V6_ONLY].begin(),
+            entry_->callbacks_[V6_ONLY].end());
+        entry_->callbacks_[V6_ONLY].clear();
+        // The process function will lock by its own
+        lock.unlock();
+        entry_->process(CallbackPtr(), ANY_OK, NULL);
+    }
+    shared_ptr<ZoneEntry> entry_;
+};
+
+void
+ZoneEntry::addCallback(CallbackPtr callback, AddressFamily family,
     shared_ptr<ZoneEntry> self)
 {
-    // TODO: this is just stub now, to compile
-    (void) callback;
-    (void) family;
-    (void) self;
-    return (false);
+    Lock lock(mutex_);
 
+    bool ask(false);
+
+    // Look at expiration time
+    if (expiry_ && time(NULL) >= expiry_) {
+        setState(EXPIRED);
+    }
+
+    // We need to ask (again)
+    if (getState() == EXPIRED || getState() == NOT_ASKED) {
+        ask = true;
+    }
+
+    // We do not have the answer right away, just queue the callback
+    if (ask || getState() == IN_PROGRESS || !callbacks_[family].empty()) {
+        callbacks_[family].push_back(callback);
+    } else {
+        // Try to process it right away, store if not possible to handle
+        lock.unlock();
+        process(callback, family, NULL);
+        return;
+    }
+
+    if (ask) {
+        setState(IN_PROGRESS);
+        QuestionPtr question(new Question(Name(name_), class_code_,
+            RRType::NS()));
+        shared_ptr<ResolverCallback> resolver_callback(
+            new ResolverCallback(self));
+        resolver_->resolve(question, resolver_callback);
+    }
+}
+
+void
+ZoneEntry::process(CallbackPtr callback, AddressFamily family,
+    NameserverEntry*)
+{
+    Lock lock(mutex_);
+
+    if (callback) {
+        callbacks_[family].push_back(callback);
+    }
+
+    switch (getState()) {
+        // These are not interesting, nothing to return now
+        case NOT_ASKED:
+        case IN_PROGRESS:
+        case EXPIRED:
+            return;
+        case UNREACHABLE: {
+            // We extract all the callbacks
+            vector<CallbackPtr> callbacks;
+            callbacks.swap(callbacks_[family]);
+            // We want to call them not locked, so we both do not block the
+            // lock and allow them to call our functions
+            lock.unlock();
+            BOOST_FOREACH(const CallbackPtr& callback, callbacks) {
+                callback->unreachable();
+            }
+            // And we do nothing more now
+            return;
+        }
+        case READY:
+            // TODO Write
+            ;
+    }
 }
 
 }; // namespace nsas

Modified: branches/trac408/src/lib/nsas/zone_entry.h
==============================================================================
--- branches/trac408/src/lib/nsas/zone_entry.h (original)
+++ branches/trac408/src/lib/nsas/zone_entry.h Fri Dec  3 16:37:13 2010
@@ -19,7 +19,6 @@
 
 #include <string>
 #include <vector>
-#include <list>
 #include <boost/thread.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -66,6 +65,7 @@
         const std::string& name, const isc::dns::RRClass& class_code,
         boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table,
         boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru) :
+        expiry_(0),
         name_(name), class_code_(class_code), resolver_(resolver),
         nameserver_table_(nameserver_table), nameserver_lru_(nameserver_lru)
     {}
@@ -98,11 +98,8 @@
      *     will already exist at that point, however it is needed to callback.
      *     When calling function on the zone entry, you should already have
      *     one.
-     * \return True if the zone is still valid and accepted the callback.
-     *     If it returns false, it should be discarded (it has timed out)
-     *     and new instance should be created.
      */
-    bool addCallback(boost::shared_ptr<AddressRequestCallback>
+    void addCallback(boost::shared_ptr<AddressRequestCallback>
         callback, AddressFamily family, boost::shared_ptr<ZoneEntry> self);
 
     /// \short Protected members, so they can be accessed by tests.
@@ -112,8 +109,13 @@
     typedef boost::shared_ptr<NameserverEntry> NameserverPtr;
     typedef std::vector<NameserverPtr> NameserverVector;
     NameserverVector nameservers_; ///< Nameservers
-    std::list<boost::shared_ptr<AddressRequestCallback> > callbacks_;
-    time_t          expiry_;    ///< Expiry time of this entry
+    /*
+     * Callbacks. For each fimily type one vector, so we can process
+     * them separately.
+     */
+    std::vector<boost::shared_ptr<AddressRequestCallback> >
+        callbacks_[ADDR_REQ_MAX];
+    time_t          expiry_;    ///< Expiry time of this entry, 0 means not set
     //}@
 private:
     mutable boost::mutex    mutex_;     ///< Mutex protecting this zone entry
@@ -123,6 +125,7 @@
     // the nameservers (if there's chance there's some info) and calls
     // callbacks. If nameserver is given, it is considered new and valid
     // even if its TTL is 0.
+    // The family says which one changed or has any update.
     void process(boost::shared_ptr<AddressRequestCallback> callback,
          AddressFamily family, NameserverEntry* nameserver);
     // Resolver we use
@@ -131,6 +134,10 @@
     // update
     boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table_;
     boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru_;
+    // Resolver callback class
+    class ResolverCallback;
+    // It has direct access to us
+    friend class ResolverCallback;
 };
 
 } // namespace nsas




More information about the bind10-changes mailing list