Example #1
0
        public void Test_FdbKeyRange_Contains()
        {
            FdbKeyRange range;

            // ["", "")
            range = FdbKeyRange.Empty;
            Assert.That(range.Contains(Slice.Empty), Is.False);
            Assert.That(range.Contains(Slice.FromAscii("\x00")), Is.False);
            Assert.That(range.Contains(Slice.FromAscii("hello")), Is.False);
            Assert.That(range.Contains(Slice.FromAscii("\xFF")), Is.False);

            // ["", "\xFF" )
            range = FdbKeyRange.Create(Slice.Empty, Slice.FromAscii("\xFF"));
            Assert.That(range.Contains(Slice.Empty), Is.True);
            Assert.That(range.Contains(Slice.FromAscii("\x00")), Is.True);
            Assert.That(range.Contains(Slice.FromAscii("hello")), Is.True);
            Assert.That(range.Contains(Slice.FromAscii("\xFF")), Is.False);

            // ["\x00", "\xFF" )
            range = FdbKeyRange.Create(Slice.FromAscii("\x00"), Slice.FromAscii("\xFF"));
            Assert.That(range.Contains(Slice.Empty), Is.False);
            Assert.That(range.Contains(Slice.FromAscii("\x00")), Is.True);
            Assert.That(range.Contains(Slice.FromAscii("hello")), Is.True);
            Assert.That(range.Contains(Slice.FromAscii("\xFF")), Is.False);

            // corner cases
            Assert.That(FdbKeyRange.Create(Slice.FromAscii("A"), Slice.FromAscii("A")).Contains(Slice.FromAscii("A")), Is.False, "Equal bounds");
        }
Example #2
0
        public void Test_FdbKeyRange_Test()
        {
            const int BEFORE = -1, INSIDE = 0, AFTER = +1;

            FdbKeyRange range;

            // range: [ "A", "Z" )
            range = FdbKeyRange.Create(Slice.FromAscii("A"), Slice.FromAscii("Z"));

            // Excluding the end: < "Z"
            Assert.That(range.Test(Slice.FromAscii("\x00"), endIncluded: false), Is.EqualTo(BEFORE));
            Assert.That(range.Test(Slice.FromAscii("@"), endIncluded: false), Is.EqualTo(BEFORE));
            Assert.That(range.Test(Slice.FromAscii("A"), endIncluded: false), Is.EqualTo(INSIDE));
            Assert.That(range.Test(Slice.FromAscii("Z"), endIncluded: false), Is.EqualTo(AFTER));
            Assert.That(range.Test(Slice.FromAscii("Z\x00"), endIncluded: false), Is.EqualTo(AFTER));
            Assert.That(range.Test(Slice.FromAscii("\xFF"), endIncluded: false), Is.EqualTo(AFTER));

            // Including the end: <= "Z"
            Assert.That(range.Test(Slice.FromAscii("\x00"), endIncluded: true), Is.EqualTo(BEFORE));
            Assert.That(range.Test(Slice.FromAscii("@"), endIncluded: true), Is.EqualTo(BEFORE));
            Assert.That(range.Test(Slice.FromAscii("A"), endIncluded: true), Is.EqualTo(INSIDE));
            Assert.That(range.Test(Slice.FromAscii("Z"), endIncluded: true), Is.EqualTo(INSIDE));
            Assert.That(range.Test(Slice.FromAscii("Z\x00"), endIncluded: true), Is.EqualTo(AFTER));
            Assert.That(range.Test(Slice.FromAscii("\xFF"), endIncluded: true), Is.EqualTo(AFTER));

            range = FdbKeyRange.Create(FdbTuple.Pack("A"), FdbTuple.Pack("Z"));
            Assert.That(range.Test(FdbTuple.Create("@")), Is.EqualTo((BEFORE)));
            Assert.That(range.Test(FdbTuple.Create("A")), Is.EqualTo((INSIDE)));
            Assert.That(range.Test(FdbTuple.Create("Z")), Is.EqualTo((AFTER)));
            Assert.That(range.Test(FdbTuple.Create("Z"), endIncluded: true), Is.EqualTo(INSIDE));
        }
