Browse Source

[1206] some functionality for config

Jelte Jansen 13 years ago
parent
commit
8f9f4ece76
2 changed files with 101 additions and 9 deletions
  1. 73 7
      src/lib/datasrc/factory.cc
  2. 28 2
      src/lib/datasrc/factory.h

+ 73 - 7
src/lib/datasrc/factory.cc

@@ -19,22 +19,88 @@
 #include "sqlite3_accessor.h"
 #include "memory_datasrc.h"
 
+using namespace isc::data;
+using namespace isc::datasrc;
+
+namespace {
+// This initial implementation hard codes specific details. These functions
+// should be moved to their corresponding backend libs if we plan on making
+// them dynamically loadable
+
+void
+addError(ElementPtr errors, const std::string& error) {
+    if (errors != ElementPtr() && errors->getType() == Element::list) {
+        errors->add(Element::create(error));
+    }
+}
+
+bool
+sqlite3CheckConfig(ConstElementPtr config, ElementPtr errors) {
+    bool result = true;
+    if (config->getType() != Element::map) {
+        addError(errors, "Base config for SQlite3 backend must be a map");
+        result = false;
+        if (!config->contains("file")) {
+            addError(errors,
+                     "Config for SQlite3 backend does not contain a 'file' value");
+            result = false;
+        } else if (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")->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 *
+sqlite3CreateInstance(isc::data::ConstElementPtr config) {
+    ElementPtr errors;
+    if (!sqlite3CheckConfig(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));
+}
+
+} // end anonymous namespace
+
 namespace isc {
 namespace datasrc {
 
-boost::shared_ptr<DataSourceClient>
+DataSourceClient *
 createDataSourceClient(const std::string& type,
-                       const isc::dns::RRClass& rrclass,
                        isc::data::ConstElementPtr config) {
     // For now, mapping hardcoded
     // config is assumed to be ok
     if (type == "sqlite3") {
-        boost::shared_ptr<DatabaseAccessor> sqlite3_accessor(
-            new SQLite3Accessor(config->get("dbfile")->stringValue(), rrclass));
-        return boost::shared_ptr<DataSourceClient>(
-            new DatabaseClient(rrclass, sqlite3_accessor));
+        return (sqlite3CreateInstance(config));
     } else if (type == "memory") {
-        return boost::shared_ptr<DataSourceClient>(new InMemoryClient());
+        return (new InMemoryClient());
     } else {
         isc_throw(DataSourceError, "Unknown datasource type: " << type);
     }

+ 28 - 2
src/lib/datasrc/factory.h

@@ -21,15 +21,41 @@
 //#include <exceptions/exceptions.h>
 
 #include <datasrc/client.h>
+#include <exceptions/exceptions.h>
 
 #include <cc/data.h>
 
 namespace isc {
 namespace datasrc {
 
-boost::shared_ptr<DataSourceClient>
+/// \brief Raised if the given config contains bad data
+///
+/// Depending on the datasource type, the configuration may differ (for
+/// instance, the sqlite3 datasource needs a database file).
+class DataSourceConfigError : public isc::Exception {
+public:
+    DataSourceConfigError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// \brief Create a datasource instance
+///
+/// This function is a fixed generator for datasource instances of all types.
+///
+/// Currently, the different types are hardcoded in the implementation of this
+/// function. However, we plan on making it more flexible, possibly through
+/// th
+///
+/// \note This function returns a raw pointer. The caller is expected to
+///       delete this pointer again. We don't return any specific smart
+///       pointer for flexibility. However, we highly advice that the
+///       return value of this function is directly put into a shared or
+///       scoped pointer.
+///
+/// \exception DataSourceConfigError if the given configuration values are
+///            bad for the given datasource type
+DataSourceClient*
 createDataSourceClient(const std::string& type,
-                       const isc::dns::RRClass& rrclass,
                        isc::data::ConstElementPtr config);
 
 }