Merge remote-tracking branch 'origin/master'
diff --git a/ccnx/ccnx-common.h b/ccnx/ccnx-common.h
index 985965c..6d17116 100644
--- a/ccnx/ccnx-common.h
+++ b/ccnx/ccnx-common.h
@@ -40,10 +40,9 @@
 #include <utility>
 #include <string.h>
 
-using namespace std;
 namespace Ccnx {
-typedef vector<unsigned char> Bytes;
-typedef vector<string>Comps;
+typedef std::vector<unsigned char> Bytes;
+typedef std::vector<std::string>Comps;
 
 typedef boost::shared_ptr<Bytes> BytesPtr;
 
@@ -90,12 +89,21 @@
 inline BytesPtr
 serializeMsg(const Msg &msg)
 {
-  int size = msg->ByteSize ();
+  int size = msg.ByteSize ();
   BytesPtr bytes (new Bytes (size));
-  msg->SerializeToArray (head(*bytes), size);
+  msg.SerializeToArray (head(*bytes), size);
   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/ccnx/ccnx-name.cpp b/ccnx/ccnx-name.cpp
index 848019a..cc34c23 100644
--- a/ccnx/ccnx-name.cpp
+++ b/ccnx/ccnx-name.cpp
@@ -24,8 +24,9 @@
 #include <ctype.h>
 #include <boost/algorithm/string/join.hpp>
 
+using namespace std;
+
 namespace Ccnx{
-CcnxCharbufPtr CcnxCharbuf::Null;
 
 void
 CcnxCharbuf::init(ccn_charbuf *buf)
@@ -57,6 +58,14 @@
   init(other.m_buf);
 }
 
+CcnxCharbuf::CcnxCharbuf(const void *buf, size_t length)
+{
+  m_buf = ccn_charbuf_create ();
+  ccn_charbuf_reserve (m_buf, length);
+  memcpy (m_buf->buf, buf, length);
+  m_buf->length = length;
+}
+
 CcnxCharbuf::~CcnxCharbuf()
 {
   ccn_charbuf_destroy(&m_buf);
@@ -126,6 +135,41 @@
   ccn_indexbuf_destroy(&idx);
 }
 
+Name::Name (const CcnxCharbuf &buf)
+{
+  ccn_indexbuf *idx = ccn_indexbuf_create();
+  ccn_name_split (buf.getBuf (), idx);
+
+  const unsigned char *compPtr = NULL;
+  size_t size = 0;
+  int i = 0;
+  while (ccn_name_comp_get(buf.getBuf ()->buf, idx, i, &compPtr, &size) == 0)
+    {
+      Bytes comp;
+      readRaw (comp, compPtr, size);
+      m_comps.push_back(comp);
+      i++;
+    }
+  ccn_indexbuf_destroy(&idx);
+}
+
+Name::Name (const ccn_charbuf *buf)
+{
+  ccn_indexbuf *idx = ccn_indexbuf_create();
+  ccn_name_split (buf, idx);
+
+  const unsigned char *compPtr = NULL;
+  size_t size = 0;
+  int i = 0;
+  while (ccn_name_comp_get(buf->buf, idx, i, &compPtr, &size) == 0)
+    {
+      Bytes comp;
+      readRaw (comp, compPtr, size);
+      m_comps.push_back(comp);
+      i++;
+    }
+  ccn_indexbuf_destroy(&idx);
+}
 
 Name &
 Name::operator=(const Name &other)
diff --git a/ccnx/ccnx-name.h b/ccnx/ccnx-name.h
index 92c3054..b32c419 100644
--- a/ccnx/ccnx-name.h
+++ b/ccnx/ccnx-name.h
@@ -37,12 +37,15 @@
   CcnxCharbuf();
   CcnxCharbuf(ccn_charbuf *buf);
   CcnxCharbuf(const CcnxCharbuf &other);
+  CcnxCharbuf(const void *buf, size_t length);
   ~CcnxCharbuf();
 
   // expose internal data structure, use with caution!!
   ccn_charbuf *
   getBuf() { return m_buf; }
-  static CcnxCharbufPtr Null;
+
+  const ccn_charbuf *
+  getBuf() const { return m_buf; }
 
   const unsigned char *
   buf () const
@@ -61,17 +64,19 @@
 
 
 struct NameException:
-  virtual boost::exception, virtual exception {};
+    virtual boost::exception, virtual std::exception {};
 
 class Name
 {
 public:
   Name();
-  Name(const string &name);
-  Name(const vector<Bytes> &comps);
+  Name(const std::string &name);
+  Name(const std::vector<Bytes> &comps);
   Name(const Name &other);
   Name(const unsigned char *data, const ccn_indexbuf *comps);
   Name (const unsigned char *buf, const size_t length);
+  Name (const CcnxCharbuf &buf);
+  Name (const ccn_charbuf *buf);
   virtual ~Name() {}
 
   CcnxCharbufPtr
@@ -86,7 +91,7 @@
   appendComp(const Bytes &comp);
 
   Name &
-  appendComp(const string &compStr);
+  appendComp(const std::string &compStr);
 
   Name &
   appendComp(const void *buf, size_t size);
@@ -114,39 +119,48 @@
   Bytes
   getComp(int index) const;
 
-  // return string format of the comp
+  // return std::string format of the comp
   // if all characters are printable, simply returns the string
   // if not, print the bytes in hex string format
-  string
+  std::string
   getCompAsString(int index) const;
 
   uint64_t
   getCompAsInt (int index) const;
 
+  inline std::string
+  getCompFromBackAsString(int index) const;
+
+  inline uint64_t
+  getCompFromBackAsInt (int index) const;
+
   Name
   getPartialName(int start, int n = -1) const;
 
-  string
+  inline Name
+  getPartialNameFromBack(int start, int n = -1) const;
+
+  std::string
   toString() const;
 
   Name &
   operator=(const Name &other);
 
   bool
-  operator==(const string &str) const;
+  operator==(const std::string &str) const;
 
   bool
-  operator!=(const string &str) const;
+  operator!=(const std::string &str) const;
 
   friend Name
   operator+(const Name &n1, const Name &n2);
 
-protected:
-  vector<Bytes> m_comps;
+private:
+  std::vector<Bytes> m_comps;
 };
 
-ostream&
-operator <<(ostream &os, const Name &name);
+std::ostream&
+operator <<(std::ostream &os, const Name &name);
 
 bool
 operator ==(const Name &n1, const Name &n2);
@@ -158,6 +172,24 @@
 operator <(const Name &n1, const Name &n2);
 
 
+std::string
+Name::getCompFromBackAsString(int index) const
+{
+  return getCompAsString (m_comps.size () - 1 - index);
+}
+
+uint64_t
+Name::getCompFromBackAsInt (int index) const
+{
+  return getCompAsInt (m_comps.size () - 1 - index);
+}
+
+Name
+Name::getPartialNameFromBack(int start, int n/* = -1*/) const
+{
+  return getPartialName (m_comps.size () - 1 - start, n);
+}
+
 
 } // Ccnx
 #endif
diff --git a/ccnx/ccnx-pco.h b/ccnx/ccnx-pco.h
index cecc763..cdb2a7e 100644
--- a/ccnx/ccnx-pco.h
+++ b/ccnx/ccnx-pco.h
@@ -48,6 +48,9 @@
   Name
   name() const;
 
+  inline const Bytes &
+  buf () const;
+
 private:
   void
   init(const unsigned char *data, size_t len);
@@ -58,6 +61,13 @@
   Bytes m_bytes;
 };
 
