/// <summary> /// Gets or Adds a snapshot component for a visibility lsn. /// </summary> public SnapshotComponent <TKey, TValue, TKeyComparer, TKeyEqualityComparer> GetOrAdd( long key, SnapshotComponent <TKey, TValue, TKeyComparer, TKeyEqualityComparer> value) { var result = this.container.GetOrAdd(key, value); return(result); }
/// <summary> /// Removes the given key. /// </summary> /// <param name="key"></param> public void Remove(long key) { SnapshotComponent <TKey, TValue, TKeyComparer, TKeyEqualityComparer> value = null; var result = this.container.TryRemove(key, out value); Diagnostics.Assert(result, this.traceType, "SnapshotComponent should be removed."); // Remove the file metadata table from the lsn map. ConcurrentDictionary <uint, FileMetadata> fileMetadataTable = null; if (this.FileMetadataTableLsnMap.TryRemove(key, out fileMetadataTable)) { // Acquire reader lock before trying to remove checkpoint file checkpointFileDeleteLock.EnterReadLock(); try { // Decrement ref on each file metadata. foreach (var item in fileMetadataTable) { var metadata = item.Value; metadata.ReleaseRef(); } } finally { checkpointFileDeleteLock.ExitReadLock(); } } }
/// <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); }