Debugging ActionLog. Corrections in dispatcher (filename in DB should be in a "generic" format)
diff --git a/ccnx/ccnx-common.h b/ccnx/ccnx-common.h
index 985965c..1824025 100644
--- a/ccnx/ccnx-common.h
+++ b/ccnx/ccnx-common.h
@@ -96,6 +96,15 @@
   return bytes;
 }
 
+template<class Msg>
+inline boost::shared_ptr<Msg>
+deserializeMsg (const Bytes &bytes)
+{
+  boost::shared_ptr<Msg> retval (new Msg ());
+  retval->ParseFromArray (head (bytes), bytes.size ());
+  return retval;
+}
+
 // --- Bytes operations end ---
 
 // Exceptions
diff --git a/log4cxx.properties b/log4cxx.properties
index 89f14d6..cd28cd6 100644
--- a/log4cxx.properties
+++ b/log4cxx.properties
@@ -1,5 +1,5 @@
 # Set root logger level to DEBUG and its only appender to A1.
-log4j.rootLogger=ERROR, A1
+log4j.rootLogger=TRACE, A1
 
 # A1 is set to be a ConsoleAppender.
 log4j.appender.A1=org.apache.log4j.ConsoleAppender
@@ -11,11 +11,11 @@
 #log4j.appender.A1.layout.ConversionPattern=%d{hh:mm:ss,SSS} %-14t %-14c  %m%n
 log4j.appender.A1.layout.ConversionPattern=%d{ss,SSS} %-5p %-12c  %m%n
 
-log4j.logger.Sync = DEBUG
-log4j.logger.Sync.Log = ERROR
+#log4j.logger.Sync = DEBUG
+#log4j.logger.Sync.Log = ERROR
 #log4j.logger.SyncInterestTable = TRACE
 #log4j.logger.AppDataFetch = TRACE
-log4j.logger.Test = TRACE
+#log4j.logger.Test = TRACE
 #log4j.logger.bgpparser=TRACE
 #log4j.logger.bgpparser.AttributeType=ERROR
 #log4j.logger.bgpparser.MRTCommonHeader=ERROR
diff --git a/src/action-log.cc b/src/action-log.cc
index 438879e..ed09796 100644
--- a/src/action-log.cc
+++ b/src/action-log.cc
@@ -77,7 +77,7 @@
             FROM ActionLog                                              \n\
             WHERE filename=NEW.filename AND                             \n\
                   version = NEW.version AND                             \n\
-                  s.device_name > NEW.device_name) IS NULL              \n\
+                  device_name > NEW.device_name) IS NULL                \n\
     BEGIN                                                               \n\
         SELECT apply_action (NEW.device_name, NEW.seq_no,               \
                              NEW.action,NEW.filename,NEW.file_hash,     \
@@ -106,8 +106,8 @@
 
 ActionLog::ActionLog (Ccnx::CcnxWrapperPtr ccnx, const boost::filesystem::path &path,
                       SyncLogPtr syncLog,
-                      const std::string &localName, const std::string &sharedFolder)
-  : DbHelper (path)
+                      const std::string &sharedFolder)
+  : DbHelper (path / ".chronoshare", "action-log.db")
   , m_syncLog (syncLog)
   , m_ccnx (ccnx)
   , m_sharedFolderName (sharedFolder)
@@ -162,11 +162,11 @@
 
 // local add action. remote action is extracted from content object
 void
-ActionLog::AddActionUpdate (const std::string &filename,
-                            const Hash &hash,
-                            time_t wtime,
-                            int mode,
-                            int seg_num)
+ActionLog::AddLocalActionUpdate (const std::string &filename,
+                                 const Hash &hash,
+                                 time_t wtime,
+                                 int mode,
+                                 int seg_num)
 {
   sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
 
@@ -188,10 +188,12 @@
                                 "parent_device_name, parent_seq_no, "
                                 "action_name, action_content_object) "
                                 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
-                                "        ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,"
+                                "        ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,?, "
                                 "        ?, ?, "
                                 "        ?, ?);", -1, &stmt, 0);
 
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
+
   if (res != SQLITE_OK)
     {
       BOOST_THROW_EXCEPTION (Error::Db ()
@@ -199,7 +201,6 @@
                              );
     }
 
-
   sqlite3_bind_blob  (stmt, 1, device_name->buf (), device_name->length (), SQLITE_TRANSIENT);
   sqlite3_bind_int64 (stmt, 2, seq_no);
   sqlite3_bind_int   (stmt, 3, 0);
