fix(driver-abcip): resolve Medium code-review finding (Driver.AbCip-006)
`PlcTagHandle` and `DeviceState.TagHandles` were dead scaffolding: the `ReleaseHandle` no-op never called `plc_tag_destroy` and the dict was never populated. Removed the file, the dead dict, and its `DisposeHandles` loop. Updated the `AbCipDriver` class doc to document that native lifetime is owned by libplctag.NET `Tag.Dispose()` (invoked from `DisposeHandles`) with the library's own finalizer covering any GC-collected instances. Two test methods that only exercised the dead `PlcTagHandle` class removed from `AbCipDriverTests`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,9 +5,8 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip;
|
||||
|
||||
/// <summary>
|
||||
/// Allen-Bradley CIP / EtherNet-IP driver for ControlLogix / CompactLogix / Micro800 /
|
||||
/// GuardLogix families. Implements <see cref="IDriver"/> only for now — read/write/
|
||||
/// subscribe/discover capabilities ship in subsequent PRs (3–8) and family-specific quirk
|
||||
/// profiles ship in PRs 9–12.
|
||||
/// GuardLogix families. Implements all read/write/subscribe/discover/probe/alarm
|
||||
/// capabilities via the libplctag.NET wrapper.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Wire layer is libplctag 1.6.x (plan decision #11). Per-device host addresses use
|
||||
@@ -17,8 +16,11 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip;
|
||||
///
|
||||
/// <para>Tier A per plan decisions #143–145 — in-process, shares server lifetime, no
|
||||
/// sidecar. <see cref="ReinitializeAsync"/> is the Tier-B escape hatch for recovering
|
||||
/// from native-heap growth that the CLR allocator can't see; it tears down every
|
||||
/// <see cref="PlcTagHandle"/> and reconnects each device.</para>
|
||||
/// from native-heap growth that the CLR allocator can't see; it tears down the
|
||||
/// libplctag.NET <c>Tag</c> instances held in <c>DeviceState.Runtimes</c> and reconnects
|
||||
/// each device. Native tag lifetime is owned by the libplctag.NET <c>Tag.Dispose()</c>
|
||||
/// (called in <see cref="DeviceState.DisposeHandles"/>); the library's own finalizer
|
||||
/// handles GC-collected tags.</para>
|
||||
/// </remarks>
|
||||
public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery, ISubscribable,
|
||||
IHostConnectivityProbe, IPerCallHostResolver, IAlarmSource, IDisposable, IAsyncDisposable
|
||||
@@ -874,8 +876,10 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
|
||||
/// <summary>
|
||||
/// Per-device runtime state. Holds the parsed host address, family profile, and the
|
||||
/// live <see cref="PlcTagHandle"/> cache keyed by tag path. PRs 3–8 populate + consume
|
||||
/// this dict via libplctag.
|
||||
/// live libplctag.NET <see cref="IAbCipTagRuntime"/> instances keyed by tag name.
|
||||
/// Native tag lifetime is owned by the <c>Tag.Dispose()</c> inside each
|
||||
/// <see cref="LibplctagTagRuntime"/>; libplctag.NET's own finalizer covers GC-collected
|
||||
/// instances so no separate SafeHandle wrapper is needed here (Driver.AbCip-006).
|
||||
/// </summary>
|
||||
internal sealed class DeviceState(
|
||||
AbCipHostAddress parsedAddress,
|
||||
@@ -901,9 +905,6 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// </summary>
|
||||
public Task? ProbeTask { get; set; }
|
||||
|
||||
public Dictionary<string, PlcTagHandle> TagHandles { get; } =
|
||||
new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Per-tag runtime handles owned by this device. One entry per configured tag is
|
||||
/// created lazily on first read (see <see cref="AbCipDriver.EnsureTagRuntimeAsync"/>).
|
||||
@@ -930,8 +931,6 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
|
||||
public void DisposeHandles()
|
||||
{
|
||||
foreach (var h in TagHandles.Values) h.Dispose();
|
||||
TagHandles.Clear();
|
||||
foreach (var r in Runtimes.Values) r.Dispose();
|
||||
Runtimes.Clear();
|
||||
foreach (var r in ParentRuntimes.Values) r.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user