[KOE-103] Added full logging of wrapper/item events using the TraceExtra log level

This commit is contained in:
Patrick Simpson 2017-07-31 15:11:18 +03:00
parent e05768a399
commit 4d21e18641
11 changed files with 443 additions and 34 deletions

View File

@ -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;
}
}

View File

@ -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, int> 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<string> ids = new List<string>();
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

View File

@ -402,6 +402,96 @@
<data name="&gt;&gt;_tabProperties.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="_layoutWrappers.ColumnCount" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="columnHeader5.Text" xml:space="preserve">
<value>Id</value>
</data>
<data name="columnHeader6.Text" xml:space="preserve">
<value>Type</value>
</data>
<data name="columnHeader7.Text" xml:space="preserve">
<value>Subject</value>
</data>
<data name="listWrappers.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="listWrappers.Location" type="System.Drawing.Point, System.Drawing">
<value>3, 3</value>
</data>
<data name="listWrappers.Size" type="System.Drawing.Size, System.Drawing">
<value>603, 651</value>
</data>
<data name="listWrappers.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="&gt;&gt;listWrappers.Name" xml:space="preserve">
<value>listWrappers</value>
</data>
<data name="&gt;&gt;listWrappers.Type" xml:space="preserve">
<value>System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;listWrappers.Parent" xml:space="preserve">
<value>_layoutWrappers</value>
</data>
<data name="&gt;&gt;listWrappers.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="_layoutWrappers.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="_layoutWrappers.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
</data>
<data name="_layoutWrappers.RowCount" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="_layoutWrappers.Size" type="System.Drawing.Size, System.Drawing">
<value>609, 657</value>
</data>
<data name="_layoutWrappers.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="&gt;&gt;_layoutWrappers.Name" xml:space="preserve">
<value>_layoutWrappers</value>
</data>
<data name="&gt;&gt;_layoutWrappers.Type" xml:space="preserve">
<value>System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;_layoutWrappers.Parent" xml:space="preserve">
<value>_tabWrappers</value>
</data>
<data name="&gt;&gt;_layoutWrappers.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="_layoutWrappers.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="listWrappers" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="Percent,50" /&gt;&lt;Rows Styles="Percent,50" /&gt;&lt;/TableLayoutSettings&gt;</value>
</data>
<data name="_tabWrappers.Location" type="System.Drawing.Point, System.Drawing">
<value>4, 33</value>
</data>
<data name="_tabWrappers.Size" type="System.Drawing.Size, System.Drawing">
<value>609, 657</value>
</data>
<data name="_tabWrappers.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
</data>
<data name="_tabWrappers.Text" xml:space="preserve">
<value>Wrappers</value>
</data>
<data name="&gt;&gt;_tabWrappers.Name" xml:space="preserve">
<value>_tabWrappers</value>
</data>
<data name="&gt;&gt;_tabWrappers.Type" xml:space="preserve">
<value>System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;_tabWrappers.Parent" xml:space="preserve">
<value>_tabs</value>
</data>
<data name="&gt;&gt;_tabWrappers.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="columnHeader1.Text" xml:space="preserve">
<value>Type</value>
</data>
@ -463,7 +553,7 @@
<value>_tabs</value>
</data>
<data name="&gt;&gt;_tabWrapperTypes.ZOrder" xml:space="preserve">
<value>1</value>
<value>2</value>
</data>
<data name="_layoutLocations.ColumnCount" type="System.Int32, mscorlib">
<value>1</value>
@ -583,7 +673,7 @@
<value>_tabs</value>
</data>
<data name="&gt;&gt;_tabWrapperLocations.ZOrder" xml:space="preserve">
<value>2</value>
<value>3</value>
</data>
<data name="_layoutItemEvents.ColumnCount" type="System.Int32, mscorlib">
<value>1</value>
@ -615,6 +705,9 @@
<data name="&gt;&gt;listItemEventDetails.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="columnItemId.Text" xml:space="preserve">
<value>ItemId</value>
</data>
<data name="listItemEvents.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
@ -672,6 +765,33 @@
<data name="&gt;&gt;buttonCleanGC.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="buttonCopyFilter.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="buttonCopyFilter.Location" type="System.Drawing.Point, System.Drawing">
<value>350, 3</value>
</data>
<data name="buttonCopyFilter.Size" type="System.Drawing.Size, System.Drawing">
<value>109, 35</value>
</data>
<data name="buttonCopyFilter.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="buttonCopyFilter.Text" xml:space="preserve">
<value>Copy filter</value>
</data>
<data name="&gt;&gt;buttonCopyFilter.Name" xml:space="preserve">
<value>buttonCopyFilter</value>
</data>
<data name="&gt;&gt;buttonCopyFilter.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;buttonCopyFilter.Parent" xml:space="preserve">
<value>_layoutEventsButtons</value>
</data>
<data name="&gt;&gt;buttonCopyFilter.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="_layoutEventsButtons.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
@ -754,7 +874,7 @@
<value>_tabs</value>
</data>
<data name="&gt;&gt;_tabItemEvents.ZOrder" xml:space="preserve">
<value>3</value>
<value>4</value>
</data>
<data name="_tabs.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
@ -879,6 +999,24 @@
<data name="&gt;&gt;columnSubject.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;columnHeader5.Name" xml:space="preserve">
<value>columnHeader5</value>
</data>
<data name="&gt;&gt;columnHeader5.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;columnHeader6.Name" xml:space="preserve">
<value>columnHeader6</value>
</data>
<data name="&gt;&gt;columnHeader6.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;columnHeader7.Name" xml:space="preserve">
<value>columnHeader7</value>
</data>
<data name="&gt;&gt;columnHeader7.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;columnHeader1.Name" xml:space="preserve">
<value>columnHeader1</value>
</data>
@ -909,6 +1047,12 @@
<data name="&gt;&gt;columnProperties.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;columnItemId.Name" xml:space="preserve">
<value>columnItemId</value>
</data>
<data name="&gt;&gt;columnItemId.Type" xml:space="preserve">
<value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>DebugDialog</value>
</data>

View File

@ -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; }
}

View File

@ -50,7 +50,14 @@ namespace Acacia.Stubs.OutlookWrappers
{
ComRelease.Release(_item);
}
else
{
}
}
virtual public string DebugContext { get { return null; } }
}
}

View File

@ -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;
}
}
}
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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<Type, int> _types = new ConcurrentDictionary<Type, int>();
private readonly ConcurrentDictionary<CustomTrace, int> _locations = new ConcurrentDictionary<CustomTrace, int>();
private readonly ConcurrentDictionary<int, DisposableInfo> _all = new ConcurrentDictionary<int, DisposableInfo>();
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<IDebugDisposable> _item;
public string Subject
{
get
{
if (_item == null)
return null;
IDebugDisposable item;
if (_item.TryGetTarget(out item))
{
if (item.IsDisposed)
return "<DISPOSED>";
try
{
return item.DebugContext;
}
catch(Exception)
{
// Exception may happen if the item is not fully loaded yet
return "<NOT LOADED>";
}
}
return "<GC>";
}
}
public DisposableInfoImpl(DisposableWrapper wrapper, int id)
{
TraceId = id;
WrapperType = wrapper.GetType();
if (wrapper is IDebugDisposable)
{
_item = new WeakReference<IDebugDisposable>((IDebugDisposable)wrapper);
}
}
}
public IEnumerable<DisposableInfo> GetActive()
{
return _all.Values;
}
}
}

View File

@ -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()

View File

@ -377,15 +377,6 @@ namespace Acacia.Utils
GC
}
public interface MailEventDebug
{
string Id { get; }
string Subject { get; }
int GetEventCount(DebugEvent which);
IEnumerable<DebugEvent> GetEvents();
IEnumerable<string> Properties { get; }
}
public static IEnumerable<MailEventDebug> MailEventsDebug
{
get { return _hookers?.Values; }
@ -405,24 +396,32 @@ namespace Acacia.Utils
private static readonly ConcurrentDictionary<int, MailEventDebugImpl> _hookers =
GlobalOptions.INSTANCE.WrapperTrace ? new ConcurrentDictionary<int, MailEventDebugImpl>() : 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<DebugEvent> GetEvents();
IEnumerable<string> Properties { get; }
}
private class MailEventDebugImpl : MailEventDebug
{
private readonly ConcurrentDictionary<DebugEvent, int> _eventCounts = new ConcurrentDictionary<DebugEvent, int>();
private readonly List<string> _properties = new List<string>();
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<DebugEvent> 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; }
}