@@ -215,7 +216,7 @@
   sqlite3_bind_int   (stmt, 11, mode);
   sqlite3_bind_int   (stmt, 12, seg_num);
 
-  if (parent_device_name->length () > 0 && parent_seq_no > 0)
+  if (parent_device_name && parent_seq_no > 0)
     {
       sqlite3_bind_blob (stmt, 13, parent_device_name->buf (), parent_device_name->length (), SQLITE_TRANSIENT);
       sqlite3_bind_int64 (stmt, 14, parent_seq_no);
@@ -233,7 +234,7 @@
   item.set_mode (mode);
   item.set_seg_num (seg_num);
 
-  if (parent_device_name->length () > 0 && parent_seq_no > 0)
+  if (parent_device_name && parent_seq_no > 0)
     {
       // cout << Name (*parent_device_name) << endl;
 
@@ -246,30 +247,35 @@
   string item_msg;
   item.SerializeToString (&item_msg);
   Name actionName = Name (m_syncLog->GetLocalName ())("action")(m_sharedFolderName)(seq_no);
+  _LOG_DEBUG ("ActionName: " << actionName);
 
   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);
+  _LOG_DEBUG (" >>>>>>> " << namePtr->buf () << " " << namePtr->length ());
+
+  sqlite3_bind_blob (stmt, 15, namePtr->buf (), namePtr->length (), SQLITE_TRANSIENT);
+  sqlite3_bind_blob (stmt, 16, head (actionData), actionData.size (), SQLITE_TRANSIENT);
 
   sqlite3_step (stmt);
 
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK && sqlite3_errcode (m_db) != SQLITE_ROW, sqlite3_errmsg (m_db));
+
   sqlite3_finalize (stmt);
 
   sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
 }
 
-void
-ActionLog::AddActionMove (const std::string &oldFile, const std::string &newFile)
-{
-  // not supported yet
-  BOOST_THROW_EXCEPTION (Error::Db ()
-                         << errmsg_info_str ("Move operation is not yet supported"));
-}
+// void
+// ActionLog::AddActionMove (const std::string &oldFile, const std::string &newFile)
+// {
+//   // not supported yet
+//   BOOST_THROW_EXCEPTION (Error::Db ()
+//                          << errmsg_info_str ("Move operation is not yet supported"));
+// }
 
 void
-ActionLog::AddActionDelete (const std::string &filename)
+ActionLog::AddLocalActionDelete (const std::string &filename)
 {
   sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
 
@@ -281,7 +287,7 @@
   sqlite3_int64 action_time = time (0);
 
   tie (version, parent_device_name, parent_seq_no) = GetLatestActionForFile (filename);
-  if (parent_device_name->length () == 0) // no records exist or file was already deleted
+  if (!parent_device_name) // no records exist or file was already deleted
     {
       sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
       return;
@@ -330,6 +336,8 @@
 
   sqlite3_step (stmt);
 
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK && sqlite3_errcode (m_db) != SQLITE_ROW, sqlite3_errmsg (m_db));
+
   // cout << Ccnx::Name (parent_device_name) << endl;
 
   // assign name to the action, serialize action, and create content object
@@ -340,6 +348,84 @@
 }
 
 
+PcoPtr
+ActionLog::LookupActionPco (const Ccnx::Name &deviceName, sqlite3_int64 seqno)
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT action_content_object FROM ActionLog WHERE device_name=? AND seq_no=?", -1, &stmt, 0);
+
+  CcnxCharbufPtr name = deviceName.toCcnxCharbuf ();
+
+  sqlite3_bind_blob  (stmt, 1, name->buf (), name->length (), SQLITE_STATIC);
+  sqlite3_bind_int64 (stmt, 2, seqno);
+
+  PcoPtr retval;
+  if (sqlite3_step (stmt) == SQLITE_ROW)
+    {
+      // _LOG_DEBUG (sqlite3_column_blob (stmt, 0) << ", " << sqlite3_column_bytes (stmt, 0));
+      retval = make_shared<ParsedContentObject> (reinterpret_cast<const unsigned char *> (sqlite3_column_blob (stmt, 0)), sqlite3_column_bytes (stmt, 0));
+    }
+  else
+    {
+      _LOG_TRACE ("No action found for deviceName [" << deviceName << "] and seqno:" << seqno);
+    }
+  // _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK && sqlite3_errcode (m_db) != SQLITE_ROW, sqlite3_errmsg (m_db));
+  sqlite3_finalize (stmt);
+
+  return retval;
+}
+
+ActionItemPtr
+ActionLog::LookupAction (const Ccnx::Name &deviceName, sqlite3_int64 seqno)
+{
+  PcoPtr pco = LookupActionPco (deviceName, seqno);
+  if (!pco) return ActionItemPtr ();
+
+  ActionItemPtr action = deserializeMsg<ActionItem> (pco->content ());
+
+  return action;
+}
+
+Ccnx::PcoPtr
+ActionLog::LookupActionPco (const Ccnx::Name &actionName)
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT action_content_object FROM ActionLog WHERE action_name=?", -1, &stmt, 0);
+
+  _LOG_DEBUG (actionName);
+  CcnxCharbufPtr name = actionName.toCcnxCharbuf ();
+
+  _LOG_DEBUG (" <<<<<<< " << name->buf () << " " << name->length ());
+
+  sqlite3_bind_blob  (stmt, 1, name->buf (), name->length (), SQLITE_STATIC);
+
+  PcoPtr retval;
+  if (sqlite3_step (stmt) == SQLITE_ROW)
+    {
+      // _LOG_DEBUG (sqlite3_column_blob (stmt, 0) << ", " << sqlite3_column_bytes (stmt, 0));
+      retval = make_shared<ParsedContentObject> (reinterpret_cast<const unsigned char *> (sqlite3_column_blob (stmt, 0)), sqlite3_column_bytes (stmt, 0));
+    }
+  else
+    {
+      _LOG_TRACE ("No action found for name: " << actionName);
+    }
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK && sqlite3_errcode (m_db) != SQLITE_ROW, sqlite3_errmsg (m_db));
+  sqlite3_finalize (stmt);
+
+  return retval;
+}
+
+ActionItemPtr
+ActionLog::LookupAction (const Ccnx::Name &actionName)
+{
+  PcoPtr pco = LookupActionPco (actionName);
+  if (!pco) return ActionItemPtr ();
+
+  ActionItemPtr action = deserializeMsg<ActionItem> (pco->content ());
+
+  return action;
+}
+
 void
 ActionLog::apply_action_xFun (sqlite3_context *context, int argc, sqlite3_value **argv)
 {
@@ -347,7 +433,7 @@
 
   if (argc != 10)
     {
-      sqlite3_result_error (context, "``apply_action'' expects 11 arguments", -1);
+      sqlite3_result_error (context, "``apply_action'' expects 10 arguments", -1);
       return;
     }
 
@@ -380,7 +466,7 @@
                           "file_atime=datetime(?, 'unixepoch'),"
                           "file_mtime=datetime(?, 'unixepoch'),"
                           "file_ctime=datetime(?, 'unixepoch'),"
-                          "file_chmod=? "
+                          "file_chmod=?, "
                           "file_seg_num=? "
                           "WHERE type=0 AND filename=?", -1, &stmt, 0);
 
@@ -406,9 +492,9 @@
         {
           sqlite3_stmt *stmt;
           sqlite3_prepare_v2 (the->m_db, "INSERT INTO FileState "
-                              "(type,filename,device_name,seq_no,file_hash,file_atime,file_mtime,file_ctime,file_chmod) "
+                              "(type,filename,device_name,seq_no,file_hash,file_atime,file_mtime,file_ctime,file_chmod,file_seg_num) "
                               "VALUES (0, ?, ?, ?, ?, "
-                              "datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?)", -1, &stmt, 0);
+                              "datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?, ?)", -1, &stmt, 0);
 
           sqlite3_bind_text  (stmt, 1, filename.c_str (), -1, SQLITE_TRANSIENT);
           sqlite3_bind_blob  (stmt, 2, device_name.buf (), device_name.length (), SQLITE_TRANSIENT);
@@ -418,6 +504,7 @@
           sqlite3_bind_int64 (stmt, 6, mtime);
           sqlite3_bind_int64 (stmt, 7, ctime);
           sqlite3_bind_int   (stmt, 8, mode);
+          sqlite3_bind_int   (stmt, 9, seg_num);
 
           sqlite3_step (stmt);
           _LOG_DEBUG_COND (sqlite3_errcode (the->m_db) != SQLITE_OK,
@@ -440,8 +527,12 @@
   sqlite3_result_null (context);
 }
 
+/**
+ * @todo Implement checking modification time and permissions
+ */
 bool
-ActionLog::KnownFileState(const std::string &filename, const Hash &hash)
+ActionLog::KnownFileState(const std::string &filename, const Hash &hash
+                          /*, time_t mtime, int chmod*/)
 {
   sqlite3_stmt *stmt;
   sqlite3_prepare_v2 (m_db, "SELECT * FROM FileState WHERE filename = ? AND file_hash = ?;", -1, &stmt, 0);
@@ -457,3 +548,18 @@
 
   return retval;
 }
+
+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;
+}
diff --git a/src/action-log.h b/src/action-log.h
index ff3b4aa..27d0869 100644
--- a/src/action-log.h
+++ b/src/action-log.h
@@ -24,37 +24,56 @@
 
 #include "db-helper.h"
 #include "sync-log.h"
+#include "action-item.pb.h"
+#include "ccnx-wrapper.h"
+#include "ccnx-pco.h"
 
 #include <boost/tuple/tuple.hpp>
-#include <action-item.pb.h>
-#include <ccnx-wrapper.h>
 
 class ActionLog;
 typedef boost::shared_ptr<ActionLog> ActionLogPtr;
+typedef boost::shared_ptr<ActionItem> ActionItemPtr;
 
 class ActionLog : public DbHelper
 {
 public:
   ActionLog (Ccnx::CcnxWrapperPtr ccnx, const boost::filesystem::path &path,
              SyncLogPtr syncLog,
-             const std::string &localName, const std::string &sharedFolder);
+             const std::string &sharedFolder);
 
   void
-  AddActionUpdate (const std::string &filename,
-                   const Hash &hash,
-                   time_t wtime,
-                   int mode,
-                   int seg_num);
+  AddLocalActionUpdate (const std::string &filename,
+                        const Hash &hash,
+                        time_t wtime,
+                        int mode,
+                        int seg_num);
+
+  // void
+  // AddActionMove (const std::string &oldFile, const std::string &newFile);
 
   void
-  AddActionMove (const std::string &oldFile, const std::string &newFile);
-
-  void
-  AddActionDelete (const std::string &filename);
+  AddLocalActionDelete (const std::string &filename);
 
   bool
   KnownFileState(const std::string &filename, const Hash &hash);
 
+  Ccnx::PcoPtr
+  LookupActionPco (const Ccnx::Name &deviceName, sqlite3_int64 seqno);
+
+  Ccnx::PcoPtr
+  LookupActionPco (const Ccnx::Name &actionName);
+
+  ActionItemPtr
+  LookupAction (const Ccnx::Name &deviceName, sqlite3_int64 seqno);
+
+  ActionItemPtr
+  LookupAction (const Ccnx::Name &actionName);
+
+public:
+  // for test purposes
+  sqlite3_int64
+  LogSize ();
+
 private:
   boost::tuple<sqlite3_int64 /*version*/, Ccnx::CcnxCharbufPtr /*device name*/, sqlite3_int64 /*seq_no*/>
   GetLatestActionForFile (const std::string &filename);
@@ -66,7 +85,7 @@
   SyncLogPtr m_syncLog;
 
   Ccnx::CcnxWrapperPtr m_ccnx;
-  Ccnx::Name m_sharedFolderName;
+  std::string m_sharedFolderName;
 };
 
 #endif // ACTION_LOG_H
diff --git a/src/db-helper.cc b/src/db-helper.cc
index d4c360e..ac63cdf 100644
--- a/src/db-helper.cc
+++ b/src/db-helper.cc
@@ -35,16 +35,15 @@
     PRAGMA foreign_keys = ON;      \
 ";
 
-DbHelper::DbHelper (const fs::path &path)
+DbHelper::DbHelper (const fs::path &path, const std::string &dbname)
 {
-  fs::path chronoshareDirectory = path / ".chronoshare";
-  fs::create_directories (chronoshareDirectory);
+  fs::create_directories (path);
 
-  int res = sqlite3_open((chronoshareDirectory / "state.db").c_str (), &m_db);
+  int res = sqlite3_open((path / dbname).c_str (), &m_db);
   if (res != SQLITE_OK)
     {
       BOOST_THROW_EXCEPTION (Error::Db ()
-                             << errmsg_info_str ("Cannot open/create dabatabase: [" + (chronoshareDirectory / "state.db").string () + "]"));
+                             << errmsg_info_str ("Cannot open/create dabatabase: [" + (path / dbname).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 a32df64..24f8c3f 100644
--- a/src/db-helper.h
+++ b/src/db-helper.h
@@ -30,14 +30,14 @@
 #include "hash-helper.h"
 #include <boost/filesystem.hpp>
 
-typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str; 
+typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
 
 class DbHelper
 {
 public:
-  DbHelper (const boost::filesystem::path &path);
+  DbHelper (const boost::filesystem::path &path, const std::string &dbname);
   virtual ~DbHelper ();
-  
+
 private:
   static void
   hash_xStep (sqlite3_context *context, int argc, sqlite3_value **argv);
diff --git a/src/dispatcher.cc b/src/dispatcher.cc
index d48bb43..bdcc469 100644
--- a/src/dispatcher.cc
+++ b/src/dispatcher.cc
@@ -39,7 +39,7 @@
            , m_sharedFolder(sharedFolder)
 {
   m_syncLog = make_shared<SyncLog>(path, localUserName);
-  m_actionLog = make_shared<ActionLog>(m_ccnx, path, m_syncLog, localUserName, sharedFolder);
+  m_actionLog = make_shared<ActionLog>(m_ccnx, path, m_syncLog, sharedFolder);
 
   Name syncPrefix(BROADCAST_DOMAIN + sharedFolder);
   m_core = new SyncCore (m_syncLog, localUserName, localPrefix, syncPrefix,
@@ -102,7 +102,7 @@
       if (filesystem::exists(absolutePath))
       {
         HashPtr hash = Hash::FromFileContent(absolutePath);
-        if (m_actionLog->KnownFileState(relativeFilePath.string(), *hash))
+        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
@@ -112,13 +112,16 @@
         else
         {
           uintmax_t fileSize = filesystem::file_size(absolutePath);
-          int seg_num = fileSize / MAX_FILE_SEGMENT_SIZE + ((fileSize % MAX_FILE_SEGMENT_SIZE == 0) ? 0 : 1);
-          time_t wtime = filesystem::last_write_time(absolutePath);
-          filesystem::file_status stat = filesystem::status(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->AddActionUpdate (relativeFilePath.string(), *hash, wtime, mode, seg_num);
+
+          m_actionLog->AddLocalActionUpdate (relativeFilePath.generic_string(), *hash, wtime, mode, seg_num);
           // publish the file
-          m_objectManager.localFileToObjects(relativeFilePath, m_localUserName);
+
           // notify SyncCore to propagate the change
           m_core->localStateChanged();
         }
@@ -131,7 +134,7 @@
     }
     case DELETE:
     {
-      m_actionLog->AddActionDelete (relativeFilePath.string());
+      m_actionLog->AddLocalActionDelete (relativeFilePath.generic_string());
       // notify SyncCore to propagate the change
       m_core->localStateChanged();
       break;
diff --git a/src/object-db.cc b/src/object-db.cc
index 0d1a2a6..2243b99 100644
--- a/src/object-db.cc
+++ b/src/object-db.cc
@@ -24,6 +24,9 @@
 #include <boost/make_shared.hpp>
 #include "db-helper.h"
 #include <sys/stat.h>
+#include "logging.h"
+
+INIT_LOGGER ("Object.Db");
 
 using namespace std;
 using namespace Ccnx;
@@ -46,7 +49,7 @@
 {
   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)
     {
@@ -54,7 +57,7 @@
                              << 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
 
@@ -64,7 +67,7 @@
     {
       // std::cerr << "DEBUG: " << errmsg << std::endl;
       sqlite3_free (errmsg);
-    }  
+    }
 }
 
 bool
@@ -89,16 +92,15 @@
           int countAll = sqlite3_column_int (stmt, 0);
           int countNonNull = sqlite3_column_int (stmt, 1);
 
-          cout << countAll << ", " << countNonNull << endl;
+          _LOG_DEBUG ("Total segments: " << countAll << ", non-empty segments: " << countNonNull);
 
           if (countAll > 0 && countAll==countNonNull)
             {
-              cout << "2" << endl;
               retval = true;
             }
         }
 
-      sqlite3_finalize (stmt);      
+      sqlite3_finalize (stmt);
     }
 
   sqlite3_close (db);
@@ -123,8 +125,8 @@
                       "(device_name, segment, content_object) "
                       "VALUES (?, ?, ?)", -1, &stmt, 0);
 
-  cout << deviceName << endl;
-  
+  _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_TRANSIENT);
   sqlite3_bind_int64 (stmt, 2, segment);
@@ -145,7 +147,7 @@
   sqlite3_bind_int64 (stmt, 2, segment);
 
   BytesPtr ret;
-  
+
   int res = sqlite3_step (stmt);
   if (res == SQLITE_ROW)
     {
@@ -165,13 +167,13 @@
 // ObjectDb::getNumberOfSegments (const Ccnx::Name &deviceName)
 // {
 //   sqlite3_stmt *stmt;
-//   sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM File WHERE device_name=?", -1, &stmt, 0); 
+//   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; 
+//       retval = true;
 //     }
 //   sqlite3_finalize (stmt);
 
diff --git a/src/object-manager.cc b/src/object-manager.cc
index bb19842..f822120 100644
--- a/src/object-manager.cc
+++ b/src/object-manager.cc
@@ -24,6 +24,7 @@
 #include "ccnx-common.h"
 #include "ccnx-pco.h"
 #include "object-db.h"
+#include "logging.h"
 
 #include <sys/stat.h>
 
@@ -32,6 +33,8 @@
 #include <boost/throw_exception.hpp>
 #include <boost/filesystem/fstream.hpp>
 
+INIT_LOGGER ("Object.Manager");
+
 using namespace Ccnx;
 using namespace boost;
 using namespace std;
@@ -50,7 +53,7 @@
 {
 }
 
-HashPtr
+boost::tuple<HashPtr /*object-db name*/, size_t /* number of segments*/>
 ObjectManager::localFileToObjects (const fs::path &file, const Ccnx::Name &deviceName)
 {
   HashPtr fileHash = Hash::FromFileContent (file);
@@ -74,7 +77,7 @@
       segment ++;
     }
 
-  return fileHash;
+  return make_tuple (fileHash, segment);
 }
 
 bool
@@ -83,8 +86,7 @@
   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
+      _LOG_ERROR ("ObjectDb for [" << m_folder << ", " << deviceName << ", " << hashStr << "] does not exist or not all segments are available");
       return false;
     }
 
diff --git a/src/object-manager.h b/src/object-manager.h
index f0cd6e6..ff26f30 100644
--- a/src/object-manager.h
+++ b/src/object-manager.h
@@ -26,6 +26,7 @@
 #include <ccnx-wrapper.h>
 #include <hash-helper.h>
 #include <boost/filesystem.hpp>
+#include <boost/tuple/tuple.hpp>
 
 // everything related to managing object files
 
@@ -35,12 +36,12 @@
   ObjectManager (Ccnx::CcnxWrapperPtr ccnx, const boost::filesystem::path &folder);
   virtual ~ObjectManager ();
 
-  HashPtr
+  boost::tuple<HashPtr /*object-db name*/, size_t /* number of segments*/>
   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;
diff --git a/src/sync-log.cc b/src/sync-log.cc
index 5623a83..671162e 100644
--- a/src/sync-log.cc
+++ b/src/sync-log.cc
@@ -97,8 +97,8 @@
 ";
 
 
-SyncLog::SyncLog (const boost::filesystem::path &path, const std::string &localName)
-  : DbHelper (path)
+SyncLog::SyncLog (const boost::filesystem::path &path, const Ccnx::Name &localName)
+  : DbHelper (path / ".chronoshare", "sync-log.db")
   , m_localName (localName)
 {
   sqlite3_exec (m_db, INIT_DATABASE.c_str (), NULL, NULL, NULL);
@@ -154,9 +154,11 @@
   if (sqlite3_step (stmt_seq) != SQLITE_ROW)
     {
       BOOST_THROW_EXCEPTION (Error::Db ()
-                             << errmsg_info_str ("Impossible thing in ActionLog::AddActionUpdate"));
+                             << errmsg_info_str ("Impossible thing in SyncLog::GetNextLocalSeqNo"));
     }
 
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
+
   sqlite3_int64 seq_no = sqlite3_column_int64 (stmt_seq, 0) + 1;
   sqlite3_finalize (stmt_seq);
 
@@ -328,6 +330,9 @@
       BOOST_THROW_EXCEPTION (Error::Db ()
                              << errmsg_info_str ("Some error with UpdateDeviceSeqNo (id)"));
     }
+
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
+
   sqlite3_finalize (stmt);
 }
 
