Remove dependency on Selectors and refactor codebase.

Change-Id: Ic3024b76ba0eea61f790c91c36090b4aa68702a3
Refs: #4522
diff --git a/examples/data-producer.cpp b/examples/data-producer.cpp
index 92dedd3..f81ab03 100644
--- a/examples/data-producer.cpp
+++ b/examples/data-producer.cpp
@@ -110,12 +110,10 @@
 Publisher::run()
 {
   if (mode == AUTO) {
-    m_scheduler.scheduleEvent(timeInterval,
-                            bind(&Publisher::autoGenerate, this));
+    m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::autoGenerate, this));
   }
   else {
-    m_scheduler.scheduleEvent(timeInterval,
-                              bind(&Publisher::generateFromFile, this));
+    m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::generateFromFile, this));
   }
   m_face.processEvents(duration);
 }
@@ -126,10 +124,8 @@
   Name name = dataPrefix;
   name.appendNumber(m_range());
   std::shared_ptr<Data> data = createData(name);
-  // std::cout<<"data name = "<<data->getName()<<std::endl;
   m_face.put(*data);
-  m_scheduler.scheduleEvent(timeInterval,
-                            bind(&Publisher::autoGenerate, this));
+  m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::autoGenerate, this));
 }
 
 void
@@ -143,8 +139,7 @@
   getline(insertStream, name);
   std::shared_ptr<Data> data = createData(Name(name));
   m_face.put(*data);
-  m_scheduler.scheduleEvent(timeInterval,
-                            bind(&Publisher::generateFromFile, this));
+  m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::generateFromFile, this));
 }
 
 std::shared_ptr<Data>
@@ -206,7 +201,7 @@
         generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg));
       }
       catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-s option should be an integer.";
+        std::cerr << "-s option should be an integer" << std::endl;;
         return 1;
       }
       break;
@@ -215,7 +210,7 @@
         generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg));
       }
       catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-t option should be an integer.";
+        std::cerr << "-t option should be an integer" << std::endl;;
         return 1;
       }
       break;
diff --git a/src/common.hpp b/src/common.hpp
index bea3ddb..1a862d0 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -22,12 +22,11 @@
 
 #include "config.hpp"
 
+#include <ndn-cxx/data.hpp>
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/interest.hpp>
-#include <ndn-cxx/name.hpp>
-#include <ndn-cxx/data.hpp>
-#include <ndn-cxx/selectors.hpp>
 #include <ndn-cxx/key-locator.hpp>
+#include <ndn-cxx/name.hpp>
 #include <ndn-cxx/security/v2/key-chain.hpp>
 #include <ndn-cxx/security/v2/validator.hpp>
 #include <ndn-cxx/security/validator-config.hpp>
@@ -55,11 +54,10 @@
 
 using ndn::Face;
 using ndn::Block;
+using ndn::operator ""_block;
 using ndn::Name;
 namespace name = ndn::name;
 using ndn::Interest;
-using ndn::Selectors;
-using ndn::Exclude;
 using ndn::Data;
 using ndn::KeyLocator;
 using ndn::Scheduler;
@@ -68,12 +66,6 @@
 using ndn::security::v2::ValidationError;
 using ndn::security::ValidatorConfig;
 
-using std::shared_ptr;
-using std::make_shared;
-using std::bind;
-using std::placeholders::_1;
-using std::placeholders::_2;
-
 using boost::noncopyable;
 
 typedef uint64_t ProcessId;
diff --git a/src/extended-error-message.hpp b/src/extended-error-message.hpp
new file mode 100644
index 0000000..217bf81
--- /dev/null
+++ b/src/extended-error-message.hpp
@@ -0,0 +1,51 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2018, Regents of the University of California.
+ *
+ * This file is part of NDN repo-ng (Next generation of NDN repository).
+ * See AUTHORS.md for complete list of repo-ng authors and contributors.
+ *
+ * repo-ng 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.
+ *
+ * repo-ng 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
+ * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef REPO_EXTENDED_ERROR_MESSAGE_HPP
+#define REPO_EXTENDED_ERROR_MESSAGE_HPP
+
+#include <boost/exception/get_error_info.hpp>
+#include <sstream>
+
+namespace repo {
+
+template<typename E>
+std::string
+getExtendedErrorMessage(const E& exception)
+{
+  std::ostringstream errorMessage;
+  errorMessage << exception.what();
+
+  const char* const* file = boost::get_error_info<boost::throw_file>(exception);
+  const int* line = boost::get_error_info<boost::throw_line>(exception);
+  const char* const* func = boost::get_error_info<boost::throw_function>(exception);
+  if (file && line) {
+    errorMessage << " [from " << *file << ":" << *line;
+    if (func) {
+      errorMessage << " in " << *func;
+    }
+    errorMessage << "]";
+  }
+
+  return errorMessage.str();
+}
+
+} // namespace repo
+
+#endif // REPO_EXTENDED_ERROR_MESSAGE_HPP
\ No newline at end of file
diff --git a/src/handles/command-base-handle.cpp b/src/handles/command-base-handle.cpp
index 1717839..8f2c6d0 100644
--- a/src/handles/command-base-handle.cpp
+++ b/src/handles/command-base-handle.cpp
@@ -32,7 +32,7 @@
 static ndn::optional<std::string>
 getSignerFromTag(const ndn::Interest& interest)
 {
-  shared_ptr<SignerTag> signerTag = interest.getTag<SignerTag>();
+  std::shared_ptr<SignerTag> signerTag = interest.getTag<SignerTag>();
   if (signerTag == nullptr) {
     return ndn::nullopt;
   }
@@ -62,13 +62,10 @@
 
       auto signer1 = getSignerFromTag(request);
       std::string signer = signer1.value_or("*");
-      //_LOG_DEBUG("accept " << request->getName() << " signer=" << signer);
       accept(signer);
     },
     [reject] (const ndn::Interest& request,
               const ndn::security::v2::ValidationError& error) {
-      //_LOG_DEBUG("reject " << request->getName() << " signer=" <<
-      //              getSignerFromTag(*request).value_or("?") << ' ' << failureInfo);
       reject(ndn::mgmt::RejectReply::STATUS403);
     });
   };
diff --git a/src/handles/delete-handle.cpp b/src/handles/delete-handle.cpp
index dc0f5f1..c892583 100644
--- a/src/handles/delete-handle.cpp
+++ b/src/handles/delete-handle.cpp
@@ -19,8 +19,12 @@
 
 #include "delete-handle.hpp"
 
+#include <ndn-cxx/util/logger.hpp>
+
 namespace repo {
 
+NDN_LOG_INIT(repo.DeleteHandle);
+
 DeleteHandle::DeleteHandle(Face& face, RepoStorage& storageHandle,
                            ndn::mgmt::Dispatcher& dispatcher, Scheduler& scheduler,
                            Validator& validator)
@@ -40,12 +44,6 @@
 {
   const RepoCommandParameter& repoParameter = dynamic_cast<const RepoCommandParameter&>(parameter);
 
-  if (repoParameter.hasSelectors()) {
-    //choose data with selector and delete it
-    processSelectorDeleteCommand(interest, repoParameter, done);
-    return;
-  }
-
   if (!repoParameter.hasStartBlockId() && !repoParameter.hasEndBlockId()) {
     processSingleDeleteCommand(interest, repoParameter, done);
     return;
@@ -87,7 +85,7 @@
 {
   int64_t nDeletedData = storageHandle.deleteData(parameter.getName());
   if (nDeletedData == -1) {
-    std::cerr << "Deletion Failed!" <<std::endl;
+    NDN_LOG_DEBUG("Deletion Failed");
     done(negativeReply(interest, 405, "Deletion Failed"));
   }
   else
@@ -95,20 +93,6 @@
 }
 
 void
-DeleteHandle::processSelectorDeleteCommand(const Interest& interest, const RepoCommandParameter& parameter,
-                                           const ndn::mgmt::CommandContinuation& done) const
-{
-  int64_t nDeletedData = storageHandle.deleteData(Interest(parameter.getName())
-                                      .setSelectors(parameter.getSelectors()));
-  if (nDeletedData == -1) {
-    std::cerr << "Deletion Failed!" <<std::endl;
-    done(negativeReply(interest, 405, "Deletion Failed"));
-  }
-  else
-    done(positiveReply(interest, parameter, 200, nDeletedData));
-}
-
-void
 DeleteHandle::processSegmentDeleteCommand(const Interest& interest, const RepoCommandParameter& parameter,
                                           const ndn::mgmt::CommandContinuation& done) const
 {
diff --git a/src/handles/delete-handle.hpp b/src/handles/delete-handle.hpp
index fbb25d3..ca32709 100644
--- a/src/handles/delete-handle.hpp
+++ b/src/handles/delete-handle.hpp
@@ -62,10 +62,6 @@
                              const ndn::mgmt::CommandContinuation& done) const;
 
   void
-  processSelectorDeleteCommand(const Interest& interest, const RepoCommandParameter& parameter,
-                               const ndn::mgmt::CommandContinuation& done) const;
-
-  void
   processSegmentDeleteCommand(const Interest& interest, const RepoCommandParameter& parameter,
                               const ndn::mgmt::CommandContinuation& done) const;
 };
diff --git a/src/handles/read-handle.cpp b/src/handles/read-handle.cpp
index 44a9d18..dbdfef7 100644
--- a/src/handles/read-handle.cpp
+++ b/src/handles/read-handle.cpp
@@ -20,8 +20,12 @@
 #include "read-handle.hpp"
 #include "repo.hpp"
 
+#include <ndn-cxx/util/logger.hpp>
+
 namespace repo {
 
+NDN_LOG_INIT(repo.ReadHandle);
+
 ReadHandle::ReadHandle(Face& face, RepoStorage& storageHandle, size_t prefixSubsetLength)
   : m_prefixSubsetLength(prefixSubsetLength)
   , m_face(face)
@@ -35,11 +39,11 @@
 {
   // Connect a RepoStorage's signals to the read handle
   if (m_prefixSubsetLength != RepoConfig::DISABLED_SUBSET_LENGTH) {
-    afterDataDeletionConnection = m_storageHandle.afterDataInsertion.connect(
+    afterDataInsertionConnection = m_storageHandle.afterDataInsertion.connect(
       [this] (const Name& prefix) {
         onDataInserted(prefix);
       });
-    afterDataInsertionConnection = m_storageHandle.afterDataDeletion.connect(
+    afterDataDeletionConnection = m_storageHandle.afterDataDeletion.connect(
       [this] (const Name& prefix) {
         onDataDeleted(prefix);
       });
@@ -49,16 +53,21 @@
 void
 ReadHandle::onInterest(const Name& prefix, const Interest& interest)
 {
-  shared_ptr<ndn::Data> data = m_storageHandle.readData(interest);
+  NDN_LOG_DEBUG("Received Interest " << interest.getName());
+  std::shared_ptr<ndn::Data> data = m_storageHandle.readData(interest);
   if (data != nullptr) {
-      m_face.put(*data);
+    NDN_LOG_DEBUG("Put Data: " << *data);
+    m_face.put(*data);
+  }
+  else {
+    NDN_LOG_DEBUG("No data for " << interest.getName());
   }
 }
 
 void
 ReadHandle::onRegisterFailed(const Name& prefix, const std::string& reason)
 {
-  std::cerr << "ERROR: Failed to register prefix in local hub's daemon" << std::endl;
+  NDN_LOG_ERROR("ERROR: Failed to register prefix in local hub's daemon");
   m_face.shutdown();
 }
 
@@ -67,8 +76,8 @@
 {
   ndn::InterestFilter filter(prefix);
   m_face.setInterestFilter(filter,
-                              bind(&ReadHandle::onInterest, this, _1, _2),
-                              bind(&ReadHandle::onRegisterFailed, this, _1, _2));
+                           std::bind(&ReadHandle::onInterest, this, _1, _2),
+                           std::bind(&ReadHandle::onRegisterFailed, this, _1, _2));
 }
 
 void
diff --git a/src/handles/read-handle.hpp b/src/handles/read-handle.hpp
index a243abd..bdd6b6f 100644
--- a/src/handles/read-handle.hpp
+++ b/src/handles/read-handle.hpp
@@ -54,7 +54,7 @@
   }
 
   /**
-   * @param after Do something after actually removing a prefix
+   * @param name Full name of the deleted Data
    */
   void
   onDataDeleted(const Name& name);
diff --git a/src/handles/tcp-bulk-insert-handle.cpp b/src/handles/tcp-bulk-insert-handle.cpp
index 53a60d6..f27d173 100644
--- a/src/handles/tcp-bulk-insert-handle.cpp
+++ b/src/handles/tcp-bulk-insert-handle.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017, Regents of the University of California.
+ * Copyright (c) 2014-2018, Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -19,8 +19,12 @@
 
 #include "tcp-bulk-insert-handle.hpp"
 
+#include <ndn-cxx/util/logger.hpp>
+
 namespace repo {
 
+NDN_LOG_INIT(repo.tcpHandle);
+
 const size_t MAX_NDN_PACKET_SIZE = 8800;
 
 namespace detail {
@@ -29,7 +33,7 @@
 {
 public:
   TcpBulkInsertClient(TcpBulkInsertHandle& writer,
-                      const shared_ptr<boost::asio::ip::tcp::socket>& socket)
+                      const std::shared_ptr<boost::asio::ip::tcp::socket>& socket)
     : m_writer(writer)
     , m_socket(socket)
     , m_hasStarted(false)
@@ -38,13 +42,13 @@
   }
 
   static void
-  startReceive(const shared_ptr<TcpBulkInsertClient>& client)
+  startReceive(const std::shared_ptr<TcpBulkInsertClient>& client)
   {
     BOOST_ASSERT(!client->m_hasStarted);
 
     client->m_socket->async_receive(
       boost::asio::buffer(client->m_inputBuffer, MAX_NDN_PACKET_SIZE), 0,
-      bind(&TcpBulkInsertClient::handleReceive, client, _1, _2, client));
+      std::bind(&TcpBulkInsertClient::handleReceive, client, _1, _2, client));
 
     client->m_hasStarted = true;
   }
@@ -53,11 +57,11 @@
   void
   handleReceive(const boost::system::error_code& error,
                 std::size_t nBytesReceived,
-                const shared_ptr<TcpBulkInsertClient>& client);
+                const std::shared_ptr<TcpBulkInsertClient>& client);
 
 private:
   TcpBulkInsertHandle& m_writer;
-  shared_ptr<boost::asio::ip::tcp::socket> m_socket;
+  std::shared_ptr<boost::asio::ip::tcp::socket> m_socket;
   bool m_hasStarted;
   uint8_t m_inputBuffer[MAX_NDN_PACKET_SIZE];
   std::size_t m_inputBufferSize;
@@ -87,22 +91,19 @@
     BOOST_THROW_EXCEPTION(Error("Cannot listen on [" + host + ":" + port + "]"));
 
   m_localEndpoint = *endpoint;
-  std::cerr << "Start listening on " << m_localEndpoint  << std::endl;
+  NDN_LOG_DEBUG("Start listening on " << m_localEndpoint);
 
   m_acceptor.open(m_localEndpoint .protocol());
   m_acceptor.set_option(ip::tcp::acceptor::reuse_address(true));
-  if (m_localEndpoint.address().is_v6())
-    {
-      m_acceptor.set_option(ip::v6_only(true));
-    }
+  if (m_localEndpoint.address().is_v6()) {
+    m_acceptor.set_option(ip::v6_only(true));
+  }
   m_acceptor.bind(m_localEndpoint);
   m_acceptor.listen(255);
 
-  shared_ptr<ip::tcp::socket> clientSocket =
-    make_shared<ip::tcp::socket>(std::ref(m_acceptor.get_io_service()));
+  auto clientSocket = std::make_shared<ip::tcp::socket>(m_acceptor.get_io_service());
   m_acceptor.async_accept(*clientSocket,
-                          bind(&TcpBulkInsertHandle::handleAccept, this, _1,
-                               clientSocket));
+                          std::bind(&TcpBulkInsertHandle::handleAccept, this, _1, clientSocket));
 }
 
 void
@@ -114,45 +115,40 @@
 
 void
 TcpBulkInsertHandle::handleAccept(const boost::system::error_code& error,
-                                  const shared_ptr<boost::asio::ip::tcp::socket>& socket)
+                                  const std::shared_ptr<boost::asio::ip::tcp::socket>& socket)
 {
   using namespace boost::asio;
 
   if (error) {
-    // if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
-    //   return;
     return;
   }
 
-  std::cerr << "New connection from " << socket->remote_endpoint() << std::endl;
+  NDN_LOG_DEBUG("New connection from " << socket->remote_endpoint());
 
-  shared_ptr<detail::TcpBulkInsertClient> client =
-    make_shared<detail::TcpBulkInsertClient>(std::ref(*this), socket);
+  std::shared_ptr<detail::TcpBulkInsertClient> client =
+    std::make_shared<detail::TcpBulkInsertClient>(*this, socket);
   detail::TcpBulkInsertClient::startReceive(client);
 
   // prepare accepting the next connection
-  shared_ptr<ip::tcp::socket> clientSocket =
-    make_shared<ip::tcp::socket>(std::ref(m_acceptor.get_io_service()));
+  auto clientSocket = std::make_shared<ip::tcp::socket>(m_acceptor.get_io_service());
   m_acceptor.async_accept(*clientSocket,
-                          bind(&TcpBulkInsertHandle::handleAccept, this, _1,
-                               clientSocket));
+                          std::bind(&TcpBulkInsertHandle::handleAccept, this, _1, clientSocket));
 }
 
 void
 detail::TcpBulkInsertClient::handleReceive(const boost::system::error_code& error,
                                            std::size_t nBytesReceived,
-                                           const shared_ptr<detail::TcpBulkInsertClient>& client)
+                                           const std::shared_ptr<detail::TcpBulkInsertClient>& client)
 {
-  if (error)
-    {
-      if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
-        return;
-
-      boost::system::error_code error;
-      m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
-      m_socket->close(error);
+  if (error) {
+    if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
       return;
-    }
+
+    boost::system::error_code error;
+    m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
+    m_socket->close(error);
+    return;
+  }
 
   m_inputBufferSize += nBytesReceived;
 
@@ -175,42 +171,37 @@
         Data data(element);
         bool isInserted = m_writer.getStorageHandle().insertData(data);
         if (isInserted)
-          std::cerr << "Successfully injected " << data.getName() << std::endl;
+          NDN_LOG_DEBUG("Successfully injected " << data.getName());
         else
-          std::cerr << "FAILED to inject " << data.getName() << std::endl;
+          NDN_LOG_DEBUG("FAILED to inject " << data.getName());
       }
       catch (const std::runtime_error& error) {
         /// \todo Catch specific error after determining what wireDecode() can throw
-        std::cerr << "Error decoding received Data packet" << std::endl;
+        NDN_LOG_ERROR("Error decoding received Data packet");
       }
     }
   }
 
-  if (!isOk && m_inputBufferSize == MAX_NDN_PACKET_SIZE && offset == 0)
-    {
-      boost::system::error_code error;
-      m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
-      m_socket->close(error);
-      return;
-    }
+  if (!isOk && m_inputBufferSize == MAX_NDN_PACKET_SIZE && offset == 0) {
+    boost::system::error_code error;
+    m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
+    m_socket->close(error);
+    return;
+  }
 
-  if (offset > 0)
-    {
-      if (offset != m_inputBufferSize)
-        {
-          std::copy(m_inputBuffer + offset, m_inputBuffer + m_inputBufferSize,
-                    m_inputBuffer);
-          m_inputBufferSize -= offset;
-        }
-      else
-        {
-          m_inputBufferSize = 0;
-        }
+  if (offset > 0) {
+    if (offset != m_inputBufferSize) {
+      std::copy(m_inputBuffer + offset, m_inputBuffer + m_inputBufferSize, m_inputBuffer);
+      m_inputBufferSize -= offset;
     }
+    else {
+      m_inputBufferSize = 0;
+    }
+  }
 
   m_socket->async_receive(boost::asio::buffer(m_inputBuffer + m_inputBufferSize,
                                               MAX_NDN_PACKET_SIZE - m_inputBufferSize), 0,
-                          bind(&TcpBulkInsertClient::handleReceive, this, _1, _2, client));
+                          std::bind(&TcpBulkInsertClient::handleReceive, this, _1, _2, client));
 }
 
 
