Esempio n. 1
0
        /// <summary>
        /// Merges <see cref="ChannelDataChunk" /> data for updates.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <exception cref="WitsmlException"></exception>
        public void Merge(ChannelDataReader reader)
        {
            if (reader == null || reader.RecordsAffected <= 0)
            {
                return;
            }

            Logger.Debug("Merging records in ChannelDataReader.");

            try
            {
                // Get the full range of the reader.
                //... This is the range that we need to select existing ChannelDataChunks from the database to update
                var updateRange = reader.GetIndexRange();

                // Make sure we have a valid index range; otherwise, nothing to do
                if (!updateRange.Start.HasValue || !updateRange.End.HasValue)
                {
                    return;
                }

                var indexChannel = reader.GetIndex();
                var increasing   = indexChannel.Increasing;
                var rangeSize    = WitsmlSettings.GetRangeSize(indexChannel.IsTimeIndex);

                // Based on the range of the updates, compute the range of the data chunk(s)
                //... so we can merge updates with existing data.
                var existingRange = new Range <double?>(
                    Range.ComputeRange(updateRange.Start.Value, rangeSize, increasing).Start,
                    Range.ComputeRange(updateRange.End.Value, rangeSize, increasing).End
                    );

                // Get DataChannelChunk list from database for the computed range and URI
                var filter  = BuildDataFilter(reader.Uri, indexChannel.Mnemonic, existingRange, increasing);
                var results = GetData(filter, increasing);

                // Backup existing chunks for the transaction
                AttachChunks(results);

                try
                {
                    BulkWriteChunks(
                        ToChunks(
                            MergeSequence(results.GetRecords(), reader.AsEnumerable(), updateRange, rangeSize)),
                        reader.Uri,
                        string.Join(",", reader.Mnemonics),
                        string.Join(",", reader.Units),
                        string.Join(",", reader.NullValues)
                        );

                    CreateChannelDataChunkIndex();
                }
                catch (FormatException ex)
                {
                    Logger.ErrorFormat("Error when merging data: {0}", ex);
                    throw new WitsmlException(ErrorCodes.ErrorMaxDocumentSizeExceeded, ex);
                }
            }
            catch (MongoException ex)
            {
                Logger.ErrorFormat("Error when merging data: {0}", ex);
                throw new WitsmlException(ErrorCodes.ErrorUpdatingInDataStore, ex);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Merges <see cref="ChannelDataChunk" /> data for updates.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <exception cref="WitsmlException"></exception>
        public void Merge(ChannelDataReader reader)
        {
            if (reader == null || reader.RecordsAffected <= 0)
            {
                return;
            }

            Logger.Debug("Merging records in ChannelDataReader.");

            try
            {
                // Get the full range of the reader.
                //... This is the range that we need to select existing ChannelDataChunks from the database to update
                var updateRange = reader.GetIndexRange();

                // Make sure we have a valid index range; otherwise, nothing to do
                if (!updateRange.Start.HasValue || !updateRange.End.HasValue)
                {
                    return;
                }

                var indexChannel = reader.GetIndex();
                var increasing   = indexChannel.Increasing;
                var rangeSize    = WitsmlSettings.GetRangeSize(indexChannel.IsTimeIndex);

                // Based on the range of the updates, compute the range of the data chunk(s)
                //... so we can merge updates with existing data.
                var chunkRange = new Range <double?>(
                    Range.ComputeRange(updateRange.Start.Value, rangeSize, increasing).Start,
                    Range.ComputeRange(updateRange.End.Value, rangeSize, increasing).End
                    );

                // Get DataChannelChunk list from database for the computed range and URI
                //specifically using a chunk limiter that will seek until the end of range is found regardless of the default read limit in the config file
                var results = GetData(reader.Uri, indexChannel.Mnemonic, chunkRange, increasing, false, GetDataSearchUntilFoundOrEndChunkLimiter);

                // Backup existing chunks for the transaction
                AttachChunks(results);

                // Check if reader overlaps existing data
                var hasOverlap        = false;
                var existingRange     = new Range <double?>();
                var existingMnemonics = results.Count > 0 ? results[0]?.MnemonicList.Split(',') : new string[0];

                if (results.Count > 0)
                {
                    existingRange = new Range <double?>(results.Min(x => x.Indices[0].Start), results.Max(x => x.Indices[0].End));
                    hasOverlap    = updateRange.Overlaps(existingRange, increasing);
                }

                try
                {
                    if (hasOverlap)
                    {
                        WriteRecordsToChunks(reader, MergeSequence(results.GetRecords(), reader.AsEnumerable(), updateRange, rangeSize));
                    }
                    else
                    {
                        // If there is no existing data add reader records only
                        if (results.Count == 0)
                        {
                            WriteRecordsToChunks(reader, reader.AsEnumerable());
                        }
                        // If there is only one chunk and the mnemonics match
                        else if (existingMnemonics != null && existingMnemonics.OrderBy(t => t).SequenceEqual(reader.Mnemonics.OrderBy(t => t)) && results.Count == 1)
                        {
                            // If the update is before the existing range
                            if (updateRange.EndsBefore(existingRange.Start.GetValueOrDefault(), increasing, true))
                            {
                                WriteRecordsToChunks(reader, reader.AsEnumerable().Concat(results.GetRecords()));
                            }
                            // If the update is after the existing range
                            else if (updateRange.StartsAfter(existingRange.End.GetValueOrDefault(), increasing, true))
                            {
                                WriteRecordsToChunks(reader, results.GetRecords().Concat(reader.AsEnumerable()));
                            }
                        }
                        // Resort to merging the records
                        else
                        {
                            WriteRecordsToChunks(reader, MergeSequence(results.GetRecords(), reader.AsEnumerable(), updateRange, rangeSize));
                        }
                    }
                    CreateChannelDataChunkIndex();
                }
                catch (FormatException ex)
                {
                    Logger.ErrorFormat("Error when merging data: {0}", ex);
                    throw new WitsmlException(ErrorCodes.ErrorMaxDocumentSizeExceeded, ex);
                }
            }
            catch (MongoException ex)
            {
                Logger.ErrorFormat("Error when merging data: {0}", ex);
                throw new WitsmlException(ErrorCodes.ErrorUpdatingInDataStore, ex);
            }
        }