示例#1
0
        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());
		}