LCOV - code coverage report
Current view: top level - python/isc/datasrc - finder_python.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 81 107 75.7 %
Date: 2012-05-15 Functions: 11 11 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 58 150 38.7 %

           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/database.h>
      27                 :            : #include <datasrc/data_source.h>
      28                 :            : #include <datasrc/sqlite3_accessor.h>
      29                 :            : #include <datasrc/iterator.h>
      30                 :            : #include <datasrc/zone.h>
      31                 :            : 
      32                 :            : #include <dns/python/name_python.h>
      33                 :            : #include <dns/python/rrset_python.h>
      34                 :            : #include <dns/python/rrclass_python.h>
      35                 :            : #include <dns/python/rrtype_python.h>
      36                 :            : #include <dns/python/pydnspp_common.h>
      37                 :            : 
      38                 :            : #include "datasrc.h"
      39                 :            : #include "finder_python.h"
      40                 :            : #include "finder_inc.cc"
      41                 :            : 
      42                 :            : using namespace std;
      43                 :            : using namespace isc::util::python;
      44                 :            : using namespace isc::dns::python;
      45                 :            : using namespace isc::datasrc;
      46                 :            : using namespace isc::datasrc::python;
      47                 :            : 
      48                 :            : namespace  {
      49                 :            : ZoneFinder::FindResultFlags
      50                 :            : getFindResultFlags(const ZoneFinder::Context& context) {
      51                 :        254 :     ZoneFinder::FindResultFlags result_flags = ZoneFinder::RESULT_DEFAULT;
      52 [ -  + ][ +  + ]:        254 :     if (context.isWildcard()) {
      53                 :          2 :         result_flags = result_flags | ZoneFinder::RESULT_WILDCARD;
      54                 :            :     }
      55 [ -  + ][ -  + ]:        254 :     if (context.isNSECSigned()) {
      56                 :          0 :         result_flags = result_flags | ZoneFinder::RESULT_NSEC_SIGNED;
      57                 :            :     }
      58 [ -  + ][ -  + ]:        254 :     if (context.isNSEC3Signed()) {
      59                 :          0 :         result_flags = result_flags | ZoneFinder::RESULT_NSEC3_SIGNED;
      60                 :            :     }
      61                 :            :     return (result_flags);
      62                 :            : }
      63                 :            : }
      64                 :            : 
      65                 :            : namespace isc_datasrc_internal {
      66                 :            : // This is the shared code for the find() call in the finder and the updater
      67                 :            : // Is is intentionally not available through any header, nor at our standard
      68                 :            : // namespace, as it is not supposed to be called anywhere but from finder and
      69                 :            : // updater
      70                 :        252 : PyObject* ZoneFinder_helper(ZoneFinder* finder, PyObject* args) {
      71         [ -  + ]:        252 :     if (finder == NULL) {
      72                 :            :         PyErr_SetString(getDataSourceException("Error"),
      73                 :            :                         "Internal error in find() wrapper; "
      74                 :          0 :                         "finder object NULL");
      75                 :          0 :         return (NULL);
      76                 :            :     }
      77                 :            :     PyObject* name;
      78                 :            :     PyObject* rrtype;
      79                 :        252 :     unsigned int options_int = ZoneFinder::FIND_DEFAULT;
      80         [ +  + ]:        252 :     if (PyArg_ParseTuple(args, "O!O!|I", &name_type, &name,
      81                 :            :                                          &rrtype_type, &rrtype,
      82                 :        252 :                                          &options_int)) {
      83                 :            :         try {
      84                 :            :             ZoneFinder::FindOptions options =
      85                 :        249 :                 static_cast<ZoneFinder::FindOptions>(options_int);
      86                 :            :             ConstZoneFinderContextPtr find_ctx(
      87 [ +  - ][ +  - ]:        249 :                 finder->find(PyName_ToName(name), PyRRType_ToRRType(rrtype),
      88         [ +  + ]:        249 :                              options));
      89                 :        248 :             const ZoneFinder::Result r = find_ctx->code;
      90                 :        248 :             isc::dns::ConstRRsetPtr rrsp = find_ctx->rrset;
      91                 :            :             ZoneFinder::FindResultFlags result_flags =
      92                 :        744 :                 getFindResultFlags(*find_ctx);
      93         [ +  + ]:        248 :             if (rrsp) {
      94                 :            :                 // Use N instead of O so the refcount isn't increased twice
      95                 :        204 :                 return (Py_BuildValue("INI", r, createRRsetObject(*rrsp),
      96 [ +  - ][ +  - ]:        204 :                                       result_flags));
      97                 :            :             } else {
      98         [ +  - ]:         44 :                 return (Py_BuildValue("IOI", r, Py_None, result_flags));
      99                 :            :             }
     100                 :          2 :         } catch (const OutOfZone& ooz) {
     101 [ -  + ][ -  + ]:          1 :             PyErr_SetString(getDataSourceException("OutOfZone"), ooz.what());
     102                 :            :             return (NULL);
     103                 :          0 :         } catch (const DataSourceError& dse) {
     104 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), dse.what());
     105                 :            :             return (NULL);
     106                 :          0 :         } catch (const std::exception& exc) {
     107 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), exc.what());
     108                 :            :             return (NULL);
     109   [ +  -  -  - ]:          1 :         } catch (...) {
     110                 :            :             PyErr_SetString(getDataSourceException("Error"),
     111 [ #  # ][ #  # ]:          0 :                             "Unexpected exception");
     112                 :            :             return (NULL);
     113                 :            :         }
     114                 :            :     } else {
     115                 :            :         return (NULL);
     116                 :            :     }
     117                 :            : }
     118                 :            : 
     119                 :          6 : PyObject* ZoneFinder_helper_all(ZoneFinder* finder, PyObject* args) {
     120         [ -  + ]:          6 :     if (finder == NULL) {
     121                 :            :         PyErr_SetString(getDataSourceException("Error"),
     122                 :            :                         "Internal error in find_all() wrapper; "
     123                 :          0 :                         "finder object NULL");
     124                 :          0 :         return (NULL);
     125                 :            :     }
     126                 :            :     PyObject* name;
     127                 :          6 :     const unsigned int options_int = ZoneFinder::FIND_DEFAULT;
     128         [ +  - ]:          6 :     if (PyArg_ParseTuple(args, "O!|I", &name_type, &name, &options_int)) {
     129                 :            :         try {
     130                 :            :             ZoneFinder::FindOptions options =
     131                 :          6 :                 static_cast<ZoneFinder::FindOptions>(options_int);
     132         [ +  - ]:          6 :             std::vector<isc::dns::ConstRRsetPtr> target;
     133                 :            :             ConstZoneFinderContextPtr find_ctx(
     134 [ +  - ][ +  - ]:          6 :                 finder->findAll(PyName_ToName(name), target, options));
     135                 :          6 :             const ZoneFinder::Result r = find_ctx->code;
     136                 :          6 :             isc::dns::ConstRRsetPtr rrsp = find_ctx->rrset;
     137                 :            :             ZoneFinder::FindResultFlags result_flags =
     138                 :         18 :                 getFindResultFlags(*find_ctx);
     139         [ +  + ]:          6 :             if (r == ZoneFinder::SUCCESS) {
     140                 :            :                 // Copy all the RRsets to the result list
     141 [ +  - ][ +  - ]:          2 :                 PyObjectContainer list_container(PyList_New(target.size()));
     142         [ +  + ]:          6 :                 for (size_t i(0); i < target.size(); ++i) {
     143         [ +  - ]:          4 :                     PyList_SET_ITEM(list_container.get(), i,
     144                 :          4 :                                     createRRsetObject(*target[i]));
     145                 :            :                 }
     146                 :            :                 // Construct the result with the list. The Py_BuildValue
     147                 :            :                 // increases the refcount and the container decreases it
     148                 :            :                 // later. This way, it feels safer in case the build function
     149                 :            :                 // would fail.
     150         [ +  - ]:          2 :                 return (Py_BuildValue("IO", r, list_container.get()));
     151                 :            :             } else {
     152         [ +  + ]:          4 :                 if (rrsp) {
     153                 :            :                     // Use N instead of O so the refcount isn't increased twice
     154                 :          2 :                     return (Py_BuildValue("INI", r, createRRsetObject(*rrsp),
     155 [ +  - ][ +  - ]:          2 :                                           result_flags));
     156                 :            :                 } else {
     157         [ +  - ]:          2 :                     return (Py_BuildValue("IOI", r, Py_None, result_flags));
     158                 :            :                 }
     159                 :            :             }
     160                 :          0 :         } catch (const DataSourceError& dse) {
     161 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), dse.what());
     162                 :            :             return (NULL);
     163                 :          0 :         } catch (const std::exception& exc) {
     164 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), exc.what());
     165                 :            :             return (NULL);
     166      [ #  #  # ]:          0 :         } catch (...) {
     167                 :            :             PyErr_SetString(getDataSourceException("Error"),
     168 [ #  # ][ #  # ]:          0 :                             "Unexpected exception");
     169                 :            :             return (NULL);
     170                 :            :         }
     171                 :            :     } else {
     172                 :            :         return (NULL);
     173                 :            :     }
     174                 :            : }
     175                 :            : 
     176                 :            : } // end namespace internal
     177                 :            : 
     178                 :            : namespace {
     179                 :            : // The s_* Class simply covers one instantiation of the object
     180                 :            : class s_ZoneFinder : public PyObject {
     181                 :            : public:
     182                 :            :     s_ZoneFinder() : cppobj(ZoneFinderPtr()), base_obj(NULL) {};
     183                 :            :     ZoneFinderPtr cppobj;
     184                 :            :     // This is a reference to a base object; if the object of this class
     185                 :            :     // depends on another object to be in scope during its lifetime,
     186                 :            :     // we use INCREF the base object upon creation, and DECREF it at
     187                 :            :     // the end of the destructor
     188                 :            :     // This is an optional argument to createXXX(). If NULL, it is ignored.
     189                 :            :     PyObject* base_obj;
     190                 :            : };
     191                 :            : 
     192                 :            : // Shortcut type which would be convenient for adding class variables safely.
     193                 :            : typedef CPPPyObjectContainer<s_ZoneFinder, ZoneFinder> ZoneFinderContainer;
     194                 :            : 
     195                 :            : // General creation and destruction
     196                 :            : int
     197                 :          1 : ZoneFinder_init(PyObject*, PyObject*, PyObject*) {
     198                 :            :     // can't be called directly
     199                 :            :     PyErr_SetString(PyExc_TypeError,
     200                 :          1 :                     "ZoneFinder cannot be constructed directly");
     201                 :            : 
     202                 :          1 :     return (-1);
     203                 :            : }
     204                 :            : 
     205                 :            : void
     206                 :        176 : ZoneFinder_destroy(PyObject* po_self) {
     207                 :        176 :     s_ZoneFinder* self = static_cast<s_ZoneFinder*>(po_self);
     208                 :            :     // cppobj is a shared ptr, but to make sure things are not destroyed in
     209                 :            :     // the wrong order, we reset it here.
     210                 :        176 :     self->cppobj.reset();
     211         [ +  + ]:        176 :     if (self->base_obj != NULL) {
     212         [ +  + ]:        175 :         Py_DECREF(self->base_obj);
     213                 :            :     }
     214                 :        176 :     Py_TYPE(self)->tp_free(self);
     215                 :        176 : }
     216                 :            : 
     217                 :            : PyObject*
     218                 :          5 : ZoneFinder_getClass(PyObject* po_self, PyObject*) {
     219                 :          5 :     s_ZoneFinder* self = static_cast<s_ZoneFinder*>(po_self);
     220                 :            :     try {
     221 [ +  - ][ +  - ]:          5 :         return (createRRClassObject(self->cppobj->getClass()));
     222         [ #  # ]:          0 :     } catch (const std::exception& exc) {
     223 [ #  # ][ #  # ]:          0 :         PyErr_SetString(getDataSourceException("Error"), exc.what());
     224                 :            :         return (NULL);
     225                 :            :     }
     226                 :            : }
     227                 :            : 
     228                 :            : PyObject*
     229                 :          5 : ZoneFinder_getOrigin(PyObject* po_self, PyObject*) {
     230                 :          5 :     s_ZoneFinder* self = static_cast<s_ZoneFinder*>(po_self);
     231                 :            :     try {
     232 [ +  - ][ +  - ]:          5 :         return (createNameObject(self->cppobj->getOrigin()));
     233                 :          0 :     } catch (const std::exception& exc) {
     234 [ #  # ][ #  # ]:          0 :         PyErr_SetString(getDataSourceException("Error"), exc.what());
     235                 :            :         return (NULL);
     236         [ #  # ]:          0 :     } catch (...) {
     237                 :            :         PyErr_SetString(getDataSourceException("Error"),
     238 [ #  # ][ #  # ]:          0 :                         "Unexpected exception");
     239                 :            :         return (NULL);
     240                 :            :     }
     241                 :            : }
     242                 :            : 
     243                 :            : PyObject*
     244                 :        248 : ZoneFinder_find(PyObject* po_self, PyObject* args) {
     245                 :        248 :     s_ZoneFinder* const self = static_cast<s_ZoneFinder*>(po_self);
     246                 :        248 :     return (isc_datasrc_internal::ZoneFinder_helper(self->cppobj.get(), args));
     247                 :            : }
     248                 :            : 
     249                 :            : PyObject*
     250                 :          3 : ZoneFinder_find_all(PyObject* po_self, PyObject* args) {
     251                 :          3 :     s_ZoneFinder* const self = static_cast<s_ZoneFinder*>(po_self);
     252                 :            :     return (isc_datasrc_internal::ZoneFinder_helper_all(self->cppobj.get(),
     253                 :          3 :                                                         args));
     254                 :            : }
     255                 :            : 
     256                 :            : PyObject*
     257                 :          4 : ZoneFinder_findPreviousName(PyObject* po_self, PyObject* args) {
     258                 :          4 :     s_ZoneFinder* const self = static_cast<s_ZoneFinder*>(po_self);
     259                 :            :     PyObject* name_obj;
     260         [ +  - ]:          4 :     if (PyArg_ParseTuple(args, "O!", &name_type, &name_obj)) {
     261                 :            :         try {
     262                 :            :             return (createNameObject(
     263 [ +  - ][ +  + ]:          5 :                 self->cppobj->findPreviousName(PyName_ToName(name_obj))));
                 [ +  - ]
     264                 :          2 :         } catch (const isc::NotImplemented& nie) {
     265                 :            :             PyErr_SetString(getDataSourceException("NotImplemented"),
     266 [ -  + ][ -  + ]:          1 :                             nie.what());
     267                 :            :             return (NULL);
     268                 :          0 :         } catch (const std::exception& exc) {
     269 [ #  # ][ #  # ]:          0 :             PyErr_SetString(getDataSourceException("Error"), exc.what());
     270                 :            :             return (NULL);
     271      [ +  -  - ]:          1 :         } catch (...) {
     272                 :            :             PyErr_SetString(getDataSourceException("Error"),
     273 [ #  # ][ #  # ]:          0 :                             "Unexpected exception");
     274                 :            :             return (NULL);
     275                 :            :         }
     276                 :            :     } else {
     277                 :            :         return (NULL);
     278                 :            :     }
     279                 :            : }
     280                 :            : 
     281                 :            : // This list contains the actual set of functions we have in
     282                 :            : // python. Each entry has
     283                 :            : // 1. Python method name
     284                 :            : // 2. Our static function here
     285                 :            : // 3. Argument type
     286                 :            : // 4. Documentation
     287                 :            : PyMethodDef ZoneFinder_methods[] = {
     288                 :            :     { "get_origin", ZoneFinder_getOrigin, METH_NOARGS,
     289                 :            :        ZoneFinder_getOrigin_doc },
     290                 :            :     { "get_class", ZoneFinder_getClass, METH_NOARGS, ZoneFinder_getClass_doc },
     291                 :            :     { "find", ZoneFinder_find, METH_VARARGS, ZoneFinder_find_doc },
     292                 :            :     { "find_all", ZoneFinder_find_all, METH_VARARGS, ZoneFinder_findAll_doc },
     293                 :            :     { "find_previous_name", ZoneFinder_findPreviousName, METH_VARARGS,
     294                 :            :       ZoneFinder_find_previous_name_doc },
     295                 :            :     { NULL, NULL, 0, NULL }
     296                 :            : };
     297                 :            : 
     298                 :            : } // end of unnamed namespace
     299                 :            : 
     300                 :            : namespace isc {
     301                 :            : namespace datasrc {
     302                 :            : namespace python {
     303                 :            : 
     304                 :            : PyTypeObject zonefinder_type = {
     305                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
     306                 :            :     "datasrc.ZoneFinder",
     307                 :            :     sizeof(s_ZoneFinder),               // tp_basicsize
     308                 :            :     0,                                  // tp_itemsize
     309                 :            :     ZoneFinder_destroy,                 // tp_dealloc
     310                 :            :     NULL,                               // tp_print
     311                 :            :     NULL,                               // tp_getattr
     312                 :            :     NULL,                               // tp_setattr
     313                 :            :     NULL,                               // tp_reserved
     314                 :            :     NULL,                               // tp_repr
     315                 :            :     NULL,                               // tp_as_number
     316                 :            :     NULL,                               // tp_as_sequence
     317                 :            :     NULL,                               // tp_as_mapping
     318                 :            :     NULL,                               // tp_hash
     319                 :            :     NULL,                               // tp_call
     320                 :            :     NULL,                               // tp_str
     321                 :            :     NULL,                               // tp_getattro
     322                 :            :     NULL,                               // tp_setattro
     323                 :            :     NULL,                               // tp_as_buffer
     324                 :            :     Py_TPFLAGS_DEFAULT,                 // tp_flags
     325                 :            :     ZoneFinder_doc,
     326                 :            :     NULL,                               // tp_traverse
     327                 :            :     NULL,                               // tp_clear
     328                 :            :     NULL,                               // tp_richcompare
     329                 :            :     0,                                  // tp_weaklistoffset
     330                 :            :     NULL,                               // tp_iter
     331                 :            :     NULL,                               // tp_iternext
     332                 :            :     ZoneFinder_methods,                 // tp_methods
     333                 :            :     NULL,                               // tp_members
     334                 :            :     NULL,                               // tp_getset
     335                 :            :     NULL,                               // tp_base
     336                 :            :     NULL,                               // tp_dict
     337                 :            :     NULL,                               // tp_descr_get
     338                 :            :     NULL,                               // tp_descr_set
     339                 :            :     0,                                  // tp_dictoffset
     340                 :            :     ZoneFinder_init,                    // tp_init
     341                 :            :     NULL,                               // tp_alloc
     342                 :            :     PyType_GenericNew,                  // tp_new
     343                 :            :     NULL,                               // tp_free
     344                 :            :     NULL,                               // tp_is_gc
     345                 :            :     NULL,                               // tp_bases
     346                 :            :     NULL,                               // tp_mro
     347                 :            :     NULL,                               // tp_cache
     348                 :            :     NULL,                               // tp_subclasses
     349                 :            :     NULL,                               // tp_weaklist
     350                 :            :     NULL,                               // tp_del
     351                 :            :     0                                   // tp_version_tag
     352                 :            : };
     353                 :            : 
     354                 :            : PyObject*
     355                 :        175 : createZoneFinderObject(isc::datasrc::ZoneFinderPtr source, PyObject* base_obj) {
     356                 :            :     s_ZoneFinder* py_zf = static_cast<s_ZoneFinder*>(
     357                 :        175 :         zonefinder_type.tp_alloc(&zonefinder_type, 0));
     358         [ +  - ]:        175 :     if (py_zf != NULL) {
     359                 :        175 :         py_zf->cppobj = source;
     360                 :        175 :         py_zf->base_obj = base_obj;
     361         [ +  - ]:        175 :         if (base_obj != NULL) {
     362                 :        175 :             Py_INCREF(base_obj);
     363                 :            :         }
     364                 :            :     }
     365                 :        175 :     return (py_zf);
     366                 :            : }
     367                 :            : 
     368                 :            : } // namespace python
     369                 :            : } // namespace datasrc
     370                 :        104 : } // namespace isc
     371                 :            : 

Generated by: LCOV version 1.9