object: Switch code to use ndn-cxx

This commit also moves code to ndn::chronoshare namespace

Change-Id: I63817cce605620c3c68d98ac4e46e1a265dc3d3b
diff --git a/src/object-db.cpp b/src/object-db.cpp
index e522b51..a77f2a5 100644
--- a/src/object-db.cpp
+++ b/src/object-db.cpp
@@ -18,34 +18,37 @@
  * See AUTHORS.md for complete list of ChronoShare authors and contributors.
  */
 
-#include "object-db.h"
-#include "db-helper.h"
-#include "logging.h"
-#include <boost/make_shared.hpp>
+#include "object-db.hpp"
+#include "db-helper.hpp"
+#include "core/logging.hpp"
+
 #include <iostream>
 #include <sys/stat.h>
 
-_LOG_INIT(Object.Db);
+#include <ndn-cxx/util/sqlite3-statement.hpp>
 
-using namespace std;
-using namespace Ndnx;
-using namespace boost;
+namespace ndn {
+namespace chronoshare {
+
+_LOG_INIT(ObjectDb);
+
 namespace fs = boost::filesystem;
+using ndn::util::Sqlite3Statement;
 
-const std::string INIT_DATABASE = "\
-CREATE TABLE                                                            \n \
-    File(                                                               \n\
-        device_name     BLOB NOT NULL,                                  \n\
-        segment         INTEGER,                                        \n\
-        content_object  BLOB,                                           \n\
-                                                                        \
-        PRIMARY KEY (device_name, segment)                              \n\
-    );                                                                  \n\
-CREATE INDEX device ON File(device_name);                               \n\
-";
+const std::string INIT_DATABASE = R"SQL(
+CREATE TABLE
+   File(
+        device_name     BLOB NOT NULL,
+        segment         INTEGER,
+        content_object  BLOB,
+
+        PRIMARY KEY (device_name, segment)
+    );
+CREATE INDEX device ON File(device_name);
+)SQL";
 
 ObjectDb::ObjectDb(const fs::path& folder, const std::string& hash)
-  : m_lastUsed(time(NULL))
+  : m_lastUsed(time::steady_clock::now())
 {
   fs::path actualFolder = folder / "objects" / hash.substr(0, 2);
   fs::create_directories(actualFolder);
@@ -54,30 +57,38 @@
 
   int res = sqlite3_open((actualFolder / hash.substr(2, hash.size() - 2)).c_str(), &m_db);
   if (res != SQLITE_OK) {
-    BOOST_THROW_EXCEPTION(Error::Db() << errmsg_info_str(
-                            "Cannot open/create dabatabase: [" +
-                            (actualFolder / hash.substr(2, hash.size() - 2)).string() + "]"));
+    BOOST_THROW_EXCEPTION(Error("Cannot open/create database: [" +
+                                (actualFolder / hash.substr(2, hash.size() - 2)).string() + "]"));
   }
 
   // Alex: determine if tables initialized. if not, initialize... not sure what is the best way to go...
   // for now, just attempt to create everything
 
   char* errmsg = 0;
-  res = sqlite3_exec(m_db, INIT_DATABASE.c_str(), NULL, NULL, &errmsg);
+  res = sqlite3_exec(m_db, INIT_DATABASE.c_str(), nullptr, nullptr, &errmsg);
   if (res != SQLITE_OK && errmsg != 0) {
-    // _LOG_TRACE ("Init \"error\": " << errmsg);
     sqlite3_free(errmsg);
   }
 
-  // _LOG_DEBUG ("open db");
-
   willStartSave();
 }
 
+ObjectDb::~ObjectDb()
+{
+  didStopSave();
+
+  int res = sqlite3_close(m_db);
+  if (res != SQLITE_OK) {
+    // complain
+  }
+}
+
 bool
-ObjectDb::DoesExist(const boost::filesystem::path& folder, const Ccnx::Name& deviceName,
+ObjectDb::doesExist(const boost::filesystem::path& folder, const Name& deviceName,
                     const std::string& hash)
 {
+  BOOST_ASSERT(hash.size() > 2);
+
   fs::path actualFolder = folder / "objects" / hash.substr(0, 2);
   bool retval = false;
 
@@ -89,8 +100,8 @@
                        "SELECT count(*), count(nullif(content_object,0)) FROM File WHERE device_name=?",
                        -1, &stmt, 0);
 
-    CcnxCharbufPtr buf = deviceName.toCcnxCharbuf();
-    sqlite3_bind_blob(stmt, 1, buf->buf(), buf->length(), SQLITE_TRANSIENT);
+    sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
+                      SQLITE_TRANSIENT);
 
     int res = sqlite3_step(stmt);
     if (res == SQLITE_ROW) {
@@ -111,105 +122,60 @@
   return retval;
 }
 
-
-ObjectDb::~ObjectDb()
-{
-  didStopSave();
-
-  // _LOG_DEBUG ("close db");
-  int res = sqlite3_close(m_db);
-  if (res != SQLITE_OK) {
-    // complain
-  }
-}
-
 void
-ObjectDb::saveContentObject(const Ccnx::Name& deviceName, sqlite3_int64 segment,
-                            const Ccnx::Bytes& data)
+ObjectDb::saveContentObject(const Name& deviceName, sqlite3_int64 segment, const Data& data)
 {
-  sqlite3_stmt* stmt;
-  sqlite3_prepare_v2(m_db, "INSERT INTO File "
-                           "(device_name, segment, content_object) "
-                           "VALUES (?, ?, ?)",
-                     -1, &stmt, 0);
-
-  //_LOG_DEBUG ("Saving content object for [" << deviceName << ", seqno: " << segment << ", size: " << data.size () << "]");
-
-  CcnxCharbufPtr buf = deviceName.toCcnxCharbuf();
-  sqlite3_bind_blob(stmt, 1, buf->buf(), buf->length(), SQLITE_STATIC);
-  sqlite3_bind_int64(stmt, 2, segment);
-  sqlite3_bind_blob(stmt, 3, &data[0], data.size(), SQLITE_STATIC);
-
-  sqlite3_step(stmt);
-  //_LOG_DEBUG ("After saving object: " << sqlite3_errmsg (m_db));
-  sqlite3_finalize(stmt);
-
   // update last used time
-  m_lastUsed = time(NULL);
+  m_lastUsed = time::steady_clock::now();
+
+  Sqlite3Statement stmt(m_db, "INSERT INTO File "
+                                "(device_name, segment, content_object) "
+                                "VALUES (?, ?, ?)");
+
+  _LOG_DEBUG("Saving content object for [" << deviceName << ", seqno: " << segment << ", size: "
+                                           << data.wireEncode().size()
+                                           << "]");
+  stmt.bind(1, deviceName.wireEncode(), SQLITE_STATIC);
+  stmt.bind(2, segment);
+  stmt.bind(3, data.wireEncode(), SQLITE_STATIC);
+  stmt.step();
 }
 
-Ccnx::BytesPtr
-ObjectDb::fetchSegment(const Ccnx::Name& deviceName, sqlite3_int64 segment)
+shared_ptr<Data>
+ObjectDb::fetchSegment(const Name& deviceName, sqlite3_int64 segment)
 {
-  sqlite3_stmt* stmt;
-  sqlite3_prepare_v2(m_db, "SELECT content_object FROM File WHERE device_name=? AND segment=?", -1,
-                     &stmt, 0);
+  // update last used time
+  m_lastUsed = time::steady_clock::now();
 
-  CcnxCharbufPtr buf = deviceName.toCcnxCharbuf();
-  sqlite3_bind_blob(stmt, 1, buf->buf(), buf->length(), SQLITE_TRANSIENT);
-  sqlite3_bind_int64(stmt, 2, segment);
+  Sqlite3Statement stmt(m_db, "SELECT content_object FROM File WHERE device_name=? AND segment=?");
+  stmt.bind(1, deviceName.wireEncode(), SQLITE_STATIC);
+  stmt.bind(2, segment);
 
-  BytesPtr ret;
-
-  int res = sqlite3_step(stmt);
-  if (res == SQLITE_ROW) {
-    const unsigned char* buf = reinterpret_cast<const unsigned char*>(sqlite3_column_blob(stmt, 0));
-    int bufBytes = sqlite3_column_bytes(stmt, 0);
-
-    ret = make_shared<Bytes>(buf, buf + bufBytes);
+  if (stmt.step() == SQLITE_ROW) {
+    return make_shared<Data>(stmt.getBlock(0));
   }
-
-  sqlite3_finalize(stmt);
-
-  // update last used time
-  m_lastUsed = time(NULL);
-
-  return ret;
+  else {
+    return nullptr;
+  }
 }
 
-time_t
-ObjectDb::secondsSinceLastUse()
+const time::steady_clock::TimePoint&
+ObjectDb::getLastUsed() const
 {
-  return (time(NULL) - m_lastUsed);
+  return m_lastUsed;
 }
 
-// sqlite3_int64
-// ObjectDb::getNumberOfSegments (const Ndnx::Name &deviceName)
-// {
-//   sqlite3_stmt *stmt;
-//   sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM File WHERE device_name=?", -1, &stmt, 0);
-
-//   bool retval = false;
-//   int res = sqlite3_step (stmt);
-//   if (res == SQLITE_ROW)
-//     {
-//       retval = true;
-//     }
-//   sqlite3_finalize (stmt);
-
-//   return retval;
-// }
-
 void
 ObjectDb::willStartSave()
 {
   sqlite3_exec(m_db, "BEGIN TRANSACTION;", 0, 0, 0);
-  // _LOG_DEBUG ("Open transaction: " << sqlite3_errmsg (m_db));
 }
 
 void
 ObjectDb::didStopSave()
 {
   sqlite3_exec(m_db, "END TRANSACTION;", 0, 0, 0);
-  // _LOG_DEBUG ("Close transaction: " << sqlite3_errmsg (m_db));
 }
+
+} // namespace chronoshare
+} // namespace ndn
diff --git a/src/object-db.hpp b/src/object-db.hpp
index 3e6f9cd..a0391b5 100644
--- a/src/object-db.hpp
+++ b/src/object-db.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2016, Regents of the University of California.
+ * Copyright (c) 2013-2017, Regents of the University of California.
  *
  * This file is part of ChronoShare, a decentralized file sharing application over NDN.
  *
