BIND 10 master, updated. c4df99eac2910af079f19b0bdacc95d7cd88192f [master] Merge branch 'trac2438'
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Jan 21 16:23:32 UTC 2013
The branch, master has been updated
via c4df99eac2910af079f19b0bdacc95d7cd88192f (commit)
via 39a3150a0fe822b177c53379b2c93ad6f24585b9 (commit)
via 610f3ecc55290ff4c2d3453f0f90c222b00a6f38 (commit)
via 003f49d97927cc4dd85c4a631611152e7e10bd1c (commit)
via fd29a774079b86f2b62c857d13ef450f0da29a00 (commit)
via e149d57f779c6597a6ed1d497c40a9641ac6651c (commit)
via ce19e77d9f6b9715502b5636511421dc09148f86 (commit)
via 88ff44432d5fed287aa8a91d620692f4a715ae1c (commit)
via 738540ce3a7b5d06707d5b298a6223629ab66050 (commit)
via 3b37e9c152b05606bb5401c16c5b9f6d37155539 (commit)
via 81ed5b0185f7b37aafada49c52880ba87b03785f (commit)
via 37a8e164d7e3267b42ad438f49ae2505bd5b952b (commit)
via e3bde86b2e51188e37fab58965709fe2f22f9610 (commit)
via 1ba7dea264623db66cbf62fed95db34cde362cf5 (commit)
via b927f6e09523bcadf613b4e409a0039e5bfbb03c (commit)
via 0cce212fefe299518426d10812c74ce14d547782 (commit)
via 878a31b83ab5df9441804a67a2f9a16ad615ae84 (commit)
via c846c5417c22b4a3b02122860ce9a6977a6ffa44 (commit)
via ae4e532f39b85f619ff99d8feb91898d8ee741a9 (commit)
via ba27028c44e71d0fa19077209b412538be635c81 (commit)
via 9a7261d103fb09bf87b1f827a733aca3cb87d46c (commit)
via ff502308eef747bad13e1e4c763ca7fc2d820a99 (commit)
via 0e9831ebbe7ff8c719605c36f3c3292db31d28c8 (commit)
via d33133715b3f211459678061e0f2d3c40738c07f (commit)
via a6e58431e3582cc73e5c3e2aa20ee09c5da199a4 (commit)
via f2fa03f0b6156c8a64376d1524fe822e3a74cb16 (commit)
via 869ad53a069b3fe4836d818fe820160e914a017c (commit)
via e601cb8dbb5dae21aa90061d2dbf0e23223186c0 (commit)
via 76b963dc31b5df73631b3689868b991759414ba9 (commit)
via 5fa3d0e12c20cd9d07fc83c98dbd32c64eadca3e (commit)
via cd894167c8d367f7367b790d60c3dd23f740ffdf (commit)
via add399ede802585b4606e6b07d60fe831aa8ec7a (commit)
via 7773035d231a2a55664dbe04baa4744da4ada7a7 (commit)
via 8d160f47d4cd2b6bf265580331215fa9d48a9571 (commit)
via f0779391ff33e44afac4fc7911400d9b3f345446 (commit)
via a2e1d3f2d9f4bd9680932a46cf2b00c1cd2a1a64 (commit)
via 09a0594ddec459ff3d7bf1e0f0814847d5904883 (commit)
via a25a5fca02c5aca0a29113ca293581b1b48bcfdd (commit)
via 8e118d8e64ff03678c4dd4bdbc6e8e8c64737ac6 (commit)
via 13b8d3383b390dfb30ba39d9f7c69d1c0a7fd572 (commit)
via 7eaf1f34a92aef6e6e82b59e1a8200c858820b77 (commit)
via 45b538d01cc68a759ed8eb1d9e069def986e2ae9 (commit)
from 99a6e8470907e678cd8c208eeef2810b4bd0bacb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c4df99eac2910af079f19b0bdacc95d7cd88192f
Merge: 99a6e84 39a3150
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Mon Jan 21 08:23:23 2013 -0800
[master] Merge branch 'trac2438'
resolved Conflicts:
src/lib/dns/python/Makefile.am
src/lib/dns/python/rrset_collection_python.cc
src/lib/dns/python/rrset_collection_python.h
src/lib/dns/python/rrset_collection_python_inc.cc
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 5 +-
src/bin/bindctl/run_bindctl.sh.in | 5 +-
src/bin/dbutil/run_dbutil.sh.in | 5 +-
src/bin/sysinfo/run_sysinfo.sh.in | 9 +-
src/lib/dns/python/rrset_collection_python.cc | 73 +++++++---
src/lib/dns/python/rrset_collection_python.h | 10 +-
src/lib/dns/python/rrset_collection_python_inc.cc | 12 +-
src/lib/dns/rrset_collection_base.h | 2 +
src/lib/python/isc/datasrc/datasrc.cc | 17 ---
src/lib/python/isc/datasrc/tests/datasrc_test.py | 35 +++++
src/lib/python/isc/datasrc/updater_inc.cc | 36 +++++
src/lib/python/isc/datasrc/updater_python.cc | 154 +++++++++++++++++++++
src/lib/python/isc/datasrc/updater_python.h | 2 +-
tests/system/ifconfig.sh | 4 +-
14 files changed, 311 insertions(+), 58 deletions(-)
-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 9ae7a30..d8bbef5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -282,7 +282,10 @@ AC_SUBST(PYTHON_LOGMSGPKG_DIR)
# This is python package paths commonly used in python tests. See
# README of log_messages for why it's included.
-COMMON_PYTHON_PATH="\$(abs_top_builddir)/src/lib/python/isc/log_messages:\$(abs_top_srcdir)/src/lib/python:\$(abs_top_builddir)/src/lib/python"
+# lib/dns/python/.libs is necessary because __init__.py of isc package
+# automatically imports isc.datasrc, which then requires the DNS loadable
+# module. #2145 should eliminate the need for it.
+COMMON_PYTHON_PATH="\$(abs_top_builddir)/src/lib/python/isc/log_messages:\$(abs_top_srcdir)/src/lib/python:\$(abs_top_builddir)/src/lib/python:\$(abs_top_builddir)/src/lib/dns/python/.libs"
AC_SUBST(COMMON_PYTHON_PATH)
# Check for python development environments
diff --git a/src/bin/bindctl/run_bindctl.sh.in b/src/bin/bindctl/run_bindctl.sh.in
index f4cc40c..999d7ee 100755
--- a/src/bin/bindctl/run_bindctl.sh.in
+++ b/src/bin/bindctl/run_bindctl.sh.in
@@ -20,7 +20,10 @@ export PYTHON_EXEC
BINDCTL_PATH=@abs_top_builddir@/src/bin/bindctl
-PYTHONPATH=@abs_top_srcdir@/src/bin:@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/bin:@abs_top_srcdir@/src/lib/python
+# Note: lib/dns/python/.libs is necessary because __init__.py of isc package
+# automatically imports isc.datasrc, which then requires the DNS loadable
+# module. #2145 should eliminate the need for it.
+PYTHONPATH=@abs_top_srcdir@/src/bin:@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/bin:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs
export PYTHONPATH
# If necessary (rare cases), explicitly specify paths to dynamic libraries
diff --git a/src/bin/dbutil/run_dbutil.sh.in b/src/bin/dbutil/run_dbutil.sh.in
index fea7482..f0c6dbd 100755
--- a/src/bin/dbutil/run_dbutil.sh.in
+++ b/src/bin/dbutil/run_dbutil.sh.in
@@ -20,7 +20,10 @@ export PYTHON_EXEC
DBUTIL_PATH=@abs_top_builddir@/src/bin/dbutil
-PYTHONPATH=@abs_top_srcdir@/src/bin:@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/bin:@abs_top_srcdir@/src/lib/python
+# Note: lib/dns/python/.libs is necessary because __init__.py of isc package
+# automatically imports isc.datasrc, which then requires the DNS loadable
+# module. #2145 should eliminate the need for it.
+PYTHONPATH=@abs_top_srcdir@/src/bin:@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/bin:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs
export PYTHONPATH
# If necessary (rare cases), explicitly specify paths to dynamic libraries
diff --git a/src/bin/sysinfo/run_sysinfo.sh.in b/src/bin/sysinfo/run_sysinfo.sh.in
index 268b5a4..6459c2d 100755
--- a/src/bin/sysinfo/run_sysinfo.sh.in
+++ b/src/bin/sysinfo/run_sysinfo.sh.in
@@ -20,10 +20,11 @@ export PYTHON_EXEC
SYSINFO_PATH=@abs_top_builddir@/src/bin/sysinfo
-# Note: we shouldn't need log_messages except for the seemingly necessary
-# dependency due to the automatic import in the isc package (its __init__.py
-# imports some other modules)
-PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python/isc/log_messages
+# Note: we shouldn't need log_messages and lib/dns except for the seemingly
+# necessary dependency due to the automatic import in the isc package (its
+# __init__.py imports some other modules)
+# #2145 should eliminate the need for them.
+PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/dns/python/.libs
export PYTHONPATH
# Likewise, we need only because isc.log requires some loadable modules.
diff --git a/src/lib/dns/python/rrset_collection_python.cc b/src/lib/dns/python/rrset_collection_python.cc
index df313f7..cfdcdae 100644
--- a/src/lib/dns/python/rrset_collection_python.cc
+++ b/src/lib/dns/python/rrset_collection_python.cc
@@ -55,10 +55,23 @@ setTypeError(PyObject* pobj, const char* var_name, const char* type_name) {
}
}
+// RRsetCollectionBase: the base RRsetCollection class in Python.
//
-// RRsetCollectionBase
-//
-
+// Any derived RRsetCollection class is supposed to be inherited from this
+// class:
+// - If the derived class is implemented via a C++ wrapper (associated with
+// a C++ implementation of RRsetCollection), its PyTypeObject should
+// specify rrset_collection_base_type for tp_base. Its C/C++-representation
+// of objects should be compatible with s_RRsetCollection, and the wrapper
+// should set its cppobj member to point to the corresponding C++
+// RRsetCollection object. Normally it doesn't have to provide Python
+// wrapper of find(); the Python interpreter will then call find() on
+// the base class, which ensures that the corresponding C++ version of
+// find() will be used.
+// - If the derived class is implemented purely in Python, it must implement
+// find() in Python within the class. As explained in the first bullet,
+// the base class method is generally expected to be used only for C++
+// wrapper of RRsetCollection derived class.
namespace {
int
RRsetCollectionBase_init(PyObject*, PyObject*, PyObject*) {
@@ -70,8 +83,13 @@ RRsetCollectionBase_init(PyObject*, PyObject*, PyObject*) {
void
RRsetCollectionBase_destroy(PyObject* po_self) {
s_RRsetCollection* self = static_cast<s_RRsetCollection*>(po_self);
- delete self->cppobj;
- self->cppobj = NULL;
+
+ // Any C++-wrapper of derived RRsetCollection class should have its own
+ // destroy function (as it may manage cppobj in its own way);
+ // Python-only derived classes shouldn't set cppobj (which is
+ // 0-initialized). So this assertion must hold.
+ assert(self->cppobj == NULL);
+
Py_TYPE(self)->tp_free(self);
}
@@ -79,6 +97,9 @@ PyObject*
RRsetCollectionBase_find(PyObject* po_self, PyObject* args) {
s_RRsetCollection* self = static_cast<s_RRsetCollection*>(po_self);
+ // If this function is called with cppobj being NULL, this means
+ // a pure-Python derived class skips implementing its own find().
+ // This is an error (see general description above).
if (self->cppobj == NULL) {
PyErr_Format(PyExc_TypeError, "find() is not implemented in the "
"derived RRsetCollection class");
@@ -108,6 +129,9 @@ RRsetCollectionBase_find(PyObject* po_self, PyObject* args) {
}
Py_RETURN_NONE;
}
+ } catch (const RRsetCollectionError& ex) {
+ PyErr_SetString(po_RRsetCollectionError, ex.what());
+ return (NULL);
} catch (const std::exception& ex) {
const string ex_what = "Unexpected failure in "
"RRsetCollectionBase.find: " + string(ex.what());
@@ -137,6 +161,9 @@ PyMethodDef RRsetCollectionBase_methods[] = {
namespace isc {
namespace dns {
namespace python {
+// Definition of class specific exception(s)
+PyObject* po_RRsetCollectionError;
+
// This defines the complete type for reflection in python and
// parsing of PyObject* to s_RRsetCollection
// Most of the functions are not actually implemented and NULL here.
@@ -193,18 +220,27 @@ PyTypeObject rrset_collection_base_type = {
// Module Initialization, all statics are initialized here
bool
initModulePart_RRsetCollectionBase(PyObject* mod) {
- // We initialize the static description object with PyType_Ready(),
- // then add it to the module. This is not just a check! (leaving
- // this out results in segmentation faults)
- if (PyType_Ready(&rrset_collection_base_type) < 0) {
+ if (!initClass(rrset_collection_base_type, "RRsetCollectionBase", mod)) {
return (false);
}
- void* p = &rrset_collection_base_type;
- if (PyModule_AddObject(mod, "RRsetCollectionBase",
- static_cast<PyObject*>(p)) < 0) {
+
+ try {
+ po_RRsetCollectionError =
+ PyErr_NewException("dns.RRsetCollectionError",
+ po_IscException, NULL);
+ PyObjectContainer(po_RRsetCollectionError).installToModule(
+ mod, "RRsetCollectionError");
+ } catch (const std::exception& ex) {
+ const std::string ex_what =
+ "Unexpected failure in RRsetCollectionBase initialization: " +
+ std::string(ex.what());
+ PyErr_SetString(po_IscException, ex_what.c_str());
+ return (false);
+ } catch (...) {
+ PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
+ "RRsetCollectionBase initialization");
return (false);
}
- Py_INCREF(&rrset_collection_base_type);
return (true);
}
@@ -405,18 +441,9 @@ PyTypeObject rrset_collection_type = {
// Module Initialization, all statics are initialized here
bool
initModulePart_RRsetCollection(PyObject* mod) {
- // We initialize the static description object with PyType_Ready(),
- // then add it to the module. This is not just a check! (leaving
- // this out results in segmentation faults)
- if (PyType_Ready(&rrset_collection_type) < 0) {
- return (false);
- }
- void* p = &rrset_collection_type;
- if (PyModule_AddObject(mod, "RRsetCollection",
- static_cast<PyObject*>(p)) < 0) {
+ if (!initClass(rrset_collection_type, "RRsetCollection", mod)) {
return (false);
}
- Py_INCREF(&rrset_collection_type);
return (true);
}
diff --git a/src/lib/dns/python/rrset_collection_python.h b/src/lib/dns/python/rrset_collection_python.h
index 98cb84b..ea442bb 100644
--- a/src/lib/dns/python/rrset_collection_python.h
+++ b/src/lib/dns/python/rrset_collection_python.h
@@ -23,10 +23,13 @@ class RRsetCollectionBase;
namespace python {
-// The s_* Class simply covers one instantiation of the object
+// The s_* Class simply covers one instantiation of the object.
// This structure will be commonly used for all derived classes of
// RRsetCollectionBase. cppobj will point to an instance of the specific
-// derived class.
+// derived class of (C++) RRsetCollectionBase.
+//
+// A C++ wrapper for Python version of RRsetCollection should set this
+// variable, and skip the implementation of C++ wrapper of find() method.
class s_RRsetCollection : public PyObject {
public:
s_RRsetCollection() : cppobj(NULL) {}
@@ -39,6 +42,9 @@ extern PyTypeObject rrset_collection_base_type;
// Python type information for dns.RRsetCollection
extern PyTypeObject rrset_collection_type;
+// Class specific exceptions
+extern PyObject* po_RRsetCollectionError;
+
bool initModulePart_RRsetCollectionBase(PyObject* mod);
bool initModulePart_RRsetCollection(PyObject* mod);
diff --git a/src/lib/dns/python/rrset_collection_python_inc.cc b/src/lib/dns/python/rrset_collection_python_inc.cc
index 5c1e532..f6eb8a3 100644
--- a/src/lib/dns/python/rrset_collection_python_inc.cc
+++ b/src/lib/dns/python/rrset_collection_python_inc.cc
@@ -1,7 +1,7 @@
namespace {
// Modifications
// - libdns++ => isc.dns, libdatasrc => isc.datasrc
-// - note about the constructor.
+// - note about the direct construction.
// - add note about iteration
const char* const RRsetCollectionBase_doc = "\
Generic class to represent a set of RRsets.\n\
@@ -18,8 +18,8 @@ maybe class) and a way to iterate over all RRsets.\n\
See RRsetCollection for a simple isc.dns implementation. Other modules\n\
such as isc.datasrc will have another implementation.\n\
\n\
-This base class cannot be directly instantiated, so no constructor is\n\
-defined.\n\
+This base class cannot be directly instantiated. Such an attempt will\n\
+result in a TypeError exception.\n\
\n\
";
@@ -79,18 +79,18 @@ RRsetCollection(filename, origin, rrclass)\n\
origin (isc.dns.Name) The zone origin.\n\
rrclass (isc.dns.RRClass) The zone class.\n\
\n\
-RRsetCollection(input_stream, origin, rrclass)\n\
+RRsetCollection(input, origin, rrclass)\n\
\n\
Constructor.\n\
\n\
This constructor is similar to the previous one, but instead of\n\
- taking a filename to load a zone from, it takes a byte object,\n\
+ taking a filename to load a zone from, it takes a bytes object,\n\
representing the zone contents in text.\n\
The constructor throws IscException if there is an error\n\
during loading.\n\
\n\
Parameters:\n\
- input (byte) Textual representation of the zone.\n\
+ input (bytes) Textual representation of the zone.\n\
origin (isc.dns.Name) The zone origin.\n\
rrclass (isc.dns.RRClass) The zone class.\n\
\n\
diff --git a/src/lib/dns/rrset_collection_base.h b/src/lib/dns/rrset_collection_base.h
index 5ae172a..7ccf7b5 100644
--- a/src/lib/dns/rrset_collection_base.h
+++ b/src/lib/dns/rrset_collection_base.h
@@ -185,6 +185,8 @@ public:
}
};
+typedef boost::shared_ptr<RRsetCollectionBase> RRsetCollectionPtr;
+
} // end of namespace dns
} // end of namespace isc
diff --git a/src/lib/python/isc/datasrc/datasrc.cc b/src/lib/python/isc/datasrc/datasrc.cc
index cfacc64..c183af9 100644
--- a/src/lib/python/isc/datasrc/datasrc.cc
+++ b/src/lib/python/isc/datasrc/datasrc.cc
@@ -218,23 +218,6 @@ initModulePart_ZoneLoader(PyObject* mod) {
}
bool
-initModulePart_ZoneUpdater(PyObject* mod) {
- // We initialize the static description object with PyType_Ready(),
- // then add it to the module. This is not just a check! (leaving
- // this out results in segmentation faults)
- if (PyType_Ready(&zoneupdater_type) < 0) {
- return (false);
- }
- void* zip = &zoneupdater_type;
- if (PyModule_AddObject(mod, "ZoneUpdater", static_cast<PyObject*>(zip)) < 0) {
- return (false);
- }
- Py_INCREF(&zoneupdater_type);
-
- return (true);
-}
-
-bool
initModulePart_ZoneJournalReader(PyObject* mod) {
if (PyType_Ready(&journal_reader_type) < 0) {
return (false);
diff --git a/src/lib/python/isc/datasrc/tests/datasrc_test.py b/src/lib/python/isc/datasrc/tests/datasrc_test.py
index 659e7a8..36cf951 100644
--- a/src/lib/python/isc/datasrc/tests/datasrc_test.py
+++ b/src/lib/python/isc/datasrc/tests/datasrc_test.py
@@ -528,6 +528,41 @@ class DataSrcUpdater(unittest.TestCase):
self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
rrset.to_text())
+ def test_updater_rrset_collection(self):
+ dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
+ updater = dsc.get_updater(isc.dns.Name("example.com"), False)
+ updater_refs = sys.getrefcount(updater)
+
+ # Get (internally create) updater's RRset collection
+ rrsets = updater.get_rrset_collection()
+
+ # From this point we cannot make further updates
+ rrset = RRset(isc.dns.Name('www.example.com'), isc.dns.RRClass.IN(),
+ isc.dns.RRType.AAAA(), isc.dns.RRTTL(10))
+ rrset.add_rdata(isc.dns.Rdata(isc.dns.RRType.AAAA(),
+ isc.dns.RRClass.IN(), '2001:db8::1'))
+ self.assertRaises(isc.datasrc.Error, updater.add_rrset, rrset)
+
+ # Checks basic API
+ found = rrsets.find(isc.dns.Name("www.example.com"),
+ isc.dns.RRClass.IN(), isc.dns.RRType.A())
+ self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
+ found.to_text())
+ self.assertEqual(None, rrsets.find(isc.dns.Name("www.example.com"),
+ isc.dns.RRClass.IN(),
+ isc.dns.RRType.AAAA()))
+
+ # Once committed collection cannot be used any more.
+ updater.commit()
+ self.assertRaises(isc.dns.RRsetCollectionError,
+ rrsets.find, isc.dns.Name("www.example.com"),
+ isc.dns.RRClass.IN(), isc.dns.RRType.A())
+
+ # When we destroy the RRsetCollection it should release the refcount
+ # to the updater.
+ rrsets = None
+ self.assertEqual(updater_refs, sys.getrefcount(updater))
+
def test_two_modules(self):
# load two modules, and check if they don't interfere
mem_cfg = { "type": "memory", "class": "IN", "zones": [] };
diff --git a/src/lib/python/isc/datasrc/updater_inc.cc b/src/lib/python/isc/datasrc/updater_inc.cc
index 32715ec..f040f85 100644
--- a/src/lib/python/isc/datasrc/updater_inc.cc
+++ b/src/lib/python/isc/datasrc/updater_inc.cc
@@ -76,6 +76,10 @@ This method must not be called once commit() is performed. If it calls\n\
after commit() the implementation must throw a isc.datasrc.Error\n\
exception.\n\
\n\
+Implementations of ZoneUpdater may not allow adding or deleting RRsets\n\
+after get_rrset_collection() is called. In this case, implementations\n\
+throw an InvalidOperation exception.\n\
+\n\
Todo As noted above we may have to revisit the design details as we\n\
gain experiences:\n\
\n\
@@ -133,6 +137,10 @@ This method must not be called once commit() is performed. If it calls\n\
after commit() the implementation must throw a isc.datasrc.Error\n\
exception.\n\
\n\
+Implementations of ZoneUpdater may not allow adding or deleting RRsets\n\
+after get_rrset_collection() is called. In this case, implementations\n\
+throw an InvalidOperation exception.\n\
+\n\
Todo: As noted above we may have to revisit the design details as we\n\
gain experiences:\n\
\n\
@@ -178,4 +186,32 @@ Exceptions:\n\
error, or wrapper error\n\\n\
\n\
";
+
+// Modifications
+// - isc.datasrc.RRsetCollectionBase => isc.dns.RRsetCollectionBase
+// (in the Python wrapper, the former is completely invisible)
+// - remove other reference to isc.datasrc.RRsetCollectionBase
+const char* const ZoneUpdater_getRRsetCollection_doc = "\
+get_rrset_collection() -> isc.dns.RRsetCollectionBase \n\
+\n\
+Return an RRsetCollection for the updater.\n\
+\n\
+This method returns an RRsetCollection for the updater, implementing\n\
+the isc.dns.RRsetCollectionBase interface. Typically, the returned\n\
+RRsetCollection is a singleton for its ZoneUpdater. The returned\n\
+RRsetCollection object must not be used after its corresponding\n\
+ZoneUpdater has been destroyed. The returned RRsetCollection object\n\
+may be used to search RRsets from the ZoneUpdater. The actual\n\
+RRsetCollection returned has a behavior dependent on the ZoneUpdater\n\
+implementation.\n\
+\n\
+The behavior of the RRsetCollection is similar to the behavior of the\n\
+Zonefinder returned by get_finder(). Implementations of ZoneUpdater\n\
+may not allow adding or deleting RRsets after get_rrset_collection()\n\
+is called. Implementations of ZoneUpdater may disable a previously\n\
+returned RRsetCollection after commit() is called. If an\n\
+RRsetCollection is disabled, using methods such as find() and using\n\
+its iterator would cause an exception to be thrown.\n\
+\n\
+";
} // unnamed namespace
diff --git a/src/lib/python/isc/datasrc/updater_python.cc b/src/lib/python/isc/datasrc/updater_python.cc
index 97ffa00..cb727c3 100644
--- a/src/lib/python/isc/datasrc/updater_python.cc
+++ b/src/lib/python/isc/datasrc/updater_python.cc
@@ -32,6 +32,7 @@
#include <dns/python/rrset_python.h>
#include <dns/python/rrclass_python.h>
#include <dns/python/rrtype_python.h>
+#include <dns/python/rrset_collection_python.h>
#include "datasrc.h"
#include "updater_python.h"
@@ -195,6 +196,107 @@ ZoneUpdater_find_all(PyObject* po_self, PyObject* args) {
&self->cppobj->getFinder(), args));
}
+namespace {
+// Below we define Python RRsetCollection class generated by the updater.
+// It's never expected to be instantiated directly from Python code, so
+// everything is hidden here, and tp_init always fails.
+
+class s_UpdaterRRsetCollection : public s_RRsetCollection {
+public:
+ s_UpdaterRRsetCollection() : s_RRsetCollection() {}
+ PyObject* base_obj_;
+};
+
+int
+RRsetCollection_init(PyObject*, PyObject*, PyObject*) {
+ // can't be called directly; actually, the constructor shouldn't even be
+ // called, but we catch the case just in case.
+ PyErr_SetString(PyExc_TypeError,
+ "datasrc.RRsetCollection cannot be constructed directly");
+
+ return (-1);
+}
+
+void
+RRsetCollection_destroy(PyObject* po_self) {
+ s_UpdaterRRsetCollection* const self =
+ static_cast<s_UpdaterRRsetCollection*>(po_self);
+
+ // We don't own the C++ collection object; we shouldn't delete it here.
+
+ // Note: we need to check if this is NULL; it remains NULL in case of
+ // direct instantiation (which fails).
+ if (self->base_obj_ != NULL) {
+ Py_DECREF(self->base_obj_);
+ }
+ Py_TYPE(self)->tp_free(self);
+}
+
+PyTypeObject updater_rrset_collection_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "datasrc.UpdaterRRsetCollection",
+ sizeof(s_UpdaterRRsetCollection), // tp_basicsize
+ 0, // tp_itemsize
+ RRsetCollection_destroy, // tp_dealloc
+ NULL, // tp_print
+ NULL, // tp_getattr
+ NULL, // tp_setattr
+ NULL, // tp_reserved
+ NULL, // tp_repr
+ NULL, // tp_as_number
+ NULL, // tp_as_sequence
+ NULL, // tp_as_mapping
+ NULL, // tp_hash
+ NULL, // tp_call
+ NULL, // tp_str
+ NULL, // tp_getattro
+ NULL, // tp_setattro
+ NULL, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ NULL,
+ NULL, // tp_traverse
+ NULL, // tp_clear
+ NULL, // tp_richcompare
+ 0, // tp_weaklistoffset
+ NULL, // tp_iter
+ NULL, // tp_iternext
+ NULL, // tp_methods
+ NULL, // tp_members
+ NULL, // tp_getset
+ NULL, // tp_base (rrset_collection_base_type, set at run time)
+ NULL, // tp_dict
+ NULL, // tp_descr_get
+ NULL, // tp_descr_set
+ 0, // tp_dictoffset
+ RRsetCollection_init, // tp_init
+ NULL, // tp_alloc
+ PyType_GenericNew, // tp_new
+ NULL, // tp_free
+ NULL, // tp_is_gc
+ NULL, // tp_bases
+ NULL, // tp_mro
+ NULL, // tp_cache
+ NULL, // tp_subclasses
+ NULL, // tp_weaklist
+ NULL, // tp_del
+ 0 // tp_version_tag
+};
+} // unnamed namespace
+
+PyObject*
+ZoneUpdater_getRRsetCollection(PyObject* po_self, PyObject*) {
+ s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
+
+ s_UpdaterRRsetCollection* collection =
+ static_cast<s_UpdaterRRsetCollection*>(
+ PyObject_New(s_RRsetCollection, &updater_rrset_collection_type));
+ collection->cppobj = &self->cppobj->getRRsetCollection();
+ collection->base_obj_ = po_self;;
+ Py_INCREF(collection->base_obj_);
+
+ return (collection);
+}
+
// This list contains the actual set of functions we have in
// python. Each entry has
// 1. Python method name
@@ -207,6 +309,8 @@ PyMethodDef ZoneUpdater_methods[] = {
{ "delete_rrset", ZoneUpdater_deleteRRset,
METH_VARARGS, ZoneUpdater_deleteRRset_doc },
{ "commit", ZoneUpdater_commit, METH_NOARGS, ZoneUpdater_commit_doc },
+ { "get_rrset_collection", ZoneUpdater_getRRsetCollection,
+ METH_NOARGS, ZoneUpdater_getRRsetCollection_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
@@ -292,6 +396,56 @@ createZoneUpdaterObject(isc::datasrc::ZoneUpdaterPtr source,
return (py_zu);
}
+bool
+initModulePart_ZoneUpdater(PyObject* mod) {
+ // We initialize the static description object with PyType_Ready(),
+ // then add it to the module. This is not just a check! (leaving
+ // this out results in segmentation faults)
+ if (PyType_Ready(&zoneupdater_type) < 0) {
+ return (false);
+ }
+ void* zip = &zoneupdater_type;
+ if (PyModule_AddObject(mod, "ZoneUpdater",
+ static_cast<PyObject*>(zip)) < 0)
+ {
+ return (false);
+ }
+ Py_INCREF(&zoneupdater_type);
+
+ // get_rrset_collection() needs the base class type information. Since
+ // it's defined in a separate loadable module, we retrieve its C object
+ // via the Python interpreter. Directly referring to
+ // isc::dns::python::rrset_collection_base_type might work depending on
+ // the runtime environment (and in fact it does for some), but that would
+ // be less portable.
+ try {
+ if (updater_rrset_collection_type.tp_base == NULL) {
+ PyObjectContainer dns_module(PyImport_ImportModule("isc.dns"));
+ PyObjectContainer dns_dict(PyModule_GetDict(dns_module.get()));
+ // GetDict doesn't acquire a reference, so we need to get it to
+ // meet the container's requirement.
+ Py_INCREF(dns_dict.get());
+ PyObjectContainer base(
+ PyDict_GetItemString(dns_dict.get(), "RRsetCollectionBase"));
+ PyTypeObject* pt_rrset_collection_base =
+ static_cast<PyTypeObject*>(static_cast<void*>(base.get()));
+ updater_rrset_collection_type.tp_base = pt_rrset_collection_base;
+ if (PyType_Ready(&updater_rrset_collection_type) < 0) {
+ isc_throw(Unexpected, "failed to import isc.dns module");
+ }
+
+ // Make sure the base type won't suddenly disappear. Note that we
+ // are effectively leaking it; it's intentional.
+ Py_INCREF(base.get());
+ }
+ } catch (...) {
+ PyErr_SetString(PyExc_SystemError,
+ "Unexpected failure in ZoneUpdater initialization");
+ return (false);
+ }
+
+ return (true);
+}
} // namespace python
} // namespace datasrc
} // namespace isc
diff --git a/src/lib/python/isc/datasrc/updater_python.h b/src/lib/python/isc/datasrc/updater_python.h
index b09c524..b7f1452 100644
--- a/src/lib/python/isc/datasrc/updater_python.h
+++ b/src/lib/python/isc/datasrc/updater_python.h
@@ -36,7 +36,7 @@ extern PyTypeObject zoneupdater_type;
PyObject* createZoneUpdaterObject(isc::datasrc::ZoneUpdaterPtr source,
PyObject* base_obj = NULL);
-
+bool initModulePart_ZoneUpdater(PyObject* mod);
} // namespace python
} // namespace datasrc
} // namespace isc
diff --git a/tests/system/ifconfig.sh b/tests/system/ifconfig.sh
index c0c365a..7c695e2 100755
--- a/tests/system/ifconfig.sh
+++ b/tests/system/ifconfig.sh
@@ -63,7 +63,7 @@ esac
case "$1" in
start|up)
- for ns in 1 2 3 4 5 6 7
+ for ns in 1 2 3 4 5 6 7 8
do
if test -n "$base"
then
@@ -145,7 +145,7 @@ case "$1" in
;;
stop|down)
- for ns in 7 6 5 4 3 2 1
+ for ns in 8 7 6 5 4 3 2 1
do
if test -n "$base"
then
More information about the bind10-changes
mailing list