/// <summary>
		/// Returns the list of names of all existing classes
		/// </summary>
		public Task<List<string>> AvailableClasses(IFdbReadOnlyTransaction tr)
		{
			return tr.GetRange(this.Subspace.Keys.ToRange(FdbTuple.Create("class")))
				.Where(kvp => { int _; return Int32.TryParse(kvp.Value.ToAscii(), out _); }) // (step 3)
				.Select(kvp => this.Subspace.Keys.Decode<string>(kvp.Key))
				.ToListAsync();
		}
        public IAsyncEnumerable <KeyValuePair <TKey, TValue> > All([NotNull] IFdbReadOnlyTransaction trans, FdbRangeOptions options = null)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }

            return(trans
                   .GetRange(this.Subspace.ToRange(), options)
                   .Select(this.DecodeItem));
        }
            private Task <long> SlowCountAsync(IFdbReadOnlyTransaction trans, int level, Slice beginKey, Slice endKey)
            {
                if (level == -1)
                {
                    return(Task.FromResult <long>(beginKey.IsPresent ? 1 : 0));
                }

                return(trans
                       .GetRange(this.Subspace.Encode(level, beginKey), this.Subspace.Encode(level, endKey))
                       .Select(kv => DecodeCount(kv.Value))
                       .SumAsync());
            }
Example #4
0
            /// <summary>Get the value of the last item in the Vector.</summary>
            public Task <T> BackAsync(IFdbReadOnlyTransaction tr)
            {
                if (tr == null)
                {
                    throw new ArgumentNullException(nameof(tr));
                }

                return(tr
                       .GetRange(this.Subspace.ToRange())
                       .Select((kvp) => this.Encoder.DecodeValue(kvp.Value) !)
                       .LastOrDefaultAsync());
            }