diff --git a/src/handles/watch-handle.cpp b/src/handles/watch-handle.cpp
deleted file mode 100644
index 105e802..0000000
--- a/src/handles/watch-handle.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2018, Regents of the University of California.
- *
- * This file is part of NDN repo-ng (Next generation of NDN repository).
- * See AUTHORS.md for complete list of repo-ng authors and contributors.
- *
- * repo-ng 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.
- *
- * repo-ng 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
- * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "watch-handle.hpp"
-
-namespace repo {
-
-static const milliseconds PROCESS_DELETE_TIME(10000_ms);
-static const milliseconds DEFAULT_INTEREST_LIFETIME(4000_ms);
-
-WatchHandle::WatchHandle(Face& face, RepoStorage& storageHandle,
-                         ndn::mgmt::Dispatcher& dispatcher, Scheduler& scheduler, Validator& validator)
-  : CommandBaseHandle(face, storageHandle, scheduler, validator)
-  , m_validator(validator)
-  , m_interestNum(0)
-  , m_maxInterestNum(0)
-  , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
-  , m_watchTimeout(0)
-  , m_startTime(steady_clock::now())
-  , m_size(0)
-{
-  dispatcher.addControlCommand<RepoCommandParameter>(ndn::PartialName("watch").append("start"),
-    makeAuthorization(),
-    std::bind(&WatchHandle::validateParameters<WatchStartCommand>, this, _1),
-    std::bind(&WatchHandle::handleStartCommand, this, _1, _2, _3, _4));
-
-  dispatcher.addControlCommand<RepoCommandParameter>(ndn::PartialName("watch").append("check"),
-    makeAuthorization(),
-    std::bind(&WatchHandle::validateParameters<WatchCheckCommand>, this, _1),
-    std::bind(&WatchHandle::handleCheckCommand, this, _1, _2, _3, _4));
-
-  dispatcher.addControlCommand<RepoCommandParameter>(ndn::PartialName("watch").append("stop"),
-    makeAuthorization(),
-    std::bind(&WatchHandle::validateParameters<WatchStopCommand>, this, _1),
-    std::bind(&WatchHandle::handleStopCommand, this, _1, _2, _3, _4));
-}
-
-void
-WatchHandle::deleteProcess(const Name& name)
-{
-  m_processes.erase(name);
-}
-
-void
-WatchHandle::handleStartCommand(const Name& prefix, const Interest& interest,
-                                const ndn::mgmt::ControlParameters& parameter,
-                                const ndn::mgmt::CommandContinuation& done)
-{
-  const RepoCommandParameter& repoParameter = dynamic_cast<const RepoCommandParameter&>(parameter);
-  processWatchCommand(interest, repoParameter, done);
-}
-
-void WatchHandle::watchStop(const Name& name)
-{
-  m_processes[name].second = false;
-  m_maxInterestNum = 0;
-  m_interestNum = 0;
-  m_startTime = steady_clock::now();
-  m_watchTimeout = 0_ms;
-  m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
-  m_size = 0;
-}
-
-
-void
-WatchHandle::onData(const Interest& interest, const ndn::Data& data, const Name& name)
-{
- m_validator.validate(data,
-                      bind(&WatchHandle::onDataValidated, this, interest, _1, name),
-                      bind(&WatchHandle::onDataValidationFailed, this, interest, _1, _2, name));
-}
-
-void
-WatchHandle::onDataValidated(const Interest& interest, const Data& data, const Name& name)
-{
-  if (!m_processes[name].second) {
-    return;
-  }
-  if (storageHandle.insertData(data)) {
-    m_size++;
-    if (!onRunning(name))
-      return;
-
-    Interest fetchInterest(interest.getName());
-    fetchInterest.setSelectors(interest.getSelectors());
-    fetchInterest.setInterestLifetime(m_interestLifetime);
-    fetchInterest.setChildSelector(1);
-
-    // update selectors
-    // if data name is equal to interest name, use MinSuffixComponents selecor to exclude this data
-    if (data.getName().size() == interest.getName().size()) {
-      fetchInterest.setMinSuffixComponents(2);
-    }
-    else {
-      Exclude exclude;
-      if (!interest.getExclude().empty()) {
-        exclude = interest.getExclude();
-      }
-
-      exclude.excludeBefore(data.getName()[interest.getName().size()]);
-      fetchInterest.setExclude(exclude);
-    }
-
-    ++m_interestNum;
-    face.expressInterest(fetchInterest,
-                              bind(&WatchHandle::onData, this, _1, _2, name),
-                              bind(&WatchHandle::onTimeout, this, _1, name), // Nack
-                              bind(&WatchHandle::onTimeout, this, _1, name));
-  }
-  else {
-    BOOST_THROW_EXCEPTION(Error("Insert into Repo Failed"));
-  }
-  m_processes[name].first.setInsertNum(m_size);
-}
-
-void
-WatchHandle::onDataValidationFailed(const Interest& interest, const Data& data,
-                                    const ValidationError& error, const Name& name)
-{
-  std::cerr << error << std::endl;
-  if (!m_processes[name].second) {
-    return;
-  }
-  if (!onRunning(name))
-    return;
-
-  Interest fetchInterest(interest.getName());
-  fetchInterest.setSelectors(interest.getSelectors());
-  fetchInterest.setInterestLifetime(m_interestLifetime);
-  fetchInterest.setChildSelector(1);
-
-  // update selectors
-  // if data name is equal to interest name, use MinSuffixComponents selecor to exclude this data
-  if (data.getName().size() == interest.getName().size()) {
-    fetchInterest.setMinSuffixComponents(2);
-  }
-  else {
-    Exclude exclude;
-    if (!interest.getExclude().empty()) {
-      exclude = interest.getExclude();
-    }
-    // Only exclude this data since other data whose names are smaller may be validated and satisfied
-    exclude.excludeBefore(data.getName()[interest.getName().size()]);
-    fetchInterest.setExclude(exclude);
-  }
-
-  ++m_interestNum;
-  face.expressInterest(fetchInterest,
-                            bind(&WatchHandle::onData, this, _1, _2, name),
-                            bind(&WatchHandle::onTimeout, this, _1, name), // Nack
-                            bind(&WatchHandle::onTimeout, this, _1, name));
-}
-
-void
-WatchHandle::onTimeout(const ndn::Interest& interest, const Name& name)
-{
-  std::cerr << "Timeout" << std::endl;
-  if (!m_processes[name].second) {
-    return;
-  }
-  if (!onRunning(name))
-    return;
-  // selectors do not need to be updated
-  Interest fetchInterest(interest.getName());
-  fetchInterest.setSelectors(interest.getSelectors());
-  fetchInterest.setInterestLifetime(m_interestLifetime);
-  fetchInterest.setChildSelector(1);
-
-  ++m_interestNum;
-  face.expressInterest(fetchInterest,
-                            bind(&WatchHandle::onData, this, _1, _2, name),
-                            bind(&WatchHandle::onTimeout, this, _1, name), // Nack
-                            bind(&WatchHandle::onTimeout, this, _1, name));
-
-}
-
-void
-WatchHandle::handleStopCommand(const Name& prefix, const Interest& interest,
-                               const ndn::mgmt::ControlParameters& parameter,
-                               const ndn::mgmt::CommandContinuation& done)
-{
-  const RepoCommandParameter& repoParameter = dynamic_cast<const RepoCommandParameter&>(parameter);
-
-  watchStop(repoParameter.getName());
-  std::string text = "Watched Prefix Insertion for prefix (" + prefix.toUri() + ") is stop.";
-  return done(RepoCommandResponse(101, text));
-}
-
-void
-WatchHandle::handleCheckCommand(const Name& prefix, const Interest& interest,
-                                const ndn::mgmt::ControlParameters& parameter,
-                                const ndn::mgmt::CommandContinuation& done)
-{
-  const RepoCommandParameter& repoParameter = dynamic_cast<const RepoCommandParameter&>(parameter);
-
-  //check whether this process exists
-  Name name = repoParameter.getName();
-  if (m_processes.count(name) == 0) {
-    std::cerr << "no such process name: " << name << std::endl;
-    RepoCommandResponse response(404, "No such process is in progress");
-    response.setBody(response.wireEncode());
-    return done(response);
-  }
-
-  RepoCommandResponse& response = m_processes[name].first;
-
-  if (!m_processes[name].second) {
-    response.setCode(101);
-  }
-
-  return done(response);
-}
-
-void
-WatchHandle::deferredDeleteProcess(const Name& name)
-{
-  scheduler.scheduleEvent(PROCESS_DELETE_TIME,
-                               bind(&WatchHandle::deleteProcess, this, name));
-}
-
-void
-WatchHandle::processWatchCommand(const Interest& interest,
-                                 const RepoCommandParameter& parameter,
-                                 const ndn::mgmt::CommandContinuation& done)
-{
-  // if there is no watchTimeout specified, m_watchTimeout will be set as 0 and this handle will run forever
-  if (parameter.hasWatchTimeout()) {
-    m_watchTimeout = parameter.getWatchTimeout();
-  }
-  else {
-    m_watchTimeout = 0_ms;
-  }
-
-  // if there is no maxInterestNum specified, m_maxInterestNum will be 0, which means infinity
-  if (parameter.hasMaxInterestNum()) {
-    m_maxInterestNum = parameter.getMaxInterestNum();
-  }
-  else {
-    m_maxInterestNum = 0;
-  }
-
-  if (parameter.hasInterestLifetime()) {
-    m_interestLifetime = parameter.getInterestLifetime();
-  }
-
-  RepoCommandResponse response(100, "Watching the prefix started.");
-  response.setBody(response.wireEncode());
-  done(response);
-
-  m_processes[parameter.getName()] =
-                std::make_pair(RepoCommandResponse(300, "This watched prefix Insertion is in progress"),
-                               true);
-
-  Interest fetchInterest(parameter.getName());
-  if (parameter.hasSelectors()) {
-    fetchInterest.setSelectors(parameter.getSelectors());
-  }
-  fetchInterest.setChildSelector(1);
-  fetchInterest.setInterestLifetime(m_interestLifetime);
-  m_startTime = steady_clock::now();
-  m_interestNum++;
-  face.expressInterest(fetchInterest,
-                       bind(&WatchHandle::onData, this, _1, _2, parameter.getName()),
-                       bind(&WatchHandle::onTimeout, this, _1, parameter.getName()), // Nack
-                       bind(&WatchHandle::onTimeout, this, _1, parameter.getName()));
-}
-
-bool
-WatchHandle::onRunning(const Name& name)
-{
-  bool isTimeout = (m_watchTimeout != milliseconds::zero() &&
-                    steady_clock::now() - m_startTime > m_watchTimeout);
-  bool isMaxInterest = m_interestNum >= m_maxInterestNum && m_maxInterestNum != 0;
-  if (isTimeout || isMaxInterest) {
-    deferredDeleteProcess(name);
-    watchStop(name);
-    return false;
-  }
-  return true;
-}
-
-} // namespace repo
diff --git a/src/handles/watch-handle.hpp b/src/handles/watch-handle.hpp
deleted file mode 100644
index 221b67d..0000000
--- a/src/handles/watch-handle.hpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2018, Regents of the University of California.
- *
- * This file is part of NDN repo-ng (Next generation of NDN repository).
- * See AUTHORS.md for complete list of repo-ng authors and contributors.
- *
- * repo-ng 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.
- *
- * repo-ng 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
- * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef REPO_HANDLES_WATCH_HANDLE_HPP
-#define REPO_HANDLES_WATCH_HANDLE_HPP
-
-#include "command-base-handle.hpp"
-
-#include <ndn-cxx/mgmt/dispatcher.hpp>
-
-#include <queue>
-
-namespace repo {
-
-using std::map;
-using std::pair;
-using std::queue;
-using namespace ndn::time;
-/**
- * @brief WatchHandle provides a different way for repo to insert data.
- *
- * Repo keeps sending interest to request the data with same prefix,
- * but with different exclude selectors(updated every time). Repo will stop
- * watching the prefix until a command interest tell it to stop, the total
- * amount of sent interests reaches a specific number or time out.
- */
-class WatchHandle : public CommandBaseHandle
-{
-
-public:
-  class Error : public CommandBaseHandle::Error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : CommandBaseHandle::Error(what)
-    {
-    }
-  };
-
-
-public:
-  WatchHandle(Face& face, RepoStorage& storageHandle,
-              ndn::mgmt::Dispatcher& dispatcher, Scheduler& scheduler,
-              Validator& validator);
-
-private: // watch-insert command
-  /**
-   * @brief handle watch commands
-   */
-
-  void
-  handleStartCommand(const Name& prefix, const Interest& interest,
-                     const ndn::mgmt::ControlParameters& parameters,
-                     const ndn::mgmt::CommandContinuation& done);
-  void
-  onValidationFailed(const std::shared_ptr<const Interest>& interest, const std::string& reason);
-
-private: // data fetching
-  /**
-   * @brief fetch data and send next interest
-   */
-  void
-  onData(const Interest& interest, const Data& data, const Name& name);
-
-  /**
-   * @brief handle when fetching one data timeout
-   */
-  void
-  onTimeout(const Interest& interest, const Name& name);
-
-  void
-  onDataValidated(const Interest& interest, const Data& data, const Name& name);
-
-  /**
-   * @brief failure of validation
-   */
-  void
-  onDataValidationFailed(const Interest& interest, const Data& data,
-                         const ValidationError& error, const Name& name);
-
-
-  void
-  processWatchCommand(const Interest& interest, const RepoCommandParameter& parameter,
-                      const ndn::mgmt::CommandContinuation& done);
-
-  void
-  watchStop(const Name& name);
-
-private: // watch state check command
-  /**
-   * @brief handle watch check command
-   */
-
-  void
-  handleCheckCommand(const Name& prefix, const Interest& interest,
-                     const ndn::mgmt::ControlParameters& parameters,
-                     const ndn::mgmt::CommandContinuation& done);
-
-  void
-  onCheckValidationFailed(const Interest& interest, const ValidationError& error);
-
-private: // watch stop command
-  /**
-   * @brief handle watch stop command
-   */
-
-  void
-  handleStopCommand(const Name& prefix, const Interest& interest,
-                    const ndn::mgmt::ControlParameters& parameters,
-                    const ndn::mgmt::CommandContinuation& done);
-
-  void
-  onStopValidationFailed(const Interest& interest, const ValidationError& error);
-
-private:
-  void
-  deferredDeleteProcess(const Name& name);
-
-  void
-  deleteProcess(const Name& name);
-
-  bool
-  onRunning(const Name& name);
-
-private:
-  Validator& m_validator;
-  map<Name, std::pair<RepoCommandResponse, bool> > m_processes;
-  int64_t m_interestNum;
-  int64_t m_maxInterestNum;
-  milliseconds m_interestLifetime;
-  milliseconds m_watchTimeout;
-  ndn::time::steady_clock::TimePoint m_startTime;
-  int64_t m_size;
-};
-
-} // namespace repo
-
-#endif // REPO_HANDLES_WATCH_HANDLE_HPP
diff --git a/src/handles/write-handle.cpp b/src/handles/write-handle.cpp
index 6cc9583..675f286 100644
--- a/src/handles/write-handle.cpp
+++ b/src/handles/write-handle.cpp
@@ -19,12 +19,16 @@
 
 #include "write-handle.hpp"
 
+#include <ndn-cxx/util/logger.hpp>
 #include <ndn-cxx/util/random.hpp>
 
 namespace repo {
 
-static const int RETRY_TIMEOUT = 3;
+NDN_LOG_INIT(repo.WriteHandle);
+
 static const int DEFAULT_CREDIT = 12;
+static const bool DEFAULT_CANBE_PREFIX = false;
+static const milliseconds MAX_TIMEOUT(60_s);
 static const milliseconds NOEND_TIMEOUT(10000_ms);
 static const milliseconds PROCESS_DELETE_TIME(10000_ms);
 static const milliseconds DEFAULT_INTEREST_LIFETIME(4000_ms);
@@ -33,8 +37,9 @@
                          Scheduler& scheduler, Validator& validator)
   : CommandBaseHandle(face, storageHandle, scheduler, validator)
   , m_validator(validator)
-  , m_retryTime(RETRY_TIMEOUT)
   , m_credit(DEFAULT_CREDIT)
+  , m_canBePrefix(DEFAULT_CANBE_PREFIX)
+  , m_maxTimeout(MAX_TIMEOUT)
   , m_noEndTimeout(NOEND_TIMEOUT)
   , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
 {
@@ -64,10 +69,6 @@
     dynamic_cast<RepoCommandParameter*>(const_cast<ndn::mgmt::ControlParameters*>(&parameter));
 
   if (repoParameter->hasStartBlockId() || repoParameter->hasEndBlockId()) {
-    if (repoParameter->hasSelectors()) {
-      done(negativeReply("BlockId present. BlockId is not supported in this protocol", 402));
-      return;
-    }
     processSegmentedInsertCommand(interest, *repoParameter, done);
   }
   else {
@@ -81,8 +82,8 @@
 WriteHandle::onData(const Interest& interest, const Data& data, ProcessId processId)
 {
   m_validator.validate(data,
-                       bind(&WriteHandle::onDataValidated, this, interest, _1, processId),
-                       bind(&WriteHandle::onDataValidationFailed, this, _1, _2));
+                       std::bind(&WriteHandle::onDataValidated, this, interest, _1, processId),
+                       [](const Data& data, const ValidationError& error){NDN_LOG_ERROR("Error: " << error);});
 }
 
 void
@@ -104,296 +105,13 @@
 }
 
 void
-WriteHandle::onDataValidationFailed(const Data& data, const ValidationError& error)
-{
-  std::cerr << error << std::endl;
-}
-
-void
-WriteHandle::onSegmentData(const Interest& interest, const Data& data, ProcessId processId)
-{
-  m_validator.validate(data,
-                       bind(&WriteHandle::onSegmentDataValidated, this, interest, _1, processId),
-                       bind(&WriteHandle::onDataValidationFailed, this, _1, _2));
-}
-
-void
-WriteHandle::onSegmentDataValidated(const Interest& interest, const Data& data, ProcessId processId)
-{
-  auto it = m_processes.find(processId);
-  if (it == m_processes.end()) {
-    return;
-  }
-  RepoCommandResponse& response = it->second.response;
-
-  //refresh endBlockId
-  auto finalBlock = data.getFinalBlock();
-  if (finalBlock && finalBlock->isSegment()) {
-    auto finalSeg = finalBlock->toSegment();
-    if (response.hasEndBlockId()) {
-      if (finalSeg < response.getEndBlockId()) {
-        response.setEndBlockId(finalSeg);
-      }
-    }
-    else {
-      response.setEndBlockId(finalSeg);
-    }
-  }
-
-  //insert data
-  if (storageHandle.insertData(data)) {
-    response.setInsertNum(response.getInsertNum() + 1);
-  }
-
-  onSegmentDataControl(processId, interest);
-}
-
-void
 WriteHandle::onTimeout(const Interest& interest, ProcessId processId)
 {
-  std::cerr << "Timeout" << std::endl;
+  NDN_LOG_DEBUG("Timeout" << std::endl);
   m_processes.erase(processId);
 }
 
 void
-WriteHandle::onSegmentTimeout(const Interest& interest, ProcessId processId)
-{
-  std::cerr << "SegTimeout" << std::endl;
-
-  onSegmentTimeoutControl(processId, interest);
-}
-
-void
-WriteHandle::segInit(ProcessId processId, const RepoCommandParameter& parameter)
-{
-  ProcessInfo& process = m_processes[processId];
-  process.credit = 0;
-
-  map<SegmentNo, int>& processRetry = process.retryCounts;
-
-  Name name = parameter.getName();
-  SegmentNo startBlockId = parameter.getStartBlockId();
-
-  uint64_t initialCredit = m_credit;
-
-  if (parameter.hasEndBlockId()) {
-    initialCredit =
-      std::min(initialCredit, parameter.getEndBlockId() - parameter.getStartBlockId() + 1);
-  }
-  else {
-    // set noEndTimeout timer
-    process.noEndTime = ndn::time::steady_clock::now() +
-                        m_noEndTimeout;
-  }
-  process.credit = initialCredit;
-  SegmentNo segment = startBlockId;
-
-  for (; segment < startBlockId + initialCredit; ++segment) {
-    Name fetchName = name;
-    fetchName.appendSegment(segment);
-    Interest interest(fetchName);
-    interest.setInterestLifetime(m_interestLifetime);
-    face.expressInterest(interest,
-                              bind(&WriteHandle::onSegmentData, this, _1, _2, processId),
-                              bind(&WriteHandle::onSegmentTimeout, this, _1, processId), // Nack
-                              bind(&WriteHandle::onSegmentTimeout, this, _1, processId));
-    process.credit--;
-    processRetry[segment] = 0;
-  }
-
-  queue<SegmentNo>& nextSegmentQueue = process.nextSegmentQueue;
-
-  process.nextSegment = segment;
-  nextSegmentQueue.push(segment);
-}
-
-void
-WriteHandle::onSegmentDataControl(ProcessId processId, const Interest& interest)
-{
-  if (m_processes.count(processId) == 0) {
-    return;
-  }
-  ProcessInfo& process = m_processes[processId];
-  RepoCommandResponse& response = process.response;
-  int& processCredit = process.credit;
-  //onSegmentDataControl is called when a data returns.
-  //When data returns, processCredit++
-  processCredit++;
-  SegmentNo& nextSegment = process.nextSegment;
-  queue<SegmentNo>& nextSegmentQueue = process.nextSegmentQueue;
-  map<SegmentNo, int>& retryCounts = process.retryCounts;
-
-  //read whether notime timeout
-  if (!response.hasEndBlockId()) {
-
-    ndn::time::steady_clock::TimePoint& noEndTime = process.noEndTime;
-    ndn::time::steady_clock::TimePoint now = ndn::time::steady_clock::now();
-
-    if (now > noEndTime) {
-      std::cerr << "noEndtimeout: " << processId << std::endl;
-      //m_processes.erase(processId);
-      //StatusCode should be refreshed as 405
-      response.setCode(405);
-      //schedule a delete event
-      deferredDeleteProcess(processId);
-      return;
-    }
-  }
-
-  //read whether this process has total ends, if ends, remove control info from the maps
-  if (response.hasEndBlockId()) {
-    uint64_t nSegments =
-      response.getEndBlockId() - response.getStartBlockId() + 1;
-    if (response.getInsertNum() >= nSegments) {
-      //m_processes.erase(processId);
-      //All the data has been inserted, StatusCode is refreshed as 200
-      response.setCode(200);
-      deferredDeleteProcess(processId);
-      return;
-    }
-  }
-
-  //check whether there is any credit
-  if (processCredit == 0)
-    return;
-
-
-  //check whether sent queue empty
-  if (nextSegmentQueue.empty()) {
-    //do not do anything
-    return;
-  }
-
-  //pop the queue
-  SegmentNo sendingSegment = nextSegmentQueue.front();
-  nextSegmentQueue.pop();
-
-  //check whether sendingSegment exceeds
-  if (response.hasEndBlockId() && sendingSegment > response.getEndBlockId()) {
-    //do not do anything
-    return;
-  }
-
-  //read whether this is retransmitted data;
-  SegmentNo fetchedSegment =
-    interest.getName().get(interest.getName().size() - 1).toSegment();
-
-  BOOST_ASSERT(retryCounts.count(fetchedSegment) != 0);
-
-  //find this fetched data, remove it from this map
-  //rit->second.erase(oit);
-  retryCounts.erase(fetchedSegment);
-  //express the interest of the top of the queue
-  Name fetchName(interest.getName().getPrefix(-1));
-  fetchName.appendSegment(sendingSegment);
-  Interest fetchInterest(fetchName);
-  fetchInterest.setInterestLifetime(m_interestLifetime);
-  face.expressInterest(fetchInterest,
-                            bind(&WriteHandle::onSegmentData, this, _1, _2, processId),
-                            bind(&WriteHandle::onSegmentTimeout, this, _1, processId), // Nack
-                            bind(&WriteHandle::onSegmentTimeout, this, _1, processId));
-  //When an interest is expressed, processCredit--
-  processCredit--;
-  if (retryCounts.count(sendingSegment) == 0) {
-    //not found
-    retryCounts[sendingSegment] = 0;
-  }
-  else {
-    //found
-    retryCounts[sendingSegment] = retryCounts[sendingSegment] + 1;
-  }
-  //increase the next seg and put it into the queue
-  if (!response.hasEndBlockId() || (nextSegment + 1) <= response.getEndBlockId()) {
-    nextSegment++;
-    nextSegmentQueue.push(nextSegment);
-  }
-}
-
-void
-WriteHandle::onSegmentTimeoutControl(ProcessId processId, const Interest& interest)
-{
-  if (m_processes.count(processId) == 0) {
-    return;
-  }
-  ProcessInfo& process = m_processes[processId];
-  // RepoCommandResponse& response = process.response;
-  // SegmentNo& nextSegment = process.nextSegment;
-  // queue<SegmentNo>& nextSegmentQueue = process.nextSegmentQueue;
-  map<SegmentNo, int>& retryCounts = process.retryCounts;
-
-  SegmentNo timeoutSegment = interest.getName().get(-1).toSegment();
-
-  std::cerr << "timeoutSegment: " << timeoutSegment << std::endl;
-
-  BOOST_ASSERT(retryCounts.count(timeoutSegment) != 0);
-
-  //read the retry time. If retry out of time, fail the process. if not, plus
-  int& retryTime = retryCounts[timeoutSegment];
-  if (retryTime >= m_retryTime) {
-    //fail this process
-    std::cerr << "Retry timeout: " << processId << std::endl;
-    m_processes.erase(processId);
-    return;
-  }
-  else {
-    //Reput it in the queue, retryTime++
-    retryTime++;
-    Interest retryInterest(interest.getName());
-    retryInterest.setInterestLifetime(m_interestLifetime);
-    face.expressInterest(retryInterest,
-                              bind(&WriteHandle::onSegmentData, this, _1, _2, processId),
-                              bind(&WriteHandle::onSegmentTimeout, this, _1, processId), // Nack
-                              bind(&WriteHandle::onSegmentTimeout, this, _1, processId));
-  }
-
-}
-
-void
-WriteHandle::handleCheckCommand(const Name& prefix, const Interest& interest,
-                                const ndn::mgmt::ControlParameters& parameter,
-                                const ndn::mgmt::CommandContinuation& done)
-{
-  const RepoCommandParameter& repoParameter = dynamic_cast<const RepoCommandParameter&>(parameter);
-
-  //check whether this process exists
-  ProcessId processId = repoParameter.getProcessId();
-  if (m_processes.count(processId) == 0) {
-    std::cerr << "no such processId: " << processId << std::endl;
-    done(negativeReply("No such this process is in progress", 404));
-    return;
-  }
-
-  ProcessInfo& process = m_processes[processId];
-
-  RepoCommandResponse& response = process.response;
-
-  //Check whether it is single data fetching
-  if (!response.hasStartBlockId() &&
-      !response.hasEndBlockId()) {
-    //reply(interest, response);
-    done(response);
-    return;
-  }
-
-  //read if noEndtimeout
-  if (!response.hasEndBlockId()) {
-    extendNoEndTime(process);
-    done(response);
-    return;
-  }
-  else {
-    done(response);
-  }
-}
-
-void
-WriteHandle::deferredDeleteProcess(ProcessId processId)
-{
-  scheduler.scheduleEvent(PROCESS_DELETE_TIME,
-                               bind(&WriteHandle::deleteProcess, this, processId));
-}
-
-void
 WriteHandle::processSingleInsertCommand(const Interest& interest, RepoCommandParameter& parameter,
                                         const ndn::mgmt::CommandContinuation& done)
 {
@@ -409,16 +127,108 @@
   done(response);
 
   response.setCode(300);
-
   Interest fetchInterest(parameter.getName());
+  fetchInterest.setCanBePrefix(m_canBePrefix);
   fetchInterest.setInterestLifetime(m_interestLifetime);
-  if (parameter.hasSelectors()) {
-    fetchInterest.setSelectors(parameter.getSelectors());
-  }
   face.expressInterest(fetchInterest,
-                       bind(&WriteHandle::onData, this, _1, _2, processId),
-                       bind(&WriteHandle::onTimeout, this, _1, processId), // Nack
-                       bind(&WriteHandle::onTimeout, this, _1, processId));
+                       std::bind(&WriteHandle::onData, this, _1, _2, processId),
+                       std::bind(&WriteHandle::onTimeout, this, _1, processId), // Nack
+                       std::bind(&WriteHandle::onTimeout, this, _1, processId));
+}
+
+void
+WriteHandle::segInit(ProcessId processId, const RepoCommandParameter& parameter)
+{
+  // use SegmentFetcher to send fetch interest.
+  ProcessInfo& process = m_processes[processId];
+  Name name = parameter.getName();
+  SegmentNo startBlockId = parameter.getStartBlockId();
+
+  uint64_t initialCredit = m_credit;
+
+  if (parameter.hasEndBlockId()) {
+    initialCredit =
+      std::min(initialCredit, parameter.getEndBlockId() - parameter.getStartBlockId() + 1);
+  }
+  else {
+    // set noEndTimeout timer
+    process.noEndTime = ndn::time::steady_clock::now() +
+                        m_noEndTimeout;
+  }
+
+  Name fetchName = name;
+  SegmentNo segment = startBlockId;
+  fetchName.appendSegment(segment);
+  Interest interest(fetchName);
+
+  ndn::util::SegmentFetcher::Options options;
+  options.initCwnd = initialCredit;
+  options.interestLifetime = m_interestLifetime;
+  options.maxTimeout = m_maxTimeout;
+  auto fetcher = ndn::util::SegmentFetcher::start(face, interest, m_validator, options);
+  fetcher->onError.connect([] (uint32_t errorCode, const std::string& errorMsg)
+                           {NDN_LOG_ERROR("Error: " << errorMsg);});
+  fetcher->afterSegmentValidated.connect([this, &fetcher, &processId] (const Data& data)
+                                         {onSegmentData(*fetcher, data, processId);});
+  fetcher->afterSegmentTimedOut.connect([this, &fetcher, &processId] ()
+                                        {onSegmentTimeout(*fetcher, processId);});
+}
+
+void
+WriteHandle::onSegmentData(ndn::util::SegmentFetcher& fetcher, const Data& data, ProcessId processId)
+{
+  auto it = m_processes.find(processId);
+  if (it == m_processes.end()) {
+    fetcher.stop();
+    return;
+  }
+
+  RepoCommandResponse& response = it->second.response;
+
+  //insert data
+  if (storageHandle.insertData(data)) {
+    response.setInsertNum(response.getInsertNum() + 1);
+  }
+
+  ProcessInfo& process = m_processes[processId];
+  //read whether notime timeout
+  if (!response.hasEndBlockId()) {
+
+    ndn::time::steady_clock::TimePoint& noEndTime = process.noEndTime;
+    ndn::time::steady_clock::TimePoint now = ndn::time::steady_clock::now();
+
+    if (now > noEndTime) {
+      NDN_LOG_DEBUG("noEndtimeout: " << processId);
+      //StatusCode should be refreshed as 405
+      response.setCode(405);
+      //schedule a delete event
+      deferredDeleteProcess(processId);
+      fetcher.stop();
+      return;
+    }
+  }
+
+  //read whether this process has total ends, if ends, remove control info from the maps
+  if (response.hasEndBlockId()) {
+    uint64_t nSegments = response.getEndBlockId() - response.getStartBlockId() + 1;
+    if (response.getInsertNum() >= nSegments) {
+      //All the data has been inserted, StatusCode is refreshed as 200
+      response.setCode(200);
+      deferredDeleteProcess(processId);
+      fetcher.stop();
+      return;
+    }
+  }
+}
+
+void
+WriteHandle::onSegmentTimeout(ndn::util::SegmentFetcher& fetcher, ProcessId processId)
+{
+  NDN_LOG_DEBUG("SegTimeout");
+  if (m_processes.count(processId) == 0) {
+    fetcher.stop();
+    return;
+  }
 }
 
 void
