/// <summary>
 /// Writes collection as json
 /// </summary>
 /// <param name="collection"></param>
 /// <param name="context"></param>
 /// <param name="formatting"></param>
 /// <param name="ostrm"></param>
 public static void SaveAsJson(this NodeStateCollection collection, Stream ostrm,
                               Newtonsoft.Json.Formatting formatting, ISystemContext context)
 {
     using (var encoder = new JsonEncoderEx(ostrm, context.ToMessageContext(),
                                            JsonEncoderEx.JsonEncoding.Array, formatting)
     {
         UseAdvancedEncoding = true,
         IgnoreDefaultValues = true
     }) {
         foreach (var node in collection.ToNodeModels(context))
         {
             if (node != null)
             {
                 encoder.WriteEncodeable(null, new EncodeableNodeModel(node));
             }
         }
     }
 }
        /// <summary>
        /// DataSetMessage to NetworkMessage Json batched encoding
        /// </summary>
        /// <param name="messages"></param>
        /// <param name="maxMessageSize"></param>
        /// <returns></returns>
        private IEnumerable <NetworkMessageModel> EncodeBatchAsJson(
            IEnumerable <DataSetMessageModel> messages, int maxMessageSize)
        {
            var notifications = GetNetworkMessages(messages, MessageEncoding.Json);

            if (notifications.Count() == 0)
            {
                yield break;
            }
            // by design all messages are generated in the same session context,
            // therefore it is safe to get the first message's context
            var encodingContext = messages.First().ServiceMessageContext;
            var current         = notifications.GetEnumerator();
            var processing      = current.MoveNext();
            var messageSize     = 2; // array brackets

            maxMessageSize -= 2048;  // reserve 2k for header
            var chunk = new Collection <NetworkMessage>();

            while (processing)
            {
                var notification     = current.Current;
                var messageCompleted = false;
                if (notification != null)
                {
                    var helperWriter  = new StringWriter();
                    var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext)
                    {
                        UseAdvancedEncoding   = true,
                        UseUriEncoding        = true,
                        UseReversibleEncoding = false
                    };
                    notification.Encode(helperEncoder);
                    helperEncoder.Close();
                    var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString());
                    if (notificationSize > maxMessageSize)
                    {
                        // we cannot handle this notification. Drop it.
                        // TODO Trace
                        NotificationsDroppedCount++;
                        processing = current.MoveNext();
                    }
                    else
                    {
                        messageCompleted = maxMessageSize < (messageSize + notificationSize);
                        if (!messageCompleted)
                        {
                            NotificationsProcessedCount++;
                            chunk.Add(notification);
                            processing   = current.MoveNext();
                            messageSize += notificationSize + (processing ? 1 : 0);
                        }
                    }
                }
                if (!processing || messageCompleted)
                {
                    var writer  = new StringWriter();
                    var encoder = new JsonEncoderEx(writer, encodingContext,
                                                    JsonEncoderEx.JsonEncoding.Array)
                    {
                        UseAdvancedEncoding   = true,
                        UseUriEncoding        = true,
                        UseReversibleEncoding = false
                    };
                    foreach (var element in chunk)
                    {
                        encoder.WriteEncodeable(null, element);
                    }
                    encoder.Close();
                    var encoded = new NetworkMessageModel {
                        Body            = Encoding.UTF8.GetBytes(writer.ToString()),
                        ContentEncoding = "utf-8",
                        Timestamp       = DateTime.UtcNow,
                        ContentType     = ContentMimeType.UaJson,
                        MessageSchema   = MessageSchemaTypes.NetworkMessageJson
                    };
                    AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) /
                                     (MessagesProcessedCount + 1);
                    AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount +
                                                  chunk.Count) / (MessagesProcessedCount + 1);
                    MessagesProcessedCount++;
                    chunk.Clear();
                    messageSize = 2;
                    yield return(encoded);
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Perform DataSetMessageModel to NetworkMessageModel batch using Json encoding
        /// </summary>
        /// <param name="messages"></param>
        /// <param name="maxMessageSize"></param>
        /// <returns></returns>
        private IEnumerable <NetworkMessageModel> EncodeBatchAsJson(
            IEnumerable <DataSetMessageModel> messages, int maxMessageSize)
        {
            var notifications = GetMonitoredItemMessages(messages, MessageEncoding.Json);

            if (notifications.Count() == 0)
            {
                yield break;
            }
            var encodingContext = messages.First().ServiceMessageContext;
            var current         = notifications.GetEnumerator();
            var processing      = current.MoveNext();
            var messageSize     = 2; // array brackets

            maxMessageSize -= 2048;  // reserve 2k for header
            var chunk = new Collection <MonitoredItemMessage>();

            while (processing)
            {
                var notification     = current.Current;
                var messageCompleted = false;
                if (notification != null)
                {
                    var helperWriter  = new StringWriter();
                    var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext)
                    {
                        UseAdvancedEncoding   = true,
                        UseUriEncoding        = true,
                        UseReversibleEncoding = false
                    };
                    notification.Encode(helperEncoder);
                    helperEncoder.Close();

                    var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString());
                    messageCompleted = maxMessageSize < (messageSize + notificationSize);

                    if (!messageCompleted)
                    {
                        chunk.Add(notification);
                        processing   = current.MoveNext();
                        messageSize += notificationSize + (processing ? 1 : 0);
                    }
                }
                if (!processing || messageCompleted)
                {
                    var writer  = new StringWriter();
                    var encoder = new JsonEncoderEx(writer, encodingContext,
                                                    JsonEncoderEx.JsonEncoding.Array)
                    {
                        UseAdvancedEncoding   = true,
                        UseUriEncoding        = true,
                        UseReversibleEncoding = false
                    };
                    foreach (var element in chunk)
                    {
                        encoder.WriteEncodeable(null, element);
                    }
                    encoder.Close();
                    chunk.Clear();
                    messageSize = 2;  // array brackets
                    var encoded = new NetworkMessageModel {
                        Body            = Encoding.UTF8.GetBytes(writer.ToString()),
                        ContentEncoding = "utf-8",
                        Timestamp       = DateTime.UtcNow,
                        ContentType     = ContentMimeType.UaJson,
                        MessageSchema   = MessageSchemaTypes.MonitoredItemMessageJson
                    };
                    yield return(encoded);
                }
            }
        }
        /// <summary>
        /// DataSetMessage to NetworkMessage Json batched encoding
        /// </summary>
        /// <param name="messages"></param>
        /// <param name="maxMessageSize"></param>
        /// <returns></returns>
        private IEnumerable <NetworkMessageModel> EncodeBatchAsJson(
            IEnumerable <DataSetMessageModel> messages, int maxMessageSize)
        {
            // by design all messages are generated in the same session context,
            // therefore it is safe to get the first message's context
            var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null)
                                  ?.ServiceMessageContext;
            var notifications = GetNetworkMessages(messages, MessageEncoding.Json, encodingContext);

            if (!notifications.Any())
            {
                yield break;
            }
            var routingInfo             = messages.FirstOrDefault(m => m?.WriterGroup != null)?.WriterGroup.WriterGroupId;
            var current                 = notifications.GetEnumerator();
            var processing              = current.MoveNext();
            var messageSize             = 2; // array brackets
            var chunk                   = new Collection <NetworkMessage>();
            int notificationsPerMessage = 0;

            while (processing)
            {
                var notification     = current.Current;
                var messageCompleted = false;
                if (notification != null)
                {
                    var helperWriter  = new StringWriter();
                    var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext)
                    {
                        UseAdvancedEncoding   = true,
                        UseUriEncoding        = true,
                        UseReversibleEncoding = false
                    };
                    notification.Encode(helperEncoder);
                    helperEncoder.Close();
                    var notificationSize     = Encoding.UTF8.GetByteCount(helperWriter.ToString());
                    var notificationsInBatch = notification.Messages.Sum(m => m.Payload.Count);
                    if (notificationSize > maxMessageSize)
                    {
                        // Message too large, drop it.
                        NotificationsDroppedCount += (uint)notificationsInBatch;
                        _logger.Warning("Message too large, dropped {notificationsInBatch} values", notificationsInBatch);
                        processing = current.MoveNext();
                    }
                    else
                    {
                        messageCompleted = maxMessageSize < (messageSize + notificationSize);
                        if (!messageCompleted)
                        {
                            chunk.Add(notification);
                            NotificationsProcessedCount += (uint)notificationsInBatch;
                            notificationsPerMessage     += notificationsInBatch;
                            processing   = current.MoveNext();
                            messageSize += notificationSize + (processing ? 1 : 0);
                        }
                    }
                }
                if (messageCompleted || (!processing && chunk.Count > 0))
                {
                    var writer  = new StringWriter();
                    var encoder = new JsonEncoderEx(writer, encodingContext,
                                                    JsonEncoderEx.JsonEncoding.Array)
                    {
                        UseAdvancedEncoding   = true,
                        UseUriEncoding        = true,
                        UseReversibleEncoding = false
                    };
                    foreach (var element in chunk)
                    {
                        encoder.WriteEncodeable(null, element);
                    }
                    encoder.Close();
                    var encoded = new NetworkMessageModel {
                        Body            = Encoding.UTF8.GetBytes(writer.ToString()),
                        ContentEncoding = "utf-8",
                        Timestamp       = DateTime.UtcNow,
                        ContentType     = ContentMimeType.Json,
                        MessageSchema   = MessageSchemaTypes.NetworkMessageJson,
                        RoutingInfo     = _enableRoutingInfo ? routingInfo : null,
                    };
                    AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) /
                                     (MessagesProcessedCount + 1);
                    AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount +
                                                  notificationsPerMessage) / (MessagesProcessedCount + 1);
                    MessagesProcessedCount++;
                    chunk.Clear();
                    messageSize             = 2;
                    notificationsPerMessage = 0;
                    yield return(encoded);
                }
            }
        }