Skip to content

Commit

Permalink
Fixes issue #116
Browse files Browse the repository at this point in the history
  • Loading branch information
ryannewington committed Jan 23, 2018
1 parent 56c0f32 commit 0a11fed
Showing 1 changed file with 59 additions and 40 deletions.
99 changes: 59 additions & 40 deletions src/Lithnet.Miiserver.AutoSync/MAInterface/MAController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,19 @@ internal class MAController
protected static ConcurrentDictionary<Guid, SemaphoreSlim> AllMaLocalOperationLocks;

public delegate void SyncCompleteEventHandler(object sender, SyncCompleteEventArgs e);

public static event SyncCompleteEventHandler SyncComplete;

public delegate void RunProfileExecutionCompleteEventHandler(object sender, RunProfileExecutionCompleteEventArgs e);

public event RunProfileExecutionCompleteEventHandler RunProfileExecutionComplete;

public delegate void StateChangedEventHandler(object sender, MAStatusChangedEventArgs e);

public event StateChangedEventHandler StateChanged;

public delegate void MessageLoggedEventHandler(object sender, MessageLoggedEventArgs e);

public event MessageLoggedEventHandler MessageLogged;

private SemaphoreSlim localOperationLock;
Expand Down Expand Up @@ -684,31 +688,31 @@ private void Debug(string message)
#endif
}

private void Wait(TimeSpan duration, string name, CancellationTokenSource ts, [CallerMemberName]string caller = "")
private void Wait(TimeSpan duration, string name, CancellationTokenSource ts, [CallerMemberName] string caller = "")
{
ts.Token.ThrowIfCancellationRequested();
this.Debug($"SLEEP: {name}: {duration}: {caller}");
ts.Token.WaitHandle.WaitOne(duration);
ts.Token.ThrowIfCancellationRequested();
}

private void Wait(WaitHandle wh, string name, CancellationTokenSource ts, [CallerMemberName]string caller = "")
private void Wait(WaitHandle wh, string name, CancellationTokenSource ts, [CallerMemberName] string caller = "")
{
this.Debug($"LOCK: WAIT: {name}: {caller}");
WaitHandle.WaitAny(new[] { wh, ts.Token.WaitHandle });
ts.Token.ThrowIfCancellationRequested();
this.Debug($"LOCK: CLEARED: {name}: {caller}");
}

private void WaitAndTakeLock(SemaphoreSlim mre, string name, CancellationTokenSource ts, [CallerMemberName]string caller = "")
private void WaitAndTakeLock(SemaphoreSlim mre, string name, CancellationTokenSource ts, [CallerMemberName] string caller = "")
{
this.Debug($"LOCK: WAIT: {name}: {caller}");
mre.Wait(ts.Token);
ts.Token.ThrowIfCancellationRequested();
this.Debug($"LOCK: TAKE: {name}: {caller}");
}

private void WaitAndTakeLockWithSemaphore(EventWaitHandle mre, SemaphoreSlim sem, string name, CancellationTokenSource ts, [CallerMemberName]string caller = "")
private void WaitAndTakeLockWithSemaphore(EventWaitHandle mre, SemaphoreSlim sem, string name, CancellationTokenSource ts, [CallerMemberName] string caller = "")
{
bool gotLock = false;

Expand All @@ -733,7 +737,7 @@ private void WaitAndTakeLockWithSemaphore(EventWaitHandle mre, SemaphoreSlim sem
}
}

