finder_python.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // Enable this if you use s# variants with PyArg_ParseTuple(), see
  15. // http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
  16. //#define PY_SSIZE_T_CLEAN
  17. // Python.h needs to be placed at the head of the program file, see:
  18. // http://docs.python.org/py3k/extending/extending.html#a-simple-example
  19. #include <Python.h>
  20. #include <util/python/pycppwrapper_util.h>
  21. #include <datasrc/client.h>
  22. #include <datasrc/database.h>
  23. #include <datasrc/data_source.h>
  24. #include <datasrc/sqlite3_accessor.h>
  25. #include <datasrc/iterator.h>
  26. #include <datasrc/zone.h>
  27. #include <dns/python/name_python.h>
  28. #include <dns/python/rrset_python.h>
  29. #include <dns/python/rrclass_python.h>
  30. #include <dns/python/rrtype_python.h>
  31. #include <dns/python/pydnspp_common.h>
  32. #include "datasrc.h"
  33. #include "finder_python.h"
  34. #include "finder_inc.cc"
  35. using namespace std;
  36. using namespace isc::util::python;
  37. using namespace isc::dns::python;
  38. using namespace isc::datasrc;
  39. using namespace isc::datasrc::python;
  40. namespace isc_datasrc_internal {
  41. // This is the shared code for the find() call in the finder and the updater
  42. // Is is intentionally not available through any header, nor at our standard
  43. // namespace, as it is not supposed to be called anywhere but from finder and
  44. // updater
  45. PyObject* ZoneFinder_helper(ZoneFinder* finder, PyObject* args) {
  46. if (finder == NULL) {
  47. PyErr_SetString(getDataSourceException("Error"),
  48. "Internal error in find() wrapper; "
  49. "finder object NULL");
  50. return (NULL);
  51. }
  52. PyObject* name;
  53. PyObject* rrtype;
  54. unsigned int options_int = ZoneFinder::FIND_DEFAULT;
  55. if (PyArg_ParseTuple(args, "O!O!|I", &name_type, &name,
  56. &rrtype_type, &rrtype,
  57. &options_int)) {
  58. try {
  59. ZoneFinder::FindOptions options =
  60. static_cast<ZoneFinder::FindOptions>(options_int);
  61. const ZoneFinder::FindResult find_result(
  62. finder->find(PyName_ToName(name), PyRRType_ToRRType(rrtype),
  63. options));
  64. const ZoneFinder::Result r = find_result.code;
  65. isc::dns::ConstRRsetPtr rrsp = find_result.rrset;
  66. if (rrsp) {
  67. // Use N instead of O so the refcount isn't increased twice
  68. return (Py_BuildValue("IN", r, createRRsetObject(*rrsp)));
  69. } else {
  70. return (Py_BuildValue("IO", r, Py_None));
  71. }
  72. } catch (const DataSourceError& dse) {
  73. PyErr_SetString(getDataSourceException("Error"), dse.what());
  74. return (NULL);
  75. } catch (const std::exception& exc) {
  76. PyErr_SetString(getDataSourceException("Error"), exc.what());
  77. return (NULL);
  78. } catch (...) {
  79. PyErr_SetString(getDataSourceException("Error"),
  80. "Unexpected exception");
  81. return (NULL);
  82. }
  83. } else {
  84. return (NULL);
  85. }
  86. return Py_BuildValue("I", 1);
  87. }
  88. } // end namespace internal
  89. namespace {
  90. // The s_* Class simply covers one instantiation of the object
  91. class s_ZoneFinder : public PyObject {
  92. public:
  93. s_ZoneFinder() : cppobj(ZoneFinderPtr()), base_obj(NULL) {};
  94. ZoneFinderPtr cppobj;
  95. // This is a reference to a base object; if the object of this class
  96. // depends on another object to be in scope during its lifetime,
  97. // we use INCREF the base object upon creation, and DECREF it at
  98. // the end of the destructor
  99. // This is an optional argument to createXXX(). If NULL, it is ignored.
  100. PyObject* base_obj;
  101. };
  102. // Shortcut type which would be convenient for adding class variables safely.
  103. typedef CPPPyObjectContainer<s_ZoneFinder, ZoneFinder> ZoneFinderContainer;
  104. // General creation and destruction
  105. int
  106. ZoneFinder_init(s_ZoneFinder* self, PyObject* args) {
  107. // can't be called directly
  108. PyErr_SetString(PyExc_TypeError,
  109. "ZoneFinder cannot be constructed directly");
  110. return (-1);
  111. }
  112. void
  113. ZoneFinder_destroy(s_ZoneFinder* const self) {
  114. // cppobj is a shared ptr, but to make sure things are not destroyed in
  115. // the wrong order, we reset it here.
  116. self->cppobj.reset();
  117. if (self->base_obj != NULL) {
  118. Py_DECREF(self->base_obj);
  119. }
  120. Py_TYPE(self)->tp_free(self);
  121. }
  122. PyObject*
  123. ZoneFinder_getClass(PyObject* po_self, PyObject*) {
  124. s_ZoneFinder* self = static_cast<s_ZoneFinder*>(po_self);
  125. try {
  126. return (createRRClassObject(self->cppobj->getClass()));
  127. } catch (const std::exception& exc) {
  128. PyErr_SetString(getDataSourceException("Error"), exc.what());
  129. return (NULL);
  130. }
  131. }
  132. PyObject*
  133. ZoneFinder_getOrigin(PyObject* po_self, PyObject*) {
  134. s_ZoneFinder* self = static_cast<s_ZoneFinder*>(po_self);
  135. try {
  136. return (createNameObject(self->cppobj->getOrigin()));
  137. } catch (const std::exception& exc) {
  138. PyErr_SetString(getDataSourceException("Error"), exc.what());
  139. return (NULL);
  140. } catch (...) {
  141. PyErr_SetString(getDataSourceException("Error"),
  142. "Unexpected exception");
  143. return (NULL);
  144. }
  145. }
  146. PyObject*
  147. ZoneFinder_find(PyObject* po_self, PyObject* args) {
  148. s_ZoneFinder* const self = static_cast<s_ZoneFinder*>(po_self);
  149. return (isc_datasrc_internal::ZoneFinder_helper(self->cppobj.get(), args));
  150. }
  151. PyObject*
  152. ZoneFinder_findPreviousName(PyObject* po_self, PyObject* args) {
  153. s_ZoneFinder* const self = static_cast<s_ZoneFinder*>(po_self);
  154. PyObject* name_obj;
  155. if (PyArg_ParseTuple(args, "O!", &name_type, &name_obj)) {
  156. try {
  157. return (createNameObject(
  158. self->cppobj->findPreviousName(PyName_ToName(name_obj))));
  159. } catch (const isc::NotImplemented& nie) {
  160. PyErr_SetString(getDataSourceException("NotImplemented"),
  161. nie.what());
  162. return (NULL);
  163. } catch (const std::exception& exc) {
  164. PyErr_SetString(getDataSourceException("Error"), exc.what());
  165. return (NULL);
  166. } catch (...) {
  167. PyErr_SetString(getDataSourceException("Error"),
  168. "Unexpected exception");
  169. return (NULL);
  170. }
  171. } else {
  172. return (NULL);
  173. }
  174. }
  175. // This list contains the actual set of functions we have in
  176. // python. Each entry has
  177. // 1. Python method name
  178. // 2. Our static function here
  179. // 3. Argument type
  180. // 4. Documentation
  181. PyMethodDef ZoneFinder_methods[] = {
  182. { "get_origin", ZoneFinder_getOrigin, METH_NOARGS,
  183. ZoneFinder_getOrigin_doc },
  184. { "get_class", ZoneFinder_getClass, METH_NOARGS, ZoneFinder_getClass_doc },
  185. { "find", ZoneFinder_find, METH_VARARGS, ZoneFinder_find_doc },
  186. { "find_previous_name", ZoneFinder_findPreviousName, METH_VARARGS,
  187. ZoneFinder_find_previous_name_doc },
  188. { NULL, NULL, 0, NULL }
  189. };
  190. } // end of unnamed namespace
  191. namespace isc {
  192. namespace datasrc {
  193. namespace python {
  194. PyTypeObject zonefinder_type = {
  195. PyVarObject_HEAD_INIT(NULL, 0)
  196. "datasrc.ZoneFinder",
  197. sizeof(s_ZoneFinder), // tp_basicsize
  198. 0, // tp_itemsize
  199. reinterpret_cast<destructor>(ZoneFinder_destroy),// tp_dealloc
  200. NULL, // tp_print
  201. NULL, // tp_getattr
  202. NULL, // tp_setattr
  203. NULL, // tp_reserved
  204. NULL, // tp_repr
  205. NULL, // tp_as_number
  206. NULL, // tp_as_sequence
  207. NULL, // tp_as_mapping
  208. NULL, // tp_hash
  209. NULL, // tp_call
  210. NULL, // tp_str
  211. NULL, // tp_getattro
  212. NULL, // tp_setattro
  213. NULL, // tp_as_buffer
  214. Py_TPFLAGS_DEFAULT, // tp_flags
  215. ZoneFinder_doc,
  216. NULL, // tp_traverse
  217. NULL, // tp_clear
  218. NULL, // tp_richcompare
  219. 0, // tp_weaklistoffset
  220. NULL, // tp_iter
  221. NULL, // tp_iternext
  222. ZoneFinder_methods, // tp_methods
  223. NULL, // tp_members
  224. NULL, // tp_getset
  225. NULL, // tp_base
  226. NULL, // tp_dict
  227. NULL, // tp_descr_get
  228. NULL, // tp_descr_set
  229. 0, // tp_dictoffset
  230. reinterpret_cast<initproc>(ZoneFinder_init),// tp_init
  231. NULL, // tp_alloc
  232. PyType_GenericNew, // tp_new
  233. NULL, // tp_free
  234. NULL, // tp_is_gc
  235. NULL, // tp_bases
  236. NULL, // tp_mro
  237. NULL, // tp_cache
  238. NULL, // tp_subclasses
  239. NULL, // tp_weaklist
  240. NULL, // tp_del
  241. 0 // tp_version_tag
  242. };
  243. PyObject*
  244. createZoneFinderObject(isc::datasrc::ZoneFinderPtr source, PyObject* base_obj) {
  245. s_ZoneFinder* py_zf = static_cast<s_ZoneFinder*>(
  246. zonefinder_type.tp_alloc(&zonefinder_type, 0));
  247. if (py_zf != NULL) {
  248. py_zf->cppobj = source;
  249. py_zf->base_obj = base_obj;
  250. if (base_obj != NULL) {
  251. Py_INCREF(base_obj);
  252. }
  253. }
  254. return (py_zf);
  255. }
  256. } // namespace python
  257. } // namespace datasrc
  258. } // namespace isc