Commit 07b6398d authored by Jelte Jansen's avatar Jelte Jansen

[1206] initial experiment with dlopened sqlite3 ds

parent f0ef6c88
......@@ -9,7 +9,7 @@ AM_CXXFLAGS = $(B10_CXXFLAGS)
CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
lib_LTLIBRARIES = libdatasrc.la
lib_LTLIBRARIES = libdatasrc.la sqlite3_ds.la
libdatasrc_la_SOURCES = data_source.h data_source.cc
libdatasrc_la_SOURCES += static_datasrc.h static_datasrc.cc
libdatasrc_la_SOURCES += sqlite3_datasrc.h sqlite3_datasrc.cc
......@@ -23,10 +23,13 @@ libdatasrc_la_SOURCES += result.h
libdatasrc_la_SOURCES += logger.h logger.cc
libdatasrc_la_SOURCES += client.h iterator.h
libdatasrc_la_SOURCES += database.h database.cc
libdatasrc_la_SOURCES += sqlite3_accessor.h sqlite3_accessor.cc
#libdatasrc_la_SOURCES += sqlite3_accessor.h sqlite3_accessor.cc
libdatasrc_la_SOURCES += factory.h factory.cc
nodist_libdatasrc_la_SOURCES = datasrc_messages.h datasrc_messages.cc
sqlite3_ds_la_SOURCES = sqlite3_accessor.h sqlite3_accessor.cc
sqlite3_ds_la_LDFLAGS = -module
libdatasrc_la_LIBADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
libdatasrc_la_LIBADD += $(top_builddir)/src/lib/dns/libdns++.la
libdatasrc_la_LIBADD += $(top_builddir)/src/lib/log/liblog.la
......
......@@ -19,6 +19,8 @@
#include "sqlite3_accessor.h"
#include "memory_datasrc.h"
#include <dlfcn.h>
using namespace isc::data;
using namespace isc::datasrc;
......@@ -116,7 +118,19 @@ createDataSourceClient(const std::string& type,
// For now, mapping hardcoded
// config is assumed to be ok
if (type == "sqlite3") {
return (sqlite3CreateInstance(config));
void *ds_lib = dlopen("sqlite3_ds.so", RTLD_LAZY);
if (ds_lib == NULL) {
isc_throw(DataSourceError, "Unable to load " << type <<
": " << dlerror());
}
dlerror();
ds_creator* ds_create = (ds_creator*)dlsym(ds_lib, "createInstance");
const char* dlsym_error = dlerror();
if (dlsym_error != NULL) {
isc_throw(DataSourceError, "Error in library " << type <<
": " << dlsym_error);
}
return (ds_create(config));
} else if (type == "memory") {
return (memoryCreateInstance(config));
} else {
......
......@@ -58,6 +58,8 @@ DataSourceClient*
createDataSourceClient(const std::string& type,
isc::data::ConstElementPtr config);
typedef DataSourceClient* ds_creator(isc::data::ConstElementPtr config);
typedef void ds_destructor();
}
}
#endif // DATA_SOURCE_FACTORY_H
......
......@@ -22,9 +22,11 @@
#include <datasrc/sqlite3_accessor.h>
#include <datasrc/logger.h>
#include <datasrc/data_source.h>
#include <datasrc/factory.h>
#include <util/filename.h>
using namespace std;
using namespace isc::data;
#define SQLITE_SCHEMA_VERSION 1
......@@ -658,5 +660,74 @@ SQLite3Accessor::deleteRecordInZone(const string (&params)[DEL_PARAM_COUNT]) {
*dbparameters_, DEL_RECORD, params, "delete record from zone");
}
namespace {
void
addError(ElementPtr errors, const std::string& error) {
if (errors != ElementPtr() && errors->getType() == Element::list) {
errors->add(Element::create(error));
}
}
} // end anonymous namespace
bool
checkConfig(ConstElementPtr config, ElementPtr errors) {
bool result = true;
if (!config || config->getType() != Element::map) {
addError(errors, "Base config for SQlite3 backend must be a map");
result = false;
} else {
if (!config->contains("file")) {
addError(errors,
"Config for SQlite3 backend does not contain a 'file' value");
result = false;
} else if (!config->get("file") ||
config->get("file")->getType() != Element::string) {
addError(errors, "file value in SQLite3 backend is not a string");
result = false;
} else if (config->get("file")->stringValue() == "") {
addError(errors, "file value in SQLite3 backend is empty");
result = false;
}
if (!config->contains("class")) {
addError(errors, "Config for SQlite3 backend does not contain a 'class' value");
result = false;
} else if (!config->get("class") ||
config->get("class")->getType() != Element::string) {
addError(errors, "class value in SQLite3 backend is not a string");
result = false;
} else {
try {
isc::dns::RRClass rrclass(config->get("class")->stringValue());
} catch (const isc::dns::InvalidRRClass& ivrc) {
addError(errors, ivrc.what());
result = false;
} catch (const isc::dns::IncompleteRRClass& icrc) {
addError(errors, icrc.what());
result = false;
}
}
}
return (result);
}
DataSourceClient *
createInstance(isc::data::ConstElementPtr config) {
ElementPtr errors(Element::createList());
if (!checkConfig(config, errors)) {
isc_throw(DataSourceConfigError, errors->str());
}
isc::dns::RRClass rrclass(config->get("class")->stringValue());
std::string dbfile = config->get("file")->stringValue();
boost::shared_ptr<DatabaseAccessor> sqlite3_accessor(
new SQLite3Accessor(dbfile, rrclass));
return (new DatabaseClient(rrclass, sqlite3_accessor));
}
void destroyInstance(DataSourceClient* instance) {
delete instance;
}
}
}
......@@ -24,6 +24,8 @@
#include <boost/scoped_ptr.hpp>
#include <string>
#include <cc/data.h>
namespace isc {
namespace dns {
class RRClass;
......@@ -187,6 +189,10 @@ private:
const std::string database_name_;
};
extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr config);
extern "C" void destroyInstance(DataSourceClient* instance);
}
}
......
......@@ -36,6 +36,9 @@ run_unittests_SOURCES += database_unittest.cc
run_unittests_SOURCES += client_unittest.cc
run_unittests_SOURCES += sqlite3_accessor_unittest.cc
run_unittests_SOURCES += factory_unittest.cc
# for the dlopened types we have tests for, we also need to include the
# sources
run_unittests_SOURCES += $(top_srcdir)/src/lib/datasrc/sqlite3_accessor.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment