[gnote] Implement local synchronization manifest
- From: Aurimas Äernius <aurimasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnote] Implement local synchronization manifest
- Date: Sat, 11 Feb 2012 19:06:31 +0000 (UTC)
commit 27af75604b41b45ab44dd0058c9ebb57249fa961
Author: Aurimas Äernius <aurisc4 gmail com>
Date: Sat Feb 11 21:02:37 2012 +0200
Implement local synchronization manifest
src/synchronization/gnotesyncclient.cpp | 185 ++++++++++++++++++++++++++++++-
src/synchronization/gnotesyncclient.hpp | 4 +
2 files changed, 184 insertions(+), 5 deletions(-)
---
diff --git a/src/synchronization/gnotesyncclient.cpp b/src/synchronization/gnotesyncclient.cpp
index 2f923bc..a0f29ef 100644
--- a/src/synchronization/gnotesyncclient.cpp
+++ b/src/synchronization/gnotesyncclient.cpp
@@ -22,8 +22,15 @@
#define _SYNCHRONIZATION_GNOTESYNCCLIENT_HPP_
+#include <boost/lexical_cast.hpp>
+
+#include "debug.hpp"
+#include "gnote.hpp"
#include "gnotesyncclient.hpp"
+#include "notemanager.hpp"
#include "sharp/files.hpp"
+#include "sharp/xml.hpp"
+#include "sharp/xmlwriter.hpp"
namespace gnote {
@@ -33,6 +40,174 @@ namespace sync {
GnoteSyncClient::GnoteSyncClient()
{
+ // TODO: Why doesn't OnChanged ever get fired?!
+#if 0
+ FileSystemWatcher w = new FileSystemWatcher ();
+ w.Path = Services.NativeApplication.ConfigurationDirectory;
+ w.Filter = localManifestFileName;
+ w.Changed += OnChanged;
+#endif
+
+ m_local_manifest_file_path = Glib::build_filename(Gnote::conf_dir(), LOCAL_MANIFEST_FILE_NAME);
+ parse(m_local_manifest_file_path);
+
+ Gnote::obj().default_note_manager().signal_note_deleted
+ .connect(sigc::mem_fun(*this, &GnoteSyncClient::note_deleted_handler));
+ }
+
+
+ void GnoteSyncClient::note_deleted_handler(const Note::Ptr & deletedNote)
+ {
+ m_deleted_notes[deletedNote->id()] = deletedNote->get_title();
+ m_file_revisions.erase(deletedNote->id());
+
+ write(m_local_manifest_file_path);
+ }
+
+
+ void GnoteSyncClient::parse(const std::string & manifest_path)
+ {
+ // Set defaults before parsing
+ m_last_sync_date = sharp::DateTime::now().add_days(-1);
+ m_last_sync_rev = -1;
+
+ if(!sharp::file_exists(manifest_path)) {
+ m_last_sync_date = sharp::DateTime();
+ write(manifest_path);
+ }
+
+ xmlDocPtr xml_doc = xmlReadFile(manifest_path.c_str(), "UTF-8", 0);
+ if(xml_doc == NULL) {
+ DBG_OUT("Invalid XML in %s. Recreating from scratch.", manifest_path.c_str());
+ m_last_sync_date = sharp::DateTime();
+ write(manifest_path);
+ xml_doc = xmlReadFile(manifest_path.c_str(), "UTF-8", 0);
+ }
+ try {
+ xmlNodePtr root_node = xmlDocGetRootElement(xml_doc);
+ sharp::XmlNodeSet note_revisions = sharp::xml_node_xpath_find(root_node, "//note-revisions");
+ // TODO: Error checking
+ for(sharp::XmlNodeSet::iterator revisionsNode = note_revisions.begin();
+ revisionsNode != note_revisions.end(); ++revisionsNode) {
+ if((*revisionsNode)->children) {
+ int i = 0;
+ do {
+ xmlNodePtr noteNode = &(*revisionsNode)->children[i];
+ std::string guid = sharp::xml_node_get_attribute(noteNode, "guid");
+ int revision = -1;
+ try {
+ revision = boost::lexical_cast<int>(sharp::xml_node_get_attribute(noteNode, "latest-revision"));
+ }
+ catch(...) {}
+
+ m_file_revisions[guid] = revision;
+ }
+ while((*revisionsNode)->last != &(*revisionsNode)->children[i++]);
+ }
+ }
+
+ sharp::XmlNodeSet note_deletions = sharp::xml_node_xpath_find(root_node, "//note-deletions");
+ for(sharp::XmlNodeSet::iterator deletionsNode = note_deletions.begin();
+ deletionsNode != note_deletions.end(); ++deletionsNode) {
+ if((*deletionsNode)->children) {
+ int i = 0;
+ do {
+ xmlNodePtr noteNode = &(*deletionsNode)->children[i];
+ std::string guid = sharp::xml_node_get_attribute(noteNode, "guid");
+ std::string title = sharp::xml_node_get_attribute(noteNode, "title");
+ m_deleted_notes[guid] = title;
+ }
+ while((*deletionsNode)->last != &(*deletionsNode)->children[i++]);
+ }
+ }
+
+ sharp::XmlNodeSet last_sync_rev = sharp::xml_node_xpath_find(root_node, "//last-sync-rev");
+ for(sharp::XmlNodeSet::iterator node = last_sync_rev.begin();
+ node != last_sync_rev.end(); ++node) {
+ try {
+ m_last_sync_rev = boost::lexical_cast<int>(sharp::xml_node_content(*node));
+ }
+ catch(...) {
+ ERR_OUT("Unparsable last-sync-rev element in %s", manifest_path.c_str());
+ }
+ }
+
+ sharp::XmlNodeSet server_id = sharp::xml_node_xpath_find(root_node, "//server-id");
+ for(sharp::XmlNodeSet::iterator node = server_id.begin();
+ node != server_id.end(); ++node) {
+ m_server_id = sharp::xml_node_content(*node);
+ }
+
+ sharp::XmlNodeSet sync_date = sharp::xml_node_xpath_find(root_node, "//last-sync-date");
+ for(sharp::XmlNodeSet::iterator node = sync_date.begin();
+ node != sync_date.end(); ++node) {
+ try {
+ m_last_sync_date = sharp::DateTime::from_iso8601(sharp::xml_node_content(*node));
+ }
+ catch(...) {
+ ERR_OUT("Unparsable last-sync-date element in %s", manifest_path.c_str());
+ }
+ }
+ xmlFreeDoc(xml_doc);
+ }
+ catch(...) {
+ xmlFreeDoc(xml_doc);
+ throw;
+ }
+ }
+
+
+ void GnoteSyncClient::write(const std::string & manifest_path)
+ {
+ sharp::XmlWriter xml(manifest_path);
+
+ try {
+ xml.write_start_document();
+ xml.write_start_element("", "manifest", "http://beatniksoftware.com/tomboy");
+
+ xml.write_start_element("", "last-sync-date", "");
+ xml.write_string(m_last_sync_date.to_iso8601());
+ xml.write_end_element();
+
+ xml.write_start_element("", "last-sync-rev", "");
+ xml.write_string(boost::lexical_cast<std::string>(m_last_sync_rev));
+ xml.write_end_element();
+
+ xml.write_start_element("", "server-id", "");
+ xml.write_string(m_server_id);
+ xml.write_end_element();
+
+ xml.write_start_element("", "note-revisions", "");
+
+ for(std::map<std::string, int>::iterator noteGuid = m_file_revisions.begin();
+ noteGuid != m_file_revisions.end(); ++noteGuid) {
+ xml.write_start_element("", "note", "");
+ xml.write_attribute_string("", "guid", "", noteGuid->first);
+ xml.write_attribute_string("", "latest-revision", "", boost::lexical_cast<std::string>(noteGuid->second));
+ xml.write_end_element();
+ }
+
+ xml.write_end_element(); // </note-revisons>
+
+ xml.write_start_element("", "note-deletions", "");
+
+ for(std::map<std::string, std::string>::iterator noteGuid = m_deleted_notes.begin();
+ noteGuid != m_deleted_notes.end(); ++noteGuid) {
+ xml.write_start_element("", "note", "");
+ xml.write_attribute_string("", "guid", "", noteGuid->first);
+ xml.write_attribute_string("", "title", "", noteGuid->second);
+ xml.write_end_element();
+ }
+
+ xml.write_end_element(); // </note-deletions>
+
+ xml.write_end_element(); // </manifest>
+ xml.close();
+ }
+ catch(...) {
+ xml.close();
+ throw;
+ }
}
@@ -41,14 +216,14 @@ namespace sync {
m_last_sync_date = date;
// If we just did a sync, we should be able to forget older deleted notes
m_deleted_notes.clear();
- //Write(localManifestFilePath); TODO
+ write(m_local_manifest_file_path);
}
void GnoteSyncClient::last_synchronized_revision(int revision)
{
m_last_sync_rev = revision;
- //Write(localManifestFilePath); TODO
+ write(m_local_manifest_file_path);
}
@@ -69,7 +244,7 @@ namespace sync {
{
m_file_revisions[note->id()] = revision;
// TODO: Should we write on each of these or no?
- //Write(localManifestFilePath); TODO
+ write(m_local_manifest_file_path);
}
@@ -78,7 +253,7 @@ namespace sync {
if(sharp::file_exists(m_local_manifest_file_path)) {
sharp::file_delete(m_local_manifest_file_path);
}
- //Parse(localManifestFilePath); TODO
+ parse(m_local_manifest_file_path);
}
@@ -86,7 +261,7 @@ namespace sync {
{
if(m_server_id != server_id) {
m_server_id = server_id;
- //Write(localManifestFilePath); TODO
+ write(m_local_manifest_file_path);
}
}
diff --git a/src/synchronization/gnotesyncclient.hpp b/src/synchronization/gnotesyncclient.hpp
index e3ee245..8db1775 100644
--- a/src/synchronization/gnotesyncclient.hpp
+++ b/src/synchronization/gnotesyncclient.hpp
@@ -56,6 +56,10 @@ namespace sync {
private:
static const char *LOCAL_MANIFEST_FILE_NAME;
+ void note_deleted_handler(const Note::Ptr &);
+ void parse(const std::string & manifest_path);
+ void write(const std::string & manifest_path);
+
sharp::DateTime m_last_sync_date;
int m_last_sync_rev;
std::string m_server_id;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]