@@ -470,6 +280,49 @@
 }
 
 void
+WriteHandle::handleCheckCommand(const Name& prefix, const Interest& interest,
+                                const ndn::mgmt::ControlParameters& parameter,
+                                const ndn::mgmt::CommandContinuation& done)
+{
+  const RepoCommandParameter& repoParameter = dynamic_cast<const RepoCommandParameter&>(parameter);
+
+  //check whether this process exists
+  ProcessId processId = repoParameter.getProcessId();
+  if (m_processes.count(processId) == 0) {
+    NDN_LOG_DEBUG("no such processId: " << processId);
+    done(negativeReply("No such this process is in progress", 404));
+    return;
+  }
+
+  ProcessInfo& process = m_processes[processId];
+
+  RepoCommandResponse& response = process.response;
+
+  //Check whether it is single data fetching
+  if (!response.hasStartBlockId() && !response.hasEndBlockId()) {
+    done(response);
+    return;
+  }
+
+  //read if noEndtimeout
+  if (!response.hasEndBlockId()) {
+    extendNoEndTime(process);
+    done(response);
+    return;
+  }
+  else {
+    done(response);
+  }
+}
+
+void
+WriteHandle::deferredDeleteProcess(ProcessId processId)
+{
+  scheduler.scheduleEvent(PROCESS_DELETE_TIME,
+                          std::bind(&WriteHandle::deleteProcess, this, processId));
+}
+
+void
 WriteHandle::extendNoEndTime(ProcessInfo& process)
 {
   ndn::time::steady_clock::TimePoint& noEndTime = process.noEndTime;
diff --git a/src/handles/write-handle.hpp b/src/handles/write-handle.hpp
index 686d68c..115801e 100644
--- a/src/handles/write-handle.hpp
+++ b/src/handles/write-handle.hpp
@@ -23,15 +23,12 @@
 #include "command-base-handle.hpp"
 
 #include <ndn-cxx/mgmt/dispatcher.hpp>
+#include <ndn-cxx/util/segment-fetcher.hpp>
 
 #include <queue>
 
 namespace repo {
 
-using std::map;
-using std::pair;
-using std::queue;
-
 /**
  * @brief WriteHandle provides basic credit based congestion control.
  *
@@ -80,12 +77,11 @@
   */
   struct ProcessInfo
   {
-    //ProcessId id;
     RepoCommandResponse response;
-    queue<SegmentNo> nextSegmentQueue;  ///< queue of waiting segment
+    std::queue<SegmentNo> nextSegmentQueue;  ///< queue of waiting segment
                                         ///  to be sent when having credits
     SegmentNo nextSegment;  ///< last segment put into the nextSegmentQueue
-    map<SegmentNo, int> retryCounts;  ///< to store retrying times of timeout segment
+    std::map<SegmentNo, int> retryCounts;  ///< to store retrying times of timeout segment
     int credit;  ///< congestion control credits of process
 
     /**
@@ -136,16 +132,13 @@
    * @brief fetch segmented data
    */
   void
-  onSegmentData(const Interest& interest, const Data& data, ProcessId processId);
-
-  void
-  onSegmentDataValidated(const Interest& interest, const Data& data, ProcessId processId);
+  onSegmentData(ndn::util::SegmentFetcher& fetcher, const Data& data, ProcessId processId);
 
   /**
-   * @brief Timeout when fetching segmented data. Data can be fetched RETRY_TIMEOUT times.
+   * @brief handle when fetching segmented data timeout
    */
   void
-  onSegmentTimeout(const Interest& interest, ProcessId processId);
+  onSegmentTimeout(ndn::util::SegmentFetcher& fetcher, ProcessId processId);
 
   /**
    * @brief initiate fetching segmented data
@@ -153,30 +146,12 @@
   void
   segInit(ProcessId processId, const RepoCommandParameter& parameter);
 
-  /**
-   * @brief control for sending interests in function onSegmentData()
-   */
-  void
-  onSegmentDataControl(ProcessId processId, const Interest& interest);
-
-  /**
-   * @brief control for sending interest in function onSegmentTimeout
-   */
-  void
-  onSegmentTimeoutControl(ProcessId processId, const Interest& interest);
-
   void
   processSegmentedInsertCommand(const Interest& interest, RepoCommandParameter& parameter,
                                 const ndn::mgmt::CommandContinuation& done);
 
 private:
   /**
-   * @brief failure of validation for both one or segmented data
-   */
-  void
-  onDataValidationFailed(const Data& data, const ValidationError& error);
-
-  /**
    * @brief extends noEndTime of process if not noEndTimeout, set StatusCode 405
    *
    * called by onCheckValidated() if there is no EndBlockId. If not noEndTimeout,
@@ -213,9 +188,12 @@
 
 private:
   Validator& m_validator;
-  map<ProcessId, ProcessInfo> m_processes;
-  int m_retryTime;
+
+  std::map<ProcessId, ProcessInfo> m_processes;
+
   int m_credit;
+  bool m_canBePrefix;
+  ndn::time::milliseconds m_maxTimeout;
   ndn::time::milliseconds m_noEndTimeout;
   ndn::time::milliseconds m_interestLifetime;
 };
diff --git a/src/main.cpp b/src/main.cpp
index 9713943..800b8c7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014,  Regents of the University of California.
+ * Copyright (c) 2018,  Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -20,6 +20,12 @@
 #include "config.hpp"
 #include "repo.hpp"
 
+#include "extended-error-message.hpp"
+
+#include <ndn-cxx/util/logger.hpp>
+
+NDN_LOG_INIT(repo.main);
+
 static const std::string ndnRepoUsageMessage =
   /* argv[0] */ " - Next generation of NDN repository\n"
   "-h: show help message\n"
@@ -35,19 +41,14 @@
   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(std::bind(&terminate, std::ref(ioService),
-                                     std::placeholders::_1, std::placeholders::_2,
-                                     std::ref(signalSet)));
-    }
+  if (signalNo == SIGINT || signalNo == SIGTERM) {
+    ioService.stop();
+    std::cout << "Caught signal '" << strsignal(signalNo) << "', exiting..." << std::endl;
+  }
+  else {
+    /// \todo try to reload config file
+    signalSet.async_wait(std::bind(&terminate, std::ref(ioService), _1, _2, std::ref(signalSet)));
+  }
 }
 
 int
@@ -91,7 +92,7 @@
     ioService.run();
   }
   catch (const std::exception& e) {
-    std::cerr << "ERROR: " << e.what() << std::endl;
+    NDN_LOG_FATAL(repo::getExtendedErrorMessage(e));
     return 2;
   }
 
diff --git a/src/repo-command-parameter.cpp b/src/repo-command-parameter.cpp
index e7f7e15..2f4de5c 100644
--- a/src/repo-command-parameter.cpp
+++ b/src/repo-command-parameter.cpp
@@ -21,9 +21,8 @@
 
 #include <ndn-cxx/encoding/encoding-buffer.hpp>
 #include <ndn-cxx/encoding/block-helpers.hpp>
-#include <ndn-cxx/name.hpp>
-#include <ndn-cxx/selectors.hpp>
 #include <ndn-cxx/mgmt/control-parameters.hpp>
+#include <ndn-cxx/name.hpp>
 
 namespace repo {
 
@@ -37,14 +36,6 @@
 }
 
 RepoCommandParameter&
-RepoCommandParameter::setSelectors(const Selectors& selectors)
-{
-  m_selectors = selectors;
-  m_wire.reset();
-  return *this;
-}
-
-RepoCommandParameter&
 RepoCommandParameter::setStartBlockId(uint64_t startBlockId)
 {
   m_startBlockId  = startBlockId;
@@ -72,24 +63,6 @@
 }
 
 RepoCommandParameter&
-RepoCommandParameter::setMaxInterestNum(uint64_t maxInterestNum)
-{
-  m_maxInterestNum = maxInterestNum;
-  m_hasFields[REPO_PARAMETER_MAX_INTEREST_NUM] = true;
-  m_wire.reset();
-  return *this;
-}
-
-RepoCommandParameter&
-RepoCommandParameter::setWatchTimeout(milliseconds watchTimeout)
-{
-  m_watchTimeout = watchTimeout;
-  m_hasFields[REPO_PARAMETER_WATCH_TIME_OUT] = true;
-  m_wire.reset();
-  return *this;
-}
-
-RepoCommandParameter&
 RepoCommandParameter::setInterestLifetime(milliseconds interestLifetime)
 {
   m_interestLifetime = interestLifetime;
@@ -126,20 +99,6 @@
     totalLength += encoder.prependVarNumber(tlv::StartBlockId);
   }
 
-  if (m_hasFields[REPO_PARAMETER_MAX_INTEREST_NUM]) {
-    variableLength = encoder.prependNonNegativeInteger(m_maxInterestNum);
-    totalLength += variableLength;
-    totalLength += encoder.prependVarNumber(variableLength);
-    totalLength += encoder.prependVarNumber(tlv::MaxInterestNum);
-  }
-
-  if (m_hasFields[REPO_PARAMETER_WATCH_TIME_OUT]) {
-    variableLength = encoder.prependNonNegativeInteger(m_watchTimeout.count());
-    totalLength += variableLength;
-    totalLength += encoder.prependVarNumber(variableLength);
-    totalLength += encoder.prependVarNumber(tlv::WatchTimeout);
-  }
-
   if (m_hasFields[REPO_PARAMETER_INTEREST_LIFETIME]) {
     variableLength = encoder.prependNonNegativeInteger(m_interestLifetime.count());
     totalLength += variableLength;
@@ -147,10 +106,6 @@
     totalLength += encoder.prependVarNumber(tlv::InterestLifetime);
   }
 
-  if (!getSelectors().empty()) {
-    totalLength += getSelectors().wireEncode(encoder);
-  }
-
   if (m_hasFields[REPO_PARAMETER_NAME]) {
     totalLength += getName().wireEncode(encoder);
   }
@@ -196,15 +151,6 @@
     m_name.wireDecode(m_wire.get(tlv::Name));
   }
 
-  // Selectors
-  val = m_wire.find(tlv::Selectors);
-  if (val != m_wire.elements_end())
-  {
-    m_selectors.wireDecode(*val);
-  }
-  else
-    m_selectors = Selectors();
-
   // StartBlockId
   val = m_wire.find(tlv::StartBlockId);
   if (val != m_wire.elements_end())
@@ -229,22 +175,6 @@
     m_processId = readNonNegativeInteger(*val);
   }
 
-  // MaxInterestNum
-  val = m_wire.find(tlv::MaxInterestNum);
-  if (val != m_wire.elements_end())
-  {
-    m_hasFields[REPO_PARAMETER_MAX_INTEREST_NUM] = true;
-    m_maxInterestNum = readNonNegativeInteger(*val);
-  }
-
-  // WatchTimeout
-  val = m_wire.find(tlv::WatchTimeout);
-  if (val != m_wire.elements_end())
-  {
-    m_hasFields[REPO_PARAMETER_WATCH_TIME_OUT] = true;
-    m_watchTimeout = milliseconds(readNonNegativeInteger(*val));
-  }
-
   // InterestLifeTime
   val = m_wire.find(tlv::InterestLifetime);
   if (val != m_wire.elements_end())
@@ -275,14 +205,6 @@
   if (repoCommandParameter.hasProcessId()) {
     os << " ProcessId: " << repoCommandParameter.getProcessId();
   }
-  // MaxInterestNum
-  if (repoCommandParameter.hasMaxInterestNum()) {
-    os << " MaxInterestNum: " << repoCommandParameter.getMaxInterestNum();
-  }
-  // WatchTimeout
-  if (repoCommandParameter.hasProcessId()) {
-    os << " WatchTimeout: " << repoCommandParameter.getWatchTimeout();
-  }
   // InterestLifetime
   if (repoCommandParameter.hasProcessId()) {
     os << " InterestLifetime: " << repoCommandParameter.getInterestLifetime();
diff --git a/src/repo-command-parameter.hpp b/src/repo-command-parameter.hpp
index 1ad212f..6ce45f0 100644
--- a/src/repo-command-parameter.hpp
+++ b/src/repo-command-parameter.hpp
@@ -24,16 +24,14 @@
 
 #include <ndn-cxx/encoding/encoding-buffer.hpp>
 #include <ndn-cxx/encoding/block-helpers.hpp>
-#include <ndn-cxx/name.hpp>
-#include <ndn-cxx/selectors.hpp>
 #include <ndn-cxx/mgmt/control-parameters.hpp>
+#include <ndn-cxx/name.hpp>
 
 namespace repo {
 
 using ndn::Name;
 using ndn::Block;
 using ndn::EncodingImpl;
-using ndn::Selectors;
 using ndn::EncodingEstimator;
 using ndn::EncodingBuffer;
 using namespace ndn::time;
@@ -43,8 +41,6 @@
   REPO_PARAMETER_START_BLOCK_ID,
   REPO_PARAMETER_END_BLOCK_ID,
   REPO_PARAMETER_PROCESS_ID,
-  REPO_PARAMETER_MAX_INTEREST_NUM,
-  REPO_PARAMETER_WATCH_TIME_OUT,
   REPO_PARAMETER_INTEREST_LIFETIME,
   REPO_PARAMETER_UBOUND
 };
@@ -54,8 +50,6 @@
   "StartBlockId",
   "EndBlockId",
   "ProcessId",
-  "MaxInterestNum",
-  "WatchTimeout",
   "InterestLifetime"
 };
 
@@ -104,20 +98,6 @@
     return m_hasFields[REPO_PARAMETER_NAME];
   }
 
-  const Selectors&
-  getSelectors() const
-  {
-    return m_selectors;
-  }
-
-  RepoCommandParameter&
-  setSelectors(const Selectors& selectors);
-
-  bool
-  hasSelectors() const
-  {
-    return !m_selectors.empty();
-  }
 
   uint64_t
   getStartBlockId() const
@@ -167,38 +147,6 @@
     return m_hasFields[REPO_PARAMETER_PROCESS_ID];
   }
 
-  uint64_t
-  getMaxInterestNum() const
-  {
-    assert(hasMaxInterestNum());
-    return m_maxInterestNum;
-  }
-
-  RepoCommandParameter&
-  setMaxInterestNum(uint64_t maxInterestNum);
-
-  bool
-  hasMaxInterestNum() const
-  {
-    return m_hasFields[REPO_PARAMETER_MAX_INTEREST_NUM];
-  }
-
-  milliseconds
-  getWatchTimeout() const
-  {
-    assert(hasWatchTimeout());
-    return m_watchTimeout;
-  }
-
-  RepoCommandParameter&
-  setWatchTimeout(milliseconds watchTimeout);
-
-  bool
-  hasWatchTimeout() const
-  {
-    return m_hasFields[REPO_PARAMETER_WATCH_TIME_OUT];
-  }
-
   milliseconds
   getInterestLifetime() const
   {
@@ -233,12 +181,9 @@
 private:
   std::vector<bool> m_hasFields;
   Name m_name;
-  Selectors m_selectors;
   uint64_t m_startBlockId;
   uint64_t m_endBlockId;
   uint64_t m_processId;
-  uint64_t m_maxInterestNum;
-  milliseconds m_watchTimeout;
   milliseconds m_interestLifetime;
 
   mutable Block m_wire;
diff --git a/src/repo-command-response.hpp b/src/repo-command-response.hpp
index a2432a7..4f30ca5 100644
--- a/src/repo-command-response.hpp
+++ b/src/repo-command-response.hpp
@@ -150,7 +150,6 @@
   wireDecode(const Block& wire);
 
 private:
-  //uint64_t m_statusCode;
   uint64_t m_startBlockId;
   uint64_t m_endBlockId;
   uint64_t m_processId;
diff --git a/src/repo-command.cpp b/src/repo-command.cpp
index b8200d5..0c1cc21 100644
--- a/src/repo-command.cpp
+++ b/src/repo-command.cpp
@@ -67,27 +67,6 @@
     .required(REPO_PARAMETER_PROCESS_ID);
 }
 
-WatchStartCommand::WatchStartCommand()
-{
-  m_requestValidator
-    .required(REPO_PARAMETER_NAME)
-    .optional(REPO_PARAMETER_INTEREST_LIFETIME)
-    .optional(REPO_PARAMETER_MAX_INTEREST_NUM)
-    .optional(REPO_PARAMETER_WATCH_TIME_OUT);
-}
-
-WatchCheckCommand::WatchCheckCommand()
-{
-  m_requestValidator
-    .required(REPO_PARAMETER_NAME);
-}
-
-WatchStopCommand::WatchStopCommand()
-{
-  m_requestValidator
-    .required(REPO_PARAMETER_NAME);
-}
-
 DeleteCommand::DeleteCommand()
 {
   m_requestValidator
@@ -96,16 +75,6 @@
     .required(REPO_PARAMETER_END_BLOCK_ID)
     .required(REPO_PARAMETER_PROCESS_ID);
 }
-void
-InsertCommand::check(const RepoCommandParameter& parameters) const
-{
-  if (parameters.hasStartBlockId() || parameters.hasEndBlockId()) {
-    if (parameters.hasSelectors()) {
-      BOOST_THROW_EXCEPTION(ArgumentError("BlockId present. BlockId is not supported in this protocol"));
-      return;
-    }
-  }
-}
 
 void
 DeleteCommand::check(const RepoCommandParameter& parameters) const
diff --git a/src/repo-command.hpp b/src/repo-command.hpp
index 9b1dbe6..28c2999 100644
--- a/src/repo-command.hpp
+++ b/src/repo-command.hpp
@@ -96,10 +96,6 @@
 {
 public:
   InsertCommand();
-
-private:
-  void
-  check(const RepoCommandParameter& parameters) const override;
 };
 
 class InsertCheckCommand : public RepoCommand
@@ -108,24 +104,6 @@
   InsertCheckCommand();
 };
 
-class WatchStartCommand : public RepoCommand
-{
-public:
-  WatchStartCommand();
-};
-
-class WatchCheckCommand : public RepoCommand
-{
-public:
-  WatchCheckCommand();
-};
-
-class WatchStopCommand : public RepoCommand
-{
-public:
-  WatchStopCommand();
-};
-
 class DeleteCommand : public RepoCommand
 {
 public:
diff --git a/src/repo-tlv.hpp b/src/repo-tlv.hpp
index 45a6a0f..b8b9f15 100644
--- a/src/repo-tlv.hpp
+++ b/src/repo-tlv.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014,  Regents of the University of California.
+ * Copyright (c) 2018,  Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -36,11 +36,9 @@
   StatusCode           = 208,
   InsertNum            = 209,
   DeleteNum            = 210,
-  MaxInterestNum       = 211,
-  WatchTimeout         = 212
 };
 
-} // tlv
-} // repo
+} // namespace tlv
+} // namespace repo
 
 #endif // REPO_REPO_TLV_HPP
diff --git a/src/repo.cpp b/src/repo.cpp
index 955db96..9deef35 100644
--- a/src/repo.cpp
+++ b/src/repo.cpp
@@ -20,18 +20,22 @@
 #include "repo.hpp"
 #include "storage/sqlite-storage.hpp"
 