+const Bytes &
+ParsedContentObject::buf () const
+{
+  return m_bytes;
+}
+
+
 typedef boost::shared_ptr<ParsedContentObject> PcoPtr;
 
 }
diff --git a/ccnx/ccnx-selectors.cpp b/ccnx/ccnx-selectors.cpp
index 001c1b7..b349cc1 100644
--- a/ccnx/ccnx-selectors.cpp
+++ b/ccnx/ccnx-selectors.cpp
@@ -2,6 +2,8 @@
 #include "ccnx-common.h"
 #include <boost/lexical_cast.hpp>
 
+using namespace std;
+
 namespace Ccnx {
 
 Selectors::Selectors()
@@ -53,7 +55,7 @@
 {
   if (isEmpty())
   {
-    return CcnxCharbuf::Null;
+    return CcnxCharbufPtr ();
   }
   CcnxCharbufPtr ptr(new CcnxCharbuf());
   ccn_charbuf *cbuf = ptr->getBuf();
diff --git a/ccnx/ccnx-selectors.h b/ccnx/ccnx-selectors.h
index 420f33e..56e29b5 100644
--- a/ccnx/ccnx-selectors.h
+++ b/ccnx/ccnx-selectors.h
@@ -27,7 +27,7 @@
 namespace Ccnx {
 
 struct InterestSelectorException:
-  virtual boost::exception, virtual exception {};
+    virtual boost::exception, virtual std::exception {};
 
 class Selectors
 {
diff --git a/ccnx/ccnx-wrapper.cpp b/ccnx/ccnx-wrapper.cpp
index 7f2e567..a8c06a3 100644
--- a/ccnx/ccnx-wrapper.cpp
+++ b/ccnx/ccnx-wrapper.cpp
@@ -325,7 +325,7 @@
 
   CcnxCharbufPtr selectorsPtr = selectors.toCcnxCharbuf();
   ccn_charbuf *templ = NULL;
-  if (selectorsPtr != CcnxCharbuf::Null)
+  if (selectorsPtr)
   {
     templ = selectorsPtr->getBuf();
   }
diff --git a/ccnx/ccnx-wrapper.h b/ccnx/ccnx-wrapper.h
index cfd030b..c1c9b9b 100644
--- a/ccnx/ccnx-wrapper.h
+++ b/ccnx/ccnx-wrapper.h
@@ -94,7 +94,7 @@
   boost::thread m_thread;
   bool m_running;
   bool m_connected;
-  map<Name, InterestCallback> m_registeredInterests;
+  std::map<Name, InterestCallback> m_registeredInterests;
 };
 
 typedef boost::shared_ptr<CcnxWrapper> CcnxWrapperPtr;
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 5c4f592..becbfe3 100644
--- a/src/action-log.cc
+++ b/src/action-log.cc
@@ -22,6 +22,8 @@
 #include "action-log.h"
 #include "logging.h"
 
+#include <boost/make_shared.hpp>
+
 using namespace boost;
 using namespace std;
 using namespace Ccnx;
@@ -30,7 +32,7 @@
 
 const std::string INIT_DATABASE = "\
 CREATE TABLE ActionLog (                                                \n\
-    device_id   INTEGER NOT NULL,                                       \n\
+    device_name BLOB NOT NULL,                                          \n\
     seq_no      INTEGER NOT NULL,                                       \n\
                                                                         \n\
     action      CHAR(1) NOT NULL, /* 0 for \"update\", 1 for \"delete\". */ \n\
@@ -46,43 +48,38 @@
     file_chmod  INTEGER,                                                \n\
     file_seg_num INTEGER, /* NULL if action is \"delete\" */            \n\
                                                                         \n\
-    parent_device_id INTEGER,                                           \n\
-    parent_seq_no    INTEGER,                                           \n\
+    parent_device_name BLOB,                                            \n\
+    parent_seq_no      INTEGER,                                         \n\
                                                                         \n\
     action_name	     TEXT,                                              \n\
     action_content_object BLOB,                                         \n\
                                                                         \n\
-    PRIMARY KEY (device_id, seq_no),                                    \n\
+    PRIMARY KEY (device_name, seq_no),                                  \n\
                                                                         \n\
-    FOREIGN KEY (parent_device_id, parent_seq_no)                       \n\
-	REFERENCES ActionLog (device_id, seq_no)                        \n\
+    FOREIGN KEY (parent_device_name, parent_seq_no)                     \n\
+	REFERENCES ActionLog (device_name, seq_no)                      \n\
 	ON UPDATE RESTRICT                                              \n\
 	ON DELETE SET NULL                                              \n\
 );                                                                      \n\
                                                                         \n\
-CREATE INDEX ActionLog_filename_version ON ActionLog (filename,version);        \n\
-CREATE INDEX ActionLog_parent ON ActionLog (parent_device_id, parent_seq_no);   \n\
+CREATE INDEX ActionLog_filename_version ON ActionLog (filename,version);          \n\
+CREATE INDEX ActionLog_parent ON ActionLog (parent_device_name, parent_seq_no);   \n\
 CREATE INDEX ActionLog_action_name ON ActionLog (action_name);          \n\
                                                                         \n\
 CREATE TRIGGER ActionLogInsert_trigger                                  \n\
     AFTER INSERT ON ActionLog                                           \n\
     FOR EACH ROW                                                        \n\
-    WHEN (SELECT device_id                                              \n\
+    WHEN (SELECT device_name                                            \n\
             FROM ActionLog                                              \n\
             WHERE filename=NEW.filename AND                             \n\
                   version > NEW.version) IS NULL AND                    \n\
-         (SELECT a.device_id                                            \n\
-            FROM ActionLog a                                            \n\
-                LEFT JOIN SyncNodes s ON s.device_id=a.device_id        \n\
+         (SELECT device_name                                            \n\
+            FROM ActionLog                                              \n\
             WHERE filename=NEW.filename AND                             \n\
                   version = NEW.version AND                             \n\
-                  a.device_id != NEW.device_id AND                      \n\
-                  s.device_name > (SELECT device_name                   \n\
-                                    FROM SyncNodes                      \n\
-                                    WHERE device_id=NEW.device_id)) IS NULL      \n\
+                  device_name > NEW.device_name) IS NULL                \n\
     BEGIN                                                               \n\
-        SELECT apply_action ((SELECT device_name FROM SyncNodes where device_id=NEW.device_id), \
-                             NEW.device_id, NEW.seq_no,                 \
+        SELECT apply_action (NEW.device_name, NEW.seq_no,               \
                              NEW.action,NEW.filename,NEW.file_hash,     \
                              strftime('%s', NEW.file_atime),strftime('%s', NEW.file_mtime),strftime('%s', NEW.file_ctime), \
                              NEW.file_chmod, NEW.file_seg_num); /* function that applies action and adds record the FileState */  \n \
@@ -91,7 +88,7 @@
 CREATE TABLE FileState (                                                \n\
     type        INTEGER NOT NULL, /* 0 - newest, 1 - oldest */          \n\
     filename    TEXT NOT NULL,                                          \n\
-    device_id   INTEGER 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_atime  TIMESTAMP,                                              \n\
@@ -103,14 +100,14 @@
     PRIMARY KEY (type, filename)                                        \n\
 );                                                                      \n\
                                                                         \n\
-CREATE INDEX FileState_device_id_seq_no ON FileState (device_id, seq_no); \n\
+CREATE INDEX FileState_device_name_seq_no ON FileState (device_name, seq_no); \n\
 ";
 
 
 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)
@@ -128,14 +125,14 @@
     }
 }
 
-tuple<sqlite3_int64, sqlite3_int64, sqlite3_int64, string>
-ActionLog::GetExistingRecord (const std::string &filename)
+tuple<sqlite3_int64 /*version*/, Ccnx::CcnxCharbufPtr /*device name*/, sqlite3_int64 /*seq_no*/>
+ActionLog::GetLatestActionForFile (const std::string &filename)
 {
   // check if something already exists
   sqlite3_stmt *stmt;
-  int res = sqlite3_prepare_v2 (m_db, "SELECT a.version,a.device_id,a.seq_no,a.action,s.device_name "
-                                "FROM ActionLog a JOIN SyncNodes s ON s.device_id = a.device_id "
-                                "WHERE filename=? ORDER BY a.version DESC LIMIT 1", -1, &stmt, 0);
+  int res = sqlite3_prepare_v2 (m_db, "SELECT version,device_name,seq_no,action "
+                                "FROM ActionLog "
+                                "WHERE filename=? ORDER BY version DESC LIMIT 1", -1, &stmt, 0);
 
   if (res != SQLITE_OK)
     {
@@ -143,78 +140,68 @@
                              << errmsg_info_str ("Some error with GetExistingRecord"));
     }
 
-  // with parent with version number + 1
-  sqlite3_int64 version = 0;
-  sqlite3_int64 parent_device_id = -1;
+  sqlite3_int64 version = -1;
+  CcnxCharbufPtr parent_device_name;
   sqlite3_int64 parent_seq_no = -1;
-  string parent_device_name;
 
   sqlite3_bind_text (stmt, 1, filename.c_str (), filename.size (), SQLITE_STATIC);
   if (sqlite3_step (stmt) == SQLITE_ROW)
     {
-      version = sqlite3_column_int64 (stmt, 0) + 1;
+      version = sqlite3_column_int64 (stmt, 0);
 
       if (sqlite3_column_int (stmt, 3) == 0) // prevent "linking" if the file was previously deleted
         {
-          parent_device_id = sqlite3_column_int64 (stmt, 1);
+          parent_device_name = make_shared<CcnxCharbuf> (sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1));
           parent_seq_no = sqlite3_column_int64 (stmt, 2);
-          parent_device_name = string(reinterpret_cast<const char*> (sqlite3_column_blob (stmt, 4)), sqlite3_column_bytes (stmt, 4));
         }
     }
 
   sqlite3_finalize (stmt);