@@ -18,40 +18,54 @@
  * See AUTHORS.md for complete list of ChronoShare authors and contributors.
  */
 
-#ifndef OBJECT_DB_H
-#define OBJECT_DB_H
+#ifndef CHRONOSHARE_SRC_OBJECT_DB_HPP
+#define CHRONOSHARE_SRC_OBJECT_DB_HPP
+
+#include "db-helper.hpp"
+#include "core/chronoshare-common.hpp"
+
+#include <sqlite3.h>
+
+#include <ctime>
+#include <vector>
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/name.hpp>
 
 #include <boost/filesystem.hpp>
-#include <boost/shared_ptr.hpp>
-#include <ccnx-common.h>
-#include <ccnx-name.h>
-#include <ctime>
-#include <sqlite3.h>
-#include <string>
-#include <vector>
+
+namespace ndn {
+namespace chronoshare {
 
 class ObjectDb
 {
 public:
+  class Error : public DbHelper::Error
+  {
+  public:
+    explicit Error(const std::string& what)
+      : DbHelper::Error(what)
+    {
+    }
+  };
+
+public:
   // database will be create in <folder>/<first-pair-of-hash-bytes>/<rest-of-hash>
   ObjectDb(const boost::filesystem::path& folder, const std::string& hash);
+
   ~ObjectDb();
 
   void
-  saveContentObject(const Ccnx::Name& deviceName, sqlite3_int64 segment, const Ccnx::Bytes& data);
+  saveContentObject(const Name& deviceName, sqlite3_int64 segment, const Data& data);
 
-  Ccnx::BytesPtr
-  fetchSegment(const Ccnx::Name& deviceName, sqlite3_int64 segment);
+  shared_ptr<Data>
+  fetchSegment(const Name& deviceName, sqlite3_int64 segment);
 
-  // sqlite3_int64
-  // getNumberOfSegments (const Ndnx::Name &deviceName);
-
-  time_t
-  secondsSinceLastUse();
+  const time::steady_clock::TimePoint&
+  getLastUsed() const;
 
   static bool
-  DoesExist(const boost::filesystem::path& folder, const Ccnx::Name& deviceName,
-            const std::string& hash);
+  doesExist(const boost::filesystem::path& folder, const Name& deviceName, const std::string& hash);
 
 private:
   void
@@ -62,9 +76,10 @@
 
 private:
   sqlite3* m_db;
-  time_t m_lastUsed;
+  time::steady_clock::TimePoint m_lastUsed;
 };
 
-typedef boost::shared_ptr<ObjectDb> ObjectDbPtr;
+} // namespace chronoshare
+} // namespace ndn
 
