LCOV - code coverage report
Current view: top level - datasrc - factory.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 45 47 95.7 %
Date: 2012-05-15 Functions: 7 7 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 44 76 57.9 %

           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                 :            : #include "factory.h"
      16                 :            : 
      17                 :            : #include "data_source.h"
      18                 :            : #include "database.h"
      19                 :            : #include "sqlite3_accessor.h"
      20                 :            : #include "memory_datasrc.h"
      21                 :            : 
      22                 :            : #include "datasrc_config.h"
      23                 :            : 
      24                 :            : #include <datasrc/logger.h>
      25                 :            : 
      26                 :            : #include <dlfcn.h>
      27                 :            : #include <cstdlib>
      28                 :            : 
      29                 :            : using namespace std;
      30                 :            : using namespace isc::data;
      31                 :            : using namespace isc::datasrc;
      32                 :            : 
      33                 :            : namespace {
      34                 :            : // This helper function takes the 'type' string as passed to
      35                 :            : // the DataSourceClient container below, and, unless it
      36                 :            : // already specifies a specific loadable .so file, will
      37                 :            : // convert the short-name to the full file.
      38                 :            : // I.e. it will add '_ds.so' (if necessary), and prepend
      39                 :            : // it with an absolute path (if necessary).
      40                 :            : // Returns the resulting string to use with LibraryContainer.
      41                 :            : const std::string
      42                 :        135 : getDataSourceLibFile(const std::string& type) {
      43         [ +  + ]:        135 :     if (type.empty()) {
      44         [ +  - ]:          2 :         isc_throw(DataSourceLibraryError,
      45                 :            :                   "DataSourceClient container called with empty type value");
      46                 :            :     }
      47         [ +  + ]:        134 :     if (type == ".so") {
      48         [ +  - ]:          2 :         isc_throw(DataSourceLibraryError, "DataSourceClient container called "
      49                 :            :                                           "with bad type or file name");
      50                 :            :     }
      51                 :            : 
      52                 :            :     // Type can be either a short name, in which case we need to
      53                 :            :     // append "_ds.so", or it can be a direct .so library.
      54                 :        133 :     std::string lib_file = type;
      55         [ +  - ]:        133 :     const int ext_pos = lib_file.rfind(".so");
      56 [ +  + ][ +  + ]:        133 :     if (ext_pos == std::string::npos || ext_pos + 3 != lib_file.length()) {
                 [ +  + ]
      57         [ +  - ]:        128 :         lib_file.append("_ds.so");
      58                 :            :     }
      59                 :            :     // And if it is not an absolute path, prepend it with our
      60                 :            :     // loadable backend library path
      61         [ +  + ]:        133 :     if (type[0] != '/') {
      62                 :            :         // When running from the build tree, we do NOT want
      63                 :            :         // to load the installed loadable library
      64         [ +  + ]:        128 :         if (getenv("B10_FROM_BUILD") != NULL) {
      65                 :        254 :             lib_file = std::string(getenv("B10_FROM_BUILD")) +
      66 [ +  - ][ +  - ]:        254 :                        "/src/lib/datasrc/.libs/" + lib_file;
      67                 :            :         } else {
      68         [ +  - ]:          2 :             lib_file = isc::datasrc::BACKEND_LIBRARY_PATH + lib_file;
      69                 :            :         }
      70                 :            :     }
      71                 :        133 :     return (lib_file);
      72                 :            : }
      73                 :            : } // end anonymous namespace
      74                 :            : 
      75                 :            : namespace isc {
      76                 :            : namespace datasrc {
      77                 :            : 
      78                 :        133 : LibraryContainer::LibraryContainer(const std::string& name) {
      79                 :            :     // use RTLD_GLOBAL so that shared symbols (e.g. exceptions)
      80                 :            :     // are recognized as such
      81                 :        133 :     ds_lib_ = dlopen(name.c_str(), RTLD_NOW | RTLD_GLOBAL);
      82         [ +  + ]:        133 :     if (ds_lib_ == NULL) {
      83                 :            :         // This may cause the filename to appear twice in the actual
      84                 :            :         // error, but the output of dlerror is implementation-dependent
      85 [ +  - ][ +  - ]:         24 :         isc_throw(DataSourceLibraryError, "dlopen failed for " << name << 
         [ +  - ][ +  - ]
      86                 :            :                                           ": " << dlerror());
      87                 :            :     }
      88                 :        121 : }
      89                 :            : 
      90                 :        121 : LibraryContainer::~LibraryContainer() {
      91                 :        121 :     dlclose(ds_lib_);
      92                 :        121 : }
      93                 :            : 
      94                 :            : void*
      95                 :        242 : LibraryContainer::getSym(const char* name) {
      96                 :            :     // Since dlsym can return NULL on success, we check for errors by
      97                 :            :     // first clearing any existing errors with dlerror(), then calling dlsym,
      98                 :            :     // and finally checking for errors with dlerror()
      99                 :        242 :     dlerror();
     100                 :            : 
     101                 :        242 :     void *sym = dlsym(ds_lib_, name);
     102                 :            : 
     103                 :        242 :     const char* dlsym_error = dlerror();
     104         [ -  + ]:        242 :     if (dlsym_error != NULL) {
     105         [ #  # ]:          0 :         isc_throw(DataSourceLibrarySymbolError, dlsym_error);
     106                 :            :     }
     107                 :            : 
     108                 :        242 :     return (sym);
     109                 :            : }
     110                 :            : 
     111                 :        135 : DataSourceClientContainer::DataSourceClientContainer(const std::string& type,
     112                 :            :                                                      ConstElementPtr config)
     113         [ +  + ]:        164 : : ds_lib_(getDataSourceLibFile(type))
     114                 :            : {
     115                 :            :     // We are casting from a data to a function pointer here
     116                 :            :     // Some compilers (rightfully) complain about that, but
     117                 :            :     // c-style casts are accepted the most here. If we run
     118                 :            :     // into any that also don't like this, we might need to
     119                 :            :     // use some form of union cast or memory copy to get
     120                 :            :     // from the void* to the function pointer.
     121         [ +  - ]:        121 :     ds_creator* ds_create = (ds_creator*)ds_lib_.getSym("createInstance");
     122         [ +  - ]:        121 :     destructor_ = (ds_destructor*)ds_lib_.getSym("destroyInstance");
     123                 :            : 
     124                 :        121 :     std::string error;
     125                 :            :     try {
     126         [ +  - ]:        121 :         instance_ = ds_create(config, error);
     127         [ +  + ]:        121 :         if (instance_ == NULL) {
     128 [ +  - ][ +  - ]:         58 :             isc_throw(DataSourceError, error);
     129                 :            :         }
     130                 :         58 :     } catch (const std::exception& exc) {
     131 [ -  + ][ -  + ]:         58 :         isc_throw(DataSourceError, "Unknown uncaught exception from " + type +
         [ -  + ][ -  + ]
                 [ -  + ]
     132                 :            :                                    " createInstance: " + exc.what());
     133         [ +  - ]:         29 :     } catch (...) {
     134 [ #  # ][ #  # ]:          0 :         isc_throw(DataSourceError, "Unknown uncaught exception from " + type);
                 [ #  # ]
     135                 :            :     }
     136                 :         92 : }
     137                 :            : 
     138                 :         92 : DataSourceClientContainer::~DataSourceClientContainer() {
     139         [ +  - ]:         92 :     destructor_(instance_);
     140                 :         92 : }
     141                 :            : 
     142                 :            : } // end namespace datasrc
     143                 :        107 : } // end namespace isc
     144                 :            : 

Generated by: LCOV version 1.9