Merge remote-tracking branch 'origin/master'
Conflicts:
wscript
diff --git a/client/client.cc b/client/client.cc
index 4d20e98..4f61d52 100644
--- a/client/client.cc
+++ b/client/client.cc
@@ -31,6 +31,7 @@
using namespace std;
using namespace boost;
using namespace ChronoshareClient;
+namespace fs = boost::filesystem;
void
usage ()
@@ -88,19 +89,20 @@
usage ();
}
- struct stat fileStats;
- int ok = stat (argv[2], &fileStats);
- if (ok == 0)
+ fs::path file (argv[2]);
+ fs::file_status fileStatus = fs::status (file);
+ if (is_regular_file (fileStatus))
{
// Alex: the following code is platform specific :(
- HashPtr fileHash = Hash::FromFileContent (argv[2]);
+ HashPtr fileHash = Hash::FromFileContent (file);
- notify->updateFile (argv[2],
+ notify->updateFile (file.generic_string (),
make_pair(reinterpret_cast<const ::Ice::Byte*> (fileHash->GetHash ()),
reinterpret_cast<const ::Ice::Byte*> (fileHash->GetHash ()) +
fileHash->GetHashBytes ()),
- fileStats.st_atime, fileStats.st_mtime, fileStats.st_ctime,
- fileStats.st_mode);
+ fs::last_write_time (file),
+ // fileStats.st_atime, fileStats.st_mtime, fileStats.st_ctime,
+ fileStatus.permissions ());
}
else
{
@@ -124,8 +126,10 @@
usage ();
}
+ fs::path srcFile (argv[2]);
+ fs::path dstFile (argv[3]);
- notify->moveFile (argv[2], argv[3]);
+ notify->moveFile (srcFile.generic_string (), dstFile.generic_string ());
}
else
{
diff --git a/daemon/notify-i.cc b/daemon/notify-i.cc
index 0994aa3..0a3880d 100644
--- a/daemon/notify-i.cc
+++ b/daemon/notify-i.cc
@@ -33,9 +33,7 @@
void
NotifyI::updateFile (const ::std::string &filename,
const ::std::pair<const Ice::Byte*, const Ice::Byte*> &hashRaw,
- ::Ice::Long atime,
- ::Ice::Long mtime,
- ::Ice::Long ctime,
+ ::Ice::Long wtime,
::Ice::Int mode,
const ::Ice::Current&)
{
@@ -44,7 +42,7 @@
cout << "updateFile " << filename << " with hash " << hash << endl;
try
{
- m_actionLog->AddActionUpdate (filename, hash, atime, mtime, ctime, mode);
+ m_actionLog->AddActionUpdate (filename, hash, wtime, mode);
m_actionLog->RememberStateInStateLog ();
}
diff --git a/daemon/notify-i.h b/daemon/notify-i.h
index 9fd7044..426e2a9 100644
--- a/daemon/notify-i.h
+++ b/daemon/notify-i.h
@@ -33,9 +33,7 @@
virtual void
updateFile (const ::std::string &filename,
const ::std::pair<const Ice::Byte*, const Ice::Byte*> &hash,
- ::Ice::Long atime,
- ::Ice::Long mtime,
- ::Ice::Long ctime,
+ ::Ice::Long wtime,
::Ice::Int mode,
const ::Ice::Current& = ::Ice::Current());
diff --git a/include/ccnx-common.h b/include/ccnx-common.h
index 06e7700..41d7814 100644
--- a/include/ccnx-common.h
+++ b/include/ccnx-common.h
@@ -1,3 +1,24 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
#ifndef CCNX_COMMON_H
#define CCNX_COMMON_H
@@ -17,18 +38,53 @@
#include <sstream>
#include <map>
#include <utility>
+#include <string.h>
using namespace std;
namespace Ccnx {
typedef vector<unsigned char> Bytes;
typedef vector<string>Comps;
-// --- Bytes operations start ---
-void
-readRaw(Bytes &bytes, const unsigned char *src, size_t len);
+typedef boost::shared_ptr<Bytes> BytesPtr;
+inline
const unsigned char *
-head(const Bytes &bytes);
+head(const Bytes &bytes)
+{
+ return &bytes[0];
+}
+
+inline
+unsigned char *
+head (Bytes &bytes)
+{
+ return &bytes[0];
+}
+
+// --- Bytes operations start ---
+inline void
+readRaw(Bytes &bytes, const unsigned char *src, size_t len)
+{
+ if (len > 0)
+ {
+ bytes.resize(len);
+ memcpy (head (bytes), src, len);
+ }
+}
+
+inline BytesPtr
+readRawPtr (const unsigned char *src, size_t len)
+{
+ if (len > 0)
+ {
+ BytesPtr ret (new Bytes (len));
+ memcpy (head (*ret), src, len);
+
+ return ret;
+ }
+ else
+ return BytesPtr ();
+}
// --- Bytes operations end ---
diff --git a/include/ccnx-pco.h b/include/ccnx-pco.h
index 7956dad..0c52c7a 100644
--- a/include/ccnx-pco.h
+++ b/include/ccnx-pco.h
@@ -22,6 +22,9 @@
Bytes
content() const;
+ BytesPtr
+ contentPtr() const;
+
Name
name() const;
diff --git a/include/ccnx-wrapper.h b/include/ccnx-wrapper.h
index 667d4be..baa22b1 100644
--- a/include/ccnx-wrapper.h
+++ b/include/ccnx-wrapper.h
@@ -50,7 +50,7 @@
getLocalPrefix ();
Bytes
- createContentObject(const Name &name, const unsigned char *buf, size_t len, int freshness = 2147/* max value for ccnx*/);
+ createContentObject(const Name &name, const void *buf, size_t len, int freshness = 2147/* max value for ccnx*/);
int
putToCcnd (const Bytes &contentObject);
diff --git a/src/action-item.proto b/src/action-item.proto
index 0144a22..3218ef8 100644
--- a/src/action-item.proto
+++ b/src/action-item.proto
@@ -12,9 +12,9 @@
required uint32 timestamp = 6;
optional bytes file_hash = 7;
- optional uint32 atime = 8;
+ // optional uint32 atime = 8;
optional uint32 mtime = 9;
- optional uint32 ctime = 10;
+ // optional uint32 ctime = 10;
optional uint32 mode = 11;
optional bytes parent_device_name = 12;
diff --git a/src/action-log.cc b/src/action-log.cc
index ff8e257..cc0d945 100644
--- a/src/action-log.cc
+++ b/src/action-log.cc
@@ -26,7 +26,8 @@
using namespace std;
using namespace Ccnx;
-ActionLog::ActionLog (Ccnx::CcnxWrapperPtr ccnx, const std::string &path, const std::string &localName, const std::string &sharedFolder)
+ActionLog::ActionLog (Ccnx::CcnxWrapperPtr ccnx, const boost::filesystem::path &path,
+ const std::string &localName, const std::string &sharedFolder)
: SyncLog (path, localName)
, m_ccnx (ccnx)
, m_sharedFolderName (sharedFolder)
@@ -83,7 +84,7 @@
void
ActionLog::AddActionUpdate (const std::string &filename,
const Hash &hash,
- time_t atime, time_t mtime, time_t ctime,
+ time_t wtime,
int mode)
{
sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
@@ -102,9 +103,11 @@
int res = sqlite3_prepare_v2 (m_db, "INSERT INTO ActionLog "
"(device_id, seq_no, action, filename, version, action_timestamp, "
"file_hash, file_atime, file_mtime, file_ctime, file_chmod, "
- "parent_device_id, parent_seq_no) "
+ "parent_device_id, parent_seq_no, "
+ "action_name, action_content_object) "
"VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
" ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,"
+ " ?, ?, "
" ?, ?);", -1, &stmt, 0);
// cout << "INSERT INTO ActionLog "
@@ -133,9 +136,9 @@
sqlite3_bind_blob (stmt, 7, hash.GetHash (), hash.GetHashBytes (), SQLITE_TRANSIENT);
- sqlite3_bind_int64 (stmt, 8, atime);
- sqlite3_bind_int64 (stmt, 9, mtime);
- sqlite3_bind_int64 (stmt, 10, ctime);
+ // sqlite3_bind_int64 (stmt, 8, atime); // NULL
+ sqlite3_bind_int64 (stmt, 9, wtime);
+ // sqlite3_bind_int64 (stmt, 10, ctime); // NULL
sqlite3_bind_int (stmt, 11, mode);
if (parent_device_id > 0 && parent_seq_no > 0)
@@ -149,8 +152,6 @@
sqlite3_bind_null (stmt, 13);
}
- sqlite3_step (stmt);
-
// missing part: creating ContentObject for the action !!!
ActionItem item;
@@ -159,9 +160,9 @@
item.set_version (version);
item.set_timestamp (action_time);
item.set_file_hash (hash.GetHash (), hash.GetHashBytes ());
- item.set_atime (atime);
- item.set_mtime (mtime);
- item.set_ctime (ctime);
+ // item.set_atime (atime);
+ item.set_mtime (wtime);
+ // item.set_ctime (ctime);
item.set_mode (mode);
if (parent_device_id > 0 && parent_seq_no > 0)
@@ -174,7 +175,23 @@
}
// assign name to the action, serialize action, and create content object
+
+ string item_msg;
+ item.SerializeToString (&item_msg);
+ Name actionName (m_localName);
+ actionName
+ .appendComp ("action")
+ .appendComp (m_sharedFolderName)
+ .appendComp (seq_no);
+ Bytes actionData = m_ccnx->createContentObject (actionName, item_msg.c_str (), item_msg.size ());
+ CcnxCharbufPtr namePtr = actionName.toCcnxCharbuf ();
+
+ sqlite3_bind_blob (stmt, 14, namePtr->buf (), namePtr->length (), SQLITE_TRANSIENT);
+ sqlite3_bind_blob (stmt, 15, &actionData[0], actionData.size (), SQLITE_TRANSIENT);
+
+ sqlite3_step (stmt);
+
sqlite3_finalize (stmt);
sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
@@ -212,8 +229,10 @@
sqlite3_stmt *stmt;
sqlite3_prepare_v2 (m_db, "INSERT INTO ActionLog "
"(device_id, seq_no, action, filename, version, action_timestamp, "
- "parent_device_id, parent_seq_no) "
+ "parent_device_id, parent_seq_no, "
+ "action_name, action_content_object) "
"VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
+ " ?, ?,"
" ?, ?)", -1, &stmt, 0);
sqlite3_bind_int64 (stmt, 1, m_localDeviceId);
@@ -241,16 +260,15 @@
actionName
.appendComp ("action")
.appendComp (m_sharedFolderName)
- .appendComp (reinterpret_cast<void*> (seq_no), sizeof (seq_no));
+ .appendComp (seq_no);
- // Bytes actionData = m_ccnx->createContentObject (?name, item_msg.c_str (), item_msg.size ());
-
+ Bytes actionData = m_ccnx->createContentObject (actionName, item_msg.c_str (), item_msg.size ());
+ CcnxCharbufPtr namePtr = actionName.toCcnxCharbuf ();
- // sqlite3_bind_blob (stmt, 10, item_msg.c_str (), item_msg.size (), SQLITE_TRANSIENT);
+ sqlite3_bind_blob (stmt, 9, namePtr->buf (), namePtr->length (), SQLITE_TRANSIENT);
+ sqlite3_bind_blob (stmt, 10, &actionData[0], actionData.size (), SQLITE_TRANSIENT);
sqlite3_step (stmt);
-
-
// cout << Ccnx::Name (reinterpret_cast<const unsigned char *> (parent_device_name.c_str ()),
// parent_device_name.size ()) << endl;
diff --git a/src/action-log.h b/src/action-log.h
index 323f6a3..7d778d8 100644
--- a/src/action-log.h
+++ b/src/action-log.h
@@ -32,12 +32,13 @@
class ActionLog : public SyncLog
{
public:
- ActionLog (Ccnx::CcnxWrapperPtr ccnx, const std::string &path, const std::string &localName, const std::string &sharedFolder);
+ ActionLog (Ccnx::CcnxWrapperPtr ccnx, const boost::filesystem::path &path,
+ const std::string &localName, const std::string &sharedFolder);
void
AddActionUpdate (const std::string &filename,
const Hash &hash,
- time_t atime, time_t mtime, time_t ctime,
+ time_t wtime,
int mode);
void
diff --git a/src/ccnx-name.cpp b/src/ccnx-name.cpp
index 28761dd..a59cf8a 100644
--- a/src/ccnx-name.cpp
+++ b/src/ccnx-name.cpp
@@ -254,7 +254,7 @@
Name::getPartialName(int start, int n) const
{
int size = m_comps.size();
- if (start < 0 || start >= size || n > 0 && start + n > size)
+ if (start < 0 || start >= size || (n > 0 && start + n > size))
{
stringstream ss(stringstream::out);
ss << "getPartialName() parameter out of range! ";
diff --git a/src/ccnx-pco.cpp b/src/ccnx-pco.cpp
index af10c7a..8c2fd3f 100644
--- a/src/ccnx-pco.cpp
+++ b/src/ccnx-pco.cpp
@@ -54,6 +54,20 @@
return bytes;
}
+BytesPtr
+ParsedContentObject::contentPtr() const
+{
+ const unsigned char *content;
+ size_t len;
+ int res = ccn_content_get_value(head(m_bytes), m_pco.offset[CCN_PCO_E], &m_pco, &content, &len);
+ if (res < 0)
+ {
+ boost::throw_exception(MisformedContentObjectException());
+ }
+
+ return readRawPtr (content, len);
+}
+
Name
ParsedContentObject::name() const
{
diff --git a/src/ccnx-tunnel.cpp b/src/ccnx-tunnel.cpp
index ecef346..f428481 100644
--- a/src/ccnx-tunnel.cpp
+++ b/src/ccnx-tunnel.cpp
@@ -8,7 +8,7 @@
: CcnxWrapper()
, m_localPrefix("/")
{
- //refreshLocalPrefix();
+ refreshLocalPrefix();
}
CcnxTunnel::~CcnxTunnel()
@@ -34,6 +34,8 @@
Closure *cp = new TunnelClosure(closure, this, interest);
CcnxWrapper::sendInterest(tunneledInterest, cp, selectors);
delete cp;
+
+ return 0;
}
void
diff --git a/src/ccnx-wrapper.cpp b/src/ccnx-wrapper.cpp
index 887f8ae..3f82889 100644
--- a/src/ccnx-wrapper.cpp
+++ b/src/ccnx-wrapper.cpp
@@ -16,22 +16,6 @@
namespace Ccnx {
-void
-readRaw(Bytes &bytes, const unsigned char *src, size_t len)
-{
- if (len > 0)
- {
- bytes.resize(len);
- memcpy(&bytes[0], src, len);
- }
-}
-
-const unsigned char *
-head(const Bytes &bytes)
-{
- return &bytes[0];
-}
-
CcnxWrapper::CcnxWrapper()
: m_handle (0)
, m_running (true)
@@ -164,7 +148,7 @@
}
Bytes
-CcnxWrapper::createContentObject(const Name &name, const unsigned char *buf, size_t len, int freshness)
+CcnxWrapper::createContentObject(const Name &name, const void *buf, size_t len, int freshness)
{
CcnxCharbufPtr ptr = name.toCcnxCharbuf();
ccn_charbuf *pname = ptr->getBuf();
@@ -212,7 +196,7 @@
int
CcnxWrapper::publishData (const Name &name, const Bytes &content, int freshness)
{
- publishData(name, head(content), content.size(), freshness);
+ return publishData(name, head(content), content.size(), freshness);
}
@@ -348,6 +332,8 @@
}
m_registeredInterests.insert(pair<Name, InterestCallback>(prefix, interestCallback));
+
+ return ret;
}
void
diff --git a/src/chronoshare-client.ice b/src/chronoshare-client.ice
index e3bf8e2..c2e056f 100644
--- a/src/chronoshare-client.ice
+++ b/src/chronoshare-client.ice
@@ -25,7 +25,7 @@
interface Notify
{
- void updateFile (string filename, ["cpp:array"] HashBytes fileHash, long atime, long mtime, long ctime, int mode);
+ void updateFile (string filename, ["cpp:array"] HashBytes fileHash, long wtime, int mode);
void moveFile (string origFilename, string newFilename);
diff --git a/src/db-helper.cc b/src/db-helper.cc
index 217c3ee..c5455e8 100644
--- a/src/db-helper.cc
+++ b/src/db-helper.cc
@@ -26,6 +26,7 @@
#include <boost/throw_exception.hpp>
using namespace boost;
+namespace fs = boost::filesystem;
const std::string INIT_DATABASE = "\
PRAGMA foreign_keys = ON; \n\
@@ -162,13 +163,16 @@
CREATE INDEX FileState_device_id_seq_no ON FileState (device_id, seq_no); \n\
";
-DbHelper::DbHelper (const std::string &path)
+DbHelper::DbHelper (const fs::path &path)
{
- int res = sqlite3_open((path+"chronoshare.db").c_str (), &m_db);
+ fs::path chronoshareDirectory = path / ".chronoshare";
+ fs::create_directories (chronoshareDirectory);
+
+ int res = sqlite3_open((chronoshareDirectory / "state.db").c_str (), &m_db);
if (res != SQLITE_OK)
{
BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Cannot open/create dabatabase: [" + path + "chronoshare.db" + "]"));
+ << errmsg_info_str ("Cannot open/create dabatabase: [" + (chronoshareDirectory / "state.db").string () + "]"));
}
res = sqlite3_create_function (m_db, "hash", 2, SQLITE_ANY, 0, 0,
diff --git a/src/db-helper.h b/src/db-helper.h
index 51970dd..a32df64 100644
--- a/src/db-helper.h
+++ b/src/db-helper.h
@@ -28,13 +28,14 @@
#include <boost/exception/all.hpp>
#include <string>
#include "hash-helper.h"
+#include <boost/filesystem.hpp>
typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
class DbHelper
{
public:
- DbHelper (const std::string &path);
+ DbHelper (const boost::filesystem::path &path);
virtual ~DbHelper ();
private:
diff --git a/src/hash-helper.cc b/src/hash-helper.cc
index 33c0e77..dbb70a3 100644
--- a/src/hash-helper.cc
+++ b/src/hash-helper.cc
@@ -33,11 +33,12 @@
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/archive/iterators/dataflow_exception.hpp>
+#include <boost/filesystem/fstream.hpp>
using namespace boost;
using namespace boost::archive::iterators;
using namespace std;
-
+namespace fs = boost::filesystem;
template<class CharType>
struct hex_from_4_bit
@@ -130,7 +131,7 @@
}
HashPtr
-Hash::FromFileContent (const std::string &filename)
+Hash::FromFileContent (const fs::path &filename)
{
HashPtr retval = make_shared<Hash> (reinterpret_cast<void*> (0), 0);
retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
@@ -138,7 +139,7 @@
EVP_MD_CTX *hash_context = EVP_MD_CTX_create ();
EVP_DigestInit_ex (hash_context, HASH_FUNCTION (), 0);
- ifstream iff (filename.c_str (), std::ios::in | std::ios::binary);
+ fs::ifstream iff (filename, std::ios::in | std::ios::binary);
while (iff.good ())
{
char buf[1024];
diff --git a/src/hash-helper.h b/src/hash-helper.h
index ea12f30..d4f750d 100644
--- a/src/hash-helper.h
+++ b/src/hash-helper.h
@@ -26,6 +26,7 @@
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/exception/all.hpp>
+#include <boost/filesystem.hpp>
// Other options: VP_md2, EVP_md5, EVP_sha, EVP_sha1, EVP_sha256, EVP_dss, EVP_dss1, EVP_mdc2, EVP_ripemd160
#define HASH_FUNCTION EVP_sha256
@@ -50,7 +51,7 @@
FromString (const std::string &hashInTextEncoding);
static HashPtr
- FromFileContent (const std::string &hashInTextEncoding);
+ FromFileContent (const boost::filesystem::path &fileName);
~Hash ()
{
diff --git a/src/object-db-file.cpp b/src/object-db-file.cpp
deleted file mode 100644
index 26f8fb3..0000000
--- a/src/object-db-file.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-#include "object-db-file.h"
-#include <assert.h>
-
-char *
-head(const Bytes &bytes)
-{
- return (char *)&bytes[0];
-}
-
-void
-writeBytes(ostream &out, const Bytes &bytes)
-{
- int size = bytes.size();
- writeInt(out, size);
- out.write(head(bytes), size);
-}
-
-void
-readBytes(istream &in, Bytes &bytes)
-{
- int size;
- readInt(in, size);
- bytes.reserve(size);
- in.read(head(bytes), size);
-}
-
-ObjectDBFile::ObjectDBFile(const string &filename)
- : m_size(0)
- , m_cap(0)
- , m_index(0)
- , m_initialized(false)
- , m_filename(filename)
- // This ensures file with filename exists (assuming having write permission)
- // This is needed as file_lock only works with existing file
- , m_ostream(m_filename.c_str(), ios_base::binary | ios_base::app)
- , m_istream(m_filename.c_str(), ios_base::binary | ios_base::binary)
- , m_filelock(m_filename.c_str())
-{
- int magic;
- ReadLock(m_filelock);
- readInt(m_istream, magic);
- if (magic == MAGIC_NUM)
- {
- m_initialized = true;
- readInt(m_istream, m_cap);
- readInt(m_istream, m_size);
- m_istream.seekg( (3 + m_cap) * sizeof(int), ios::beg);
- }
-}
-
-ObjectDBFile::~ObjectDBFile()
-{
- m_istream.close();
- m_ostream.close();
-}
-
-void
-ObjectDBFile::init(int capacity)
-{
- WriteLock(*m_filelock);
- if (m_initialized)
- {
- throwException("Trying to init already initialized ObjectDBFile object" + m_filename);
- }
-
- m_cap = capacity;
- m_size = 0;
-
- int magic = MAGIC_NUM;
- writeInt(m_ostream, magic);
- writeInt(m_ostream, m_cap);
- writeInt(m_ostream, m_size);
- m_initialized = true;
-
- int count = m_cap;
- int offset = 0;
- while (count-- > 0)
- {
- writeInt(m_ostream, offset);
- }
-
- // prepare read pos
- m_istream.seekg(m_ostream.tellp(), ios::beg);
-
- // DEBUG
- assert(m_ostream.tellp() == ((3 + m_cap) * sizeof(int)));
-
-}
-
-// Append is not super efficient as it needs to seek and update the pos for the
-// Content object. However, in our app, it is the case the these objects are wrote
-// once and read multiple times, so it's not a big problem.
-void
-ObjectDBFile::append(const Bytes &co)
-{
- WriteLock(m_filelock);
- checkInit("Trying to append to un-initialized ObjectDBFile: " + m_filename);
-
- if (m_size >= m_cap)
- {
- throwException("Exceed Maximum capacity: " + boost::lexical_cast<string>(m_cap));
- }
-
- // pos for this CO
- int coPos = m_ostream.tellp();
- // index field for this CO
- int indexPos = (3 + m_size) * sizeof(int);
-
- m_size++;
-
- // Update size (is it necessary?) We'll do it for now anyway
- m_ostream.seekp( 2 * sizeof(int), ios::beg);
- writeInt(m_ostream, m_size);
-
- // Write the pos for the CO
- m_ostream.seekp(indexPos, ios::beg);
- writeInt(m_ostream, coPos);
-
- // write the content object
- m_ostream.seekp(coPos, ios::beg);
- writeBytes(m_ostream, co);
-
- // By the end, the write pos is at the end of the file
-}
-
-// forget about caching for now; but ideally, we should cache the next few COs in memory
-// and the request for COs tends to be sequential
-Bytes
-ObjectDBFile::next()
-{
- // Scoped shared lock for cache
- {
- SLock(m_cacheLock);
- // no need to read file if found in cache
- if (m_dummyCache.find(m_index) != m_dummyCache.end())
- {
- int index = m_index;
- m_index++;
- return m_dummyCache[index];
- }
- }
-
- ReadLock(m_filelock);
-
- // m_index not found in cache
- Bytes co;
- if (m_index >= m_size)
- {
- // at the end of file, return empty
- return co;
- }
-
- readBytes(m_istream, co);
- m_index++;
-
- // fill dummy cache with the next CACHE_SIZE COs
- fillDummyCache();
-
- return co;
-}
-
-void
-ObjectDBFile::fillDummyCache()
-{
- ULock(m_cacheLock);
- m_dummyCache.clear();
- int stop = (m_index + CACHE_SIZE < m_size) ? m_index + CACHE_SIZE : m_size;
- // the m_index should not change
- int index = m_index;
- while (index < stop)
- {
- Bytes co;
- readBytes(m_istream, co);
- m_dummyCache.insert(make_pair(index, co));
- index++;
- }
-}
-
-int
-ObjectDBFile::size() const
-{
- return m_size;
-}
-
-void
-ObjectDBFile::updateSize()
-{
- int pos = m_istream.tellg();
- m_istream.seekg(2 * sizeof(int), ios::beg);
- readInt(m_istream, m_size);
- // recover the original pos
- m_istream.seekg(pos, ios::beg);
-}
-
-int
-ObjectDBFile::fSize()
-{
- ReadLock(m_filelock);
- updateSize();
- return m_size;
-}
-
-int
-ObjectDBFile::index()
-{
- ReadLock(m_filelock);
- return m_index;
-}
-
-bool
-ObjectDBFile::seek(int index)
-{
- ReadLock(m_filelock);
- updateSize();
- if (m_size <= index)
- {
- return false;
- }
- m_index = index;
- m_istream.seekg( (3 + m_index) * sizeof(int), ios::beg);
- int pos;
- readInt(m_istream, pos);
- m_istream.seekg(pos, ios::beg);
- return true;
-}
-
-void
-ObjectDBFile::rewind()
-{
- ReadLock(m_filelock);
- m_index = 0;
- // point to the start of the CO fields
- m_istream.seekg( (3 + m_cap) * sizeof(int), ios::beg);
-}
-
-void
-ObjectDBFile::checkInit(const string &msg)
-{
- if (!m_initialized)
- {
- throwException(msg);
- }
-}
diff --git a/src/object-db-file.h b/src/object-db-file.h
deleted file mode 100644
index 1eb1ef8..0000000
--- a/src/object-db-file.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifndef OBJECT_DB_FILE_H
-#define OBJECT_DB_FILE_H
-
-#include "object-db.h"
-#include <stdio.h>
-#include <fstream>
-#include <sstream>
-#include <deque>
-#include <boost/thread/locks.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/thread/shared_mutex.hpp>
-#include <boost/interprocess/sync/file_lock.hpp>
-#include <boost/interprocess/sync/sharable_lock.hpp>
-#include <boost/interprocess/sync/scoped_lock.hpp>
-
-#define _OVERRIDE
-#ifdef __GNUC__
-#if __GNUC_MAJOR >= 4 && __GNUC_MINOR__ >= 7
- #undef _OVERRIDE
- #define _OVERRIDE override
-#endif // __GNUC__ version
-#endif // __GNUC__
-
-using namespace std;
-
-// This is a file based ObjectDB implementation
-// The assumption is, the Content Objects will be stored sequentially
-
-// To provide random access, we will have a table of "address" for each
-// ContentObject at the beginning of the file.
-// This also requires another assumption, that is the number of COs must
-// be know a priori. This requirement is reasonable for our dropbox-like
-// System, as the file we publish is static file and we can easily know
-// the number of COs before we store them into ObjectDB.
-
-/* How file looks like:
- * |MAGIC_NUM|capacity|size|pos for each CO ...|1st CO|2nd CO| ... |
- */
-
-class ObjectDBFile
-{
-public:
- typedef boost::interprocess::file_lock Filelock;
- typedef boost::interprocess::scoped_lock<Filelock> WriteLock;
- typedef boost::interprocess::sharable_lock<Filelock> ReadLock;
- typedef boost::shared_mutex Mutex;
- typedef boost::shared_lock<Mutex> SLock;
- typedef boost::unique_lock<Mutex> ULock;
-
- ObjectDBFile(const string &filename);
- virtual ~ObjectDBFile();
-
- // reserve the "address" table for n COs; must reserve before
- // write anything (unless reserved quota has not be consumed yet)
- void
- init(int capacity);
-
- bool
- initialized() const { return m_initialized; }
-
- // assume sequential
- virtual void
- append(const Bytes &co) _OVERRIDE;
-
- // get next CO
- virtual Bytes
- next() _OVERRIDE;
-
- // size in terms of number of COs
- // This is the lazy form of size, i.e. it returns the size cached in this object
- // but that may not necessarily equal to the actual size kept in file
- // This is enough if the caller knows for sure that no other thread is changing the
- // file or the caller does not care about the new size.
- virtual int
- size() const _OVERRIDE;
-
- // this returns the actual size (also update the size cache in this object), but it is more costly, and requires file IO
- int
- fSize();
-
- // the index of the CO to be read
- int
- index();
-
- // set the pos to be the desired CO
- // return true if success
- bool
- seek(int index);
-
- // reset pos to be zero
- void
- rewind();
-
-protected:
- // read or write lock should have been grabbed already before the call
- void
- checkInit(const string &msg);
-
- // read lock should have been grabbed already before the call
- void
- updateSize();
-
- // read lock should have been grabbed already before the call
- void
- fillDummyCache();
-
- #define MAGIC_NUM 0xAAAAAAAA
-
-protected:
- string m_filename;
- ifstream m_istream;
- ofstream m_ostream;
- Filelock m_filelock;
- bool m_initialized;
- // capacity in terms of number of COs
- int m_cap;
- int m_size;
- // the index (or seq) of the CO to be read
- int m_index;
-
- // A dummy Cache that holds the next 10 (or all remaining if less than 10)
- // COs after a next() operation
- // If needed and time allows, we can have more complex cache
- #define CACHE_SIZE 10
- map<int, Bytes> m_dummyCache;
- Mutex m_cacheMutex;
-};
-
-void inline
-writeInt(ostream &out, const int &x)
-{
- out.write((const char *)&x, sizeof(int));
-}
-
-void inline
-readInt(istream &in, int &x)
-{
- in.read((char *)&x, sizeof(int));
-}
-
-// write size and then the actual bytes
-// operator << overloading is not used to avoid confusion
-void
-writeBytes(ostream &out, const Bytes &bytes);
-
-// read size and then the actual bytes
-void
-readBytes(istream &in, Bytes &bytes);
-
-char *
-head(const Bytes &bytes);
-
-#endif
diff --git a/src/object-db.cc b/src/object-db.cc
new file mode 100644
index 0000000..0d1a2a6
--- /dev/null
+++ b/src/object-db.cc
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "object-db.h"
+#include <iostream>
+#include <boost/make_shared.hpp>
+#include "db-helper.h"
+#include <sys/stat.h>
+
+using namespace std;
+using namespace Ccnx;
+using namespace boost;
+namespace fs = boost::filesystem;
+
+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\
+";
+
+ObjectDb::ObjectDb (const fs::path &folder, const std::string &hash)
+{
+ fs::path actualFolder = folder / "objects" / hash.substr (0, 2);
+ fs::create_directories (actualFolder);
+
+ 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 () + "]"));
+ }
+
+ // 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);
+ if (res != SQLITE_OK && errmsg != 0)
+ {
+ // std::cerr << "DEBUG: " << errmsg << std::endl;
+ sqlite3_free (errmsg);
+ }
+}
+
+bool
+ObjectDb::DoesExist (const boost::filesystem::path &folder, const Ccnx::Name &deviceName, const std::string &hash)
+{
+ fs::path actualFolder = folder / "objects" / hash.substr (0, 2);
+ bool retval = false;
+
+ sqlite3 *db;
+ int res = sqlite3_open((actualFolder / hash.substr (2, hash.size () - 2)).c_str (), &db);
+ if (res == SQLITE_OK)
+ {
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2 (db, "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);
+
+ int res = sqlite3_step (stmt);
+ if (res == SQLITE_ROW)
+ {
+ int countAll = sqlite3_column_int (stmt, 0);
+ int countNonNull = sqlite3_column_int (stmt, 1);
+
+ cout << countAll << ", " << countNonNull << endl;
+
+ if (countAll > 0 && countAll==countNonNull)
+ {
+ cout << "2" << endl;
+ retval = true;
+ }
+ }
+
+ sqlite3_finalize (stmt);
+ }
+
+ sqlite3_close (db);
+ return retval;
+}
+
+
+ObjectDb::~ObjectDb ()
+{
+ 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)
+{
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2 (m_db, "INSERT INTO File "
+ "(device_name, segment, content_object) "
+ "VALUES (?, ?, ?)", -1, &stmt, 0);
+
+ cout << deviceName << endl;
+
+ CcnxCharbufPtr buf = deviceName.toCcnxCharbuf ();
+ sqlite3_bind_blob (stmt, 1, buf->buf (), buf->length (), SQLITE_TRANSIENT);
+ sqlite3_bind_int64 (stmt, 2, segment);
+ sqlite3_bind_blob (stmt, 3, &data[0], data.size (), SQLITE_TRANSIENT);
+
+ sqlite3_step (stmt);
+ sqlite3_finalize (stmt);
+}
+
+Ccnx::BytesPtr
+ObjectDb::fetchSegment (const Ccnx::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);
+
+ CcnxCharbufPtr buf = deviceName.toCcnxCharbuf ();
+ sqlite3_bind_blob (stmt, 1, buf->buf (), buf->length (), SQLITE_TRANSIENT);
+ sqlite3_bind_int64 (stmt, 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);
+ }
+
+ sqlite3_finalize (stmt);
+
+ return ret;
+}
+
+
+// sqlite3_int64
+// ObjectDb::getNumberOfSegments (const Ccnx::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;
+// }
diff --git a/src/object-db.h b/src/object-db.h
index 8c31418..9ecd753 100644
--- a/src/object-db.h
+++ b/src/object-db.h
@@ -1,42 +1,54 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
#ifndef OBJECT_DB_H
#define OBJECT_DB_H
-#include <boost/exception/all.hpp>
-#include <vector>
+#include <string>
+#include <sqlite3.h>
+#include <ccnx-common.h>
+#include <ccnx-name.h>
+#include <boost/filesystem.hpp>
-using namespace std;
-
-struct ObjectDBException : virtual boost::exception, virtual exception { };
-typedef boost::error_info<struct tag_errmsg, std::string> error_info_str;
-
-inline void throwException(const string &msg) { boost::throw_exception(ObjectDBException() << error_info_str(msg)); }
-
-typedef unsigned char Byte;
-typedef vector<Byte> Bytes;
-
-// OK. This name is a bit miss-leading, but this ObjectDB is really some storage
-// that stores the Ccnx ContentObjects of a file. So unlike a normal database,
-// this DB is per file.
-
-// The assumption is, the ContentObjects will be write to ObjectDB sequentially
-// This guarantees that when read, the Nth ContentObject read has the sequence number N as the last component of its name
-class ObjectDB
+class ObjectDb
{
public:
- virtual ~ObjectDB(){}
+ // 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 ();
- // assume sequential
- virtual void
- append(const Bytes &co) = 0;
+ void
+ saveContentObject (const Ccnx::Name &deviceName, sqlite3_int64 segment, const Ccnx::Bytes &data);
- // get next CO
- virtual Bytes
- next() = 0;
+ Ccnx::BytesPtr
+ fetchSegment (const Ccnx::Name &deviceName, sqlite3_int64 segment);
- // size in terms of number of COs
- virtual int
- size() = 0;
+ // sqlite3_int64
+ // getNumberOfSegments (const Ccnx::Name &deviceName);
+ static bool
+ DoesExist (const boost::filesystem::path &folder, const Ccnx::Name &deviceName, const std::string &hash);
+
+private:
+ sqlite3 *m_db;
};
-#endif
+#endif // OBJECT_DB_H
diff --git a/src/object-manager.cc b/src/object-manager.cc
new file mode 100644
index 0000000..7f66b2a
--- /dev/null
+++ b/src/object-manager.cc
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "object-manager.h"
+#include "ccnx-name.h"
+#include "ccnx-common.h"
+#include "ccnx-pco.h"
+#include "object-db.h"
+
+#include <sys/stat.h>
+
+#include <fstream>
+#include <boost/lexical_cast.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+using namespace Ccnx;
+using namespace boost;
+using namespace std;
+namespace fs = boost::filesystem;
+
+const int MAX_FILE_SEGMENT_SIZE = 1024;
+
+ObjectManager::ObjectManager (Ccnx::CcnxWrapperPtr ccnx, const fs::path &folder)
+ : m_ccnx (ccnx)
+ , m_folder (folder / ".chronoshare")
+{
+ fs::create_directories (m_folder);
+}
+
+ObjectManager::~ObjectManager ()
+{
+}
+
+HashPtr
+ObjectManager::localFileToObjects (const fs::path &file, const Ccnx::Name &deviceName)
+{
+ HashPtr fileHash = Hash::FromFileContent (file);
+ ObjectDb fileDb (m_folder, lexical_cast<string> (*fileHash));
+
+ fs::ifstream iff (file, std::ios::in | std::ios::binary);
+ sqlite3_int64 segment = 0;
+ while (iff.good ())
+ {
+ char buf[MAX_FILE_SEGMENT_SIZE];
+ iff.read (buf, MAX_FILE_SEGMENT_SIZE);
+
+ Name name (deviceName);
+ name
+ .appendComp ("file")
+ .appendComp (fileHash->GetHash (), fileHash->GetHashBytes ())
+ .appendComp (segment);
+
+ // cout << *fileHash << endl;
+ // cout << name << endl;
+
+ Bytes data = m_ccnx->createContentObject (name, buf, iff.gcount ());
+ fileDb.saveContentObject (deviceName, segment, data);
+
+ segment ++;
+ }
+
+ return fileHash;
+}
+
+bool
+ObjectManager::objectsToLocalFile (/*in*/const Ccnx::Name &deviceName, /*in*/const Hash &fileHash, /*out*/ const fs::path &file)
+{
+ string hashStr = lexical_cast<string> (fileHash);
+ if (!ObjectDb::DoesExist (m_folder, deviceName, hashStr))
+ {
+ cout << "Brr" << endl;
+ // file does not exist or not all segments are available
+ return false;
+ }
+
+ fs::ofstream off (file, std::ios::out | std::ios::binary);
+ ObjectDb fileDb (m_folder, hashStr);
+
+ sqlite3_int64 segment = 0;
+ BytesPtr bytes = fileDb.fetchSegment (deviceName, 0);
+ while (bytes != BytesPtr())
+ {
+ ParsedContentObject obj (*bytes);
+ BytesPtr data = obj.contentPtr ();
+
+ off.write (reinterpret_cast<const char*> (head(*data)), data->size());
+
+ segment ++;
+ bytes = fileDb.fetchSegment (deviceName, segment);
+ }
+
+ // permission and timestamp should be assigned somewhere else (ObjectManager has no idea about that)
+
+ return true;
+}
diff --git a/src/object-manager.h b/src/object-manager.h
new file mode 100644
index 0000000..f0cd6e6
--- /dev/null
+++ b/src/object-manager.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012-2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#ifndef OBJECT_MANAGER_H
+#define OBJECT_MANAGER_H
+
+#include <string>
+#include <ccnx-wrapper.h>
+#include <hash-helper.h>
+#include <boost/filesystem.hpp>
+
+// everything related to managing object files
+
+class ObjectManager
+{
+public:
+ ObjectManager (Ccnx::CcnxWrapperPtr ccnx, const boost::filesystem::path &folder);
+ virtual ~ObjectManager ();
+
+ HashPtr
+ localFileToObjects (const boost::filesystem::path &file, const Ccnx::Name &deviceName);
+
+ bool
+ objectsToLocalFile (/*in*/const Ccnx::Name &deviceName, /*in*/const Hash &hash, /*out*/ const boost::filesystem::path &file);
+
+private:
+ Ccnx::CcnxWrapperPtr m_ccnx;
+ boost::filesystem::path m_folder;
+};
+
+typedef boost::shared_ptr<ObjectManager> ObjectManagerPtr;
+
+namespace Error {
+struct ObjectManager : virtual boost::exception, virtual std::exception { };
+}
+
+#endif // OBJECT_MANAGER_H
diff --git a/src/sync-log.cc b/src/sync-log.cc
index ce5b46c..ca6adf7 100644
--- a/src/sync-log.cc
+++ b/src/sync-log.cc
@@ -26,7 +26,7 @@
using namespace boost;
using namespace std;
-SyncLog::SyncLog (const std::string &path, const std::string &localName)
+SyncLog::SyncLog (const boost::filesystem::path &path, const std::string &localName)
: DbHelper (path)
, m_localName (localName)
{
diff --git a/src/sync-log.h b/src/sync-log.h
index 0316294..c75fcf7 100644
--- a/src/sync-log.h
+++ b/src/sync-log.h
@@ -31,7 +31,7 @@
class SyncLog : public DbHelper
{
public:
- SyncLog (const std::string &path, const std::string &localName);
+ SyncLog (const boost::filesystem::path &path, const std::string &localName);
sqlite3_int64
GetNextLocalSeqNo (); // side effect: local seq_no will be increased
diff --git a/test/database-test.cc b/test/database-test.cc
index a4fe0d6..dcbcc2b 100644
--- a/test/database-test.cc
+++ b/test/database-test.cc
@@ -26,19 +26,20 @@
#include "action-log.h"
#include <iostream>
#include <ccnx-name.h>
+#include <boost/filesystem.hpp>
using namespace std;
using namespace boost;
using namespace Ccnx;
+namespace fs = boost::filesystem;
BOOST_AUTO_TEST_SUITE(DatabaseTest)
BOOST_AUTO_TEST_CASE (BasicDatabaseTest)
{
- char dir_tmpl [] = "/tmp/tmp-chornoshare-XXXXXXXXXXX";
- string tmp_dir = mkdtemp (dir_tmpl);
- SyncLog db (tmp_dir, "/alex");
+ fs::path tmpdir = fs::unique_path (fs::temp_directory_path () / "%%%%-%%%%-%%%%-%%%%");
+ SyncLog db (tmpdir, "/alex");
HashPtr hash = db.RememberStateInStateLog ();
// should be empty
@@ -77,6 +78,7 @@
// db.FindStateDifferences ("86b51f1f98662583b295b61385ae4450ff8fac955981f1ca4381144ab1d7a4e0",
// "d001d4680fd9adcb48e34a795e3cc3d5d36f209fbab34fd57f70f362c2085310");
+ remove_all (tmpdir);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/test-object-manager.cc b/test/test-object-manager.cc
new file mode 100644
index 0000000..78337b3
--- /dev/null
+++ b/test/test-object-manager.cc
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "object-manager.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <boost/test/unit_test.hpp>
+#include <unistd.h>
+#include <boost/make_shared.hpp>
+#include <iostream>
+#include <iterator>
+
+using namespace Ccnx;
+using namespace std;
+using namespace boost;
+namespace fs = boost::filesystem;
+
+BOOST_AUTO_TEST_SUITE(ObjectManagerTests)
+
+BOOST_AUTO_TEST_CASE (ObjectManagerTest)
+{
+ fs::path tmpdir = fs::unique_path (fs::temp_directory_path () / "%%%%-%%%%-%%%%-%%%%");
+ cout << tmpdir << endl;
+ Name deviceName ("/device");
+
+ CcnxWrapperPtr ccnx = make_shared<CcnxWrapper> ();
+ ObjectManager manager (ccnx, tmpdir);
+
+ HashPtr hash = manager.localFileToObjects (fs::path("test") / "test-object-manager.cc", deviceName);
+
+ bool ok = manager.objectsToLocalFile (deviceName, *hash, tmpdir / "test.cc");
+ BOOST_CHECK_EQUAL (ok, true);
+
+ {
+ fs::ifstream origFile (fs::path("test") / "test-object-manager.cc");
+ fs::ifstream newFile (tmpdir / "test.cc");
+
+ istream_iterator<char> eof,
+ origFileI (origFile),
+ newFileI (newFile);
+
+ BOOST_CHECK_EQUAL_COLLECTIONS (origFileI, eof, newFileI, eof);
+ }
+
+ remove_all (tmpdir);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/wscript b/wscript
index 6ec706f..5d38675 100644
--- a/wscript
+++ b/wscript
@@ -19,7 +19,6 @@
conf.define ("CHRONOSHARE_VERSION", VERSION)
conf.check_cfg(package='sqlite3', args=['--cflags', '--libs'], uselib_store='SQLITE3', mandatory=True)
-
conf.check_cfg(package='libevent', args=['--cflags', '--libs'], uselib_store='LIBEVENT', mandatory=True)
conf.check_cfg(package='libevent_pthreads', args=['--cflags', '--libs'], uselib_store='LIBEVENT_PTHREADS', mandatory=True)
@@ -36,7 +35,7 @@
conf.load ('ccnx')
conf.load('boost')
- conf.check_boost(lib='system test iostreams regex thread')
+ conf.check_boost(lib='system test iostreams filesystem regex thread')
boost_version = conf.env.BOOST_VERSION.split('_')
if int(boost_version[0]) < 1 or int(boost_version[1]) < 46:
@@ -60,6 +59,16 @@
conf.write_config_header('src/config.h')
def build (bld):
+ common = bld.objects (
+ target = "common",
+ features = ["cxx"],
+ source = ['src/hash-helper.cc',
+ 'src/chronoshare-client.ice',
+ ],
+ use = 'BOOST',
+ includes = ['include', 'src'],
+ )
+
libccnx = bld (
target=CCNXLIB,
features=['cxx', 'cxxshlib'],
@@ -68,22 +77,13 @@
'src/ccnx-pco.cpp',
'src/ccnx-closure.cpp',
'src/ccnx-tunnel.cpp',
- 'src/object-db-file.cpp',
+ 'src/object-db.cc',
+ 'src/object-manager.cc',
'src/ccnx-name.cpp',
'src/ccnx-selectors.cpp',
'src/event-scheduler.cpp',
],
- use = 'BOOST BOOST_THREAD SSL CCNX LIBEVENT LIBEVENT_PTHREADS',
- includes = ['include', ],
- )
-
- common = bld.objects (
- target = "common",
- features = ["cxx"],
- source = ['src/hash-helper.cc',
- 'src/chronoshare-client.ice',
- ],
- use = 'BOOST',
+ use = 'BOOST BOOST_THREAD BOOST_FILESYSTEM SSL SQLITE3 CCNX common LIBEVENT LIBEVENT_PTHREADS',
includes = ['include', 'src'],
)
@@ -107,7 +107,7 @@
target="unit-tests",
source = bld.path.ant_glob(['test/**/*.cc']),
features=['cxx', 'cxxprogram'],
- use = 'BOOST_TEST LIBEVENT LIBEVENT_PTHREADS ccnxx database',
+ use = 'BOOST_TEST ccnxx database',
includes = ['include', 'src'],
)