+#include <ndn-cxx/util/logger.hpp>
+
 namespace repo {
 
+NDN_LOG_INIT(repo);
+
 RepoConfig
 parseConfig(const std::string& configPath)
 {
   if (configPath.empty()) {
-    std::cerr << "configuration file path is empty" << std::endl;
+    NDN_LOG_DEBUG("configuration file path is empty");
   }
 
   std::ifstream fin(configPath.c_str());
  if (!fin.is_open())
-    BOOST_THROW_EXCEPTION(Repo::Error("failed to open configuration file '"+ configPath +"'"));
+    BOOST_THROW_EXCEPTION(Repo::Error("failed to open configuration file '" + configPath + "'"));
 
   using namespace boost::property_tree;
   ptree propertyTree;
@@ -39,7 +43,7 @@
     read_info(fin, propertyTree);
   }
   catch (const ptree_error& e) {
-    BOOST_THROW_EXCEPTION(Repo::Error("failed to read configuration file '"+ configPath +"'"));
+    BOOST_THROW_EXCEPTION(Repo::Error("failed to read configuration file '" + configPath + "'"));
   }
 
   ptree repoConf = propertyTree.get_child("repo");
@@ -74,11 +78,6 @@
   if (tcpBulkInsert) {
     for (const auto& section : *tcpBulkInsert) {
       isTcpBulkEnabled = true;
-
-      // tcp_bulk_insert {
-      //   host "localhost"  ; IP address or hostname to listen on
-      //   port 7635  ; Port number to listen on
-      // }
       if (section.first == "host") {
         host = section.second.get_value<std::string>();
       }
@@ -113,11 +112,10 @@
   , m_face(ioService)
   , m_dispatcher(m_face, m_keyChain)
   , m_store(std::make_shared<SqliteStorage>(config.dbPath))
-  , m_storageHandle(config.nMaxPackets, *m_store)
+  , m_storageHandle(*m_store)
   , m_validator(m_face)
   , m_readHandle(m_face, m_storageHandle, m_config.registrationSubset)
   , m_writeHandle(m_face, m_storageHandle, m_dispatcher, m_scheduler, m_validator)
-  , m_watchHandle(m_face, m_storageHandle, m_dispatcher, m_scheduler, m_validator)
   , m_deleteHandle(m_face, m_storageHandle, m_dispatcher, m_scheduler, m_validator)
   , m_tcpBulkInsertHandle(ioService, m_storageHandle)
 {
@@ -129,10 +127,9 @@
 {
   // Rebuild storage if storage checkpoin exists
   ndn::time::steady_clock::TimePoint start = ndn::time::steady_clock::now();
-  m_storageHandle.initialize();
   ndn::time::steady_clock::TimePoint end = ndn::time::steady_clock::now();
   ndn::time::milliseconds cost = ndn::time::duration_cast<ndn::time::milliseconds>(end - start);
-  std::cerr << "initialize storage cost: " << cost << "ms" << std::endl;
+  NDN_LOG_DEBUG("initialize storage cost: " << cost << "ms");
 }
 
 void
@@ -145,7 +142,7 @@
   for (const ndn::Name& cmdPrefix : m_config.repoPrefixes) {
     m_face.registerPrefix(cmdPrefix, nullptr,
       [] (const Name& cmdPrefix, const std::string& reason) {
-        std::cerr << "Command prefix " << cmdPrefix << " registration error: " << reason << std::endl;
+        NDN_LOG_DEBUG("Command prefix " << cmdPrefix << " registration error: " << reason);
         BOOST_THROW_EXCEPTION(Error("Command prefix registration failed"));
       });
 
diff --git a/src/repo.hpp b/src/repo.hpp
index e417960..21f314d 100644
--- a/src/repo.hpp
+++ b/src/repo.hpp
@@ -26,7 +26,6 @@
 #include "handles/delete-handle.hpp"
 #include "handles/read-handle.hpp"
 #include "handles/tcp-bulk-insert-handle.hpp"
-#include "handles/watch-handle.hpp"
 #include "handles/write-handle.hpp"
 
 #include "common.hpp"
@@ -44,12 +43,11 @@
   static const size_t DISABLED_SUBSET_LENGTH = -1;
 
   std::string repoConfigPath;
-  //StorageMethod storageMethod; This will be implemtented if there is other method.
   std::string dbPath;
   std::vector<ndn::Name> dataPrefixes;
   size_t registrationSubset = DISABLED_SUBSET_LENGTH;
   std::vector<ndn::Name> repoPrefixes;
-  std::vector<std::pair<std::string, std::string> > tcpBulkInsertEndpoints;
+  std::vector<std::pair<std::string, std::string>> tcpBulkInsertEndpoints;
   uint64_t nMaxPackets;
   boost::property_tree::ptree validatorNode;
 };
@@ -95,7 +93,6 @@
 
   ReadHandle m_readHandle;
   WriteHandle m_writeHandle;
-  WatchHandle m_watchHandle;
   DeleteHandle m_deleteHandle;
   TcpBulkInsertHandle m_tcpBulkInsertHandle;
 };
diff --git a/src/storage/index.cpp b/src/storage/index.cpp
deleted file mode 100644
index 3eb2cce..0000000
--- a/src/storage/index.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2017, Regents of the University of California.
- *
- * This file is part of NDN repo-ng (Next generation of NDN repository).
- * See AUTHORS.md for complete list of repo-ng authors and contributors.
- *
- * repo-ng 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.
- *
- * repo-ng 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
- * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "index.hpp"
-
-#include <ndn-cxx/util/sha256.hpp>
-#include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
-
-namespace repo {
-
-/** @brief determines if entry can satisfy interest
- *  @param hash SHA256 hash of PublisherPublicKeyLocator if exists in interest, otherwise ignored
- */
-static bool
-matchesSimpleSelectors(const Interest& interest, ndn::ConstBufferPtr& hash,
-                       const Index::Entry& entry)
-{
-  const Name& fullName = entry.getName();
-
-  if (!interest.getName().isPrefixOf(fullName))
-    return false;
-
-  size_t nSuffixComponents = fullName.size() - interest.getName().size();
-  if (interest.getMinSuffixComponents() >= 0 &&
-      nSuffixComponents < static_cast<size_t>(interest.getMinSuffixComponents()))
-    return false;
-  if (interest.getMaxSuffixComponents() >= 0 &&
-      nSuffixComponents > static_cast<size_t>(interest.getMaxSuffixComponents()))
-    return false;
-
-  if (!interest.getExclude().empty() &&
-      entry.getName().size() > interest.getName().size() &&
-      interest.getExclude().isExcluded(entry.getName()[interest.getName().size()]))
-    return false;
-  if (!interest.getPublisherPublicKeyLocator().empty())
-    {
-      if (*entry.getKeyLocatorHash() != *hash)
-          return false;
-    }
-  return true;
-}
-
-Index::Index(size_t nMaxPackets)
-  : m_maxPackets(nMaxPackets)
-  , m_size(0)
-{
-}
-
-
-bool
-Index::insert(const Data& data, int64_t id)
-{
-  if (isFull())
-    BOOST_THROW_EXCEPTION(Error("The Index is Full. Cannot Insert Any Data!"));
-  Entry entry(data, id);
-  bool isInserted = m_indexContainer.insert(entry).second;
-  if (isInserted)
-    ++m_size;
-  return isInserted;
-}
-
-bool
-Index::insert(const Name& fullName, int64_t id,
-              const ndn::ConstBufferPtr& keyLocatorHash)
-{
-  if (isFull())
-    BOOST_THROW_EXCEPTION(Error("The Index is Full. Cannot Insert Any Data!"));
-  Entry entry(fullName, keyLocatorHash, id);
-  bool isInserted = m_indexContainer.insert(entry).second;
-  if (isInserted)
-    ++m_size;
-  return isInserted;
-}
-
-std::pair<int64_t,Name>
-Index::find(const Interest& interest) const
-{
-  Name name = interest.getName();
-  IndexContainer::const_iterator result = m_indexContainer.lower_bound(name);
-  if (result != m_indexContainer.end())
-    {
-      return selectChild(interest, result);
-    }
-  else
-    {
-      return std::make_pair(0, Name());
-    }
-}
-
-std::pair<int64_t,Name>
-Index::find(const Name& name) const
-{
-  IndexContainer::const_iterator result = m_indexContainer.lower_bound(name);
-  if (result != m_indexContainer.end())
-    {
-      return findFirstEntry(name, result);
-    }
-  else
-    {
-      return std::make_pair(0, Name());
-    }
-}
-
-bool
-Index::hasData(const Data& data) const
-{
-  Index::Entry entry(data, -1); // the id number is useless
-  IndexContainer::const_iterator result = m_indexContainer.find(entry);
-  return result != m_indexContainer.end();
-
-}
-
-std::pair<int64_t,Name>
-Index::findFirstEntry(const Name& prefix,
-                      IndexContainer::const_iterator startingPoint) const
-{
-  BOOST_ASSERT(startingPoint != m_indexContainer.end());
-  if (prefix.isPrefixOf(startingPoint->getName()))
-    {
-      return std::make_pair(startingPoint->getId(), startingPoint->getName());
-    }
-  else
-    {
-      return std::make_pair(0, Name());
-    }
-}
-
-bool
-Index::erase(const Name& fullName)
-{
-  Entry entry(fullName);
-  IndexContainer::const_iterator findIterator = m_indexContainer.find(entry);
-  if (findIterator != m_indexContainer.end())
-    {
-      m_indexContainer.erase(findIterator);
-      m_size--;
-      return true;
-    }
-  else
-    return false;
-}
-
-const ndn::ConstBufferPtr
-Index::computeKeyLocatorHash(const KeyLocator& keyLocator)
-{
-  const Block& block = keyLocator.wireEncode();
-  ndn::ConstBufferPtr keyLocatorHash = ndn::util::Sha256::computeDigest(block.wire(), block.size());
-  return keyLocatorHash;
-}
-
-std::pair<int64_t,Name>
-Index::selectChild(const Interest& interest,
-                   IndexContainer::const_iterator startingPoint) const
-{
-  BOOST_ASSERT(startingPoint != m_indexContainer.end());
-  bool isLeftmost = (interest.getChildSelector() <= 0);
-  ndn::ConstBufferPtr hash;
-  if (!interest.getPublisherPublicKeyLocator().empty())
-    {
-      KeyLocator keyLocator = interest.getPublisherPublicKeyLocator();
-      const Block& block = keyLocator.wireEncode();
-      hash = ndn::util::Sha256::computeDigest(block.wire(), block.size());
-    }
-
-  if (isLeftmost)
-    {
-      for (IndexContainer::const_iterator it = startingPoint;
-           it != m_indexContainer.end(); ++it)
-        {
-          if (!interest.getName().isPrefixOf(it->getName()))
-            return std::make_pair(0, Name());
-          if (matchesSimpleSelectors(interest, hash, (*it)))
-            return std::make_pair(it->getId(), it->getName());
-        }
-    }
-  else
-    {
-      IndexContainer::const_iterator boundary = m_indexContainer.lower_bound(interest.getName());
-      if (boundary == m_indexContainer.end() || !interest.getName().isPrefixOf(boundary->getName()))
-        return std::make_pair(0, Name());
-      Name successor = interest.getName().getSuccessor();
-      IndexContainer::const_iterator last = interest.getName().size() == 0 ?
-                    m_indexContainer.end() : m_indexContainer.lower_bound(interest.getName().getSuccessor());
-      while (true)
-        {
-          IndexContainer::const_iterator prev = last;
-          --prev;
-          if (prev == boundary)
-            {
-              bool isMatch = matchesSimpleSelectors(interest, hash, (*prev));
-              if (isMatch)
-                {
-                  return std::make_pair(prev->getId(), prev->getName());
-                }
-              else
-                return std::make_pair(0, Name());
-            }
-          IndexContainer::const_iterator first =
-            m_indexContainer.lower_bound(prev->getName().getPrefix(interest.getName().size() + 1));
-          IndexContainer::const_iterator match =
-                     std::find_if(first, last, bind(&matchesSimpleSelectors, interest, hash, _1));
-          if (match != last)
-            {
-              return std::make_pair(match->getId(), match->getName());
-            }
-          last = first;
-        }
-    }
-  return std::make_pair(0, Name());
-}
-
-Index::Entry::Entry(const Data& data, int64_t id)
-  : m_name(data.getFullName())
-  , m_id(id)
-{
-  const ndn::Signature& signature = data.getSignature();
-  if (signature.hasKeyLocator())
-    m_keyLocatorHash = computeKeyLocatorHash(signature.getKeyLocator());
-}
-
-Index::Entry::Entry(const Name& fullName, const KeyLocator& keyLocator, int64_t id)
-  : m_name(fullName)
-  , m_keyLocatorHash(computeKeyLocatorHash(keyLocator))
-  , m_id(id)
-{
-}
-
-Index::Entry::Entry(const Name& fullName,
-                    const ndn::ConstBufferPtr& keyLocatorHash, int64_t id)
-  : m_name(fullName)
-  , m_keyLocatorHash(keyLocatorHash)
-  , m_id(id)
-{
-}
-
-Index::Entry::Entry(const Name& name)
-  : m_name(name)
-{
-}
-
-} // namespace repo
diff --git a/src/storage/index.hpp b/src/storage/index.hpp
deleted file mode 100644
index d60bd37..0000000
--- a/src/storage/index.hpp
+++ /dev/null
@@ -1,243 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2018, Regents of the University of California.
- *
- * This file is part of NDN repo-ng (Next generation of NDN repository).
- * See AUTHORS.md for complete list of repo-ng authors and contributors.
- *
- * repo-ng 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.
- *
- * repo-ng 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
- * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef REPO_STORAGE_INDEX_HPP
-#define REPO_STORAGE_INDEX_HPP
-
-#include "../common.hpp"
-
-#include <set>
-
-namespace repo {
-
-class Index : noncopyable
-{
-public:
-  class Error : public std::runtime_error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : std::runtime_error(what)
-    {
-    }
-  };
-
-  class Entry
-  {
-  public:
-    class Error : public std::runtime_error
-    {
-    public:
-      explicit
-      Error(const std::string& what)
-        : std::runtime_error(what)
-      {
-      }
-    };
-
-  public:
-    /**
-     * @brief used by set to construct node
-     */
-    Entry() = default;
-
-    /**
-     * @brief construct Entry by data and id number
-     */
-    Entry(const Data& data, int64_t id);
-
-    /**
-     * @brief construct Entry by fullName, keyLocator and id number
-     */
-    Entry(const Name& fullName, const KeyLocator& keyLocator, int64_t id);
-
-    /**
-     * @brief construct Entry by fullName, keyLocatorHash and id number
-     * @param  fullName        full name with digest computed from data
-     * @param  keyLocatorHash  keyLocator hashed by sha256
-     * @param  id              record ID from database
-     */
-    Entry(const Name& fullName, const ndn::ConstBufferPtr& keyLocatorHash, int64_t id);
-
-    /**
-     *  @brief implicit construct Entry by full name
-     *
-     *  Allow implicit conversion from Name for set lookups by Name
-     */
-    Entry(const Name& name);
-
-    /**
-     *  @brief get the name of entry
-     */
-    const Name&
-    getName() const
-    {
-      return m_name;
-    }
-
-    /**
-     *  @brief get the keyLocator hash value of the entry
-     */
-    const ndn::ConstBufferPtr&
-    getKeyLocatorHash() const
-    {
-      return m_keyLocatorHash;
-    }
-
-    /**
-     *  @brief get record ID from database
-     */
-    int64_t
-    getId() const
-    {
-      return m_id;
-    }
-
-    bool
-    operator>(const Entry& entry) const
-    {
-      return m_name > entry.getName();
-    }
-
-    bool
-    operator<(const Entry& entry) const
-    {
-      return m_name < entry.getName();
-    }
-
-    bool
-    operator==(const Entry& entry) const
-    {
-      return m_name == entry.getName();
-    }
-
-    bool
-    operator!=(const Entry& entry) const
-    {
-      return m_name != entry.getName();
-    }
-
-  private:
-    Name m_name;
-    ndn::ConstBufferPtr m_keyLocatorHash;
-    int64_t m_id;
-  };
-
-private:
-  typedef std::set<Entry> IndexContainer;
-
-public:
-  explicit
-  Index(size_t nMaxPackets);
-
-  /**
-   *  @brief insert entries into index
-   *  @param  data    used to construct entries
-   *  @param  id      obtained from database
-   */
-  bool
-  insert(const Data& data, int64_t id);
-
-  /**
-   *  @brief insert entries into index
-   *  @param  data    used to construct entries
-   *  @param  id      obtained from database
-   */
-  bool
-  insert(const Name& fullName, int64_t id,
-         const ndn::ConstBufferPtr& keyLocatorHash);
-
-  /**
-   *  @brief erase the entry in index by its fullname
-   */
-  bool
-  erase(const Name& fullName);
-
-  /** @brief find the Entry for best match of an Interest
-   * @return ID and fullName of the Entry, or (0,ignored) if not found
-   */
-  std::pair<int64_t, Name>
-  find(const Interest& interest) const;
-
-  /** @brief find the first Entry under a Name prefix
-   * @return ID and fullName of the Entry, or (0,ignored) if not found
-   */
-  std::pair<int64_t, Name>
-  find(const Name& name) const;
-
-  /**
-   *  @brief determine whether same Data is already in the index
-   *  @return true if identical Data exists, false otherwise
-   */
-  bool
-  hasData(const Data& data) const;
-
-  /**
-    *  @brief compute the hash value of keyLocator
-    */
-  static const ndn::ConstBufferPtr
-  computeKeyLocatorHash(const KeyLocator& keyLocator);
-
-  size_t
-  size() const
-  {
-    return m_size;
-  }
-
-private:
-  /**
-   *  @brief select entries which satisfy the selectors in interest and return their name
-   *  @param  interest   used to select entries by comparing the name and checking selectors
-   *  @param  idName    save the id and name of found entries
-   *  @param  startingPoint the entry whose name is equal or larger than the interest name
-   */
-  std::pair<int64_t, Name>
-  selectChild(const Interest& interest,
-              IndexContainer::const_iterator startingPoint) const;
-
-  /**
-   *  @brief check whether the index is full
-   */
-  bool
-  isFull() const
-  {
-    return m_size >= m_maxPackets;
-  }
-
-  /**
-   *  @brief find the first entry with the prefix
-   *  @param  prefix        used to request the entries
-   *  @param  startingPoint the entry whose name is equal or larger than the interest name
-   *  @return int64_t  the id number of found entry
-   *  @return Name     the name of found entry
-   */
-  std::pair<int64_t, Name>
-  findFirstEntry(const Name& prefix,
-                 IndexContainer::const_iterator startingPoint) const;
-
-private:
-  IndexContainer m_indexContainer;
-  size_t m_maxPackets;
-  size_t m_size;
-};
-
-} // namespace repo
-
-#endif // REPO_STORAGE_INDEX_HPP
diff --git a/src/storage/repo-storage.cpp b/src/storage/repo-storage.cpp
index 148116b..334b4d3 100644
--- a/src/storage/repo-storage.cpp
+++ b/src/storage/repo-storage.cpp
@@ -28,62 +28,52 @@
 
 NDN_LOG_INIT(repo.RepoStorage);
 
-RepoStorage::RepoStorage(const int64_t& nMaxPackets, Storage& store)
-  : m_index(nMaxPackets)
-  , m_storage(store)
+RepoStorage::RepoStorage(Storage& store)
+  : m_storage(store)
 {
 }
 
-void
-RepoStorage::initialize()
-{
-  NDN_LOG_DEBUG("Initialize");
-  m_storage.fullEnumerate(bind(&RepoStorage::insertItemToIndex, this, _1));
-}
-
-void
-RepoStorage::insertItemToIndex(const Storage::ItemMeta& item)
-{
-  NDN_LOG_DEBUG("Insert data to index " << item.fullName);
-  m_index.insert(item.fullName, item.id, item.keyLocatorHash);
-  afterDataInsertion(item.fullName);
-}
-
 bool
 RepoStorage::insertData(const Data& data)
 {
-   bool isExist = m_index.hasData(data);
-   if (isExist)
-     BOOST_THROW_EXCEPTION(Error("The Entry Has Already In the Skiplist. Cannot be Inserted!"));
-   int64_t id = m_storage.insert(data);
-   if (id == -1)
-     return false;
-   bool didInsert = m_index.insert(data, id);
-   if (didInsert)
-     afterDataInsertion(data.getName());
-   return didInsert;
+  bool isExist = m_storage.has(data.getFullName());
+
+  if (isExist) {
+    NDN_LOG_DEBUG("Data already in storage, regarded as successful data insertion");
+    return true;
+  }
+
+  int64_t id = m_storage.insert(data);
+  NDN_LOG_DEBUG("Insert ID: " << id << ", full name:" << data.getFullName());
+  if (id == NOTFOUND)
+    return false;
+
+  afterDataInsertion(data.getName());
+  return true;
 }
 
 ssize_t
 RepoStorage::deleteData(const Name& name)
 {
+  NDN_LOG_DEBUG("Delete: " << name);
   bool hasError = false;
-  std::pair<int64_t,ndn::Name> idName = m_index.find(name);
-  if (idName.first == 0)
-    return false;
+
   int64_t count = 0;
-  while (idName.first != 0) {
-    bool resultDb = m_storage.erase(idName.first);
-    bool resultIndex = m_index.erase(idName.second); //full name
-    if (resultDb && resultIndex) {
-      afterDataDeletion(idName.second);
+  std::shared_ptr<Data> foundData;
+  Name foundName;
+  while ((foundData = m_storage.find(name))) {
+    foundName = foundData->getFullName();
+    bool resultDb = m_storage.erase(foundName);
+    if (resultDb) {
+      afterDataDeletion(foundName);
       count++;
     }
     else {
       hasError = true;
     }
-    idName = m_index.find(name);
+    NDN_LOG_DEBUG("Delete: " << name << ", found " << foundName << ", count " << count << ", result " << resultDb);
   }
+
   if (hasError)
     return -1;
   else
@@ -93,40 +83,15 @@
 ssize_t
 RepoStorage::deleteData(const Interest& interest)
 {
-  Interest interestDelete = interest;
-  interestDelete.setChildSelector(0);  //to disable the child selector in delete handle
-  int64_t count = 0;
-  bool hasError = false;
-  std::pair<int64_t,ndn::Name> idName = m_index.find(interestDelete);
-  while (idName.first != 0) {
-    bool resultDb = m_storage.erase(idName.first);
-    bool resultIndex = m_index.erase(idName.second); //full name
-    if (resultDb && resultIndex) {
-      afterDataDeletion(idName.second);
-      count++;
-    }
-    else {
-      hasError = true;
-    }
-    idName = m_index.find(interestDelete);
-  }
-  if (hasError)
-    return -1;
-  else
-    return count;
+  return deleteData(interest.getName());
 }
 
-shared_ptr<Data>
+std::shared_ptr<Data>
 RepoStorage::readData(const Interest& interest) const
 {
-  std::pair<int64_t,ndn::Name> idName = m_index.find(interest);
-  if (idName.first != 0) {
-    shared_ptr<Data> data = m_storage.read(idName.first);
-    if (data) {
-      return data;
-    }
-  }
-  return shared_ptr<Data>();
+  NDN_LOG_DEBUG("Reading data for " << interest.getName());
+
+  return m_storage.read(interest.getName());
 }
 
 
diff --git a/src/storage/repo-storage.hpp b/src/storage/repo-storage.hpp
index ec5faa7..39e576d 100644
--- a/src/storage/repo-storage.hpp
+++ b/src/storage/repo-storage.hpp
@@ -22,10 +22,8 @@
 
 #include "../common.hpp"
 #include "storage.hpp"
-#include "index.hpp"
 #include "../repo-command-parameter.hpp"
 
-#include <ndn-cxx/exclude.hpp>
 #include <ndn-cxx/util/signal.hpp>
 
 #include <queue>
@@ -50,13 +48,7 @@
   };
 
 public:
-  RepoStorage(const int64_t& nMaxPackets, Storage& store);
-
-  /**
-   *  @brief  rebuild index from database
-   */
-  void
-  initialize();
+  RepoStorage(Storage& store);
 
   /**
    *  @brief  insert data into repo
@@ -66,7 +58,7 @@
 
   /**
    *  @brief   delete data from repo
-   *  @param   name     used to find entry needed to be erased in repo
+   *  @param   name from interest, use it as a prefix to find entry needed to be erased in repo
    *  @return  if deletion in either index or database fail, return -1,
    *           otherwise return the number of erased entries
    */
@@ -83,24 +75,20 @@
   deleteData(const Interest& interest);
 
   /**
-   *  @brief  read data from repo
+   *  @brief   read data from repo
    *  @param   interest  used to request data
    *  @return  std::shared_ptr<Data>
    */
   std::shared_ptr<Data>
   readData(const Interest& interest) const;
 
-private:
-  void
-  insertItemToIndex(const Storage::ItemMeta& item);
-
 public:
   ndn::util::Signal<RepoStorage, ndn::Name> afterDataInsertion;
   ndn::util::Signal<RepoStorage, ndn::Name> afterDataDeletion;
 
 private:
-  Index m_index;
   Storage& m_storage;
+  const int NOTFOUND = -1;
 };
 
 } // namespace repo
diff --git a/src/storage/sqlite-storage.cpp b/src/storage/sqlite-storage.cpp
index 42739c3..91016ea 100644
--- a/src/storage/sqlite-storage.cpp
+++ b/src/storage/sqlite-storage.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017, Regents of the University of California.
+ * Copyright (c) 2014-2018, Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -19,23 +19,25 @@
 
 #include "sqlite-storage.hpp"
 #include "config.hpp"
-#include "index.hpp"
 
 #include <ndn-cxx/util/sha256.hpp>
+#include <ndn-cxx/util/sqlite3-statement.hpp>
+
 #include <boost/filesystem.hpp>
 #include <istream>
 
+#include <ndn-cxx/util/logger.hpp>
+
 namespace repo {
 
-using std::string;
+NDN_LOG_INIT(repo.SqliteStorage);
 
-SqliteStorage::SqliteStorage(const string& dbPath)
-  : m_size(0)
+SqliteStorage::SqliteStorage(const std::string& dbPath)
 {
   if (dbPath.empty()) {
-    std::cerr << "Create db file in local location [" << dbPath << "]. " << std::endl
-              << "You can assign the path using -d option" << std::endl;
-    m_dbPath = string("ndn_repo.db");
+    m_dbPath = std::string("ndn_repo.db");
+    NDN_LOG_DEBUG("Create db file in local location [" << m_dbPath << "]. " );
+    NDN_LOG_DEBUG("You can assign the path using -d option" );
   }
   else {
     boost::filesystem::path fsPath(dbPath);
@@ -55,32 +57,31 @@
 void
 SqliteStorage::initializeRepo()
 {
-  char* errMsg = 0;
-
+  char* errMsg = nullptr;
   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
+                           nullptr
 #endif
-                           );
+                          );
 
   if (rc == SQLITE_OK) {
-    sqlite3_exec(m_db, "CREATE TABLE NDN_REPO ("
-                      "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
-                      "name BLOB, "
-                      "data BLOB, "
-                      "keylocatorHash BLOB);\n "
-                 , 0, 0, &errMsg);
+    // Create a new table named NDN_REPO_V2, distinguish from the old table name(NDN_REPO)
+    sqlite3_exec(m_db, "CREATE TABLE NDN_REPO_V2 (name BLOB, data BLOB);", nullptr, nullptr, &errMsg);
     // Ignore errors (when database already exists, errors are expected)
+    sqlite3_exec(m_db, "CREATE UNIQUE INDEX index_name ON NDN_REPO_V2 (name);", nullptr, nullptr, &errMsg);
   }
   else {
-    std::cerr << "Database file open failure rc:" << rc << std::endl;
+    NDN_LOG_DEBUG("Database file open failure rc:" << rc);
     BOOST_THROW_EXCEPTION(Error("Database file open failure"));
   }
-  sqlite3_exec(m_db, "PRAGMA synchronous = OFF", 0, 0, &errMsg);
-  sqlite3_exec(m_db, "PRAGMA journal_mode = WAL", 0, 0, &errMsg);
+
+  // SQLite continues without syncing as soon as it has handed data off to the operating system
+  sqlite3_exec(m_db, "PRAGMA synchronous = OFF;", nullptr, nullptr, &errMsg);
+  // Uses a write-ahead log instead of a rollback journal to implement transactions.
+  sqlite3_exec(m_db, "PRAGMA journal_mode = WAL;", nullptr, nullptr, &errMsg);
 }
 
 SqliteStorage::~SqliteStorage()
@@ -88,211 +89,158 @@
   sqlite3_close(m_db);
 }
 
-void
-SqliteStorage::fullEnumerate(const std::function<void(const Storage::ItemMeta)>& f)
-{
-  sqlite3_stmt* m_stmt = 0;
-  int rc = SQLITE_DONE;
-  string sql = string("SELECT id, name, keylocatorHash FROM NDN_REPO;");
-  rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &m_stmt, 0);
-  if (rc != SQLITE_OK)
-    BOOST_THROW_EXCEPTION(Error("Initiation Read Entries from Database Prepare error"));
-  int entryNumber = 0;
-  while (true) {
-    rc = sqlite3_step(m_stmt);
-    if (rc == SQLITE_ROW) {
-
-      ItemMeta item;
-      item.fullName.wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(m_stmt, 1)),
-                                     sqlite3_column_bytes(m_stmt, 1)));
-      item.id = sqlite3_column_int(m_stmt, 0);
-      item.keyLocatorHash = make_shared<const ndn::Buffer>(sqlite3_column_blob(m_stmt, 3),
-                                                           sqlite3_column_bytes(m_stmt, 3));
-
-      try {
-        f(item);
-      }
-      catch (...) {
-        sqlite3_finalize(m_stmt);
-        throw;
-      }
-      entryNumber++;
-    }
-    else if (rc == SQLITE_DONE) {
-      sqlite3_finalize(m_stmt);
-      break;
-    }
-    else {
-      std::cerr << "Initiation Read Entries rc:" << rc << std::endl;
-      sqlite3_finalize(m_stmt);
-      BOOST_THROW_EXCEPTION(Error("Initiation Read Entries error"));
-    }
-  }
-  m_size = entryNumber;
-}
-
 int64_t
 SqliteStorage::insert(const Data& data)
 {
-  Name name = data.getName();
+  Name name = data.getFullName(); // store the full name
+  ndn::util::Sqlite3Statement stmt(m_db, "INSERT INTO NDN_REPO_V2 (name, data) VALUES (?, ?);");
 
-  Index::Entry entry(data, 0); //the id is not used
-  int64_t id = -1;
-  if (name.empty()) {
-    std::cerr << "name is empty" << std::endl;
-    return -1;
-  }
-
-  int rc = 0;
-
-  sqlite3_stmt* insertStmt = 0;
-
-  string insertSql = string("INSERT INTO NDN_REPO (id, name, data, keylocatorHash) "
-                            "VALUES (?, ?, ?, ?)");
-
-  if (sqlite3_prepare_v2(m_db, insertSql.c_str(), -1, &insertStmt, 0) != SQLITE_OK) {
-    sqlite3_finalize(insertStmt);
-    std::cerr << "insert sql not prepared" << std::endl;
-  }
   //Insert
-  auto result = sqlite3_bind_null(insertStmt, 1);
+  // Bind NULL to name value in NDN_REPO_V2 when initialize result.
+  auto result = sqlite3_bind_null(stmt, 1);
   if (result == SQLITE_OK) {
-    result = sqlite3_bind_blob(insertStmt, 2,
-                               entry.getName().wireEncode().wire(),
-                               entry.getName().wireEncode().size(), SQLITE_STATIC);
+    result = stmt.bind(1, name.wireEncode().value(),
+                          name.wireEncode().value_size(), SQLITE_STATIC);
   }
   if (result == SQLITE_OK) {
-    result = sqlite3_bind_blob(insertStmt, 3,
-                               data.wireEncode().wire(),
-                               data.wireEncode().size(), SQLITE_STATIC);
-  }
-  if (result == SQLITE_OK) {
-    BOOST_ASSERT(entry.getKeyLocatorHash()->size() == ndn::util::Sha256::DIGEST_SIZE);
-    result = sqlite3_bind_blob(insertStmt, 4,
-                               entry.getKeyLocatorHash()->data(),
-                               entry.getKeyLocatorHash()->size(), SQLITE_STATIC);
+    result = stmt.bind(2, data.wireEncode(), SQLITE_STATIC);
   }
 
+  int id = 0;
   if (result == SQLITE_OK) {
-    rc = sqlite3_step(insertStmt);
+    int rc = 0;
+    rc = stmt.step();
     if (rc == SQLITE_CONSTRAINT) {
-      std::cerr << "Insert failed" << std::endl;
-      sqlite3_finalize(insertStmt);
+      NDN_LOG_DEBUG("Insert failed");
       BOOST_THROW_EXCEPTION(Error("Insert failed"));
-     }
-    sqlite3_reset(insertStmt);
-     m_size++;
-     id = sqlite3_last_insert_rowid(m_db);
+    }
+    sqlite3_reset(stmt);
+    id = sqlite3_last_insert_rowid(m_db);
   }
   else {
     BOOST_THROW_EXCEPTION(Error("Some error with insert"));
   }
