|
View:
New views
7 Messages
—
Rating Filter:
Alert me
|
|
|
WIP Note Directory Watcher Patch - v2The NoteDirectoryWatcher Addin is nearly ready. Its useful and there
is little chance of you losing your data. Please check out the updated patch and preamble. If you use an external process to modify you ".note" files (ie DropBox) there is a significant risk that you will lose you note data. Tomboy will overwrite the note on disk with its representation in memory. NoteDirectoryWatcher will watch your ~/.tomboy directory for changes and update Tomboy's in-memory copy of the note if the note changes. This reduces the change of losing notes. Unfortunately there is still a small chance you will lose data. If you a) Update a note externally. b) Change the note in Tomboy more than 4 seconds but less than five seconds after A. I'll work on this later. There is still one corner case that needs to be handled (FileSystemWatcher.Error) but its highly unlikely you will encounter it. Running Tomboy under windows with your notes on a SMB share is a good way to try :). [watch.patch] diff --git a/Tomboy/Addins/Makefile.am b/Tomboy/Addins/Makefile.am index 57f5f56..9520b67 100644 --- a/Tomboy/Addins/Makefile.am +++ b/Tomboy/Addins/Makefile.am @@ -13,5 +13,6 @@ SUBDIRS = \ SshSyncService \ StickyNoteImport \ Tasque \ + NoteDirectoryWatcher \ WebDavSyncService diff --git a/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am b/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am new file mode 100644 index 0000000..8250fd2 --- /dev/null +++ b/Tomboy/Addins/NoteDirectoryWatcher/Makefile.am @@ -0,0 +1,39 @@ +include $(top_srcdir)/Makefile.include + +CSFLAGS = \ + -debug \ + -define:DEBUG \ + -target:library + +ASSEMBLIES = \ + $(LINK_TOMBOY_EXE) \ + $(GTKSHARP_LIBS) \ + $(LINK_MONO_ADDINS) \ + -r:Mono.Posix + +ADDIN_NAME = NoteDirectoryWatcher +TARGET = $(ADDIN_NAME).dll +CSFILES = \ + $(srcdir)/NoteDirectoryWatcherApplicationAddin.cs +RESOURCES = \ + -resource:$(srcdir)/$(ADDIN_NAME).addin.xml + +$(TARGET).mdb: $(TARGET) + +$(TARGET): $(CSFILES) $(top_builddir)/Tomboy/Tomboy.exe + $(CSC) -out:$@ $(CSFLAGS) $(ASSEMBLIES) $(CSFILES) $(RESOURCES) + + +addinsdir = $(pkglibdir)/addins +addins_DATA = \ + $(TARGET) \ + $(TARGET).mdb + +EXTRA_DIST = \ + $(CSFILES) \ + $(srcdir)/$(ADDIN_NAME).addin.xml + +CLEANFILES = \ + $(TARGET).mdb \ + $(TARGET) + diff --git a/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml new file mode 100644 index 0000000..6bfd500 --- /dev/null +++ b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcher.addin.xml @@ -0,0 +1,22 @@ +<Addin id="NoteDirectoryWatcher" + namespace="Tomboy" + name="Note Directory Watcher" + author="Tomboy Project" + description="Watch your Tomboy note directory for changes to your notes." + category="Tools" + defaultEnabled="false" + version="0.1"> + + <Runtime> + <Import assembly="NoteDirectoryWatcher.dll" /> + </Runtime> + + <Dependencies> + <Addin id="Tomboy" version="0.10" /> + </Dependencies> + + <Extension path="/Tomboy/ApplicationAddins"> + <ApplicationAddin type="Tomboy.NoteDirectoryWatcher.NoteDirectoryWatcherApplicationAddin" /> + </Extension> + +</Addin> diff --git a/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs new file mode 100644 index 0000000..07ab267 --- /dev/null +++ b/Tomboy/Addins/NoteDirectoryWatcher/NoteDirectoryWatcherApplicationAddin.cs @@ -0,0 +1,233 @@ + +using System; +using System.Collections.Generic; +using System.IO; + +using Tomboy; + +namespace Tomboy.NoteDirectoryWatcher +{ + class NoteFileChangeRecord + { + public DateTime last_change; + public bool deleted; + public bool changed; + } + + public class NoteDirectoryWatcherApplicationAddin : ApplicationAddin + { + private static bool VERBOSE_LOGGING = false; + + private FileSystemWatcher file_system_watcher; + private bool initialized; + + private Dictionary<string, NoteFileChangeRecord> file_change_records; + + public override void Initialize () + { + string note_path = Tomboy.DefaultNoteManager.NoteDirectoryPath; + + file_change_records = new Dictionary<string, NoteFileChangeRecord>(); + + file_system_watcher = new FileSystemWatcher (note_path); + + file_system_watcher.Changed += HandleFileSystemChangeEvent; + file_system_watcher.Deleted += HandleFileSystemChangeEvent; + file_system_watcher.Created += HandleFileSystemChangeEvent; + file_system_watcher.Renamed += HandleFileSystemChangeEvent; + + file_system_watcher.Error += HandleFileSystemErrorEvent; + + // Setting to true will starts the FileSystemWatcher. + file_system_watcher.EnableRaisingEvents = true; + + initialized = true; + } + + public override void Shutdown () + { + file_system_watcher.EnableRaisingEvents = false; + initialized = false; + } + + public override bool Initialized + { + get + { + return initialized; + } + } + + private void HandleFileSystemErrorEvent (Object sender, ErrorEventArgs arg) + { + // TODO Rescan the local notes in case some of them have changed. + } + + private void HandleFileSystemChangeEvent (Object sender, FileSystemEventArgs arg) + { + string note_id = GetId(arg.FullPath); + + if (VERBOSE_LOGGING) + { + Logger.Debug ("{0} has {1} (note_id={2})", arg.FullPath, arg.ChangeType, note_id); + } + + // If the note_id is long 36 characters then the file probably wasn't a note. + if (note_id.Length != 36) + { + if (VERBOSE_LOGGING) + { + Logger.Debug ("Ignoring change to {0}", arg.FullPath); + } + + return; + } + + // Record that the file has been added/changed/deleted. Adds/changes trump + // deletes. Record the date. + lock (file_change_records) + { + NoteFileChangeRecord record = null; + + if (file_change_records.ContainsKey (note_id)) + { + record = file_change_records[note_id]; + } + else + { + record = new NoteFileChangeRecord (); + file_change_records[note_id] = record; + } + + if (arg.ChangeType == WatcherChangeTypes.Changed) + { + record.changed = true; + record.deleted = false; + } + else if (arg.ChangeType == WatcherChangeTypes.Created) + { + record.changed = true; + record.deleted = false; + } + else if (arg.ChangeType == WatcherChangeTypes.Renamed) + { + record.changed = true; + record.deleted = false; + } + else if (arg.ChangeType == WatcherChangeTypes.Deleted) + { + if (!record.changed) + { + record.deleted = true; + } + } + else + { + String message = "Unexpected WatcherChangeType " + arg.ChangeType; + Logger.Error (message); + throw new Exception (message); + } + + record.last_change = DateTime.Now; + } + + GLib.Timeout.Add (5000, new GLib.TimeoutHandler (HandleTimeout)); + } + + private bool HandleTimeout () + { + lock (file_change_records) + { + List<string> keysToRemove = new List<string> (file_change_records.Count); + + foreach (KeyValuePair<string, NoteFileChangeRecord> pair in file_change_records) + { + if (VERBOSE_LOGGING) + { + Logger.Debug ("Handling (timeout) {0}", pair.Key); + } + + if (DateTime.Now > pair.Value.last_change.Add (new TimeSpan (4000)) ) + { + if (pair.Value.deleted) + { + DeleteNote (pair.Key); + } + else + { + AddOrUpdateNote (pair.Key); + } + + keysToRemove.Add (pair.Key); + } + } + + foreach (string note_id in keysToRemove) + { + file_change_records.Remove (note_id); + } + } + + return false; + } + + private static void DeleteNote (string note_id) + { + Logger.Debug ("Deleting {0} because file deleted.", note_id); + + string note_uri = MakeUri (note_id); + + Note note_to_delete = Tomboy.DefaultNoteManager.FindByUri (note_uri); + + Tomboy.DefaultNoteManager.Notes.Remove (note_to_delete); + + note_to_delete.Delete (); + } + + private static void AddOrUpdateNote (string note_id) + { + string note_path = Tomboy.DefaultNoteManager.NoteDirectoryPath + + Path.DirectorySeparatorChar + note_id + ".note"; + + string note_uri = MakeUri (note_id); + + Note note = Tomboy.DefaultNoteManager.FindByUri (note_uri); + + if (note == null) + { + Logger.Debug ("Adding {0} because file changed.", note_id); + Note new_note = Note.Load (note_path, Tomboy.DefaultNoteManager); + Tomboy.DefaultNoteManager.Notes.Add (new_note); + } + else + { + NoteData data = NoteArchiver.Instance.ReadFile (note_path, note_uri); + + // Only record changes if the note actually changes. This prevents the Addin from + // noticing changes from Tomboy itself. + if (data.Text == note.XmlContent) + { + if (VERBOSE_LOGGING) + { + Logger.Debug ("Ignoring {0} because contents identical", note_id); + } + } + else + { + Logger.Debug ("Updating {0} because file changed.", note_id); + note.XmlContent = data.Text; + note.Title = data.Title; + } + } + } + + private static String MakeUri (string note_id) + { + return "note://tomboy/" + note_id; + } + + private static string GetId (string path) + { + int last_slash = path.LastIndexOf (Path.DirectorySeparatorChar); + int first_period = path.IndexOf ('.', last_slash); + + return path.Substring (last_slash + 1, first_period - last_slash - 1); + } + } +} diff --git a/configure.in b/configure.in index ab9b951..8563e58 100644 --- a/configure.in +++ b/configure.in @@ -333,6 +333,7 @@ Tomboy/Addins/SshSyncService/Makefile Tomboy/Addins/StickyNoteImport/Makefile Tomboy/Addins/Tasque/Makefile Tomboy/Addins/WebDavSyncService/Makefile +Tomboy/Addins/NoteDirectoryWatcher/Makefile test/Makefile po/Makefile.in ]) _______________________________________________ Tomboy-list mailing list Tomboy-list@... http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com |
|
|
Re: WIP Note Directory Watcher Patch - v2Only time for a quick look right now, but I still think you should use
Note.LoadForeignNoteXml instead of setting note.XmlContent and note.Title (it picks up a bunch of other metadata, whereas XmlContent just picks up stuff in the content area). Going to play with this soon, want to get it in git ASAP. BTW, does anybody else feel weird writing "git" all lower-case, after years of "CVS" and "SVN"? :-P On Tue, Apr 28, 2009 at 12:40 PM, Michael Fletcher <m.fletcher@...> wrote: > The NoteDirectoryWatcher Addin is nearly ready. Its useful and there > is little chance of you losing your data. Please check out the > updated patch and preamble. > > > > If you use an external process to modify you ".note" files (ie > DropBox) there is a significant risk that you will lose you note data. > Tomboy will overwrite the note on disk with its representation in > memory. > > NoteDirectoryWatcher will watch your ~/.tomboy directory for changes > and update Tomboy's in-memory copy of the note if the note changes. > This reduces the change of losing notes. > > Unfortunately there is still a small chance you will lose data. If you > a) Update a note externally. > b) Change the note in Tomboy more than 4 seconds but less than five > seconds after A. I'll work on this later. > > There is still one corner case that needs to be handled > (FileSystemWatcher.Error) but its highly unlikely you will encounter > it. Running Tomboy under windows with your notes on a SMB share is a > good way to try :). > > _______________________________________________ > Tomboy-list mailing list > Tomboy-list@... > http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com > > Tomboy-list mailing list Tomboy-list@... http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com |
|
|
Re: WIP Note Directory Watcher Patch - v2> Only time for a quick look right now, but I still think you should use
> Note.LoadForeignNoteXml instead of setting note.XmlContent and > note.Title (it picks up a bunch of other metadata, whereas XmlContent > just picks up stuff in the content area). Sorry, I was going to comment on this. I tried and it didn't work. The UI was never updated. I don't know enough about Tomboy internals to know why. _______________________________________________ Tomboy-list mailing list Tomboy-list@... http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com |
|
|
Re: WIP Note Directory Watcher Patch - v2On Tue, Apr 28, 2009 at 2:11 PM, Michael Fletcher
<m.fletcher@...> wrote: >> Only time for a quick look right now, but I still think you should use >> Note.LoadForeignNoteXml instead of setting note.XmlContent and >> note.Title (it picks up a bunch of other metadata, whereas XmlContent >> just picks up stuff in the content area). > Sorry, I was going to comment on this. I tried and it didn't work. > The UI was never updated. I don't know enough about Tomboy internals > to know why. Okay, I'll look into it, thanks! Sandy _______________________________________________ Tomboy-list mailing list Tomboy-list@... http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com |
|
|
Re: WIP Note Directory Watcher Patch - v2On Tue, Apr 28, 2009 at 2:45 PM, Sandy Armstrong
<sanfordarmstrong@...> wrote: > On Tue, Apr 28, 2009 at 2:11 PM, Michael Fletcher > <m.fletcher@...> wrote: >>> Only time for a quick look right now, but I still think you should use >>> Note.LoadForeignNoteXml instead of setting note.XmlContent and >>> note.Title (it picks up a bunch of other metadata, whereas XmlContent >>> just picks up stuff in the content area). >> Sorry, I was going to comment on this. I tried and it didn't work. >> The UI was never updated. I don't know enough about Tomboy internals >> to know why. > > Okay, I'll look into it, thanks! Mike, I'd like to get this into git, and work on it centrally. Can you commit to master, make a patch with git-format-patch, and email that to the list? Then I'll push it and we can start polishing it a bit. Thanks, Sandy _______________________________________________ Tomboy-list mailing list Tomboy-list@... http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com |
|
|
|
|
|
Re: WIP Note Directory Watcher Patch - v2On Wed, Apr 29, 2009 at 6:52 PM, Michael Fletcher
<m.fletcher@...> wrote: > Hello > > The patch using git-format-patch is attached. Pushed. I modified your commit message a bit. We try to keep the first line to be a very short summary of what the commit is for. I have not yet looked at the problems with LoadForeignNoteXml, but the code is now in git for anybody to work on. Awesome work, Sandy _______________________________________________ Tomboy-list mailing list Tomboy-list@... http://lists.beatniksoftware.com/listinfo.cgi/tomboy-list-beatniksoftware.com |
| Free embeddable forum powered by Nabble | Forum Help |