zonewriter_python.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Copyright (C) 2013 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 <string>
  21. #include <stdexcept>
  22. #include <util/python/pycppwrapper_util.h>
  23. #include <datasrc/memory/zone_writer.h>
  24. #include "zonewriter_python.h"
  25. #include "datasrc.h"
  26. #include "zonewriter_inc.cc"
  27. using namespace std;
  28. using namespace isc::util::python;
  29. using namespace isc::datasrc;
  30. using namespace isc::datasrc::memory;
  31. using namespace isc::datasrc::python;
  32. using namespace isc::datasrc::memory::python;
  33. //
  34. // ZoneWriter
  35. //
  36. namespace {
  37. // The s_* Class simply covers one instantiation of the object
  38. class s_ZoneWriter : public PyObject {
  39. public:
  40. s_ZoneWriter() :
  41. cppobj(ConfigurableClientList::ZoneWriterPtr()),
  42. base_obj(NULL)
  43. {}
  44. ConfigurableClientList::ZoneWriterPtr cppobj;
  45. // This is a reference to a base object; if the object of this class
  46. // depends on another object to be in scope during its lifetime,
  47. // we use INCREF the base object upon creation, and DECREF it at
  48. // the end of the destructor
  49. // This is an optional argument to createXXX(). If NULL, it is ignored.
  50. PyObject* base_obj;
  51. };
  52. int
  53. ZoneWriter_init(PyObject*, PyObject*, PyObject*) {
  54. // can't be called directly
  55. PyErr_SetString(PyExc_TypeError,
  56. "ZoneWriter cannot be constructed directly");
  57. return (-1);
  58. }
  59. void
  60. ZoneWriter_destroy(PyObject* po_self) {
  61. s_ZoneWriter* self = static_cast<s_ZoneWriter*>(po_self);
  62. // cppobj is a shared ptr, but to make sure things are not destroyed in
  63. // the wrong order, we reset it here.
  64. self->cppobj.reset();
  65. if (self->base_obj != NULL) {
  66. Py_DECREF(self->base_obj);
  67. }
  68. Py_TYPE(self)->tp_free(self);
  69. }
  70. PyObject*
  71. ZoneWriter_load(PyObject* po_self, PyObject*) {
  72. s_ZoneWriter* self = static_cast<s_ZoneWriter*>(po_self);
  73. try {
  74. std::string error_msg;
  75. self->cppobj->load(&error_msg);
  76. if (!error_msg.empty()) {
  77. return (Py_BuildValue("s", error_msg.c_str()));
  78. }
  79. } catch (const std::exception& exc) {
  80. PyErr_SetString(getDataSourceException("Error"), exc.what());
  81. return (NULL);
  82. } catch (...) {
  83. PyErr_SetString(getDataSourceException("Error"),
  84. "Unknown C++ exception");
  85. return (NULL);
  86. }
  87. Py_RETURN_NONE;
  88. }
  89. PyObject*
  90. ZoneWriter_install(PyObject* po_self, PyObject*) {
  91. s_ZoneWriter* self = static_cast<s_ZoneWriter*>(po_self);
  92. try {
  93. self->cppobj->install();
  94. } catch (const std::exception& exc) {
  95. PyErr_SetString(getDataSourceException("Error"), exc.what());
  96. return (NULL);
  97. } catch (...) {
  98. PyErr_SetString(getDataSourceException("Error"),
  99. "Unknown C++ exception");
  100. return (NULL);
  101. }
  102. Py_RETURN_NONE;
  103. }
  104. PyObject*
  105. ZoneWriter_cleanup(PyObject* po_self, PyObject*) {
  106. s_ZoneWriter* self = static_cast<s_ZoneWriter*>(po_self);
  107. try {
  108. self->cppobj->cleanup();
  109. } catch (const std::exception& exc) {
  110. PyErr_SetString(getDataSourceException("Error"), exc.what());
  111. return (NULL);
  112. } catch (...) {
  113. PyErr_SetString(getDataSourceException("Error"),
  114. "Unknown C++ exception");
  115. return (NULL);
  116. }
  117. Py_RETURN_NONE;
  118. }
  119. // This list contains the actual set of functions we have in
  120. // python. Each entry has
  121. // 1. Python method name
  122. // 2. Our static function here
  123. // 3. Argument type
  124. // 4. Documentation
  125. PyMethodDef ZoneWriter_methods[] = {
  126. { "load", ZoneWriter_load, METH_NOARGS,
  127. ZoneWriter_load_doc },
  128. { "install", ZoneWriter_install, METH_NOARGS,
  129. ZoneWriter_install_doc },
  130. { "cleanup", ZoneWriter_cleanup, METH_NOARGS,
  131. ZoneWriter_cleanup_doc },
  132. { NULL, NULL, 0, NULL }
  133. };
  134. } // end of unnamed namespace
  135. namespace isc {
  136. namespace datasrc {
  137. namespace memory {
  138. namespace python {
  139. // This defines the complete type for reflection in python and
  140. // parsing of PyObject* to s_ZoneWriter
  141. // Most of the functions are not actually implemented and NULL here.
  142. PyTypeObject zonewriter_type = {
  143. PyVarObject_HEAD_INIT(NULL, 0)
  144. "datasrc.ZoneWriter",
  145. sizeof(s_ZoneWriter), // tp_basicsize
  146. 0, // tp_itemsize
  147. ZoneWriter_destroy, // tp_dealloc
  148. NULL, // tp_print
  149. NULL, // tp_getattr
  150. NULL, // tp_setattr
  151. NULL, // tp_reserved
  152. NULL, // tp_repr
  153. NULL, // tp_as_number
  154. NULL, // tp_as_sequence
  155. NULL, // tp_as_mapping
  156. NULL, // tp_hash
  157. NULL, // tp_call
  158. NULL, // tp_str
  159. NULL, // tp_getattro
  160. NULL, // tp_setattro
  161. NULL, // tp_as_buffer
  162. Py_TPFLAGS_DEFAULT, // tp_flags
  163. ZoneWriter_doc,
  164. NULL, // tp_traverse
  165. NULL, // tp_clear
  166. NULL, // tp_richcompare
  167. 0, // tp_weaklistoffset
  168. NULL, // tp_iter
  169. NULL, // tp_iternext
  170. ZoneWriter_methods, // tp_methods
  171. NULL, // tp_members
  172. NULL, // tp_getset
  173. NULL, // tp_base
  174. NULL, // tp_dict
  175. NULL, // tp_descr_get
  176. NULL, // tp_descr_set
  177. 0, // tp_dictoffset
  178. ZoneWriter_init, // tp_init
  179. NULL, // tp_alloc
  180. PyType_GenericNew, // tp_new
  181. NULL, // tp_free
  182. NULL, // tp_is_gc
  183. NULL, // tp_bases
  184. NULL, // tp_mro
  185. NULL, // tp_cache
  186. NULL, // tp_subclasses
  187. NULL, // tp_weaklist
  188. NULL, // tp_del
  189. 0 // tp_version_tag
  190. };
  191. // Module Initialization, all statics are initialized here
  192. bool
  193. initModulePart_ZoneWriter(PyObject* mod) {
  194. // We initialize the static description object with PyType_Ready(),
  195. // then add it to the module. This is not just a check! (leaving
  196. // this out results in segmentation faults)
  197. if (PyType_Ready(&zonewriter_type) < 0) {
  198. return (false);
  199. }
  200. void* p = &zonewriter_type;
  201. if (PyModule_AddObject(mod, "ZoneWriter", static_cast<PyObject*>(p)) < 0) {
  202. return (false);
  203. }
  204. Py_INCREF(&zonewriter_type);
  205. return (true);
  206. }
  207. PyObject*
  208. createZoneWriterObject(ConfigurableClientList::ZoneWriterPtr source,
  209. PyObject* base_obj)
  210. {
  211. s_ZoneWriter* py_zf = static_cast<s_ZoneWriter*>(
  212. zonewriter_type.tp_alloc(&zonewriter_type, 0));
  213. if (py_zf != NULL) {
  214. py_zf->cppobj = source;
  215. py_zf->base_obj = base_obj;
  216. if (base_obj != NULL) {
  217. Py_INCREF(base_obj);
  218. }
  219. }
  220. return (py_zf);
  221. }
  222. } // namespace python
  223. } // namespace memory
  224. } // namespace datasrc
  225. } // namespace isc