LCOV - code coverage report
Current view: top level - python/isc/datasrc - client_python.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 71 101 70.3 %
Date: 2012-05-15 Functions: 7 7 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 74 186 39.8 %

           Branch data     Line data    Source code
       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                 :            : 
      15                 :            : // Enable this if you use s# variants with PyArg_ParseTuple(), see
      16                 :            : // http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
      17                 :            : //#define PY_SSIZE_T_CLEAN
      18                 :            : 
      19                 :            : // Python.h needs to be placed at the head of the program file, see:
      20                 :            : // http://docs.python.org/py3k/extending/extending.html#a-simple-example
      21                 :            : #include <Python.h>
      22                 :            : 
      23                 :            : #include <util/python/pycppwrapper_util.h>
      24                 :            : 
      25                 :            : #include <datasrc/client.h>
      26                 :            : #include <datasrc/factory.h>
      27                 :            : #include <datasrc/database.h>
      28                 :            : #include <datasrc/data_source.h>
      29                 :            : #include <datasrc/sqlite3_accessor.h>
      30                 :            : #include <datasrc/iterator.h>
      31                 :            : 
      32                 :            : #include <dns/python/name_python.h>
      33                 :            : #include <dns/python/rrset_python.h>
      34                 :            : #include <dns/python/pydnspp_common.h>
      35                 :            : 
      36                 :            : #include "datasrc.h"
      37                 :            : #include "client_python.h"
      38                 :            : #include "finder_python.h"
      39                 :            : #include "iterator_python.h"
      40                 :            : #include "updater_python.h"
      41                 :            : #include "journal_reader_python.h"
      42                 :            : #include "client_inc.cc"
      43                 :            : 
      44                 :            : using namespace std;
      45                 :            : using namespace isc::util::python;
      46                 :            : using namespace isc::dns::python;
      47                 :            : using namespace isc::datasrc;
      48                 :            : using namespace isc::datasrc::python;
      49                 :            : 
      50                 :            : namespace {
      51                 :            : // The s_* Class simply covers one instantiation of the object
      52                 :            : class s_DataSourceClient : public PyObject {
      53                 :            : public:
      54                 :            :     s_DataSourceClient() : cppobj(NULL) {};
      55                 :            :     DataSourceClientContainer* cppobj;
      56                 :            : };
      57                 :            : 
      58                 :            : PyObject*
      59                 :        175 : DataSourceClient_findZone(PyObject* po_self, PyObject* args) {
      60                 :        175 :     s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
      61                 :            :     PyObject *name;
      62         [ +  - ]:        175 :     if (PyArg_ParseTuple(args, "O!", &name_type, &name)) {
      63                 :            :         try {
      64                 :            :             DataSourceClient::FindResult find_result(
      65 [ +  - ][ +  - ]:        175 :                 self->cppobj->getInstance().findZone(PyName_ToName(name)));
      66                 :            : 
      67                 :        175 :             result::Result r = find_result.code;
      68                 :            :             ZoneFinderPtr zfp = find_result.zone_finder;
      69                 :            :             // Use N instead of O so refcount isn't increased twice
      70 [ +  - ][ +  - ]:        175 :             return (Py_BuildValue("IN", r, createZoneFinderObject(zfp, po_self)));
      71                 :          0 :         } catch (const std::exception& exc) {
      72 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), exc.what());
      73                 :            :             return (NULL);
      74         [ #  # ]:          0 :         } catch (...) {
      75                 :            :             PyErr_SetString(getDataSourceException("Error"),
      76 [ #  # ][ #  # ]:          0 :                             "Unexpected exception");
      77                 :            :             return (NULL);
      78                 :            :         }
      79                 :            :     } else {
      80                 :            :         return (NULL);
      81                 :            :     }
      82                 :            : }
      83                 :            : 
      84                 :            : PyObject*
      85                 :         10 : DataSourceClient_getIterator(PyObject* po_self, PyObject* args) {
      86                 :         10 :     s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
      87                 :            :     PyObject* name_obj;
      88                 :         10 :     PyObject* separate_rrs_obj = NULL;
      89         [ +  + ]:         10 :     if (PyArg_ParseTuple(args, "O!|O", &name_type, &name_obj,
      90                 :         10 :                          &separate_rrs_obj)) {
      91                 :            :         try {
      92                 :          9 :             bool separate_rrs = false;
      93         [ +  + ]:          9 :             if (separate_rrs_obj != NULL) {
      94                 :            :                 // store result in local var so we can explicitely check for
      95                 :            :                 // -1 error return value
      96         [ +  - ]:          5 :                 int separate_rrs_true = PyObject_IsTrue(separate_rrs_obj);
      97         [ +  + ]:          5 :                 if (separate_rrs_true == 1) {
      98                 :            :                     separate_rrs = true;
      99         [ -  + ]:          1 :                 } else if (separate_rrs_true == -1) {
     100                 :            :                     PyErr_SetString(getDataSourceException("Error"),
     101 [ #  # ][ #  # ]:          0 :                                     "Error getting value of separate_rrs");
     102                 :            :                     return (NULL);
     103                 :            :                 }
     104                 :            :             }
     105                 :            :             return (createZoneIteratorObject(
     106         [ +  - ]:          9 :                 self->cppobj->getInstance().getIterator(PyName_ToName(name_obj),
     107                 :          9 :                                                         separate_rrs),
     108 [ +  - ][ +  - ]:          9 :                 po_self));
     109                 :          0 :         } catch (const isc::NotImplemented& ne) {
     110                 :            :             PyErr_SetString(getDataSourceException("NotImplemented"),
     111 [ #  # ][ #  # ]:          0 :                             ne.what());
     112                 :            :             return (NULL);
     113                 :          0 :         } catch (const DataSourceError& dse) {
     114 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), dse.what());
     115                 :            :             return (NULL);
     116                 :          0 :         } catch (const std::exception& exc) {
     117 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), exc.what());
     118                 :            :             return (NULL);
     119   [ #  #  #  # ]:          0 :         } catch (...) {
     120                 :            :             PyErr_SetString(getDataSourceException("Error"),
     121 [ #  # ][ #  # ]:          0 :                             "Unexpected exception");
     122                 :            :             return (NULL);
     123                 :            :         }
     124                 :            :     } else {
     125                 :            :         return (NULL);
     126                 :            :     }
     127                 :            : }
     128                 :            : 
     129                 :            : PyObject*
     130                 :         33 : DataSourceClient_getUpdater(PyObject* po_self, PyObject* args) {
     131                 :         33 :     s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
     132                 :            :     PyObject *name_obj;
     133                 :         33 :     PyObject *replace_obj = NULL;
     134                 :         33 :     PyObject *journaling_obj = Py_False;
     135 [ +  + ][ +  + ]:         33 :     if (PyArg_ParseTuple(args, "O!O|O", &name_type, &name_obj,
         [ +  + ][ +  + ]
     136                 :         33 :                          &replace_obj, &journaling_obj) &&
     137                 :            :         PyBool_Check(replace_obj) && PyBool_Check(journaling_obj)) {
     138                 :         30 :         const bool replace = (replace_obj != Py_False);
     139                 :         30 :         const bool journaling = (journaling_obj == Py_True);
     140                 :            :         try {
     141                 :            :             ZoneUpdaterPtr updater =
     142         [ +  - ]:         30 :                 self->cppobj->getInstance().getUpdater(PyName_ToName(name_obj),
     143         [ +  + ]:         30 :                                                        replace, journaling);
     144         [ +  + ]:         29 :             if (!updater) {
     145                 :            :                 return (Py_None);
     146                 :            :             }
     147         [ +  - ]:         28 :             return (createZoneUpdaterObject(updater, po_self));
     148                 :          0 :         } catch (const isc::NotImplemented& ne) {
     149                 :            :             PyErr_SetString(getDataSourceException("NotImplemented"),
     150 [ #  # ][ #  # ]:          0 :                             ne.what());
     151                 :            :             return (NULL);
     152                 :          0 :         } catch (const DataSourceError& dse) {
     153 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), dse.what());
     154                 :            :             return (NULL);
     155                 :          2 :         } catch (const std::exception& exc) {
     156 [ -  + ][ -  + ]:          1 :             PyErr_SetString(getDataSourceException("Error"), exc.what());
     157                 :            :             return (NULL);
     158   [ -  -  +  - ]:          1 :         } catch (...) {
     159                 :            :             PyErr_SetString(getDataSourceException("Error"),
     160 [ #  # ][ #  # ]:          0 :                             "Unexpected exception");
     161                 :            :             return (NULL);
     162                 :            :         }
     163                 :            :     } else {
     164                 :            :         // PyBool_Check doesn't set the error, so we have to set it ourselves.
     165 [ +  + ][ +  + ]:          3 :         if (replace_obj != NULL && !PyBool_Check(replace_obj)) {
     166                 :            :             PyErr_SetString(PyExc_TypeError, "'replace' for "
     167                 :          1 :                             "DataSourceClient.get_updater must be boolean");
     168                 :            :         }
     169         [ +  + ]:          3 :         if (!PyBool_Check(journaling_obj)) {
     170                 :            :             PyErr_SetString(PyExc_TypeError, "'journaling' for "
     171                 :         33 :                             "DataSourceClient.get_updater must be boolean");
     172                 :            :         }
     173                 :            :         return (NULL);
     174                 :            :     }
     175                 :            : }
     176                 :            : 
     177                 :            : PyObject*
     178                 :         10 : DataSourceClient_getJournalReader(PyObject* po_self, PyObject* args) {
     179                 :         10 :     s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
     180                 :            :     PyObject *name_obj;
     181                 :            :     unsigned long begin_obj, end_obj;
     182                 :            : 
     183         [ +  + ]:         10 :     if (PyArg_ParseTuple(args, "O!kk", &name_type, &name_obj,
     184                 :         10 :                          &begin_obj, &end_obj)) {
     185                 :            :         try {
     186                 :            :             pair<ZoneJournalReader::Result, ZoneJournalReaderPtr> result =
     187                 :          7 :                 self->cppobj->getInstance().getJournalReader(
     188         [ +  - ]:          7 :                     PyName_ToName(name_obj), static_cast<uint32_t>(begin_obj),
     189         [ +  - ]:          7 :                     static_cast<uint32_t>(end_obj));
     190                 :            :             PyObject* po_reader;
     191         [ +  + ]:          7 :             if (result.first == ZoneJournalReader::SUCCESS) {
     192                 :            :                 po_reader = createZoneJournalReaderObject(result.second,
     193         [ +  - ]:          4 :                                                           po_self);
     194                 :            :             } else {
     195                 :          3 :                 po_reader = Py_None;
     196                 :          3 :                 Py_INCREF(po_reader); // this will soon be released
     197                 :            :             }
     198         [ +  - ]:          7 :             PyObjectContainer container(po_reader);
     199         [ +  - ]:          7 :             return (Py_BuildValue("(iO)", result.first, container.get()));
     200                 :          0 :         } catch (const isc::NotImplemented& ex) {
     201                 :            :             PyErr_SetString(getDataSourceException("NotImplemented"),
     202 [ #  # ][ #  # ]:          0 :                             ex.what());
     203                 :          0 :         } catch (const DataSourceError& ex) {
     204 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), ex.what());
     205                 :          0 :         } catch (const std::exception& ex) {
     206         [ #  # ]:          0 :             PyErr_SetString(PyExc_SystemError, ex.what());
     207   [ #  #  #  # ]:          0 :         } catch (...) {
     208         [ #  # ]:          0 :             PyErr_SetString(PyExc_SystemError, "Unexpected exception");
     209                 :            :         }
     210                 :            :     }
     211                 :            :     return (NULL);
     212                 :            : }
     213                 :            : 
     214                 :            : // This list contains the actual set of functions we have in
     215                 :            : // python. Each entry has
     216                 :            : // 1. Python method name
     217                 :            : // 2. Our static function here
     218                 :            : // 3. Argument type
     219                 :            : // 4. Documentation
     220                 :            : PyMethodDef DataSourceClient_methods[] = {
     221                 :            :     { "find_zone", DataSourceClient_findZone, METH_VARARGS,
     222                 :            :       DataSourceClient_findZone_doc },
     223                 :            :     { "get_iterator",
     224                 :            :       DataSourceClient_getIterator, METH_VARARGS,
     225                 :            :       DataSourceClient_getIterator_doc },
     226                 :            :     { "get_updater", DataSourceClient_getUpdater,
     227                 :            :       METH_VARARGS, DataSourceClient_getUpdater_doc },
     228                 :            :     { "get_journal_reader", DataSourceClient_getJournalReader,
     229                 :            :       METH_VARARGS, DataSourceClient_getJournalReader_doc },
     230                 :            :     { NULL, NULL, 0, NULL }
     231                 :            : };
     232                 :            : 
     233                 :            : int
     234                 :         95 : DataSourceClient_init(PyObject* po_self, PyObject* args, PyObject*) {
     235                 :         95 :     s_DataSourceClient* self = static_cast<s_DataSourceClient*>(po_self);
     236                 :            :     char* ds_type_str;
     237                 :            :     char* ds_config_str;
     238                 :            :     try {
     239                 :            :         // Turn the given argument into config Element; then simply call
     240                 :            :         // factory class to do its magic
     241                 :            : 
     242                 :            :         // for now, ds_config must be JSON string
     243 [ +  - ][ +  + ]:         95 :         if (PyArg_ParseTuple(args, "ss", &ds_type_str, &ds_config_str)) {
     244                 :            :             isc::data::ConstElementPtr ds_config =
     245 [ +  - ][ +  + ]:        185 :                 isc::data::Element::fromJSON(ds_config_str);
     246                 :            :             self->cppobj = new DataSourceClientContainer(ds_type_str,
     247 [ +  - ][ +  - ]:        276 :                                                          ds_config);
                 [ +  + ]
     248                 :         85 :             return (0);
     249                 :            :         } else {
     250                 :            :             return (-1);
     251                 :            :         }
     252                 :          2 :     } catch (const isc::data::JSONError& je) {
     253                 :            :         const string ex_what = "JSON parse error in data source configuration "
     254                 :            :                                "data for type " +
     255 [ -  + ][ -  + ]:          2 :                                string(ds_type_str) + ":" + je.what();
         [ -  + ][ -  + ]
     256 [ -  + ][ -  + ]:          1 :         PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
     257                 :            :         return (-1);
     258                 :         14 :     } catch (const DataSourceError& dse) {
     259                 :            :         const string ex_what = "Failed to create DataSourceClient of type " +
     260 [ -  + ][ -  + ]:         14 :                                string(ds_type_str) + ":" + dse.what();
         [ -  + ][ -  + ]
     261 [ -  + ][ -  + ]:          7 :         PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
     262                 :            :         return (-1);
     263                 :          0 :     } catch (const exception& ex) {
     264                 :            :         const string ex_what = "Failed to construct DataSourceClient object: " +
     265 [ #  # ][ #  # ]:          0 :             string(ex.what());
     266 [ #  # ][ #  # ]:          0 :         PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
     267                 :            :         return (-1);
     268   [ +  +  -  - ]:          8 :     } catch (...) {
     269                 :            :         PyErr_SetString(PyExc_RuntimeError,
     270         [ #  # ]:          0 :             "Unexpected exception in constructing DataSourceClient");
     271                 :            :         return (-1);
     272                 :            :     }
     273                 :            :     PyErr_SetString(PyExc_TypeError,
     274                 :            :                     "Invalid arguments to DataSourceClient constructor");
     275                 :            : 
     276                 :            :     return (-1);
     277                 :            : }
     278                 :            : 
     279                 :            : void
     280                 :         95 : DataSourceClient_destroy(PyObject* po_self) {
     281                 :         95 :     s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
     282         [ +  + ]:         95 :     delete self->cppobj;
     283                 :         95 :     self->cppobj = NULL;
     284                 :         95 :     Py_TYPE(self)->tp_free(self);
     285                 :         95 : }
     286                 :            : 
     287                 :            : } // end anonymous namespace
     288                 :            : 
     289                 :            : namespace isc {
     290                 :            : namespace datasrc {
     291                 :            : namespace python {
     292                 :            : // This defines the complete type for reflection in python and
     293                 :            : // parsing of PyObject* to s_DataSourceClient
     294                 :            : // Most of the functions are not actually implemented and NULL here.
     295                 :            : PyTypeObject datasourceclient_type = {
     296                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
     297                 :            :     "datasrc.DataSourceClient",
     298                 :            :     sizeof(s_DataSourceClient),         // tp_basicsize
     299                 :            :     0,                                  // tp_itemsize
     300                 :            :     DataSourceClient_destroy,           // tp_dealloc
     301                 :            :     NULL,                               // tp_print
     302                 :            :     NULL,                               // tp_getattr
     303                 :            :     NULL,                               // tp_setattr
     304                 :            :     NULL,                               // tp_reserved
     305                 :            :     NULL,                               // tp_repr
     306                 :            :     NULL,                               // tp_as_number
     307                 :            :     NULL,                               // tp_as_sequence
     308                 :            :     NULL,                               // tp_as_mapping
     309                 :            :     NULL,                               // tp_hash
     310                 :            :     NULL,                               // tp_call
     311                 :            :     NULL,                               // tp_str
     312                 :            :     NULL,                               // tp_getattro
     313                 :            :     NULL,                               // tp_setattro
     314                 :            :     NULL,                               // tp_as_buffer
     315                 :            :     Py_TPFLAGS_DEFAULT,                 // tp_flags
     316                 :            :     DataSourceClient_doc,
     317                 :            :     NULL,                               // tp_traverse
     318                 :            :     NULL,                               // tp_clear
     319                 :            :     NULL,                               // tp_richcompare
     320                 :            :     0,                                  // tp_weaklistoffset
     321                 :            :     NULL,                               // tp_iter
     322                 :            :     NULL,                               // tp_iternext
     323                 :            :     DataSourceClient_methods,           // tp_methods
     324                 :            :     NULL,                               // tp_members
     325                 :            :     NULL,                               // tp_getset
     326                 :            :     NULL,                               // tp_base
     327                 :            :     NULL,                               // tp_dict
     328                 :            :     NULL,                               // tp_descr_get
     329                 :            :     NULL,                               // tp_descr_set
     330                 :            :     0,                                  // tp_dictoffset
     331                 :            :     DataSourceClient_init,              // tp_init
     332                 :            :     NULL,                               // tp_alloc
     333                 :            :     PyType_GenericNew,                  // tp_new
     334                 :            :     NULL,                               // tp_free
     335                 :            :     NULL,                               // tp_is_gc
     336                 :            :     NULL,                               // tp_bases
     337                 :            :     NULL,                               // tp_mro
     338                 :            :     NULL,                               // tp_cache
     339                 :            :     NULL,                               // tp_subclasses
     340                 :            :     NULL,                               // tp_weaklist
     341                 :            :     NULL,                               // tp_del
     342                 :            :     0                                   // tp_version_tag
     343                 :            : };
     344                 :            : 
     345                 :            : } // namespace python
     346                 :            : } // namespace datasrc
     347                 :        104 : } // namespace isc

Generated by: LCOV version 1.9