mirror of
				https://github.com/Kopano-dev/kopano-ol-extension.git
				synced 2023-10-10 11:37:40 +00:00 
			
		
		
		
	Added statistics on tasks. Added debug cycling of gab resync.
This commit is contained in:
		| @@ -47,6 +47,76 @@ namespace Acacia.Features.DebugSupport | |||||||
|             Properties.Refresh(); |             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<GAB.FeatureGAB>(); | ||||||
|  |             if (gab != null) | ||||||
|  |             { | ||||||
|  |                 cycle = new DebugCycleInfo(this, gab, count); | ||||||
|  |                 cycle.Run(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         #region Logging |         #region Logging | ||||||
|  |  | ||||||
|         private const string INDENT = "+"; |         private const string INDENT = "+"; | ||||||
| @@ -89,6 +159,11 @@ namespace Acacia.Features.DebugSupport | |||||||
|  |  | ||||||
|         private void buttonGC_Click(object sender, EventArgs e) |         private void buttonGC_Click(object sender, EventArgs e) | ||||||
|         { |         { | ||||||
|  |             GarbageCollect(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void GarbageCollect() | ||||||
|  |         {  | ||||||
|             GC.Collect(); |             GC.Collect(); | ||||||
|             GC.WaitForPendingFinalizers(); |             GC.WaitForPendingFinalizers(); | ||||||
|             GC.Collect(); |             GC.Collect(); | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ namespace Acacia.Features.DebugSupport | |||||||
|     { |     { | ||||||
|         Version, |         Version, | ||||||
|         Memory, |         Memory, | ||||||
|  |         Tasks, | ||||||
|         Wrappers, |         Wrappers, | ||||||
|         Misc, |         Misc, | ||||||
|         System, |         System, | ||||||
| @@ -133,6 +134,25 @@ namespace Acacia.Features.DebugSupport | |||||||
|  |  | ||||||
|         #endregion |         #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 |         #region Wrappers | ||||||
|  |  | ||||||
|         [DebugCategory(DebugCategory.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)] |         [DebugCategory(DebugCategory.Misc)] | ||||||
|         public bool ZPushSync |         public bool ZPushSync | ||||||
|         { |         { | ||||||
| @@ -227,7 +241,7 @@ namespace Acacia.Features.DebugSupport | |||||||
|  |  | ||||||
|         #endregion |         #endregion | ||||||
|  |  | ||||||
| #region Outlook |         #region Outlook | ||||||
|  |  | ||||||
|         [DebugCategory(DebugCategory.System)] |         [DebugCategory(DebugCategory.System)] | ||||||
|         public string OutlookVersion |         public string OutlookVersion | ||||||
| @@ -247,7 +261,7 @@ namespace Acacia.Features.DebugSupport | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| #endregion |         #endregion | ||||||
|  |  | ||||||
| #region Helpers | #region Helpers | ||||||
|  |  | ||||||
|   | |||||||
| @@ -45,11 +45,19 @@ namespace Acacia.Features.DebugSupport | |||||||
|             RegisterButton(this, "Settings", false, ShowSettings); |             RegisterButton(this, "Settings", false, ShowSettings); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         public override void AfterStartup() | ||||||
|  |         { | ||||||
|  |             ShowAbout(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         #region About dialog |         #region About dialog | ||||||
|          |  | ||||||
|         public void ShowAbout() |         public void ShowAbout() | ||||||
|         { |         { | ||||||
|             new AboutDialog().ShowDialog(); |             DebugDialog dd = new DebugDialog(); | ||||||
|  |             dd.Show(); | ||||||
|  |             dd.DebugCycle(5); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #endregion |         #endregion | ||||||
|   | |||||||
| @@ -25,6 +25,9 @@ namespace Acacia.Features.DebugSupport | |||||||
| { | { | ||||||
|     public static class Statistics |     public static class Statistics | ||||||
|     { |     { | ||||||
|  |         public static long StartedTasks; | ||||||
|  |         public static long FinishedTasks; | ||||||
|  |  | ||||||
|         public static long CreatedWrappers; |         public static long CreatedWrappers; | ||||||
|         public static long DeletedWrappers; |         public static long DeletedWrappers; | ||||||
|         public static long DisposedWrappers; |         public static long DisposedWrappers; | ||||||
|   | |||||||
| @@ -226,6 +226,11 @@ namespace Acacia.Features | |||||||
|  |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public virtual void AfterStartup() | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|         #endregion |         #endregion | ||||||
|  |  | ||||||
|         #region Z-Push channels |         #region Z-Push channels | ||||||
|   | |||||||
| @@ -333,10 +333,14 @@ namespace Acacia.Features.GAB | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // Do the resync |                 // Do the resync | ||||||
|  |                 int remaining = _gabsByDomainName.Count; | ||||||
|                 foreach (GABHandler gab in _gabsByDomainName.Values) |                 foreach (GABHandler gab in _gabsByDomainName.Values) | ||||||
|                 { |                 { | ||||||
|                     Logger.Instance.Debug(this, "FullResync: Starting resync: {0}", gab.DisplayName); |                     Logger.Instance.Debug(this, "FullResync: Starting resync: {0}", gab.DisplayName); | ||||||
|                     Tasks.Task(this, "FullResync", () => gab.FullResync()); |                     Tasks.Task(this, "FullResync", () => | ||||||
|  |                     { | ||||||
|  |                         gab.FullResync(); | ||||||
|  |                     }); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             finally |             finally | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ namespace Acacia.Stubs | |||||||
|         /// Restarts the application |         /// Restarts the application | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         void Restart(); |         void Restart(); | ||||||
|  |         void Quit(); | ||||||
|  |  | ||||||
|         void InvokeUI(Action action); |         void InvokeUI(Action action); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -57,6 +57,11 @@ namespace Acacia.Stubs.OutlookWrappers | |||||||
|             _app.Quit(); |             _app.Quit(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public void Quit() | ||||||
|  |         { | ||||||
|  |             _app.Quit(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         public event NSOutlook.ApplicationEvents_11_ItemLoadEventHandler ItemLoad |         public event NSOutlook.ApplicationEvents_11_ItemLoadEventHandler ItemLoad | ||||||
|         { |         { | ||||||
|             add { _app.ItemLoad += value; } |             add { _app.ItemLoad += value; } | ||||||
|   | |||||||
| @@ -44,9 +44,6 @@ namespace Acacia | |||||||
|             private set; |             private set; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // TODO: remove? |  | ||||||
|         private Control _dispatcher; |  | ||||||
|  |  | ||||||
|         #region Features |         #region Features | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -92,10 +89,6 @@ namespace Acacia | |||||||
|                 int lcid = Application.LanguageSettings.get_LanguageID(Microsoft.Office.Core.MsoAppLanguageID.msoLanguageIDUI); |                 int lcid = Application.LanguageSettings.get_LanguageID(Microsoft.Office.Core.MsoAppLanguageID.msoLanguageIDUI); | ||||||
|                 Thread.CurrentThread.CurrentUICulture = new CultureInfo(lcid); |                 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. |                 // 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 |                 // It's null in older versions of .Net, this fixes that | ||||||
|                 if (SynchronizationContext.Current == null) |                 if (SynchronizationContext.Current == null) | ||||||
| @@ -142,6 +135,9 @@ namespace Acacia | |||||||
|                 // Done |                 // Done | ||||||
|                 Logger.Instance.Debug(this, "Startup done"); |                 Logger.Instance.Debug(this, "Startup done"); | ||||||
|                 Acacia.Features.DebugSupport.Statistics.StartupTime.Stop(); |                 Acacia.Features.DebugSupport.Statistics.StartupTime.Stop(); | ||||||
|  |                 foreach (Feature feature in Features) | ||||||
|  |                     feature.AfterStartup(); | ||||||
|  |  | ||||||
|             } |             } | ||||||
|             catch (System.Exception e) |             catch (System.Exception e) | ||||||
|             { |             { | ||||||
|   | |||||||
| @@ -15,9 +15,11 @@ | |||||||
| /// Consult LICENSE file for details | /// Consult LICENSE file for details | ||||||
|  |  | ||||||
| using Acacia.Features; | using Acacia.Features; | ||||||
|  | using Acacia.Features.DebugSupport; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
|  | using System.Threading; | ||||||
| using System.Windows.Forms; | using System.Windows.Forms; | ||||||
|  |  | ||||||
| namespace Acacia.Utils | namespace Acacia.Utils | ||||||
| @@ -64,10 +66,29 @@ namespace Acacia.Utils | |||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public interface TaskExecutor |     public abstract class TaskExecutor | ||||||
|     { |     { | ||||||
|         string Name { get; } |         public abstract string Name { get; } | ||||||
|         void ExecuteTask(AcaciaTask task); |  | ||||||
|  |         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 |     public static class Tasks | ||||||
| @@ -103,12 +124,12 @@ namespace Acacia.Utils | |||||||
|  |  | ||||||
|         public static void Task(Feature owner, string name, Action action) |         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) |         public static void Task(AcaciaTask task) | ||||||
|         { |         { | ||||||
|             Executor.ExecuteTask(task); |             Executor.AddTask(task); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -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 | /// 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, | /// it under the terms of the GNU Affero General Public License, version 3, | ||||||
| @@ -13,7 +15,6 @@ | |||||||
| /// along with this program.If not, see<http://www.gnu.org/licenses/>. | /// along with this program.If not, see<http://www.gnu.org/licenses/>. | ||||||
| ///  | ///  | ||||||
| /// Consult LICENSE file for details | /// Consult LICENSE file for details | ||||||
|  |  | ||||||
| using System; | using System; | ||||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| @@ -40,15 +41,15 @@ namespace Acacia.Utils | |||||||
|             while (!_tasks.IsCompleted) |             while (!_tasks.IsCompleted) | ||||||
|             { |             { | ||||||
|                 AcaciaTask task = _tasks.Take(); |                 AcaciaTask task = _tasks.Take(); | ||||||
|                 task.Execute(); |                 PerformTask(task); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void ExecuteTask(AcaciaTask task) |         protected override void EnqueueTask(AcaciaTask task) | ||||||
|         { |         { | ||||||
|             _tasks.Add(task); |             _tasks.Add(task); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public string Name { get { return "Background"; } } |         override public string Name { get { return "Background"; } } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -73,7 +73,7 @@ namespace Acacia.Utils | |||||||
|                 { |                 { | ||||||
|                     AcaciaTask task = _tasks.Dequeue(); |                     AcaciaTask task = _tasks.Dequeue(); | ||||||
|                     Logger.Instance.Trace(task.Id, "Beginning task"); |                     Logger.Instance.Trace(task.Id, "Beginning task"); | ||||||
|                     task.Execute(); |                     PerformTask(task); | ||||||
|                     Logger.Instance.Info(task.Id, "Ending task: {0}ms", timer.ElapsedMilliseconds); |                     Logger.Instance.Info(task.Id, "Ending task: {0}ms", timer.ElapsedMilliseconds); | ||||||
|                     // Execute another task if available and we haven't taken too long. |                     // Execute another task if available and we haven't taken too long. | ||||||
|                 } while (_tasks.Count > 0 && timer.ElapsedMilliseconds < 50); |                 } while (_tasks.Count > 0 && timer.ElapsedMilliseconds < 50); | ||||||
| @@ -99,7 +99,7 @@ namespace Acacia.Utils | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="name">The name, for debugging and logging.</param> |         /// <param name="name">The name, for debugging and logging.</param> | ||||||
|         /// <param name="action">The action to execute</param> |         /// <param name="action">The action to execute</param> | ||||||
|         public void ExecuteTask(AcaciaTask task) |         override protected void EnqueueTask(AcaciaTask task) | ||||||
|         { |         { | ||||||
|             if (_init == InitState.Uninitialised) |             if (_init == InitState.Uninitialised) | ||||||
|             { |             { | ||||||
| @@ -112,6 +112,6 @@ namespace Acacia.Utils | |||||||
|             _tasks.Enqueue(task); |             _tasks.Enqueue(task); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public string Name { get { return "MainThread"; } } |         override public string Name { get { return "MainThread"; } } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,11 +24,11 @@ namespace Acacia.Utils | |||||||
| { | { | ||||||
|     public class TasksSynchronous : TaskExecutor |     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"; } } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user