private async Task <bool> TryRemoteSplitPointAsync([NotNull] IFdbTransaction trans, long offset) { Contract.Requires(trans != null && offset >= 0); var b = await GetChunkAtAsync(trans, offset).ConfigureAwait(false); if (b.Offset == 0 || b.Key == Slice.Nil) { return(false); // in sparse region, or at beginning } var a = await GetChunkAtAsync(trans, b.Offset - 1).ConfigureAwait(false); if (a.Key == Slice.Nil) { return(false); // no previous chunk } if (a.Offset + a.Data.Count != b.Offset) { return(false); // chunks can't be joined } if (a.Data.Count + b.Data.Count > CHUNK_SMALL) { return(false); // chunks shouldn't be joined } // yay--merge chunks trans.Clear(b.Key); trans.Set(a.Key, a.Data + b.Data); return(true); }
/// <summary>Decrements the count of an (index, value) pair in the multimap, and optionally removes it if the count reaches zero.</summary> /// <param name="trans">Transaction used for the operation</param> /// <param name="key">Key of the entry</param> /// <param name="value">Value for the <paramref name="key"/> to decrement</param> /// <remarks>If the updated count reaches zero or less, and AllowNegativeValues is not set, the key will be cleared from the map.</remarks> public async Task SubtractAsync([NotNull] IFdbTransaction trans, TKey key, TValue value) { if (trans == null) { throw new ArgumentNullException("trans"); } Slice k = this.Location.Keys.Encode(key, value); if (this.AllowNegativeValues) { trans.AtomicAdd(k, MinusOne); // note: it's faster, but we will end up with counts less than or equal to 0 // If 'k' does not already exist, its count will be set to -1 } else { Slice v = await trans.GetAsync(k).ConfigureAwait(false); if (this.AllowNegativeValues || v.ToInt64() > 1) //note: Slice.Nil.ToInt64() will return 0 { trans.AtomicAdd(k, MinusOne); //note: since we already read 'k', the AtomicAdd will be optimized into the equivalent of Set(k, v - 1) by the client, unless RYW has been disabled on the transaction //TODO: if AtomicMax ever gets implemented, we could use it to truncate the values to 0 } else { trans.Clear(k); } } }
/// <summary>Swap the items at positions i1 and i2.</summary> public async Task SwapAsync([NotNull] IFdbTransaction tr, long index1, long index2) { if (tr == null) { throw new ArgumentNullException("tr"); } if (index1 < 0 || index2 < 0) { throw new IndexOutOfRangeException(String.Format("Indices ({0}, {1}) must be positive", index1, index2)); } var k1 = GetKeyAt(index1); var k2 = GetKeyAt(index2); long currentSize = await ComputeSizeAsync(tr).ConfigureAwait(false); if (index1 >= currentSize || index2 >= currentSize) { throw new IndexOutOfRangeException(String.Format("Indices ({0}, {1}) are out of range", index1, index2)); } var vs = await tr.GetValuesAsync(new[] { k1, k2 }).ConfigureAwait(false); var v1 = vs[0]; var v2 = vs[1]; if (!v2.IsNullOrEmpty) { tr.Set(k1, v2); } else if (v1.IsPresent && index1 < currentSize - 1) { tr.Clear(k1); } if (!v1.IsNullOrEmpty) { tr.Set(k2, v1); } else if (v2.IsPresent && index2 < currentSize - 1) { tr.Clear(k2); } }
/// <summary>Remove a value for a specific key</summary> /// <param name="trans"></param> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public void Remove([NotNull] IFdbTransaction trans, TKey key, TValue value) { if (trans == null) { throw new ArgumentNullException("trans"); } trans.Clear(this.Location.Keys.Encode(key, value)); }
/// <summary>Remove a value for a specific key</summary> /// <param name="trans"></param> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public void Remove(IFdbTransaction trans, TKey key, TValue value) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } trans.Clear(this.Subspace[key, value]); }
/// <summary>Remove an entity from the index</summary> /// <param name="trans">Transaction to use</param> /// <param name="id">Id of the entity that has been deleted</param> /// <param name="value">Previous value of the entity in the index</param> public void Remove([NotNull] IFdbTransaction trans, TId id, TValue value) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } trans.Clear(this.Subspace.Keys[value, id]); }
/// <summary>Remove a single entry from the map</summary> /// <param name="trans">Transaction used for the operation</param> /// <param name="id">Key of the entry to remove</param> /// <remarks>If the entry did not exist, the operation will not do anything.</remarks> public void Remove([NotNull] IFdbTransaction trans, TKey id) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (id == null) { throw new ArgumentNullException(nameof(id)); } trans.Clear(this.Subspace.Keys[id]); }
/// <summary>Remove a single entry from the map</summary> /// <param name="trans">Transaction used for the operation</param> /// <param name="id">Key of the entry to remove</param> /// <remarks>If the entry did not exist, the operation will not do anything.</remarks> public void Remove([NotNull] IFdbTransaction trans, TKey id) { if (trans == null) { throw new ArgumentNullException("trans"); } if (id == null) { throw new ArgumentNullException("id"); } trans.Clear(this.Location.Keys.Encode(id)); }
/// <summary> /// Drop a student from a class /// </summary> public async Task Drop(IFdbTransaction tr, string s, string c) { var rec = AttendsKey(s, c); if ((await tr.GetAsync(rec)).IsNullOrEmpty) { // not taking this class return; } var students = Int32.Parse((await tr.GetAsync(ClassKey(c))).ToStringAscii()); tr.Set(ClassKey(c), Slice.FromStringAscii((students + 1).ToString())); tr.Clear(rec); }
private async Task <Optional <T> > PopSimpleAsync([NotNull] IFdbTransaction tr) { #if DEBUG tr.Annotate("PopSimple()"); #endif var firstItem = await GetFirstItemAsync(tr).ConfigureAwait(false); if (firstItem.Key.IsNull) { return(default(Optional <T>)); } tr.Clear(firstItem.Key); return(this.Encoder.DecodeValue(firstItem.Value)); }
/// <summary>Remove a field of an hashset</summary> /// <param name="trans"></param> /// <param name="id"></param> /// <param name="field"></param> public void DeleteValue(IFdbTransaction trans, IVarTuple id, string field) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (id == null) { throw new ArgumentNullException(nameof(id)); } if (string.IsNullOrEmpty(field)) { throw new ArgumentNullException(nameof(field)); } trans.Clear(GetFieldKey(id, field)); }
/// <summary>Update the indexed values of an entity</summary> /// <param name="trans">Transaction to use</param> /// <param name="id">Id of the entity that has changed</param> /// <param name="newValue">Previous value of this entity in the index</param> /// <param name="previousValue">New value of this entity in the index</param> /// <returns>True if a change was performed in the index; otherwise false (if <paramref name="previousValue"/> and <paramref name="newValue"/>)</returns> /// <remarks>If <paramref name="newValue"/> and <paramref name="previousValue"/> are identical, then nothing will be done. Otherwise, the old index value will be deleted and the new value will be added</remarks> public bool Update([NotNull] IFdbTransaction trans, TId id, TValue newValue, TValue previousValue) { if (!this.ValueComparer.Equals(newValue, previousValue)) { // remove previous value if (this.IndexNullValues || previousValue != null) { trans.Clear(this.Subspace.Keys[previousValue, id]); } // add new value if (this.IndexNullValues || newValue != null) { trans.Set(this.Subspace.Keys[newValue, id], Slice.Empty); } // cannot be both null, so we did at least something) return(true); } return(false); }
public async Task EraseAsync(IFdbTransaction trans, Slice key) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (!(await ContainsAsync(trans, key).ConfigureAwait(false))) { return; } for (int level = 0; level < MAX_LEVELS; level++) { // This could be optimized with hash var k = this.Subspace.Encode(level, key); var c = await trans.GetAsync(k).ConfigureAwait(false); if (c.HasValue) { trans.Clear(k); } if (level == 0) { continue; } var prevKey = await GetPreviousNodeAsync(trans, level, key); Contract.Assert(prevKey != key); long countChange = -1; if (c.HasValue) { countChange += DecodeCount(c); } trans.AtomicAdd64(this.Subspace.Encode(level, prevKey), countChange); } }
/// <summary>Get and pops the last item off the Vector.</summary> public async Task <Optional <T> > PopAsync([NotNull] IFdbTransaction tr) { if (tr == null) { throw new ArgumentNullException("tr"); } var keyRange = this.Subspace.Keys.ToRange(); // Read the last two entries so we can check if the second to last item // is being represented sparsely. If so, we will be required to set it // to the default value var lastTwo = await tr .GetRange(keyRange, new FdbRangeOptions { Reverse = true, Limit = 2 }) .ToListAsync() .ConfigureAwait(false); // Vector was empty if (lastTwo.Count == 0) { return(default(Optional <T>)); } //note: keys are reversed so indices[0] = last, indices[1] = second to last var indices = lastTwo.Select(kvp => this.Subspace.Keys.DecodeFirst <long>(kvp.Key)).ToList(); if (indices[0] == 0) { // Vector has size one //pass } else if (lastTwo.Count == 1 || indices[0] > indices[1] + 1) { // Second to last item is being represented sparsely tr.Set(GetKeyAt(indices[0] - 1), this.Encoder.EncodeValue(this.DefaultValue)); } tr.Clear(lastTwo[0].Key); return(this.Encoder.DecodeValue(lastTwo[0].Value)); }
/// <summary>Remove one or more fields of an hashset</summary> /// <param name="trans"></param> /// <param name="id"></param> /// <param name="fields"></param> public void Delete(IFdbTransaction trans, IVarTuple id, params string[] fields) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (id == null) { throw new ArgumentNullException(nameof(id)); } if (fields == null) { throw new ArgumentNullException(nameof(fields)); } foreach (var field in fields) { if (string.IsNullOrEmpty(field)) { throw new ArgumentException("Field cannot have an empty name", nameof(fields)); } trans.Clear(GetFieldKey(id, field)); } }
/// <summary>Remove an existing node from its parents</summary> /// <returns>True if the parent node was found, otherwise false</returns> private async Task<bool> RemoveFromParent(IFdbTransaction tr, IFdbTuple path) { Contract.Requires(tr != null && path != null); var parent = await FindAsync(tr, path.Substring(0, path.Count - 1)).ConfigureAwait(false); if (parent.Exists) { if (FdbDirectoryLayer.AnnotateTransactions) tr.Annotate("Removing path {0} from its parent folder at {1}", path, parent.Subspace.Key); tr.Clear(GetSubDirKey(parent.Subspace, path.Get<string>(-1))); return true; } return false; }
/// <summary>Remove an existing node from its parents</summary> /// <returns>True if the parent node was found, otherwise false</returns> private async Task<bool> RemoveFromParent(IFdbTransaction tr, IFdbTuple path) { Contract.Requires(tr != null && path != null); var parent = await FindAsync(tr, path.Substring(0, path.Count - 1)).ConfigureAwait(false); if (parent.Exists) { tr.Clear(GetSubDirKey(parent.Subspace, path.Get<string>(-1))); return true; } return false; }
// Compare the behavior of the MemoryDB against a FoundationDB database private async Task Scenario1(IFdbTransaction tr) { tr.Set(Slice.FromAscii("hello"), Slice.FromAscii("world!")); tr.Clear(Slice.FromAscii("removed")); var result = await tr.GetAsync(Slice.FromAscii("narf")); }
/// <summary> /// Drop a student from a class /// </summary> public async Task Drop(IFdbTransaction tr, string s, string c) { var rec = AttendsKey(s, c); if ((await tr.GetAsync(rec)).IsNullOrEmpty) { // not taking this class return; } var students = Int32.Parse((await tr.GetAsync(ClassKey(c))).ToAscii()); tr.Set(ClassKey(c), Slice.FromAscii((students + 1).ToString())); tr.Clear(rec); }
public virtual void Clear(Slice key) { ThrowIfDisposed(); m_transaction.Clear(key); }
public void Clear([NotNull] IFdbTransaction trans, T key) { trans.Clear(EncodeKey(key)); }
private async Task<bool> TryRemoteSplitPointAsync(IFdbTransaction trans, long offset) { Contract.Requires(trans != null && offset >= 0); var b = await GetChunkAtAsync(trans, offset).ConfigureAwait(false); if (b.Offset == 0 || b.Key == Slice.Nil) return false; // in sparse region, or at beginning var a = await GetChunkAtAsync(trans, b.Offset - 1).ConfigureAwait(false); if (a.Key == Slice.Nil) return false; // no previous chunk if (a.Offset + a.Data.Count != b.Offset) return false; // chunks can't be joined if (a.Data.Count + b.Data.Count > CHUNK_SMALL) return false; // chunks shouldn't be joined // yay--merge chunks trans.Clear(b.Key); trans.Set(a.Key, a.Data + b.Data); return true; }
public void Clear([NotNull] IFdbTransaction trans, FdbTuple <T1, T2> key) { trans.Clear(EncodeKey(key)); }
public void Clear([NotNull] IFdbTransaction trans, T1 key1, T2 key2) { trans.Clear(EncodeKey(key1, key2)); }
/// <inheritdoc /> public virtual void Clear(ReadOnlySpan <byte> key) { ThrowIfDisposed(); m_transaction.Clear(key); }
/// <summary>Remove a field of an hashset</summary> /// <param name="trans"></param> /// <param name="id"></param> /// <param name="field"></param> public void DeleteValue(IFdbTransaction trans, IFdbTuple id, string field) { if (trans == null) throw new ArgumentNullException("trans"); if (id == null) throw new ArgumentNullException("id"); if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field"); trans.Clear(GetFieldKey(id, field)); }
/// <summary>Remove one or more fields of an hashset</summary> /// <param name="trans"></param> /// <param name="id"></param> /// <param name="fields"></param> public void Delete(IFdbTransaction trans, IFdbTuple id, params string[] fields) { if (trans == null) throw new ArgumentNullException("trans"); if (id == null) throw new ArgumentNullException("id"); if (fields == null) throw new ArgumentNullException("fields"); foreach (var field in fields) { if (string.IsNullOrEmpty(field)) throw new ArgumentException("Field cannot have an empty name", "fields"); trans.Clear(GetFieldKey(id, field)); } }
/// <summary>Remove an entity from the index</summary> public void Remove(IFdbTransaction trans, TId id, TValue value) { trans.Clear(this.Subspace[value, id]); }