-  return make_tuple (version, parent_device_id, parent_seq_no, parent_device_name);
+  return make_tuple (version, parent_device_name, parent_seq_no);
 }
 
 // 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);
 
-  sqlite3_int64 seq_no = m_syncLog->GetNextLocalSeqNo ();
-  sqlite3_int64 version = 0;
-  sqlite3_int64 parent_device_id = -1;
-  string        parent_device_name;
-  sqlite3_int64 parent_seq_no = -1;
+  CcnxCharbufPtr device_name = m_syncLog->GetLocalName ().toCcnxCharbuf ();
+  sqlite3_int64  seq_no = m_syncLog->GetNextLocalSeqNo ();
+  sqlite3_int64  version;
+  CcnxCharbufPtr parent_device_name;
+  sqlite3_int64  parent_seq_no = -1;
 
-  sqlite3_int64 action_time = time (0);
+  sqlite3_int64  action_time = time (0);
 
-  tie (version, parent_device_id, parent_seq_no, parent_device_name) = GetExistingRecord (filename);
+  tie (version, parent_device_name, parent_seq_no) = GetLatestActionForFile (filename);
+  version ++;
 
   sqlite3_stmt *stmt;
   int res = sqlite3_prepare_v2 (m_db, "INSERT INTO ActionLog "
-                                "(device_id, seq_no, action, filename, version, action_timestamp, "
+                                "(device_name, seq_no, action, filename, version, action_timestamp, "
                                 "file_hash, file_atime, file_mtime, file_ctime, file_chmod, file_seg_num, "
-                                "parent_device_id, parent_seq_no, "
+                                "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);
 
-  // cout << "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) "
-  //                               "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
-  //                               "        ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,"
-  //   "        ?, ?)" << endl;
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
 
   if (res != SQLITE_OK)
     {
       BOOST_THROW_EXCEPTION (Error::Db ()
                              << errmsg_info_str (sqlite3_errmsg (m_db))
                              );
-                             // << errmsg_info_str ("Some error with prepare AddActionUpdate"));
     }
 
-
-  sqlite3_bind_int64 (stmt, 1, m_syncLog->GetLocalSyncNodeId ());
+  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);
   sqlite3_bind_text  (stmt, 4, filename.c_str (), filename.size (), SQLITE_TRANSIENT);
