private static async Task <List <Slice> > GetBoundaryKeysInternalAsync([NotNull] IFdbReadOnlyTransaction trans, Slice begin, Slice end) { Contract.Requires(trans != null && end >= begin); #if TRACE_COUNTING trans.Annotate("Get boundary keys in range {0}", KeyRange.Create(begin, end)); #endif trans.WithReadAccessToSystemKeys(); var results = new List <Slice>(); int iterations = 0; var options = new FdbRangeOptions { Mode = FdbStreamingMode.WantAll }; while (begin < end) { FdbException error = null; Slice lastBegin = begin; try { var chunk = await trans.Snapshot.GetRangeAsync(KeyServers + begin, KeyServers + end, options, iterations).ConfigureAwait(false); ++iterations; if (chunk.Count > 0) { foreach (var kvp in chunk) { results.Add(kvp.Key.Substring(KeyServers.Count)); } begin = chunk.Last.Substring(KeyServers.Count) + 0; } if (!chunk.HasMore) { begin = end; } } catch (FdbException e) { error = e; } if (error != null) { if (error.Code == FdbError.PastVersion && begin != lastBegin) { // if we get a PastVersion and *something* has happened, then we are no longer transactional trans.Reset(); } else { await trans.OnErrorAsync(error.Code).ConfigureAwait(false); } iterations = 0; trans.WithReadAccessToSystemKeys(); } } #if TRACE_COUNTING if (results.Count == 0) { trans.Annotate("There is no chunk boundary in range {0}", KeyRange.Create(begin, end)); } else { trans.Annotate("Found {0} boundaries in {1} iteration(s)", results.Count, iterations); } #endif return(results); }