/// <summary>Returns a 64-bit integer that /// 1) has never and will never be returned by another call to this /// method on the same subspace /// 2) is nearly as short as possible given the above /// </summary> public async Task<long> AllocateAsync(IFdbTransaction trans) { // find the current window size, by reading the last entry in the 'counters' subspace long start = 0, count = 0; var kv = await trans .Snapshot .GetRange(this.Counters.ToRange()) .LastOrDefaultAsync(); if (kv.Key.IsPresent) { start = this.Counters.UnpackSingle<long>(kv.Key); count = kv.Value.ToInt64(); } // check if the window is full int window = GetWindowSize(start); if ((count + 1) * 2 >= window) { // advance the window trans.ClearRange(this.Counters.Key, this.Counters.Pack(start) + FdbKey.MinValue); start += window; trans.ClearRange(this.Recent.Key, this.Recent.Pack(start)); } // Increment the allocation count for the current window trans.AtomicAdd(this.Counters.Pack(start), Slice.FromFixed64(1)); // As of the snapshot being read from, the window is less than half // full, so this should be expected to take 2 tries. Under high // contention (and when the window advances), there is an additional // subsequent risk of conflict for this transaction. while (true) { // Find a random free slot in the current window... long candidate; lock (m_rnd) { candidate = start + m_rnd.Next(window); } // test if the key is used var key = this.Recent.Pack(candidate); var value = await trans.GetAsync(key).ConfigureAwait(false); if (value.IsNull) { // free slot // mark as used trans.Set(key, Slice.Empty); return candidate; } // no luck this time, try again... } }
private Task Scenario3(IFdbTransaction tr) { var location = FdbSubspace.Create(Slice.FromAscii("TEST")); tr.Set(location.Key + (byte)'a', Slice.FromAscii("A")); tr.AtomicAdd(location.Key + (byte)'k', Slice.FromFixed32(1)); tr.Set(location.Key + (byte)'z', Slice.FromAscii("C")); tr.ClearRange(location.Key + (byte)'a', location.Key + (byte)'k'); tr.ClearRange(location.Key + (byte)'k', location.Key + (byte)'z'); return Task.FromResult<object>(null); }
/// <summary> /// Delete all key-value pairs associated with the blob. /// </summary> public void Delete([NotNull] IFdbTransaction trans) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } trans.ClearRange(this.Subspace); }
/// <summary>Remove all the values for a specific key</summary> /// <param name="trans"></param> /// <param name="key"></param> /// <returns></returns> public void Remove([NotNull] IFdbTransaction trans, TKey key) { if (trans == null) { throw new ArgumentNullException("trans"); } trans.ClearRange(KeyRange.StartsWith(this.Location.Partial.Keys.Encode(key))); }
/// <summary>Insert a new document in the collection</summary> public async Task InsertAsync(IFdbTransaction trans, TDocument document) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (document == null) { throw new ArgumentNullException(nameof(document)); } var id = this.IdSelector(document); if (id == null) { throw new InvalidOperationException("Cannot insert a document with a null identifier"); } // encode the document var packed = this.ValueEncoder.EncodeValue(document); var subspace = await this.Location.Resolve(trans); if (subspace == null) { throw new InvalidOperationException($"Location '{this.Location}' referenced by Document Collection Layer was not found."); } // Key Prefix = ...(id,) var key = subspace.EncodePartial(id); // clear previous value trans.ClearRange(KeyRange.StartsWith(key)); int remaining = packed.Count; if (remaining <= this.ChunkSize) { // stored as a single element // Key = ...(id,) trans.Set(key, packed); } else { // splits in as many chunks as necessary // Key = ...(id, N) where N is the chunk index (0-based) int p = 0; int index = 0; while (remaining > 0) { int sz = Math.Max(remaining, this.ChunkSize); trans.Set(subspace[id, index], packed.Substring(p, sz)); ++index; p += sz; remaining -= sz; } } }
private Task Scenario2(IFdbTransaction tr) { var location = FdbSubspace.Create(Slice.FromAscii("TEST")); tr.ClearRange(FdbKeyRange.StartsWith(location.Key)); for (int i = 0; i < 10; i++) { tr.Set(location.Pack(i), Slice.FromString("value of " + i)); } return Task.FromResult<object>(null); }
private Task Scenario2(IFdbTransaction tr) { var location = FdbSubspace.Create(Slice.FromAscii("TEST")); tr.ClearRange(FdbKeyRange.StartsWith(location.Key)); for (int i = 0; i < 10; i++) { tr.Set(location.Pack(i), Slice.FromString("value of " + i)); } return(Task.FromResult <object>(null)); }
/// <summary>Delete a document from the collection</summary> /// <param name="trans"></param> /// <param name="ids"></param> public void DeleteMultiple(IFdbTransaction trans, IEnumerable<TId> ids) { if (trans == null) throw new ArgumentNullException(nameof(trans)); if (ids == null) throw new ArgumentNullException(nameof(ids)); foreach (var id in ids) { var key = this.Subspace.Keys.EncodePartial(id); trans.ClearRange(KeyRange.StartsWith(key)); } }
/// <summary>Remove all fields of an hashset</summary> /// <param name="id"></param> public void Delete(IFdbTransaction trans, IVarTuple id) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (id == null) { throw new ArgumentNullException(nameof(id)); } // remove all fields of the hash trans.ClearRange(KeyRange.StartsWith(GetKey(id))); }
/// <summary>Insert a new document in the collection</summary> public void Insert(IFdbTransaction trans, TDocument document) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (document == null) { throw new ArgumentNullException(nameof(document)); } var id = this.IdSelector(document); if (id == null) { throw new InvalidOperationException("Cannot insert a document with a null identifier"); } // encode the document var packed = this.ValueEncoder.EncodeValue(document); // Key Prefix = ...(id,) var key = this.Location.Partial.Keys.Encode(id); // clear previous value trans.ClearRange(KeyRange.StartsWith(key)); int remaining = packed.Count; if (remaining <= this.ChunkSize) { // stored as a single element // Key = ...(id,) trans.Set(key, packed); } else { // splits in as many chunks as necessary // Key = ...(id, N) where N is the chunk index (0-based) int p = 0; int index = 0; while (remaining > 0) { int sz = Math.Max(remaining, this.ChunkSize); trans.Set(this.Location.Keys.Encode(id, index), packed.Substring(p, sz)); ++index; p += sz; remaining -= sz; } } }
/// <summary>Delete a document from the collection</summary> /// <param name="trans"></param> /// <param name="id"></param> public void Delete(IFdbTransaction trans, TId id) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (id == null) { throw new ArgumentNullException(nameof(id)); } var key = this.Location.Partial.Keys.Encode(id); trans.ClearRange(KeyRange.StartsWith(key)); }
/// <summary>Delete a document from the collection</summary> /// <param name="trans"></param> /// <param name="ids"></param> public void DeleteMultiple(IFdbTransaction trans, IEnumerable <TId> ids) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (ids == null) { throw new ArgumentNullException(nameof(ids)); } foreach (var key in this.Location.Partial.Keys.Encode(ids)) { trans.ClearRange(KeyRange.StartsWith(key)); } }
/// <summary>Delete a document from the collection</summary> /// <param name="trans"></param> /// <param name="id"></param> public async Task DeleteAsync(IFdbTransaction trans, TId id) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (id == null) { throw new ArgumentNullException(nameof(id)); } var subspace = await this.Location.Resolve(trans); if (subspace == null) { throw new InvalidOperationException($"Location '{this.Location}' referenced by Document Collection Layer was not found."); } var key = subspace.EncodePartial(id); trans.ClearRange(KeyRange.StartsWith(key)); }
/// <summary>Grow or shrink the size of the Vector.</summary> public async Task ResizeAsync([NotNull] IFdbTransaction tr, long length) { if (tr == null) { throw new ArgumentNullException("tr"); } long currentSize = await ComputeSizeAsync(tr).ConfigureAwait(false); if (length < currentSize) { tr.ClearRange(GetKeyAt(length), this.Subspace.Keys.ToRange().End); // Check if the new end of the vector was being sparsely represented if (await ComputeSizeAsync(tr).ConfigureAwait(false) < length) { tr.Set(GetKeyAt(length - 1), this.Encoder.EncodeValue(this.DefaultValue)); } } else if (length > currentSize) { tr.Set(GetKeyAt(length - 1), this.Encoder.EncodeValue(this.DefaultValue)); } }
private void ClearTask(IFdbTransaction tr, Slice taskId) { tr.Annotate("Deleting task {0}", taskId.ToAsciiOrHexaString()); // clear all metadata about the task tr.ClearRange(FdbKeyRange.StartsWith(this.TaskStore.Pack(taskId))); // decrement pending number of tasks this.Counters.Decrement(tr, COUNTER_PENDING_TASKS); }
/// <summary>Clear the entire content of a subspace</summary> public static void ClearRange(this IFdbTransaction trans, [NotNull] FdbSubspace subspace) { Contract.Requires(trans != null && subspace != null); trans.ClearRange(FdbKeyRange.StartsWith(subspace.Key)); }
/// <inheritdoc /> public virtual void ClearRange(ReadOnlySpan <byte> beginKeyInclusive, ReadOnlySpan <byte> endKeyExclusive) { ThrowIfDisposed(); m_transaction.ClearRange(beginKeyInclusive, endKeyExclusive); }
/// <summary>Returns a 64-bit integer that /// 1) has never and will never be returned by another call to this /// method on the same subspace /// 2) is nearly as short as possible given the above /// </summary> public async Task <long> AllocateAsync([NotNull] IFdbTransaction trans) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } // find the current window size, by reading the last entry in the 'counters' subspace long start = 0, count = 0; var kv = await trans .Snapshot .GetRange(this.Counters.Keys.ToRange()) .LastOrDefaultAsync(); if (kv.Key.IsPresent) { start = this.Counters.Keys.Decode <long>(kv.Key); count = kv.Value.ToInt64(); } // check if the window is full int window = GetWindowSize(start); if ((count + 1) * 2 >= window) { // advance the window if (FdbDirectoryLayer.AnnotateTransactions) { trans.Annotate("Advance allocator window size to {0} starting at {1}", window, start + window); } trans.ClearRange(this.Counters.GetPrefix(), this.Counters.Keys.Encode(start) + FdbKey.MinValue); start += window; count = 0; trans.ClearRange(this.Recent.GetPrefix(), this.Recent.Keys.Encode(start)); } // Increment the allocation count for the current window trans.AtomicAdd64(this.Counters.Keys.Encode(start), 1); // As of the snapshot being read from, the window is less than half // full, so this should be expected to take 2 tries. Under high // contention (and when the window advances), there is an additional // subsequent risk of conflict for this transaction. while (true) { // Find a random free slot in the current window... long candidate; lock (m_rnd) { candidate = start + m_rnd.Next(window); } // test if the key is used var key = this.Recent.Keys.Encode(candidate); var value = await trans.GetAsync(key).ConfigureAwait(false); if (value.IsNull) { // free slot // mark as used trans.Set(key, Slice.Empty); if (FdbDirectoryLayer.AnnotateTransactions) { trans.Annotate("Allocated prefix {0} from window [{1}..{2}] ({3} used)", candidate, start, start + window - 1, count + 1); } return(candidate); } // no luck this time, try again... } }
public virtual void ClearRange(Slice beginKeyInclusive, Slice endKeyExclusive) { ThrowIfDisposed(); m_transaction.ClearRange(beginKeyInclusive, endKeyExclusive); }
/// <summary> /// Delete all key-value pairs associated with the blob. /// </summary> public void Delete(IFdbTransaction trans) { if (trans == null) throw new ArgumentNullException("trans"); trans.ClearRange(this.Subspace); }
public static async Task <long> AllocateAsync(IFdbTransaction trans, ITypedKeySubspace <int, long> subspace, Random rng) { Contract.NotNull(trans); // find the current window size, by reading the last entry in the 'counters' subspace long start = 0, count = 0; var kv = await trans .Snapshot .GetRange(subspace.EncodePartialRange(COUNTERS)) .LastOrDefaultAsync(); if (kv.Key.Count != 0) { start = subspace.DecodeLast(kv.Key); count = kv.Value.ToInt64(); } // check if the window is full int window = GetWindowSize(start); if ((count + 1) * 2 >= window) { // advance the window if (FdbDirectoryLayer.AnnotateTransactions) { trans.Annotate("Advance allocator window size to {0} starting at {1}", window, start + window); } trans.ClearRange(subspace[COUNTERS, 0], subspace[COUNTERS, start + 1]); start += window; count = 0; trans.ClearRange(subspace[RECENT, 0], subspace[RECENT, start]); } // Increment the allocation count for the current window trans.AtomicAdd64(subspace[COUNTERS, start], 1); // As of the snapshot being read from, the window is less than half // full, so this should be expected to take 2 tries. Under high // contention (and when the window advances), there is an additional // subsequent risk of conflict for this transaction. while (true) { // Find a random free slot in the current window... long candidate; lock (rng) { candidate = start + rng.Next(window); } // test if the key is used var key = subspace[RECENT, candidate]; var value = await trans.GetAsync(key).ConfigureAwait(false); if (value.IsNull) { // free slot // mark as used trans.Set(key, Slice.Empty); if (FdbDirectoryLayer.AnnotateTransactions) { trans.Annotate("Allocated prefix {0} from window [{1}..{2}] ({3} used)", candidate, start, start + window - 1, count + 1); } return(candidate); } // no luck this time, try again... } }
/// <summary>Resursively remove a node (including the content), all its children</summary> private async Task RemoveRecursive(IFdbTransaction tr, FdbSubspace node) { Contract.Requires(tr != null && node != null); //note: we could use Task.WhenAll to remove the children, but there is a risk of task explosion if the subtree is very large... await SubdirNamesAndNodes(tr, node).ForEachAsync((kvp) => RemoveRecursive(tr, kvp.Value)).ConfigureAwait(false); // remove ALL the contents if (FdbDirectoryLayer.AnnotateTransactions) tr.Annotate("Removing all content located under {0}", node.Key); tr.ClearRange(FdbKeyRange.StartsWith(ContentsOfNode(node, FdbTuple.Empty, Slice.Empty).Key)); // and all the metadata for this folder if (FdbDirectoryLayer.AnnotateTransactions) tr.Annotate("Removing all metadata for folder under {0}", node.Key); tr.ClearRange(node.ToRange()); }
/// <summary>Remove all the values for a specific key</summary> /// <param name="trans"></param> /// <param name="key"></param> /// <returns></returns> public void Remove([NotNull] IFdbTransaction trans, TKey key) { if (trans == null) throw new ArgumentNullException(nameof(trans)); trans.ClearRange(KeyRange.StartsWith(this.Subspace.Keys.EncodePartial(key))); }
/// <summary>Remove all items from the queue.</summary> public void Clear(IFdbTransaction tr) { Contract.NotNull(tr, nameof(tr)); tr.ClearRange(this.Subspace.ToRange()); }
//TODO: get_range /// <summary>Clears the entire set.</summary> public Task ClearAllAsync(IFdbTransaction trans) { trans.ClearRange(this.Subspace.ToRange()); return(SetupLevelsAsync(trans)); }
/// <summary>Resursively remove a node (including the content), all its children</summary> private async Task RemoveRecursive(IFdbTransaction tr, FdbSubspace node) { Contract.Requires(tr != null && node != null); //note: we could use Task.WhenAll to remove the children, but there is a risk of task explosion if the subtree is very large... await SubdirNamesAndNodes(tr, node).ForEachAsync((kvp) => RemoveRecursive(tr, kvp.Value)).ConfigureAwait(false); tr.ClearRange(FdbKeyRange.StartsWith(ContentsOfNode(node, FdbTuple.Empty, Slice.Empty).Key)); tr.ClearRange(node.ToRange()); }
/// <summary>Remove all fields of an hashset</summary> /// <param name="id"></param> public void Delete(IFdbTransaction trans, IFdbTuple id) { if (trans == null) throw new ArgumentNullException("trans"); if (id == null) throw new ArgumentNullException("id"); // remove all fields of the hash trans.ClearRange(FdbKeyRange.StartsWith(GetKey(id))); }
private async Task MakeSparseAsync(IFdbTransaction trans, long start, long end) { await MakeSplitPointAsync(trans, start).ConfigureAwait(false); await MakeSplitPointAsync(trans, end).ConfigureAwait(false); trans.ClearRange(DataKey(start), DataKey(end)); }