@@ -229,18 +216,11 @@
   sqlite3_bind_int   (stmt, 11, mode);
   sqlite3_bind_int   (stmt, 12, seg_num);
 
-  if (parent_device_id > 0 && parent_seq_no > 0)
+  if (parent_device_name && parent_seq_no > 0)
     {
-      sqlite3_bind_int64 (stmt, 13, parent_device_id);
+      sqlite3_bind_blob (stmt, 13, parent_device_name->buf (), parent_device_name->length (), SQLITE_TRANSIENT);
       sqlite3_bind_int64 (stmt, 14, parent_seq_no);
     }
-  else
-    {
-      sqlite3_bind_null (stmt, 13);
-      sqlite3_bind_null (stmt, 14);
-    }
-
-  // missing part: creating ContentObject for the action !!!
 
   ActionItem item;
   item.set_action (ActionItem::UPDATE);
@@ -254,12 +234,11 @@
   item.set_mode (mode);
   item.set_seg_num (seg_num);
 
-  if (parent_device_id > 0 && parent_seq_no > 0)
+  if (parent_device_name && parent_seq_no > 0)
     {
-      cout << Name (reinterpret_cast<const unsigned char *> (parent_device_name.c_str ()),
-                    parent_device_name.size ()) << endl;
+      // cout << Name (*parent_device_name) << endl;
 
-      item.set_parent_device_name (parent_device_name);
+      item.set_parent_device_name (parent_device_name->buf (), parent_device_name->length ());
       item.set_parent_seq_no (parent_seq_no);
     }
 
