From 4d21e18641a6db6a1c38bcfc63bda8c222297440 Mon Sep 17 00:00:00 2001
From: Patrick Simpson
Date: Mon, 31 Jul 2017 15:11:18 +0300
Subject: [PATCH] [KOE-103] Added full logging of wrapper/item events using the
TraceExtra log level
---
.../DebugSupport/DebugDialog.Designer.cs | 81 +++++++++-
.../Features/DebugSupport/DebugDialog.cs | 76 ++++++++-
.../Features/DebugSupport/DebugDialog.resx | 150 +++++++++++++++++-
.../AcaciaZPushPlugin/Stubs/IComWrapper.cs | 9 +-
.../Stubs/OutlookWrappers/ComWrapper.cs | 7 +
.../Stubs/OutlookWrappers/OutlookWrapper.cs | 11 ++
.../Utils/DisposableTracer.cs | 2 +-
.../Utils/DisposableTracerDummy.cs | 3 +-
.../Utils/DisposableTracerFull.cs | 88 +++++++++-
.../Utils/DisposableWrapper.cs | 5 +-
.../AcaciaZPushPlugin/Utils/MailEvents.cs | 45 ++++--
11 files changed, 443 insertions(+), 34 deletions(-)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.Designer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.Designer.cs
index 6113b5b..303f96e 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.Designer.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.Designer.cs
@@ -46,6 +46,12 @@
this._tabs = new System.Windows.Forms.TabControl();
this._tabProperties = new System.Windows.Forms.TabPage();
this.Properties = new System.Windows.Forms.PropertyGrid();
+ this._tabWrappers = new System.Windows.Forms.TabPage();
+ this._layoutWrappers = new System.Windows.Forms.TableLayoutPanel();
+ this.listWrappers = new System.Windows.Forms.ListView();
+ this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this._tabWrapperTypes = new System.Windows.Forms.TabPage();
this.listWrapperTypes = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
@@ -59,10 +65,12 @@
this._tabItemEvents = new System.Windows.Forms.TabPage();
this._layoutItemEvents = new System.Windows.Forms.TableLayoutPanel();
this.listItemEventDetails = new System.Windows.Forms.ListView();
+ this.columnProperties = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.listItemEvents = new System.Windows.Forms.ListView();
+ this.columnItemId = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this._layoutEventsButtons = new System.Windows.Forms.FlowLayoutPanel();
this.buttonCleanGC = new System.Windows.Forms.Button();
- this.columnProperties = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.buttonCopyFilter = new System.Windows.Forms.Button();
columnMethod = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
columnFile = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
columnLine = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
@@ -75,6 +83,8 @@
this.flowButtons.SuspendLayout();
this._tabs.SuspendLayout();
this._tabProperties.SuspendLayout();
+ this._tabWrappers.SuspendLayout();
+ this._layoutWrappers.SuspendLayout();
this._tabWrapperTypes.SuspendLayout();
this._tabWrapperLocations.SuspendLayout();
this._layoutLocations.SuspendLayout();
@@ -163,6 +173,7 @@
// _tabs
//
this._tabs.Controls.Add(this._tabProperties);
+ this._tabs.Controls.Add(this._tabWrappers);
this._tabs.Controls.Add(this._tabWrapperTypes);
this._tabs.Controls.Add(this._tabWrapperLocations);
this._tabs.Controls.Add(this._tabItemEvents);
@@ -185,6 +196,45 @@
this.Properties.PropertySort = System.Windows.Forms.PropertySort.Categorized;
this.Properties.ToolbarVisible = false;
//
+ // _tabWrappers
+ //
+ this._tabWrappers.Controls.Add(this._layoutWrappers);
+ resources.ApplyResources(this._tabWrappers, "_tabWrappers");
+ this._tabWrappers.Name = "_tabWrappers";
+ this._tabWrappers.UseVisualStyleBackColor = true;
+ //
+ // _layoutWrappers
+ //
+ resources.ApplyResources(this._layoutWrappers, "_layoutWrappers");
+ this._layoutWrappers.Controls.Add(this.listWrappers, 0, 0);
+ this._layoutWrappers.Name = "_layoutWrappers";
+ //
+ // listWrappers
+ //
+ this.listWrappers.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeader5,
+ this.columnHeader6,
+ this.columnHeader7});
+ resources.ApplyResources(this.listWrappers, "listWrappers");
+ this.listWrappers.FullRowSelect = true;
+ this.listWrappers.HideSelection = false;
+ this.listWrappers.MultiSelect = false;
+ this.listWrappers.Name = "listWrappers";
+ this.listWrappers.UseCompatibleStateImageBehavior = false;
+ this.listWrappers.View = System.Windows.Forms.View.Details;
+ //
+ // columnHeader5
+ //
+ resources.ApplyResources(this.columnHeader5, "columnHeader5");
+ //
+ // columnHeader6
+ //
+ resources.ApplyResources(this.columnHeader6, "columnHeader6");
+ //
+ // columnHeader7
+ //
+ resources.ApplyResources(this.columnHeader7, "columnHeader7");
+ //
// _tabWrapperTypes
//
this._tabWrapperTypes.Controls.Add(this.listWrapperTypes);
@@ -293,11 +343,16 @@
this.listItemEventDetails.UseCompatibleStateImageBehavior = false;
this.listItemEventDetails.View = System.Windows.Forms.View.Details;
//
+ // columnProperties
+ //
+ resources.ApplyResources(this.columnProperties, "columnProperties");
+ //
// listItemEvents
//
this.listItemEvents.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
columnId,
columnEvents,
+ this.columnItemId,
columnSubject});
resources.ApplyResources(this.listItemEvents, "listItemEvents");
this.listItemEvents.FullRowSelect = true;
@@ -309,11 +364,17 @@
this.listItemEvents.UseCompatibleStateImageBehavior = false;
this.listItemEvents.View = System.Windows.Forms.View.Details;
this.listItemEvents.SelectedIndexChanged += new System.EventHandler(this.listItemEvents_SelectedIndexChanged);
+ this.listItemEvents.DoubleClick += new System.EventHandler(this.listItemEvents_DoubleClick);
+ //
+ // columnItemId
+ //
+ resources.ApplyResources(this.columnItemId, "columnItemId");
//
// _layoutEventsButtons
//
resources.ApplyResources(this._layoutEventsButtons, "_layoutEventsButtons");
this._layoutEventsButtons.Controls.Add(this.buttonCleanGC);
+ this._layoutEventsButtons.Controls.Add(this.buttonCopyFilter);
this._layoutEventsButtons.Name = "_layoutEventsButtons";
//
// buttonCleanGC
@@ -323,9 +384,12 @@
this.buttonCleanGC.UseVisualStyleBackColor = true;
this.buttonCleanGC.Click += new System.EventHandler(this.buttonCleanGC_Click);
//
- // columnProperties
+ // buttonCopyFilter
//
- resources.ApplyResources(this.columnProperties, "columnProperties");
+ resources.ApplyResources(this.buttonCopyFilter, "buttonCopyFilter");
+ this.buttonCopyFilter.Name = "buttonCopyFilter";
+ this.buttonCopyFilter.UseVisualStyleBackColor = true;
+ this.buttonCopyFilter.Click += new System.EventHandler(this.buttonCopyFilter_Click);
//
// DebugDialog
//
@@ -336,12 +400,15 @@
this.MinimizeBox = false;
this.Name = "DebugDialog";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
+ this.TopMost = true;
this.tableMain.ResumeLayout(false);
this.tableMain.PerformLayout();
this.flowButtons.ResumeLayout(false);
this.flowButtons.PerformLayout();
this._tabs.ResumeLayout(false);
this._tabProperties.ResumeLayout(false);
+ this._tabWrappers.ResumeLayout(false);
+ this._layoutWrappers.ResumeLayout(false);
this._tabWrapperTypes.ResumeLayout(false);
this._tabWrapperLocations.ResumeLayout(false);
this._layoutLocations.ResumeLayout(false);
@@ -383,5 +450,13 @@
private System.Windows.Forms.FlowLayoutPanel _layoutEventsButtons;
private System.Windows.Forms.Button buttonCleanGC;
private System.Windows.Forms.ColumnHeader columnProperties;
+ private System.Windows.Forms.ColumnHeader columnItemId;
+ private System.Windows.Forms.TabPage _tabWrappers;
+ private System.Windows.Forms.TableLayoutPanel _layoutWrappers;
+ private System.Windows.Forms.ListView listWrappers;
+ private System.Windows.Forms.ColumnHeader columnHeader5;
+ private System.Windows.Forms.ColumnHeader columnHeader6;
+ private System.Windows.Forms.ColumnHeader columnHeader7;
+ private System.Windows.Forms.Button buttonCopyFilter;
}
}
\ No newline at end of file
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
index f869b2a..7e2af22 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
@@ -51,6 +51,7 @@ namespace Acacia.Features.DebugSupport
}
else
{
+ listWrappers.ListViewItemSorter = new WrapperCountSorter(0);
listWrapperTypes.ListViewItemSorter = new WrapperCountSorter(1);
listWrapperLocations.ListViewItemSorter = new WrapperCountSorter(1);
listItemEvents.ListViewItemSorter = new WrapperCountSorter(0);
@@ -77,6 +78,25 @@ namespace Acacia.Features.DebugSupport
if (_tracer == null)
return;
+ // Wrappers
+ listWrappers.Items.Clear();
+ foreach (DisposableTracerFull.DisposableInfo wrapperInfo in _tracer.GetActive())
+ {
+ Type type = wrapperInfo.WrapperType;
+ string name = type.Name;
+ if (type.DeclaringType != null)
+ name = type.DeclaringType.Name + "." + name;
+
+ ListViewItem item = new ListViewItem(wrapperInfo.TraceId.ToString());
+ item.Tag = wrapperInfo;
+ item.ToolTipText = type.FullName;
+ item.SubItems.Add(name);
+ item.SubItems.Add(wrapperInfo.Subject);
+ listWrappers.Items.Add(item);
+ }
+ foreach (ColumnHeader header in listWrappers.Columns)
+ header.Width = -2;
+
// Wrapper types
listWrapperTypes.Items.Clear();
foreach(KeyValuePair type in _tracer.GetTypes())
@@ -90,9 +110,8 @@ namespace Acacia.Features.DebugSupport
item.SubItems.Add(type.Value.ToString());
listWrapperTypes.Items.Add(item);
}
-
- listWrapperTypes.Columns[0].Width = -2;
- listWrapperTypes.Columns[1].Width = -2;
+ foreach (ColumnHeader header in listWrapperTypes.Columns)
+ header.Width = -2;
// Wrapper locations
listWrapperLocations.Items.Clear();
@@ -103,9 +122,8 @@ namespace Acacia.Features.DebugSupport
item.Tag = entry.Key;
listWrapperLocations.Items.Add(item);
}
-
- listWrapperLocations.Columns[0].Width = -2;
- listWrapperLocations.Columns[1].Width = -2;
+ foreach (ColumnHeader header in listWrapperLocations.Columns)
+ header.Width = -2;
}
private class WrapperCountSorter : IComparer
@@ -143,6 +161,19 @@ namespace Acacia.Features.DebugSupport
header.Width = -2;
}
+ private void SelectWrapper(int id)
+ {
+ foreach(ListViewItem item in listWrappers.Items)
+ {
+ if (((DisposableTracerFull.DisposableInfo)item.Tag).TraceId == id)
+ {
+ item.Selected = true;
+ break;
+ }
+ }
+ _tabs.SelectedTab = _tabWrappers;
+ }
+
#endregion
#region Item events
@@ -158,6 +189,7 @@ namespace Acacia.Features.DebugSupport
ListViewItem item = new ListViewItem(events.Id);
item.Tag = events;
item.SubItems.Add(string.Join(", ", events.GetEvents()));
+ item.SubItems.Add(events.ItemId.ToString());
item.SubItems.Add(events.Subject);
listItemEvents.Items.Add(item);
}
@@ -187,12 +219,44 @@ namespace Acacia.Features.DebugSupport
header.Width = -2;
}
+ private void listItemEvents_DoubleClick(object sender, EventArgs e)
+ {
+ if (listItemEvents.SelectedItems.Count > 0)
+ {
+ MailEvents.MailEventDebug events = (MailEvents.MailEventDebug)listItemEvents.SelectedItems[0].Tag;
+
+ // Switch to wrappers tab and select the wrapper
+ SelectWrapper(events.ItemId);
+ }
+ }
+
private void buttonCleanGC_Click(object sender, EventArgs e)
{
MailEvents.MailEventsDebugClean();
RefreshItemEvents();
}
+ private void buttonCopyFilter_Click(object sender, EventArgs e)
+ {
+ if (listItemEvents.SelectedItems.Count > 0)
+ {
+ MailEvents.MailEventDebug events = (MailEvents.MailEventDebug)listItemEvents.SelectedItems[0].Tag;
+ List ids = new List();
+ foreach(ListViewItem item in listItemEvents.Items)
+ {
+ MailEvents.MailEventDebug current = (MailEvents.MailEventDebug)item.Tag;
+ if (current.Subject?.Equals(events.Subject) == true)
+ {
+ ids.Add(": " + current.Id);
+ ids.Add(": " + current.ItemId.ToString());
+ }
+ }
+
+ string filter = string.Join("|", ids);
+ Clipboard.SetText(filter);
+ }
+ }
+
#endregion
#region Cycling
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.resx b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.resx
index 191a93d..775337a 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.resx
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.resx
@@ -402,6 +402,96 @@
0
+
+ 1
+
+
+ Id
+
+
+ Type
+
+
+ Subject
+
+
+ Fill
+
+
+ 3, 3
+
+
+ 603, 651
+
+
+ 0
+
+
+ listWrappers
+
+
+ System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ _layoutWrappers
+
+
+ 0
+
+
+ Fill
+
+
+ 0, 0
+
+
+ 1
+
+
+ 609, 657
+
+
+ 0
+
+
+ _layoutWrappers
+
+
+ System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ _tabWrappers
+
+
+ 0
+
+
+ <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="listWrappers" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,50" /><Rows Styles="Percent,50" /></TableLayoutSettings>
+
+
+ 4, 33
+
+
+ 609, 657
+
+
+ 4
+
+
+ Wrappers
+
+
+ _tabWrappers
+
+
+ System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ _tabs
+
+
+ 1
+
Type
@@ -463,7 +553,7 @@
_tabs
- 1
+ 2
1
@@ -583,7 +673,7 @@
_tabs
- 2
+ 3
1
@@ -615,6 +705,9 @@
0
+
+ ItemId
+
Fill
@@ -672,6 +765,33 @@
0
+
+ True
+
+
+ 350, 3
+
+
+ 109, 35
+
+
+ 1
+
+
+ Copy filter
+
+
+ buttonCopyFilter
+
+
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ _layoutEventsButtons
+
+
+ 1
+
Fill
@@ -754,7 +874,7 @@
_tabs
- 3
+ 4
Fill
@@ -879,6 +999,24 @@
System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ columnHeader5
+
+
+ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ columnHeader6
+
+
+ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ columnHeader7
+
+
+ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
columnHeader1
@@ -909,6 +1047,12 @@
System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ columnItemId
+
+
+ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
DebugDialog
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IComWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IComWrapper.cs
index dfb0514..6ec06cc 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IComWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IComWrapper.cs
@@ -21,7 +21,14 @@ using System.Threading.Tasks;
namespace Acacia.Stubs
{
- public interface IComWrapper : IDisposable
+ public interface IDebugDisposable : IDisposable
+ {
+ int TraceId { get; }
+ string DebugContext { get; }
+ bool IsDisposed { get; }
+ }
+
+ public interface IComWrapper : IDebugDisposable
{
bool MustRelease { get; set; }
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs
index b8d4930..736ce6d 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs
@@ -50,7 +50,14 @@ namespace Acacia.Stubs.OutlookWrappers
{
ComRelease.Release(_item);
}
+ else
+ {
+
+ }
}
+
+ virtual public string DebugContext { get { return null; } }
+
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs
index 634eac1..4a2b65f 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs
@@ -193,5 +193,16 @@ namespace Acacia.Stubs.OutlookWrappers
public override abstract string ToString();
public abstract IStore GetStore();
public abstract void Delete();
+
+ override public string DebugContext
+ {
+ get
+ {
+ if (this is IItem)
+ return ((IItem)this).Subject;
+ return EntryID;
+ }
+ }
+
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracer.cs
index d1fc373..193471f 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracer.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracer.cs
@@ -8,7 +8,7 @@ namespace Acacia.Utils
{
public interface DisposableTracer
{
- void Created(DisposableWrapper wrapper);
+ void Created(DisposableWrapper wrapper, out int id);
void Deleted(DisposableWrapper wrapper, bool wasDisposed);
void Disposed(DisposableWrapper wrapper);
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerDummy.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerDummy.cs
index 415ccf8..1aa8ab6 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerDummy.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerDummy.cs
@@ -8,8 +8,9 @@ namespace Acacia.Utils
{
public class DisposableTracerDummy : DisposableTracer
{
- public void Created(DisposableWrapper wrapper)
+ public void Created(DisposableWrapper wrapper, out int id)
{
+ id = -1;
}
public void Deleted(DisposableWrapper wrapper, bool wasDisposed)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerFull.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerFull.cs
index 37f5c37..af528b9 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerFull.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableTracerFull.cs
@@ -7,6 +7,8 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
+using System.Threading;
+using Acacia.Stubs;
namespace Acacia.Utils
{
@@ -145,25 +147,49 @@ namespace Acacia.Utils
}
}
+ private int _nextId;
+
private readonly ConcurrentDictionary _types = new ConcurrentDictionary();
private readonly ConcurrentDictionary _locations = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary _all = new ConcurrentDictionary();
- public void Created(DisposableWrapper wrapper)
+ private void LogWrapperEvent(DisposableWrapper wrapper, int id, string name, bool stack)
{
+ IDebugDisposable debug = wrapper as IDebugDisposable;
+ Logger.Instance.TraceExtra(typeof(DisposableTracerFull), "{0}: {1}, disposed={2}, release={3}{4}", name, id,
+ debug?.IsDisposed,
+ (wrapper as IComWrapper)?.MustRelease,
+ stack ? ("\n" + new CustomTrace(new StackTrace(2, true)).ToString()) : "");
+ }
+
+ public void Created(DisposableWrapper wrapper, out int id)
+ {
+ id = Interlocked.Increment(ref _nextId);
+ _all.TryAdd(id, new DisposableInfoImpl(wrapper, id));
_types.AddOrUpdate(wrapper.GetType(), 1, (i, value) => value + 1);
_locations.AddOrUpdate(new CustomTrace(wrapper.StackTrace), 1, (i, value) => value + 1);
+ LogWrapperEvent(wrapper, id, "Created", true);
}
public void Deleted(DisposableWrapper wrapper, bool wasDisposed)
{
if (!wasDisposed)
{
- _types.AddOrUpdate(wrapper.GetType(), 0, (i, value) => value - 1);
- _locations.AddOrUpdate(new CustomTrace(wrapper.StackTrace), 0, (i, value) => value - 1);
+ DisposedInternal(wrapper);
}
+
+ DisposableInfo dummy;
+ _all.TryRemove(wrapper.TraceId, out dummy);
+ LogWrapperEvent(wrapper, wrapper.TraceId, "Deleted", true);
}
public void Disposed(DisposableWrapper wrapper)
+ {
+ LogWrapperEvent(wrapper, wrapper.TraceId, "Disposed", true);
+ DisposedInternal(wrapper);
+ }
+
+ private void DisposedInternal(DisposableWrapper wrapper)
{
_types.AddOrUpdate(wrapper.GetType(), 0, (i, value) => value - 1);
_locations.AddOrUpdate(new CustomTrace(wrapper.StackTrace), 0, (i, value) => value - 1);
@@ -178,5 +204,61 @@ namespace Acacia.Utils
{
return _locations;
}
+
+ public interface DisposableInfo
+ {
+ int TraceId { get; }
+ Type WrapperType { get; }
+ string Subject { get; }
+ }
+
+ private class DisposableInfoImpl : DisposableInfo
+ {
+ public int TraceId { get; private set; }
+ public Type WrapperType { get; private set; }
+
+ private readonly WeakReference _item;
+ public string Subject
+ {
+ get
+ {
+ if (_item == null)
+ return null;
+
+ IDebugDisposable item;
+ if (_item.TryGetTarget(out item))
+ {
+ if (item.IsDisposed)
+ return "";
+
+ try
+ {
+ return item.DebugContext;
+ }
+ catch(Exception)
+ {
+ // Exception may happen if the item is not fully loaded yet
+ return "";
+ }
+ }
+ return "";
+ }
+ }
+
+ public DisposableInfoImpl(DisposableWrapper wrapper, int id)
+ {
+ TraceId = id;
+ WrapperType = wrapper.GetType();
+ if (wrapper is IDebugDisposable)
+ {
+ _item = new WeakReference((IDebugDisposable)wrapper);
+ }
+ }
+ }
+
+ public IEnumerable GetActive()
+ {
+ return _all.Values;
+ }
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableWrapper.cs
index 8a0010c..4e78b7c 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableWrapper.cs
@@ -42,12 +42,15 @@ namespace Acacia.Utils
private bool _isDisposed;
public readonly System.Diagnostics.StackTrace StackTrace;
+ private readonly int _traceId;
+ public int TraceId { get { return _traceId; } }
+ public bool IsDisposed { get { return _isDisposed; } }
protected DisposableWrapper()
{
Interlocked.Increment(ref Statistics.CreatedWrappers);
this.StackTrace = new System.Diagnostics.StackTrace(1, true);
- tracer.Created(this);
+ tracer.Created(this, out _traceId);
}
~DisposableWrapper()
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs
index 1933fd6..9ca2e3e 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs
@@ -377,15 +377,6 @@ namespace Acacia.Utils
GC
}
- public interface MailEventDebug
- {
- string Id { get; }
- string Subject { get; }
- int GetEventCount(DebugEvent which);
- IEnumerable GetEvents();
- IEnumerable Properties { get; }
- }
-
public static IEnumerable MailEventsDebug
{
get { return _hookers?.Values; }
@@ -405,24 +396,32 @@ namespace Acacia.Utils
private static readonly ConcurrentDictionary _hookers =
GlobalOptions.INSTANCE.WrapperTrace ? new ConcurrentDictionary() : null;
- private static int _nextHookerId;
- private class MailEventHooker : DisposableWrapper
+ private class MailEventHooker : DisposableWrapper, IDebugDisposable
{
private readonly MailEventDebugImpl _debug;
private IItem _item;
private readonly MailEvents _events;
+ public string DebugContext
+ {
+ get
+ {
+ return "Events for " + _item.DebugContext;
+ }
+ }
+
public MailEventHooker(IItem item, MailEvents events)
{
+ this._item = item;
+ this._events = events;
+
if (_hookers != null)
{
- _debug = new MailEventDebugImpl(Interlocked.Increment(ref _nextHookerId));
+ _debug = new MailEventDebugImpl(TraceId, _item);
_hookers.TryAdd(_debug._id, _debug);
}
- this._item = item;
- this._events = events;
HookEvents(true);
}
@@ -535,21 +534,34 @@ namespace Acacia.Utils
}
}
+ public interface MailEventDebug
+ {
+ string Id { get; }
+ int ItemId { get; }
+ string Subject { get; }
+ int GetEventCount(DebugEvent which);
+ IEnumerable GetEvents();
+ IEnumerable Properties { get; }
+ }
+
+
private class MailEventDebugImpl : MailEventDebug
{
private readonly ConcurrentDictionary _eventCounts = new ConcurrentDictionary();
private readonly List _properties = new List();
public readonly int _id;
+ private readonly int _itemId;
public DateTime? GCTime
{
get;
private set;
}
- public MailEventDebugImpl(int id)
+ public MailEventDebugImpl(int id, IItem item)
{
this._id = id;
+ _itemId = item.TraceId;
}
public int GetEventCount(DebugEvent which)
@@ -564,6 +576,8 @@ namespace Acacia.Utils
_eventCounts.AddOrUpdate(which, 1, (i, value) => value + 1);
if (property != null)
_properties.Add(property);
+ Logger.Instance.TraceExtra(typeof(DisposableTracerFull), "{0}: {1}{2}", _itemId, which, property,
+ property == null ? "" : (" " + property));
}
public IEnumerable GetEvents()
@@ -582,6 +596,7 @@ namespace Acacia.Utils
}
public string Id { get { return _id.ToString(); } }
+ public int ItemId { get { return _itemId; } }
public string Subject { get; set; }
}