/// <summary> /// Updates the data row count for the log. /// </summary> /// <param name="uri">The URI.</param> protected override void UpdateDataRowCount(EtpUri uri) { var current = GetEntity(uri); var dataRowCount = ChannelDataChunkAdapter.GetDataRowCount(uri); if (current.DataRowCount.Equals(dataRowCount)) { return; } // Update the dataRowCount in the header var updates = GetDataRowCountUpdate(null, current, dataRowCount); var filter = MongoDbUtility.GetEntityFilter <Log>(uri); var fields = MongoDbUtility.CreateUpdateFields <Log>(); Logger.Debug($"Updating dataRowCount for URI: {uri}"); updates = MongoDbUtility.BuildUpdate(updates, fields); var mongoUpdate = new MongoDbUpdate <Log>(Container, GetCollection(), null, IdPropertyName); mongoUpdate.UpdateFields(filter, updates); // Join existing Transaction var transaction = Transaction; transaction.Attach(MongoDbAction.Update, DbCollectionName, IdPropertyName, current.ToBsonDocument(), uri); transaction.Save(); }
/// <summary> /// Replaces the specified <see cref="Log" /> instance in the store. /// </summary> /// <param name="parser">The update parser.</param> /// <param name="dataObject">The data object to be replaced.</param> public override void Replace(WitsmlQueryParser parser, Log dataObject) { var uri = dataObject.GetUri(); using (var transaction = GetTransaction()) { transaction.SetContext(uri); // Remove previous log data ChannelDataChunkAdapter.Delete(uri); // Gather original mnemonics var originalMnemonics = GetMnemonics(uri); // Separate log header and log data var readers = ExtractDataReaders(dataObject); // Replace log header ReplaceEntity(dataObject, uri); if (CanSaveData()) { // Update log data and index ranges UpdateLogDataAndIndexRange(uri, readers, originalMnemonics); } // Validate log header result ValidateUpdatedEntity(Functions.PutObject, uri); // Commit transaction transaction.Commit(); } }
/// <summary> /// Adds <see cref="ChannelSet" /> to the data store. /// </summary> /// <param name="parser">The input template parser.</param> /// <param name="dataObject">The <see cref="ChannelSet" /> to be added.</param> public override void Add(WitsmlQueryParser parser, ChannelSet dataObject) { // Extract Data var reader = ExtractDataReader(dataObject); InsertEntity(dataObject); if (reader != null) { Logger.DebugFormat("Adding ChannelSet data with uid '{0}' and name '{1}'", dataObject.Uuid, dataObject.Citation.Title); var increasing = dataObject.IsIncreasing(); var allMnemonics = reader.Indices.Select(i => i.Mnemonic).Concat(reader.Mnemonics).ToArray(); // Get current index information var ranges = GetCurrentIndexRange(dataObject); var indexCurve = dataObject.Index[0]; Logger.DebugFormat("Index curve mnemonic: {0}.", indexCurve.Mnemonic); GetUpdatedLogHeaderIndexRange(reader, allMnemonics, ranges, increasing); // Add ChannelDataChunks ChannelDataChunkAdapter.Add(reader); // Update index range UpdateIndexRange(dataObject.GetUri(), dataObject, ranges, allMnemonics); } }
/// <summary> /// Deletes a data object by the specified identifier. /// </summary> /// <param name="uri">The data object URI.</param> public override void Delete(EtpUri uri) { using (var transaction = GetTransaction()) { transaction.SetContext(uri); base.Delete(uri); ChannelDataChunkAdapter.Delete(uri); // Commit transaction transaction.Commit(); } }
/// <summary> /// Gets the channel data for a given index range. /// </summary> /// <param name="uri">The URI.</param> /// <param name="indexChannel">The index channel.</param> /// <param name="range">The range to query the channel data.</param> /// <param name="increasing">if set to <c>true</c> if the log is increasing, false otherwise.</param> /// <param name="requestLatestValues">The number of latest values requested, null if not requested.</param> /// <returns>The channel data records requested</returns> private IEnumerable <IChannelDataRecord> GetChannelData(EtpUri uri, string indexChannel, Range <double?> range, bool increasing, int?requestLatestValues = null) { Logger.DebugFormat("Getting channel data for channelSet: {0}", uri); // The increasing value passed in may be flipped we need to send in a reverse //... flag to signal that there was a flip because not all code paths should be reversed. var chunks = ChannelDataChunkAdapter.GetData( uri, indexChannel, range, requestLatestValues.HasValue ? !increasing : increasing, reverse: requestLatestValues.HasValue); return(chunks.GetRecords(range, increasing, reverse: requestLatestValues.HasValue)); }
/// <summary> /// Partially delete the log data. /// </summary> /// <param name="uri">The URI.</param> /// <param name="parser">The parser.</param> /// <param name="channels">The current logCurve information.</param> /// <param name="currentRanges">The current channel index ranges.</param> protected override void PartialDeleteLogData(EtpUri uri, WitsmlQueryParser parser, List <LogCurveInfo> channels, Dictionary <string, Range <double?> > currentRanges) { var uidToMnemonics = channels.ToDictionary(c => c.Uid, c => c.Mnemonic.Value); var updatedRanges = new Dictionary <string, Range <double?> >(); WitsmlParser.RemoveEmptyElements(parser.Root); var delete = WitsmlParser.Parse <LogList>(parser.Root, false).Log.FirstOrDefault(); var current = GetEntity(uri); delete.IndexType = current.IndexType; delete.Direction = current.Direction; var indexRange = currentRanges[current.IndexCurve]; if (!indexRange.Start.HasValue || !ToDeleteLogData(delete, parser)) { return; } TimeSpan?offset = null; var indexCurve = current.IndexCurve; var indexChannel = current.LogCurveInfo.FirstOrDefault(l => l.Mnemonic.Value == indexCurve); if (DeleteAllLogData(current, delete, updatedRanges)) { ChannelDataChunkAdapter.Delete(uri); foreach (var curve in current.LogCurveInfo) { updatedRanges.Add(curve.Mnemonic.Value, new Range <double?>(null, null)); } } else { var deletedChannels = GetDeletedChannels(current, uidToMnemonics); var defaultDeleteRange = GetDefaultDeleteRange(current, delete); var isTimeLog = current.IsTimeLog(); var updateRanges = GetDeleteQueryIndexRange(delete, channels, uidToMnemonics, indexCurve, current.IsIncreasing(), isTimeLog); offset = currentRanges[indexCurve].Offset; var ranges = MergePartialDeleteRanges(deletedChannels, defaultDeleteRange, currentRanges, updateRanges, indexCurve, current.IsIncreasing()); ChannelDataChunkAdapter.PartialDeleteLogData(uri, indexCurve, current.IsIncreasing(), isTimeLog, deletedChannels, ranges, updatedRanges); } UpdateIndexRange(uri, current, updatedRanges, updatedRanges.Keys.ToList(), current.IsTimeLog(), indexChannel?.Unit, offset, false, true); }
/// <summary> /// Replaces the specified <see cref="Log" /> instance in the store. /// </summary> /// <param name="parser">The update parser.</param> /// <param name="dataObject">The data object to be replaced.</param> public override void Replace(WitsmlQueryParser parser, Log dataObject) { var uri = dataObject.GetUri(); using (var transaction = GetTransaction()) { transaction.SetContext(uri); // Remove previous log data ChannelDataChunkAdapter.Delete(uri); // Separate log header and log data var reader = ExtractDataReader(dataObject, GetEntity(uri)); // Replace log header ReplaceEntity(dataObject, uri); // Update log data and index ranges UpdateLogDataAndIndexRange(uri, new [] { reader }); // Validate log header result ValidateUpdatedEntity(Functions.PutObject, uri); // Commit transaction transaction.Commit(); } }
private void UpdateChannelDataAndIndexRange(EtpUri uri, ChannelDataReader reader) { // Get Updated ChannelSet var current = GetEntity(uri); // Merge ChannelDataChunks if (reader != null) { var increasing = current.IsIncreasing(); var allMnemonics = reader.Indices.Select(i => i.Mnemonic).Concat(reader.Mnemonics).ToArray(); // Get current index information var ranges = GetCurrentIndexRange(current); GetUpdatedLogHeaderIndexRange(reader, allMnemonics, ranges, increasing); // Add ChannelDataChunks ChannelDataChunkAdapter.Merge(reader); // Update index range UpdateIndexRange(uri, current, ranges, allMnemonics); } }
public ChannelSet200DataAdapter(IContainer container, IDatabaseProvider databaseProvider, ChannelDataChunkAdapter channelDataChunkAdapter) : base(container, databaseProvider, ObjectNames.ChannelSet200, ObjectTypes.Uuid) { Logger.Verbose("Instance created."); ChannelDataChunkAdapter = channelDataChunkAdapter; }
/// <summary> /// Partially delete the log data. /// </summary> /// <param name="uri">The URI.</param> /// <param name="parser">The parser.</param> /// <param name="channels">The current logCurve information.</param> /// <param name="currentRanges">The current channel index ranges.</param> protected override void PartialDeleteLogData(EtpUri uri, WitsmlQueryParser parser, List <LogCurveInfo> channels, Dictionary <string, Range <double?> > currentRanges) { var uidToMnemonics = channels.ToDictionary(c => c.Uid, c => c.Mnemonic.Value); var updatedRanges = new Dictionary <string, Range <double?> >(); WitsmlParser.RemoveEmptyElements(parser.Root); var delete = WitsmlParser.Parse <LogList>(parser.Root, false).Log.FirstOrDefault(); var current = GetEntity(uri); delete.IndexType = current.IndexType; delete.Direction = current.Direction; var indexRange = currentRanges[current.IndexCurve]; var headerOnlyDeletion = !indexRange.Start.HasValue || !ToDeleteLogData(delete, parser); // Audit if only the header is being updated if (headerOnlyDeletion) { AuditPartialDeleteHeaderOnly(delete, parser); UpdateGrowingObject(current, null); return; } TimeSpan?offset = null; var indexCurve = current.IndexCurve; var indexChannel = current.LogCurveInfo.FirstOrDefault(l => l.Mnemonic.Value == indexCurve); if (DeleteAllLogData(current, delete, updatedRanges)) { ChannelDataChunkAdapter.Delete(uri); foreach (var curve in current.LogCurveInfo) { updatedRanges.Add(curve.Mnemonic.Value, new Range <double?>(null, null)); } AuditPartialDelete(current, GetMnemonics(uri), indexRange.Start, indexRange.End); } else { var deletedChannels = GetDeletedChannels(current, uidToMnemonics); var defaultDeleteRange = GetDefaultDeleteRange(current, delete); var isTimeLog = current.IsTimeLog(); var updateRanges = GetDeleteQueryIndexRange(delete, channels, uidToMnemonics, indexCurve, current.IsIncreasing(), isTimeLog); offset = currentRanges[indexCurve].Offset; var ranges = MergePartialDeleteRanges(deletedChannels, defaultDeleteRange, currentRanges, updateRanges, indexCurve, current.IsIncreasing()); ChannelDataChunkAdapter.PartialDeleteLogData(uri, indexCurve, current.IsIncreasing(), isTimeLog, deletedChannels, ranges, updatedRanges); var affectedMnemonics = updatedRanges.Keys.Where(x => x != indexCurve).ToArray(); if (defaultDeleteRange.IsClosed()) { AuditPartialDelete(current, affectedMnemonics, defaultDeleteRange.Start, defaultDeleteRange.End); } else { // If full channels were deleted if (deletedChannels.Count > 0) { var minRange = channels.Where(x => deletedChannels.ContainsIgnoreCase(x.Mnemonic.Value)) .Min(x => x.GetIndexRange(current.IsIncreasing(), isTimeLog).Start); var maxRange = channels.Where(x => deletedChannels.ContainsIgnoreCase(x.Mnemonic.Value)) .Max(x => x.GetIndexRange(current.IsIncreasing(), isTimeLog).End); AuditPartialDelete(current, deletedChannels.ToArray(), minRange, maxRange, true); } else { AuditPartialDelete(current, affectedMnemonics, updateRanges.Min(x => x.Value.Start), updateRanges.Max(x => x.Value.End)); } } } var logHeaderUpdate = GetIndexRangeUpdate(uri, current, updatedRanges, updatedRanges.Keys.ToList(), current.IsTimeLog(), indexChannel?.Unit, offset, true); UpdateGrowingObject(current, logHeaderUpdate); }
/// <summary> /// Deletes a data object by the specified identifier. /// </summary> /// <param name="uri">The data object URI.</param> public override void Delete(EtpUri uri) { base.Delete(uri); ChannelDataChunkAdapter.Delete(uri); }