Use only a single watcher to monitor the SparkleShare folder

This commit is contained in:
Hylke Bons 2012-07-08 23:53:44 +02:00
parent e20dcd55ea
commit ca22672842
7 changed files with 84 additions and 122 deletions

View file

@ -16,6 +16,7 @@ SOURCES = \
SparkleRepoBase.cs \
SparkleUser.cs \
SparkleWatcher.cs \
SparkleWatcherFactory.cs \
SparkleWrappers.cs

View file

@ -152,7 +152,7 @@ namespace SparkleLib {
this.identifier = Identifier;
ChangeSets = GetChangeSets ();
this.watcher = CreateWatcher ();
this.watcher = SparkleWatcherFactory.CreateWatcher (this);
new Thread (
new ThreadStart (delegate {
@ -201,11 +201,6 @@ namespace SparkleLib {
public void OnFileActivity (FileSystemEventArgs args)
{
// Check the watcher for the occasions where this
// method is called directly
if (!this.watcher.EnableRaisingEvents || IsBuffering)
return;
lock (this.change_lock) {
this.remote_timer.Stop ();
@ -220,7 +215,6 @@ namespace SparkleLib {
if (!IsBuffering && HasLocalChanges) {
IsBuffering = true;
this.watcher.Disable ();
SparkleHelpers.DebugInfo ("Local", Name + " | Activity detected, waiting for it to settle...");
@ -244,10 +238,8 @@ namespace SparkleLib {
SparkleHelpers.DebugInfo ("Local", Name + " | Activity has settled");
IsBuffering = false;
this.watcher.Disable ();
while (HasLocalChanges)
SyncUpBase ();
this.watcher.Enable ();
} else {
Thread.Sleep (500);
@ -271,7 +263,6 @@ namespace SparkleLib {
private void SyncUpBase ()
{
try {
this.watcher.Disable ();
this.remote_timer.Stop ();
SparkleHelpers.DebugInfo ("SyncUp", Name + " | Initiated");
@ -294,7 +285,6 @@ namespace SparkleLib {
HasUnsyncedChanges = true;
SyncDownBase ();
this.watcher.Disable ();
if (ServerOnline && SyncUp ()) {
HasUnsyncedChanges = false;
@ -314,7 +304,6 @@ namespace SparkleLib {
} finally {
this.remote_timer.Start ();
this.watcher.Enable ();
ProgressPercentage = 0.0;
ProgressSpeed = "";
@ -326,7 +315,6 @@ namespace SparkleLib {
{
SparkleHelpers.DebugInfo ("SyncDown", Name + " | Initiated");
this.remote_timer.Stop ();
this.watcher.Disable ();
if (SyncStatusChanged != null)
SyncStatusChanged (SyncStatus.SyncDown);
@ -380,19 +368,6 @@ namespace SparkleLib {
SyncStatusChanged (SyncStatus.Idle);
this.remote_timer.Start ();
this.watcher.Enable ();
}
private SparkleWatcher CreateWatcher ()
{
SparkleWatcher watcher = new SparkleWatcher (LocalPath);
watcher.ChangeEvent += delegate (FileSystemEventArgs args) {
OnFileActivity (args);
};
return watcher;
}
@ -456,7 +431,7 @@ namespace SparkleLib {
!announcement.Message.Equals (CurrentRevision)) {
while (this.is_syncing)
System.Threading.Thread.Sleep (100);
Thread.Sleep (100);
SparkleHelpers.DebugInfo ("Listener", "Syncing due to announcement");
SyncDownBase ();

View file

@ -16,57 +16,60 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using IO = System.IO;
namespace SparkleLib {
public class SparkleWatcher : FileSystemWatcher {
public class SparkleWatcher : IO.FileSystemWatcher {
public delegate void ChangeEventEventHandler (FileSystemEventArgs args);
public event ChangeEventEventHandler ChangeEvent;
private Object thread_lock = new Object ();
public List<SparkleRepoBase> ReposToNotify = new List<SparkleRepoBase> ();
public SparkleWatcher (string path) : base (path)
public SparkleWatcher (SparkleRepoBase repo)
{
ReposToNotify.Add (repo);
Changed += Notify;
Created += Notify;
Deleted += Notify;
Renamed += Notify;
Filter = "*";
Path = IO.Path.GetDirectoryName (repo.LocalPath);
IncludeSubdirectories = true;
EnableRaisingEvents = true;
Filter = "*";
Changed += delegate (object o, FileSystemEventArgs args) {
if (ChangeEvent != null)
ChangeEvent (args);
};
Created += delegate (object o, FileSystemEventArgs args) {
if (ChangeEvent != null)
ChangeEvent (args);
};
Deleted += delegate (object o, FileSystemEventArgs args) {
if (ChangeEvent != null)
ChangeEvent (args);
};
Renamed += delegate (object o, RenamedEventArgs args) {
if (ChangeEvent != null)
ChangeEvent (args);
};
}
public void Enable ()
public void Notify (object sender, IO.FileSystemEventArgs args)
{
lock (this.thread_lock)
EnableRaisingEvents = true;
}
char separator = IO.Path.DirectorySeparatorChar;
string relative_path = args.FullPath.Substring (Path.Length);
relative_path = relative_path.Trim (new char [] {' ', separator});
// Ignore changes that happened in the parent path
if (!relative_path.Contains (separator.ToString ()))
return;
public void Disable ()
{
lock (this.thread_lock)
EnableRaisingEvents = false;
string repo_name = relative_path.Substring (0, relative_path.IndexOf (separator));
foreach (SparkleRepoBase repo in ReposToNotify) {
if (repo.Name.Equals (repo_name) && !repo.IsBuffering &&
(repo.Status != SyncStatus.SyncUp && repo.Status != SyncStatus.SyncDown)) {
Thread thread = new Thread (
new ThreadStart (delegate {
repo.OnFileActivity (args);
})
);
thread.Start ();
}
}
}
}
}

View file

@ -21,30 +21,43 @@ using System.IO;
namespace SparkleLib {
public static class SparkleListenerFactory {
public static class SparkleWatcherFactory {
private static List<SparkleWatcher> watchers = new List<SparkleWatcher> ();
public static SparkleWatcher CreateWatcher (string path_to_watch)
public static SparkleWatcher CreateWatcher (SparkleRepoBase repo_to_watch)
{
path_to_watch = Path.GetDirectoryName (path_to_watch);
foreach (SparkleWatcher watcher in watchers) {
if (watcher.Path.Equals (path_to_watch)) {
SparkleHelpers.DebugInfo ("WatcherFactory",
"Refered to existing watcher for " + path_to_watch);
foreach (SparkleRepoBase repo in watcher.ReposToNotify) {
string path_to_watch = Path.GetDirectoryName (repo_to_watch.LocalPath);
return watcher;
if (watcher.Path.Equals (path_to_watch)) {
watcher.ReposToNotify.Add (repo_to_watch);
SparkleHelpers.DebugInfo ("WatcherFactory", "Refered to existing watcher for " + path_to_watch);
return watcher;
}
}
}
watchers.Add (new SparkleWatcher (path_to_watch));
SparkleWatcher new_watcher = new SparkleWatcher (repo_to_watch);
watchers.Add (new_watcher);
SparkleHelpers.DebugInfo ("WatcherFactory",
"Issued new watcher for " + path_to_watch);
SparkleHelpers.DebugInfo ("WatcherFactory", "Issued new watcher for " + repo_to_watch.Name);
return watchers [watchers.Count - 1];
}
public static void TriggerWatcherManually (FileSystemEventArgs args)
{
foreach (SparkleWatcher watcher in watchers) {
if (args.FullPath.StartsWith (watcher.Path)) {
watcher.Notify (null, args);
return;
}
}
}
}
}

View file

@ -57,12 +57,10 @@ namespace SparkleShare {
// Let's use the bundled git first
SparkleLib.Git.SparkleGit.GitPath =
Path.Combine (NSBundle.MainBundle.ResourcePath,
"git", "libexec", "git-core", "git");
Path.Combine (NSBundle.MainBundle.ResourcePath, "git", "libexec", "git-core", "git");
SparkleLib.Git.SparkleGit.ExecPath =
Path.Combine (NSBundle.MainBundle.ResourcePath,
"git", "libexec", "git-core");
Path.Combine (NSBundle.MainBundle.ResourcePath, "git", "libexec", "git-core");
}
@ -70,36 +68,13 @@ namespace SparkleShare {
{
base.Initialize ();
this.watcher.Changed += delegate (object sender, SparkleMacWatcherEventArgs args) {
string path = args.Path;
this.watcher.Changed += delegate (string path) {
string full_path = Path.Combine (SparkleConfig.DefaultConfig.FoldersPath, path + "/something");
// Don't even bother with paths in .git/
if (path.Contains (".git"))
return;
FileSystemEventArgs event_args = new FileSystemEventArgs (WatcherChangeTypes.Changed,
Path.GetDirectoryName (full_path), Path.GetFileName (full_path));
string repo_name;
if (path.Contains ("/"))
repo_name = path.Substring (0, path.IndexOf ("/"));
else
repo_name = path;
// Ignore changes in the root of each subfolder, these
// are already handled by the repository
if (Path.GetFileNameWithoutExtension (path).Equals (repo_name))
return;
repo_name = repo_name.Trim ("/".ToCharArray ());
FileSystemEventArgs fse_args = new FileSystemEventArgs (
WatcherChangeTypes.Changed,
Path.Combine (SparkleConfig.DefaultConfig.FoldersPath, path),
Path.GetFileName (path)
);
foreach (SparkleRepoBase repo in Repositories) {
if (repo.Name.Equals (repo_name))
repo.OnFileActivity (fse_args);
}
SparkleWatcherFactory.TriggerWatcherManually (event_args);
};
}

View file

@ -53,25 +53,14 @@ using MonoMac.Foundation;
namespace SparkleShare {
[Serializable]
public sealed class SparkleMacWatcherEventArgs : EventArgs {
public sealed class SparkleMacWatcher : IDisposable {
public delegate void ChangedEventHandler (string path);
public event ChangedEventHandler Changed;
public string Path { get; private set; }
public SparkleMacWatcherEventArgs (string path)
{
Path = path;
}
}
public sealed class SparkleMacWatcher : IDisposable
{
public event EventHandler<SparkleMacWatcherEventArgs> Changed;
public string Path { get; private set; }
[Flags]
[Serializable]
private enum FSEventStreamCreateFlags : uint
@ -186,7 +175,7 @@ namespace SparkleShare {
string path = paths [0];
path = path.Substring (Path.Length);
path = path.Trim ("/".ToCharArray ());
handler (this, new SparkleMacWatcherEventArgs (path));
handler (path);
}
GC.KeepAlive (this);

View file

@ -284,6 +284,12 @@ namespace SparkleShare {
return;
} else {
if (Directory.Exists (args.FullPath) &&
args.ChangeType == WatcherChangeTypes.Created) {
return;
}
CheckRepositories ();
}
}