From 773f0b07bfcd36464453fe113febe970c17b13af Mon Sep 17 00:00:00 2001
From: Patrick Simpson
Date: Wed, 8 Feb 2017 18:05:42 +0100
Subject: [PATCH] Added statistics on tasks. Added debug cycling of gab resync.
---
.../Features/DebugSupport/DebugDialog.cs | 75 +++++++++++++++++++
.../Features/DebugSupport/DebugInfo.cs | 30 ++++++--
.../DebugSupport/FeatureDebugSupport.cs | 12 ++-
.../Features/DebugSupport/Statistics.cs | 3 +
.../AcaciaZPushPlugin/Features/Feature.cs | 5 ++
.../Features/GAB/FeatureGAB.cs | 6 +-
.../AcaciaZPushPlugin/Stubs/IAddIn.cs | 1 +
.../Stubs/OutlookWrappers/AddInWrapper.cs | 5 ++
.../AcaciaZPushPlugin/ThisAddIn.cs | 10 +--
.../AcaciaZPushPlugin/Utils/Tasks.cs | 31 ++++++--
.../Utils/TasksBackground.cs | 11 +--
.../Utils/TasksMainThread.cs | 6 +-
.../Utils/TasksSynchronous.cs | 6 +-
13 files changed, 167 insertions(+), 34 deletions(-)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
index 8b057dc..acd8d91 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
@@ -47,6 +47,76 @@ namespace Acacia.Features.DebugSupport
Properties.Refresh();
}
+ private class DebugCycleInfo
+ {
+ private int cycleIndex = 0;
+ private int cycleCount;
+ private Timer timer = new Timer();
+ private GAB.FeatureGAB gab;
+ private int zeroCount = 1000;
+
+ public DebugCycleInfo(DebugDialog dlg, GAB.FeatureGAB gab, int count)
+ {
+ this.cycleCount = count;
+ this.gab = gab;
+ timer.Interval = 1000;
+ timer.Tick += (a, b) =>
+ {
+ dlg.Text = string.Format("Cycle {0} of {1}", cycleIndex + 1, cycleCount);
+ dlg.GarbageCollect();
+
+ if (((DebugInfo)dlg.Properties.SelectedObject).ActiveTasks == 0)
+ {
+ // Make sure the value is stable at zero
+ ++zeroCount;
+ if (zeroCount >= 3)
+ {
+ zeroCount = 0;
+ Logger.Instance.Debug(this, "CYCLER");
+ ++cycleIndex;
+
+ if (cycleIndex >= cycleCount)
+ {
+ timer.Stop();
+ dlg.Hide();
+ ThisAddIn.Instance.Quit();
+ }
+ else
+ {
+ DebugCycle();
+ }
+ }
+ }
+ };
+ }
+
+ public void Run()
+ {
+ timer.Start();
+ }
+
+ private void DebugCycle()
+ {
+ Tasks.Task(gab, "DebugCycle", () =>
+ {
+ gab.FullResync();
+ });
+ }
+
+ }
+
+ private DebugCycleInfo cycle;
+
+ internal void DebugCycle(int count)
+ {
+ GAB.FeatureGAB gab = ThisAddIn.Instance.GetFeature();
+ if (gab != null)
+ {
+ cycle = new DebugCycleInfo(this, gab, count);
+ cycle.Run();
+ }
+ }
+
#region Logging
private const string INDENT = "+";
@@ -89,6 +159,11 @@ namespace Acacia.Features.DebugSupport
private void buttonGC_Click(object sender, EventArgs e)
{
+ GarbageCollect();
+ }
+
+ private void GarbageCollect()
+ {
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugInfo.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugInfo.cs
index cc11799..e6ddead 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugInfo.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugInfo.cs
@@ -32,6 +32,7 @@ namespace Acacia.Features.DebugSupport
{
Version,
Memory,
+ Tasks,
Wrappers,
Misc,
System,
@@ -133,6 +134,25 @@ namespace Acacia.Features.DebugSupport
#endregion
+ #region Tasks
+
+ [DebugCategory(DebugCategory.Tasks)]
+ public string Threading
+ {
+ get { return Tasks.Executor.Name; }
+ }
+
+ [DebugCategory(DebugCategory.Tasks)]
+ public long ActiveTasks { get { return Statistics.StartedTasks - Statistics.FinishedTasks; } }
+
+ [DebugCategory(DebugCategory.Tasks)]
+ public long StartedTasks { get { return Statistics.StartedTasks; } }
+
+ [DebugCategory(DebugCategory.Tasks)]
+ public long FinishedTasks { get { return Statistics.FinishedTasks; } }
+
+ #endregion
+
#region Wrappers
[DebugCategory(DebugCategory.Wrappers)]
@@ -163,12 +183,6 @@ namespace Acacia.Features.DebugSupport
}
}
- [DebugCategory(DebugCategory.Misc)]
- public string Threading
- {
- get { return Tasks.Executor.Name; }
- }
-
[DebugCategory(DebugCategory.Misc)]
public bool ZPushSync
{
@@ -227,7 +241,7 @@ namespace Acacia.Features.DebugSupport
#endregion
-#region Outlook
+ #region Outlook
[DebugCategory(DebugCategory.System)]
public string OutlookVersion
@@ -247,7 +261,7 @@ namespace Acacia.Features.DebugSupport
}
}
-#endregion
+ #endregion
#region Helpers
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/FeatureDebugSupport.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/FeatureDebugSupport.cs
index 44315c5..12e43d5 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/FeatureDebugSupport.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/FeatureDebugSupport.cs
@@ -45,11 +45,19 @@ namespace Acacia.Features.DebugSupport
RegisterButton(this, "Settings", false, ShowSettings);
}
+
+ public override void AfterStartup()
+ {
+ ShowAbout();
+ }
+
#region About dialog
-
+
public void ShowAbout()
{
- new AboutDialog().ShowDialog();
+ DebugDialog dd = new DebugDialog();
+ dd.Show();
+ dd.DebugCycle(5);
}
#endregion
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/Statistics.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/Statistics.cs
index a1fcf69..f9d5a9c 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/Statistics.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/Statistics.cs
@@ -25,6 +25,9 @@ namespace Acacia.Features.DebugSupport
{
public static class Statistics
{
+ public static long StartedTasks;
+ public static long FinishedTasks;
+
public static long CreatedWrappers;
public static long DeletedWrappers;
public static long DisposedWrappers;
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Feature.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Feature.cs
index 3d0b1b2..32ab950 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Feature.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Feature.cs
@@ -226,6 +226,11 @@ namespace Acacia.Features
}
+ public virtual void AfterStartup()
+ {
+
+ }
+
#endregion
#region Z-Push channels
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs
index 53b1922..e53bf0e 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs
@@ -333,10 +333,14 @@ namespace Acacia.Features.GAB
}
// Do the resync
+ int remaining = _gabsByDomainName.Count;
foreach (GABHandler gab in _gabsByDomainName.Values)
{
Logger.Instance.Debug(this, "FullResync: Starting resync: {0}", gab.DisplayName);
- Tasks.Task(this, "FullResync", () => gab.FullResync());
+ Tasks.Task(this, "FullResync", () =>
+ {
+ gab.FullResync();
+ });
}
}
finally
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs
index 5489474..a581a84 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs
@@ -41,6 +41,7 @@ namespace Acacia.Stubs
/// Restarts the application
///
void Restart();
+ void Quit();
void InvokeUI(Action action);
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs
index 9b81921..444a6af 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs
@@ -57,6 +57,11 @@ namespace Acacia.Stubs.OutlookWrappers
_app.Quit();
}
+ public void Quit()
+ {
+ _app.Quit();
+ }
+
public event NSOutlook.ApplicationEvents_11_ItemLoadEventHandler ItemLoad
{
add { _app.ItemLoad += value; }
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs
index c1fb633..5db7f0d 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs
@@ -44,9 +44,6 @@ namespace Acacia
private set;
}
- // TODO: remove?
- private Control _dispatcher;
-
#region Features
///
@@ -92,10 +89,6 @@ namespace Acacia
int lcid = Application.LanguageSettings.get_LanguageID(Microsoft.Office.Core.MsoAppLanguageID.msoLanguageIDUI);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(lcid);
- // Create a dispatcher
- _dispatcher = new Control();
- _dispatcher.CreateControl();
-
// The synchronization context is needed to allow background tasks to jump back to the UI thread.
// It's null in older versions of .Net, this fixes that
if (SynchronizationContext.Current == null)
@@ -142,6 +135,9 @@ namespace Acacia
// Done
Logger.Instance.Debug(this, "Startup done");
Acacia.Features.DebugSupport.Statistics.StartupTime.Stop();
+ foreach (Feature feature in Features)
+ feature.AfterStartup();
+
}
catch (System.Exception e)
{
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs
index e616f85..9169b04 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs
@@ -15,9 +15,11 @@
/// Consult LICENSE file for details
using Acacia.Features;
+using Acacia.Features.DebugSupport;
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Threading;
using System.Windows.Forms;
namespace Acacia.Utils
@@ -64,10 +66,29 @@ namespace Acacia.Utils
}
- public interface TaskExecutor
+ public abstract class TaskExecutor
{
- string Name { get; }
- void ExecuteTask(AcaciaTask task);
+ public abstract string Name { get; }
+
+ public void AddTask(AcaciaTask task)
+ {
+ Interlocked.Increment(ref Statistics.StartedTasks);
+ EnqueueTask(task);
+ }
+
+ abstract protected void EnqueueTask(AcaciaTask task);
+
+ protected void PerformTask(AcaciaTask task)
+ {
+ try
+ {
+ task.Execute();
+ }
+ finally
+ {
+ Interlocked.Increment(ref Statistics.FinishedTasks);
+ }
+ }
}
public static class Tasks
@@ -103,12 +124,12 @@ namespace Acacia.Utils
public static void Task(Feature owner, string name, Action action)
{
- Executor.ExecuteTask(new AcaciaTask(owner, name, action));
+ Task(new AcaciaTask(owner, name, action));
}
public static void Task(AcaciaTask task)
{
- Executor.ExecuteTask(task);
+ Executor.AddTask(task);
}
}
}
\ No newline at end of file
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksBackground.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksBackground.cs
index 94da998..98acf58 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksBackground.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksBackground.cs
@@ -1,4 +1,6 @@
-/// Copyright 2016 Kopano b.v.
+
+using Acacia.Features.DebugSupport;
+/// Copyright 2016 Kopano b.v.
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License, version 3,
@@ -13,7 +15,6 @@
/// along with this program.If not, see.
///
/// Consult LICENSE file for details
-
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -40,15 +41,15 @@ namespace Acacia.Utils
while (!_tasks.IsCompleted)
{
AcaciaTask task = _tasks.Take();
- task.Execute();
+ PerformTask(task);
}
}
- public void ExecuteTask(AcaciaTask task)
+ protected override void EnqueueTask(AcaciaTask task)
{
_tasks.Add(task);
}
- public string Name { get { return "Background"; } }
+ override public string Name { get { return "Background"; } }
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksMainThread.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksMainThread.cs
index 2c91c12..0825f12 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksMainThread.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksMainThread.cs
@@ -73,7 +73,7 @@ namespace Acacia.Utils
{
AcaciaTask task = _tasks.Dequeue();
Logger.Instance.Trace(task.Id, "Beginning task");
- task.Execute();
+ PerformTask(task);
Logger.Instance.Info(task.Id, "Ending task: {0}ms", timer.ElapsedMilliseconds);
// Execute another task if available and we haven't taken too long.
} while (_tasks.Count > 0 && timer.ElapsedMilliseconds < 50);
@@ -99,7 +99,7 @@ namespace Acacia.Utils
///
/// The name, for debugging and logging.
/// The action to execute
- public void ExecuteTask(AcaciaTask task)
+ override protected void EnqueueTask(AcaciaTask task)
{
if (_init == InitState.Uninitialised)
{
@@ -112,6 +112,6 @@ namespace Acacia.Utils
_tasks.Enqueue(task);
}
- public string Name { get { return "MainThread"; } }
+ override public string Name { get { return "MainThread"; } }
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksSynchronous.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksSynchronous.cs
index 15b67ae..075ad5e 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksSynchronous.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/TasksSynchronous.cs
@@ -24,11 +24,11 @@ namespace Acacia.Utils
{
public class TasksSynchronous : TaskExecutor
{
- public void ExecuteTask(AcaciaTask task)
+ protected override void EnqueueTask(AcaciaTask task)
{
- task.Execute();
+ PerformTask(task);
}
- public string Name { get { return "Synchronous"; } }
+ override public string Name { get { return "Synchronous"; } }
}
}