Example #3
0
        public void Test_FdbKeyRange_Disjoint()
        {
            Func <byte, byte, FdbKeyRange> range = (x, y) => FdbKeyRange.Create(Slice.FromByte(x), Slice.FromByte(y));

            #region Disjoint...

            // [0, 1) [2, 3)
            // #X
            //   #X
            Assert.That(range(0, 1).Disjoint(range(2, 3)), Is.True);
            // [2, 3) [0, 1)
            //   #X
            // #X
            Assert.That(range(2, 3).Disjoint(range(0, 1)), Is.True);

            #endregion

            #region Not Disjoint...

            // [0, 1) [1, 2)
            // #X
            //  #X
            Assert.That(range(0, 1).Disjoint(range(1, 2)), Is.False);
            // [1, 2) [0, 1)
            //  #X
            // #X
            Assert.That(range(1, 2).Disjoint(range(0, 1)), Is.False);

            // [0, 2) [1, 3)
            // ##X
            //  ##X
            Assert.That(range(0, 2).Disjoint(range(1, 3)), Is.False);
            // [1, 3) [0, 2)
            //  ##X
            // ##X
            Assert.That(range(1, 3).Disjoint(range(0, 2)), Is.False);

            // [0, 1) [0, 2)
            // #X
            // ##X
            Assert.That(range(0, 1).Disjoint(range(0, 2)), Is.False);
            // [0, 2) [0, 1)
            // ##X
            // #X
            Assert.That(range(0, 2).Disjoint(range(0, 1)), Is.False);

            // [0, 2) [1, 2)
            // ##X
            //  #X
            Assert.That(range(0, 2).Disjoint(range(1, 2)), Is.False);
            // [1, 2) [0, 2)
            //  #X
            // ##X
            Assert.That(range(1, 2).Disjoint(range(0, 2)), Is.False);

            #endregion
        }
Example #4
0
        public async Task <Slice> GetKeyAsync(FdbKeySelector selector, bool snapshot, CancellationToken cancellationToken)
        {
            Contract.Requires(selector.Key.HasValue);
            cancellationToken.ThrowIfCancellationRequested();

            CheckAccessToSystemKeys(selector.Key, end: true);

            //Trace.WriteLine("## GetKey " + selector + ", snapshot=" + snapshot);

            FdbKeyRange keyRange;

            lock (m_buffer)
            {
                keyRange = m_buffer.InternRangeFromKey(selector.Key);
                selector = new FdbKeySelector(keyRange.Begin, selector.OrEqual, selector.Offset);
            }

            // we need the read version
            EnsureHasReadVersion();

            var results = await m_db.GetKeysAtVersion(new [] { selector }, m_readVersion.Value).ConfigureAwait(false);

            Contract.Assert(results != null && results.Length == 1);
            var result = results[0];

            FdbKeyRange resultRange;
            int         c = result.CompareTo(selector.Key);

            if (c == 0)
            {             // the result is identical to the key
                resultRange = keyRange;
                result      = keyRange.Begin;
            }
            else
            {             // intern the result
                lock (m_buffer)
                {
                    resultRange = m_buffer.InternRangeFromKey(result);
                    result      = resultRange.Begin;
                }
            }

            //TODO: how to merge the results with the local state mutations ?
            // => add values that were inserted
            // => remove values that were cleared
            // => change the value of keys that were mutated locally

            if (!snapshot)
            {
                lock (m_lock)
                {
                    //TODO: use the result to create the conflict range (between the resolver key and the returned key)
                    if (c == 0)
                    {                     // the key itself was selected, so it can only conflict if it gets deleted by another transaction
                        // [ result, result+\0 )
                        AddReadConflict_NeedsLocking(resultRange);
                    }
                    else if (c < 0)
                    {                     // the result is before the selected key, so any change between them (including deletion of the result) will conflict
                        // orEqual == true  => [ result, key + \0 )
                        // orEqual == false => [ result, key )
                        AddReadConflict_NeedsLocking(FdbKeyRange.Create(resultRange.Begin, selector.OrEqual ? keyRange.End : keyRange.Begin));
                    }
                    else
                    {                     // the result is after the selected key, so any change between it and the result will conflict
                        // orEqual == true  => [ key + \0, result + \0 )
                        // orEqual == false => [ key , result + \0 )
                        AddReadConflict_NeedsLocking(FdbKeyRange.Create(selector.OrEqual ? keyRange.End : keyRange.Begin, resultRange.End));
                    }
                }
            }

            return(result);
        }