/// <summary> /// Reads instant data from the stream at the given cursor time and pushes it to all registered adapting data providers. /// </summary> /// <param name="streamReader">The stream reader that will read the data.</param> /// <param name="cursorTime">The cursor time at which to read the data.</param> /// <param name="streamCache">The stream reader's cache.</param> public void ReadInstantData(IStreamReader streamReader, DateTime cursorTime, ObservableKeyedCache <DateTime, StreamCacheEntry> streamCache) { // Get the index of the data, given the cursor time int index = IndexHelper.GetIndexForTime(cursorTime, streamCache?.Count ?? 0, (idx) => streamCache[idx].OriginatingTime, this.CursorEpsilon); T data = default; StreamCacheEntry cacheEntry = default; if (index >= 0) { // Get the index entry cacheEntry = streamCache[index]; // Read the data data = cacheEntry.Read <T>(streamReader); } // Notify each adapting data provider of the new data foreach (IAdaptingInstantDataProvider <T> adaptingInstantDataProvider in this.dataProviders.ToList()) { adaptingInstantDataProvider.PushData(data, cacheEntry); } // Release the reference to the local copy of the data if it's shared if (this.isSharedType && data != null) { (data as IDisposable).Dispose(); } }
/// <inheritdoc/> public void PushData(TSource sourceData, StreamCacheEntry streamCacheEntry) { // Adapt the data to the type required by target. TDestination adaptedData = this.streamAdapter.AdaptData(sourceData); // Call each of the targets with the adapted data, cloning it if it's shared. foreach (InstantDataTarget instantDataTarget in this.targets.Values.ToList()) { instantDataTarget.Callback.Invoke(adaptedData, streamCacheEntry); } // We're done with the adapted data, so decrement its reference count if it's shared if (this.adaptedDataIsSharedType && adaptedData != null) { (adaptedData as IDisposable).Dispose(); } }
/// <summary> /// Reads instant data from the stream at the given cursor time and pushes it to all registered adapting data providers. /// </summary> /// <param name="streamReader">The stream reader that will read the data.</param> /// <param name="cursorTime">The cursor time at which to read the data.</param> /// <param name="streamCache">The stream reader's cache.</param> public void ReadInstantData(IStreamReader streamReader, DateTime cursorTime, ObservableKeyedCache <DateTime, StreamCacheEntry> streamCache) { // Get the index of the data, given the cursor time int index = IndexHelper.GetIndexForTime(cursorTime, streamCache?.Count ?? 0, (idx) => streamCache[idx].OriginatingTime, this.CursorEpsilon); T data = default; StreamCacheEntry cacheEntry = default; if (index >= 0) { // Get the index entry cacheEntry = streamCache[index]; // Read the data data = cacheEntry.Read <T>(streamReader); } else { // cache miss, attempt to seek directly while the cache is presumably being populated streamReader.Seek(cursorTime + this.CursorEpsilon, true); streamReader.OpenStream <T>(this.streamName, (m, e) => { cacheEntry = new StreamCacheEntry(null, e.CreationTime, e.OriginatingTime); data = m; }); streamReader.MoveNext(out var envelope); } // Notify each adapting data provider of the new data foreach (IAdaptingInstantDataProvider <T> adaptingInstantDataProvider in this.dataProviders.ToList()) { adaptingInstantDataProvider.PushData(data, cacheEntry); } // Release the reference to the local copy of the data if it's shared if (this.isSharedType && data != null) { (data as IDisposable).Dispose(); } }