|
@@ -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
|