-
-  sqlite3_finalize(insertStmt);
   return id;
 }
 
-
 bool
-SqliteStorage::erase(const int64_t id)
+SqliteStorage::erase(const Name& name)
 {
-  sqlite3_stmt* deleteStmt = 0;
+  ndn::util::Sqlite3Statement stmt(m_db, "DELETE FROM NDN_REPO_V2 WHERE name = ?;");
 
-  string deleteSql = string("DELETE from NDN_REPO where id = ?;");
+  auto result = stmt.bind(1,
+                          name.wireEncode().value(),
+                          name.wireEncode().value_size(), SQLITE_STATIC);
 
-  if (sqlite3_prepare_v2(m_db, deleteSql.c_str(), -1, &deleteStmt, 0) != SQLITE_OK) {
-    sqlite3_finalize(deleteStmt);
-    std::cerr << "delete statement prepared failed" << std::endl;
-    BOOST_THROW_EXCEPTION(Error("delete statement prepared failed"));
-  }
-
-  if (sqlite3_bind_int64(deleteStmt, 1, id) == SQLITE_OK) {
-    int rc = sqlite3_step(deleteStmt);
+  if (result == SQLITE_OK) {
+    int rc = stmt.step();
     if (rc != SQLITE_DONE && rc != SQLITE_ROW) {
-      std::cerr << " node delete error rc:" << rc << std::endl;
-      sqlite3_finalize(deleteStmt);
-      BOOST_THROW_EXCEPTION(Error(" node delete error"));
+      NDN_LOG_DEBUG("Node delete error rc:" << rc);
+      BOOST_THROW_EXCEPTION(Error("Node delete error"));
     }
-    if (sqlite3_changes(m_db) != 1)
+    if (sqlite3_changes(m_db) != 1) {
       return false;
-    m_size--;
+    }
   }
   else {
-    std::cerr << "delete bind error" << std::endl;
-    sqlite3_finalize(deleteStmt);
+    NDN_LOG_DEBUG("delete bind error");
     BOOST_THROW_EXCEPTION(Error("delete bind error"));
   }
-  sqlite3_finalize(deleteStmt);
   return true;
 }
 
-
-shared_ptr<Data>
-SqliteStorage::read(const int64_t id)
+std::shared_ptr<Data>
+SqliteStorage::read(const Name& name)
 {
-  sqlite3_stmt* queryStmt = 0;
-  string sql = string("SELECT * FROM NDN_REPO WHERE id = ? ;");
-  int rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
-  if (rc == SQLITE_OK) {
-    if (sqlite3_bind_int64(queryStmt, 1, id) == SQLITE_OK) {
-      rc = sqlite3_step(queryStmt);
-      if (rc == SQLITE_ROW) {
-        auto data = make_shared<Data>();
-        data->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(queryStmt, 2)),
-                               sqlite3_column_bytes(queryStmt, 2)));
-        sqlite3_finalize(queryStmt);
-        return data;
+  return find(name);
+}
+
+bool
+SqliteStorage::has(const Name& name)
+{
+  // find exact match
+  return find(name, true) != nullptr;
+}
+
+std::shared_ptr<Data>
+SqliteStorage::find(const Name& name, bool exactMatch)
+{
+  NDN_LOG_DEBUG("Trying to find: " << name);
+  Name nameSuccessor;
+  if (!exactMatch) {
+    nameSuccessor = name.getSuccessor();
+  }
+
+  std::string sql;
+  if (exactMatch)
+    sql = "SELECT * FROM NDN_REPO_V2 WHERE name = ?;";
+  else
+    sql = "SELECT * FROM NDN_REPO_V2 WHERE name >= ? and name < ?;";
+
+  ndn::util::Sqlite3Statement stmt(m_db, sql);
+
+  auto result = stmt.bind(1,
+                          name.wireEncode().value(),
+                          name.wireEncode().value_size(), SQLITE_STATIC);
+
+  // use getsuccessor to locate prefix match items
+  if (result == SQLITE_OK && !exactMatch) {
+    // use V in TLV for prefix match when there is no exact match
+    result = stmt.bind(2,
+                       nameSuccessor.wireEncode().value(),
+                       nameSuccessor.wireEncode().value_size(), SQLITE_STATIC);
+  }
+
+  if (result == SQLITE_OK) {
+    int rc = stmt.step();
+    if (rc == SQLITE_ROW) {
+      Name foundName;
+
+      auto data = std::make_shared<Data>();
+      try {
+        data->wireDecode(stmt.getBlock(1));
       }
-      else if (rc == SQLITE_DONE) {
+      catch (const ndn::Block::Error& error) {
+        NDN_LOG_DEBUG(error.what());
         return nullptr;
       }
-      else {
-        std::cerr << "Database query failure rc:" << rc << std::endl;
-        sqlite3_finalize(queryStmt);
-        BOOST_THROW_EXCEPTION(Error("Database query failure"));
+      NDN_LOG_DEBUG("Data from db: " << *data);
+
+      foundName = data->getFullName();
+
+      if ((exactMatch && name == foundName) || (!exactMatch && name.isPrefixOf(foundName))) {
+        NDN_LOG_DEBUG("Found: " << foundName << " " << stmt.getInt(0));
+        return data;
       }
     }
-    else {
-      std::cerr << "select bind error" << std::endl;
-      sqlite3_finalize(queryStmt);
-      BOOST_THROW_EXCEPTION(Error("select bind error"));
+    else if (rc == SQLITE_DONE) {
+      return nullptr;
     }
-    sqlite3_finalize(queryStmt);
+    else {
+      NDN_LOG_DEBUG("Database query failure rc:" << rc);
+      BOOST_THROW_EXCEPTION(Error("Database query failure"));
+    }
   }
   else {
-    sqlite3_finalize(queryStmt);
-    std::cerr << "select statement prepared failed" << std::endl;
-    BOOST_THROW_EXCEPTION(Error("select statement prepared failed"));
+    NDN_LOG_DEBUG("select bind error");
+    BOOST_THROW_EXCEPTION(Error("select bind error"));
   }
   return nullptr;
 }
 
-int64_t
+uint64_t
 SqliteStorage::size()
 {
-  sqlite3_stmt* queryStmt = 0;
-  string sql("SELECT count(*) FROM NDN_REPO ");
-  int rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
-  if (rc != SQLITE_OK)
-    {
-      std::cerr << "Database query failure rc:" << rc << std::endl;
-      sqlite3_finalize(queryStmt);
-      BOOST_THROW_EXCEPTION(Error("Database query failure"));
-    }
+  ndn::util::Sqlite3Statement stmt(m_db, "SELECT count(*) FROM NDN_REPO_V2;");
 
-  rc = sqlite3_step(queryStmt);
-  if (rc != SQLITE_ROW)
-    {
-      std::cerr << "Database query failure rc:" << rc << std::endl;
-      sqlite3_finalize(queryStmt);
-      BOOST_THROW_EXCEPTION(Error("Database query failure"));
-    }
-
-  int64_t nDatas = sqlite3_column_int64(queryStmt, 0);
-  if (m_size != nDatas) {
-    std::cerr << "The size of database is not correct! " << std::endl;
+  int rc = stmt.step();
+  if (rc != SQLITE_ROW) {
+    NDN_LOG_DEBUG("Database query failure rc:" << rc);
+    BOOST_THROW_EXCEPTION(Error("Database query failure"));
   }
-  return nDatas;
+
+  uint64_t nData = stmt.getInt(0);
+  return nData;
 }
 
 } // namespace repo
diff --git a/src/storage/sqlite-storage.hpp b/src/storage/sqlite-storage.hpp
old mode 100755
new mode 100644
index 168cc41..4d7142b
--- a/src/storage/sqlite-storage.hpp
+++ b/src/storage/sqlite-storage.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014,  Regents of the University of California.
+ * Copyright (c) 2018,  Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -21,19 +21,17 @@
 #define REPO_STORAGE_SQLITE_STORAGE_HPP
 
 #include "storage.hpp"
-#include "index.hpp"
-#include <string>
-#include <iostream>
-#include <sqlite3.h>
-#include <stdlib.h>
-#include <vector>
-#include <queue>
+
 #include <algorithm>
+#include <iostream>
+#include <queue>
+#include <stdlib.h>
+#include <string>
+#include <sqlite3.h>
+#include <vector>
 
 namespace repo {
 
-using std::queue;
-
 class SqliteStorage : public Storage
 {
 public:
@@ -50,7 +48,6 @@
   explicit
   SqliteStorage(const std::string& dbPath);
 
-  virtual
   ~SqliteStorage();
 
   /**
@@ -58,35 +55,30 @@
    *  @param  data     the data should be inserted into databse
    *  @return int64_t  the id number of each entry in the database
    */
-  virtual int64_t
-  insert(const Data& data);
+  int64_t
+  insert(const Data& data) override;
 
   /**
-   *  @brief  remove the entry in the database by using id
-   *  @param  id   id number of each entry in the database
+   *  @brief  remove the entry in the database by using name as index
+   *  @param  name   name of the data
    */
-  virtual bool
-  erase(const int64_t id);
+  bool
+  erase(const Name& name) override;
 
-  /**
-   *  @brief  get the data from database
-   *  @para   id   id number of each entry in the database, used to find the data
-   */
-  virtual std::shared_ptr<Data>
-  read(const int64_t id);
+  std::shared_ptr<Data>
+  read(const Name& name) override;
+
+  bool
+  has(const Name& name) override;
+
+  std::shared_ptr<Data>
+  find(const Name& name, bool exactMatch = false) override;
 
   /**
    *  @brief  return the size of database
    */
-  virtual int64_t
-  size();
-
-  /**
-   *  @brief enumerate each entry in database and call the function
-   *         insertItemToIndex to reubuild index from database
-   */
-  void
-  fullEnumerate(const std::function<void(const Storage::ItemMeta)>& f);
+  uint64_t
+  size() override;
 
 private:
   void
@@ -95,7 +87,6 @@
 private:
   sqlite3* m_db;
   std::string m_dbPath;
-  int64_t m_size;
 };
 
 
diff --git a/src/storage/storage.hpp b/src/storage/storage.hpp
old mode 100755
new mode 100644
index 5286c8a..146368f
--- a/src/storage/storage.hpp
+++ b/src/storage/storage.hpp
@@ -43,14 +43,6 @@
     }
   };
 
-  class ItemMeta
-  {
-  public:
-    int64_t id;
-    Name fullName;
-    ndn::ConstBufferPtr keyLocatorHash;
-  };
-
 public:
   virtual
   ~Storage() = default;
@@ -63,31 +55,38 @@
   insert(const Data& data) = 0;
 
   /**
-   *  @brief  remove the entry in the database by using id
-   *  @param  id   id number of entry in the database
+   *  @brief  remove the entry in the database by full name
+   *  @param  full name   full name of the data
    */
   virtual bool
-  erase(const int64_t id) = 0;
+  erase(const Name& name) = 0;
 
   /**
    *  @brief  get the data from database
-   *  @param  id   id number of each entry in the database, used to find the data
+   *  @param  full name   full name of the data
    */
   virtual std::shared_ptr<Data>
-  read(const int64_t id) = 0;
+  read(const Name& name) = 0;
+
+  /**
+   *  @brief  check if database already has the data
+   *  @param  full name   full name of the data
+   */
+  virtual bool
+  has(const Name& name) = 0;
+
+  /**
+   *  @brief  find the data in database by full name and return it
+   *  @param  full name   full name of the data
+   */
+  virtual std::shared_ptr<Data>
+  find(const Name& name, bool exactMatch = false) = 0;
 
   /**
    *  @brief  return the size of database
    */
-  virtual int64_t
+  virtual uint64_t
   size() = 0;
-
-  /**
-   *  @brief enumerate each entry in database and call the function
-   *         insertItemToIndex to reubuild index from database
-   */
-  virtual void
-  fullEnumerate(const std::function<void(const Storage::ItemMeta)>& f) = 0;
 };
 
 } // namespace repo
diff --git a/tests/dataset-fixtures.hpp b/tests/dataset-fixtures.hpp
index bb03bd6..1a4e272 100644
--- a/tests/dataset-fixtures.hpp
+++ b/tests/dataset-fixtures.hpp
@@ -40,13 +40,13 @@
     }
   };
 
-  typedef std::list<std::shared_ptr<ndn::Data> > DataContainer;
+  using DataContainer = std::list<std::shared_ptr<ndn::Data>>;
   DataContainer data;
 
-  typedef std::list<std::pair<ndn::Interest, std::shared_ptr<ndn::Data> > > InterestContainer;
+  using InterestContainer = std::list<std::pair<ndn::Interest, std::shared_ptr<ndn::Data>>>;
   InterestContainer interests;
 
-  typedef std::list<std::pair<ndn::Interest, size_t > > RemovalsContainer;
+  using RemovalsContainer = std::list<std::pair<ndn::Interest, size_t>>;
   RemovalsContainer removals;
 
 protected:
@@ -77,7 +77,7 @@
   }
 
 private:
-  std::map<Name, shared_ptr<Data> > map;
+  std::map<Name, std::shared_ptr<Data>> map;
 };
 
 
@@ -205,187 +205,10 @@
   }
 };
 
-
-class BasicChildSelectorDataset : public DatasetBase
-{
-public:
-  static const std::string&
-  getName()
-  {
-    static std::string name = "BasicChildSelectorDataset";
-    return name;
-  }
-
-  BasicChildSelectorDataset()
-  {
-    this->data.push_back(createData("/a/1"));
-    this->data.push_back(createData("/b/1"));
-    this->interests.push_back(std::make_pair(Interest()
-                                               .setName("/b")
-                                               .setSelectors(Selectors()
-                                                               .setChildSelector(0)),
-                                             this->data.back()));
-
-    this->data.push_back(createData("/c/1"));
-    this->data.push_back(createData("/b/99"));
-    this->interests.push_back(std::make_pair(Interest()
-                                               .setName("/b")
-                                               .setSelectors(Selectors()
-                                                               .setChildSelector(1)),
-                                             this->data.back()));
-    this->data.push_back(createData("/b/5"));
-    this->data.push_back(createData("/b/55"));
-  }
-};
-
-
-class ExtendedChildSelectorDataset : public DatasetBase
-{
-public:
-  static const std::string&
-  getName()
-  {
-    static std::string name = "storage";
-    return name;
-  }
-
-  ExtendedChildSelectorDataset()
-  {
-    this->data.push_back(createData("/a/b/1"));
-
-    this->data.push_back(createData("/a/c/1"));
-    this->interests.push_back(std::make_pair(Interest("/a")
-                                             .setSelectors(Selectors()
-                                                           .setChildSelector(1)),
-                                              this->data.back()));
-
-    this->data.push_back(createData("/a/c/2"));
-
-    this->data.push_back(createData("/b"));
-  }
-};
-
-
-class ComplexSelectorsDataset : public DatasetBase
-{
-public:
-  static const std::string&
-  getName()
-  {
-    static std::string name = "ComplexSelectorsDataset";
-    return name;
-  }
-
-  std::map<std::string, shared_ptr<Data> > map;
-
-  void
-  addData(const std::string& name)
-  {
-  }
-
-  ComplexSelectorsDataset()
-  {
-    // Dataset
-    this->data.push_back(createData("/a/b/c"));
-    this->data.push_back(createData("/a/b/d/1"));
-    this->data.push_back(createData("/a/b/d/2"));
-    this->data.push_back(createData("/a/b/d/3"));
-    this->data.push_back(createData("/a/b/d/4/I"));
-    this->data.push_back(createData("/a/b/d/4"));
-    this->data.push_back(createData("/a/b/d"));
-    this->data.push_back(createData("/a/b/e/1"));
-    this->data.push_back(createData("/a/b/e"));
-
-    // Basic selects
-    this->interests.push_back(std::make_pair(Interest("/a/b/c"),     this->getData("/a/b/c")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/d"),     this->getData("/a/b/d")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/d/1"),   this->getData("/a/b/d/1")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/d/2"),   this->getData("/a/b/d/2")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/d/3"),   this->getData("/a/b/d/3")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/d/4/I"), this->getData("/a/b/d/4/I")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/d/4"),   this->getData("/a/b/d/4")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/e"),     this->getData("/a/b/e")));
-    this->interests.push_back(std::make_pair(Interest("/a/b/e/1"),   this->getData("/a/b/e/1")));
-
-    // Complex selects
-    this->interests.push_back(std::make_pair(Interest("/a/b")
-                                             .setSelectors(Selectors()
-                                                           .setMinSuffixComponents(2)
-                                                           .setMaxSuffixComponents(2)),
-                                             this->getData("/a/b/c")));
-
-    this->interests.push_back(std::make_pair(Interest("/a/b/d")
-                                             .setSelectors(Selectors()
-                                                           .setMinSuffixComponents(-1)
-                                                           .setChildSelector(0)),
-                                             this->getData("/a/b/d")));
-
-    this->interests.push_back(std::make_pair(Interest("/a/b/d")
-                                             .setSelectors(Selectors()
-                                                           .setMinSuffixComponents(2)
-                                                           .setChildSelector(0)),
-                                             this->getData("/a/b/d/1")));
-
-    this->interests.push_back(std::make_pair(
-      Interest("/a/b/d")
-      .setSelectors(Selectors()
-                    .setChildSelector(1)
-                    .setMaxSuffixComponents(2)
-                    .setMinSuffixComponents(2)
-                    .setExclude(Exclude()
-                                .excludeRange(ndn::name::Component("3"),
-                                              ndn::name::Component("4")))),
-      this->getData("/a/b/d/2")));
-
-
-    this->interests.push_back(std::make_pair(Interest("/a/b/d")
-                                               .setSelectors(Selectors().setMinSuffixComponents(3)),
-                                             this->getData("/a/b/d/4/I")));
-
-    // According to selector definition, RightMost for the next level and LeftMost for the next-next level
-    this->interests.push_back(std::make_pair(Interest("/a/b/d")
-                                             .setSelectors(Selectors()
-                                                           .setMinSuffixComponents(2)
-                                                           .setChildSelector(1)),
-                                             this->getData("/a/b/d/4")));
-
-    // because of the digest component, /a/b/d will be to the right of /a/b/d/4
-    this->interests.push_back(std::make_pair(Interest("/a/b/d")
-                                             .setSelectors(Selectors()
-                                                           .setChildSelector(1)),
-                                             this->getData("/a/b/d/4")));
-
-    // Alex: this interest doesn't make sense, as all Data packets will have the same selector
-    this->interests.push_back(std::make_pair(Interest("/a/b/e")
-                                             .setSelectors(Selectors()
-                                                           .setPublisherPublicKeyLocator(
-                                                             this->data.back()
-                                                               ->getSignature().getKeyLocator())),
-                                             this->getData("/a/b/e")));
-
-    // Removals
-    this->removals.push_back(std::make_pair(Interest("/a/b/d/2"), 1));
-
-    this->removals.push_back(std::make_pair(
-      Interest("/a/b/d")
-      .setSelectors(Selectors()
-                    .setMaxSuffixComponents(2)
-                    .setMinSuffixComponents(2)
-                    .setExclude(Exclude()
-                                .excludeOne(ndn::name::Component("3")))),
-      2));
-  }
-};
-
-
-typedef boost::mpl::vector<BasicDataset,
-                           FetchByPrefixDataset,
-                           BasicChildSelectorDataset,
-                           ExtendedChildSelectorDataset,
-                           SamePrefixDataset<10>,
-                           SamePrefixDataset<100>> CommonDatasets;
-
-
+using CommonDatasets = boost::mpl::vector<BasicDataset,
+                                          FetchByPrefixDataset,
+                                          SamePrefixDataset<10>,
+                                          SamePrefixDataset<100>>;
 } // namespace tests
 } // namespace repo
 
