Another reorganization
diff --git a/client/client.cc b/client/client.cc
index 22a0147..8ab8013 100644
--- a/client/client.cc
+++ b/client/client.cc
@@ -24,6 +24,9 @@
#include <config.h>
#include <Ice/Ice.h>
#include <chronoshare-client.ice.h>
+#include <sys/stat.h>
+#include <hash-helper.h>
+
using namespace std;
using namespace boost;
@@ -42,6 +45,7 @@
exit (1);
}
+
int
main (int argc, char **argv)
{
@@ -58,29 +62,7 @@
cout << "chronoshare version " << CHRONOSHARE_VERSION << endl;
exit (0);
}
- else if (cmd == "update")
- {
- if (argc != 3)
- {
- usage ();
- }
- }
- else if (cmd == "delete")
- {
- if (argc != 3)
- {
- usage ();
- }
- }
- else if (cmd == "move")
- {
- if (argc != 4)
- {
- usage ();
- }
- }
-
-
+
int status = 0;
Ice::CommunicatorPtr ic;
try
@@ -98,7 +80,59 @@
NotifyPrx notify = NotifyPrx::checkedCast (base);
if (notify)
{
- notify->deleteFile ("bla");
+
+ if (cmd == "update")
+ {
+ if (argc != 3)
+ {
+ usage ();
+ }
+
+ struct stat fileStats;
+ int ok = stat (argv[2], &fileStats);
+ if (ok == 0)
+ {
+ // Alex: the following code is platform specific :(
+
+ char atimespec[26], mtimespec[26], ctimespec[26];
+ ctime_r (&fileStats.st_atime, atimespec);
+ ctime_r (&fileStats.st_mtime, mtimespec);
+ ctime_r (&fileStats.st_ctime, ctimespec);
+
+ HashPtr fileHash = Hash::FromFileContent (argv[2]);
+
+ notify->updateFile (argv[2],
+ make_pair(reinterpret_cast<const ::Ice::Byte*> (fileHash->GetHash ()),
+ reinterpret_cast<const ::Ice::Byte*> (fileHash->GetHash ()) +
+ fileHash->GetHashBytes ()),
+ atimespec, mtimespec, ctimespec,
+ fileStats.st_mode);
+ }
+ else
+ {
+ cerr << "File [" << argv[2] << "] doesn't exist or is not accessible" << endl;
+ return 1;
+ }
+ }
+ else if (cmd == "delete")
+ {
+ if (argc != 3)
+ {
+ usage ();
+ }
+
+ notify->deleteFile (argv[2]);
+ }
+ else if (cmd == "move")
+ {
+ if (argc != 4)
+ {
+ usage ();
+ }
+
+
+ notify->moveFile (argv[2], argv[3]);
+ }
}
else
{
diff --git a/daemon/daemon.cc b/daemon/daemon.cc
index fad4017..97fee4f 100644
--- a/daemon/daemon.cc
+++ b/daemon/daemon.cc
@@ -19,7 +19,7 @@
* Zhenkai Zhu <zhenkai@cs.ucla.edu>
*/
-#include "db-helper.h"
+#include "action-log.h"
#include <iostream>
#include <Ice/Service.h>
#include <Ice/Identity.h>
@@ -61,7 +61,8 @@
try
{
- DbHelper db ("./");
+ // DbHelper db ("./", "/ndn/ucla.edu/alex");
+ ActionLog bla ("./", "/ndn/ucla.edu/alex");
MyService svc;
status = svc.main (argc, argv);
diff --git a/daemon/notify-i.cc b/daemon/notify-i.cc
index 48ac56c..0f8b004 100644
--- a/daemon/notify-i.cc
+++ b/daemon/notify-i.cc
@@ -20,26 +20,46 @@
*/
#include "notify-i.h"
+#include <hash-helper.h>
using namespace std;
+// NotifyI::NotifyI (DbHelperPtr &db)
+// : m_db (db)
+// {
+// }
+
void
NotifyI::updateFile (const ::std::string &filename,
- const ::ChronoshareClient::HashBytes &hash,
+ const ::std::pair<const Ice::Byte*, const Ice::Byte*> &hashRaw,
const ::std::string &atime,
const ::std::string &mtime,
const ::std::string &ctime,
::Ice::Int mode,
const ::Ice::Current&)
{
- cout << "updateFile " << filename << endl;
+ Hash hash (hashRaw.first, hashRaw.second-hashRaw.first);
+
+ // m_db->AddActionUpdate (filename, hash, atime, mtime, ctime, mode);
+
+ // cout << "updateFile " << filename << " with hash " << hash << endl;
}
+void
+NotifyI::moveFile (const ::std::string &oldFilename,
+ const ::std::string &newFilename,
+ const ::Ice::Current&)
+{
+ // cout << "moveFile from " << oldFilename << " to " << newFilename << endl;
+ // m_db->AddActionMove (filename, oldFilename);
+}
void
NotifyI::deleteFile (const ::std::string &filename,
const ::Ice::Current&)
{
- cout << "deleteFile " << filename << endl;
+ // m_db->AddActionDelete (filename, oldFilename);
+
+ // cout << "deleteFile " << filename << endl;
}
diff --git a/daemon/notify-i.h b/daemon/notify-i.h
index 7afb0dd..a2cea97 100644
--- a/daemon/notify-i.h
+++ b/daemon/notify-i.h
@@ -27,9 +27,11 @@
class NotifyI : public ChronoshareClient::Notify
{
public:
+ // NotifyI (DbHelperPtr &db);
+
virtual void
updateFile (const ::std::string &filename,
- const ::ChronoshareClient::HashBytes &hash,
+ const ::std::pair<const Ice::Byte*, const Ice::Byte*> &hash,
const ::std::string &atime,
const ::std::string &mtime,
const ::std::string &ctime,
@@ -37,9 +39,16 @@
const ::Ice::Current& = ::Ice::Current());
virtual void
+ moveFile (const ::std::string &oldFilename,
+ const ::std::string &newFilename,
+ const ::Ice::Current& = ::Ice::Current());
+
+ virtual void
deleteFile (const ::std::string &filename,
const ::Ice::Current& = ::Ice::Current());
+private:
+ // DbHelperPtr m_db;
};
#endif // NOTIFY_I_H
diff --git a/src/action-log.cc b/src/action-log.cc
new file mode 100644
index 0000000..cf5156a
--- /dev/null
+++ b/src/action-log.cc
@@ -0,0 +1,78 @@
+/* -*- 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>
+ */
+
+#include "action-log.h"
+
+using namespace boost;
+using namespace std;
+
+ActionLog::ActionLog (const std::string &path, const std::string &localName)
+ : SyncLog (path)
+ , m_localName (localName)
+{
+}
+
+// local add action. remote action is extracted from content object
+void
+ActionLog::AddActionUpdate (const std::string &filename,
+ const Hash &hash,
+ const std::string &atime, const std::string &mtime, const std::string &ctime,
+ int mode)
+{
+ int res = sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
+
+ // sqlite3_stmt *stmt;
+ // res += sqlite3_prepare_v2 (m_db, "SELECT version,device_id,seq_no FROM ActionLog WHERE filename=? ORDER BY version DESC,device_id DESC LIMIT 1", -1, &stmt, 0);
+
+ // if (res != SQLITE_OK)
+ // {
+ // BOOST_THROW_EXCEPTION (Error::Db ()
+ // << errmsg_info_str ("Some error with AddActionUpdate"));
+ // }
+
+ // sqlite3_bind_text (stmt, 1, filename.c_str (), -1);
+ // if (sqlite3_step (stmt) == SQLITE_ROW)
+ // {
+ // // with parent
+ // sqlite3_int64 version = sqlite3_value_int64 (stmt, 0) + 1;
+ // sqlite3_int64 device_id = sqlite3_value_int64 (stmt, 1);
+ // sqlite3_int64 seq_no = sqlite3_value_int64 (stmt, 0);
+
+
+ // }
+ // else
+ // {
+ // // without parent
+
+ // }
+
+ res += sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
+}
+
+void
+ActionLog::AddActionMove (const std::string &oldFile, const std::string &newFile)
+{
+}
+
+void
+ActionLog::AddActionDelete (const std::string &filename)
+{
+}
diff --git a/src/action-log.h b/src/action-log.h
new file mode 100644
index 0000000..6827cba
--- /dev/null
+++ b/src/action-log.h
@@ -0,0 +1,51 @@
+/* -*- 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 ACTION_LOG_H
+#define ACTION_LOG_H
+
+#include "sync-log.h"
+
+class ActionLog : public SyncLog
+{
+public:
+ ActionLog (const std::string &path, const std::string &localName);
+
+
+
+
+ void
+ AddActionUpdate (const std::string &filename,
+ const Hash &hash,
+ const std::string &atime, const std::string &mtime, const std::string &ctime,
+ int mode);
+
+ void
+ AddActionMove (const std::string &oldFile, const std::string &newFile);
+
+ void
+ AddActionDelete (const std::string &filename);
+
+protected:
+ std::string m_localName;
+};
+
+#endif // ACTION_LOG_H
diff --git a/src/chronoshare-client.ice b/src/chronoshare-client.ice
index f32577e..be40c3e 100644
--- a/src/chronoshare-client.ice
+++ b/src/chronoshare-client.ice
@@ -25,7 +25,9 @@
interface Notify
{
- void updateFile (string filename, HashBytes fileHash, string atime, string mtime, string ctime, int mode);
+ void updateFile (string filename, ["cpp:array"] HashBytes fileHash, string atime, string mtime, string ctime, int mode);
+
+ void moveFile (string origFilename, string newFilename);
void deleteFile (string filename);
};
diff --git a/src/db-helper.cc b/src/db-helper.cc
index f6d7ba8..9bd2d61 100644
--- a/src/db-helper.cc
+++ b/src/db-helper.cc
@@ -23,13 +23,7 @@
// #include "sync-log.h"
#include <boost/make_shared.hpp>
#include <boost/ref.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
-
#include <boost/throw_exception.hpp>
-typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
-// typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int;
using namespace boost;
@@ -145,24 +139,6 @@
<< errmsg_info_str ("Cannot create function ``hash''"));
}
- res = sqlite3_create_function (m_db, "hash2str", 2, SQLITE_ANY, 0,
- DbHelper::hash2str_Func,
- 0, 0);
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Cannot create function ``hash''"));
- }
-
- res = sqlite3_create_function (m_db, "str2hash", 2, SQLITE_ANY, 0,
- DbHelper::str2hash_Func,
- 0, 0);
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Cannot create function ``hash''"));
- }
-
// Alex: determine if tables initialized. if not, initialize... not sure what is the best way to go...
// for now, just attempt to create everything
@@ -184,72 +160,6 @@
}
}
-HashPtr
-DbHelper::RememberStateInStateLog ()
-{
- int res = sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
-
- res += sqlite3_exec (m_db, "\
-INSERT INTO SyncLog \
- (state_hash, last_update) \
- SELECT \
- hash(device_name, seq_no), datetime('now') \
- FROM SyncNodes \
- ORDER BY device_name; \
-", 0,0,0);
-
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("1"));
- }
-
- sqlite3_int64 rowId = sqlite3_last_insert_rowid (m_db);
-
- sqlite3_stmt *insertStmt;
- res += sqlite3_prepare (m_db, "\
-INSERT INTO SyncStateNodes \
- (state_id, device_id, seq_no) \
- SELECT ?, device_id, seq_no \
- FROM SyncNodes; \
-", -1, &insertStmt, 0);
-
- res += sqlite3_bind_int64 (insertStmt, 1, rowId);
- sqlite3_step (insertStmt);
-
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("4"));
- }
- sqlite3_finalize (insertStmt);
-
- sqlite3_stmt *getHashStmt;
- res += sqlite3_prepare (m_db, "\
-SELECT state_hash FROM SyncLog WHERE state_id = ?\
-", -1, &getHashStmt, 0);
- res += sqlite3_bind_int64 (getHashStmt, 1, rowId);
-
- HashPtr retval;
- int stepRes = sqlite3_step (getHashStmt);
- if (stepRes == SQLITE_ROW)
- {
- retval = make_shared<Hash> (sqlite3_column_blob (getHashStmt, 0),
- sqlite3_column_bytes (getHashStmt, 0));
- }
- sqlite3_finalize (getHashStmt);
- res += sqlite3_exec (m_db, "COMMIT;", 0,0,0);
-
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Some error with rememberStateInStateLog"));
- }
-
- return retval;
-}
-
-
void
DbHelper::hash_xStep (sqlite3_context *context, int argc, sqlite3_value **argv)
{
@@ -319,169 +229,5 @@
EVP_MD_CTX_destroy (*hash_context);
}
-void
-DbHelper::hash2str_Func (sqlite3_context *context, int argc, sqlite3_value **argv)
-{
- if (argc != 1 || sqlite3_value_type (argv[0]) != SQLITE_BLOB)
- {
- sqlite3_result_error (context, "Wrong arguments are supplied for ``hash2str'' function", -1);
- return;
- }
-
- int hashBytes = sqlite3_value_bytes (argv[0]);
- const void *hash = sqlite3_value_blob (argv[0]);
-
- std::ostringstream os;
- Hash tmpHash (hash, hashBytes);
- os << tmpHash;
- sqlite3_result_text (context, os.str ().c_str (), -1, SQLITE_TRANSIENT);
-}
-
-void
-DbHelper::str2hash_Func (sqlite3_context *context, int argc, sqlite3_value **argv)
-{
- if (argc != 1 || sqlite3_value_type (argv[0]) != SQLITE_TEXT)
- {
- sqlite3_result_error (context, "Wrong arguments are supplied for ``str2hash'' function", -1);
- return;
- }
-
- size_t hashTextBytes = sqlite3_value_bytes (argv[0]);
- const unsigned char *hashText = sqlite3_value_text (argv[0]);
-
- Hash hash (std::string (reinterpret_cast<const char*> (hashText), hashTextBytes));
- sqlite3_result_blob (context, hash.GetHash (), hash.GetHashBytes (), SQLITE_TRANSIENT);
-}
-sqlite3_int64
-DbHelper::LookupSyncLog (const std::string &stateHash)
-{
- Hash tmpHash (stateHash);
- return LookupSyncLog (stateHash);
-}
-
-sqlite3_int64
-DbHelper::LookupSyncLog (const Hash &stateHash)
-{
- sqlite3_stmt *stmt;
- int res = sqlite3_prepare (m_db, "SELECT state_id FROM SyncLog WHERE state_hash = ?",
- -1, &stmt, 0);
-
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Cannot prepare statement"));
- }
-
- res = sqlite3_bind_blob (stmt, 1, stateHash.GetHash (), stateHash.GetHashBytes (), SQLITE_STATIC);
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Cannot bind"));
- }
-
- sqlite3_int64 row = 0; // something bad
-
- if (sqlite3_step (stmt) == SQLITE_ROW)
- {
- row = sqlite3_column_int64 (stmt, 0);
- }
-
- sqlite3_finalize (stmt);
-
- return row;
-}
-
-void
-DbHelper::UpdateDeviceSeqno (const std::string &name, uint64_t seqNo)
-{
- sqlite3_stmt *stmt;
- // update is performed using trigger
- int res = sqlite3_prepare (m_db, "INSERT INTO SyncNodes (device_name, seq_no) VALUES (?,?);",
- -1, &stmt, 0);
-
- res += sqlite3_bind_text (stmt, 1, name.c_str (), name.size (), SQLITE_STATIC);
- res += sqlite3_bind_int64 (stmt, 2, seqNo);
- sqlite3_step (stmt);
-
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Some error with UpdateDeviceSeqno"));
- }
- sqlite3_finalize (stmt);
-}
-
-void
-DbHelper::FindStateDifferences (const std::string &oldHash, const std::string &newHash)
-{
- Hash tmpOldHash (oldHash);
- Hash tmpNewHash (newHash);
-
- FindStateDifferences (tmpOldHash, tmpNewHash);
-}
-
-void
-DbHelper::FindStateDifferences (const Hash &oldHash, const Hash &newHash)
-{
- sqlite3_stmt *stmt;
-
- int res = sqlite3_prepare_v2 (m_db, "\
-SELECT sn.device_name, s_old.seq_no, s_new.seq_no \
- FROM (SELECT * \
- FROM SyncStateNodes \
- WHERE state_id=(SELECT state_id \
- FROM SyncLog \
- WHERE state_hash=:old_hash)) s_old \
- LEFT JOIN (SELECT * \
- FROM SyncStateNodes \
- WHERE state_id=(SELECT state_id \
- FROM SyncLog \
- WHERE state_hash=:new_hash)) s_new \
- \
- ON s_old.device_id = s_new.device_id \
- JOIN SyncNodes sn ON sn.device_id = s_old.device_id \
- \
- WHERE s_new.seq_no IS NULL OR \
- s_old.seq_no != s_new.seq_no \
- \
-UNION ALL \
- \
-SELECT sn.device_name, s_old.seq_no, s_new.seq_no \
- FROM (SELECT * \
- FROM SyncStateNodes \
- WHERE state_id=(SELECT state_id \
- FROM SyncLog \
- WHERE state_hash=:new_hash )) s_new \
- LEFT JOIN (SELECT * \
- FROM SyncStateNodes \
- WHERE state_id=(SELECT state_id \
- FROM SyncLog \
- WHERE state_hash=:old_hash)) s_old \
- \
- ON s_old.device_id = s_new.device_id \
- JOIN SyncNodes sn ON sn.device_id = s_new.device_id \
- \
- WHERE s_old.seq_no IS NULL \
-", -1, &stmt, 0);
-
- if (res != SQLITE_OK)
- {
- BOOST_THROW_EXCEPTION (Error::Db ()
- << errmsg_info_str ("Some error with FindStateDifferences"));
- }
-
- res += sqlite3_bind_blob (stmt, 1, oldHash.GetHash (), oldHash.GetHashBytes (), SQLITE_STATIC);
- res += sqlite3_bind_blob (stmt, 2, newHash.GetHash (), newHash.GetHashBytes (), SQLITE_STATIC);
-
- while (sqlite3_step (stmt) == SQLITE_ROW)
- {
- std::cout << sqlite3_column_text (stmt, 0) <<
- ": from " << sqlite3_column_int64 (stmt, 1) <<
- " to " << sqlite3_column_int64 (stmt, 2) <<
- std::endl;
- }
- sqlite3_finalize (stmt);
-
-}
diff --git a/src/db-helper.h b/src/db-helper.h
index e119523..a0a9442 100644
--- a/src/db-helper.h
+++ b/src/db-helper.h
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
- * Copyright (c) 2012 University of California, Los Angeles
+ * 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
@@ -19,54 +19,22 @@
* Zhenkai Zhu <zhenkai@cs.ucla.edu>
*/
-#ifndef SQLITE_HELPER_H
-#define SQLITE_HELPER_H
+#ifndef DB_HELPER_H
+#define DB_HELPER_H
#include <sqlite3.h>
#include <openssl/evp.h>
#include <boost/exception/all.hpp>
#include <string>
-#include "hash-string-converter.h"
+#include "hash-helper.h"
-// temporarily ignoring all potential database errors
+typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
class DbHelper
{
public:
DbHelper (const std::string &path);
- ~DbHelper ();
-
- // done
- void
- UpdateDeviceSeqno (const std::string &name, uint64_t seqNo);
-
- // std::string
- // LookupForwardingAlias (const std::string &deviceName);
-
- // void
- // UpdateForwardingAlias ();
-
- // done
- /**
- * Create an entry in SyncLog and SyncStateNodes corresponding to the current state of SyncNodes
- */
- HashPtr
- RememberStateInStateLog ();
-
- // done
- sqlite3_int64
- LookupSyncLog (const std::string &stateHash);
-
- // done
- sqlite3_int64
- LookupSyncLog (const Hash &stateHash);
-
- // How difference is exposed will be determined later by the actual protocol
- void
- FindStateDifferences (const std::string &oldHash, const std::string &newHash);
-
- void
- FindStateDifferences (const Hash &oldHash, const Hash &newHash);
+ virtual ~DbHelper ();
private:
static void
@@ -75,13 +43,7 @@
static void
hash_xFinal (sqlite3_context *context);
- static void
- hash2str_Func (sqlite3_context *context, int argc, sqlite3_value **argv);
-
- static void
- str2hash_Func (sqlite3_context *context, int argc, sqlite3_value **argv);
-
-private:
+protected:
sqlite3 *m_db;
};
@@ -89,5 +51,7 @@
struct Db : virtual boost::exception, virtual std::exception { };
}
+typedef boost::shared_ptr<DbHelper> DbHelperPtr;
-#endif // SQLITE_HELPER_H
+
+#endif // DB_HELPER_H
diff --git a/src/hash-string-converter.cc b/src/hash-helper.cc
similarity index 78%
rename from src/hash-string-converter.cc
rename to src/hash-helper.cc
index 2961069..04b52b2 100644
--- a/src/hash-string-converter.cc
+++ b/src/hash-helper.cc
@@ -19,12 +19,13 @@
* Zhenkai Zhu <zhenkai@cs.ucla.edu>
*/
-#include "hash-string-converter.h"
+#include "hash-helper.h"
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/make_shared.hpp>
#include <openssl/evp.h>
+#include <fstream>
typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int;
@@ -101,29 +102,56 @@
return os;
}
-Hash::Hash (const std::string &hashInTextEncoding)
+HashPtr
+Hash::FromString (const std::string &hashInTextEncoding)
{
+ HashPtr retval = make_shared<Hash> (reinterpret_cast<void*> (0), 0);
+
if (hashInTextEncoding.size () == 0)
{
- m_buf = 0;
- m_length = 0;
- return;
+ return retval;
}
if (hashInTextEncoding.size () > EVP_MAX_MD_SIZE * 2)
{
cerr << "Input hash is too long. Returning an empty hash" << endl;
- m_buf = 0;
- m_length = 0;
- return;
+ return retval;
}
- m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
unsigned char *end = copy (string_to_binary (hashInTextEncoding.begin ()),
string_to_binary (hashInTextEncoding.end ()),
- m_buf);
+ retval->m_buf);
- m_length = end-m_buf;
+ retval->m_length = end - retval->m_buf;
+
+ return retval;
}
+HashPtr
+Hash::FromFileContent (const std::string &filename)
+{
+ HashPtr retval = make_shared<Hash> (reinterpret_cast<void*> (0), 0);
+ retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
+ 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);
+ while (iff.good ())
+ {
+ char buf[1024];
+ iff.read (buf, 1024);
+ EVP_DigestUpdate (hash_context, buf, iff.gcount ());
+ }
+
+ retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
+ EVP_DigestFinal_ex (hash_context,
+ retval->m_buf, &retval->m_length);
+
+ EVP_MD_CTX_destroy (hash_context);
+
+ return retval;
+}
diff --git a/src/hash-string-converter.h b/src/hash-helper.h
similarity index 80%
rename from src/hash-string-converter.h
rename to src/hash-helper.h
index b696426..ea12f30 100644
--- a/src/hash-string-converter.h
+++ b/src/hash-helper.h
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
- * Copyright (c) 2012 University of California, Los Angeles
+ * 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
@@ -19,18 +19,24 @@
* Zhenkai Zhu <zhenkai@cs.ucla.edu>
*/
-#ifndef HASH_STRING_CONVERTER_H
-#define HASH_STRING_CONVERTER_H
+#ifndef HASH_HELPER_H
+#define HASH_HELPER_H
#include <string.h>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/exception/all.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
+
+class Hash;
+typedef boost::shared_ptr<Hash> HashPtr;
+
class Hash
{
public:
- Hash (const void *buf, size_t length)
+ Hash (const void *buf, unsigned int length)
: m_length (length)
{
if (m_length != 0)
@@ -40,8 +46,12 @@
}
}
- Hash (const std::string &hashInTextEncoding);
+ static HashPtr
+ FromString (const std::string &hashInTextEncoding);
+ static HashPtr
+ FromFileContent (const std::string &hashInTextEncoding);
+
~Hash ()
{
if (m_length != 0)
@@ -70,7 +80,7 @@
return m_buf;
}
- size_t
+ unsigned int
GetHashBytes () const
{
return m_length;
@@ -78,7 +88,7 @@
private:
unsigned char *m_buf;
- size_t m_length;
+ unsigned int m_length;
Hash (const Hash &) { }
Hash & operator = (const Hash &) { return *this; }
@@ -91,8 +101,6 @@
struct HashConversion : virtual boost::exception, virtual std::exception { };
}
-typedef boost::shared_ptr<Hash> HashPtr;
-
std::ostream &
operator << (std::ostream &os, const Hash &digest);
diff --git a/src/sync-log.cc b/src/sync-log.cc
new file mode 100644
index 0000000..99b652c
--- /dev/null
+++ b/src/sync-log.cc
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 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>
+ */
+
+#include "sync-log.h"
+
+#include <boost/make_shared.hpp>
+
+using namespace boost;
+using namespace std;
+
+HashPtr
+SyncLog::RememberStateInStateLog ()
+{
+ int res = sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
+
+ res += sqlite3_exec (m_db, "\
+INSERT INTO SyncLog \
+ (state_hash, last_update) \
+ SELECT \
+ hash(device_name, seq_no), datetime('now') \
+ FROM SyncNodes \
+ ORDER BY device_name; \
+", 0,0,0);
+
+ if (res != SQLITE_OK)
+ {
+ BOOST_THROW_EXCEPTION (Error::Db ()
+ << errmsg_info_str ("1"));
+ }
+
+ sqlite3_int64 rowId = sqlite3_last_insert_rowid (m_db);
+
+ sqlite3_stmt *insertStmt;
+ res += sqlite3_prepare (m_db, "\
+INSERT INTO SyncStateNodes \
+ (state_id, device_id, seq_no) \
+ SELECT ?, device_id, seq_no \
+ FROM SyncNodes; \
+", -1, &insertStmt, 0);
+
+ res += sqlite3_bind_int64 (insertStmt, 1, rowId);
+ sqlite3_step (insertStmt);
+
+ if (res != SQLITE_OK)
+ {
+ BOOST_THROW_EXCEPTION (Error::Db ()
+ << errmsg_info_str ("4"));
+ }
+ sqlite3_finalize (insertStmt);
+
+ sqlite3_stmt *getHashStmt;
+ res += sqlite3_prepare (m_db, "\
+SELECT state_hash FROM SyncLog WHERE state_id = ?\
+", -1, &getHashStmt, 0);
+ res += sqlite3_bind_int64 (getHashStmt, 1, rowId);
+
+ HashPtr retval;
+ int stepRes = sqlite3_step (getHashStmt);
+ if (stepRes == SQLITE_ROW)
+ {
+ retval = make_shared<Hash> (sqlite3_column_blob (getHashStmt, 0),
+ sqlite3_column_bytes (getHashStmt, 0));
+ }
+ sqlite3_finalize (getHashStmt);
+ res += sqlite3_exec (m_db, "COMMIT;", 0,0,0);
+
+ if (res != SQLITE_OK)
+ {
+ BOOST_THROW_EXCEPTION (Error::Db ()
+ << errmsg_info_str ("Some error with rememberStateInStateLog"));
+ }
+
+ return retval;
+}
+
+sqlite3_int64
+SyncLog::LookupSyncLog (const std::string &stateHash)
+{
+ return LookupSyncLog (*Hash::FromString (stateHash));
+}
+
+sqlite3_int64
+SyncLog::LookupSyncLog (const Hash &stateHash)
+{
+ sqlite3_stmt *stmt;
+ int res = sqlite3_prepare (m_db, "SELECT state_id FROM SyncLog WHERE state_hash = ?",
+ -1, &stmt, 0);
+
+ if (res != SQLITE_OK)
+ {
+ BOOST_THROW_EXCEPTION (Error::Db ()
+ << errmsg_info_str ("Cannot prepare statement"));
+ }
+
+ res = sqlite3_bind_blob (stmt, 1, stateHash.GetHash (), stateHash.GetHashBytes (), SQLITE_STATIC);
+ if (res != SQLITE_OK)
+ {
+ BOOST_THROW_EXCEPTION (Error::Db ()
+ << errmsg_info_str ("Cannot bind"));
+ }
+
+ sqlite3_int64 row = 0; // something bad
+
+ if (sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ row = sqlite3_column_int64 (stmt, 0);
+ }
+
+ sqlite3_finalize (stmt);
+
+ return row;
+}
+
+void
+SyncLog::UpdateDeviceSeqno (const std::string &name, uint64_t seqNo)
+{
+ sqlite3_stmt *stmt;
+ // update is performed using trigger
+ int res = sqlite3_prepare (m_db, "INSERT INTO SyncNodes (device_name, seq_no) VALUES (?,?);",
+ -1, &stmt, 0);
+
+ res += sqlite3_bind_text (stmt, 1, name.c_str (), name.size (), SQLITE_STATIC);
+ res += sqlite3_bind_int64 (stmt, 2, seqNo);
+ sqlite3_step (stmt);
+
+ if (res != SQLITE_OK)
+ {
+ BOOST_THROW_EXCEPTION (Error::Db ()
+ << errmsg_info_str ("Some error with UpdateDeviceSeqno"));
+ }
+ sqlite3_finalize (stmt);
+}
+
+void
+SyncLog::FindStateDifferences (const std::string &oldHash, const std::string &newHash)
+{
+ FindStateDifferences (*Hash::FromString (oldHash), *Hash::FromString (newHash));
+}
+
+void
+SyncLog::FindStateDifferences (const Hash &oldHash, const Hash &newHash)
+{
+ sqlite3_stmt *stmt;
+
+ int res = sqlite3_prepare_v2 (m_db, "\
+SELECT sn.device_name, s_old.seq_no, s_new.seq_no \
+ FROM (SELECT * \
+ FROM SyncStateNodes \
+ WHERE state_id=(SELECT state_id \
+ FROM SyncLog \
+ WHERE state_hash=:old_hash)) s_old \
+ LEFT JOIN (SELECT * \
+ FROM SyncStateNodes \
+ WHERE state_id=(SELECT state_id \
+ FROM SyncLog \
+ WHERE state_hash=:new_hash)) s_new \
+ \
+ ON s_old.device_id = s_new.device_id \
+ JOIN SyncNodes sn ON sn.device_id = s_old.device_id \
+ \
+ WHERE s_new.seq_no IS NULL OR \
+ s_old.seq_no != s_new.seq_no \
+ \
+UNION ALL \
+ \
+SELECT sn.device_name, s_old.seq_no, s_new.seq_no \
+ FROM (SELECT * \
+ FROM SyncStateNodes \
+ WHERE state_id=(SELECT state_id \
+ FROM SyncLog \
+ WHERE state_hash=:new_hash )) s_new \
+ LEFT JOIN (SELECT * \
+ FROM SyncStateNodes \
+ WHERE state_id=(SELECT state_id \
+ FROM SyncLog \
+ WHERE state_hash=:old_hash)) s_old \
+ \
+ ON s_old.device_id = s_new.device_id \
+ JOIN SyncNodes sn ON sn.device_id = s_new.device_id \
+ \
+ WHERE s_old.seq_no IS NULL \
+", -1, &stmt, 0);
+
+ if (res != SQLITE_OK)
+ {
+ BOOST_THROW_EXCEPTION (Error::Db ()
+ << errmsg_info_str ("Some error with FindStateDifferences"));
+ }
+
+ res += sqlite3_bind_blob (stmt, 1, oldHash.GetHash (), oldHash.GetHashBytes (), SQLITE_STATIC);
+ res += sqlite3_bind_blob (stmt, 2, newHash.GetHash (), newHash.GetHashBytes (), SQLITE_STATIC);
+
+ while (sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ std::cout << sqlite3_column_text (stmt, 0) <<
+ ": from " << sqlite3_column_int64 (stmt, 1) <<
+ " to " << sqlite3_column_int64 (stmt, 2) <<
+ std::endl;
+ }
+ sqlite3_finalize (stmt);
+}
diff --git a/src/sync-log.h b/src/sync-log.h
index 267a08d..a597888 100644
--- a/src/sync-log.h
+++ b/src/sync-log.h
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
- * Copyright (c) 2012 University of California, Los Angeles
+ * Copyright (c) 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
@@ -22,27 +22,48 @@
#ifndef SYNC_LOG_H
#define SYNC_LOG_H
-#define INIT_LOGGER(name)
-#define _LOG_FUNCTION(x)
-#define _LOG_FUNCTION_NOARGS
-#define _LOG_TRACE(x)
-#define INIT_LOGGERS(x)
+#include "db-helper.h"
-#ifdef _DEBUG
+class SyncLog : public DbHelper
+{
+public:
+ SyncLog (const std::string &path)
+ : DbHelper (path)
+ {
+ }
-#include <boost/thread/thread.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <iostream>
-#include <string>
+ // done
+ void
+ UpdateDeviceSeqno (const std::string &name, uint64_t seqNo);
-#define _LOG_DEBUG(x) \
- std::clog << boost::get_system_time () << " " << boost::this_thread::get_id () << " " << x << std::endl;
+ // std::string
+ // LookupForwardingAlias (const std::string &deviceName);
-#else
-#define _LOG_DEBUG(x)
-#endif
+ // void
+ // UpdateForwardingAlias ();
-#define _LOG_ERROR(x) \
- std::clog << boost::get_system_time () << " " << boost::this_thread::get_id () << " " << x << std::endl;
+ // done
+ /**
+ * Create an entry in SyncLog and SyncStateNodes corresponding to the current state of SyncNodes
+ */
+ HashPtr
+ RememberStateInStateLog ();
+
+ // done
+ sqlite3_int64
+ LookupSyncLog (const std::string &stateHash);
+
+ // done
+ sqlite3_int64
+ LookupSyncLog (const Hash &stateHash);
+
+ // How difference is exposed will be determined later by the actual protocol
+ void
+ FindStateDifferences (const std::string &oldHash, const std::string &newHash);
+
+ void
+ FindStateDifferences (const Hash &oldHash, const Hash &newHash);
+};
+
#endif // SYNC_LOG_H
diff --git a/wscript b/wscript
index af3befd..b37b9f4 100644
--- a/wscript
+++ b/wscript
@@ -84,9 +84,9 @@
common = bld.objects (
target = "common",
features = ["cxx"],
- source = bld.path.ant_glob(
- 'src/chronoshare-client.ice'
- ),
+ source = ['src/hash-helper.cc',
+ 'src/chronoshare-client.ice',
+ ],
use = 'BOOST',
includes = ['include', 'src'],
)
@@ -108,7 +108,8 @@
source = ['daemon/daemon.cc',
'daemon/notify-i.cc',
'src/db-helper.cc',
- 'src/hash-string-converter.cc',
+ 'src/sync-log.cc',
+ 'src/action-log.cc',
],
use = "BOOST CCNX SSL SQLITE3 ICE common",
includes = ['include', 'src'],