@@ -268,66 +247,72 @@
   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);
 
-  sqlite3_int64 version = 0;
-  sqlite3_int64 parent_device_id = -1;
-  string        parent_device_name;
-  sqlite3_int64 parent_seq_no = -1;
+  CcnxCharbufPtr device_name = m_syncLog->GetLocalName ().toCcnxCharbuf ();
+  sqlite3_int64  version;
+  CcnxCharbufPtr parent_device_name;
+  sqlite3_int64  parent_seq_no = -1;
 
   sqlite3_int64 action_time = time (0);
 
-  tie (version, parent_device_id, parent_seq_no, parent_device_name) = GetExistingRecord (filename);
-  if (parent_device_id < 0) // no records exist or file was already deleted
+  tie (version, parent_device_name, parent_seq_no) = GetLatestActionForFile (filename);
+  if (!parent_device_name) // no records exist or file was already deleted
     {
       sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
       return;
     }
+  version ++;
 
   sqlite3_int64 seq_no = m_syncLog->GetNextLocalSeqNo ();
 
   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, "
+                      "(device_name, seq_no, action, filename, version, action_timestamp, "
+                      "parent_device_name, parent_seq_no, "
                       "action_name, action_content_object) "
                       "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
                       "        ?, ?,"
                       "        ?, ?)", -1, &stmt, 0);
 
-  sqlite3_bind_int64 (stmt, 1, m_syncLog->GetLocalSyncNodeId ());
+  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, 1);
   sqlite3_bind_text  (stmt, 4, filename.c_str (), filename.size (), SQLITE_TRANSIENT);
   sqlite3_bind_int64 (stmt, 5, version);
   sqlite3_bind_int64 (stmt, 6, action_time);
 
-  sqlite3_bind_int64 (stmt, 7, parent_device_id);
+  sqlite3_bind_blob  (stmt, 7, parent_device_name->buf (), parent_device_name->length (), SQLITE_TRANSIENT);
   sqlite3_bind_int64 (stmt, 8, parent_seq_no);
 
 
@@ -336,7 +321,7 @@
   item.set_filename (filename);
   item.set_version (version);
   item.set_timestamp (action_time);
-  item.set_parent_device_name (parent_device_name);
+  item.set_parent_device_name (parent_device_name->buf (), parent_device_name->length ());
   item.set_parent_seq_no (parent_seq_no);
 
   string item_msg;
@@ -351,8 +336,9 @@
 
   sqlite3_step (stmt);
 
-  // cout << Ccnx::Name (reinterpret_cast<const unsigned char *> (parent_device_name.c_str ()),
-  //                     parent_device_name.size ()) << endl;
+  _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
 
@@ -362,53 +348,226 @@
 }
 
 