diff --git a/tests/integrated/command-fixture.cpp b/tests/integrated/command-fixture.cpp
index a803a51..ad7955a 100644
--- a/tests/integrated/command-fixture.cpp
+++ b/tests/integrated/command-fixture.cpp
@@ -28,8 +28,8 @@
   , dispatcher(repoFace, keyChain)
   , validator(repoFace)
 {
-  this->saveIdentityCertificate(keyChain.getPib().getDefaultIdentity().getName(),
-                                "tests/integrated/insert-delete-test.cert");
+  this->addIdentity("/ndn/test/repo");
+  this->saveIdentityCertificate("/ndn/test/repo", "tests/integrated/insert-delete-test.cert");
   validator.load("tests/integrated/insert-delete-validator-config.conf");
 }
 
diff --git a/tests/integrated/insert-delete-validator-config.conf b/tests/integrated/insert-delete-validator-config.conf
index c97bb4c..0820266 100644
--- a/tests/integrated/insert-delete-validator-config.conf
+++ b/tests/integrated/insert-delete-validator-config.conf
@@ -1,8 +1,7 @@
 ; The test rules below are for test suite TestBasicCommandInsertDelete.
 ; Signed interests and data packets are signed by default certificate.
 ; In these test rules, the type of checker is fixed signer and signer type is file.
-; So user who wants to run this test could use security tool to dump the defualt
-; certificate into a file named "insert-delete-test.cert"
+
 rule
 {
   id "Test Rule For Signed Interest"
@@ -20,7 +19,7 @@
     key-locator
     {
       type name
-      name /DEFAULT
+      name /ndn/test/repo
       relation equal
     }
   }
@@ -43,7 +42,7 @@
     key-locator
     {
       type name
-      name /DEFAULT
+      name /ndn/test/repo
       relation equal
     }
   }
diff --git a/tests/integrated/test-basic-command-insert-delete.cpp b/tests/integrated/test-basic-command-insert-delete.cpp
index ea58abe..f3685f6 100644
--- a/tests/integrated/test-basic-command-insert-delete.cpp
+++ b/tests/integrated/test-basic-command-insert-delete.cpp
@@ -36,9 +36,6 @@
 #include <boost/mpl/vector.hpp>
 #include <boost/test/unit_test.hpp>
 
-
-#include <iostream>
-
 namespace repo {
 namespace tests {
 
@@ -46,6 +43,7 @@
 using ndn::time::seconds;
 using ndn::EventId;
 
+
 // All the test cases in this test suite should be run at once.
 BOOST_AUTO_TEST_SUITE(TestBasicCommandInsertDelete)
 
@@ -60,6 +58,7 @@
     , deleteHandle(repoFace, *handle, dispatcher, scheduler, validator)
     , insertFace(repoFace.getIoService())
     , deleteFace(repoFace.getIoService())
+    , signer(keyChain)
   {
     Name cmdPrefix("/repo/command");
     repoFace.registerPrefix(cmdPrefix, nullptr,
@@ -113,6 +112,8 @@
   Face insertFace;
   Face deleteFace;
   std::map<Name, EventId> insertEvents;
+  std::map<Name, Name> deleteNamePairs;
+  ndn::security::CommandInterestSigner signer;
 };
 
 template<class T> void
@@ -129,9 +130,7 @@
     insertEvents.erase(event);
   }
   // schedule an event 50ms later to check whether insert is Ok
-  scheduler.scheduleEvent(500_ms,
-                          bind(&Fixture<T>::checkInsertOk, this, interest));
-
+  scheduler.scheduleEvent(500_ms, std::bind(&Fixture<T>::checkInsertOk, this, interest));
 }
 
 
@@ -165,8 +164,7 @@
   BOOST_CHECK_EQUAL(statusCode, 200);
 
   //schedlute an event to check whether delete is Ok.
-  scheduler.scheduleEvent(100_ms,
-                          bind(&Fixture<T>::checkDeleteOk, this, interest));
+  scheduler.scheduleEvent(100_ms, std::bind(&Fixture<T>::checkDeleteOk, this, interest));
 }
 
 template<class T> void
@@ -185,25 +183,25 @@
 Fixture<T>::sendInsertInterest(const Interest& insertInterest)
 {
   insertFace.expressInterest(insertInterest,
-                             bind(&Fixture<T>::onInsertData, this, _1, _2),
-                             bind(&Fixture<T>::onInsertTimeout, this, _1), // Nack
-                             bind(&Fixture<T>::onInsertTimeout, this, _1));
+                             std::bind(&Fixture<T>::onInsertData, this, _1, _2),
+                             std::bind(&Fixture<T>::onInsertTimeout, this, _1), // Nack
+                             std::bind(&Fixture<T>::onInsertTimeout, this, _1));
 }
 
 template<class T> void
 Fixture<T>::sendDeleteInterest(const Interest& deleteInterest)
 {
   deleteFace.expressInterest(deleteInterest,
-                             bind(&Fixture<T>::onDeleteData, this, _1, _2),
-                             bind(&Fixture<T>::onDeleteTimeout, this, _1), // Nack
-                             bind(&Fixture<T>::onDeleteTimeout, this, _1));
+                             std::bind(&Fixture<T>::onDeleteData, this, _1, _2),
+                             std::bind(&Fixture<T>::onDeleteTimeout, this, _1), // Nack
+                             std::bind(&Fixture<T>::onDeleteTimeout, this, _1));
 }
 
 template<class T> void
 Fixture<T>::checkInsertOk(const Interest& interest)
 {
   BOOST_TEST_MESSAGE(interest);
-  shared_ptr<Data> data = handle->readData(interest);
+  std::shared_ptr<Data> data = handle->readData(interest);
   if (data) {
     int rc = memcmp(data->getContent().value(), content, sizeof(content));
     BOOST_CHECK_EQUAL(rc, 0);
@@ -216,10 +214,14 @@
 template<class T> void
 Fixture<T>::checkDeleteOk(const Interest& interest)
 {
-  shared_ptr<Data> data = handle->readData(interest);
-  BOOST_CHECK_EQUAL(data, shared_ptr<Data>());
+  std::map<Name, Name>::iterator name = deleteNamePairs.find(interest.getName());
+  BOOST_CHECK_MESSAGE(name != deleteNamePairs.end(), "Delete name not found: " << interest.getName());
+  Interest dataInterest(name->second);
+  std::shared_ptr<Data> data = handle->readData(dataInterest);
+  BOOST_CHECK(!data);
 }
 
+
 template<class T> void
 Fixture<T>::scheduleInsertEvent()
 {
@@ -230,24 +232,20 @@
     RepoCommandParameter insertParameter;
     insertParameter.setName(Name((*i)->getName())
                             .appendNumber(ndn::random::generateWord64()));
-
     insertCommandName.append(insertParameter.wireEncode());
-    Interest insertInterest(insertCommandName);
-    keyChain.sign(insertInterest);
-
+    Interest insertInterest = signer.makeCommandInterest(insertCommandName);
     // schedule a job to express insertInterest every 50ms
     scheduler.scheduleEvent(milliseconds(timeCount * 50 + 1000),
-                            bind(&Fixture<T>::sendInsertInterest, this, insertInterest));
+                            std::bind(&Fixture<T>::sendInsertInterest, this, insertInterest));
     // schedule what to do when interest timeout
     EventId delayEventId = scheduler.scheduleEvent(milliseconds(5000 + timeCount * 50),
-                                                   bind(&Fixture<T>::delayedInterest, this));
+                                                   std::bind(&Fixture<T>::delayedInterest, this));
     insertEvents[insertParameter.getName()] = delayEventId;
-
-    //The delayEvent will be canceled in onInsertInterest
+    // The delayEvent will be canceled in onInsertInterest
     insertFace.setInterestFilter(insertParameter.getName(),
-                                 bind(&Fixture<T>::onInsertInterest, this, _2),
+                                 std::bind(&Fixture<T>::onInsertInterest, this, _2),
                                  ndn::RegisterPrefixSuccessCallback(),
-                                 bind(&Fixture<T>::onRegisterFailed, this, _2));
+                                 std::bind(&Fixture<T>::onRegisterFailed, this, _2));
     timeCount++;
   }
 }
@@ -263,27 +261,23 @@
     deleteParameter.setProcessId(ndn::random::generateWord64());
     deleteParameter.setName((*i)->getName());
     deleteCommandName.append(deleteParameter.wireEncode());
-    Interest deleteInterest(deleteCommandName);
-    keyChain.sign(deleteInterest);
+    Interest deleteInterest = signer.makeCommandInterest(deleteCommandName);
+    deleteNamePairs[deleteInterest.getName()] = (*i)->getName();
     scheduler.scheduleEvent(milliseconds(4000 + timeCount * 50),
-                            bind(&Fixture<T>::sendDeleteInterest, this, deleteInterest));
+                            std::bind(&Fixture<T>::sendDeleteInterest, this, deleteInterest));
     timeCount++;
   }
 }
 
-typedef boost::mpl::vector<BasicDataset,
-                           FetchByPrefixDataset,
-                           BasicChildSelectorDataset,
-                           ExtendedChildSelectorDataset,
-                           SamePrefixDataset<10>> Datasets;
+using Datasets = boost::mpl::vector<BasicDataset,
+                                    FetchByPrefixDataset,
+                                    SamePrefixDataset<10>>;
 
 BOOST_FIXTURE_TEST_CASE_TEMPLATE(InsertDelete, T, Datasets, Fixture<T>)
 {
   // schedule events
-  this->scheduler.scheduleEvent(0_s,
-                                bind(&Fixture<T>::scheduleInsertEvent, this));
-  this->scheduler.scheduleEvent(10_s,
-                                bind(&Fixture<T>::scheduleDeleteEvent, this));
+  this->scheduler.scheduleEvent(0_s, std::bind(&Fixture<T>::scheduleInsertEvent, this));
+  this->scheduler.scheduleEvent(10_s, std::bind(&Fixture<T>::scheduleDeleteEvent, this));
 
   this->repoFace.processEvents(30_s);
 }
