repo: update sync algorithm. fewer threads, less complexity

This commit is contained in:
Hylke Bons 2013-02-09 23:42:32 +00:00
parent 95122e44fd
commit a483759760
3 changed files with 48 additions and 107 deletions

View file

@ -161,30 +161,6 @@ namespace SparkleLib.Git {
File.WriteAllText (size_file_path, size.ToString ());
File.WriteAllText (history_size_file_path, history_size.ToString ());
}
public override string [] UnsyncedFilePaths {
get {
List<string> file_paths = new List<string> ();
SparkleGit git = new SparkleGit (LocalPath, "status --porcelain");
string output = git.StartAndReadStandardOutput ();
string [] lines = output.Split ("\n".ToCharArray ());
foreach (string line in lines) {
if (line [1].ToString ().Equals ("M") ||
line [1].ToString ().Equals ("?") ||
line [1].ToString ().Equals ("A")) {
string path = line.Substring (3);
path = path.Trim ("\"".ToCharArray ());
file_paths.Add (path);
}
}
return file_paths.ToArray ();
}
}
public override string CurrentRevision {

View file

@ -45,20 +45,25 @@ namespace SparkleLib {
public abstract class SparkleRepoBase {
public static bool UseCustomWatcher = false;
public abstract bool SyncUp ();
public abstract bool SyncDown ();
public abstract void RestoreFile (string path, string revision, string target_file_path);
public abstract bool HasUnsyncedChanges { get; set; }
public abstract bool HasLocalChanges { get; }
public abstract bool HasRemoteChanges { get; }
public abstract string CurrentRevision { get; }
public abstract double Size { get; }
public abstract double HistorySize { get; }
public abstract List<string> ExcludePaths { get; }
public abstract bool HasUnsyncedChanges { get; set; }
public abstract bool HasLocalChanges { get; }
public abstract bool HasRemoteChanges { get; }
public abstract bool SyncUp ();
public abstract bool SyncDown ();
public abstract List<SparkleChangeSet> GetChangeSets ();
public abstract List<SparkleChangeSet> GetChangeSets (string path);
public abstract void RestoreFile (string path, string revision, string target_file_path);
public static bool UseCustomWatcher = false;
public event SyncStatusChangedEventHandler SyncStatusChanged = delegate { };
public delegate void SyncStatusChangedEventHandler (SyncStatus new_status);
@ -114,12 +119,6 @@ namespace SparkleLib {
}
}
public virtual string [] UnsyncedFilePaths {
get {
return new string [0];
}
}
protected SparkleConfig local_config;
@ -127,16 +126,13 @@ namespace SparkleLib {
private string identifier;
private SparkleListenerBase listener;
private SparkleWatcher watcher;
private TimeSpan poll_interval = PollInterval.Short;
private DateTime last_poll = DateTime.Now;
private DateTime progress_last_change = DateTime.Now;
private TimeSpan progress_change_interval = new TimeSpan (0, 0, 0, 1);
private Timers.Timer remote_timer = new Timers.Timer () { Interval = 5000 };
private TimeSpan poll_interval = PollInterval.Short;
private DateTime last_poll = DateTime.Now;
private DateTime progress_last_change = DateTime.Now;
private Timers.Timer remote_timer = new Timers.Timer () { Interval = 5000 };
private bool is_syncing {
get {
return (Status == SyncStatus.SyncUp || Status == SyncStatus.SyncDown || IsBuffering);
}
get { return (Status == SyncStatus.SyncUp || Status == SyncStatus.SyncDown || IsBuffering); }
}
private static class PollInterval {
@ -162,9 +158,7 @@ namespace SparkleLib {
string identifier_file_path = Path.Combine (LocalPath, ".sparkleshare");
File.SetAttributes (identifier_file_path, FileAttributes.Hidden);
SyncStatusChanged += delegate (SyncStatus status) {
Status = status;
};
SyncStatusChanged += delegate (SyncStatus status) { Status = status; };
if (!UseCustomWatcher)
this.watcher = new SparkleWatcher (LocalPath);
@ -176,20 +170,23 @@ namespace SparkleLib {
return;
int time_comparison = DateTime.Compare (this.last_poll, DateTime.Now.Subtract (this.poll_interval));
bool time_to_poll = (time_comparison < 0);
if (time_to_poll && !is_syncing) {
if (time_comparison < 0) {
if (HasUnsyncedChanges && !this.is_syncing)
SyncUpBase ();
this.last_poll = DateTime.Now;
if (HasRemoteChanges) {
this.poll_interval = PollInterval.Long;
if (HasRemoteChanges && !this.is_syncing)
SyncDownBase ();
}
if (this.listener.IsConnected)
this.poll_interval = PollInterval.Long;
}
// In the unlikely case that we haven't synced up our
// changes or the server was down, sync up again
if (HasUnsyncedChanges && !is_syncing && Error == ErrorStatus.None)
if (HasUnsyncedChanges && !this.is_syncing && Error == ErrorStatus.None)
SyncUpBase ();
};
}
@ -197,18 +194,20 @@ namespace SparkleLib {
public void Initialize ()
{
if (!UseCustomWatcher)
this.watcher.ChangeEvent += OnFileActivity;
// Sync up everything that changed
// since we've been offline
// Sync up everything that changed since we've been offline
new Thread (() => {
if (!this.is_syncing && (HasUnsyncedChanges || HasLocalChanges)) {
if (HasRemoteChanges)
SyncDownBase ();
if (HasUnsyncedChanges || HasLocalChanges) {
do {
SyncUpBase ();
} while (!this.is_syncing && HasLocalChanges);
} while (HasLocalChanges);
}
if (!UseCustomWatcher)
this.watcher.ChangeEvent += OnFileActivity;
this.remote_timer.Start ();
@ -306,7 +305,7 @@ namespace SparkleLib {
return;
// Only trigger the ProgressChanged event once per second
if (DateTime.Compare (this.progress_last_change, DateTime.Now.Subtract (this.progress_change_interval)) >= 0)
if (DateTime.Compare (this.progress_last_change, DateTime.Now.Subtract (new TimeSpan (0, 0, 0, 1))) >= 0)
return;
if (progress_percentage == 100.0)
@ -350,8 +349,8 @@ namespace SparkleLib {
if (Error == ErrorStatus.None && SyncUp ()) {
HasUnsyncedChanges = false;
SyncStatusChanged (SyncStatus.Idle);
this.listener.Announce (new SparkleAnnouncement (Identifier, CurrentRevision));
SyncStatusChanged (SyncStatus.Idle);
} else {
this.poll_interval = PollInterval.Short;
@ -409,8 +408,8 @@ namespace SparkleLib {
if (HasUnsyncedChanges) {
SyncStatusChanged (SyncStatus.SyncUp);
SyncUp ();
HasUnsyncedChanges = false;
if (SyncUp ())
HasUnsyncedChanges = false;
}
SyncStatusChanged (SyncStatus.Idle);
@ -425,10 +424,10 @@ namespace SparkleLib {
ProgressPercentage = 0.0;
ProgressSpeed = 0.0;
SyncStatusChanged (SyncStatus.Idle);
if (!UseCustomWatcher)
this.watcher.Enable ();
SyncStatusChanged (SyncStatus.Idle);
}
@ -436,69 +435,38 @@ namespace SparkleLib {
{
this.listener = SparkleListenerFactory.CreateListener (Name, Identifier);
if (this.listener.IsConnected) {
if (this.listener.IsConnected)
this.poll_interval = PollInterval.Long;
new Thread (() => {
if (!this.is_syncing && !HasLocalChanges && HasRemoteChanges)
SyncDownBase ();
}).Start ();
}
this.listener.Connected += ListenerConnectedDelegate;
this.listener.Disconnected += ListenerDisconnectedDelegate;
this.listener.AnnouncementReceived += ListenerAnnouncementReceivedDelegate;
// Start listening
if (!this.listener.IsConnected && !this.listener.IsConnecting)
this.listener.Connect ();
}
// Stop polling when the connection to the irc channel is succesful
private void ListenerConnectedDelegate ()
{
this.poll_interval = PollInterval.Long;
this.last_poll = DateTime.Now;
if (!this.is_syncing) {
// Check for changes manually one more time
if (HasRemoteChanges)
SyncDownBase ();
// Push changes that were made since the last disconnect
if (HasUnsyncedChanges)
SyncUpBase ();
}
}
// Start polling when the connection to the channel is lost
private void ListenerDisconnectedDelegate ()
{
this.poll_interval = PollInterval.Short;
SparkleLogger.LogInfo (Name, "Falling back to polling");
SparkleLogger.LogInfo (Name, "Falling back to regular polling");
}
// Fetch changes when there is an announcement
private void ListenerAnnouncementReceivedDelegate (SparkleAnnouncement announcement)
{
string identifier = Identifier;
if (announcement.FolderIdentifier.Equals (identifier) &&
!announcement.Message.Equals (CurrentRevision)) {
if (!announcement.FolderIdentifier.Equals (identifier))
return;
if (!announcement.Message.Equals (CurrentRevision)) {
while (this.is_syncing)
Thread.Sleep (100);
SparkleLogger.LogInfo (Name, "Syncing due to announcement");
SyncDownBase ();
} else {
if (announcement.FolderIdentifier.Equals (identifier))
SparkleLogger.LogInfo (Name, "Not syncing, message is for current revision");
}
}
@ -531,7 +499,6 @@ namespace SparkleLib {
this.remote_timer.Stop ();
this.remote_timer.Dispose ();
this.listener.Connected -= ListenerConnectedDelegate;
this.listener.Disconnected -= ListenerDisconnectedDelegate;
this.listener.AnnouncementReceived -= ListenerAnnouncementReceivedDelegate;

View file

@ -23,7 +23,6 @@ namespace SparkleShare {
public static class SparkleUIHelpers {
// Looks up an icon from the system's theme
public static Gdk.Pixbuf GetIcon (string name, int size)
{
IconTheme icon_theme = new IconTheme ();
@ -36,7 +35,6 @@ namespace SparkleShare {
icon_theme.AppendSearchPath ("/usr/share/icons");
icon_theme.AppendSearchPath ("/usr/local/share/icons");
icon_theme.AppendSearchPath ("/opt/local/share/icons");
icon_theme.AppendSearchPath (Path.Combine (SparkleUI.AssetsPath, "icons"));
try {