-#endif // OBJECT_DB_H
+#endif // CHRONOSHARE_SRC_OBJECT_DB_HPP
diff --git a/src/object-manager.cpp b/src/object-manager.cpp
index d900098..4ca0361 100644
--- a/src/object-manager.cpp
+++ b/src/object-manager.cpp
@@ -19,31 +19,30 @@
  */
 
 #include "object-manager.hpp"
-#include "ccnx-common.hpp"
-#include "ccnx-name.hpp"
-#include "ccnx-pco.hpp"
-#include "logging.hpp"
 #include "object-db.hpp"
+#include "core/logging.hpp"
 
 #include <sys/stat.h>
 
 #include <boost/filesystem/fstream.hpp>
 #include <boost/lexical_cast.hpp>
-#include <boost/throw_exception.hpp>
-#include <fstream>
+
+#include <ndn-cxx/util/string-helper.hpp>
+
+namespace ndn {
+namespace chronoshare {
 
 _LOG_INIT(Object.Manager);
 
-using namespace Ndnx;
-using namespace boost;
-using namespace std;
 namespace fs = boost::filesystem;
+using util::Sha256;
 
 const int MAX_FILE_SEGMENT_SIZE = 1024;
 
-ObjectManager::ObjectManager(Ccnx::CcnxWrapperPtr ccnx, const fs::path& folder,
-                             const std::string& appName)
-  : m_ccnx(ccnx)
+ObjectManager::ObjectManager(Face& face, KeyChain& keyChain,
+                             const fs::path& folder, const std::string& appName)
+  : m_face(face)
+  , m_keyChain(keyChain)
   , m_folder(folder / ".chronoshare")
   , m_appName(appName)
 {
@@ -55,11 +54,12 @@
 }
 
 // /<devicename>/<appname>/file/<hash>/<segment>
-boost::tuple<HashPtr /*object-db name*/, size_t /* number of segments*/>
-ObjectManager::localFileToObjects(const fs::path& file, const Ccnx::Name& deviceName)
+std::tuple<ConstBufferPtr /*object-db name*/, size_t /* number of segments*/>
+ObjectManager::localFileToObjects(const fs::path& file, const Name& deviceName)
 {
-  HashPtr fileHash = Hash::FromFileContent(file);
-  ObjectDb fileDb(m_folder, lexical_cast<string>(*fileHash));
+  fs::ifstream input1(file, std::ios::in | std::ios::binary);
+  Sha256 fileHash(input1);
+  ObjectDb fileDb(m_folder, fileHash.toString());
 
   fs::ifstream iff(file, std::ios::in | std::ios::binary);
   sqlite3_int64 segment = 0;
@@ -71,37 +71,54 @@
       break;
     }
 
-    Name name = Name("/")(deviceName)(m_appName)("file")(fileHash->GetHash(),
-                                                         fileHash->GetHashBytes())(segment);
+    Name name = Name("/");
+    name.append(deviceName)
+      .append(m_appName)
+      .append("file")
+      .appendImplicitSha256Digest(fileHash.computeDigest())
+      .appendNumber(segment);
 
-    // cout << *fileHash << endl;
-    // cout << name << endl;
-    //_LOG_DEBUG ("Read " << iff.gcount () << " from " << file << " for segment " << segment);
+    shared_ptr<Data> data = make_shared<Data>();
+    data->setName(name);
+    data->setFreshnessPeriod(time::seconds(60));
+    data->setContent(reinterpret_cast<const uint8_t*>(&buf), iff.gcount());
+    m_keyChain.sign(*data);
+    m_face.put(*data);
 
-    Bytes data = m_ccnx->createContentObject(name, buf, iff.gcount());
-    fileDb.saveContentObject(deviceName, segment, data);
+    fileDb.saveContentObject(deviceName, segment, *data);
 
     segment++;
   }
   if (segment == 0) // handle empty files
   {
-    Name name =
-      Name("/")(m_appName)("file")(fileHash->GetHash(), fileHash->GetHashBytes())(deviceName)(0);
-    Bytes data = m_ccnx->createContentObject(name, 0, 0);
-    fileDb.saveContentObject(deviceName, 0, data);
+    Name name = Name("/");
+    name.append(m_appName)
+      .append("file")
+      .appendImplicitSha256Digest(fileHash.computeDigest())
+      .append(deviceName)
+      .appendNumber(0);
+
+    shared_ptr<Data> data = make_shared<Data>();
+    data->setName(name);
+    data->setFreshnessPeriod(time::seconds(0));
+    data->setContent(0, 0);
+    m_keyChain.sign(*data);
+    m_face.put(*data);
+
+    fileDb.saveContentObject(deviceName, 0, *data);
 
     segment++;
   }
 
-  return make_tuple(fileHash, segment);
+  return std::make_tuple(fileHash.computeDigest(), segment);
 }
 
 bool