+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::AddRemoteAction (const Ccnx::Name &deviceName, sqlite3_int64 seqno, Ccnx::PcoPtr actionPco)
+{
+  if (!actionPco)
+    {
+      BOOST_THROW_EXCEPTION (Error::ActionLog () << errmsg_info_str ("actionPco is not valid"));
+    }
+  ActionItemPtr action = deserializeMsg<ActionItem> (actionPco->content ());
+
+  if (!action)
+    {
+      BOOST_THROW_EXCEPTION (Error::ActionLog () << errmsg_info_str ("action cannot be decoded"));
+    }
+
+  sqlite3_stmt *stmt;
+  int res = sqlite3_prepare_v2 (m_db, "INSERT INTO ActionLog "
+                                "(device_name, seq_no, action, filename, version, action_timestamp, "
+                                "file_hash, file_atime, file_mtime, file_ctime, file_chmod, file_seg_num, "
+                                "parent_device_name, parent_seq_no, "
+                                "action_name, action_content_object) "
+                                "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
+                                "        ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,?, "
+                                "        ?, ?, "
+                                "        ?, ?);", -1, &stmt, 0);
+
+  CcnxCharbufPtr device_name = deviceName.toCcnxCharbuf ();
+  sqlite3_bind_blob  (stmt, 1, device_name->buf (), device_name->length (), SQLITE_STATIC);
+  sqlite3_bind_int64 (stmt, 2, seqno);
+
+  sqlite3_bind_int   (stmt, 3, action->action ());
+  sqlite3_bind_text  (stmt, 4, action->filename ().c_str (), action->filename ().size (), SQLITE_STATIC);
+  sqlite3_bind_int64 (stmt, 5, action->version ());
+  sqlite3_bind_int64 (stmt, 6, action->timestamp ());
+
+  if (action->action () == ActionItem::UPDATE)
+    {
+      sqlite3_bind_blob  (stmt, 7, action->file_hash ().c_str (), action->file_hash ().size (), SQLITE_STATIC);
+
+      // sqlite3_bind_int64 (stmt, 8, atime); // NULL
+      sqlite3_bind_int64 (stmt, 9, action->mtime ());
+      // sqlite3_bind_int64 (stmt, 10, ctime); // NULL
+
+      sqlite3_bind_int   (stmt, 11, action->mode ());
+      sqlite3_bind_int   (stmt, 12, action->seg_num ());
+    }
+
+  if (action->has_parent_device_name ())
+    {
+      sqlite3_bind_blob (stmt, 13, action->parent_device_name ().c_str (), action->parent_device_name ().size (), SQLITE_TRANSIENT);
+      sqlite3_bind_int64 (stmt, 14, action->parent_seq_no ());
+    }
+
+  Name actionName = Name (deviceName)("action")(m_sharedFolderName)(seqno);
+  CcnxCharbufPtr namePtr = actionName.toCcnxCharbuf ();
+
+  sqlite3_bind_blob (stmt, 15, namePtr->buf (), namePtr->length (), SQLITE_STATIC);
+  sqlite3_bind_blob (stmt, 16, head (actionPco->buf ()), actionPco->buf ().size (), SQLITE_STATIC);
+  sqlite3_step (stmt);
+
+  // if action needs to be applied to file state, the trigger will take care of it
+
+  _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK && sqlite3_errcode (m_db) != SQLITE_ROW, sqlite3_errmsg (m_db));
+
+  sqlite3_finalize (stmt);
+}
+
+void
+ActionLog::AddRemoteAction (Ccnx::PcoPtr actionPco)
+{
+  Name name = actionPco->name ();
+  // <device_name>/"action"/<shared_folder_name_one_component>/<seqno>
+
+  uint64_t seqno = name.getCompFromBackAsInt (0);
+  string sharedFolder = name.getCompFromBackAsString (1);
+
+  if (sharedFolder != m_sharedFolderName)
+    {
+      BOOST_THROW_EXCEPTION (Error::ActionLog () << errmsg_info_str ("Action doesn't belong to this shared folder"));
+    }
+
+  string action = name.getCompFromBackAsString (2);
+
+  if (action != "action")
+    {
+      BOOST_THROW_EXCEPTION (Error::ActionLog () << errmsg_info_str ("not an action"));
+    }
+  Name deviceName = name.getPartialName (0, name.size ()-3);
+
+  _LOG_DEBUG ("From [" << name << "] extracted deviceName: " << deviceName << ", sharedFolder: " << sharedFolder << ", seqno: " << seqno);
+
+  AddRemoteAction (deviceName, seqno, actionPco);
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+// SHOULD BE MOVED TO SEPARATE FILESTATE CLASS "EVENTUALLY"
+///////////////////////////////////////////////////////////////////////////////////
+
 void
 ActionLog::apply_action_xFun (sqlite3_context *context, int argc, sqlite3_value **argv)
 {
   ActionLog *the = reinterpret_cast<ActionLog*> (sqlite3_user_data (context));
 
-  if (argc != 11)
+  if (argc != 10)
     {
-      sqlite3_result_error (context, "``apply_action'' expects 11 arguments", -1);
+      sqlite3_result_error (context, "``apply_action'' expects 10 arguments", -1);
       return;
     }
 
-  // cout << "apply_function called with " << argc << endl;
+  CcnxCharbuf device_name (sqlite3_value_blob (argv[0]), sqlite3_value_bytes (argv[0]));
+  sqlite3_int64 seq_no    = sqlite3_value_int64 (argv[1]);
+  int action         = sqlite3_value_int  (argv[2]);
+  string filename    = reinterpret_cast<const char*> (sqlite3_value_text (argv[3]));
 
-  // cout << "device_name: " << sqlite3_value_text (argv[0]) << endl;
-  // cout << "action: " << sqlite3_value_int (argv[1]) << endl;
-  // cout << "filename: " << sqlite3_value_text (argv[2]) << endl;
-
-  string device_name (reinterpret_cast<const char*> (sqlite3_value_blob (argv[0])), sqlite3_value_bytes (argv[0]));
-  sqlite3_int64 device_id = sqlite3_value_int64 (argv[1]);
-  sqlite3_int64 seq_no    = sqlite3_value_int64 (argv[2]);
-  int action         = sqlite3_value_int  (argv[3]);
-  string filename    = reinterpret_cast<const char*> (sqlite3_value_text (argv[4]));
+  _LOG_TRACE ("apply_function called with " << argc);
+  _LOG_TRACE ("device_name: " << Name (device_name)
+              << ", action: " << action
+              << ", file: " << filename);
 
   if (action == 0) // update
     {
-      Hash hash (sqlite3_value_blob (argv[5]), sqlite3_value_bytes (argv[5]));
-      time_t atime = static_cast<time_t> (sqlite3_value_int64 (argv[6]));
-      time_t mtime = static_cast<time_t> (sqlite3_value_int64 (argv[7]));
-      time_t ctime = static_cast<time_t> (sqlite3_value_int64 (argv[8]));
-      int mode = sqlite3_value_int (argv[9]);
-      int seg_num = sqlite3_value_int (argv[10]);
+      Hash hash (sqlite3_value_blob (argv[4]), sqlite3_value_bytes (argv[4]));
+      time_t atime = static_cast<time_t> (sqlite3_value_int64 (argv[5]));
+      time_t mtime = static_cast<time_t> (sqlite3_value_int64 (argv[6]));
+      time_t ctime = static_cast<time_t> (sqlite3_value_int64 (argv[7]));
+      int mode = sqlite3_value_int (argv[8]);
+      int seg_num = sqlite3_value_int (argv[9]);
 
-      cout << "Update " << filename << " " << atime << " " << mtime << " " << ctime << " " << hash << endl;
+      _LOG_DEBUG ("Update " << filename << " " << atime << " " << mtime << " " << ctime << " " << hash);
 
       sqlite3_stmt *stmt;
       sqlite3_prepare_v2 (the->m_db, "UPDATE FileState "
                           "SET "
-                          "device_id=?, seq_no=?, "
+                          "device_name=?, seq_no=?, "
                           "file_hash=?,"
                           "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);
 
-      sqlite3_bind_int64 (stmt, 1, device_id);
+      sqlite3_bind_blob  (stmt, 1, device_name.buf (), device_name.length (), SQLITE_TRANSIENT);
       sqlite3_bind_int64 (stmt, 2, seq_no);
       sqlite3_bind_blob  (stmt, 3, hash.GetHash (), hash.GetHashBytes (), SQLITE_TRANSIENT);
       sqlite3_bind_int64 (stmt, 4, atime);
@@ -420,7 +579,8 @@
 
       sqlite3_step (stmt);
 
-      // cout << sqlite3_errmsg (the->m_db) << endl;
+      _LOG_DEBUG_COND (sqlite3_errcode (the->m_db) != SQLITE_OK,
+                       sqlite3_errmsg (the->m_db));
 
       sqlite3_finalize (stmt);
 
@@ -429,21 +589,23 @@
         {
           sqlite3_stmt *stmt;
           sqlite3_prepare_v2 (the->m_db, "INSERT INTO FileState "
-                              "(type,filename,device_id,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_int64 (stmt, 2, device_id);
+          sqlite3_bind_blob  (stmt, 2, device_name.buf (), device_name.length (), SQLITE_TRANSIENT);
           sqlite3_bind_int64 (stmt, 3, seq_no);
           sqlite3_bind_blob  (stmt, 4, hash.GetHash (), hash.GetHashBytes (), SQLITE_TRANSIENT);
           sqlite3_bind_int64 (stmt, 5, atime);
           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);
-          // cout << sqlite3_errmsg (the->m_db) << endl;
+          _LOG_DEBUG_COND (sqlite3_errcode (the->m_db) != SQLITE_OK,
+                           sqlite3_errmsg (the->m_db));
           sqlite3_finalize (stmt);
         }
     }
@@ -453,7 +615,7 @@
       sqlite3_prepare_v2 (the->m_db, "DELETE FROM FileState WHERE type=0 AND filename=?", -1, &stmt, 0);
       sqlite3_bind_text (stmt, 1, filename.c_str (), -1, SQLITE_STATIC);
 
-      cout << "Delete " << filename << endl;
+      _LOG_DEBUG ("Delete " << filename);
 
       sqlite3_step (stmt);
       sqlite3_finalize (stmt);
@@ -462,17 +624,39 @@
   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);
   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;
   if (sqlite3_step (stmt) == SQLITE_ROW)
   {
-    return true;
+    retval = true;
+  }
+  sqlite3_finalize (stmt);
+
+  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 false;
+  return retval;
 }
diff --git a/src/action-log.h b/src/action-log.h
index 1654215..4123713 100644
--- a/src/action-log.h
+++ b/src/action-log.h
@@ -24,40 +24,83 @@
 
 #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);
+
+  //////////////////////////
+  // Local operations     //
+  //////////////////////////
+  void
+  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
-  AddActionUpdate (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
-  AddActionDelete (const std::string &filename);
+  AddLocalActionDelete (const std::string &filename);
 
   bool
   KnownFileState(const std::string &filename, const Hash &hash);
 
+  //////////////////////////
+  // Remote operations    //
+  //////////////////////////
+
+  void
+  AddRemoteAction (const Ccnx::Name &deviceName, sqlite3_int64 seqno, Ccnx::PcoPtr actionPco);
+
+  /**
+   * @brief Add remote action using just action's parsed content object
+   *
+   * This function extracts device name and sequence number from the content object's and calls the overloaded method
+   */
+  void
+  AddRemoteAction (Ccnx::PcoPtr actionPco);
+
+  ///////////////////////////
+  // General operations    //
+  ///////////////////////////
+
+  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, sqlite3_int64, sqlite3_int64, std::string>
-  GetExistingRecord (const std::string &filename);
+  boost::tuple<sqlite3_int64 /*version*/, Ccnx::CcnxCharbufPtr /*device name*/, sqlite3_int64 /*seq_no*/>
+  GetLatestActionForFile (const std::string &filename);
 
   static void
   apply_action_xFun (sqlite3_context *context, int argc, sqlite3_value **argv);
@@ -66,7 +109,12 @@
   SyncLogPtr m_syncLog;
 
   Ccnx::CcnxWrapperPtr m_ccnx;
-  Ccnx::Name m_sharedFolderName;
+  std::string m_sharedFolderName;
 };
 
+namespace Error {
+struct ActionLog : virtual boost::exception, virtual std::exception { };
+}
+
+
 #endif // ACTION_LOG_H
diff --git a/src/db-helper.cc b/src/db-helper.cc
index 95ccc7a..ac63cdf 100644
--- a/src/db-helper.cc
+++ b/src/db-helper.cc
@@ -32,19 +32,18 @@
 namespace fs = boost::filesystem;
 
 const std::string INIT_DATABASE = "\
-PRAGMA foreign_keys = ON;                                       \n\
+    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 24340c6..d7e570a 100644
--- a/src/dispatcher.cc
+++ b/src/dispatcher.cc
@@ -40,8 +40,8 @@
            , m_server(NULL)
 {
   m_syncLog = make_shared<SyncLog>(path, localUserName);
-  m_actionLog = make_shared<ActionLog>(m_ccnx, path, m_syncLog, localUserName, sharedFolder);
-  Name syncPrefix(BROADCAST_DOMAIN + sharedFolder);
+  m_actionLog = make_shared<ActionLog>(m_ccnx, path, m_syncLog, sharedFolder);
+  Name syncPrefix = Name(BROADCAST_DOMAIN)(sharedFolder);
 
   m_server = new ContentServer(m_ccnx, m_actionLog, rootDir);
   m_server->registerPrefix(localPrefix);
@@ -114,7 +114,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
@@ -124,13 +124,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);
+          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();
         }
@@ -143,7 +146,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/file-item.proto b/src/file-item.proto
new file mode 100644
index 0000000..937226b
--- /dev/null
+++ b/src/file-item.proto
@@ -0,0 +1,18 @@
+message FileItem
+{
+  enum FileType
+  {
+    LATEST = 0;
+    OLDEST = 1;
+  }
+  required FileType type = 1;
+
+  required string filename = 2;
+  required bytes  device_name = 3;
+  required uint64 seq_no = 4;
+
+  required bytes  file_hash = 5;
+  required uint32 mtime = 6;
+  required uint32 mode  = 7;
+  required uint64 seg_num = 8;
+}
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-core.cc b/src/sync-core.cc
index d85093b..9d2003d 100644
--- a/src/sync-core.cc
+++ b/src/sync-core.cc
@@ -82,7 +82,7 @@
 
   // reply sync Interest with oldHash as last component
   Name syncName = Name (m_syncPrefix)(oldHash->GetHash(), oldHash->GetHashBytes());
-  BytesPtr syncData = serializeMsg (msg);
+  BytesPtr syncData = serializeMsg (*msg);
 
   m_ccnx->publishData(syncName, *syncData, FRESHNESS);
   _LOG_TRACE (m_log->GetLocalName () << " publishes: " << *oldHash);
