private async Task <long> GetNextIndexAsync([NotNull] IFdbReadOnlyTransaction tr, FdbSubspace subspace) { var range = subspace.ToRange(); var lastKey = await tr.GetKeyAsync(FdbKeySelector.LastLessThan(range.End)).ConfigureAwait(false); if (lastKey < range.Begin) { return(0); } return(subspace.Unpack(lastKey).Get <long>(0) + 1); }
private async Task PushQueueAsync(IFdbTransaction tr, FdbSubspace queue, Slice taskId) { //TODO: use a high contention algo ? // - must support Push and Pop // - an empty queue must correspond to an empty subspace // get the current size of the queue var range = queue.ToRange(); var lastKey = await tr.Snapshot.GetKeyAsync(FdbKeySelector.LastLessThan(range.End)).ConfigureAwait(false); int count = lastKey < range.Begin ? 0 : queue.Unpack(lastKey).Get <int>(0) + 1; // set the value tr.Set(queue.Pack(count, GetRandomId()), taskId); }
private async Task <KeyValuePair <Slice, Slice> > FindRandomItem(IFdbTransaction tr, FdbSubspace ring) { var range = ring.ToRange(); // start from a random position around the ring Slice key = ring.Pack(GetRandomId()); // We want to find the next item in the clockwise direction. If we reach the end of the ring, we "wrap around" by starting again from the start // => So we do find_next(key <= x < MAX) and if that does not produce any result, we do a find_next(MIN <= x < key) // When the ring only contains a few items (or is empty), there is more than 50% change that we wont find anything in the first read. // To reduce the latency for this case, we will issue both range reads at the same time, and discard the second one if the first returned something. // This should reduce the latency in half when the ring is empty, or when it contains only items before the random key. var candidate = await tr.GetRange(key, range.End).FirstOrDefaultAsync(); if (!candidate.Key.IsPresent) { candidate = await tr.GetRange(range.Begin, key).FirstOrDefaultAsync(); } return(candidate); }
private async Task PushQueueAsync(IFdbTransaction tr, FdbSubspace queue, Slice taskId) { //TODO: use a high contention algo ? // - must support Push and Pop // - an empty queue must correspond to an empty subspace // get the current size of the queue var range = queue.ToRange(); var lastKey = await tr.Snapshot.GetKeyAsync(FdbKeySelector.LastLessThan(range.End)).ConfigureAwait(false); int count = lastKey < range.Begin ? 0 : queue.Unpack(lastKey).Get<int>(0) + 1; // set the value tr.Set(queue.Pack(count, GetRandomId()), taskId); }
private async Task<KeyValuePair<Slice, Slice>> FindRandomItem(IFdbTransaction tr, FdbSubspace ring) { var range = ring.ToRange(); // start from a random position around the ring Slice key = ring.Pack(GetRandomId()); // We want to find the next item in the clockwise direction. If we reach the end of the ring, we "wrap around" by starting again from the start // => So we do find_next(key <= x < MAX) and if that does not produce any result, we do a find_next(MIN <= x < key) // When the ring only contains a few items (or is empty), there is more than 50% change that we wont find anything in the first read. // To reduce the latency for this case, we will issue both range reads at the same time, and discard the second one if the first returned something. // This should reduce the latency in half when the ring is empty, or when it contains only items before the random key. var candidate = await tr.GetRange(key, range.End).FirstOrDefaultAsync(); if (!candidate.Key.IsPresent) { candidate = await tr.GetRange(range.Begin, key).FirstOrDefaultAsync(); } return candidate; }
/// <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>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()); }