[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