Example #5
0
        public static IAsyncEnumerable <KeyValuePair <Slice, Slice> > MergeSort <TKey>([NotNull] this IFdbReadOnlyTransaction trans, [NotNull] IEnumerable <KeySelectorPair> ranges, [NotNull] Func <KeyValuePair <Slice, Slice>, TKey> keySelector, IComparer <TKey> keyComparer = null)
        {
            //TODO: Range options ?
            Contract.NotNull(trans, nameof(trans));
            Contract.NotNull(ranges, nameof(ranges));
            Contract.NotNull(keySelector, nameof(keySelector));

            trans.EnsureCanRead();
            return(new MergeSortAsyncIterator <KeyValuePair <Slice, Slice>, TKey, KeyValuePair <Slice, Slice> >(
                       ranges.Select(range => trans.GetRange(range, new FdbRangeOptions {
                Mode = FdbStreamingMode.Iterator
            })),
Example #6
0
        public IAsyncEnumerable <(TValue Value, long Count)> GetCounts([NotNull] IFdbReadOnlyTransaction trans, TKey key)
        {
            var range = KeyRange.StartsWith(this.Subspace.Keys.EncodePartial(key));

            var query = trans
                        .GetRange(range)
                        .Select(kvp => (Value: this.Subspace.Keys.Decode(kvp.Key).Item2, Count: kvp.Value.ToInt64()));

            return(this.AllowNegativeValues
                                ? query
                                : query.Where(x => x.Count > 0));
        }
            /// <summary>Returns the number of items in the set.</summary>
            /// <param name="trans"></param>
            /// <returns></returns>
            public Task <long> SizeAsync(IFdbReadOnlyTransaction trans)
            {
                if (trans == null)
                {
                    throw new ArgumentNullException(nameof(trans));
                }

                return(trans
                       .GetRange(this.Subspace.Partition.ByKey(MAX_LEVELS - 1).ToRange())
                       .Select(kv => DecodeCount(kv.Value))
                       .SumAsync());
            }
		private static async Task PrintRankedSet(FdbRankedSet rs, IFdbReadOnlyTransaction tr)
		{
			var sb = new StringBuilder();
			for (int l = 0; l < 6; l++)
			{
				sb.AppendFormat("Level {0}:\r\n", l);
				await tr.GetRange(rs.Subspace.Partition(l).ToRange()).ForEachAsync((kvp) =>
				{
					sb.AppendFormat("\t{0} = {1}\r\n", rs.Subspace.Unpack(kvp.Key), kvp.Value.ToInt64());
				});
			}
			Console.WriteLine(sb.ToString());
		}
Example #9
0
        private static async Task PrintRankedSet(FdbRankedSet rs, IFdbReadOnlyTransaction tr)
        {
            var sb = new StringBuilder();

            for (int l = 0; l < 6; l++)
            {
                sb.AppendFormat("Level {0}:\r\n", l);
                await tr.GetRange(rs.Subspace.Partition.ByKey(l).Keys.ToRange()).ForEachAsync((kvp) =>
                {
                    sb.AppendFormat("\t{0} = {1}\r\n", rs.Subspace.Keys.Unpack(kvp.Key), kvp.Value.ToInt64());
                });
            }
            Log(sb.ToString());
        }
Example #10
0
        public IFdbAsyncEnumerable <TValue> Get([NotNull] IFdbReadOnlyTransaction trans, TKey key)
        {
            if (trans == null)
            {
                throw new ArgumentNullException("trans");
            }

            var range = FdbKeyRange.StartsWith(this.Location.Partial.Keys.Encode(key));

            if (this.AllowNegativeValues)
            {
                return(trans
                       .GetRange(range)
                       .Select(kvp => this.Location.Keys.Decode(kvp.Key).Item2));
            }
            else
            {
                return(trans
                       .GetRange(range)
                       .Where(kvp => kvp.Value.ToInt64() > 0)                  // we need to filter out zero or negative values (possible artefacts)
                       .Select(kvp => this.Location.Keys.Decode(kvp.Key).Item2));
            }
        }
Example #11
0
        public static IFdbAsyncEnumerable <TResult> MergeSort <TKey, TResult>(this IFdbReadOnlyTransaction trans, IEnumerable <FdbKeySelectorPair> ranges, Func <KeyValuePair <Slice, Slice>, TKey> keySelector, Func <KeyValuePair <Slice, Slice>, TResult> resultSelector, IComparer <TKey> keyComparer = null)
        {
            //TODO: Range options ?

            trans.EnsureCanRead();
            return(new FdbMergeSortIterator <KeyValuePair <Slice, Slice>, TKey, TResult>(
                       ranges.Select(range => trans.GetRange(range, new FdbRangeOptions {
                Mode = FdbStreamingMode.Iterator
            })),
                       default(int?),
                       keySelector,
                       resultSelector,
                       keyComparer
                       ));
        }
Example #12
0
        public static IFdbAsyncEnumerable <KeyValuePair <Slice, Slice> > Intersect <TKey>(this IFdbReadOnlyTransaction trans, IEnumerable <FdbKeySelectorPair> ranges, Func <KeyValuePair <Slice, Slice>, TKey> keySelector, IComparer <TKey> keyComparer = null)
        {
            //TODO: Range options ?

            trans.EnsureCanRead();
            return(new FdbIntersectIterator <KeyValuePair <Slice, Slice>, TKey, KeyValuePair <Slice, Slice> >(
                       ranges.Select(range => trans.GetRange(range, new FdbRangeOptions {
                Mode = FdbStreamingMode.Iterator
            })),
                       default(int?),
                       keySelector,
                       TaskHelpers.Cache <KeyValuePair <Slice, Slice> > .Identity,
                       keyComparer
                       ));
        }
        /// <summary>Get the value of the counter.
        /// Not recommended for use with read/write transactions when the counter is being frequently updated (conflicts will be very likely).
        /// </summary>
        public async Task <long> GetTransactional(IFdbReadOnlyTransaction trans)
        {
            if (trans == null)
            {
                throw new ArgumentNullException("trans");
            }

            long total = 0;
            await trans
            .GetRange(this.Subspace.ToRange())
            .ForEachAsync((kvp) => { checked { total += this.Encoder.DecodeValue(kvp.Value); } })
            .ConfigureAwait(false);

            return(total);
        }
Example #14
0
        public IFdbAsyncEnumerable <KeyValuePair <TValue, long> > GetCounts([NotNull] IFdbReadOnlyTransaction trans, TKey key)
        {
            var range = FdbKeyRange.StartsWith(this.Location.Partial.Keys.Encode(key));

            var query = trans
                        .GetRange(range)
                        .Select(kvp => new KeyValuePair <TValue, long>(this.Location.Keys.Decode(kvp.Key).Item2, kvp.Value.ToInt64()));

            if (this.AllowNegativeValues)
            {
                return(query);
            }
            else
            {
                return(query.Where(kvp => kvp.Value > 0));
            }
        }
        public static IFdbAsyncEnumerable <KeyValuePair <Slice, Slice> > Except <TKey>([NotNull] this IFdbReadOnlyTransaction trans, IEnumerable <KeySelectorPair> ranges, Func <KeyValuePair <Slice, Slice>, TKey> keySelector, IComparer <TKey> keyComparer = null)
        {
            //TODO: Range options ?
            Contract.NotNull(trans, nameof(trans));
            Contract.NotNull(ranges, nameof(ranges));
            Contract.NotNull(keySelector, nameof(keySelector));

            trans.EnsureCanRead();
            return(new FdbExceptIterator <KeyValuePair <Slice, Slice>, TKey, KeyValuePair <Slice, Slice> >(
                       ranges.Select(range => trans.GetRange(range, new FdbRangeOptions {
                Mode = FdbStreamingMode.Iterator
            })),
                       default(int?),
                       keySelector,
                       (kv) => kv,
                       keyComparer
                       ));
        }
            public async Task <long?> Rank(IFdbReadOnlyTransaction trans, Slice key)
            {
                if (trans == null)
                {
                    throw new ArgumentNullException(nameof(trans));
                }
                if (key.IsNull)
                {
                    throw new ArgumentException("Empty key not allowed in set", nameof(key));
                }

                if (!(await ContainsAsync(trans, key).ConfigureAwait(false)))
                {
                    return(default(long?));
                }

                long r       = 0;
                var  rankKey = Slice.Empty;

                for (int level = MAX_LEVELS - 1; level >= 0; level--)
                {
                    var  lss       = this.Subspace.Partition.ByKey(level);
                    long lastCount = 0;
                    var  kcs       = await trans.GetRange(
                        KeySelector.FirstGreaterOrEqual(lss.Encode(rankKey)),
                        KeySelector.FirstGreaterThan(lss.Encode(key))
                        ).ToListAsync().ConfigureAwait(false);

                    foreach (var kc in kcs)
                    {
                        rankKey   = lss.Decode <Slice>(kc.Key);
                        lastCount = DecodeCount(kc.Value);
                        r        += lastCount;
                    }
                    r -= lastCount;
                    if (rankKey == key)
                    {
                        break;
                    }
                }
                return(r);
            }
Example #17
0
        public FdbRangeQuery <TId> LookupGreaterThan([NotNull] IFdbReadOnlyTransaction trans, TValue value, bool orEqual, bool reverse = false)
        {
            var prefix = this.Location.Partial.EncodeKey(value);

            if (!orEqual)
            {
                prefix = FdbKey.Increment(prefix);
            }

            var space = new FdbKeySelectorPair(
                FdbKeySelector.FirstGreaterThan(prefix),
                this.Location.ToSelectorPair().End
                );

            return(trans
                   .GetRange(space, new FdbRangeOptions {
                Reverse = reverse
            })
                   .Select((kvp) => this.Location.DecodeKey(kvp.Key).Item2));
        }
Example #18
0
        private static async Task PrintVector <T>(FdbVector <T> vector, IFdbReadOnlyTransaction tr)
        {
            bool first = true;
            var  sb    = new StringBuilder();

            await tr.GetRange(vector.Subspace.Keys.ToRange()).ForEachAsync((kvp) =>
            {
                if (!first)
                {
                    sb.Append(", ");
                }
                else
                {
                    first = false;
                }
                sb.Append(vector.Subspace.Keys.DecodeLast <long>(kvp.Key) + ":" + kvp.Value.ToAsciiOrHexaString());
            });

            Console.WriteLine("> Vector: (" + sb.ToString() + ")");
        }
        public FdbRangeQuery <TId> LookupLessThan([NotNull] IFdbReadOnlyTransaction trans, TValue value, bool orEqual, bool reverse = false)
        {
            var prefix = this.Subspace.Keys.EncodePartial(value);

            if (orEqual)
            {
                prefix = FdbKey.Increment(prefix);
            }

            var space = new KeySelectorPair(
                KeySelector.FirstGreaterOrEqual(this.Subspace.ToRange().Begin),
                KeySelector.FirstGreaterThan(prefix)
                );

            return(trans
                   .GetRange(space, new FdbRangeOptions {
                Reverse = reverse
            })
                   .Select((kvp) => this.Subspace.Keys.Decode(kvp.Key).Item2));
        }
Example #20
0
        private static async Task PrintVector <T>(FdbVector <T> .State vector, IFdbReadOnlyTransaction tr)
        {
            bool first = true;
            var  sb    = new StringBuilder();

            await tr.GetRange(vector.Subspace.ToRange()).ForEachAsync((kvp) =>
            {
                if (!first)
                {
                    sb.Append(", ");
                }
                else
                {
                    first = false;
                }
                sb.Append($"{vector.Subspace.DecodeLast<long>(kvp.Key)}:{kvp.Value:P}");
            });

            Log("> Vector: (" + sb.ToString() + ")");
        }
Example #21
0
        /// <summary>Return the list the names of all fields of an hashset</summary>
        /// <param name="trans">Transaction that will be used for this request</param>
        /// <param name="id">Unique identifier of the hashset</param>
        /// <returns>List of all fields. If the list is empty, the hashset does not exist</returns>
        public Task <List <string> > GetKeys(IFdbReadOnlyTransaction trans, IVarTuple id)
        {
            //note: As of Beta2, FDB does not have a fdb_get_range that only return the keys. That means that we will have to also read the values from the db, in order to just get the names of the fields :(
            //TODO: find a way to optimize this ?

            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            var prefix = GetKey(id);

            return(trans
                   .GetRange(KeyRange.StartsWith(prefix))
                   .Select((kvp) => ParseFieldKey(TuPack.Unpack(kvp.Key)))
                   .ToListAsync());
        }
        /// <summary>Return the list the names of all fields of an hashset</summary>
        /// <param name="trans">Transaction that will be used for this request</param>
        /// <param name="id">Unique identifier of the hashset</param>
        /// <returns>List of all fields. If the list is empty, the hashset does not exist</returns>
        public Task <List <string> > GetKeys(IFdbReadOnlyTransaction trans, ITuple id, CancellationToken cancellationToken = default(CancellationToken))
        {
            //note: As of Beta2, FDB does not have a fdb_get_range that only return the keys. That means that we will have to also read the values from the db, in order to just get the names of the fields :(
            //TODO: find a way to optimize this ?

            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            var prefix  = GetKey(id);
            var results = new Dictionary <string, Slice>(StringComparer.OrdinalIgnoreCase);

            return(trans
                   .GetRange(KeyRange.StartsWith(prefix))
                   .Select((kvp) => ParseFieldKey(STuple.Unpack(kvp.Key)))
                   .ToListAsync(cancellationToken));
        }
        /// <summary>Get the value of the counter.
        /// Not recommended for use with read/write transactions when the counter is being frequently updated (conflicts will be very likely).
        /// </summary>
        public async Task <long> GetTransactional(IFdbReadOnlyTransaction trans)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }

            var subspace = await this.Location.Resolve(trans);

            if (subspace == null)
            {
                throw new InvalidOperationException($"Location '{this.Location} referenced by High Contention Counter Layer was not found.");
            }

            long total = 0;
            await trans
            .GetRange(subspace.ToRange())
            .ForEachAsync((kvp) => { checked { total += this.Encoder.DecodeValue(kvp.Value); } })
            .ConfigureAwait(false);

            return(total);
        }
            public async Task <Slice> GetNthAsync(IFdbReadOnlyTransaction trans, long rank)
            {
                if (rank < 0)
                {
                    return(Slice.Nil);
                }

                long r   = rank;
                var  key = Slice.Empty;

                for (int level = MAX_LEVELS - 1; level >= 0; level--)
                {
                    var lss = this.Subspace.Partition.ByKey(level);
                    var kcs = await trans.GetRange(lss.Encode(key), lss.ToRange().End).ToListAsync().ConfigureAwait(false);

                    if (kcs.Count == 0)
                    {
                        break;
                    }

                    foreach (var kc in kcs)
                    {
                        key = lss.Decode <Slice>(kc.Key);
                        long count = DecodeCount(kc.Value);
                        if (key.IsPresent && r == 0)
                        {
                            return(key);
                        }
                        if (count > r)
                        {
                            break;
                        }
                        r -= count;
                    }
                }
                return(Slice.Nil);
            }
        public static async Task DumpSubspace(IFdbReadOnlyTransaction tr, IKeySubspace subspace)
        {
            Assert.That(tr, Is.Not.Null);
            Assert.That(subspace, Is.Not.Null);

            FdbTest.Log($"Dumping content of {subspace} at {subspace.GetPrefix():K}:");
            int count = 0;
            await tr
            .GetRange(KeyRange.StartsWith(subspace.GetPrefix()))
            .ForEachAsync((kvp) =>
            {
                var key = subspace.ExtractKey(kvp.Key, boundCheck: true);
                ++count;
                string keyDump;
                try
                {
                    // attempts decoding it as a tuple
                    keyDump = TuPack.Unpack(key).ToString() !;
                }
                catch (Exception)
                {
                    // not a tuple, dump as bytes
                    keyDump = "'" + key.ToString() + "'";
                }

                FdbTest.Log("- " + keyDump + " = " + kvp.Value.ToString());
            });

            if (count == 0)
            {
                FdbTest.Log("> empty !");
            }
            else
            {
                FdbTest.Log("> Found " + count + " values");
            }
        }
        public static async Task DumpSubspace([NotNull] IFdbReadOnlyTransaction tr, [NotNull] IFdbSubspace subspace)
        {
            Assert.That(tr, Is.Not.Null);

            Console.WriteLine("Dumping content of subspace " + subspace.ToString() + " :");
            int count = 0;
            await tr
            .GetRange(KeyRange.StartsWith(subspace.Key))
            .ForEachAsync((kvp) =>
            {
                var key = subspace.ExtractKey(kvp.Key, boundCheck: true);
                ++count;
                string keyDump = null;
                try
                {
                    // attemps decoding it as a tuple
                    keyDump = key.ToTuple().ToString();
                }
                catch (Exception)
                {
                    // not a tuple, dump as bytes
                    keyDump = "'" + key.ToString() + "'";
                }

                Console.WriteLine("- " + keyDump + " = " + kvp.Value.ToString());
            });

            if (count == 0)
            {
                Console.WriteLine("> empty !");
            }
            else
            {
                Console.WriteLine("> Found " + count + " values");
            }
        }
        private Task <List <KeyValuePair <Slice, Slice> > > GetItemsAsync([NotNull] IFdbReadOnlyTransaction tr, int numItems)
        {
            var range = this.QueueItem.Keys.ToRange();

            return(tr.GetRange(range, limit: numItems, reverse: false).ToListAsync());
        }
		private Task<long> SlowCountAsync(IFdbReadOnlyTransaction trans, int level, Slice beginKey, Slice endKey)
		{
			if (level == -1)
			{
				return Task.FromResult<long>(beginKey.IsPresent ? 1 : 0);
			}

			return trans
				.GetRange(this.Subspace.Pack(level, beginKey), this.Subspace.Pack(level, endKey))
				.Select(kv => DecodeCount(kv.Value))
				.SumAsync();
		}
        /// <summary>
        /// Read from the blob, starting at <paramref name="offset"/>, retrieving up to <paramref name="n"/> bytes (fewer then n bytes are returned when the end of the blob is reached).
        /// </summary>
        public async Task <Slice> ReadAsync([NotNull] IFdbReadOnlyTransaction trans, long offset, int n)
        {
            if (trans == null)
            {
                throw new ArgumentNullException("trans");
            }
            if (offset < 0)
            {
                throw new ArgumentNullException("offset", "Offset cannot be less than zero");
            }

            long?size = await GetSizeAsync(trans).ConfigureAwait(false);

            if (size == null)
            {
                return(Slice.Nil);                          // not found
            }
            if (offset >= size.Value)
            {
                return(Slice.Empty);
            }

            // read all chunks matching the segment we need, and copy them in our buffer
            var buffer = new byte[Math.Min(n, size.Value - offset)];

            await trans
            .GetRange(
                FdbKeySelector.LastLessOrEqual(DataKey(offset)),
                FdbKeySelector.FirstGreaterOrEqual(DataKey(offset + n))
                )
            .ForEachAsync((chunk) =>
            {
                // get offset of this chunk
                long chunkOffset = DataKeyOffset(chunk.Key);
                Slice chunkData  = chunk.Value;

                checked
                {
                    // intersect chunk bounds with output
                    int delta = (int)(chunkOffset - offset);
                    int start = delta;
                    int end   = delta + chunkData.Count;
                    if (start < 0)
                    {
                        start = 0;
                    }
                    if (end > n)
                    {
                        end = n;
                    }

                    // compute the relative offsets in the chunk
                    int rStart = start - delta;
                    int rEnd   = end - delta;

                    var intersect = chunkData[rStart, rEnd];
                    if (intersect.IsPresent)
                    {                             // copy the data that fits
                        intersect.CopyTo(buffer, start);
                    }
                }
            })
            .ConfigureAwait(false);

            return(new Slice(buffer, 0, buffer.Length));
        }
Example #30
0
		/// <summary>Get the value of the counter.
		/// Not recommended for use with read/write transactions when the counter is being frequently updated (conflicts will be very likely).
		/// </summary>
		public async Task<long> GetTransactional(IFdbReadOnlyTransaction trans)
		{
			if (trans == null) throw new ArgumentNullException("trans");

			long total = 0;
			await trans
				.GetRange(this.Subspace.ToRange())
				.ForEachAsync((kvp) => { checked { total += this.Encoder.DecodeValue(kvp.Value); } })
				.ConfigureAwait(false);

			return total;
		}
        public static FdbRangeQuery <KeyValuePair <Slice, Slice> > GetRangeStartsWith(this IFdbReadOnlyTransaction trans, [NotNull] FdbSubspace subspace, FdbRangeOptions options = null)
        {
            Contract.Requires(trans != null && subspace != null);

            return(trans.GetRange(FdbKeyRange.StartsWith(subspace.Key), options));
        }
 public virtual FdbRangeQuery <KeyValuePair <Slice, Slice> > GetRange(KeySelector beginInclusive, KeySelector endInclusive, FdbRangeOptions options = null)
 {
     return(m_transaction.GetRange(beginInclusive, endInclusive, options));
 }
		/// <summary>Returns the list of names and nodes of all children of the specified node</summary>
		private IFdbAsyncEnumerable<KeyValuePair<string, FdbSubspace>> SubdirNamesAndNodes(IFdbReadOnlyTransaction tr, FdbSubspace node)
		{
			Contract.Requires(tr != null && node != null);

			var sd = node.Partition(SUBDIRS);
			return tr
				.GetRange(sd.ToRange())
				.Select(kvp => new KeyValuePair<string, FdbSubspace>(
					sd.UnpackSingle<string>(kvp.Key),
					NodeWithPrefix(kvp.Value)
				));
		}
		/// <summary>
		/// Read from the blob, starting at <paramref name="offset"/>, retrieving up to <paramref name="n"/> bytes (fewer then n bytes are returned when the end of the blob is reached).
		/// </summary>
		public async Task<Slice> ReadAsync(IFdbReadOnlyTransaction trans, long offset, int n)
		{
			if (trans == null) throw new ArgumentNullException("trans");
			if (offset < 0) throw new ArgumentNullException("offset", "Offset cannot be less than zero");

			long? size = await GetSizeAsync(trans).ConfigureAwait(false);
			if (size == null) return Slice.Nil; // not found

			if (offset >= size.Value)
				return Slice.Empty;

			// read all chunks matching the segment we need, and copy them in our buffer
			var buffer = new byte[Math.Min(n, size.Value - offset)];

			await trans
				.GetRange(
					FdbKeySelector.LastLessOrEqual(DataKey(offset)),
					FdbKeySelector.FirstGreaterOrEqual(DataKey(offset + n))
				)
				.ForEachAsync((chunk) =>
				{
					// get offset of this chunk
					long chunkOffset = DataKeyOffset(chunk.Key);
					Slice chunkData = chunk.Value;

					checked
					{
						// intersect chunk bounds with output
						int delta = (int)(chunkOffset - offset);
						int start = delta;
						int end = delta + chunkData.Count;
						if (start < 0) start = 0;
						if (end > n) end = n;

						// compute the relative offsets in the chunk
						int rStart = start - delta;
						int rEnd = end - delta;

						var intersect = chunkData[rStart, rEnd];
						if (intersect.IsPresent)
						{ // copy the data that fits
							intersect.CopyTo(buffer, start);
						}
					}
				})
				.ConfigureAwait(false);

			return new Slice(buffer, 0, buffer.Length);
		}
        private Task <KeyValuePair <Slice, Slice> > GetFirstItemAsync([NotNull] IFdbReadOnlyTransaction tr)
        {
            var range = this.QueueItem.Keys.ToRange();

            return(tr.GetRange(range).FirstOrDefaultAsync());
        }
        private Task <List <KeyValuePair <Slice, Slice> > > GetWaitingPopsAsync([NotNull] IFdbReadOnlyTransaction tr, int numPops)
        {
            var range = this.ConflictedPop.Keys.ToRange();

            return(tr.GetRange(range, limit: numPops, reverse: false).ToListAsync());
        }
		/// <summary>Return the list the names of all fields of an hashset</summary>
		/// <param name="trans">Transaction that will be used for this request</param>
		/// <param name="id">Unique identifier of the hashset</param>
		/// <returns>List of all fields. If the list is empty, the hashset does not exist</returns>
		public Task<List<string>> GetKeys(IFdbReadOnlyTransaction trans, IFdbTuple id, CancellationToken cancellationToken = default(CancellationToken))
		{
			//note: As of Beta2, FDB does not have a fdb_get_range that only return the keys. That means that we will have to also read the values from the db, in order to just get the names of the fields :(
			//TODO: find a way to optimize this ?

			if (trans == null) throw new ArgumentNullException("trans");
			if (id == null) throw new ArgumentNullException("id");

			var prefix = GetKey(id);
			var results = new Dictionary<string, Slice>(StringComparer.OrdinalIgnoreCase);

			return trans
				.GetRange(FdbKeyRange.StartsWith(prefix))
				.Select((kvp) => ParseFieldKey(FdbTuple.Unpack(kvp.Key)))
				.ToListAsync(cancellationToken);
		}
		private async Task<bool> IsPrefixFree(IFdbReadOnlyTransaction tr, Slice prefix)
		{
			Contract.Requires(tr != null);

			// Returns true if the given prefix does not "intersect" any currently
			// allocated prefix (including the root node). This means that it neither
			// contains any other prefix nor is contained by any other prefix.

			if (prefix.IsNullOrEmpty) return false;
			if (await NodeContainingKey(tr, prefix).ConfigureAwait(false) != null) return false;

			return await tr
				.GetRange(
					this.NodeSubspace.Pack(prefix),
					this.NodeSubspace.Pack(FdbKey.Increment(prefix))
				)
				.NoneAsync()
				.ConfigureAwait(false);
		}
		private async Task<FdbSubspace> NodeContainingKey(IFdbReadOnlyTransaction tr, Slice key)
		{
			Contract.Requires(tr != null);

			// Right now this is only used for _is_prefix_free(), but if we add
			// parent pointers to directory nodes, it could also be used to find a
			// path based on a key.

			if (this.NodeSubspace.Contains(key))
				return this.RootNode;

			var kvp = await tr
				.GetRange(
					this.NodeSubspace.ToRange().Begin,
					this.NodeSubspace.Pack(key) + FdbKey.MinValue
				)
				.LastOrDefaultAsync()
				.ConfigureAwait(false);

			if (kvp.Key.HasValue)
			{
				var prevPrefix = this.NodeSubspace.UnpackFirst<Slice>(kvp.Key);
				if (key.StartsWith(prevPrefix))
				{
					return NodeWithPrefix(prevPrefix);
				}
			}

			return null;
		}
		/// <summary>Return all fields of an hashset</summary>
		/// <param name="trans">Transaction that will be used for this request</param>
		/// <param name="id">Unique identifier of the hashset</param>
		/// <returns>Dictionary containing, for all fields, their associated values</returns>
		public async Task<IDictionary<string, Slice>> GetAsync(IFdbReadOnlyTransaction trans, IFdbTuple id)
		{
			if (trans == null) throw new ArgumentNullException("trans");
			if (id == null) throw new ArgumentNullException("id");

			var prefix = GetKey(id);
			var results = new Dictionary<string, Slice>(StringComparer.OrdinalIgnoreCase);

			await trans
				.GetRange(FdbKeyRange.StartsWith(prefix))
				.ForEachAsync((kvp) =>
				{
					string field = this.Subspace.UnpackLast<string>(kvp.Key);
					results[field] = kvp.Value;
				})
				.ConfigureAwait(false);

			return results;
		}