Parcourir la source

Merge branch 'master' of ssh://git.bind10.isc.org/var/bind10/git/bind10

JINMEI Tatuya il y a 13 ans
Parent
commit
7132a80692

+ 7 - 0
ChangeLog

@@ -1,3 +1,10 @@
+359.	[func]*		vorner
+	The target parameter of ZoneFinder::find is no longer present, as the
+	interface was awkward. To get all the RRsets of a single domain, use
+	the new findAll method (the same applies to python version, the method
+	is named find_all).
+	(Trac #1483,#1484, git 0020456f8d118c9f3fd6fc585757c822b79a96f6)
+
 349.	[bug]		dvv
 	resolver: If an upstream server responds with FORMERR to an EDNS query,
 	try querying it without EDNS.

+ 1 - 1
src/bin/xfrin/tests/xfrin_test.py

@@ -158,7 +158,7 @@ class MockDataSourceClient():
             return (DataSourceClient.PARTIALMATCH, self)
         raise ValueError('Unexpected input to mock client: bug in test case?')
 
-    def find(self, name, rrtype, target=None, options=ZoneFinder.FIND_DEFAULT):
+    def find(self, name, rrtype, options=ZoneFinder.FIND_DEFAULT):
         '''Mock ZoneFinder.find().
 
         It returns the predefined SOA RRset to queries for SOA of the common

+ 1 - 2
src/bin/xfrin/xfrin.py.in

@@ -583,8 +583,7 @@ class XfrinConnection(asyncore.dispatcher):
             result, finder = self._datasrc_client.find_zone(self._zone_name)
         if result != DataSourceClient.SUCCESS:
             return None
-        result, soa_rrset = finder.find(self._zone_name, RRType.SOA(),
-                                        None, ZoneFinder.FIND_DEFAULT)
+        result, soa_rrset = finder.find(self._zone_name, RRType.SOA())
         if result != ZoneFinder.SUCCESS:
             logger.info(XFRIN_ZONE_NO_SOA, self.zone_str())
             return None

+ 1 - 1
src/bin/xfrout/tests/xfrout_test.py.in

@@ -95,7 +95,7 @@ class MockDataSrcClient:
             return (isc.datasrc.DataSourceClient.NOTFOUND, None)
         return (isc.datasrc.DataSourceClient.SUCCESS, self)
 
-    def find(self, name, rrtype, target=None, options=ZoneFinder.FIND_DEFAULT):
+    def find(self, name, rrtype, options=ZoneFinder.FIND_DEFAULT):
         '''Mock ZoneFinder.find().
 
         (At the moment) this method only handles query for type SOA.

+ 1 - 2
src/bin/xfrout/xfrout.py.in

@@ -336,8 +336,7 @@ class XfroutSession():
         result, finder = self._datasrc_client.find_zone(zone_name)
         if result != DataSourceClient.SUCCESS:
             return (Rcode.NOTAUTH(), None)
-        result, soa_rrset = finder.find(zone_name, RRType.SOA(), None,
-                                        ZoneFinder.FIND_DEFAULT)
+        result, soa_rrset = finder.find(zone_name, RRType.SOA())
         if result != ZoneFinder.SUCCESS:
             return (Rcode.SERVFAIL(), None)
         # Especially for database-based zones, a working zone may be in

+ 0 - 4
src/lib/datasrc/zone.h

@@ -238,10 +238,6 @@ public:
     /// - If the search name matches a delegation point of DNAME, it returns
     ///   the code of \c DNAME and that DNAME RR.
     ///
-    /// \note This behavior is controversial as we discussed in
-    /// https://lists.isc.org/pipermail/bind10-dev/2011-January/001918.html
-    /// We should revisit the interface before we heavily rely on it.
-    ///
     /// The \c options parameter specifies customized behavior of the search.
     /// Their semantics is as follows (they are or bit-field):
     ///

+ 21 - 11
src/lib/python/isc/datasrc/finder_inc.cc

@@ -46,9 +46,8 @@ Return the RR class of the zone.\n\
 // - Return type: use tuple instead of the dedicated FindResult type
 // - NULL->None
 // - exceptions
-// - description of the 'target' parameter (must be None for now)
 const char* const ZoneFinder_find_doc = "\
-find(name, type, target=None, options=FIND_DEFAULT) -> (integer, RRset)\n\
+find(name, type, options=FIND_DEFAULT) -> (integer, RRset)\n\
 \n\
 Search the zone for a given pair of domain name and RR type.\n\
 \n\
@@ -72,14 +71,6 @@ answer for the search key. Specifically,\n\
   and the code of SUCCESS will be returned.\n\
 - If the search name matches a delegation point of DNAME, it returns\n\
   the code of DNAME and that DNAME RR.\n\
-- If the target isn't None, all RRsets under the domain are inserted\n\
-  there and SUCCESS (or NXDOMAIN, in case of empty domain) is returned\n\
-  instead of normall processing. This is intended to handle ANY query.\n\
-  (Note: the Python version doesn't support this feature yet)\n\
-\n\
-Note: This behavior is controversial as we discussed in\n\
-https://lists.isc.org/pipermail/bind10-dev/2011-January/001918.html We\n\
-should revisit the interface before we heavily rely on it.\n\
 \n\
 The options parameter specifies customized behavior of the search.\n\
 Their semantics is as follows (they are or bit-field):\n\
@@ -107,13 +98,32 @@ internal error in the datasource.\n\
 Parameters:\n\
   name       The domain name to be searched for.\n\
   type       The RR type to be searched for.\n\
-  target     Must be None.\n\
   options    The search options.\n\
 \n\
 Return Value(s): A tuple of a result code (integer) and an RRset object\n\
 enclosing the search result (see above).\n\
 ";
 
+const char* const ZoneFinder_find_all_doc = "\
+find_all(isc.dns.Name, options=FIND_DEFAULT) -> (integer, RRset) | (integer, [RRset])\
+\n\
+This acts mostly the same as the find method. The main difference is,\n\
+when the lookup is successful (eg. the first part of the result is either\n\
+SUCCESS or WILDCARD), the second part is list of all RRsets in the given name\n\
+instead of a single RRset as in case of find.\n\
+\n\
+This method raises an isc.datasrc.Error exception if there is an\n\
+internal error in the datasource.\n\
+\n\
+Parameters:\n\
+  name       The domain name to be searched for.\n\
+  options    The search options.\n\
+\n\
+Return Value(s): A tuple of a result code (integer) and an either RRset object,\n\
+for cases where the result is some kind of delegation, CNAME or similar, or list\n\
+of RRset objects, containing all the results.\n\
+";
+
 const char* const ZoneFinder_find_previous_name_doc = "\
 find_previous_name(isc.dns.Name) -> isc.dns.Name\n\
 \n\

+ 69 - 13
src/lib/python/isc/datasrc/finder_python.cc

@@ -59,17 +59,11 @@ PyObject* ZoneFinder_helper(ZoneFinder* finder, PyObject* args) {
     }
     PyObject* name;
     PyObject* rrtype;
-    PyObject* target = Py_None;
     unsigned int options_int = ZoneFinder::FIND_DEFAULT;
-    if (PyArg_ParseTuple(args, "O!O!|OI", &name_type, &name,
+    if (PyArg_ParseTuple(args, "O!O!|I", &name_type, &name,
                                          &rrtype_type, &rrtype,
-                                         &target, &options_int)) {
+                                         &options_int)) {
         try {
-            if (target != Py_None) {
-                PyErr_SetString(PyExc_TypeError,
-                                "find(): target must be None in this version");
-                return (NULL);
-            }
             ZoneFinder::FindOptions options =
                 static_cast<ZoneFinder::FindOptions>(options_int);
             const ZoneFinder::FindResult find_result(
@@ -97,7 +91,60 @@ PyObject* ZoneFinder_helper(ZoneFinder* finder, PyObject* args) {
     } else {
         return (NULL);
     }
-    return Py_BuildValue("I", 1);
+}
+
+PyObject* ZoneFinder_helper_all(ZoneFinder* finder, PyObject* args) {
+    if (finder == NULL) {
+        PyErr_SetString(getDataSourceException("Error"),
+                        "Internal error in find_all() wrapper; "
+                        "finder object NULL");
+        return (NULL);
+    }
+    PyObject* name;
+    const unsigned int options_int = ZoneFinder::FIND_DEFAULT;
+    if (PyArg_ParseTuple(args, "O!|I", &name_type, &name, &options_int)) {
+        try {
+            ZoneFinder::FindOptions options =
+                static_cast<ZoneFinder::FindOptions>(options_int);
+            std::vector<isc::dns::ConstRRsetPtr> target;
+            const ZoneFinder::FindResult find_result(
+                finder->findAll(PyName_ToName(name), target, options));
+            const ZoneFinder::Result r = find_result.code;
+            isc::dns::ConstRRsetPtr rrsp = find_result.rrset;
+            if (r == ZoneFinder::SUCCESS || r == ZoneFinder::WILDCARD) {
+                // Copy all the RRsets to the result list
+                PyObjectContainer list_container(PyList_New(target.size()));
+                for (size_t i(0); i < target.size(); ++i) {
+                    PyList_SET_ITEM(list_container.get(), i,
+                                    createRRsetObject(*target[i]));
+                }
+                // Construct the result with the list. The Py_BuildValue
+                // increases the refcount and the container decreases it
+                // later. This way, it feels safer in case the build function
+                // would fail.
+                return (Py_BuildValue("IO", r, list_container.get()));
+            } else {
+                if (rrsp) {
+                    // Use N instead of O so the refcount isn't increased twice
+                    return (Py_BuildValue("IN", r, createRRsetObject(*rrsp)));
+                } else {
+                    return (Py_BuildValue("IO", r, Py_None));
+                }
+            }
+        } catch (const DataSourceError& dse) {
+            PyErr_SetString(getDataSourceException("Error"), dse.what());
+            return (NULL);
+        } catch (const std::exception& exc) {
+            PyErr_SetString(getDataSourceException("Error"), exc.what());
+            return (NULL);
+        } catch (...) {
+            PyErr_SetString(getDataSourceException("Error"),
+                            "Unexpected exception");
+            return (NULL);
+        }
+    } else {
+        return (NULL);
+    }
 }
 
 } // end namespace internal
@@ -121,7 +168,7 @@ typedef CPPPyObjectContainer<s_ZoneFinder, ZoneFinder> ZoneFinderContainer;
 
 // General creation and destruction
 int
-ZoneFinder_init(s_ZoneFinder* self, PyObject* args) {
+ZoneFinder_init(PyObject*, PyObject*, PyObject*) {
     // can't be called directly
     PyErr_SetString(PyExc_TypeError,
                     "ZoneFinder cannot be constructed directly");
@@ -130,7 +177,8 @@ ZoneFinder_init(s_ZoneFinder* self, PyObject* args) {
 }
 
 void
-ZoneFinder_destroy(s_ZoneFinder* const self) {
+ZoneFinder_destroy(PyObject* po_self) {
+    s_ZoneFinder* self = static_cast<s_ZoneFinder*>(po_self);
     // cppobj is a shared ptr, but to make sure things are not destroyed in
     // the wrong order, we reset it here.
     self->cppobj.reset();
@@ -173,6 +221,13 @@ ZoneFinder_find(PyObject* po_self, PyObject* args) {
 }
 
 PyObject*
+ZoneFinder_find_all(PyObject* po_self, PyObject* args) {
+    s_ZoneFinder* const self = static_cast<s_ZoneFinder*>(po_self);
+    return (isc_datasrc_internal::ZoneFinder_helper_all(self->cppobj.get(),
+                                                        args));
+}
+
+PyObject*
 ZoneFinder_findPreviousName(PyObject* po_self, PyObject* args) {
     s_ZoneFinder* const self = static_cast<s_ZoneFinder*>(po_self);
     PyObject* name_obj;
@@ -208,6 +263,7 @@ PyMethodDef ZoneFinder_methods[] = {
        ZoneFinder_getOrigin_doc },
     { "get_class", ZoneFinder_getClass, METH_NOARGS, ZoneFinder_getClass_doc },
     { "find", ZoneFinder_find, METH_VARARGS, ZoneFinder_find_doc },
+    { "find_all", ZoneFinder_find_all, METH_VARARGS, ZoneFinder_find_all_doc },
     { "find_previous_name", ZoneFinder_findPreviousName, METH_VARARGS,
       ZoneFinder_find_previous_name_doc },
     { NULL, NULL, 0, NULL }
@@ -224,7 +280,7 @@ PyTypeObject zonefinder_type = {
     "datasrc.ZoneFinder",
     sizeof(s_ZoneFinder),               // tp_basicsize
     0,                                  // tp_itemsize
-    reinterpret_cast<destructor>(ZoneFinder_destroy),// tp_dealloc
+    ZoneFinder_destroy,                 // tp_dealloc
     NULL,                               // tp_print
     NULL,                               // tp_getattr
     NULL,                               // tp_setattr
@@ -255,7 +311,7 @@ PyTypeObject zonefinder_type = {
     NULL,                               // tp_descr_get
     NULL,                               // tp_descr_set
     0,                                  // tp_dictoffset
-    reinterpret_cast<initproc>(ZoneFinder_init),// tp_init
+    ZoneFinder_init,                    // tp_init
     NULL,                               // tp_alloc
     PyType_GenericNew,                  // tp_new
     NULL,                               // tp_free

+ 78 - 43
src/lib/python/isc/datasrc/tests/datasrc_test.py

@@ -57,6 +57,61 @@ def create_soa(serial):
                         str(serial) + ' 3600 1800 2419200 7200'))
     return soa
 
+def test_findall_common(self, tested):
+    """
+    Common part of the find_all test. It tests a find_all method on the passed
+    object.
+    """
+    # Some "failure" responses
+    result, rrset = tested.find_all(isc.dns.Name("www.sql1.example.com"),
+                                    ZoneFinder.FIND_DEFAULT)
+    self.assertEqual(ZoneFinder.DELEGATION, result)
+    expected = RRset(Name('sql1.example.com.'), RRClass.IN(), RRType.NS(),
+                     RRTTL(3600))
+    expected.add_rdata(Rdata(RRType.NS(), RRClass.IN(),
+                             'dns01.example.com.'))
+    expected.add_rdata(Rdata(RRType.NS(), RRClass.IN(),
+                             'dns02.example.com.'))
+    expected.add_rdata(Rdata(RRType.NS(), RRClass.IN(),
+                             'dns03.example.com.'))
+    self.assertTrue(rrsets_equal(expected, rrset))
+
+    result, rrset = tested.find_all(isc.dns.Name("nxdomain.example.com"),
+                                     ZoneFinder.FIND_DEFAULT)
+    self.assertEqual(ZoneFinder.NXDOMAIN, result)
+    self.assertIsNone(None, rrset)
+
+    # A success. It should return the list now.
+    # This also tests we can ommit the options parameter
+    result, rrsets = tested.find_all(isc.dns.Name("mix.example.com."))
+    self.assertEqual(ZoneFinder.SUCCESS, result)
+    self.assertEqual(2, len(rrsets))
+    rrsets.sort(key=lambda rrset: rrset.get_type().to_text())
+    expected = [
+        RRset(Name('mix.example.com.'), RRClass.IN(), RRType.A(),
+              RRTTL(3600)),
+        RRset(Name('mix.example.com.'), RRClass.IN(), RRType.AAAA(),
+              RRTTL(3600))
+    ]
+    expected[0].add_rdata(Rdata(RRType.A(), RRClass.IN(), "192.0.2.1"))
+    expected[0].add_rdata(Rdata(RRType.A(), RRClass.IN(), "192.0.2.2"))
+    expected[1].add_rdata(Rdata(RRType.AAAA(), RRClass.IN(),
+                                "2001:db8::1"))
+    expected[1].add_rdata(Rdata(RRType.AAAA(), RRClass.IN(),
+                                "2001:db8::2"))
+    for (rrset, exp) in zip(rrsets, expected):
+        self.assertTrue(rrsets_equal(exp, rrset))
+
+    # Check the reference counts on them. The getrefcount returns one more,
+    # as for the reference in its own parameter - see its docs.
+
+    # Two - one for the variable, one for parameter
+    self.assertEqual(2, sys.getrefcount(rrsets))
+    for rrset in rrsets:
+        # 3 - one as the element of list, one for the rrset variable
+        # and one for the parameter.
+        self.assertEqual(3, sys.getrefcount(rrset))
+
 class DataSrcClient(unittest.TestCase):
 
     def test_(self):
@@ -269,6 +324,19 @@ class DataSrcClient(unittest.TestCase):
         self.assertNotEqual(ZoneFinder.WILDCARD_CNAME,
                             ZoneFinder.WILDCARD_NXRRSET)
 
+    def test_findall(self):
+        """
+        A test for the find_all method.
+        """
+        dsc = isc.datasrc.DataSourceClient("sqlite3", READ_ZONE_DB_CONFIG)
+        result, finder = dsc.find_zone(isc.dns.Name("example.com"))
+
+        self.assertEqual(finder.SUCCESS, result)
+        self.assertEqual(isc.dns.RRClass.IN(), finder.get_class())
+        self.assertEqual("example.com.", finder.get_origin().to_text())
+
+        test_findall_common(self, finder)
+
     def test_find(self):
         dsc = isc.datasrc.DataSourceClient("sqlite3", READ_ZONE_DB_CONFIG)
 
@@ -279,7 +347,6 @@ class DataSrcClient(unittest.TestCase):
 
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
@@ -292,20 +359,8 @@ class DataSrcClient(unittest.TestCase):
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
                          rrset.to_text())
 
-        result, rrset = finder.find(isc.dns.Name("www.example.com"),
-                                    isc.dns.RRType.A(), None)
-        self.assertEqual(finder.SUCCESS, result)
-        self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
-                         rrset.to_text())
-
-        # Invalid value for the "target"
-        self.assertRaises(TypeError, finder.find,
-                          isc.dns.Name("www.example.com"),
-                          isc.dns.RRType.A(), True)
-
         result, rrset = finder.find(isc.dns.Name("www.sql1.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.DELEGATION, result)
         self.assertEqual("sql1.example.com. 3600 IN NS dns01.example.com.\n" +
@@ -315,28 +370,24 @@ class DataSrcClient(unittest.TestCase):
 
         result, rrset = finder.find(isc.dns.Name("doesnotexist.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.NXDOMAIN, result)
         self.assertEqual(None, rrset)
 
         result, rrset = finder.find(isc.dns.Name("www.some.other.domain"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.NXDOMAIN, result)
         self.assertEqual(None, rrset)
 
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.TXT(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.NXRRSET, result)
         self.assertEqual(None, rrset)
 
         result, rrset = finder.find(isc.dns.Name("cname-ext.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.CNAME, result)
         self.assertEqual(
@@ -345,7 +396,6 @@ class DataSrcClient(unittest.TestCase):
 
         result, rrset = finder.find(isc.dns.Name("foo.wild.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.WILDCARD, result)
         self.assertEqual("foo.wild.example.com. 3600 IN A 192.0.2.255\n",
@@ -353,7 +403,6 @@ class DataSrcClient(unittest.TestCase):
 
         result, rrset = finder.find(isc.dns.Name("foo.wild.example.com"),
                                     isc.dns.RRType.TXT(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.WILDCARD_NXRRSET, result)
         self.assertEqual(None, rrset)
@@ -361,17 +410,14 @@ class DataSrcClient(unittest.TestCase):
         self.assertRaises(TypeError, finder.find,
                           "foo",
                           isc.dns.RRType.A(),
-                          None,
                           finder.FIND_DEFAULT)
         self.assertRaises(TypeError, finder.find,
                           isc.dns.Name("cname-ext.example.com"),
                           "foo",
-                          None,
                           finder.FIND_DEFAULT)
         self.assertRaises(TypeError, finder.find,
                           isc.dns.Name("cname-ext.example.com"),
                           isc.dns.RRType.A(),
-                          None,
                           "foo")
 
     def test_find_previous(self):
@@ -399,6 +445,16 @@ class DataSrcUpdater(unittest.TestCase):
         # Make a fresh copy of the writable database with all original content
         shutil.copyfile(READ_ZONE_DB_FILE, WRITE_ZONE_DB_FILE)
 
+    def test_findall(self):
+        """
+        The same test as DataSrcClient.test_findall, but on an updater
+        instead of a finder.
+        """
+        dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
+        updater = dsc.get_updater(isc.dns.Name("example.com"), False)
+
+        test_findall_common(self, updater)
+
     def test_construct(self):
         # can't construct directly
         self.assertRaises(TypeError, isc.datasrc.ZoneUpdater)
@@ -409,7 +465,6 @@ class DataSrcUpdater(unittest.TestCase):
         updater = dsc.get_updater(isc.dns.Name("example.com"), False)
         result, rrset = updater.find(isc.dns.Name("www.example.com"),
                                      isc.dns.RRType.A(),
-                                     None,
                                      ZoneFinder.FIND_DEFAULT)
         self.assertEqual(ZoneFinder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
@@ -422,17 +477,6 @@ class DataSrcUpdater(unittest.TestCase):
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
                          rrset.to_text())
 
-        result, rrset = updater.find(isc.dns.Name("www.example.com"),
-                                     isc.dns.RRType.A(), None)
-        self.assertEqual(ZoneFinder.SUCCESS, result)
-        self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
-                         rrset.to_text())
-
-        # Invalid value for 'target'
-        self.assertRaises(TypeError, updater.find,
-                          isc.dns.Name("www.example.com"),
-                          isc.dns.RRType.A(), 1)
-
     def test_update_delete_commit(self):
 
         dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
@@ -445,7 +489,6 @@ class DataSrcUpdater(unittest.TestCase):
 
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
@@ -467,14 +510,12 @@ class DataSrcUpdater(unittest.TestCase):
         # finder (since we have not committed)
         result, rrset = updater.find(isc.dns.Name("www.example.com"),
                                      isc.dns.RRType.A(),
-                                     None,
                                      finder.FIND_DEFAULT)
         self.assertEqual(finder.NXDOMAIN, result)
         self.assertEqual(None, rrset)
 
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
@@ -487,7 +528,6 @@ class DataSrcUpdater(unittest.TestCase):
         # the record should be gone now in the 'real' finder as well
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.NXDOMAIN, result)
         self.assertEqual(None, rrset)
@@ -502,7 +542,6 @@ class DataSrcUpdater(unittest.TestCase):
 
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
@@ -527,7 +566,6 @@ class DataSrcUpdater(unittest.TestCase):
         self.assertEqual("example.com.", finder.get_origin().to_text())
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
@@ -551,7 +589,6 @@ class DataSrcUpdater(unittest.TestCase):
 
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
@@ -573,7 +610,6 @@ class DataSrcUpdater(unittest.TestCase):
         # finder (since we have not committed)
         result, rrset = updater.find(isc.dns.Name("www.example.com"),
                                      isc.dns.RRType.A(),
-                                     None,
                                      finder.FIND_DEFAULT)
         self.assertEqual(finder.NXDOMAIN, result)
         self.assertEqual(None, rrset)
@@ -584,7 +620,6 @@ class DataSrcUpdater(unittest.TestCase):
         # the record should still be available in the 'real' finder as well
         result, rrset = finder.find(isc.dns.Name("www.example.com"),
                                     isc.dns.RRType.A(),
-                                    None,
                                     finder.FIND_DEFAULT)
         self.assertEqual(finder.SUCCESS, result)
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",

+ 22 - 12
src/lib/python/isc/datasrc/updater_python.cc

@@ -48,6 +48,7 @@ using namespace isc::datasrc::python;
 namespace isc_datasrc_internal {
 // See finder_python.cc
 PyObject* ZoneFinder_helper(ZoneFinder* finder, PyObject* args);
+PyObject* ZoneFinder_helper_all(ZoneFinder* finder, PyObject* args);
 }
 
 namespace {
@@ -74,7 +75,7 @@ typedef CPPPyObjectContainer<s_ZoneUpdater, ZoneUpdater> ZoneUpdaterContainer;
 
 // General creation and destruction
 int
-ZoneUpdater_init(s_ZoneUpdater* self, PyObject* args) {
+ZoneUpdater_init(PyObject*, PyObject*, PyObject*) {
     // can't be called directly
     PyErr_SetString(PyExc_TypeError,
                     "ZoneUpdater cannot be constructed directly");
@@ -83,7 +84,9 @@ ZoneUpdater_init(s_ZoneUpdater* self, PyObject* args) {
 }
 
 void
-ZoneUpdater_destroy(s_ZoneUpdater* const self) {
+ZoneUpdater_destroy(PyObject* po_self) {
+    s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
+
     // cppobj is a shared ptr, but to make sure things are not destroyed in
     // the wrong order, we reset it here.
     self->cppobj.reset();
@@ -185,6 +188,13 @@ ZoneUpdater_find(PyObject* po_self, PyObject* args) {
                                                     args));
 }
 
+PyObject*
+ZoneUpdater_find_all(PyObject* po_self, PyObject* args) {
+    s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
+    return (isc_datasrc_internal::ZoneFinder_helper_all(
+        &self->cppobj->getFinder(), args));
+}
+
 // This list contains the actual set of functions we have in
 // python. Each entry has
 // 1. Python method name
@@ -192,22 +202,22 @@ ZoneUpdater_find(PyObject* po_self, PyObject* args) {
 // 3. Argument type
 // 4. Documentation
 PyMethodDef ZoneUpdater_methods[] = {
-    { "add_rrset", reinterpret_cast<PyCFunction>(ZoneUpdater_addRRset),
+    { "add_rrset", ZoneUpdater_addRRset,
       METH_VARARGS, ZoneUpdater_addRRset_doc },
-    { "delete_rrset", reinterpret_cast<PyCFunction>(ZoneUpdater_deleteRRset),
+    { "delete_rrset", ZoneUpdater_deleteRRset,
       METH_VARARGS, ZoneUpdater_deleteRRset_doc },
-    { "commit", reinterpret_cast<PyCFunction>(ZoneUpdater_commit), METH_NOARGS,
-      ZoneUpdater_commit_doc },
+    { "commit", ZoneUpdater_commit, METH_NOARGS, ZoneUpdater_commit_doc },
     // Instead of a getFinder, we implement the finder functionality directly
     // This is because ZoneFinder is non-copyable, and we should not create
     // a ZoneFinder object from a reference only (which is what is returned
     // by getFinder(). Apart from that
-    { "get_origin", reinterpret_cast<PyCFunction>(ZoneUpdater_getOrigin),
+    { "get_origin", ZoneUpdater_getOrigin,
       METH_NOARGS, ZoneFinder_getOrigin_doc },
-    { "get_class", reinterpret_cast<PyCFunction>(ZoneUpdater_getClass),
+    { "get_class", ZoneUpdater_getClass,
       METH_NOARGS, ZoneFinder_getClass_doc },
-    { "find", reinterpret_cast<PyCFunction>(ZoneUpdater_find), METH_VARARGS,
-      ZoneFinder_find_doc },
+    { "find", ZoneUpdater_find, METH_VARARGS, ZoneFinder_find_doc },
+    { "find_all", ZoneUpdater_find_all, METH_VARARGS,
+      ZoneFinder_find_all_doc },
     { NULL, NULL, 0, NULL }
 };
 
@@ -221,7 +231,7 @@ PyTypeObject zoneupdater_type = {
     "datasrc.ZoneUpdater",
     sizeof(s_ZoneUpdater),              // tp_basicsize
     0,                                  // tp_itemsize
-    reinterpret_cast<destructor>(ZoneUpdater_destroy),// tp_dealloc
+    ZoneUpdater_destroy,                // tp_dealloc
     NULL,                               // tp_print
     NULL,                               // tp_getattr
     NULL,                               // tp_setattr
@@ -252,7 +262,7 @@ PyTypeObject zoneupdater_type = {
     NULL,                               // tp_descr_get
     NULL,                               // tp_descr_set
     0,                                  // tp_dictoffset
-    reinterpret_cast<initproc>(ZoneUpdater_init),// tp_init
+    ZoneUpdater_init,                   // tp_init
     NULL,                               // tp_alloc
     PyType_GenericNew,                  // tp_new
     NULL,                               // tp_free