repo: update sync algorithm. fewer threads, less complexity
This commit is contained in:
parent
95122e44fd
commit
a483759760
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue