232c03ed1b
- HistoryUpdate Primary gate now reads IHistoryUpdateRoleView (PrimaryGatePolicy.ShouldServeHistoryUpdate): the data-plane verdict but CLOSED until this node's first redundancy snapshot, so both pair nodes cannot accept in the pre-join boot window. Single nodes open on their own singleton's first snapshot; admin-only nodes register no view => no gate. DriverHostActor publishes it at every Primary-verdict publish point. - SqlServer v1: the updater throws NotSupportedException on every arm; the node manager maps it to a node-level BadHistoryOperationUnsupported (was per-item under a Good node for UpdateData/DeleteAtTime). HistoryWrite bit still advertised on v1 (not knowable at materialise time) — documented. - The update plan is evaluated before the Primary gate: an unservable request (Remove, IsDeleteModified, not historized, no updater) is BadHistoryOperationUnsupported off-Primary, not BadInvalidState. - Local-kind SourceTimestamp converted to UTC before the future-skew compare and sent as UTC. - Hosted-service wiring extracted to BuildHistoryUpdatePosture and tested (gate source, skew, clock). - Docs: Historian.md (boot window, ordering, node-level v1, HistoryWrite bit), CLAUDE.md. Co-Authored-By: Claude <noreply@anthropic.com>
31 lines
1.4 KiB
C#
31 lines
1.4 KiB
C#
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common;
|
|
|
|
/// <summary>
|
|
/// Every OPC UA status the SQL historian backends emit, as named constants (inline literals are invisible to
|
|
/// <c>StatusCodeParityTests</c>). Values mirror <c>Opc.Ua.StatusCodes</c>.
|
|
/// </summary>
|
|
public static class HistorianStatusCodes
|
|
{
|
|
public const uint Good = 0x00000000u;
|
|
public const uint GoodEntryInserted = 0x00A20000u;
|
|
public const uint GoodEntryReplaced = 0x00A30000u;
|
|
public const uint BadNoData = 0x809B0000u;
|
|
|
|
/// <summary>Generic Bad: a time-weighted interval holding data but no non-Bad time (the SDK aggregate rule).</summary>
|
|
public const uint Bad = 0x80000000u;
|
|
public const uint BadEntryExists = 0x809F0000u;
|
|
public const uint BadNoEntryExists = 0x80A00000u;
|
|
public const uint BadInvalidTimestamp = 0x80230000u;
|
|
public const uint BadAggregateInvalidInputs = 0x80D60000u;
|
|
public const uint UncertainDataSubNormal = 0x40A40000u;
|
|
|
|
/// <summary>Stored for a non-finite Double (NaN / ±Infinity) that arrived with a non-Bad status.</summary>
|
|
public const uint BadOutOfRange = 0x803C0000u;
|
|
|
|
/// <summary>
|
|
/// A HistoryUpdate value that cannot be stored: a Double NaN / ±Infinity, an Empty (null) value with a non-Bad
|
|
/// status, or a tag name longer than <see cref="HistorianTagNames.MaxLength"/>.
|
|
/// </summary>
|
|
public const uint BadInvalidArgument = 0x80AB0000u;
|
|
}
|