diff --git a/tests/integrated/test-basic-command-watch.cpp b/tests/integrated/test-basic-command-watch.cpp
deleted file mode 100644
index 6fe677d..0000000
--- a/tests/integrated/test-basic-command-watch.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2018, Regents of the University of California.
- *
- * This file is part of NDN repo-ng (Next generation of NDN repository).
- * See AUTHORS.md for complete list of repo-ng authors and contributors.
- *
- * repo-ng 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.
- *
- * repo-ng 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
- * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "handles/watch-handle.hpp"
-#include "storage/sqlite-storage.hpp"
-
-#include "command-fixture.hpp"
-#include "../repo-storage-fixture.hpp"
-#include "../dataset-fixtures.hpp"
-
-#include <ndn-cxx/util/random.hpp>
-
-#include <boost/mpl/vector.hpp>
-#include <boost/test/unit_test.hpp>
-
-namespace repo {
-namespace tests {
-
-using ndn::time::milliseconds;
-using ndn::time::seconds;
-using ndn::EventId;
-
-// All the test cases in this test suite should be run at once.
-BOOST_AUTO_TEST_SUITE(TestBasicCommandWatchDelete)
-
-const static uint8_t content[8] = {3, 1, 4, 1, 5, 9, 2, 6};
-
-template<class Dataset>
-class Fixture : public CommandFixture, public RepoStorageFixture, public Dataset
-{
-public:
-  Fixture()
-    : watchHandle(repoFace, *handle, dispatcher, scheduler, validator)
-    , watchFace(repoFace.getIoService())
-  {
-    Name cmdPrefix("/repo/command");
-    repoFace.registerPrefix(cmdPrefix, nullptr,
-      [] (const Name& cmdPrefix, const std::string& reason) {
-        BOOST_FAIL("Command prefix registration error: " << reason);
-      });
-  }
-
-  void
-  scheduleWatchEvent();
-
-  void
-  onWatchInterest(const Interest& interest);
-
-  void
-  onRegisterFailed(const std::string& reason);
-
-  void
-  delayedInterest();
-
-  void
-  onWatchData(const Interest& interest, const Data& data);
-
-  void
-  onWatchStopData(const Interest& interest, const Data& data);
-
-  void
-  onWatchTimeout(const Interest& interest);
-
-  void
-  sendWatchStartInterest(const Interest& interest);
-
-  void
-  sendWatchStopInterest(const Interest& interest);
-
-  void
-  checkWatchOk(const Interest& interest);
-
-public:
-  WatchHandle watchHandle;
-  Face watchFace;
-  std::map<Name, EventId> watchEvents;
-};
-
-template<class T> void
-Fixture<T>::onWatchInterest(const Interest& interest)
-{
-  auto data = make_shared<Data>(Name(interest.getName())
-                                .appendNumber(ndn::random::generateWord64() + 100));
-  data->setContent(content, sizeof(content));
-  data->setFreshnessPeriod(0_ms);
-  keyChain.sign(*data);
-  watchFace.put(*data);
-
-  // schedule an event 50ms later to check whether watch is Ok
-  scheduler.scheduleEvent(10000_ms,
-                          bind(&Fixture<T>::checkWatchOk, this,
-                               Interest(data->getName())));
-}
-
-
-template<class T> void
-Fixture<T>::onRegisterFailed(const std::string& reason)
-{
-  BOOST_ERROR("ERROR: Failed to register prefix in local hub's daemon" + reason);
-}
-
-template<class T> void
-Fixture<T>::delayedInterest()
-{
-  BOOST_ERROR("Fetching interest does not come. It may be satisfied in CS or something is wrong");
-}
-
-template<class T> void
-Fixture<T>::onWatchData(const Interest& interest, const Data& data)
-{
-  RepoCommandResponse response;
-  response.wireDecode(data.getContent().blockFromValue());
-
-  int statusCode = response.getCode();
-  BOOST_CHECK_EQUAL(statusCode, 100);
-}
-
-template<class T> void
-Fixture<T>::onWatchStopData(const Interest& interest, const Data& data)
-{
-  RepoCommandResponse response;
-  response.wireDecode(data.getContent().blockFromValue());
-
-  int statusCode = response.getCode();
-  BOOST_CHECK_EQUAL(statusCode, 101);
-}
-
-template<class T> void
-Fixture<T>::onWatchTimeout(const Interest& interest)
-{
-  BOOST_ERROR("Watch command timeout");
-}
-
-template<class T> void
-Fixture<T>::sendWatchStartInterest(const Interest& watchInterest)
-{
-  watchFace.expressInterest(watchInterest,
-                            bind(&Fixture<T>::onWatchData, this, _1, _2),
-                            bind(&Fixture<T>::onWatchTimeout, this, _1), // Nack
-                            bind(&Fixture<T>::onWatchTimeout, this, _1));
-}
-
-template<class T> void
-Fixture<T>::sendWatchStopInterest(const Interest& watchInterest)
-{
-  watchFace.expressInterest(watchInterest,
-                            bind(&Fixture<T>::onWatchStopData, this, _1, _2),
-                            bind(&Fixture<T>::onWatchTimeout, this, _1), // Nack
-                            bind(&Fixture<T>::onWatchTimeout, this, _1));
-}
-
-template<class T> void
-Fixture<T>::checkWatchOk(const Interest& interest)
-{
-  BOOST_TEST_MESSAGE(interest);
-  shared_ptr<Data> data = handle->readData(interest);
-  if (data) {
-    int rc = memcmp(data->getContent().value(), content, sizeof(content));
-    BOOST_CHECK_EQUAL(rc, 0);
-  }
-  else {
-    std::cerr<<"Check Watch Failed"<<std::endl;
-  }
-}
-
-template<class T> void
-Fixture<T>::scheduleWatchEvent()
-{
-  Name watchCommandName("/repo/command/watch/start");
-  RepoCommandParameter watchParameter;
-  watchParameter.setName(Name("/a/b"));
-  watchParameter.setMaxInterestNum(10);
-  watchParameter.setInterestLifetime(50000_ms);
-  watchParameter.setWatchTimeout(1000000000_ms);
-  watchCommandName.append(watchParameter.wireEncode());
-  Interest watchInterest(watchCommandName);
-  keyChain.sign(watchInterest);
-  //schedule a job to express watchInterest
-  scheduler.scheduleEvent(1000_ms,
-                          bind(&Fixture<T>::sendWatchStartInterest, this, watchInterest));
-
-  Name watchStopName("/repo/command/watch/stop");
-  RepoCommandParameter watchStopParameter;
-  watchStopName.append(watchStopParameter.wireEncode());
-  Interest watchStopInterest(watchStopName);
-  keyChain.sign(watchStopInterest);
-
-  //The delayEvent will be canceled in onWatchInterest
-  watchFace.setInterestFilter(watchParameter.getName(),
-                              bind(&Fixture<T>::onWatchInterest, this, _2),
-                              ndn::RegisterPrefixSuccessCallback(),
-                              bind(&Fixture<T>::onRegisterFailed, this, _2));
-}
-
-typedef boost::mpl::vector<BasicDataset> Dataset;
-
-BOOST_FIXTURE_TEST_CASE_TEMPLATE(WatchDelete, T, Dataset, Fixture<T>)
-{
-  // schedule events
-  this->scheduler.scheduleEvent(1_s,
-                                bind(&Fixture<T>::scheduleWatchEvent, this));
-
-  this->repoFace.processEvents(500_s);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace repo
diff --git a/tests/integrated/test-basic-interest-read.cpp b/tests/integrated/test-basic-interest-read.cpp
index 0ad2f3c..d73b0d1 100644
--- a/tests/integrated/test-basic-interest-read.cpp
+++ b/tests/integrated/test-basic-interest-read.cpp
@@ -27,12 +27,14 @@
 #include <boost/asio/io_service.hpp>
 #include <boost/test/unit_test.hpp>
 
+#include <ndn-cxx/util/logger.hpp>
 #include <ndn-cxx/util/time.hpp>
 
 namespace repo {
 namespace tests {
 
-// All the test cases in this test suite should be run at once.
+NDN_LOG_INIT(repo.tests.read);
+
 BOOST_AUTO_TEST_SUITE(TestBasicInerestRead)
 
 const static uint8_t content[8] = {3, 1, 4, 1, 5, 9, 2, 6};
@@ -69,13 +71,16 @@
       (*i)->setContent(content, sizeof(content));
       (*i)->setFreshnessPeriod(36000_ms);
       keyChain.sign(**i);
+      NDN_LOG_DEBUG(**i);
       bool rc = handle->insertData(**i);
 
       BOOST_CHECK_EQUAL(rc, true);
+      NDN_LOG_DEBUG("Inserted Data " << (**i).getName());
+
       Interest readInterest((*i)->getName());
       readInterest.setMustBeFresh(true);
       scheduler.scheduleEvent(ndn::time::milliseconds(timeCount * 50),
-                              bind(&BasicInterestReadFixture<Dataset>::sendInterest, this,
+                              std::bind(&BasicInterestReadFixture<Dataset>::sendInterest, this,
                                         readInterest));
       timeCount++;
     }
@@ -91,22 +96,25 @@
   void
   onReadTimeout(const ndn::Interest& interest)
   {
-    BOOST_ERROR("Insert not successfull or Read data does not successfull");
+    NDN_LOG_DEBUG("Timed out " << interest.getName());
+    BOOST_ERROR("Insert or read not successfull");
   }
 
   void
   onReadNack(const ndn::Interest& interest, const ndn::lp::Nack& nack)
   {
+    NDN_LOG_DEBUG("Nacked " << interest.getName() << nack.getReason());
     BOOST_ERROR("Read nacked");
   }
 
   void
   sendInterest(const ndn::Interest& interest)
   {
+    NDN_LOG_DEBUG("Sending Interest " << interest.getName());
     readFace.expressInterest(interest,
-                             bind(&BasicInterestReadFixture::onReadData, this, _1, _2),
-                             bind(&BasicInterestReadFixture::onReadNack, this, _1, _2),
-                             bind(&BasicInterestReadFixture::onReadTimeout, this, _1));
+                             std::bind(&BasicInterestReadFixture::onReadData, this, _1, _2),
+                             std::bind(&BasicInterestReadFixture::onReadNack, this, _1, _2),
+                             std::bind(&BasicInterestReadFixture::onReadTimeout, this, _1));
   }
 
 public:
@@ -117,17 +125,16 @@
   ndn::Face readFace;
 };
 
-typedef boost::mpl::vector<BasicDataset,
-                            FetchByPrefixDataset,
-                            BasicChildSelectorDataset,
-                            ExtendedChildSelectorDataset,
-                            SamePrefixDataset<10>> Datasets;
+
+using Datasets = boost::mpl::vector<BasicDataset,
+                                    FetchByPrefixDataset,
+                                    SamePrefixDataset<10>>;
 
 BOOST_FIXTURE_TEST_CASE_TEMPLATE(Read, T, Datasets, BasicInterestReadFixture<T>)
 {
   this->startListen();
   this->scheduler.scheduleEvent(1_s,
-                                bind(&BasicInterestReadFixture<T>::scheduleReadEvent, this));
+                                std::bind(&BasicInterestReadFixture<T>::scheduleReadEvent, this));
 
   this->repoFace.processEvents(20_s);
 
diff --git a/tests/repo-storage-fixture.hpp b/tests/repo-storage-fixture.hpp
index 29df163..9a82169 100644
--- a/tests/repo-storage-fixture.hpp
+++ b/tests/repo-storage-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014,  Regents of the University of California.
+ * Copyright (c) 2018,  Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -32,8 +32,8 @@
 {
 public:
   RepoStorageFixture()
-    : store(make_shared<SqliteStorage>("unittestdb"))
-    , handle(new RepoStorage(static_cast<int64_t>(65535), *store))
+    : store(std::make_shared<SqliteStorage>("unittestdb"))
+    , handle(std::make_shared<RepoStorage>(*store))
   {
   }
 
@@ -44,8 +44,8 @@
 
 
 public:
-  shared_ptr<Storage> store;
-  shared_ptr<RepoStorage> handle;
+  std::shared_ptr<Storage> store;
+  std::shared_ptr<RepoStorage> handle;
 };
 
 } // namespace tests
diff --git a/tests/unit/index.cpp b/tests/unit/index.cpp
deleted file mode 100644
index 6f255a2..0000000
--- a/tests/unit/index.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2017, Regents of the University of California.
- *
- * This file is part of NDN repo-ng (Next generation of NDN repository).
- * See AUTHORS.md for complete list of repo-ng authors and contributors.
- *
- * repo-ng 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.
- *
- * repo-ng 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
- * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "storage/index.hpp"
-
-#include "../sqlite-fixture.hpp"
-#include "../dataset-fixtures.hpp"
-
-#include <iostream>
-
-#include <ndn-cxx/security/signing-helpers.hpp>
-#include <ndn-cxx/util/sha256.hpp>
-#include <ndn-cxx/util/random.hpp>
-
-#include <boost/mpl/push_back.hpp>
-#include <boost/test/unit_test.hpp>
-
-namespace repo {
-namespace tests {
-
-BOOST_AUTO_TEST_SUITE(Index)
-
-class FindFixture
-{
-protected:
-  FindFixture()
-    : m_index(std::numeric_limits<size_t>::max())
-  {
-  }
-
-  Name
-  insert(int id, const Name& name)
-  {
-    shared_ptr<Data> data = make_shared<Data>(name);
-    data->setContent(reinterpret_cast<const uint8_t*>(&id), sizeof(id));
-    m_keyChain.sign(*data, ndn::signingWithSha256());
-    data->wireEncode();
-    m_index.insert(*data, id);
-
-    return data->getFullName();
-  }
-
-  Interest&
-  startInterest(const Name& name)
-  {
-    m_interest = make_shared<Interest>(name);
-    return *m_interest;
-  }
-
-  int
-  find()
-  {
-    std::pair<int, Name> found = m_index.find(*m_interest);
-    return found.first;
-  }
-
-protected:
-  repo::Index m_index;
-  KeyChain m_keyChain;
-  shared_ptr<Interest> m_interest;
-};
-
-BOOST_FIXTURE_TEST_SUITE(Find, FindFixture)
-
-BOOST_AUTO_TEST_CASE(EmptyDataName)
-{
-  insert(1, "ndn:/");
-  startInterest("ndn:/");
-  BOOST_CHECK_EQUAL(find(), 1);
-}
-
-BOOST_AUTO_TEST_CASE(EmptyInterestName)
-{
-  insert(1, "ndn:/A");
-  startInterest("ndn:/");
-  BOOST_CHECK_EQUAL(find(), 1);
-}
-
-BOOST_AUTO_TEST_CASE(ExactName)
-{
-  insert(1, "ndn:/");
-  insert(2, "ndn:/A");
-  insert(3, "ndn:/A/B");
-  insert(4, "ndn:/A/C");
-  insert(5, "ndn:/D");
-
-  startInterest("ndn:/A");
-  BOOST_CHECK_EQUAL(find(), 2);
-}
-
-BOOST_AUTO_TEST_CASE(FullName)
-{
-  Name n1 = insert(1, "ndn:/A");
-  Name n2 = insert(2, "ndn:/A");
-
-  startInterest(n1);
-  BOOST_CHECK_EQUAL(find(), 1);
-
-  startInterest(n2);
-  BOOST_CHECK_EQUAL(find(), 2);
-}
-
-BOOST_AUTO_TEST_CASE(Leftmost)
-{
-  insert(1, "ndn:/A");
-  insert(2, "ndn:/B/p/1");
-  insert(3, "ndn:/B/p/2");
-  insert(4, "ndn:/B/q/1");
-  insert(5, "ndn:/B/q/2");
-  insert(6, "ndn:/C");
-
-  startInterest("ndn:/B");
-  BOOST_CHECK_EQUAL(find(), 2);
-}
-
-BOOST_AUTO_TEST_CASE(Rightmost)
-{
-  insert(1, "ndn:/A");
-  insert(2, "ndn:/B/p/1");
-  insert(3, "ndn:/B/p/2");
-  insert(4, "ndn:/B/q/1");
-  insert(5, "ndn:/B/q/2");
-  insert(6, "ndn:/C");
-
-  startInterest("ndn:/B")
-    .setChildSelector(1);
-  BOOST_CHECK_EQUAL(find(), 4);
-}
-
-BOOST_AUTO_TEST_CASE(MinSuffixComponents)
-{
-  insert(1, "ndn:/");
-  insert(2, "ndn:/A");
-  insert(3, "ndn:/B/1");
-  insert(4, "ndn:/C/1/2");
-  insert(5, "ndn:/D/1/2/3");
-  insert(6, "ndn:/E/1/2/3/4");
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(0);
-  BOOST_CHECK_EQUAL(find(), 1);
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(1);
-  BOOST_CHECK_EQUAL(find(), 1);
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(2);
-  BOOST_CHECK_EQUAL(find(), 2);
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(3);
-  BOOST_CHECK_EQUAL(find(), 3);
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(4);
-  BOOST_CHECK_EQUAL(find(), 4);
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(5);
-  BOOST_CHECK_EQUAL(find(), 5);
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(6);
-  BOOST_CHECK_EQUAL(find(), 6);
-
-  startInterest("ndn:/")
-    .setMinSuffixComponents(7);
-  BOOST_CHECK_EQUAL(find(), 0);
-}
-
-BOOST_AUTO_TEST_CASE(MaxSuffixComponents)
-{
-  insert(1, "ndn:/");
-  insert(2, "ndn:/A");
-  insert(3, "ndn:/B/2");
-  insert(4, "ndn:/C/2/3");
-  insert(5, "ndn:/D/2/3/4");
-  insert(6, "ndn:/E/2/3/4/5");
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(0);
-  BOOST_CHECK_EQUAL(find(), 0);
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(1);
-  BOOST_CHECK_EQUAL(find(), 1);
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(2);
-  BOOST_CHECK_EQUAL(find(), 2);
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(3);
-  BOOST_CHECK_EQUAL(find(), 3);
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(4);
-  BOOST_CHECK_EQUAL(find(), 4);
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(5);
-  BOOST_CHECK_EQUAL(find(), 5);
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(6);
-  BOOST_CHECK_EQUAL(find(), 6);
-
-  startInterest("ndn:/")
-    .setChildSelector(1)
-    .setMaxSuffixComponents(7);
-  BOOST_CHECK_EQUAL(find(), 6);
-}
-
-BOOST_AUTO_TEST_CASE(DigestOrder)
-{
-  insert(1, "ndn:/A");
-  insert(2, "ndn:/A");
-  // We don't know which comes first, but there must be some order
-
-  startInterest("ndn:/A")
-    .setChildSelector(0);
-  uint32_t leftmost = find();
-
-  startInterest("ndn:/A")
-    .setChildSelector(1);
-  uint32_t rightmost = find();
-
-  BOOST_CHECK_NE(leftmost, rightmost);
-}
-
-BOOST_AUTO_TEST_CASE(DigestExclude)
-{
-  insert(1, "ndn:/A");
-  Name n2 = insert(2, "ndn:/A");
-  insert(3, "ndn:/A/B");
-
-  uint8_t digest00[ndn::util::Sha256::DIGEST_SIZE];
-  std::fill_n(digest00, sizeof(digest00), 0x00);
-  uint8_t digestFF[ndn::util::Sha256::DIGEST_SIZE];
-  std::fill_n(digestFF, sizeof(digestFF), 0xFF);
-
-  Exclude excludeDigest;
-  excludeDigest.excludeRange(
-    name::Component::fromImplicitSha256Digest(digest00, sizeof(digest00)),
-    name::Component::fromImplicitSha256Digest(digestFF, sizeof(digestFF)));
-
-  startInterest("ndn:/A")
-    .setChildSelector(0)
-    .setExclude(excludeDigest);
-  BOOST_CHECK_EQUAL(find(), 3);
-
-  startInterest("ndn:/A")
-    .setChildSelector(1)
-    .setExclude(excludeDigest);
-  BOOST_CHECK_EQUAL(find(), 3);
-
-  Exclude excludeGeneric;
-  excludeGeneric.excludeAfter(name::Component(static_cast<uint8_t*>(nullptr), 0));
-
-  startInterest("ndn:/A")
-    .setChildSelector(0)
-    .setExclude(excludeGeneric);
-  int found1 = find();
-  BOOST_CHECK(found1 == 1 || found1 == 2);
-
-  startInterest("ndn:/A")
-    .setChildSelector(1)
-    .setExclude(excludeGeneric);
-  int found2 = find();
-  BOOST_CHECK(found2 == 1 || found2 == 2);
-
-  Exclude exclude2 = excludeGeneric;
-  exclude2.excludeOne(n2.get(-1));
-
-  startInterest("ndn:/A")
-    .setChildSelector(0)
-    .setExclude(exclude2);
-  BOOST_CHECK_EQUAL(find(), 1);
-
-  startInterest("ndn:/A")
-    .setChildSelector(1)
-    .setExclude(exclude2);
-  BOOST_CHECK_EQUAL(find(), 1);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Find
-
-
-template<class Dataset>
-class Fixture : public Dataset
-{
-public:
-  Fixture()
-    : index(65535)
-  {
-  }
-
-public:
-  std::map<int64_t, shared_ptr<Data> > idToDataMap;
-  repo::Index index;
-};
-
-// Combine CommonDatasets with ComplexSelectorDataset
-typedef boost::mpl::push_back<CommonDatasets,
-                              ComplexSelectorsDataset>::type Datasets;
-
-BOOST_FIXTURE_TEST_CASE_TEMPLATE(Bulk, T, Datasets, Fixture<T>)
-{
-  BOOST_TEST_MESSAGE(T::getName());
-
-  for (typename T::DataContainer::iterator i = this->data.begin();
-       i != this->data.end(); ++i)
-    {
-      int64_t id = std::abs(static_cast<int64_t>(ndn::random::generateWord64()));
-      this->idToDataMap.insert(std::make_pair(id, *i));
-
-      BOOST_CHECK_EQUAL(this->index.insert(**i, id), true);
-    }
-
-  BOOST_CHECK_EQUAL(this->index.size(), this->data.size());
-
-  for (typename T::InterestContainer::iterator i = this->interests.begin();
-       i != this->interests.end(); ++i)
-    {
-      std::pair<int64_t, Name> item = this->index.find(i->first);
-
-      BOOST_REQUIRE_GT(item.first, 0);
-      BOOST_REQUIRE(this->idToDataMap.count(item.first) > 0);
-
-      BOOST_TEST_MESSAGE(i->first);
-      BOOST_CHECK_EQUAL(*this->idToDataMap[item.first], *i->second);
-
-      BOOST_CHECK_EQUAL(this->index.hasData(*i->second), true);
-    }
-
-  // Need support for selector-based removal
-  // for (typename T::RemovalsContainer::iterator i = this->removals.begin();
-  //      i != this->removals.end(); ++i)
-  //   {
-  //     size_t nRemoved = 0;
-  //     BOOST_REQUIRE_NO_THROW(this->index.erase(*i));
-  //     BOOST_CHECK_EQUAL(nRemoved, i->seconds);
-  //   }
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace repo
diff --git a/tests/unit/repo-command-parameter.cpp b/tests/unit/repo-command-parameter.cpp
index 3e35169..f01832a 100644
--- a/tests/unit/repo-command-parameter.cpp
+++ b/tests/unit/repo-command-parameter.cpp
@@ -19,8 +19,12 @@
 
 #include "repo-command-parameter.hpp"
 
-#include <ndn-cxx/selectors.hpp>
+#include "common.hpp"
 
+#include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/block-helpers.hpp>
+
+#include <boost/lexical_cast.hpp>
 #include <boost/test/unit_test.hpp>
 
 namespace repo {
@@ -35,33 +39,21 @@
   parameter.setStartBlockId(1);
   parameter.setEndBlockId(100);
   parameter.setProcessId(1234567890);
-  ndn::Selectors selectors;
-  selectors.setMaxSuffixComponents(1);
-  parameter.setSelectors(selectors);
 
-  ndn::Block wire = parameter.wireEncode();
+  Block wire = parameter.wireEncode();
 
   // These octets are obtained by the snippet below.
   // This check is intended to detect unexpected encoding change in the future.
-  //for (auto it = wire.begin(); it != wire.end(); ++it) {
-  //  printf("0x%02x, ", *it);
-  //}
-  static const uint8_t expected[] = {
-    0xc9, 0x1c, 0x07, 0x09, 0x08, 0x01, 0x61, 0x08, 0x01, 0x62, 0x08,
-    0x01, 0x63, 0x09, 0x03, 0x0e, 0x01, 0x01, 0xcc, 0x01, 0x01, 0xcd,
-    0x01, 0x64, 0xce, 0x04, 0x49, 0x96, 0x02, 0xd2
-  };
+  // Construct a \c Block from hexadecimal \p input.
+  Block expected = "C917 0709080161080162080163CC0101CD0164CE04499602D2"_block;
 
-  BOOST_REQUIRE_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
-                                  wire.begin(), wire.end());
+  BOOST_CHECK_EQUAL(wire, expected);
 
   repo::RepoCommandParameter decoded(wire);
   BOOST_CHECK_EQUAL(decoded.getName(), parameter.getName());
   BOOST_CHECK_EQUAL(decoded.getStartBlockId(), parameter.getStartBlockId());
   BOOST_CHECK_EQUAL(decoded.getEndBlockId(), parameter.getEndBlockId());
   BOOST_CHECK_EQUAL(decoded.getProcessId(), parameter.getProcessId());
-  BOOST_CHECK_EQUAL(decoded.getSelectors().getMaxSuffixComponents(),
-                    parameter.getSelectors().getMaxSuffixComponents());
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/unit/repo-command-response.cpp b/tests/unit/repo-command-response.cpp
index 7686c50..057b180 100644
--- a/tests/unit/repo-command-response.cpp
+++ b/tests/unit/repo-command-response.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018, Regents of the University of California.
+ * Copyright (c) 2018, Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -19,6 +19,8 @@
 
 #include "repo-command-response.hpp"
 
+#include "common.hpp"
+
 #include <boost/test/unit_test.hpp>
 
 namespace repo {
@@ -36,21 +38,15 @@
   response.setInsertNum(100);
   response.setDeleteNum(100);
 
-  ndn::Block wire = response.wireEncode();
+  Block wire = response.wireEncode();
 
   // These octets are obtained by the snippet below.
   // This check is intended to detect unexpected encoding change in the future.
-  //for (auto it = wire.begin(); it != wire.end(); ++it) {
-  //  printf("0x%02x, ", *it);
-  //}
-  static const uint8_t expected[] = {
-    0xcf, 0x16, 0xce, 0x04, 0x49, 0x96, 0x02, 0xd2, 0xd0, 0x02,
-    0x01, 0x94, 0xcc, 0x01, 0x01, 0xcd, 0x01, 0x64, 0xd1, 0x01,
-    0x64, 0xd2, 0x01, 0x64
-  };
+  // Construct a \c Block from hexadecimal \p input.
 
-  BOOST_REQUIRE_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
-                                  wire.begin(), wire.end());
+  Block expected = "CF16 CE04499602D2D0020194CC0101CD0164D10164D20164"_block;
+
+  BOOST_CHECK_EQUAL(wire, expected);
 
   repo::RepoCommandResponse decoded(wire);
   BOOST_CHECK_EQUAL(decoded.getCode(), response.getCode());
diff --git a/tests/unit/repo-storage.cpp b/tests/unit/repo-storage.cpp
index 1caecf1..0458c23 100644
--- a/tests/unit/repo-storage.cpp
+++ b/tests/unit/repo-storage.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017, Regents of the University of California.
+ * Copyright (c) 2014-2018, Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -37,41 +37,31 @@
 {
 };
 
-// Combine CommonDatasets with ComplexSelectorDataset
-typedef boost::mpl::push_back<CommonDatasets,
-                              ComplexSelectorsDataset>::type Datasets;
 
-BOOST_FIXTURE_TEST_CASE_TEMPLATE(Bulk, T, Datasets, Fixture<T>)
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Bulk, T, CommonDatasets, Fixture<T>)
 {
-  // typedef ComplexSelectorsDataset T;
   BOOST_TEST_MESSAGE(T::getName());
 
   // Insert data into repo
-  for (typename T::DataContainer::iterator i = this->data.begin();
-       i != this->data.end(); ++i)
-    {
-      BOOST_CHECK_EQUAL(this->handle->insertData(**i), true);
-    }
+  for (auto i = this->data.begin(); i != this->data.end(); ++i) {
+    BOOST_CHECK_EQUAL(this->handle->insertData(**i), true);
+  }
 
   // check size directly with the storage (repo doesn't have interface yet)
   BOOST_CHECK_EQUAL(this->store->size(), static_cast<int64_t>(this->data.size()));
 
   // Read
-  for (typename T::InterestContainer::iterator i = this->interests.begin();
-       i != this->interests.end(); ++i)
-  {
-      shared_ptr<ndn::Data> dataTest = this->handle->readData(i->first);
-      BOOST_CHECK_EQUAL(*this->handle->readData(i->first), *i->second);
-    }
+  for (auto i = this->interests.begin(); i != this->interests.end(); ++i) {
+    std::shared_ptr<ndn::Data> dataTest = this->handle->readData(i->first);
+    BOOST_CHECK_EQUAL(*dataTest, *i->second);
+  }
 
   // Remove items
-  for (typename T::RemovalsContainer::iterator i = this->removals.begin();
-       i != this->removals.end(); ++i)
-    {
-      size_t nRemoved = 0;
-      BOOST_REQUIRE_NO_THROW(nRemoved = this->handle->deleteData(i->first));
-      BOOST_CHECK_EQUAL(nRemoved, i->second);
-    }
+  for (auto i = this->removals.begin(); i != this->removals.end(); ++i) {
+    size_t nRemoved = 0;
+    nRemoved = this->handle->deleteData(i->first);
+    BOOST_CHECK_EQUAL(nRemoved, i->second);
+  }
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/unit/sqlite-handle.cpp b/tests/unit/sqlite-handle.cpp
index ca7c7dd..9cfb0bf 100644
--- a/tests/unit/sqlite-handle.cpp
+++ b/tests/unit/sqlite-handle.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017, Regents of the University of California.
+ * Copyright (c) 2014-2018, Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -34,40 +34,40 @@
 class Fixture : public SqliteFixture, public Dataset
 {
 public:
-  std::map<int64_t, shared_ptr<Data>> idToDataMap;
+  std::map<Name, std::shared_ptr<Data>> nameToDataMap;
 };
 
 BOOST_FIXTURE_TEST_CASE_TEMPLATE(InsertReadDelete, T, CommonDatasets, Fixture<T>)
 {
   BOOST_TEST_CHECKPOINT(T::getName());
 
-  std::vector<int64_t> ids;
+  std::vector<Name> names;
 
   // Insert
-  for (typename T::DataContainer::iterator i = this->data.begin();
+  for (auto i = this->data.begin();
        i != this->data.end(); ++i) {
-    int64_t id = -1;
-    BOOST_REQUIRE_NO_THROW(id = this->handle->insert(**i));
-
-    this->idToDataMap.insert(std::make_pair(id, *i));
-    ids.push_back(id);
+    Name name = Name();
+    this->handle->insert(**i);
+    name = (*i)->getFullName();
+    this->nameToDataMap.insert(std::make_pair(name, *i));
+    names.push_back(name);
   }
   BOOST_CHECK_EQUAL(this->handle->size(), static_cast<int64_t>(this->data.size()));
 
   std::mt19937 rng{std::random_device{}()};
-  std::shuffle(ids.begin(), ids.end(), rng);
+  std::shuffle(names.begin(), names.end(), rng);
 
   // Read (all items should exist)
-  for (std::vector<int64_t>::iterator i = ids.begin(); i != ids.end(); ++i) {
-    shared_ptr<Data> retrievedData = this->handle->read(*i);
+  for (auto i = names.begin(); i != names.end(); ++i) {
+    std::shared_ptr<Data> retrievedData = this->handle->read(*i);
 
-    BOOST_REQUIRE(this->idToDataMap.count(*i) > 0);
-    BOOST_CHECK_EQUAL(*this->idToDataMap[*i], *retrievedData);
+    BOOST_REQUIRE(this->nameToDataMap.count(*i) > 0);
+    BOOST_CHECK_EQUAL(*this->nameToDataMap[*i], *retrievedData);
   }
   BOOST_CHECK_EQUAL(this->handle->size(), static_cast<int64_t>(this->data.size()));
 
   // Delete
-  for (std::vector<int64_t>::iterator i = ids.begin(); i != ids.end(); ++i) {
+  for (auto i = names.begin(); i != names.end(); ++i) {
     BOOST_CHECK_EQUAL(this->handle->erase(*i), true);
   }
 
diff --git a/tests/unit/tcp-bulk-insert-handle.cpp b/tests/unit/tcp-bulk-insert-handle.cpp
index f35a42f..48ec17d 100644
--- a/tests/unit/tcp-bulk-insert-handle.cpp
+++ b/tests/unit/tcp-bulk-insert-handle.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  Regents of the University of California.
+ * Copyright (c) 2014-2018,  Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -57,17 +57,16 @@
     ip::tcp::endpoint serverEndpoint = *endpoint;
 
     socket.async_connect(serverEndpoint,
-                         bind(&TcpClient::onSuccessfullConnect, this, _1));
+                         std::bind(&TcpClient::onSuccessfullConnect, this, _1));
   }
 
   virtual void
   onSuccessfullConnect(const boost::system::error_code& error)
   {
-    if (error)
-      {
-        BOOST_FAIL("TCP connection aborted");
-        return;
-      }
+    if (error) {
+      BOOST_FAIL("TCP connection aborted");
+      return;
+    }
   }
 
 public:
@@ -86,7 +85,7 @@
     , bulkInserter(ioService, *handle)
   {
     guardEvent = scheduler.scheduleEvent(ndn::time::seconds(2),
-                                         bind(&TcpBulkInsertFixture::fail, this, "Test timed out"));
+                                         std::bind(&TcpBulkInsertFixture::fail, this, "Test timed out"));
   }
 
   virtual void
@@ -102,15 +101,12 @@
     // described in http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/overview/implementation.html,
     // scatter-gather is limited to at most `min(64,IOV_MAX)` buffers to be transmitted
     // in a single operation
-    for (typename Dataset::DataContainer::iterator i = this->data.begin();
-         i != this->data.end(); ++i) {
+    for (auto i = this->data.begin(); i != this->data.end(); ++i) {
 
-      socket.async_send(boost::asio::buffer((*i)->wireEncode().wire(),  (*i)->wireEncode().size()),
-                        bind(&TcpBulkInsertFixture::onSendFinished, this, _1, false));
+      socket.async_send(boost::asio::buffer((*i)->wireEncode().wire(), (*i)->wireEncode().size()),
+                        std::bind(&TcpBulkInsertFixture::onSendFinished, this, _1, false));
     }
-
-    socket.async_send(boost::asio::buffer(static_cast<const uint8_t*>(0), 0),
-                      bind(&TcpBulkInsertFixture::onSendFinished, this, _1, true));
+    onSendFinished(error, true);
   }
 
   void
@@ -127,7 +123,7 @@
       // In case there are some outstanding handlers
       // ioService.post(bind(&TcpBulkInsertFixture::stop, this));
       scheduler.scheduleEvent(ndn::time::seconds(1),
-                              bind(&TcpBulkInsertFixture::stop, this));
+                              std::bind(&TcpBulkInsertFixture::stop, this));
     }
   }
 
@@ -170,9 +166,8 @@
   this->ioService.run();
 
   // Read (all items should exist)
-  for (typename T::InterestContainer::iterator i = this->interests.begin();
-       i != this->interests.end(); ++i) {
-      BOOST_CHECK_EQUAL(*this->handle->readData(i->first), *i->second);
+  for (auto i = this->interests.begin(); i != this->interests.end(); ++i) {
+    BOOST_CHECK_EQUAL(*this->handle->readData(i->first), *i->second);
   }
 }
 
diff --git a/tools/ndngetfile.cpp b/tools/ndngetfile.cpp
index 9764ca6..559541c 100644
--- a/tools/ndngetfile.cpp
+++ b/tools/ndngetfile.cpp
@@ -47,14 +47,15 @@
   }
   else {
     interest.setMustBeFresh(true);
-    interest.setChildSelector(1);
   }
 
+  interest.setCanBePrefix(m_canBePrefix);
+
   m_face.expressInterest(interest,
-                         m_hasVersion ? bind(&Consumer::onVersionedData, this, _1, _2)
-                                      : bind(&Consumer::onUnversionedData, this, _1, _2),
-                         bind(&Consumer::onTimeout, this, _1), // Nack
-                         bind(&Consumer::onTimeout, this, _1));
+                         m_hasVersion ? std::bind(&Consumer::onVersionedData, this, _1, _2)
+                                      : std::bind(&Consumer::onUnversionedData, this, _1, _2),
+                         std::bind(&Consumer::onTimeout, this, _1), // Nack
+                         std::bind(&Consumer::onTimeout, this, _1));
 }
 
 void
@@ -112,7 +113,6 @@
 Consumer::onUnversionedData(const Interest& interest, const Data& data)
 {
   const Name& name = data.getName();
-  //std::cout<<"recevied data name = "<<name<<std::endl;
   if (name.size() == m_dataName.size() + 1) {
     if (!m_isSingle) {
       Name fetchName = name;
@@ -155,7 +155,7 @@
     std::cerr << "LOG: received data = " << data.getName() << std::endl;
   }
   if (m_isFinished || m_isSingle) {
-    std::cerr << "INFO: End of file is reached." << std::endl;
+    std::cerr << "INFO: End of file is reached" << std::endl;
     std::cerr << "INFO: Total # of segments received: " << m_nextSegment  << std::endl;
     std::cerr << "INFO: Total # bytes of content received: " << m_totalSize << std::endl;
   }
@@ -188,7 +188,7 @@
     // Retransmit the interest
     fetchData(interest.getName());
     if (m_verbose) {
-        std::cerr << "TIMEOUT: retransmit interest for " << interest.getName() << std::endl;
+      std::cerr << "TIMEOUT: retransmit interest for " << interest.getName() << std::endl;
     }
   }
   else {
@@ -240,7 +240,7 @@
           interestLifetime = boost::lexical_cast<int>(optarg);
         }
         catch (const boost::bad_lexical_cast&) {
-          std::cerr << "ERROR: -l option should be an integer." << std::endl;
+          std::cerr << "ERROR: -l option should be an integer" << std::endl;
           return 1;
         }
         interestLifetime = std::max(interestLifetime, 0);
@@ -250,7 +250,7 @@
           timeout = boost::lexical_cast<int>(optarg);
         }
         catch (const boost::bad_lexical_cast&) {
-          std::cerr << "ERROR: -w option should be an integer." << std::endl;
+          std::cerr << "ERROR: -w option should be an integer" << std::endl;
           return 1;
         }
         timeout = std::max(timeout, 0);
diff --git a/tools/ndngetfile.hpp b/tools/ndngetfile.hpp
index e7e851b..92cf799 100644
--- a/tools/ndngetfile.hpp
+++ b/tools/ndngetfile.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017, Regents of the University of California.
+ * Copyright (c) 2014-2018, Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -30,7 +30,8 @@
   Consumer(const std::string& dataName, std::ostream& os,
            bool verbose, bool versioned, bool single,
            int interestLifetime, int timeout,
-           bool mustBeFresh = false)
+           bool mustBeFresh = false,
+           bool canBePrefix = false)
     : m_dataName(dataName)
     , m_os(os)
     , m_verbose(verbose)
