server: add read configuration file function

Change-Id: I6a3fe8208219a18e0a67b791dedb6b93d5e9caab
diff --git a/.waf-tools/boost.py b/.waf-tools/boost.py
index 911e7f9..305945a 100644
--- a/.waf-tools/boost.py
+++ b/.waf-tools/boost.py
@@ -39,9 +39,9 @@
  - boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC
    So before calling `conf.check_boost` you might want to disabling by adding:
    	conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
-   Errors: 
+   Errors:
  - boost might also be compiled with /MT, which links the runtime statically.
-   If you have problems with redefined symbols, 
+   If you have problems with redefined symbols,
 		self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
 		self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc']
 Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases.
@@ -59,7 +59,15 @@
 BOOST_VERSION_CODE = '''
 #include <iostream>
 #include <boost/version.hpp>
-int main() { std::cout << BOOST_LIB_VERSION << std::endl; }
+int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
+'''
+BOOST_SYSTEM_CODE = '''
+#include <boost/system/error_code.hpp>
+int main() { boost::system::error_code c; }
+'''
+BOOST_THREAD_CODE = '''
+#include <boost/thread.hpp>
+int main() { boost::thread t; }
 '''
 
 # toolsets from {boost_dir}/tools/build/v2/tools/common.jam
@@ -93,13 +101,13 @@
 
 def options(opt):
 	opt = opt.add_option_group('Boost Options')
-    
+
 	opt.add_option('--boost-includes', type='string',
 				   default='', dest='boost_includes',
-				   help='''path to the directory where the boost includes are, e.g., /path/to/boost_1_47_0/stage/include''')
+				   help='''path to the directory where the boost includes are, e.g., /path/to/boost_1_55_0/stage/include''')
 	opt.add_option('--boost-libs', type='string',
 				   default='', dest='boost_libs',
-				   help='''path to the directory where the boost libs are, e.g., /path/to/boost_1_47_0/stage/lib''')
+				   help='''path to the directory where the boost libs are, e.g., /path/to/boost_1_55_0/stage/lib''')
 	opt.add_option('--boost-static', action='store_true',
 				   default=False, dest='boost_static',
 				   help='link with static boost libraries (.lib/.a)')
@@ -136,11 +144,16 @@
 		except (OSError, IOError):
 			Logs.error("Could not read the file %r" % node.abspath())
 		else:
-			re_but = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.*)"', re.M)
-			m = re_but.search(txt)
-			if m:
-				return m.group(1)
-	return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True)
+			re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
+			m1 = re_but1.search(txt)
+
+			re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
+			m2 = re_but2.search(txt)
+
+			if m1 and m2:
+				return (m1.group(1), m2.group(1))
+
+	return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(":")
 
 @conf
 def boost_get_includes(self, *k, **kw):
@@ -280,8 +293,12 @@
 
 	self.start_msg('Checking boost includes')
 	self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
-	self.env.BOOST_VERSION = self.boost_get_version(inc)
-	self.end_msg(self.env.BOOST_VERSION)
+	versions = self.boost_get_version(inc)
+	self.env.BOOST_VERSION = versions[0]
+	self.env.BOOST_VERSION_NUMBER = int(versions[1])
+	self.end_msg("%d.%d.%d" % (int(versions[1]) / 100000,
+				   int(versions[1]) / 100 % 1000,
+				   int(versions[1]) % 100))
 	if Logs.verbose:
 		Logs.pprint('CYAN', '	path : %s' % self.env['INCLUDES_%s' % var])
 
@@ -301,19 +318,13 @@
 	def try_link():
 		if 'system' in params['lib']:
 			self.check_cxx(
-			 fragment="\n".join([
-			  '#include <boost/system/error_code.hpp>',
-			  'int main() { boost::system::error_code c; }',
-			 ]),
+			 fragment=BOOST_SYSTEM_CODE,
 			 use=var,
 			 execute=False,
 			)
 		if 'thread' in params['lib']:
 			self.check_cxx(
-			 fragment="\n".join([
-			  '#include <boost/thread.hpp>',
-			  'int main() { boost::thread t; }',
-			 ]),
+			 fragment=BOOST_THREAD_CODE,
 			 use=var,
 			 execute=False,
 			)
