updater_python.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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/zone.h>
  26. #include <dns/python/name_python.h>
  27. #include <dns/python/rrset_python.h>
  28. #include <dns/python/rrclass_python.h>
  29. #include <dns/python/rrtype_python.h>
  30. #include "datasrc.h"
  31. #include "updater_python.h"
  32. #include "updater_inc.cc"
  33. #include "finder_inc.cc"
  34. using namespace std;
  35. using namespace isc::util::python;
  36. using namespace isc::dns::python;
  37. using namespace isc::datasrc;
  38. using namespace isc::datasrc::python;
  39. namespace isc_datasrc_internal {
  40. // See finder_python.cc
  41. PyObject* ZoneFinder_helper(ZoneFinder* finder, PyObject* args);
  42. PyObject* ZoneFinder_helper_all(ZoneFinder* finder, PyObject* args);
  43. }
  44. namespace {
  45. // The s_* Class simply covers one instantiation of the object
  46. class s_ZoneUpdater : public PyObject {
  47. public:
  48. s_ZoneUpdater() : cppobj(ZoneUpdaterPtr()), base_obj(NULL) {};
  49. ZoneUpdaterPtr cppobj;
  50. // This is a reference to a base object; if the object of this class
  51. // depends on another object to be in scope during its lifetime,
  52. // we use INCREF the base object upon creation, and DECREF it at
  53. // the end of the destructor
  54. // This is an optional argument to createXXX(). If NULL, it is ignored.
  55. PyObject* base_obj;
  56. };
  57. // Shortcut type which would be convenient for adding class variables safely.
  58. typedef CPPPyObjectContainer<s_ZoneUpdater, ZoneUpdater> ZoneUpdaterContainer;
  59. //
  60. // We declare the functions here, the definitions are below
  61. // the type definition of the object, since both can use the other
  62. //
  63. // General creation and destruction
  64. int
  65. ZoneUpdater_init(s_ZoneUpdater* self, PyObject* args) {
  66. // can't be called directly
  67. PyErr_SetString(PyExc_TypeError,
  68. "ZoneUpdater cannot be constructed directly");
  69. return (-1);
  70. }
  71. void
  72. ZoneUpdater_destroy(s_ZoneUpdater* const self) {
  73. // cppobj is a shared ptr, but to make sure things are not destroyed in
  74. // the wrong order, we reset it here.
  75. self->cppobj.reset();
  76. if (self->base_obj != NULL) {
  77. Py_DECREF(self->base_obj);
  78. }
  79. Py_TYPE(self)->tp_free(self);
  80. }
  81. PyObject*
  82. ZoneUpdater_addRRset(PyObject* po_self, PyObject* args) {
  83. s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
  84. PyObject* rrset_obj;
  85. if (PyArg_ParseTuple(args, "O!", &rrset_type, &rrset_obj)) {
  86. try {
  87. self->cppobj->addRRset(PyRRset_ToRRset(rrset_obj));
  88. Py_RETURN_NONE;
  89. } catch (const DataSourceError& dse) {
  90. PyErr_SetString(getDataSourceException("Error"), dse.what());
  91. return (NULL);
  92. } catch (const std::exception& exc) {
  93. PyErr_SetString(getDataSourceException("Error"), exc.what());
  94. return (NULL);
  95. }
  96. } else {
  97. return (NULL);
  98. }
  99. }
  100. PyObject*
  101. ZoneUpdater_deleteRRset(PyObject* po_self, PyObject* args) {
  102. s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
  103. PyObject* rrset_obj;
  104. if (PyArg_ParseTuple(args, "O!", &rrset_type, &rrset_obj)) {
  105. try {
  106. self->cppobj->deleteRRset(PyRRset_ToRRset(rrset_obj));
  107. Py_RETURN_NONE;
  108. } catch (const DataSourceError& dse) {
  109. PyErr_SetString(getDataSourceException("Error"), dse.what());
  110. return (NULL);
  111. } catch (const std::exception& exc) {
  112. PyErr_SetString(getDataSourceException("Error"), exc.what());
  113. return (NULL);
  114. }
  115. } else {
  116. return (NULL);
  117. }
  118. }
  119. PyObject*
  120. ZoneUpdater_commit(PyObject* po_self, PyObject*) {
  121. s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
  122. try {
  123. self->cppobj->commit();
  124. Py_RETURN_NONE;
  125. } catch (const DataSourceError& dse) {
  126. PyErr_SetString(getDataSourceException("Error"), dse.what());
  127. return (NULL);
  128. } catch (const std::exception& exc) {
  129. PyErr_SetString(getDataSourceException("Error"), exc.what());
  130. return (NULL);
  131. }
  132. }
  133. PyObject*
  134. ZoneUpdater_getClass(PyObject* po_self, PyObject*) {
  135. s_ZoneUpdater* self = static_cast<s_ZoneUpdater*>(po_self);
  136. try {
  137. return (createRRClassObject(self->cppobj->getFinder().getClass()));
  138. } catch (const std::exception& exc) {
  139. PyErr_SetString(getDataSourceException("Error"), exc.what());
  140. return (NULL);
  141. } catch (...) {
  142. PyErr_SetString(getDataSourceException("Error"),
  143. "Unexpected exception");
  144. return (NULL);
  145. }
  146. }
  147. PyObject*
  148. ZoneUpdater_getOrigin(PyObject* po_self, PyObject*) {
  149. s_ZoneUpdater* self = static_cast<s_ZoneUpdater*>(po_self);
  150. try {
  151. return (createNameObject(self->cppobj->getFinder().getOrigin()));
  152. } catch (const std::exception& exc) {
  153. PyErr_SetString(getDataSourceException("Error"), exc.what());
  154. return (NULL);
  155. } catch (...) {
  156. PyErr_SetString(getDataSourceException("Error"),
  157. "Unexpected exception");
  158. return (NULL);
  159. }
  160. }
  161. PyObject*
  162. ZoneUpdater_find(PyObject* po_self, PyObject* args) {
  163. s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
  164. return (isc_datasrc_internal::ZoneFinder_helper(&self->cppobj->getFinder(),
  165. args));
  166. }
  167. PyObject*
  168. ZoneUpdater_find_all(PyObject* po_self, PyObject* args) {
  169. s_ZoneUpdater* const self = static_cast<s_ZoneUpdater*>(po_self);
  170. return (isc_datasrc_internal::ZoneFinder_helper_all(
  171. &self->cppobj->getFinder(), args));
  172. }
  173. // This list contains the actual set of functions we have in
  174. // python. Each entry has
  175. // 1. Python method name
  176. // 2. Our static function here
  177. // 3. Argument type
  178. // 4. Documentation
  179. PyMethodDef ZoneUpdater_methods[] = {
  180. { "add_rrset", reinterpret_cast<PyCFunction>(ZoneUpdater_addRRset),
  181. METH_VARARGS, ZoneUpdater_addRRset_doc },
  182. { "delete_rrset", reinterpret_cast<PyCFunction>(ZoneUpdater_deleteRRset),
  183. METH_VARARGS, ZoneUpdater_deleteRRset_doc },
  184. { "commit", reinterpret_cast<PyCFunction>(ZoneUpdater_commit), METH_NOARGS,
  185. ZoneUpdater_commit_doc },
  186. // Instead of a getFinder, we implement the finder functionality directly
  187. // This is because ZoneFinder is non-copyable, and we should not create
  188. // a ZoneFinder object from a reference only (which is what is returned
  189. // by getFinder(). Apart from that
  190. { "get_origin", reinterpret_cast<PyCFunction>(ZoneUpdater_getOrigin),
  191. METH_NOARGS, ZoneFinder_getOrigin_doc },
  192. { "get_class", reinterpret_cast<PyCFunction>(ZoneUpdater_getClass),
  193. METH_NOARGS, ZoneFinder_getClass_doc },
  194. { "find", reinterpret_cast<PyCFunction>(ZoneUpdater_find), METH_VARARGS,
  195. ZoneFinder_find_doc },
  196. { "find_all", ZoneUpdater_find_all, METH_VARARGS, "TODO" },
  197. { NULL, NULL, 0, NULL }
  198. };
  199. } // end of unnamed namespace
  200. namespace isc {
  201. namespace datasrc {
  202. namespace python {
  203. PyTypeObject zoneupdater_type = {
  204. PyVarObject_HEAD_INIT(NULL, 0)
  205. "datasrc.ZoneUpdater",
  206. sizeof(s_ZoneUpdater), // tp_basicsize
  207. 0, // tp_itemsize
  208. reinterpret_cast<destructor>(ZoneUpdater_destroy),// tp_dealloc
  209. NULL, // tp_print
  210. NULL, // tp_getattr
  211. NULL, // tp_setattr
  212. NULL, // tp_reserved
  213. NULL, // tp_repr
  214. NULL, // tp_as_number
  215. NULL, // tp_as_sequence
  216. NULL, // tp_as_mapping
  217. NULL, // tp_hash
  218. NULL, // tp_call
  219. NULL, // tp_str
  220. NULL, // tp_getattro
  221. NULL, // tp_setattro
  222. NULL, // tp_as_buffer
  223. Py_TPFLAGS_DEFAULT, // tp_flags
  224. ZoneUpdater_doc,
  225. NULL, // tp_traverse
  226. NULL, // tp_clear
  227. NULL, // tp_richcompare
  228. 0, // tp_weaklistoffset
  229. NULL, // tp_iter
  230. NULL, // tp_iternext
  231. ZoneUpdater_methods, // tp_methods
  232. NULL, // tp_members
  233. NULL, // tp_getset
  234. NULL, // tp_base
  235. NULL, // tp_dict
  236. NULL, // tp_descr_get
  237. NULL, // tp_descr_set
  238. 0, // tp_dictoffset
  239. reinterpret_cast<initproc>(ZoneUpdater_init),// tp_init
  240. NULL, // tp_alloc
  241. PyType_GenericNew, // tp_new
  242. NULL, // tp_free
  243. NULL, // tp_is_gc
  244. NULL, // tp_bases
  245. NULL, // tp_mro
  246. NULL, // tp_cache
  247. NULL, // tp_subclasses
  248. NULL, // tp_weaklist
  249. NULL, // tp_del
  250. 0 // tp_version_tag
  251. };
  252. PyObject*
  253. createZoneUpdaterObject(isc::datasrc::ZoneUpdaterPtr source,
  254. PyObject* base_obj)
  255. {
  256. s_ZoneUpdater* py_zu = static_cast<s_ZoneUpdater*>(
  257. zoneupdater_type.tp_alloc(&zoneupdater_type, 0));
  258. if (py_zu != NULL) {
  259. py_zu->cppobj = source;
  260. py_zu->base_obj = base_obj;
  261. if (base_obj != NULL) {
  262. Py_INCREF(base_obj);
  263. }
  264. }
  265. return (py_zu);
  266. }
  267. } // namespace python
  268. } // namespace datasrc
  269. } // namespace isc