@@ -44,6 +45,7 @@
     , m_totalSize(0)
     , m_retryCount(0)
     , m_mustBeFresh(mustBeFresh)
+    , m_canBePrefix(canBePrefix)
   {
   }
 
@@ -85,6 +87,7 @@
   int m_totalSize;
   int m_retryCount;
   bool m_mustBeFresh;
+  bool m_canBePrefix;
 };
 
 } // namespace repo
diff --git a/tools/ndnputfile.cpp b/tools/ndnputfile.cpp
index b4f40f4..97dbd77 100644
--- a/tools/ndnputfile.cpp
+++ b/tools/ndnputfile.cpp
@@ -33,9 +33,9 @@
 #include <iostream>
 #include <string>
 
+#include <boost/asio.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/lexical_cast.hpp>
-#include <boost/asio.hpp>
 #include <boost/iostreams/operations.hpp>
 #include <boost/iostreams/read.hpp>
 
@@ -161,7 +161,7 @@
   bool m_isFinished;
   ndn::Name m_dataPrefix;
 
-  typedef std::map<uint64_t, shared_ptr<ndn::Data> > DataContainer;
+  using DataContainer = std::map<uint64_t, shared_ptr<ndn::Data>>;
   DataContainer m_data;
   ndn::security::CommandInterestSigner m_cmdSigner;
 };
@@ -265,7 +265,6 @@
 NdnPutFile::onInsertCommandResponse(const ndn::Interest& interest, const ndn::Data& data)
 {
   RepoCommandResponse response(data.getContent().blockFromValue());
-  //int statusCode = response.getStatusCode();
   int statusCode = response.getCode();
   if (statusCode >= 400) {
     BOOST_THROW_EXCEPTION(Error("insert command failed with code " +
@@ -503,7 +502,7 @@
         ndnPutFile.freshnessPeriod = milliseconds(boost::lexical_cast<uint64_t>(optarg));
       }
       catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-x option should be an integer.";
+        std::cerr << "-x option should be an integer" << std::endl;;
         return 1;
       }
       break;
@@ -512,7 +511,7 @@
         ndnPutFile.interestLifetime = milliseconds(boost::lexical_cast<uint64_t>(optarg));
       }
       catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-l option should be an integer.";
+        std::cerr << "-l option should be an integer" << std::endl;;
         return 1;
       }
       break;
@@ -522,7 +521,7 @@
         ndnPutFile.timeout = milliseconds(boost::lexical_cast<uint64_t>(optarg));
       }
       catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-w option should be an integer.";
+        std::cerr << "-w option should be an integer" << std::endl;;
         return 1;
       }
       break;
@@ -543,10 +542,9 @@
   if (argc != 3)
     usage();
 
-  ndnPutFile.repoPrefix = Name(argv[0]); std::cout << "Repo prefix: " << argv[0] << std::endl;
-  ndnPutFile.ndnName = Name(argv[1]);    std::cout << "NDN name: " << argv[1] << std::endl;
+  ndnPutFile.repoPrefix = Name(argv[0]);
+  ndnPutFile.ndnName = Name(argv[1]);
   if (strcmp(argv[2], "-") == 0) {
-
     ndnPutFile.insertStream = &std::cin;
     ndnPutFile.run();
   }
diff --git a/tools/ndnrepowatch.cpp b/tools/ndnrepowatch.cpp
deleted file mode 100644
index b844c00..0000000
--- a/tools/ndnrepowatch.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2018, Regents of the University of California.
- *
- * This file is part of NDN repo-ng (Next generation of NDN repository).
- * See AUTHORS.md for complete list of repo-ng authors and contributors.
- *
- * repo-ng 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.
- *
- * repo-ng 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
- * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "../src/repo-command-parameter.hpp"
-#include "../src/repo-command-response.hpp"
-
-#include <ndn-cxx/face.hpp>
-#include <ndn-cxx/security/command-interest-signer.hpp>
-#include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/security/signing-helpers.hpp>
-
-#include <boost/asio/io_service.hpp>
-#include <ndn-cxx/util/scheduler.hpp>
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <fstream>
-#include <iostream>
-#include <string>
-
-#include <boost/asio/io_service.hpp>
-#include <boost/lexical_cast.hpp>
-
-namespace repo {
-
-using namespace ndn::time;
-
-using std::shared_ptr;
-using std::bind;
-using std::placeholders::_1;
-using std::placeholders::_2;
-
-static const uint64_t DEFAULT_INTEREST_LIFETIME = 4000;
-static const uint64_t DEFAULT_FRESHNESS_PERIOD = 10000;
-static const uint64_t DEFAULT_CHECK_PERIOD = 1000;
-
-enum CommandType
-{
-  START,
-  CHECK,
-  STOP
-};
-
-class NdnRepoWatch : boost::noncopyable
-{
-public:
-  class Error : public std::runtime_error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : std::runtime_error(what)
-    {
-    }
-  };
-
-  NdnRepoWatch()
-    : freshnessPeriod(DEFAULT_FRESHNESS_PERIOD)
-    , interestLifetime(DEFAULT_INTEREST_LIFETIME)
-    , hasTimeout(false)
-    , watchTimeout(0)
-    , hasMaxInterestNum(false)
-    , maxInterestNum(0)
-    , status(START)
-    , isVerbose(false)
-    , m_scheduler(m_face.getIoService())
-    , m_checkPeriod(DEFAULT_CHECK_PERIOD)
-    , m_cmdSigner(m_keyChain)
-  {
-  }
-
-  void
-  run();
-
-private:
-
-  void
-  startWatchCommand();
-
-  void
-  onWatchCommandResponse(const ndn::Interest& interest, const ndn::Data& data);
-
-  void
-  onWatchCommandTimeout(const ndn::Interest& interest);
-
-  void
-  stopProcess();
-
-  void
-  signData(ndn::Data& data);
-
-  void
-  startCheckCommand();
-
-  void
-  onCheckCommandTimeout(const ndn::Interest& interest);
-
-  void
-  onStopCommandResponse(const ndn::Interest& interest, ndn::Data& data);
-
-  void
-  onStopCommandTimeout(const ndn::Interest& interest);
-
-  ndn::Interest
-  generateCommandInterest(const ndn::Name& commandPrefix, const std::string& command,
-                          const RepoCommandParameter& commandParameter);
-
-public:
-  std::string identityForCommand;
-  milliseconds freshnessPeriod;
-  milliseconds interestLifetime;
-  bool hasTimeout;
-  milliseconds watchTimeout;
-  bool hasMaxInterestNum;
-  int64_t maxInterestNum;
-  CommandType status;
-  ndn::Name repoPrefix;
-  ndn::Name ndnName;
-  bool isVerbose;
-
-
-private:
-  ndn::Face m_face;
-  ndn::Scheduler m_scheduler;
-  milliseconds m_checkPeriod;
-
-  ndn::Name m_dataPrefix;
-  ndn::KeyChain m_keyChain;
-  typedef std::map<uint64_t, shared_ptr<ndn::Data> > DataContainer;
-  ndn::security::CommandInterestSigner m_cmdSigner;
-};
-
-void
-NdnRepoWatch::run()
-{
-  m_dataPrefix = ndnName;
-  startWatchCommand();
-
-  if (hasTimeout)
-    m_scheduler.scheduleEvent(watchTimeout, bind(&NdnRepoWatch::stopProcess, this));
-
-  m_face.processEvents();
-}
-
-void
-NdnRepoWatch::startWatchCommand()
-{
-  RepoCommandParameter parameters;
-  parameters.setName(m_dataPrefix);
-
-  repoPrefix.append("watch");
-  if (status == START) {
-    if (hasMaxInterestNum) {
-      parameters.setMaxInterestNum(maxInterestNum);
-    }
-    if (hasTimeout) {
-      parameters.setWatchTimeout(watchTimeout);
-    }
-    ndn::Interest commandInterest = generateCommandInterest(repoPrefix, "start", parameters);
-    m_face.expressInterest(commandInterest,
-                           bind(&NdnRepoWatch::onWatchCommandResponse, this,
-                                     _1, _2),
-                           bind(&NdnRepoWatch::onWatchCommandTimeout, this, _1), // Nack
-                           bind(&NdnRepoWatch::onWatchCommandTimeout, this, _1));
-  }
-  else if (status == STOP){
-    ndn::Interest commandInterest = generateCommandInterest(repoPrefix, "stop", parameters);
-    m_face.expressInterest(commandInterest,
-                           bind(&NdnRepoWatch::onWatchCommandResponse, this,
-                                     _1, _2),
-                           bind(&NdnRepoWatch::onWatchCommandTimeout, this, _1), // Nack
-                           bind(&NdnRepoWatch::onWatchCommandTimeout, this, _1));
-  }
-  else if (status == CHECK){
-    ndn::Interest commandInterest = generateCommandInterest(repoPrefix, "check", parameters);
-    m_face.expressInterest(commandInterest,
-                           bind(&NdnRepoWatch::onWatchCommandResponse, this,
-                                     _1, _2),
-                           bind(&NdnRepoWatch::onWatchCommandTimeout, this, _1), // Nack
-                           bind(&NdnRepoWatch::onWatchCommandTimeout, this, _1));
-  }
-
-}
-
-void
-NdnRepoWatch::onWatchCommandResponse(const ndn::Interest& interest, const ndn::Data& data)
-{
-  RepoCommandResponse response(data.getContent().blockFromValue());
-  int statusCode = response.getCode();
-  if (statusCode >= 400) {
-    BOOST_THROW_EXCEPTION(Error("Watch command failed with code " +
-                                boost::lexical_cast<std::string>(statusCode)));
-  }
-  else if (statusCode == 101) {
-    std::cerr << "Watching prefix is stopped!" <<std::endl;
-    m_face.getIoService().stop();
-    return;
-  }
-  else if (statusCode == 300) {
-    std::cerr << "Watching prefix is running!" <<std::endl;
-    m_scheduler.scheduleEvent(m_checkPeriod,
-                              bind(&NdnRepoWatch::startCheckCommand, this));
-    return;
-  }
-  else if (statusCode == 100) {
-    std::cerr << "Watching prefix starts!" <<std::endl;
-    m_scheduler.scheduleEvent(m_checkPeriod,
-                              bind(&NdnRepoWatch::startCheckCommand, this));
-    return;
-  }
-  else {
-    BOOST_THROW_EXCEPTION(Error("Unrecognized Status Code " +
-                                boost::lexical_cast<std::string>(statusCode)));
-  }
-}
-
-void
-NdnRepoWatch::onWatchCommandTimeout(const ndn::Interest& interest)
-{
-  BOOST_THROW_EXCEPTION(Error("command response timeout"));
-}
-
-void
-NdnRepoWatch::stopProcess()
-{
-  m_face.getIoService().stop();
-}
-
-void
-NdnRepoWatch::startCheckCommand()
-{
-  repoPrefix.append("watch");
-  ndn::Interest checkInterest = generateCommandInterest(repoPrefix, "check",
-                                                        RepoCommandParameter()
-                                                          .setName(m_dataPrefix));
-  m_face.expressInterest(checkInterest,
-                         bind(&NdnRepoWatch::onWatchCommandResponse, this, _1, _2),
-                         bind(&NdnRepoWatch::onCheckCommandTimeout, this, _1), // Nack
-                         bind(&NdnRepoWatch::onCheckCommandTimeout, this, _1));
-}
-
-void
-NdnRepoWatch::onCheckCommandTimeout(const ndn::Interest& interest)
-{
-  BOOST_THROW_EXCEPTION(Error("check response timeout"));
-}
-
-void
-NdnRepoWatch::onStopCommandResponse(const ndn::Interest& interest, ndn::Data& data)
-{
-  RepoCommandResponse response(data.getContent().blockFromValue());
-  int statusCode = response.getCode();
-  if (statusCode != 101) {
-    BOOST_THROW_EXCEPTION(Error("Watch stop command failed with code: " +
-                                boost::lexical_cast<std::string>(statusCode)));
-  }
-  else {
-    std::cerr << "Status code is 101. Watching prefix is stopped successfully!" << std::endl;
-    m_face.getIoService().stop();
-    return;
-  }
-}
-
-void
-NdnRepoWatch::onStopCommandTimeout(const ndn::Interest& interest)
-{
-  BOOST_THROW_EXCEPTION(Error("stop response timeout"));
-}
-
-ndn::Interest
-NdnRepoWatch::generateCommandInterest(const ndn::Name& commandPrefix, const std::string& command,
-                                      const RepoCommandParameter& commandParameter)
-{
-  Name cmd = commandPrefix;
-  cmd
-    .append(command)
-    .append(commandParameter.wireEncode());
-  ndn::Interest interest;
-
-  if (identityForCommand.empty())
-    interest = m_cmdSigner.makeCommandInterest(cmd);
-  else {
-    interest = m_cmdSigner.makeCommandInterest(cmd, ndn::signingByIdentity(identityForCommand));
-  }
-
-  interest.setInterestLifetime(interestLifetime);
-  return interest;
-}
-
-static void
-usage()
-{
-  fprintf(stderr,
-          "NdnRepoWatch [-I identity]"
-          "  [-x freshness] [-l lifetime] [-w watchtimeout]"
-          "  [-n maxinterestnum][-s stop] [-c check]repo-prefix ndn-name\n"
-          "\n"
-          " Write a file into a repo.\n"
-          "  -I: specify identity used for signing commands\n"
-          "  -x: FreshnessPeriod in milliseconds\n"
-          "  -l: InterestLifetime in milliseconds for each command\n"
-          "  -w: timeout in milliseconds for whole process (default unlimited)\n"
-          "  -n: total number of interests to be sent for whole process (default unlimited)\n"
-          "  -s: stop the whole process\n"
-          "  -c: check the process\n"
-          "  repo-prefix: repo command prefix\n"
-          "  ndn-name: NDN Name prefix for written Data\n"
-          );
-  exit(1);
-}
-
-int
-main(int argc, char** argv)
-{
-  NdnRepoWatch app;
-  int opt;
-  while ((opt = getopt(argc, argv, "x:l:w:n:scI:")) != -1) {
-    switch (opt) {
-    case 'x':
-      try {
-        app.freshnessPeriod = milliseconds(boost::lexical_cast<uint64_t>(optarg));
-      }
-      catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-x option should be an integer.";
-        return 1;
-      }
-      break;
-    case 'l':
-      try {
-        app.interestLifetime = milliseconds(boost::lexical_cast<uint64_t>(optarg));
-      }
-      catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-l option should be an integer.";
-        return 1;
-      }
-      break;
-    case 'w':
-      app.hasTimeout = true;
-      try {
-        app.watchTimeout = milliseconds(boost::lexical_cast<int64_t>(optarg));
-      }
-      catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-w option should be an integer.";
-        return 1;
-      }
-      break;
-    case 'n':
-      app.hasMaxInterestNum = true;
-      try {
-        app.maxInterestNum = boost::lexical_cast<int64_t>(optarg);
-      }
-      catch (const boost::bad_lexical_cast&) {
-        std::cerr << "-n option should be an integer.";
-        return 1;
-      }
-      break;
-    case 's':
-      app.status = STOP;
-      break;
-    case 'c':
-      app.status = CHECK;
-      break;
-    case 'I':
-      app.identityForCommand = std::string(optarg);
-      break;
-    case 'v':
-      app.isVerbose = true;
-      break;
-    case 'h':
-      usage();
-      break;
-    default:
-      break;
-    }
-  }
-
-  argc -= optind;
-  argv += optind;
-
-  if (argc != 2)
-    usage();
-
-  app.repoPrefix = Name(argv[0]);
-  app.ndnName = Name(argv[1]);
-
-  app.run();
-
-  return 0;
-}
-
-} // namespace repo
-
-int
-main(int argc, char** argv)
-{
-  try {
-    return repo::main(argc, argv);
-  }
-  catch (const std::exception& e) {
-    std::cerr << "ERROR: " << e.what() << std::endl;
-    return 2;
-  }
-}
diff --git a/tools/repo-ng-ls.cpp b/tools/repo-ng-ls.cpp
index 1ce0b28..637b03f 100644
--- a/tools/repo-ng-ls.cpp
+++ b/tools/repo-ng-ls.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017, Regents of the University of California.
+ * Copyright (c) 2014-2018, Regents of the University of California.
  *
  * This file is part of NDN repo-ng (Next generation of NDN repository).
  * See AUTHORS.md for complete list of repo-ng authors and contributors.
@@ -23,6 +23,8 @@
 #include <iostream>
 #include <string>
 
+#include <ndn-cxx/util/sqlite3-statement.hpp>
+
 #include <boost/property_tree/info_parser.hpp>
 #include <boost/property_tree/ptree.hpp>
 
@@ -30,8 +32,6 @@
 
 namespace repo {
 
-using std::string;
-
 static void
 printUsage(const char* programName)
 {
@@ -80,20 +80,19 @@
 RepoEnumerator::RepoEnumerator(const std::string& configFile)
 {
   readConfig(configFile);
-  char* errMsg = 0;
-  int rc = sqlite3_open_v2(m_dbPath.c_str(), &m_db,
-                           SQLITE_OPEN_READONLY,
+  char* errMsg = nullptr;
+  int rc = sqlite3_open_v2(m_dbPath.c_str(), &m_db, SQLITE_OPEN_READONLY,
    #ifdef DISABLE_SQLITE3_FS_LOCKING
-                            "unix-dotfile"
+                           "unix-dotfile"
    #else
-                            0
+                           nullptr
    #endif
                           );
   if (rc != SQLITE_OK) {
     BOOST_THROW_EXCEPTION(Error("Database file open failure"));
   }
-  sqlite3_exec(m_db, "PRAGMA synchronous = OFF", 0, 0, &errMsg);
-  sqlite3_exec(m_db, "PRAGMA journal_mode = WAL", 0, 0, &errMsg);
+  sqlite3_exec(m_db, "PRAGMA synchronous = OFF", nullptr, nullptr, &errMsg);
+  sqlite3_exec(m_db, "PRAGMA journal_mode = WAL", nullptr, nullptr, &errMsg);
 }
 
 void
@@ -123,49 +122,34 @@
 uint64_t
 RepoEnumerator::enumerate(bool showImplicitDigest)
 {
-  sqlite3_stmt* m_stmt = 0;
-  int rc = SQLITE_DONE;
-  string sql = string("SELECT id, name, keylocatorHash FROM NDN_REPO;");
-  rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &m_stmt, 0);
-  if (rc != SQLITE_OK)
-    BOOST_THROW_EXCEPTION(Error("Initiation Read Entries from Database Prepare error"));
-  uint64_t entryNumber = 0;
+  ndn::util::Sqlite3Statement stmt(m_db, "SELECT data FROM NDN_REPO_V2;");
+  uint64_t nEntries = 0;
   while (true) {
-    rc = sqlite3_step(m_stmt);
+    int rc = stmt.step();
     if (rc == SQLITE_ROW) {
-      Name name;
-      name.wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(m_stmt, 1)),
-                            sqlite3_column_bytes(m_stmt, 1)));
-      try {
-        if (showImplicitDigest) {
-          std::cout << name << std::endl;
-        }
-        else {
-          std::cout << name.getPrefix(-1) << std::endl;
-        }
+      Data data(stmt.getBlock(0));
+      if (showImplicitDigest) {
+        std::cout << data.getFullName() << std::endl;
       }
-      catch (...){
-        sqlite3_finalize(m_stmt);
-        throw;
+      else {
+        std::cout << data.getName() << std::endl;
       }
-      entryNumber++;
+      nEntries++;
     }
     else if (rc == SQLITE_DONE) {
-      sqlite3_finalize(m_stmt);
       break;
     }
     else {
-      sqlite3_finalize(m_stmt);
       BOOST_THROW_EXCEPTION(Error("Initiation Read Entries error"));
     }
   }
-  return entryNumber;
+  return nEntries;
 }
 
 int
 main(int argc, char** argv)
 {
-  string configPath = DEFAULT_CONFIG_FILE;
+  std::string configPath = DEFAULT_CONFIG_FILE;
   bool showImplicitDigest = true;
   int opt;
   while ((opt = getopt(argc, argv, "hc:n")) != -1) {
@@ -174,7 +158,7 @@
       printUsage(argv[0]);
       return 0;
     case 'c':
-      configPath = string(optarg);
+      configPath = std::string(optarg);
       break;
     case 'n':
       showImplicitDigest = false;