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