@@ -365,4 +376,3 @@
 			self.end_msg("Could not link against boost libraries using supplied options")
 			self.fatal('The configuration failed')
 		self.end_msg('ok')
-
diff --git a/.waf-tools/default-compiler-flags.py b/.waf-tools/default-compiler-flags.py
index bdc4065..167e88a 100644
--- a/.waf-tools/default-compiler-flags.py
+++ b/.waf-tools/default-compiler-flags.py
@@ -1,40 +1,49 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+#
+# Copyright (c) 2014, Regents of the University of California
+#
+# GPL 3.0 license, see the COPYING.md file for more information
 
 from waflib import Logs, Configure
 
+def options(opt):
+    opt.add_option('--with-c++11', action='store_true', default=False, dest='use_cxx11',
+                   help='''Enable C++11 mode (experimental, may not work)''')
+    opt.add_option('--debug', '--with-debug', action='store_true', default=False, dest='debug',
+                   help='''Compile in debugging mode without all optimizations (-O0)''')
+
 def configure(conf):
     areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
+    defaultFlags = []
+
+    if conf.options.use_cxx11:
+        defaultFlags += ['-std=c++0x', '-std=c++11']
+    else:
+        defaultFlags += ['-std=c++03']
+
+    defaultFlags += ['-pedantic', '-Wall', '-Wno-long-long']
+
     if conf.options.debug:
         conf.define('_DEBUG', 1)
-        defaultFlags = ['-O0', '-g3',
-                        '-Werror',
-                        '-Wall',
-                        '-fcolor-diagnostics', # only clang supports
-
-                        # to disable known warnings
-                        '-Wno-unused-variable', # cryptopp
-                        '-Wno-unused-function',
-                        '-Wno-deprecated-declarations',
+        defaultFlags += ['-O0',
+                         '-Og', # gcc >= 4.8
+                         '-g3',
+                         '-fcolor-diagnostics', # clang
+                         '-fdiagnostics-color', # gcc >= 4.9
+                         '-Werror'
                         ]
-
         if areCustomCxxflagsPresent:
             missingFlags = [x for x in defaultFlags if x not in conf.env.CXXFLAGS]
             if len(missingFlags) > 0:
                 Logs.warn("Selected debug mode, but CXXFLAGS is set to a custom value '%s'"
-                           % " ".join(conf.env.CXXFLAGS))
+                          % " ".join(conf.env.CXXFLAGS))
                 Logs.warn("Default flags '%s' are not activated" % " ".join(missingFlags))
         else:
-            conf.add_supported_cxxflags(cxxflags = defaultFlags)
+            conf.add_supported_cxxflags(defaultFlags)
     else:
-        defaultFlags = ['-O2', '-g', '-Wall',
-
-                        # to disable known warnings
-                        '-Wno-unused-variable', # cryptopp
-                        '-Wno-unused-function',
-                        '-Wno-deprecated-declarations',
-                        ]
+        defaultFlags += ['-O2', '-g']
         if not areCustomCxxflagsPresent:
-            conf.add_supported_cxxflags(cxxflags = defaultFlags)
+            conf.add_supported_cxxflags(defaultFlags)
 
 @Configure.conf
 def add_supported_cxxflags(self, cxxflags):
@@ -45,8 +54,8 @@
 
     supportedFlags = []
     for flag in cxxflags:
-        if self.check_cxx (cxxflags=[flag], mandatory=False):
+        if self.check_cxx(cxxflags=[flag], mandatory=False):
             supportedFlags += [flag]
 
