Merge re/r1.4-gethi-finding: R1.1 ExecuteSqlCommand + R1.4 GetHistorianInfo (bounded)

# Conflicts:
#	docs/plans/hcal-roadmap.md
#	src/AVEVA.Historian.Client/HistorianClient.cs
#	src/AVEVA.Historian.Client/Protocol/Historian2020ProtocolDialect.cs
#	tests/AVEVA.Historian.Client.Tests/HistorianClientIntegrationTests.cs
#	tools/AVEVA.Historian.NativeTraceHarness/Program.cs
This commit is contained in:
Joseph Doherty
2026-06-21 16:18:01 -04:00
19 changed files with 1118 additions and 14 deletions
@@ -478,6 +478,33 @@ internal static class Program
}));
return 0;
}
else if (openSuccess && status.ConnectedToServer && IsHistorianInfoScenario(scenario))
{
// R1.4 capture: drive HistorianAccess.GetHistorianInfo(out HistorianInfo, out error)
// so instrument-wcf-{write,read}message can observe the WCF GETHI pRequestBuff that
// returns the full 518-byte HISTORIAN_INFO struct (version@0 + EventStorageMode@514),
// distinct from the named-value "HistorianVersion" request. Pure status read.
MethodInfo getInfoMethod = accessType.GetMethods()
.First(m => m.Name == "GetHistorianInfo"
&& m.GetParameters().Length == 2
&& m.GetParameters()[0].ParameterType.IsByRef
&& m.GetParameters()[1].ParameterType.IsByRef);
object infoError = Activator.CreateInstance(errorType)!;
object?[] infoArgs = new object?[] { null, infoError };
WriteRuntimeMethodPointerSnapshot(assembly, runtimeMethodPointerOutput, runtimeMethodPointerFilters, repoRoot, scenario, "before-get-historian-info");
bool infoOk = (bool)getInfoMethod.Invoke(access, infoArgs)!;
Console.WriteLine(Serialize(new
{
Scenario = scenario,
GetHistorianInfoReturned = infoOk,
HistorianInfoType = getInfoMethod.GetParameters()[0].ParameterType.GetElementType()?.FullName,
HistorianInfo = infoArgs[0] is null ? null : SnapshotObject(infoArgs[0]!),
Error = SnapshotObject(infoArgs[1]!),
}));
return 0;
}
else if (openSuccess && status.ConnectedToServer && IsEventSendScenario(scenario))
{
// R2.1 capture: drive AddStreamedValue(HistorianEvent) and let instrument-wcf-*
@@ -1770,6 +1797,19 @@ internal static class Program
|| scenario.Equals("runtime-parameter", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Historian-info scenario (R1.4 capture): opens a normal authenticated process connection and
/// calls <c>GetHistorianInfo(out HistorianInfo, out error)</c> so instrument-wcf-{write,read}message
/// can observe the WCF GETHI <c>pRequestBuff</c>/<c>pResponseBuff</c> that returns the full
/// 518-byte HISTORIAN_INFO struct (version@0 + EventStorageMode@514). Pure status read.
/// </summary>
private static bool IsHistorianInfoScenario(string scenario)
{
return scenario.Equals("historian-info", StringComparison.OrdinalIgnoreCase)
|| scenario.Equals("hist-info", StringComparison.OrdinalIgnoreCase)
|| scenario.Equals("gethi", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// SQL-command scenario (R1.1 capture): opens a normal authenticated process connection and
/// calls <c>ExecuteSqlCommand</c> (Retr.ExeC + Retr.GetR) so the string-handle SQL surface