@@ -513,3 +518,19 @@
 
   return seq;
 }
+
+sqlite3_int64
+SyncLog::LogSize ()
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM SyncLog", -1, &stmt, 0);
+
+  sqlite3_int64 retval = -1;
+  if (sqlite3_step (stmt) == SQLITE_ROW)
+  {
+    retval = sqlite3_column_int64 (stmt, 0);
+  }
+
+  return retval;
+}
+
diff --git a/src/sync-log.h b/src/sync-log.h
index 4d51aed..7aed587 100644
--- a/src/sync-log.h
+++ b/src/sync-log.h
@@ -33,7 +33,7 @@
 class SyncLog : public DbHelper
 {
 public:
-  SyncLog (const boost::filesystem::path &path, const std::string &localName);
+  SyncLog (const boost::filesystem::path &path, const Ccnx::Name &localName);
 
   /**
    * @brief Get local username
@@ -86,11 +86,13 @@
   sqlite3_int64
   SeqNo(const Ccnx::Name &name);
 
+  sqlite3_int64
+  LogSize ();
+
 protected:
   void
   UpdateDeviceSeqNo (sqlite3_int64 deviceId, sqlite3_int64 seqNo);
 
-
 protected:
   Ccnx::Name m_localName;
 
diff --git a/test/test-action-log.cc b/test/test-action-log.cc
new file mode 100644
index 0000000..efa485f
--- /dev/null
+++ b/test/test-action-log.cc
@@ -0,0 +1,121 @@
+/* -*- 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 <boost/test/unit_test.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include "logging.h"
+#include "action-log.h"
+
+#include <unistd.h>
+#include <iostream>
+#include <boost/filesystem.hpp>
+#include <boost/make_shared.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace Ccnx;
+namespace fs = boost::filesystem;
+
+BOOST_AUTO_TEST_SUITE(TestActionLog)
+
+BOOST_AUTO_TEST_CASE (ActionLogTest)
+{
+  INIT_LOGGERS ();
+
+  Name localName ("/alex");
+
+  fs::path tmpdir = fs::unique_path (fs::temp_directory_path () / "%%%%-%%%%-%%%%-%%%%");
+  SyncLogPtr syncLog = make_shared<SyncLog> (tmpdir, localName);
+  CcnxWrapperPtr ccnx = make_shared<CcnxWrapper> ();
+
+  ActionLogPtr actionLog = make_shared<ActionLog> (ccnx, tmpdir, syncLog, "top-secret");
+
+// const std::string &filename,
+//                    const Hash &hash,
+//                    time_t wtime,
+//                    int mode,
+//                    int seg_num
+  BOOST_CHECK_EQUAL (syncLog->SeqNo (localName), 0);
+
+  BOOST_CHECK_EQUAL (syncLog->LogSize (), 0);
+  BOOST_CHECK_EQUAL (actionLog->LogSize (), 0);
+
+  actionLog->AddLocalActionUpdate ("file.txt", *Hash::FromString ("2ff304769cdb0125ac039e6fe7575f8576dceffc62618a431715aaf6eea2bf1c"),
+                              time (NULL), 0755, 10);
+
+  BOOST_CHECK_EQUAL (syncLog->SeqNo (localName), 1);
+  BOOST_CHECK_EQUAL (syncLog->LogSize (), 0);
+  BOOST_CHECK_EQUAL (actionLog->LogSize (), 1);
+
+  HashPtr hash = syncLog->RememberStateInStateLog ();
+  BOOST_CHECK_EQUAL (syncLog->LogSize (), 1);
+  BOOST_CHECK_EQUAL (lexical_cast<string> (*hash), "3410477233f98d6c3f9a6f8da24494bf5a65e1a7c9f4f66b228128bd4e020558");
+
+  PcoPtr pco = actionLog->LookupActionPco (localName, 0);
+  BOOST_CHECK_EQUAL ((bool)pco, false);
+
+  pco = actionLog->LookupActionPco (localName, 1);
+  BOOST_CHECK_EQUAL ((bool)pco, true);
+
+  BOOST_CHECK_EQUAL (pco->name (), "/alex/action/top-secret/%00%01");
+
+  ActionItemPtr action = actionLog->LookupAction (Name ("/alex/action/top-secret")(0));
+  BOOST_CHECK_EQUAL ((bool)action, false);
+
+  action = actionLog->LookupAction (Name ("/alex/action/top-secret")(1));
+  BOOST_CHECK_EQUAL ((bool)action, true);
+
+  BOOST_CHECK_EQUAL (action->version (), 0);
+  BOOST_CHECK_EQUAL (action->action (), 0);
+
+  BOOST_CHECK_EQUAL (action->filename (), "file.txt");
+  BOOST_CHECK_EQUAL (action->seg_num (), 10);
+  BOOST_CHECK_EQUAL (action->file_hash ().size (), 32);
+  BOOST_CHECK_EQUAL (action->mode (), 0755);
+
+  BOOST_CHECK_EQUAL (action->has_parent_device_name (), false);
+  BOOST_CHECK_EQUAL (action->has_parent_seq_no (), false);
+
+  actionLog->AddLocalActionUpdate ("file.txt", *Hash::FromString ("2ff304769cdb0125ac039e6fe7575f8576dceffc62618a431715aaf6eea2bf1c"),
+                              time (NULL), 0755, 10);
+  BOOST_CHECK_EQUAL (syncLog->SeqNo (localName), 2);
+  BOOST_CHECK_EQUAL (syncLog->LogSize (), 1);
+  BOOST_CHECK_EQUAL (actionLog->LogSize (), 2);
+
+  action = actionLog->LookupAction (Name ("/alex"), 2);
+  BOOST_CHECK_EQUAL ((bool)action, true);
+
+  BOOST_CHECK_EQUAL (action->has_parent_device_name (), true);
+  BOOST_CHECK_EQUAL (action->has_parent_seq_no (), true);
+
+  BOOST_CHECK_EQUAL (action->parent_seq_no (), 1);
+  BOOST_CHECK_EQUAL (action->version (), 1);
+
+  remove_all (tmpdir);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+  // catch (boost::exception &err)
+  //   {
+  //     cout << *boost::get_error_info<errmsg_info_str> (err) << endl;
+  //   }
diff --git a/test/test-object-manager.cc b/test/test-object-manager.cc
index 78337b3..8f2ef2c 100644
--- a/test/test-object-manager.cc
+++ b/test/test-object-manager.cc
@@ -19,6 +19,7 @@
  *	   Zhenkai Zhu <zhenkai@cs.ucla.edu>
  */
 
+#include "logging.h"
 #include "object-manager.h"
 
 #include <boost/filesystem.hpp>
@@ -30,25 +31,31 @@
 #include <iostream>
 #include <iterator>
 
+INIT_LOGGER ("Test.ObjectManager");
+
 using namespace Ccnx;
 using namespace std;
 using namespace boost;
 namespace fs = boost::filesystem;
 
-BOOST_AUTO_TEST_SUITE(ObjectManagerTests)
+BOOST_AUTO_TEST_SUITE(TestObjectManager)
 
 BOOST_AUTO_TEST_CASE (ObjectManagerTest)
 {
+  INIT_LOGGERS ();
+
   fs::path tmpdir = fs::unique_path (fs::temp_directory_path () / "%%%%-%%%%-%%%%-%%%%");
-  cout << tmpdir << endl;
+  _LOG_DEBUG ("tmpdir: " << tmpdir);
   Name deviceName ("/device");
-  
+
   CcnxWrapperPtr ccnx = make_shared<CcnxWrapper> ();
   ObjectManager manager (ccnx, tmpdir);
 
-  HashPtr hash = manager.localFileToObjects (fs::path("test") / "test-object-manager.cc", deviceName);
+  tuple<HashPtr,int> hash_semgents = manager.localFileToObjects (fs::path("test") / "test-object-manager.cc", deviceName);
 
-  bool ok = manager.objectsToLocalFile (deviceName, *hash, tmpdir / "test.cc");
+  BOOST_CHECK_EQUAL (hash_semgents.get<1> (), 3);
+
+  bool ok = manager.objectsToLocalFile (deviceName, *hash_semgents.get<0> (), tmpdir / "test.cc");
   BOOST_CHECK_EQUAL (ok, true);
 
   {
@@ -61,7 +68,7 @@
 
     BOOST_CHECK_EQUAL_COLLECTIONS (origFileI, eof, newFileI, eof);
   }
-  
+
   remove_all (tmpdir);
 }
 
diff --git a/test/test-sync-log.cc b/test/test-sync-log.cc
index 311f937..09443e9 100644
--- a/test/test-sync-log.cc
+++ b/test/test-sync-log.cc
@@ -42,7 +42,7 @@
   INIT_LOGGERS ();
 
   fs::path tmpdir = fs::unique_path (fs::temp_directory_path () / "%%%%-%%%%-%%%%-%%%%");
-  SyncLog db (tmpdir, "/alex");
+  SyncLog db (tmpdir, Name ("/alex"));
 
   HashPtr hash = db.RememberStateInStateLog ();
   // should be empty