/// <summary> /// Adds a new key-value pair, or updates an existing one. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <param name="alreadyExists">Assigned to true if an existing key-value pair was /// updated, otherwise false. This should be considered undefined if false is returned.</param> /// <returns>True if the new key-value pair was added, or an existing one was updated. /// False only indicates failure to add a new key-value pair due to capacity limitations /// on the base <see cref="IPageStorage"/>.</returns> /// <exception cref="InvalidOperationException">Thrown if <see cref="IsReadOnly"/> is true or if this /// method is called from a thread that is currently enumerating via <see cref="GetEnumerator"/>.</exception> /// <remarks> /// This method will check whether a key-value pair already exists with the specified /// <paramref name="key"/>. If it does, then the value will be updated. Otherwise, a new key-value /// pair will be added. Addition of a new key-value pair may fail (as documented in the /// <see cref="TryAdd(TKey, TValue)"/> method's remarks) if inflation of the base /// <see cref="IPageStorage"/> fails. In this case, false will be returned and /// no key-value pairs will be changed (this is considered a graceful failure). /// </remarks> public bool TryAddOrUpdate(TKey key, TValue value, out bool alreadyExists) { if (IsReadOnly) { throw new InvalidOperationException("Cannot add a new key-value pair to, or update an existing one on, a read-only " + nameof(StorageDictionary <TKey, TValue>) + "."); } lock (locker) { if (isEnumerating_) { throw new InvalidOperationException("Cannot add or update a key-value pair on the same thread that is currently enumerating this " + nameof(StorageDictionary <TKey, TValue>) + "."); } if (BTree.Insert(key, value, true, out alreadyExists)) { CachedPageStorage.Flush();//Ensure that data is written to base storage now return(true); } else { return(false); } } }
/// <summary> /// Adds a new key-value pair. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns>True if addition was successful, false if it failed only due to capacity limitations /// on the base <see cref="IPageStorage"/>.</returns> /// <exception cref="InvalidOperationException">Thrown if <see cref="IsReadOnly"/> is true or if this /// method is called from a thread that is currently enumerating via <see cref="GetEnumerator"/>.</exception> /// <exception cref="ArgumentException">Thrown if the <paramref name="key"/> already exists in /// this <see cref="StorageDictionary{TKey, TValue}"/>.</exception> /// <remarks> /// This method will only add a new key-value pair, it will not update an existing one. /// The base <see cref="IPageStorage"/> may be inflated by this method if necessary (unless /// it is fixed-capacity). If inflation is required, but not possible or fails, then the /// new key-value pair will not be added and false will be returned (this is considered /// a graceful failure). If there is already a key-value pair with the specified /// <paramref name="key"/>, then an <see cref="ArgumentException"/> will be thrown and /// nothing will change. Any other failure will be reported by an <see cref="Exception"/> /// (of any type) being thrown, and may indicate data corruption. /// </remarks> public bool TryAdd(TKey key, TValue value) { if (IsReadOnly) { throw new InvalidOperationException("Cannot add to a read-only " + nameof(StorageDictionary <TKey, TValue>) + "."); } lock (locker) { if (isEnumerating_) { throw new InvalidOperationException("Cannot add a key-value pair on the same thread that is currently enumerating this " + nameof(StorageDictionary <TKey, TValue>) + "."); } if (BTree.Insert(key, value, false, out bool alreadyExists)) { CachedPageStorage.Flush();//Ensure that data is written to base storage now return(true); } else { if (alreadyExists) { throw new ArgumentException("A key-value pair with the specified key already exists.", nameof(key)); } else { return(false);//Insert failed due to storage limitation } } } }
/// <summary> /// Updates the value of an existing key-value pair. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value to assign.</param> /// <exception cref="InvalidOperationException">Thrown if <see cref="IsReadOnly"/> is true or if this /// method is called from a thread that is currently enumerating via <see cref="GetEnumerator"/>.</exception> /// <exception cref="KeyNotFoundException">Thrown if there is no existing key-value pair with the /// specified <paramref name="key"/>.</exception> public void UpdateValue(TKey key, TValue value) { if (IsReadOnly) { throw new InvalidOperationException("Cannot update any key-value pair in a read-only " + nameof(StorageDictionary <TKey, TValue>) + "."); } lock (locker) { if (isEnumerating_) { throw new InvalidOperationException("Cannot update a key-value pair on the same thread that is currently enumerating this " + nameof(StorageDictionary <TKey, TValue>) + "."); } if (BTree.TryGetValueOnNode(key, out _, out var onNode, out long indexOnNode, new CancellationToken(false))) { onNode.SetValueAt(indexOnNode, value); CachedPageStorage.Flush();//Ensure that data is written to base storage now }