-    self.end_msg (' '.join (supportedFlags))
-    self.env.CXXFLAGS += supportedFlags
+    self.end_msg(' '.join(supportedFlags))
+    self.env.CXXFLAGS = supportedFlags + self.env.CXXFLAGS
diff --git a/AUTHORS b/AUTHORS
index 70d7af0..c4c1781 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,4 @@
-Shuo Chen <chenatu2006@gmail.com>
-Alexander Afanasyev (http://lasr.cs.ucla.edu/afanasyev/index.html)
-
+Shuo Chen           <chenatu2006@gmail.com>
+Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+Junxiao Shi         <http://www.cs.arizona.edu/people/shijunxiao/>
+Hang Zhang          <http://netlab.bit.edu.cn/z_hang>
diff --git a/INSTALL.md b/INSTALL.md
index f53beaf..64252fd 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,17 +1,14 @@
-ndn-repo:  A basic version of NDN repository
-===========================================================================
+ndn-repo-ng:  Next generation of NDN repository
+===============================================
 
 Prerequisites
 -------------
 
-Required: 
+Required:
 
-* libcrypto
-* libsqlite3 
-* libcrypto++
-* boost libraries
-* [NDN-CPP](https://github.com/cawka/ndn-cpp)
-* OSX Security framework (on OSX platform only)
+* [ndn-cpp-dev and its dependencies](https://github.com/named-data/ndn-cpp-dev)
+* sqlite3
+* Boost libraries
 
 Build
 -----
@@ -24,16 +21,5 @@
 
 This makes and installs the following items:
 
-If configured with tests: ``./waf configure --test``), the above commands will
-also produce test programs in ./build/test directory
-
-Supported platforms
--------------------
-
-(to be confirmed)
-
-NDN-CPP is tested on the following platforms:
-Ubuntu 12.04 (64 bit and 32 bit) (gcc 4.6.3)
-Ubuntu 13.04 (64 bit) (gcc 4.7.3)
-Mac OS X 10.8.4 (clang 4.2)
-Mac OS X 10.8.4 (gcc 4.2)
+If configured with tests: `./waf configure --with-tests`), the above commands will
+also generate unit tests in `./built/unit-tests`
diff --git a/README.md b/README.md
index 349e0d3..e5ce613 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,20 @@
-ndn-repo:  A basic version of NDN repository
----------------------------------------------------------------------------
+ndn-repo-ng: Next generation of NDN repository
+==============================================
 
-ndn_repo is an implementation of a Named Data Networking data repository.
-The ndn_repo follows Repo protocol of NDN. The specification of repo protocol is:
+**ndn-repo-ng** is an implementation of a Named Data Networking data repository.  The
+**ndn-repo-ng** follows Repo protocol of NDN. The specification of repo protocol is:
 
-http://redmine.named-data.net/projects/repo-ng/wiki
+* http://redmine.named-data.net/projects/repo-ng/wiki
 
-ndn_repo uses [NDN-CPP-dev](https://github.com/cawka/ndn-cpp) library as NDN development library, and uses sqlite3 as underlying storage.
+**ndn-repo-ng** uses [ndn-cpp-dev](https://github.com/cawka/ndn-cpp) library as NDN
+development library, and uses sqlite3 as underlying storage.
 
-The security model and access control have not been decided in current version. The insertion and deletion commands are signed interests, but they can all be validated.
-	
-ndn_repo is open source under a license described in the file COPYING.  While the license
-does not require it, we really would appreciate it if others would share their
-contributions to the library if they are willing to do so under the same license. 
+**ndn-repo-ng** is open source under a license described in the file COPYING.  While the
+license does not require it, we really would appreciate it if others would share their
+contributions to the library if they are willing to do so under the same license.
 
-See the file INSTALL for build and install instructions.
+See the file `INSTALL.md` for build and install instructions.
 
-Please submit any bugs or issues to the ndn_repo issue tracker:
+Please submit any bugs or issues to the **ndn-repo-ng** issue tracker:
 
-http://redmine.named-data.net/projects/repo-ng/issues
-
-
+* http://redmine.named-data.net/projects/repo-ng/issues
diff --git a/ndn-handle/base-handle.cpp b/ndn-handle/base-handle.cpp
index b932ebd..dcebdfb 100644
--- a/ndn-handle/base-handle.cpp
+++ b/ndn-handle/base-handle.cpp
@@ -16,4 +16,4 @@
   return dist(gen);
 }
 
-}
\ No newline at end of file
+}
diff --git a/ndn-handle/delete-handle.cpp b/ndn-handle/delete-handle.cpp
index 8e1130c..ba9619b 100644
--- a/ndn-handle/delete-handle.cpp
+++ b/ndn-handle/delete-handle.cpp
@@ -88,7 +88,7 @@
 void
 DeleteHandle::listen(const Name& prefix)
 {
-  getFace().setInterestFilter(prefix,
+  getFace().setInterestFilter(Name(prefix).append("delete"),
                               bind(&DeleteHandle::onInterest, this, _1, _2),
                               bind(&DeleteHandle::onRegisterFailed, this, _1, _2));
 }
diff --git a/repo-ng.conf.sample b/repo-ng.conf.sample
new file mode 100644
index 0000000..24350a5
--- /dev/null
+++ b/repo-ng.conf.sample
@@ -0,0 +1,39 @@
+repo
+{
+  ; Section defining list of Data prefixes to register
+  ; Only 'prefix' option is allowed here, which can be repeated multiple times
+  data
+  {
+    prefix "ndn:/example/data/1"
+    prefix "ndn:/example/data/2"
+  }
+
+  ; Section defining list of command prefixes (to insert or delete Data) to register.
+  ; Only 'prefix' option is allowed here, which can be repeated multiple times
+  command
+  {
+    prefix "ndn:/example/repo/1"
+    prefix "ndn:/example/repo/2"
+  }
+
+  ; Section to specify where data should be stored
+  ; Right now only a single 'sqlite' option is allowed:
+  storage
+  {
+    method "sqlite"             ; Currently, only sqlite storage engine is supported
+    path "/var/db/ndn-repo-ng"  ; path to repo-ng storage folder
+  }
+
+  ; Section to enable TCP bulk insert capability
+  ; If section is present, then TCP bulk insert is enabled (empty section enables
+  ; TCP bulk insert to listen on "localhost:7376")
+  tcp_bulk_insert {
+    ; host "localhost"  ; Set to listen on different IP address or hostname
+    ; port 7376  ; Set to listen on different port number
+  }
+
+  validator
+  {
+    policy "not implemented yet"
+  }
+}
\ No newline at end of file
diff --git a/server/repo.cpp b/server/repo.cpp
new file mode 100644
index 0000000..0c3165a
--- /dev/null
+++ b/server/repo.cpp
@@ -0,0 +1,157 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "repo.hpp"
+
+namespace repo {
+
+RepoConfig
+parseConfig(const std::string& configPath)
+{
+  if (configPath.empty()) {
+    std::cerr << "configuration file path is empty" << std::endl;
+  }
+
+  std::ifstream fin(configPath.c_str());
+  if (!fin.is_open())
+    throw Repo::Error("failed to open configuration file '"+ configPath +"'");
+
+  using namespace boost::property_tree;
+  ptree propertyTree;
+  try {
+    read_info(fin, propertyTree);
+  }
+  catch (ptree_error& e) {
+    throw Repo::Error("failed to read configuration file '"+ configPath +"'");
+  }
+
+  ptree repoConf = propertyTree.get_child("repo");
+
+  RepoConfig repoConfig;
+
+  ptree dataConf = repoConf.get_child("data");
+
+  for (ptree::const_iterator it = dataConf.begin();
+       it != dataConf.end();
+       ++it)
+  {
+    if (it->first == "prefix")
+      repoConfig.dataPrefixes.push_back(Name(it->second.get_value<std::string>()));
+    else
+      throw Repo::Error("Unrecognized '" + it->first + "' option in 'data' section in "
+                        "configuration file '"+ configPath +"'");
+  }
+
+  ptree commandConf = repoConf.get_child("command");
+  for (ptree::const_iterator it = commandConf.begin();
+       it != commandConf.end();
+       ++it)
+  {
+    if (it->first == "prefix")
+      repoConfig.repoPrefixes.push_back(Name(it->second.get_value<std::string>()));
+    else
+      throw Repo::Error("Unrecognized '" + it->first + "' option in 'command' section in "
+                        "configuration file '"+ configPath +"'");
+  }
+
+  ptree tcpBulkInsert = repoConf.get_child("tcp_bulk_insert");
+  bool isTcpBulkEnabled = false;
+  std::string host = "localhost";
+  std::string port = "7376";
+  for (ptree::const_iterator it = tcpBulkInsert.begin();
+       it != tcpBulkInsert.end();
+       ++it)
+  {
+    isTcpBulkEnabled = true;
+
+    // tcp_bulk_insert {
+    //   host "localhost"  ; IP address or hostname to listen on
+    //   port 7635  ; Port number to listen on
+    // }
+    if (it->first == "host") {
+      host = it->second.get_value<std::string>();
+    }
+    else if (it->first == "port") {
+      port = it->second.get_value<std::string>();
+    }
+    else
+      throw Repo::Error("Unrecognized '" + it->first + "' option in 'tcp_bulk_insert' section in "
+                        "configuration file '"+ configPath +"'");
+  }
+  if (isTcpBulkEnabled) {
+    repoConfig.tcpBulkInsertEndpoints.push_back(std::make_pair(host, port));
+  }
+
+  if (repoConf.get<std::string>("storage.method") != "sqlite")
+    throw Repo::Error("Only 'sqlite' storage method is supported");
+
+  repoConfig.dbPath = repoConf.get<std::string>("storage.path");
+
+  repoConfig.validatorNode = repoConf.get_child("validator");
+  return repoConfig;
+}
+
+inline static void
+NullDeleter(boost::asio::io_service* variable)
+{
+  // do nothing
+}
+
+Repo::Repo(boost::asio::io_service& ioService, const RepoConfig& config)
+  : m_config(config)
+  , m_scheduler(ioService)
+  , m_face(shared_ptr<boost::asio::io_service>(&ioService, &NullDeleter))
+  , m_storageHandle(openStorage(config))
+  , m_readHandle(m_face, *m_storageHandle, m_keyChain, m_scheduler)
+  , m_writeHandle(m_face, *m_storageHandle, m_keyChain, m_scheduler, m_validator)
+  , m_deleteHandle(m_face, *m_storageHandle, m_keyChain, m_scheduler, m_validator)
+  , m_tcpBulkInsertHandle(ioService, *m_storageHandle)
+
+{
+  //Trust model not implemented, this is just an empty validator
+  //@todo add a function to parse RepoConfig.validatorNode and define the trust model
+  m_validator.addInterestRule("^<>",
+                              *m_keyChain.
+                              getCertificate(m_keyChain.getDefaultCertificateName()));
+}
+
+shared_ptr<StorageHandle>
+Repo::openStorage(const RepoConfig& config)
+{
+  shared_ptr<StorageHandle> storageHandle = ndn::make_shared<SqliteHandle>(config.dbPath);
+  return storageHandle;
+}
+
+void
+Repo::enableListening()
+{
+  // Enable "listening" on Data prefixes
+  for (vector<ndn::Name>::iterator it = m_config.dataPrefixes.begin();
+       it != m_config.dataPrefixes.end();
+       ++it)
+    {
+      m_readHandle.listen(*it);
+    }
+
+  // Enable "listening" on control prefixes
+  for (vector<ndn::Name>::iterator it = m_config.repoPrefixes.begin();
+       it != m_config.repoPrefixes.end();
+       ++it)
+    {
+      m_writeHandle.listen(*it);
+      m_deleteHandle.listen(*it);
+    }
+
+  // Enable listening on TCP bulk insert addresses
+  for (vector<pair<string, string> >::iterator it = m_config.tcpBulkInsertEndpoints.begin();
+       it != m_config.tcpBulkInsertEndpoints.end();
+       ++it)
+    {
+      m_tcpBulkInsertHandle.listen(it->first, it->second);
+    }
+}
+
+} // namespace repo
diff --git a/server/repo.hpp b/server/repo.hpp
new file mode 100644
index 0000000..d5cb653
--- /dev/null
+++ b/server/repo.hpp
@@ -0,0 +1,86 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef REPO_SERVER_REPO_HPP
+#define REPO_SERVER_REPO_HPP
+
+#include "../storage/storage-handle.hpp"
+#include "../storage/sqlite/sqlite-handle.hpp"
+#include "../ndn-handle/read-handle.hpp"
+#include "../ndn-handle/write-handle.hpp"
+#include "../ndn-handle/delete-handle.hpp"
+#include "../ndn-handle/tcp-bulk-insert-handle.hpp"
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <ndn-cpp-dev/face.hpp>
+#include <ndn-cpp-dev/util/command-interest-validator.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/info_parser.hpp>
+
+namespace repo {
+
+using std::string;
+using std::vector;
+using std::pair;
+
+struct RepoConfig
+{
+  //StorageMethod storageMethod; This will be implemtented if there is other method.
+  std::string dbPath;
+  vector<ndn::Name> dataPrefixes;
+  vector<ndn::Name> repoPrefixes;
+  vector<pair<string, string> > tcpBulkInsertEndpoints;
+
+  //@todo validator should be configured in config file
+  boost::property_tree::ptree validatorNode;
+};
+
+RepoConfig
+parseConfig(const std::string& confPath);
+
+class Repo : noncopyable
+{
+
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+public:
+  Repo(boost::asio::io_service& ioService, const RepoConfig& config);
+
+  void
+  enableListening();
+
+private:
+  static shared_ptr<StorageHandle>
+  openStorage(const RepoConfig& config);
+
+private:
+  RepoConfig m_config;
+  ndn::Scheduler m_scheduler;
+  ndn::Face m_face;
+  shared_ptr<StorageHandle> m_storageHandle;
+  KeyChain m_keyChain;
+  CommandInterestValidator m_validator;
+  ReadHandle m_readHandle;
+  WriteHandle m_writeHandle;
+  DeleteHandle m_deleteHandle;
+  TcpBulkInsertHandle m_tcpBulkInsertHandle;
+};
+
+} // namespace repo
+
+#endif // REPO_SERVER_REPO_HPP
diff --git a/server/server.cpp b/server/server.cpp
index b577be0..1adc68f 100644
--- a/server/server.cpp
+++ b/server/server.cpp
@@ -4,80 +4,79 @@
  * See COPYING for copyright and distribution information.
  */
 
-#include <string>
-#include <iostream>
-#include <ndn-cpp-dev/face.hpp>
-#include <ndn-cpp-dev/util/command-interest-validator.hpp>
-
-#include "../storage/storage-handle.hpp"
-#include "../storage/sqlite/sqlite-handle.hpp"
-#include "../ndn-handle/read-handle.hpp"
-#include "../ndn-handle/write-handle.hpp"
-#include "../ndn-handle/tcp-bulk-insert-handle.hpp"
-#include "../ndn-handle/delete-handle.hpp"
+#include "config.hpp"
+#include "repo.hpp"
 
 using namespace repo;
 
 static const string ndnRepoUsageMessage =
-  "ndn-repo - NDNx Repository Daemon\n"
-  "-d: set database path\n"
+  /* argv[0] */ " - Next generation of NDN repository\n"
   "-h: show help message\n"
   "-c: set config file path\n"
   ;
 
+void
+terminate(boost::asio::io_service& ioService,
+          const boost::system::error_code& error,
+          int signalNo,
+          boost::asio::signal_set& signalSet)
+{
+  if (error)
+    return;
+
+  if (signalNo == SIGINT ||
+      signalNo == SIGTERM)
+    {
+      ioService.stop();
+      std::cout << "Caught signal '" << strsignal(signalNo) << "', exiting..." << std::endl;
+    }
+  else
+    {
+      /// \todo May be try to reload config file
+      signalSet.async_wait(bind(&terminate, boost::ref(ioService), _1, _2,
+                                boost::ref(signalSet)));
+    }
+}
+
 int
-main(int argc, char** argv) {
+main(int argc, char** argv)
+{
+  string configPath = DEFAULT_CONFIG_FILE;
   int opt;
-  string dbPath;
-  string confPath;
-  while ((opt = getopt(argc, argv, "d:hc:")) != -1) {
+  while ((opt = getopt(argc, argv, "hc:")) != -1) {
     switch (opt) {
-    case 'd':
-      dbPath = string(optarg);
-      break;
     case 'h':
-      std::cout << ndnRepoUsageMessage << std::endl;
+      std::cout << argv[0] << ndnRepoUsageMessage << std::endl;
       return 1;
     case 'c':
-      confPath = string(optarg);
+      configPath = string(optarg);
       break;
     default:
       break;
     }
   }
 
-  if (confPath.empty()) {
-    confPath = "./repo.conf";
+  try {
+    boost::asio::io_service ioService;
+    Repo repoInstance(ioService, parseConfig(configPath));
+
+    boost::asio::signal_set signalSet(ioService);
+    signalSet.add(SIGINT);
+    signalSet.add(SIGTERM);
+    signalSet.add(SIGHUP);
+    signalSet.add(SIGUSR1);
+    signalSet.add(SIGUSR2);
+    signalSet.async_wait(bind(&terminate, boost::ref(ioService), _1, _2,
+                              boost::ref(signalSet)));
+
+    repoInstance.enableListening();
+
+    ioService.run();
+  }
+  catch (const std::exception& e) {
+    std::cerr << "ERROR: " << e.what() << std::endl;
+    return 2;
   }
 
-  Name dataPrefix("ndn:/");
-  Name repoPrefix("ndn:/example/repo");
-  /// @todo read from configuration
-
-  SqliteHandle sqliteHandle(dbPath);
-
-  shared_ptr<boost::asio::io_service> io =
-    ndn::make_shared<boost::asio::io_service>();
-
-  Face face(io);
-  Scheduler scheduler(*io);
-
-  /// @todo specify trust model
-  CommandInterestValidator validator;
-  KeyChain keyChain;
-
-  ReadHandle readHandle(face, sqliteHandle, keyChain, scheduler);
-  readHandle.listen(dataPrefix);
-
-  WriteHandle writeHandle(face, sqliteHandle, keyChain, scheduler, validator);
-  writeHandle.listen(repoPrefix);
-
-  DeleteHandle deleteHandle(face, sqliteHandle, keyChain, scheduler, validator);
-  deleteHandle.listen(repoPrefix);
-
-  TcpBulkInsertHandle tcpBulkInsertHandle(*io, sqliteHandle);
-  tcpBulkInsertHandle.listen("localhost", "7376");
-
-  face.processEvents();
   return 0;
 }
diff --git a/storage/sqlite/sqlite-handle.cpp b/storage/sqlite/sqlite-handle.cpp
index 2c872e4..9883146 100644
--- a/storage/sqlite/sqlite-handle.cpp
+++ b/storage/sqlite/sqlite-handle.cpp
@@ -4,7 +4,9 @@
  * See COPYING for copyright and distribution information.
  */
 
+#include "config.hpp"
 #include "sqlite-handle.hpp"
+#include <boost/filesystem.hpp>
 
 namespace repo {
 
@@ -17,6 +19,14 @@
     m_dbPath = string("ndn_repo.db");
   }
   else {
+    boost::filesystem::path fsPath(dbPath);
+    boost::filesystem::file_status fsPathStatus = boost::filesystem::status(fsPath);
+    if (!boost::filesystem::is_directory(fsPathStatus)) {
+      if (!boost::filesystem::create_directory(boost::filesystem::path(fsPath))) {
+        throw Error("Folder '" + dbPath + "' does not exists and cannot be created");
+      }
+    }
+
     m_dbPath = dbPath + "/ndn_repo.db";
   }
   initializeRepo();
@@ -26,7 +36,16 @@
 SqliteHandle::initializeRepo()
 {
   char* errMsg = 0;
-  int rc = sqlite3_open(m_dbPath.c_str(), &m_db);
+
+  int rc = sqlite3_open_v2(m_dbPath.c_str(), &m_db,
+                           SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+#ifdef DISABLE_SQLITE3_FS_LOCKING
+                           "unix-dotfile"
+#else
+                           0
+#endif
+                           );
+
   if (rc == SQLITE_OK) {
     sqlite3_exec(m_db, "CREATE TABLE NDN_REPO ("
                       "name BLOB PRIMARY KEY, "
diff --git a/tests/sqlite-fixture.hpp b/tests/sqlite-fixture.hpp
index b370f20..80c10e1 100644
--- a/tests/sqlite-fixture.hpp
+++ b/tests/sqlite-fixture.hpp
@@ -20,13 +20,6 @@
 public:
   SqliteFixture()
   {
-    boost::filesystem::path testPath("unittestdb");
-    boost::filesystem::file_status testPathStatus = boost::filesystem::status(testPath);
-    if (!boost::filesystem::is_directory(testPathStatus)) {
-      if (!boost::filesystem::create_directory(boost::filesystem::path(testPath))) {
-        BOOST_FAIL("Cannot create unittestdb folder");
-      }
-    }
     handle = new SqliteHandle("unittestdb");
   }
 
diff --git a/wscript b/wscript
index 9beb207..3a67d9a 100644
--- a/wscript
+++ b/wscript
@@ -8,10 +8,8 @@
     opt.load('compiler_c compiler_cxx gnu_dirs')
     opt.load('boost default-compiler-flags doxygen', tooldir=['.waf-tools'])
 
-    ropt = opt.add_option_group('NDN Repo Options')
+    ropt = opt.add_option_group('ndn-repo-ng Options')
 
-    ropt.add_option('--debug',action = 'store_true',default = False,dest = 'debug',
-                    help='''debugging mode''')
     ropt.add_option('--with-tests', action = 'store_true', default=False, dest = 'with_tests',
                     help = '''build unit tests''')
 
@@ -43,6 +41,11 @@
     except:
         pass
 
+    conf.define('DEFAULT_CONFIG_FILE', '%s/ndn/repo-ng.conf' % conf.env['SYSCONFDIR'])
+
+    if not conf.options.with_sqlite_locking:
+        conf.define('DISABLE_SQLITE3_FS_LOCKING', 1)
+
     conf.write_config_header('config.hpp')
 
 def build(bld):
@@ -51,12 +54,14 @@
         features = ["cxx"],
         source = bld.path.ant_glob(['ndn-handle/*.cpp',
                                     'storage/**/*.cpp',
-                                    'helpers/*.cpp']),
+                                    'helpers/*.cpp',
+                                    'server/*.cpp'],
+                                    excl=['server/server.cpp']),
         use = 'NDNCPPDEV BOOST SQLITE3',
         includes = ".",
         )
 
-    bld(target = "ndn-repo",
+    bld(target = "ndn-repo-ng",
         features = ["cxx", "cxxprogram"],
         source = bld.path.ant_glob(['server/server.cpp']),
         use = 'ndn-repo-objects',
@@ -66,3 +71,5 @@
     # Unit tests
     if bld.env['WITH_TESTS']:
         bld.recurse('tests')
+
+    bld.install_files('${SYSCONFDIR}/ndn', 'repo-ng.conf.sample')