-ObjectManager::objectsToLocalFile(/*in*/ const Ccnx::Name& deviceName, /*in*/ const Hash& fileHash,
+ObjectManager::objectsToLocalFile(/*in*/ const Name& deviceName, /*in*/ const Buffer& fileHash,
                                   /*out*/ const fs::path& file)
 {
-  string hashStr = lexical_cast<string>(fileHash);
-  if (!ObjectDb::DoesExist(m_folder, deviceName, hashStr)) {
+  std::string hashStr = toHex(fileHash);
+  if (!ObjectDb::doesExist(m_folder, deviceName, hashStr)) {
     _LOG_ERROR("ObjectDb for [" << m_folder << ", " << deviceName << ", " << hashStr
                                 << "] does not exist or not all segments are available");
     return false;
@@ -115,20 +132,18 @@
   ObjectDb fileDb(m_folder, hashStr);
 
   sqlite3_int64 segment = 0;
-  BytesPtr bytes = fileDb.fetchSegment(deviceName, 0);
-  while (bytes) {
-    ParsedContentObject obj(*bytes);
-    BytesPtr data = obj.contentPtr();
+  auto data = fileDb.fetchSegment(deviceName, 0);
+  while (data != nullptr) {
+    off.write(reinterpret_cast<const char*>(data->getContent().value()), data->getContent().value_size());
 
-    if (data) {
-      off.write(reinterpret_cast<const char*>(head(*data)), data->size());
-    }
-
-    segment++;
-    bytes = fileDb.fetchSegment(deviceName, segment);
+    ++segment;
+    data = fileDb.fetchSegment(deviceName, segment);
   }
 
-  // permission and timestamp should be assigned somewhere else (ObjectManager has no idea about that)
+  // permission and timestamp should be assigned somewhere else(ObjectManager has no idea about that)
 
   return true;
 }
+
+} // namespace chronoshare
+} // namespace ndn
diff --git a/src/object-manager.hpp b/src/object-manager.hpp
index 51a5880..b00c846 100644
--- a/src/object-manager.hpp
+++ b/src/object-manager.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2016, Regents of the University of California.
+ * Copyright (c) 2013-2017, Regents of the University of California.
  *
  * This file is part of ChronoShare, a decentralized file sharing application over NDN.
  *
@@ -18,48 +18,59 @@
  * See AUTHORS.md for complete list of ChronoShare authors and contributors.
  */
 
-#ifndef OBJECT_MANAGER_H
-#define OBJECT_MANAGER_H
+#ifndef CHRONOSHARE_SRC_OBJECT_MANAGER_HPP
+#define CHRONOSHARE_SRC_OBJECT_MANAGER_HPP
+
+#include "core/chronoshare-common.hpp"
 
 #include <boost/filesystem.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <ccnx-wrapper.h>
-#include <hash-helper.h>
-#include <string>
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/util/digest.hpp>
 
 // everything related to managing object files
 
+namespace ndn {
+namespace chronoshare {
+
 class ObjectManager
 {
 public:
-  ObjectManager(Ccnx::CcnxWrapperPtr ccnx, const boost::filesystem::path& folder,
-                const std::string& appName);
-  virtual ~ObjectManager();
+  ObjectManager(Face& face, KeyChain& keyChain,
+                const boost::filesystem::path& folder, const std::string& appName);
+
+  virtual
+  ~ObjectManager();
 
   /**
    * @brief Creates and saves local file in a local database file
    *
    * Format: /<appname>/file/<hash>/<devicename>/<segment>
    */
-  boost::tuple<HashPtr /*object-db name*/, size_t /* number of segments*/>
-  localFileToObjects(const boost::filesystem::path& file, const Ccnx::Name& deviceName);
+  std::tuple<ConstBufferPtr /*object-db name*/, size_t /* number of segments*/>
+  localFileToObjects(const boost::filesystem::path& file, const Name& deviceName);
 
   bool
-  objectsToLocalFile(/*in*/ const Ccnx::Name& deviceName, /*in*/ const Hash& hash,
+  objectsToLocalFile(/*in*/ const Name& deviceName, /*in*/ const Buffer& hash,
                      /*out*/ const boost::filesystem::path& file);
 
 private:
-  Ndnx::NdnxWrapperPtr m_ndnx;
+  Face& m_face;
+  KeyChain& m_keyChain;
   boost::filesystem::path m_folder;
   std::string m_appName;
 };
 
-typedef boost::shared_ptr<ObjectManager> ObjectManagerPtr;
+typedef shared_ptr<ObjectManager> ObjectManagerPtr;
 
-namespace Error {
+namespace error {
 struct ObjectManager : virtual boost::exception, virtual std::exception
 {
 };
-}
+} // namespace error
 
-#endif // OBJECT_MANAGER_H
+} // namespace chronoshare
+} // namespace ndn
+
+#endif // CHRONOSHARE_SRC_OBJECT_MANAGER_HPP
diff --git a/wscript b/wscript
index fe8c036..117e90c 100644
--- a/wscript
+++ b/wscript
@@ -107,6 +107,7 @@
                                   'src/sync-*.cpp',
                                   'src/file-state.cpp',
                                   'src/action-log.cpp',
+                                  'src/object-*.cpp',
                                   ]),
         use='core-objects adhoc NDN_CXX BOOST TINYXML SQLITE3',
         includes="src",