add DbMgr
Change-Id: I799f6a066ef60ecd42d64de7d8d04be8996564ed
diff --git a/.waf-tools/default-compiler-flags.py b/.waf-tools/default-compiler-flags.py
index 97921e2..249ddcd 100644
--- a/.waf-tools/default-compiler-flags.py
+++ b/.waf-tools/default-compiler-flags.py
@@ -21,7 +21,7 @@
else:
defaultFlags += ['-std=c++03', '-Wno-variadic-macros', '-Wno-c99-extensions']
- defaultFlags += ['-pedantic', '-Wall', '-Wno-long-long', '-Wno-unneeded-internal-declaration']
+ defaultFlags += ['-Wall', '-Wno-long-long', '-Wno-unneeded-internal-declaration']
if conf.options.debug:
conf.define('_DEBUG', 1)
diff --git a/docs/index.rst b/docs/index.rst
index 052856e..9c11ec6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -16,6 +16,7 @@
INSTALL
ndns-packet-format
+ ndns-db-manage
manpages
**Additional documentation**
diff --git a/docs/ndns-db-manage.rst b/docs/ndns-db-manage.rst
new file mode 100644
index 0000000..84c5abb
--- /dev/null
+++ b/docs/ndns-db-manage.rst
@@ -0,0 +1,21 @@
+Database Management Hints
+=========================
+
+Pre-requisites
+--------------
+
+``sqlite3`` installed
+
+
+Create the database
+-------------------
+
+Set the attribute ``dbfile`` in the NDNS configuration file, e.g., ``${SYSCONFDIR}/ndn/ndns.conf`` (``/etc/ndn/ndns.conf``), to the desired path of the database file.
+By default, ``dbfile`` is assigned to ``${LOCALSTATEDIR}/lib/ndns/ndns.db`` (``/var/lib/ndns/ndns.db``).
+
+When NDNS started, an empty database will be automatically created.
+
+Reset the database
+------------------
+
+Remove the database file.
diff --git a/src/db/db-mgr.cpp b/src/db/db-mgr.cpp
new file mode 100644
index 0000000..27d7db4
--- /dev/null
+++ b/src/db/db-mgr.cpp
@@ -0,0 +1,112 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "db-mgr.hpp"
+#include "../logger.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+
+#include <iostream>
+#include <fstream>
+
+namespace ndn {
+namespace ndns {
+
+NDNS_LOG_INIT("DbMgr");
+
+static const std::string NDNS_SCHEMA = "\
+CREATE TABLE IF NOT EXISTS zones ( \n\
+ id INTEGER NOT NULL PRIMARY KEY, \n\
+ name blob NOT NULL UNIQUE, \n\
+ ttl integer(10) NOT NULL); \n\
+ \n\
+CREATE TABLE IF NOT EXISTS rrsets ( \n\
+ id INTEGER NOT NULL PRIMARY KEY, \n\
+ zone_id integer(10) NOT NULL, \n\
+ label blob NOT NULL, \n\
+ type blob NOT NULL, \n\
+ version blob NOT NULL, \n\
+ ttl integer(10) NOT NULL, \n\
+ data blob NOT NULL, \n\
+ FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade); \n\
+ \n\
+CREATE UNIQUE INDEX rrsets_zone_id_label_type_version \n\
+ ON rrsets (zone_id, label, type, version); \n\
+";
+
+DbMgr::DbMgr(const std::string& dbFile/* = DEFAULT_CONFIG_PATH "/" "ndns.conf"*/)
+ : m_dbFile(dbFile)
+ , m_conn(0)
+ , m_status(DB_CLOSED)
+{
+ this->open();
+}
+
+
+DbMgr::~DbMgr()
+{
+ if (m_status != DB_CLOSED) {
+ this->close();
+ }
+}
+
+void
+DbMgr::open()
+{
+ if (m_status == DB_CONNECTED)
+ return;
+
+ int res = sqlite3_open_v2(m_dbFile.c_str(), &m_conn,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+#ifdef DISABLE_SQLITE3_FS_LOCKING
+ "unix-dotfile"
+#else
+ 0
+#endif
+ );
+
+ if (res != SQLITE_OK) {
+ m_err = "Cannot open the db file: " + m_dbFile;
+ NDNS_LOG_FATAL(m_err);
+ m_status = DB_ERROR;
+ }
+
+ // ignore any errors from DB creation (command will fail for the existing database, which is ok)
+ sqlite3_exec(m_conn, NDNS_SCHEMA.c_str(), 0, 0, 0);
+
+ m_status = DB_CONNECTED;
+}
+
+void
+DbMgr::close()
+{
+ if (m_status == DB_CLOSED)
+ return;
+
+ int ret = sqlite3_close(m_conn);
+ if (ret != SQLITE_OK) {
+ m_err = "Cannot close the db: " + m_dbFile;
+ NDNS_LOG_FATAL(m_err);
+ m_status = DB_ERROR;
+ }
+ m_status = DB_CLOSED;
+}
+
+} // namespace ndns
+} // namespace ndn
diff --git a/src/db/db-mgr.hpp b/src/db/db-mgr.hpp
new file mode 100644
index 0000000..6c5eafd
--- /dev/null
+++ b/src/db/db-mgr.hpp
@@ -0,0 +1,124 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California.
+ *
+ * This file is part of NDNS (Named Data Networking Domain Name Service).
+ * See AUTHORS.md for complete list of NDNS authors and contributors.
+ *
+ * NDNS is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NDNS_DB_DB_MGR_HPP
+#define NDNS_DB_DB_MGR_HPP
+
+#include "config.hpp"
+
+#include <ndn-cxx/common.hpp>
+#include <sqlite3.h>
+
+namespace ndn {
+namespace ndns {
+
+/**
+ * @brief Database Manager, which provides some common DB functionalities
+ */
+class DbMgr : noncopyable
+{
+public:
+ /**
+ * @brief The Database Status
+ */
+ enum DbStatus {
+ DB_CONNECTED,
+ DB_CLOSED,
+ DB_ERROR
+ };
+
+public:
+ /**
+ * @brief constructor
+ */
+ explicit
+ DbMgr(const std::string& dbFile = DEFAULT_CONFIG_PATH "/" "ndns.conf");
+
+ /**
+ * @brief destructor
+ */
+ ~DbMgr();
+
+ /**
+ * @brief connect to the database
+ */
+ void
+ open();
+
+ /**
+ * @brief close the database connection
+ */
+ void
+ close();
+
+ /**
+ * @brief get error message
+ *
+ * only valid when some db-related error happens,
+ * such as db file does not exist, wrong SQL, etc
+ */
+ const std::string&
+ getErr() const
+ {
+ return m_err;
+ }
+
+ /**
+ * @brief get Database connection status
+ */
+ DbStatus
+ getStatus() const
+ {
+ return m_status;
+ }
+
+private:
+ /**
+ * @brief set error message
+ *
+ * only valid when some db-related error happens,
+ * such as db file does not exist, wrong SQL, etc
+ */
+ void
+ setErr(const std::string& err)
+ {
+ this->m_err = err;
+ }
+
+ /**
+ * @brief set Database connection status
+ */
+ void
+ setStatus(DbStatus status)
+ {
+ this->m_status = status;
+ }
+
+private:
+ std::string m_dbFile;
+ sqlite3* m_conn;
+
+ std::string m_err;
+ DbStatus m_status;
+};
+
+} // namespace ndns
+} // namespace ndn
+
+#endif // NDNS_DB_DB_MGR_HPP
diff --git a/src/zone.cpp b/src/zone.cpp
index 6f859a4..3c7fd1a 100644
--- a/src/zone.cpp
+++ b/src/zone.cpp
@@ -18,10 +18,13 @@
*/
#include "zone.hpp"
+#include "logger.hpp"
namespace ndn {
namespace ndns {
+NDNS_LOG_INIT("Zone")
+
Zone::Zone()
: m_id(0)
, m_ttl(3600)
diff --git a/tests/skeleton.cpp b/tests/unit/db/db-mgr.cpp
similarity index 72%
rename from tests/skeleton.cpp
rename to tests/unit/db/db-mgr.cpp
index afa3bde..198a851 100644
--- a/tests/skeleton.cpp
+++ b/tests/unit/db/db-mgr.cpp
@@ -17,17 +17,26 @@
* NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
-// #include ""
-#include "boost-test.hpp"
+#include "db/db-mgr.hpp"
+#include "../../boost-test.hpp"
namespace ndn {
namespace ndns {
namespace tests {
-BOOST_AUTO_TEST_SUITE(Skeleton)
+BOOST_AUTO_TEST_SUITE(DbMgr)
-BOOST_AUTO_TEST_CASE(TestCase)
+BOOST_AUTO_TEST_CASE(Basic)
{
+ ndns::DbMgr mgr(BUILDDIR "/tests/unit/db/dbmgr-ndns.db");
+ BOOST_CHECK_EQUAL(mgr.getStatus(), ndns::DbMgr::DB_CONNECTED);
+
+ mgr.close();
+ BOOST_CHECK_EQUAL(mgr.getStatus(), ndns::DbMgr::DB_CLOSED);
+
+ // reopen
+ mgr.open();
+ BOOST_CHECK_EQUAL(mgr.getStatus(), ndns::DbMgr::DB_CONNECTED);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/logger.cpp b/tests/unit/logger.cpp
similarity index 99%
rename from tests/logger.cpp
rename to tests/unit/logger.cpp
index 2352a92..100aa5b 100644
--- a/tests/logger.cpp
+++ b/tests/unit/logger.cpp
@@ -18,7 +18,7 @@
*/
#include "logger.hpp"
-#include "boost-test.hpp"
+#include "../boost-test.hpp"
#include <fstream>
diff --git a/tests/unit/zone.cpp b/tests/unit/zone.cpp
index 0a26e76..f533d2e 100644
--- a/tests/unit/zone.cpp
+++ b/tests/unit/zone.cpp
@@ -26,13 +26,12 @@
namespace ndns {
namespace tests {
+BOOST_AUTO_TEST_SUITE(Zone)
-BOOST_AUTO_TEST_SUITE(ZoneTest)
-
-BOOST_AUTO_TEST_CASE(TestCase)
+BOOST_AUTO_TEST_CASE(Basic)
{
Name zoneName("/net/ndnsim");
- Zone zone1;
+ ndns::Zone zone1;
zone1.setName(zoneName);
zone1.setId(2);
zone1.setTtl(time::seconds(4000));
@@ -41,11 +40,11 @@
BOOST_CHECK_EQUAL(zone1.getName(), zoneName);
BOOST_CHECK_EQUAL(zone1.getTtl(), time::seconds(4000));
- Zone zone2(zoneName);
+ ndns::Zone zone2(zoneName);
BOOST_CHECK_EQUAL(zone1, zone2);
BOOST_CHECK_EQUAL(zone2.getName(), zone1.getName());
- BOOST_CHECK_NE(zone1, Zone("/net/ndnsim2"));
+ BOOST_CHECK_NE(zone1, ndns::Zone("/net/ndnsim2"));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/wscript b/tests/wscript
index 383ae8c..0407962 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -1,6 +1,6 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-from waflib import Utils
+from waflib import Utils, Context
top = '..'
@@ -12,4 +12,5 @@
source=bld.path.ant_glob(['**/*.cpp']),
use='ndns-objects',
install_path=None,
+ defines="BUILDDIR=\"%s\"" % Context.out_dir,
)
diff --git a/wscript b/wscript
index 5886fc1..9c5bd1f 100644
--- a/wscript
+++ b/wscript
@@ -43,6 +43,9 @@
if not conf.options.with_sqlite_locking:
conf.define('DISABLE_SQLITE3_FS_LOCKING', 1)
+ conf.define("DEFAULT_CONFIG_PATH", "%s/ndn" % conf.env['SYSCONFDIR'])
+ conf.define("DEFAULT_DATABASE_PATH", "%s/ndn/ndns" % conf.env['LOCALSTATEDIR'])
+
conf.write_config_header('src/config.hpp')
def build (bld):