OPCFoundation / UA-.NET-Legacy

OPC Foundation Unified Architecture .NET Reference Implementations
330 stars 298 forks source link

Reversed time of received values #137

Closed astrowalker closed 7 years ago

astrowalker commented 7 years ago

AFAIK when you subscribe to given node you should get values in chronological order. However I noticed it is not always the case, after adding some trace points so far I found out that in client library, type Opc.Ua.Client.MonitoredItemDataCache, method OnNotification receives values with reversed time stamps.

I added such code at top of the method:

if (m_lastValue!=null && m_lastValue.ServerTimestamp>notification.Value.ServerTimestamp)
    Utils.Trace($"Wrong timestamps, last {m_lastValue.ServerTimestamp.ToString("O")}, incoming {notification.Value.ServerTimestamp.ToString("O")}");

After some time of testing I got indeed values with reversed time. I am not saying the problem lies in client part, but I added similar check to server side, for adding to queue and publishing values, and I didn't get any report about inversion.

So far it is not clear for me what exactly triggers inversion and where in code it happens, in other words it is time consuming to reproduce.

astrowalker commented 7 years ago

So far I was able to narrow it a bit, in Opc.Ua.Client.Subscribtion class, in method OnMessageRecieved the existing lock is a bit too short. In the effect it is possible to have two concurrent calls on that method, but after exit of the lock area it is possible that the newer call is executed first and after that older call. In effect client receives notifications in reversed order.

AlinMoldovean commented 7 years ago

This situation is described also in the OPC UA specifications and it can happen on both server and client side.

The recommendation in this case is to use the value of ServerTimestamp for sorting the data in order to know the order of the values. Also, the DataChangeNotification.SequenceNo will identify the subscription publish message that the notification belongs to.

It can happen sometimes that the order of Publish responses arriving from the server to be something like sequenceNumber 1, 2, 4

astrowalker commented 7 years ago

I see, thank you for clarification, after reading guarantees for the queue I assumed too much.

astrowalker commented 7 years ago

Sorry for bothering you, I just wanted to check it but I cannot find anything like DataChangeNotification.SequenceNo. What did you have in mind? Thank you in advance.

AlinMoldovean commented 7 years ago

In the handler of a MonitoredItem.Notification event, you can get the sequence number of the publish response containing the datachange like this:

    private void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
    {
        try
        {
            if (m_session == null)
            {
                return;
            }

            // Log MonitoredItem Notification event
            MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;

            uint sequenceNo = notification.Message.SequenceNumber;

In Subscription.OnMesageReceived, you can get it in NotificationMessage.SequenceNumber for each NotificationMessage