@@ -125,7 +125,7 @@
     // we know the hash, should reply everything
     SyncStateMsgPtr msg = m_log->FindStateDifferences(*(Hash::Origin), *m_rootHash);
 
-    BytesPtr syncData = serializeMsg (msg);
+    BytesPtr syncData = serializeMsg (*msg);
     m_ccnx->publishData(name, *syncData, FRESHNESS);
     _LOG_TRACE (m_log->GetLocalName () << " publishes " << hash);
     _LOG_TRACE (msg);
@@ -153,7 +153,7 @@
     _LOG_TRACE ("found hash in sync log");
     SyncStateMsgPtr msg = m_log->FindStateDifferences(*hash, *m_rootHash);
 
-    BytesPtr syncData = serializeMsg (msg);
+    BytesPtr syncData = serializeMsg (*msg);
     m_ccnx->publishData(name, *syncData, FRESHNESS);
     _LOG_TRACE (m_log->GetLocalName () << " publishes: " << *hash);
     _LOG_TRACE (msg);
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 1ab25e9..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
@@ -41,12 +41,6 @@
   inline const Ccnx::Name &
   GetLocalName () const;
 
-  /**
-   * @brief Get database ID of the local sync node (make sense only for the local database)
-   */
-  inline const sqlite3_int64
-  GetLocalSyncNodeId () const;
-
   sqlite3_int64
   GetNextLocalSeqNo (); // side effect: local seq_no will be increased
 
@@ -92,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;
 
@@ -116,11 +112,4 @@
   return m_localName;
 }
 
-const sqlite3_int64
-SyncLog::GetLocalSyncNodeId () const
-{
-  return m_localDeviceId;
-}
-
-
 #endif // SYNC_LOG_H
diff --git a/test/test-action-log.cc b/test/test-action-log.cc
new file mode 100644
index 0000000..985af5c
--- /dev/null
+++ b/test/test-action-log.cc
@@ -0,0 +1,139 @@
+/* -*- 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);
+
+  BOOST_CHECK_NO_THROW (actionLog->AddRemoteAction (pco));
+  BOOST_CHECK_EQUAL (actionLog->LogSize (), 2);
+
+  // create a real remote action
+  ActionItem item;
+  item.set_action (ActionItem::UPDATE);
+  item.set_filename ("file.txt");
+  item.set_version (2);
+  item.set_timestamp (time (NULL));
+
+  BytesPtr item_msg = serializeMsg (item);
+  Name actionName = Name ("/zhenkai")("action")("top-secret")(1);
+  Bytes actionData = ccnx->createContentObject (actionName, head (*item_msg), item_msg->size ());
+
+  pco = make_shared<ParsedContentObject> (actionData);
+  BOOST_CHECK_NO_THROW (actionLog->AddRemoteAction (pco));
+  BOOST_CHECK_EQUAL (actionLog->LogSize (), 3);
+
+  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