private void UpdateAddList(TKey key, TVersionedItem <TValue> value, IReadableStoreComponent <TKey, TVersionedItem <TValue> > consolidationManager) { // Note: Temporary Assert that should not be required. bool isInReadOnlyMode = Volatile.Read(ref this.isReadonly); Diagnostics.Assert(isInReadOnlyMode == false, this.traceType, "Write operation cannot come after the differential has become readonly."); var snapAddList = this.addList; Diagnostics.Assert( snapAddList != null, this.traceType, "If Apply's are coming, perform checkpoint could not have been called (hence Sort). Version: {0} IsReadOnly: {1}", value.VersionSequenceNumber, Volatile.Read(ref this.isReadonly)); // If the verion being added is a delete then it does not need to be added to the add list. // Either // a) Insert is in LC - 1 and hence in addList already // b) Insert is in the same txn and hence it is not needed in addlist // c) Insert/Update is in Consolidated and hence not needed in addlist. if (value.Kind == RecordKind.DeletedVersion) { return; } // If consolidated component does not have the key or the latest version it has is a delete, we need to add it to addList. // Reminder: AddList is a list of all keys that are in the differential but not in consolidated. var valueInConsolidationManager = consolidationManager.Read(key); if (valueInConsolidationManager == null || valueInConsolidationManager.Kind == RecordKind.DeletedVersion) { snapAddList.TryAdd(key); } }
public AsyncEnumerable( bool isValueAReferenceType, ReadMode readMode, IEnumerable <TKey> keyEnumerables, IReadableStoreComponent <TKey, TVersionedItem <TValue> > differentState, IReadableStoreComponent <TKey, TVersionedItem <TValue> > consolidatedState, MetadataTable currentMetadataTable, LoadValueCounter loadValueCounter, IStateSerializer <TValue> valueSerializer, string traceType) { this.traceType = traceType; this.isValueAReferenceType = isValueAReferenceType; this.readMode = readMode; this.keyEnumerable = keyEnumerables; this.differentState = differentState; this.consolidatedState = consolidatedState; this.currentMetadataTable = currentMetadataTable; this.loadValueCounter = loadValueCounter; this.valueSerializer = valueSerializer; this.isInvalidated = false; }
/// <summary> /// Adds a new entry to this store component. /// </summary> /// <devnote> /// Consolidated Manager is only required for the AddList feature. /// </devnote> public void Add(TKey key, TVersionedItem <TValue> value, IReadableStoreComponent <TKey, TVersionedItem <TValue> > consolidationManager) { bool isInReadOnlyMode = Volatile.Read(ref this.isReadonly); Diagnostics.Assert(isInReadOnlyMode == false, this.traceType, "Write operation cannot come after the differential has become readonly."); var concurrentDictionary = this.component as ConcurrentDictionary <TKey, DifferentialStateVersions <TValue> >; Diagnostics.Assert(concurrentDictionary != null, this.traceType, "write operation came after becoming readonly."); var differentialVersions = concurrentDictionary.GetOrAdd(key, k => new DifferentialStateVersions <TValue>()); if (differentialVersions.CurrentVersion == null) { Diagnostics.Assert(differentialVersions.PreviousVersion == null, this.traceType, "previous version should be null"); differentialVersions.CurrentVersion = value; if (value.Kind == RecordKind.InsertedVersion) { Diagnostics.Assert( (differentialVersions.flags & DifferentialStateFlags.NewKey) == DifferentialStateFlags.None, this.traceType, "DifferentialStateFlags.NewKey is already set"); differentialVersions.flags |= DifferentialStateFlags.NewKey; } } else { // Assert that version sequence number is lesser or equal compared to the new one. // Sequence number can be equal if the same key gets updated multiple times in the same transaction. if (differentialVersions.CurrentVersion.VersionSequenceNumber > value.VersionSequenceNumber) { var message = string.Format(@"New lsn {0} should be greater than or equal the existing current lsn {1}. This error could be caused by an incorrect implementation of key comparer or key serializer. Please check your implementation of IEquatable, IComparable, and custom serializer (if applicable).", value.VersionSequenceNumber, differentialVersions.CurrentVersion.VersionSequenceNumber); FabricEvents.Events.StoreDiagnosticError(this.traceType, message); Diagnostics.Assert( false, this.traceType, message); } if (differentialVersions.CurrentVersion.VersionSequenceNumber == value.VersionSequenceNumber) { // Set the latest value in case there are multiple updates in the same transaction(same lsn). differentialVersions.CurrentVersion = value; this.UpdateAddList(key, value, consolidationManager); return; } // Check if previous version is null if (differentialVersions.PreviousVersion == null) { differentialVersions.PreviousVersion = differentialVersions.CurrentVersion; differentialVersions.CurrentVersion = value; } else { // Move to snapshot container, if needed. var removeVersionResult = this.transactionalReplicator.TryRemoveVersion( this.stateProviderId, differentialVersions.PreviousVersion.VersionSequenceNumber, differentialVersions.CurrentVersion.VersionSequenceNumber); if (!removeVersionResult.CanBeRemoved) { var enumerationSet = removeVersionResult.EnumerationSet; foreach (var snapshotVisibilityLsn in enumerationSet) { var snapshotComponent = this.snapshotContainer.Read(snapshotVisibilityLsn); if (snapshotComponent == null) { snapshotComponent = new SnapshotComponent <TKey, TValue, TKeyComparer, TKeyEqualityComparer>(this.snapshotContainer, this.loadValueCounter, this.isValueAReferenceType, this.traceType); snapshotComponent = this.snapshotContainer.GetOrAdd(snapshotVisibilityLsn, snapshotComponent); } snapshotComponent.Add(key, differentialVersions.PreviousVersion); } // Wait on notifications and remove the entry from the container if (removeVersionResult.EnumerationCompletionNotifications != null) { foreach (var enumerationResult in removeVersionResult.EnumerationCompletionNotifications) { enumerationResult.Notification.ContinueWith(x => { this.snapshotContainer.Remove(enumerationResult.VisibilitySequenceNumber); }) .IgnoreExceptionVoid(); } } } // Remove from differential state differentialVersions.PreviousVersion = differentialVersions.CurrentVersion; differentialVersions.CurrentVersion = value; } } this.UpdateAddList(key, value, consolidationManager); }