Exemplo n.º 1
0
        /// <summary>
        /// Deserializes counter (metric) data from the stream and adds all objects to provided collection.
        /// </summary>
        /// <param name="stream">Stream from which data should be deserialized. Stream should be readable and provide randon access.</param>
        /// <param name="metricBuilder">An object responsible for creation and further consumption of deserialized data.</param>
        /// <param name="maxMetricStringsLength">Maximum length of strings, which represent metric name, dimension names and values.</param>
        /// <param name="maxMetricNamespaceStringsLength">Maximum length of metric namespace string.</param>
        /// <param name="maxMetricDimensionValueStringsLength">Maximum length of metric dimension value string.</param>
        public void Deserialize(Stream stream, IMetricBuilder <TMetadata> metricBuilder, int maxMetricStringsLength, int maxMetricNamespaceStringsLength, int maxMetricDimensionValueStringsLength)
        {
            if (!stream.CanRead || !stream.CanSeek)
            {
                throw new ArgumentException(@"Stream should be readable and provide random access.", nameof(stream));
            }

            try
            {
                using (var reader = new NoCloseBinaryReader(stream, Encoding.UTF8))
                {
                    var startStreamPosition = stream.Position;

                    // Read version and type serializers info
                    var version = reader.ReadUInt16();
                    if (version > MaxVersion)
                    {
                        throw new VersionNotSupportedMetricSerializationException(
                                  string.Format(
                                      CultureInfo.InvariantCulture,
                                      "Version is not supported. Read version:{0}, Max version:{1}.",
                                      version,
                                      MaxVersion));
                    }

                    if (version >= 5)
                    {
                        // Read CRC. CRC check is done in upper layers.
                        reader.ReadUInt32();
                    }

                    if (reader.ReadUInt32() != TypeSerializerFlags)
                    {
                        throw new VersionNotSupportedMetricSerializationException("Type serializers not supported.");
                    }

                    metricBuilder.SetSerializationVersion(version);

                    // Read strings
                    var deserializerDataPosition = stream.Position;
                    stream.Position += sizeof(long);
                    stream.Position  = startStreamPosition + reader.ReadInt64();
                    var count = SerializationUtils.ReadUInt32FromBase128(reader);
                    for (uint i = 0; i < count; ++i)
                    {
                        this.stringsDictionary.Add(reader.ReadString());
                    }

                    // Read metrics metadata
                    stream.Position = deserializerDataPosition;
                    stream.Position = startStreamPosition + reader.ReadInt64();
                    count           = SerializationUtils.ReadUInt32FromBase128(reader);
                    for (uint i = 0; i < count; ++i)
                    {
                        this.metadataDictionary.Add(this.ReadMetricMetadata(reader, metricBuilder, version, maxMetricStringsLength, maxMetricNamespaceStringsLength));
                    }

                    // Read metrics data
                    stream.Position = deserializerDataPosition + (2 * sizeof(long));
                    this.ReadMetricsData(reader, metricBuilder, version, maxMetricStringsLength, maxMetricNamespaceStringsLength, maxMetricDimensionValueStringsLength);
                }
            }
            catch (IOException ioException)
            {
                throw new MetricSerializationException("Failed to deserialize data. Problem with input stream.", ioException);
            }
            catch (Exception exception)
            {
                throw new MetricSerializationException("Failed to deserialize data. Likely the incoming stream contains corrupted data.", exception);
            }
            finally
            {
                this.metadataDictionary.Clear();
                this.stringsDictionary.Clear();
                this.histogramBuffer.Clear();
            }
        }