Parcourir la source

ZoneEntry::Lock implementation

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac408@3517 e5f2f494-b856-4b98-b285-d166d9295462
Michal Vaner il y a 14 ans
Parent
commit
46c0c2faaa
3 fichiers modifiés avec 46 ajouts et 5 suppressions
  1. 3 1
      src/lib/nsas/nameserver_entry.h
  2. 39 2
      src/lib/nsas/zone_entry.cc
  3. 4 2
      src/lib/nsas/zone_entry.h

+ 3 - 1
src/lib/nsas/nameserver_entry.h

@@ -55,7 +55,7 @@ public:
     {}
 };
 
-
+class ZoneEntry;
 
 /// \brief Nameserver Entry
 ///
@@ -202,6 +202,8 @@ private:
     std::vector<AddressEntry> address_; ///< Set of V4/V6 addresses
     time_t          expiration_;        ///< Summary expiration time
     time_t          last_access_;       ///< Last access time to the structure
+    // We allow ZoneEntry to lock us
+    friend class ZoneEntry;
 };
 
 }   // namespace dns

+ 39 - 2
src/lib/nsas/zone_entry.cc

@@ -16,14 +16,23 @@
 
 #include "zone_entry.h"
 #include "address_request_callback.h"
+#include "nameserver_entry.h"
+
+#include <algorithm>
+#include <boost/foreach.hpp>
+
+using namespace std;
+using namespace boost;
 
 namespace isc {
 namespace nsas {
 
 namespace {
 // Shorter aliases for frequently used types
-typedef boost::mutex::scoped_lock LLock; // Local lock, nameservers not locked
-typedef boost::shared_ptr<AddressRequestCallback> CallbackPtr;
+typedef mutex::scoped_lock LLock; // Local lock, nameservers not locked
+typedef shared_ptr<LLock> LockPtr;
+typedef vector<LockPtr> Locks;
+typedef shared_ptr<AddressRequestCallback> CallbackPtr;
 }
 
 void
@@ -46,5 +55,33 @@ ZoneEntry::popCallback() {
     return (result);
 }
 
+// Struct, we are somewhere inside, no need to play the private & public game
+struct ZoneEntry::Lock::Impl {
+    Locks locks;
+};
+
+ZoneEntry::Lock::Lock(shared_ptr<Impl> impl) :
+    impl_(impl)
+{ }
+
+ZoneEntry::Lock
+ZoneEntry::getLock() {
+    // First, lock the zone so we can get the nameservers
+    LockPtr lock(new LLock(mutex_));
+    // Get a sorted copy of the nameservers
+    // They are sorted to avoid possible race conditions, they will be locked
+    // in increasing order
+    NameserverVector nameserverCopy(nameservers_);
+    sort(nameserverCopy.begin(), nameserverCopy.end());
+    // Construct the list of locks and lock all the nameservers
+    shared_ptr<Lock::Impl> impl(new Lock::Impl);
+    impl->locks.push_back(lock);
+    BOOST_FOREACH(NameserverPtr ns, nameserverCopy) {
+        impl->locks.push_back(LockPtr(new LLock(ns->mutex_)));
+    }
+
+    return (Lock(impl));
+}
+
 }; // namespace nsas
 }; // namespace isc

+ 4 - 2
src/lib/nsas/zone_entry.h

@@ -133,12 +133,14 @@ public:
      * Copy constructor, assignment operator and destructor are default.
      * The constructor that creates a new lock is private, use getLock()
      * to lock a zone entry.
+     *
+     * It is an error for the lock to survive destruction of its zone entry.
      */
     class Lock {
         private:
             struct Impl;
             boost::shared_ptr<Impl> impl_;
-            Lock(ZoneEntry&);
+            Lock(boost::shared_ptr<Impl>);
             friend class ZoneEntry;
     };
 
@@ -147,7 +149,7 @@ public:
      *
      * \see Lock
      */
-    Lock getLock() { return Lock(*this); }
+    Lock getLock();
 private:
     mutable boost::mutex    mutex_;     ///< Mutex protecting this zone entry
     std::string     name_;      ///< Canonical zone name