configurableclientlist_python.cc 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. // Copyright (C) 2012 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 <dns/python/rrclass_python.h>
  24. #include <dns/python/name_python.h>
  25. #include <datasrc/client_list.h>
  26. #include "configurableclientlist_python.h"
  27. #include "datasrc.h"
  28. #include "configurableclientlist_inc.cc"
  29. #include "finder_python.h"
  30. #include "client_python.h"
  31. using namespace std;
  32. using namespace isc::util::python;
  33. using namespace isc::datasrc;
  34. using namespace isc::datasrc::python;
  35. //
  36. // ConfigurableClientList
  37. //
  38. // Trivial constructor.
  39. s_ConfigurableClientList::s_ConfigurableClientList() : cppobj(NULL) {
  40. }
  41. namespace {
  42. int
  43. ConfigurableClientList_init(PyObject* po_self, PyObject* args, PyObject*) {
  44. s_ConfigurableClientList* self =
  45. static_cast<s_ConfigurableClientList*>(po_self);
  46. try {
  47. const PyObject* rrclass;
  48. if (PyArg_ParseTuple(args, "O!", &isc::dns::python::rrclass_type,
  49. &rrclass)) {
  50. self->cppobj =
  51. new ConfigurableClientList(isc::dns::python::
  52. PyRRClass_ToRRClass(rrclass));
  53. return (0);
  54. }
  55. } catch (const exception& ex) {
  56. const string ex_what = "Failed to construct ConfigurableClientList object: " +
  57. string(ex.what());
  58. PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
  59. return (-1);
  60. } catch (...) {
  61. PyErr_SetString(PyExc_SystemError, "Unexpected C++ exception");
  62. return (-1);
  63. }
  64. return (-1);
  65. }
  66. void
  67. ConfigurableClientList_destroy(PyObject* po_self) {
  68. s_ConfigurableClientList* self =
  69. static_cast<s_ConfigurableClientList*>(po_self);
  70. delete self->cppobj;
  71. self->cppobj = NULL;
  72. Py_TYPE(self)->tp_free(self);
  73. }
  74. PyObject*
  75. ConfigurableClientList_configure(PyObject* po_self, PyObject* args) {
  76. s_ConfigurableClientList* self =
  77. static_cast<s_ConfigurableClientList*>(po_self);
  78. try {
  79. const char* configuration;
  80. int allow_cache;
  81. if (PyArg_ParseTuple(args, "si", &configuration, &allow_cache)) {
  82. const isc::data::ConstElementPtr
  83. element(isc::data::Element::fromJSON(string(configuration)));
  84. self->cppobj->configure(*element, allow_cache);
  85. Py_RETURN_NONE;
  86. } else {
  87. return (NULL);
  88. }
  89. } catch (const std::exception& exc) {
  90. PyErr_SetString(getDataSourceException("Error"), exc.what());
  91. return (NULL);
  92. } catch (...) {
  93. PyErr_SetString(getDataSourceException("Error"),
  94. "Unknown C++ exception");
  95. return (NULL);
  96. }
  97. }
  98. PyObject*
  99. ConfigurableClientList_find(PyObject* po_self, PyObject* args) {
  100. s_ConfigurableClientList* self =
  101. static_cast<s_ConfigurableClientList*>(po_self);
  102. try {
  103. PyObject* name_obj;
  104. int want_exact_match = 0;
  105. int want_finder = 1;
  106. if (PyArg_ParseTuple(args, "O!|ii", &isc::dns::python::name_type,
  107. &name_obj, &want_exact_match, &want_finder)) {
  108. const isc::dns::Name
  109. name(isc::dns::python::PyName_ToName(name_obj));
  110. const ClientList::FindResult
  111. result(self->cppobj->find(name, want_exact_match,
  112. want_finder));
  113. PyObjectContainer dsrc;
  114. if (result.dsrc_client_ == NULL) {
  115. // Use the Py_BuildValue, as it takes care of the
  116. // reference counts correctly.
  117. dsrc.reset(Py_BuildValue(""));
  118. } else {
  119. dsrc.reset(wrapDataSourceClient(result.dsrc_client_));
  120. }
  121. PyObjectContainer finder;
  122. if (result.finder_ == NULL) {
  123. finder.reset(Py_BuildValue(""));
  124. } else {
  125. finder.reset(createZoneFinderObject(result.finder_));
  126. }
  127. PyObjectContainer exact(PyBool_FromLong(result.exact_match_));
  128. return (Py_BuildValue("OOO", dsrc.get(), finder.get(),
  129. exact.get()));
  130. } else {
  131. return (NULL);
  132. }
  133. } catch (const std::exception& exc) {
  134. PyErr_SetString(getDataSourceException("Error"), exc.what());
  135. return (NULL);
  136. } catch (...) {
  137. PyErr_SetString(getDataSourceException("Error"),
  138. "Unknown C++ exception");
  139. return (NULL);
  140. }
  141. }
  142. // This list contains the actual set of functions we have in
  143. // python. Each entry has
  144. // 1. Python method name
  145. // 2. Our static function here
  146. // 3. Argument type
  147. // 4. Documentation
  148. PyMethodDef ConfigurableClientList_methods[] = {
  149. { "configure", ConfigurableClientList_configure, METH_VARARGS,
  150. "TODO: Docs" },
  151. { "find", ConfigurableClientList_find, METH_VARARGS, "TODO: Docs" },
  152. { NULL, NULL, 0, NULL }
  153. };
  154. } // end of unnamed namespace
  155. namespace isc {
  156. namespace datasrc {
  157. namespace python {
  158. // This defines the complete type for reflection in python and
  159. // parsing of PyObject* to s_ConfigurableClientList
  160. // Most of the functions are not actually implemented and NULL here.
  161. PyTypeObject configurableclientlist_type = {
  162. PyVarObject_HEAD_INIT(NULL, 0)
  163. "datasrc.ConfigurableClientList",
  164. sizeof(s_ConfigurableClientList), // tp_basicsize
  165. 0, // tp_itemsize
  166. ConfigurableClientList_destroy, // tp_dealloc
  167. NULL, // tp_print
  168. NULL, // tp_getattr
  169. NULL, // tp_setattr
  170. NULL, // tp_reserved
  171. NULL, // tp_repr
  172. NULL, // tp_as_number
  173. NULL, // tp_as_sequence
  174. NULL, // tp_as_mapping
  175. NULL, // tp_hash
  176. NULL, // tp_call
  177. NULL, // tp_str
  178. NULL, // tp_getattro
  179. NULL, // tp_setattro
  180. NULL, // tp_as_buffer
  181. Py_TPFLAGS_DEFAULT, // tp_flags
  182. ConfigurableClientList_doc,
  183. NULL, // tp_traverse
  184. NULL, // tp_clear
  185. NULL, // tp_richcompare
  186. 0, // tp_weaklistoffset
  187. NULL, // tp_iter
  188. NULL, // tp_iternext
  189. ConfigurableClientList_methods, // tp_methods
  190. NULL, // tp_members
  191. NULL, // tp_getset
  192. NULL, // tp_base
  193. NULL, // tp_dict
  194. NULL, // tp_descr_get
  195. NULL, // tp_descr_set
  196. 0, // tp_dictoffset
  197. ConfigurableClientList_init, // tp_init
  198. NULL, // tp_alloc
  199. PyType_GenericNew, // tp_new
  200. NULL, // tp_free
  201. NULL, // tp_is_gc
  202. NULL, // tp_bases
  203. NULL, // tp_mro
  204. NULL, // tp_cache
  205. NULL, // tp_subclasses
  206. NULL, // tp_weaklist
  207. NULL, // tp_del
  208. 0 // tp_version_tag
  209. };
  210. // Module Initialization, all statics are initialized here
  211. bool
  212. initModulePart_ConfigurableClientList(PyObject* mod) {
  213. // We initialize the static description object with PyType_Ready(),
  214. // then add it to the module. This is not just a check! (leaving
  215. // this out results in segmentation faults)
  216. if (PyType_Ready(&configurableclientlist_type) < 0) {
  217. return (false);
  218. }
  219. void* p = &configurableclientlist_type;
  220. if (PyModule_AddObject(mod, "ConfigurableClientList",
  221. static_cast<PyObject*>(p)) < 0) {
  222. return (false);
  223. }
  224. Py_INCREF(&configurableclientlist_type);
  225. #if 0
  226. TODO: The return states, etc.
  227. try {
  228. // Constant class variables
  229. installClassVariable(configurableclientlist_type, "REPLACE_ME",
  230. Py_BuildValue("REPLACE ME"));
  231. } catch (const exception& ex) {
  232. const string ex_what =
  233. "Unexpected failure in ConfigurableClientList initialization: " +
  234. string(ex.what());
  235. PyErr_SetString(po_IscException, ex_what.c_str());
  236. return (false);
  237. } catch (...) {
  238. PyErr_SetString(PyExc_SystemError,
  239. "Unexpected failure in ConfigurableClientList initialization");
  240. return (false);
  241. }
  242. #endif
  243. return (true);
  244. }
  245. } // namespace python
  246. } // namespace datasrc
  247. } // namespace isc