Dispatcher now have all desired functions. Hopefully, after testing and debugging everything going to work
diff --git a/src/action-log.cc b/src/action-log.cc
index e33a221..9b2ee9c 100644
--- a/src/action-log.cc
+++ b/src/action-log.cc
@@ -90,7 +90,7 @@
filename TEXT NOT NULL, \n\
device_name BLOB NOT NULL, \n\
seq_no INTEGER NOT NULL, \n\
- file_hash BLOB, /* NULL if action is \"delete\" */ \n\
+ file_hash BLOB NOT NULL, \n\
file_atime TIMESTAMP, \n\
file_mtime TIMESTAMP, \n\
file_ctime TIMESTAMP, \n\
@@ -101,6 +101,7 @@
); \n\
\n\
CREATE INDEX FileState_device_name_seq_no ON FileState (device_name, seq_no); \n\
+CREATE INDEX FileState_type_file_hash ON FileState (type, file_hash); \n\
";
@@ -528,6 +529,22 @@
return AddRemoteAction (deviceName, seqno, actionPco);
}
+sqlite3_int64
+ActionLog::LogSize ()
+{
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM ActionLog", -1, &stmt, 0);
+
+ sqlite3_int64 retval = -1;
+ if (sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ retval = sqlite3_column_int64 (stmt, 0);
+ }
+
+ return retval;
+}
+
+
///////////////////////////////////////////////////////////////////////////////////
// SHOULD BE MOVED TO SEPARATE FILESTATE CLASS "EVENTUALLY"
///////////////////////////////////////////////////////////////////////////////////
@@ -636,36 +653,59 @@
/**
* @todo Implement checking modification time and permissions
*/
-bool
-ActionLog::KnownFileState(const std::string &filename, const Hash &hash
- /*, time_t mtime, int chmod*/)
+FileItemPtr
+ActionLog::LookupFile (const std::string &filename)
{
sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT * FROM FileState WHERE filename = ? AND file_hash = ?;", -1, &stmt, 0);
+ sqlite3_prepare_v2 (m_db,
+ "SELECT filename,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num "
+ " FROM FileState "
+ " WHERE type = 0 AND filename = ?", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
- sqlite3_bind_blob(stmt, 2, hash.GetHash (), hash.GetHashBytes (), SQLITE_STATIC);
- bool retval = false;
+ FileItemPtr retval;
if (sqlite3_step (stmt) == SQLITE_ROW)
{
- retval = true;
+ retval = make_shared<FileItem> ();
+ retval->set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
+ retval->set_device_name (sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1));
+ retval->set_seq_no (sqlite3_column_int64 (stmt, 2));
+ retval->set_file_hash (sqlite3_column_blob (stmt, 3), sqlite3_column_bytes (stmt, 3));
+ retval->set_mtime (sqlite3_column_int (stmt, 4));
+ retval->set_mode (sqlite3_column_int (stmt, 5));
+ retval->set_seg_num (sqlite3_column_int64 (stmt, 6));
}
sqlite3_finalize (stmt);
return retval;
}
-sqlite3_int64
-ActionLog::LogSize ()
+FileItemsPtr
+ActionLog::LookupFilesForHash (const Hash &hash)
{
sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM ActionLog", -1, &stmt, 0);
+ sqlite3_prepare_v2 (m_db,
+ "SELECT filename,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num "
+ " FROM FileState "
+ " WHERE type = 0 AND file_hash = ?;", -1, &stmt, 0);
+ sqlite3_bind_blob(stmt, 1, hash.GetHash (), hash.GetHashBytes (), SQLITE_STATIC);
- sqlite3_int64 retval = -1;
- if (sqlite3_step (stmt) == SQLITE_ROW)
- {
- retval = sqlite3_column_int64 (stmt, 0);
- }
+ FileItemsPtr retval = make_shared<FileItems> ();
+ while (sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ FileItem file;
+ file.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
+ file.set_device_name (sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1));
+ file.set_seq_no (sqlite3_column_int64 (stmt, 2));
+ file.set_file_hash (sqlite3_column_blob (stmt, 3), sqlite3_column_bytes (stmt, 3));
+ file.set_mtime (sqlite3_column_int (stmt, 4));
+ file.set_mode (sqlite3_column_int (stmt, 5));
+ file.set_seg_num (sqlite3_column_int64 (stmt, 6));
+
+ retval->push_back (file);
+ }
+
+ sqlite3_finalize (stmt);
return retval;
}
diff --git a/src/action-log.h b/src/action-log.h
index fec6e82..9833b92 100644
--- a/src/action-log.h
+++ b/src/action-log.h
@@ -25,6 +25,7 @@
#include "db-helper.h"
#include "sync-log.h"
#include "action-item.pb.h"
+#include "file-item.pb.h"
#include "ccnx-wrapper.h"
#include "ccnx-pco.h"
@@ -34,6 +35,10 @@
typedef boost::shared_ptr<ActionLog> ActionLogPtr;
typedef boost::shared_ptr<ActionItem> ActionItemPtr;
+typedef std::list<FileItem> FileItems;
+typedef boost::shared_ptr<FileItem> FileItemPtr;
+typedef boost::shared_ptr<FileItems> FileItemsPtr;
+
class ActionLog : public DbHelper
{
public:
@@ -64,9 +69,6 @@
ActionItemPtr
AddLocalActionDelete (const std::string &filename);
- bool
- KnownFileState(const std::string &filename, const Hash &hash);
-
//////////////////////////
// Remote operations //
//////////////////////////
@@ -98,7 +100,14 @@
ActionItemPtr
LookupAction (const Ccnx::Name &actionName);
+ ///////////////////////////
+ // File state operations //
+ ///////////////////////////
+ FileItemPtr
+ LookupFile (const std::string &filename);
+ FileItemsPtr
+ LookupFilesForHash (const Hash &hash);
public:
// for test purposes
diff --git a/src/dispatcher.cc b/src/dispatcher.cc
index d9bc37a..ab2dc41 100644
--- a/src/dispatcher.cc
+++ b/src/dispatcher.cc
@@ -93,37 +93,31 @@
Dispatcher::Did_LocalFile_AddOrModify_Execute (filesystem::path relativeFilePath)
{
filesystem::path absolutePath = m_rootDir / relativeFilePath;
- if (filesystem::exists(absolutePath))
- {
- HashPtr hash = Hash::FromFileContent(absolutePath);
- if (m_actionLog->KnownFileState(relativeFilePath.generic_string(), *hash))
- {
- // the file state is known; i.e. the detected changed file is identical to
- // the file state kept in FileState table
- // it is the case that backend puts the file fetched from remote;
- // we should not publish action for this.
- }
- else
- {
- uintmax_t fileSize = filesystem::file_size(absolutePath);
- int seg_num;
- tie (hash, seg_num) = m_objectManager.localFileToObjects (absolutePath, m_localUserName);
-
- time_t wtime = filesystem::last_write_time(absolutePath);
- filesystem::file_status stat = filesystem::status(absolutePath);
- int mode = stat.permissions();
-
- m_actionLog->AddLocalActionUpdate (relativeFilePath.generic_string(), *hash, wtime, mode, seg_num);
- // publish the file
-
- // notify SyncCore to propagate the change
- m_core->localStateChanged();
- }
- }
- else
+ if (!filesystem::exists(absolutePath))
{
BOOST_THROW_EXCEPTION (Error::Dispatcher() << error_info_str("Update non exist file: " + absolutePath.string() ));
}
+
+ FileItemPtr currentFile = m_actionLog->LookupFile (relativeFilePath.generic_string ());
+ if (currentFile &&
+ *Hash::FromFileContent (absolutePath) == Hash (currentFile->file_hash ().c_str (), currentFile->file_hash ().size ()) &&
+ last_write_time (absolutePath) == currentFile->mtime () &&
+ status (absolutePath).permissions () == static_cast<filesystem::perms> (currentFile->mode ()))
+ {
+ _LOG_ERROR ("Got notification about the same file [" << relativeFilePath << "]");
+ return;
+ }
+
+ int seg_num;
+ HashPtr hash;
+ tie (hash, seg_num) = m_objectManager.localFileToObjects (absolutePath, m_localUserName);
+
+ m_actionLog->AddLocalActionUpdate (relativeFilePath.generic_string(),
+ *hash,
+ last_write_time (absolutePath), status (absolutePath).permissions (), seg_num);
+
+ // notify SyncCore to propagate the change
+ m_core->localStateChanged();
}
void
@@ -135,6 +129,19 @@
void
Dispatcher::Did_LocalFile_Delete_Execute (filesystem::path relativeFilePath)
{
+ filesystem::path absolutePath = m_rootDir / relativeFilePath;
+ if (!filesystem::exists(absolutePath))
+ {
+ BOOST_THROW_EXCEPTION (Error::Dispatcher() << error_info_str("Delete notification but file exists: " + absolutePath.string() ));
+ }
+
+ FileItemPtr currentFile = m_actionLog->LookupFile (relativeFilePath.generic_string ());
+ if (!currentFile)
+ {
+ _LOG_ERROR ("File already deleted [" << relativeFilePath << "]");
+ return;
+ }
+
m_actionLog->AddLocalActionDelete (relativeFilePath.generic_string());
// notify SyncCore to propagate the change
m_core->localStateChanged();
@@ -267,24 +274,30 @@
Dispatcher::Did_FetchManager_FileFetchComplete_Execute (Ccnx::Name deviceName, Ccnx::Name fileBaseName)
{
_LOG_DEBUG ("Finished fetching " << deviceName << ", fileBaseName: " << fileBaseName);
- // int size = fileNamePrefix.size();
- // Bytes hashBytes = fileNamePrefix.getComp(size - 1);
- // Hash hash(head(hashBytes), hashBytes.size());
- // ostringstream oss;
- // oss << hash;
- // string hashString = oss.str();
- // if (m_objectDbMap.find(hashString) != m_objectDbMap.end())
- // {
- // // remove the db handle
- // m_objectDbMap.erase(hashString);
- // }
- // else
- // {
- // cout << "no db available for this file: " << fileNamePrefix << endl;
- // }
+ const Bytes &hashBytes = fileBaseName.getCompFromBack (1);
+ Hash hash (head (hashBytes), hashBytes.size ());
- // query the action table to get the path on local file system
- // m_objectManager.objectsToLocalFile(deviceName, hash, relativeFilePath);
+ FileItemsPtr filesToAssemble = m_actionLog->LookupFilesForHash (hash);
+ for (FileItems::iterator file = filesToAssemble->begin ();
+ file != filesToAssemble->end ();
+ file++)
+ {
+ boost::filesystem::path filePath = m_rootDir / file->filename ();
+ m_objectManager.objectsToLocalFile (deviceName, hash, filePath);
+
+ last_write_time (filePath, file->mtime ());
+ permissions (filePath, static_cast<filesystem::perms> (file->mode ()));
+ }
+
+ if (m_objectDbMap.find (hash) != m_objectDbMap.end())
+ {
+ // remove the db handle
+ m_objectDbMap.erase (hash);
+ }
+ else
+ {
+ _LOG_ERROR ("no db available for this file: " << hash);
+ }
}
diff --git a/src/fetcher.cc b/src/fetcher.cc
index 18e1484..fe75596 100644
--- a/src/fetcher.cc
+++ b/src/fetcher.cc
@@ -94,7 +94,7 @@
if (m_outOfOrderRecvSeqNo.find (m_minSendSeqNo+1) != m_outOfOrderRecvSeqNo.end ())
continue;
- _LOG_DEBUG (" >>> i " << Name (m_forwardingHint)(m_name)(m_minSendSeqNo+1));
+ _LOG_DEBUG (" >>> i (" << (m_minSendSeqNo+1) << ") " << Name (m_forwardingHint)(m_name)(m_minSendSeqNo+1));
// cout << ">>> " << m_minSendSeqNo+1 << endl;
m_ccnx->sendInterest (Name (m_forwardingHint)(m_name)(m_minSendSeqNo+1),
diff --git a/src/object-manager.cc b/src/object-manager.cc
index 848929e..c89fd55 100644
--- a/src/object-manager.cc
+++ b/src/object-manager.cc
@@ -96,6 +96,11 @@
return false;
}
+ if (!exists (file.parent_path ()))
+ {
+ create_directories (file.parent_path ());
+ }
+
fs::ofstream off (file, std::ios::out | std::ios::binary);
ObjectDb fileDb (m_folder, hashStr);