client_python.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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/factory.h>
  23. #include <datasrc/database.h>
  24. #include <datasrc/data_source.h>
  25. #include <datasrc/sqlite3_accessor.h>
  26. #include <datasrc/iterator.h>
  27. #include <dns/python/name_python.h>
  28. #include <dns/python/rrset_python.h>
  29. #include <dns/python/pydnspp_common.h>
  30. #include "datasrc.h"
  31. #include "client_python.h"
  32. #include "finder_python.h"
  33. #include "iterator_python.h"
  34. #include "updater_python.h"
  35. #include "client_inc.cc"
  36. using namespace std;
  37. using namespace isc::util::python;
  38. using namespace isc::dns::python;
  39. using namespace isc::datasrc;
  40. using namespace isc::datasrc::python;
  41. namespace {
  42. // The s_* Class simply covers one instantiation of the object
  43. class s_DataSourceClient : public PyObject {
  44. public:
  45. s_DataSourceClient() : cppobj(NULL) {};
  46. DataSourceClientContainer* cppobj;
  47. };
  48. PyObject*
  49. DataSourceClient_findZone(PyObject* po_self, PyObject* args) {
  50. s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
  51. PyObject *name;
  52. if (PyArg_ParseTuple(args, "O!", &name_type, &name)) {
  53. try {
  54. DataSourceClient::FindResult find_result(
  55. self->cppobj->getInstance().findZone(PyName_ToName(name)));
  56. result::Result r = find_result.code;
  57. ZoneFinderPtr zfp = find_result.zone_finder;
  58. // Use N instead of O so refcount isn't increased twice
  59. return (Py_BuildValue("IN", r, createZoneFinderObject(zfp, po_self)));
  60. } catch (const std::exception& exc) {
  61. PyErr_SetString(getDataSourceException("Error"), exc.what());
  62. return (NULL);
  63. } catch (...) {
  64. PyErr_SetString(getDataSourceException("Error"),
  65. "Unexpected exception");
  66. return (NULL);
  67. }
  68. } else {
  69. return (NULL);
  70. }
  71. }
  72. PyObject*
  73. DataSourceClient_getIterator(PyObject* po_self, PyObject* args) {
  74. s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
  75. PyObject *name_obj;
  76. if (PyArg_ParseTuple(args, "O!", &name_type, &name_obj)) {
  77. try {
  78. return (createZoneIteratorObject(
  79. self->cppobj->getInstance().getIterator(PyName_ToName(name_obj)),
  80. po_self));
  81. } catch (const isc::NotImplemented& ne) {
  82. PyErr_SetString(getDataSourceException("NotImplemented"),
  83. ne.what());
  84. return (NULL);
  85. } catch (const DataSourceError& dse) {
  86. PyErr_SetString(getDataSourceException("Error"), dse.what());
  87. return (NULL);
  88. } catch (const std::exception& exc) {
  89. PyErr_SetString(getDataSourceException("Error"), exc.what());
  90. return (NULL);
  91. } catch (...) {
  92. PyErr_SetString(getDataSourceException("Error"),
  93. "Unexpected exception");
  94. return (NULL);
  95. }
  96. } else {
  97. return (NULL);
  98. }
  99. }
  100. PyObject*
  101. DataSourceClient_getUpdater(PyObject* po_self, PyObject* args) {
  102. s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
  103. PyObject *name_obj;
  104. PyObject *replace_obj;
  105. if (PyArg_ParseTuple(args, "O!O", &name_type, &name_obj, &replace_obj) &&
  106. PyBool_Check(replace_obj)) {
  107. bool replace = (replace_obj != Py_False);
  108. try {
  109. ZoneUpdaterPtr updater =
  110. self->cppobj->getInstance().getUpdater(PyName_ToName(name_obj),
  111. replace);
  112. if (!updater) {
  113. return (Py_None);
  114. }
  115. return (createZoneUpdaterObject(updater, po_self));
  116. } catch (const isc::NotImplemented& ne) {
  117. PyErr_SetString(getDataSourceException("NotImplemented"),
  118. ne.what());
  119. return (NULL);
  120. } catch (const DataSourceError& dse) {
  121. PyErr_SetString(getDataSourceException("Error"), dse.what());
  122. return (NULL);
  123. } catch (const std::exception& exc) {
  124. PyErr_SetString(getDataSourceException("Error"), exc.what());
  125. return (NULL);
  126. } catch (...) {
  127. PyErr_SetString(getDataSourceException("Error"),
  128. "Unexpected exception");
  129. return (NULL);
  130. }
  131. } else {
  132. return (NULL);
  133. }
  134. }
  135. // This list contains the actual set of functions we have in
  136. // python. Each entry has
  137. // 1. Python method name
  138. // 2. Our static function here
  139. // 3. Argument type
  140. // 4. Documentation
  141. PyMethodDef DataSourceClient_methods[] = {
  142. { "find_zone", reinterpret_cast<PyCFunction>(DataSourceClient_findZone),
  143. METH_VARARGS, DataSourceClient_findZone_doc },
  144. { "get_iterator",
  145. reinterpret_cast<PyCFunction>(DataSourceClient_getIterator), METH_VARARGS,
  146. DataSourceClient_getIterator_doc },
  147. { "get_updater", reinterpret_cast<PyCFunction>(DataSourceClient_getUpdater),
  148. METH_VARARGS, DataSourceClient_getUpdater_doc },
  149. { NULL, NULL, 0, NULL }
  150. };
  151. int
  152. DataSourceClient_init(s_DataSourceClient* self, PyObject* args) {
  153. char* ds_type_str;
  154. char* ds_config_str;
  155. try {
  156. // Turn the given argument into config Element; then simply call
  157. // factory class to do its magic
  158. // for now, ds_config must be JSON string
  159. if (PyArg_ParseTuple(args, "ss", &ds_type_str, &ds_config_str)) {
  160. isc::data::ConstElementPtr ds_config =
  161. isc::data::Element::fromJSON(ds_config_str);
  162. self->cppobj = new DataSourceClientContainer(ds_type_str,
  163. ds_config);
  164. return (0);
  165. } else {
  166. return (-1);
  167. }
  168. } catch (const isc::data::JSONError& je) {
  169. const string ex_what = "JSON parse error in data source configuration "
  170. "data for type " +
  171. string(ds_type_str) + ":" + je.what();
  172. PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
  173. return (-1);
  174. } catch (const DataSourceError& dse) {
  175. const string ex_what = "Failed to create DataSourceClient of type " +
  176. string(ds_type_str) + ":" + dse.what();
  177. PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
  178. return (-1);
  179. } catch (const exception& ex) {
  180. const string ex_what = "Failed to construct DataSourceClient object: " +
  181. string(ex.what());
  182. PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
  183. return (-1);
  184. } catch (...) {
  185. PyErr_SetString(PyExc_RuntimeError,
  186. "Unexpected exception in constructing DataSourceClient");
  187. return (-1);
  188. }
  189. PyErr_SetString(PyExc_TypeError,
  190. "Invalid arguments to DataSourceClient constructor");
  191. return (-1);
  192. }
  193. void
  194. DataSourceClient_destroy(s_DataSourceClient* const self) {
  195. delete self->cppobj;
  196. self->cppobj = NULL;
  197. Py_TYPE(self)->tp_free(self);
  198. }
  199. } // end anonymous namespace
  200. namespace isc {
  201. namespace datasrc {
  202. namespace python {
  203. // This defines the complete type for reflection in python and
  204. // parsing of PyObject* to s_DataSourceClient
  205. // Most of the functions are not actually implemented and NULL here.
  206. PyTypeObject datasourceclient_type = {
  207. PyVarObject_HEAD_INIT(NULL, 0)
  208. "datasrc.DataSourceClient",
  209. sizeof(s_DataSourceClient), // tp_basicsize
  210. 0, // tp_itemsize
  211. reinterpret_cast<destructor>(DataSourceClient_destroy),// tp_dealloc
  212. NULL, // tp_print
  213. NULL, // tp_getattr
  214. NULL, // tp_setattr
  215. NULL, // tp_reserved
  216. NULL, // tp_repr
  217. NULL, // tp_as_number
  218. NULL, // tp_as_sequence
  219. NULL, // tp_as_mapping
  220. NULL, // tp_hash
  221. NULL, // tp_call
  222. NULL, // tp_str
  223. NULL, // tp_getattro
  224. NULL, // tp_setattro
  225. NULL, // tp_as_buffer
  226. Py_TPFLAGS_DEFAULT, // tp_flags
  227. DataSourceClient_doc,
  228. NULL, // tp_traverse
  229. NULL, // tp_clear
  230. NULL, // tp_richcompare
  231. 0, // tp_weaklistoffset
  232. NULL, // tp_iter
  233. NULL, // tp_iternext
  234. DataSourceClient_methods, // tp_methods
  235. NULL, // tp_members
  236. NULL, // tp_getset
  237. NULL, // tp_base
  238. NULL, // tp_dict
  239. NULL, // tp_descr_get
  240. NULL, // tp_descr_set
  241. 0, // tp_dictoffset
  242. reinterpret_cast<initproc>(DataSourceClient_init),// tp_init
  243. NULL, // tp_alloc
  244. PyType_GenericNew, // tp_new
  245. NULL, // tp_free
  246. NULL, // tp_is_gc
  247. NULL, // tp_bases
  248. NULL, // tp_mro
  249. NULL, // tp_cache
  250. NULL, // tp_subclasses
  251. NULL, // tp_weaklist
  252. NULL, // tp_del
  253. 0 // tp_version_tag
  254. };
  255. } // namespace python
  256. } // namespace datasrc
  257. } // namespace isc