private void Wait(WaitHandle[] waitHandles, string name, CancellationTokenSource ts, [CallerMemberName]string caller = "")
private void Wait(WaitHandle[] waitHandles, string name, CancellationTokenSource ts, [CallerMemberName] string caller = "")
{
this.Debug($"LOCK: WAIT: {name}: {caller}");
while (!WaitHandle.WaitAll(waitHandles, 1000))
Expand All @@ -752,7 +756,7 @@ private void TakeLockUnsafe(EventWaitHandle mre, string name, CancellationTokenS
ts.Token.ThrowIfCancellationRequested();
}

private void ReleaseLock(EventWaitHandle mre, string name, [CallerMemberName]string caller = "")
private void ReleaseLock(EventWaitHandle mre, string name, [CallerMemberName] string caller = "")
{
this.Debug($"LOCK: RELEASE: {name}: {caller}");
mre.Set();
Expand Down Expand Up @@ -1912,50 +1916,28 @@ private void CheckAndQueueUnmanagedChanges()
this.WaitAndTakeLock(this.localOperationLock, nameof(this.localOperationLock), this.controllerCancellationTokenSource);
hasLocalLock = true;

this.Trace("Checking for unmanaged changes");
RunDetails run = this.ma.GetLastRun();
bool hasRun = this.lastRunNumber > 0;
int lastKnownRun = this.lastRunNumber;

if (run == null || this.lastRunNumber == run.RunNumber)
{
return;
}

this.Trace($"Unprocessed changes detected. Last recorded run: {this.lastRunNumber}. Last run in sync engine: {run.RunNumber}");
RunDetails run = this.ma.GetLastRun();
this.lastRunNumber = run?.RunNumber ?? 0;

this.lastRunNumber = run.RunNumber;
this.Trace("Checking for unmanaged changes");

foreach (PartitionConfiguration c in this.GetPartitionsRequiringExport())
if (hasRun && run != null)
{
if (c.ExportRunProfileName != null)
if (lastKnownRun == this.lastRunNumber)
{
ExecutionParameters p = new ExecutionParameters(c.ExportRunProfileName);
this.AddPendingActionIfNotQueued(p, "Pending export check");
return;
}
}

if (run?.StepDetails != null)
{
foreach (StepDetails step in run.StepDetails)
{
if (step.HasUnconfirmedExports())
{
PartitionConfiguration c = this.Configuration.Partitions.GetActiveItemOrNull(step.StepDefinition.Partition);
this.Trace($"Unprocessed changes detected. Last recorded run: {lastKnownRun}. Last run in sync engine: {run.RunNumber}");

if (c != null)
{
this.AddPendingActionIfNotQueued(new ExecutionParameters(c.ConfirmingImportRunProfileName), "Unconfirmed export check");
}
}
}
this.PerformPostRunActions(run);
}

foreach (PartitionConfiguration c in this.GetPartitionsRequiringSync())
else
{
if (c.ExportRunProfileName != null)
{
ExecutionParameters p = new ExecutionParameters(c.DeltaSyncRunProfileName);
this.AddPendingActionIfNotQueued(p, "Staged import check");
}
this.CheckAndQueueUnmanagedChanges(run);
}
}
finally
Expand All @@ -1968,6 +1950,43 @@ private void CheckAndQueueUnmanagedChanges()
}
}

private void CheckAndQueueUnmanagedChanges(RunDetails run)
{
foreach (PartitionConfiguration c in this.GetPartitionsRequiringExport())
{
if (c.ExportRunProfileName != null)
{
ExecutionParameters p = new ExecutionParameters(c.ExportRunProfileName);
this.AddPendingActionIfNotQueued(p, "Pending export check");
}
}

if (run?.StepDetails != null)
{
foreach (StepDetails step in run.StepDetails)
{
if (step.HasUnconfirmedExports())
{
PartitionConfiguration c = this.Configuration.Partitions.GetActiveItemOrNull(step.StepDefinition.Partition);

if (c != null)
{
this.AddPendingActionIfNotQueued(new ExecutionParameters(c.ConfirmingImportRunProfileName), "Unconfirmed export check");
}
}
}
}

foreach (PartitionConfiguration c in this.GetPartitionsRequiringSync())
{
if (c.ExportRunProfileName != null)
{
ExecutionParameters p = new ExecutionParameters(c.DeltaSyncRunProfileName);
this.AddPendingActionIfNotQueued(p, "Staged import check");
}
}
}

private void MAController_SyncComplete(object sender, SyncCompleteEventArgs e)
{
if (e.TargetMA != this.ma.ID)
Expand Down

0 comments on commit 0a11fed

Please sign in to comment.