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)); }
/// <summary> /// Simulate a student that is really indecisive /// </summary> public async Task RunProducer(IFdbDatabase db, CancellationToken ct) { int cnt = 0; var rnd = new Random(123456); DateTime last = DateTime.Now; rnd = new Random(); this.TimeLine.Start(); while (!ct.IsCancellationRequested) { int k = cnt++; Slice taskId = FdbTuple.Pack(this.Id.GetHashCode(), k); var ts = Stopwatch.GetTimestamp(); string msg = "Message #" + k + " from producer " + this.Id + " (" + DateTime.UtcNow.ToString("O") + ")"; var latency = Stopwatch.StartNew(); await this.WorkerPool.ScheduleTaskAsync(db, taskId, Slice.FromString(msg), ct).ConfigureAwait(false); latency.Stop(); Console.Write(k.ToString("N0") + "\r"); this.TimeLine.Add(latency.Elapsed.TotalMilliseconds); TimeSpan delay = TimeSpan.FromTicks(rnd.Next((int)this.DelayMin.Ticks, (int)this.DelayMax.Ticks)); await Task.Delay(delay).ConfigureAwait(false); } this.TimeLine.Stop(); ct.ThrowIfCancellationRequested(); }
public void Test_Simple_SelfTerms_Codecs() { // encodes a key using 3 parts: (x, y, z) => ordered_key string x = "abc"; long y = 123; Guid z = Guid.NewGuid(); var first = FdbTupleCodec <string> .Default; var second = FdbTupleCodec <long> .Default; var third = FdbTupleCodec <Guid> .Default; var writer = SliceWriter.Empty; first.EncodeOrderedSelfTerm(ref writer, x); second.EncodeOrderedSelfTerm(ref writer, y); third.EncodeOrderedSelfTerm(ref writer, z); var data = writer.ToSlice(); Assert.That(data, Is.EqualTo(FdbTuple.Pack(x, y, z))); var reader = new SliceReader(data); Assert.That(first.DecodeOrderedSelfTerm(ref reader), Is.EqualTo(x)); Assert.That(second.DecodeOrderedSelfTerm(ref reader), Is.EqualTo(y)); Assert.That(third.DecodeOrderedSelfTerm(ref reader), Is.EqualTo(z)); Assert.That(reader.HasMore, Is.False); }
public async Task Test_Can_MergeSort() { int K = 3; int N = 100; using (var db = await OpenTestPartitionAsync()) { var location = await GetCleanDirectory(db, "Queries", "MergeSort"); // clear! await db.ClearRangeAsync(location, this.Cancellation); // create K lists var lists = Enumerable.Range(0, K).Select(i => location.Partition(i)).ToArray(); // lists[0] contains all multiples of K ([0, 0], [K, 1], [2K, 2], ...) // lists[1] contains all multiples of K, offset by 1 ([1, 0], [K+1, 1], [2K+1, 2], ...) // lists[k-1] contains all multiples of K, offset by k-1 ([K-1, 0], [2K-1, 1], [3K-1, 2], ...) // more generally: lists[k][i] = (..., MergeSort, k, (i * K) + k) = (k, i) for (int k = 0; k < K; k++) { using (var tr = db.BeginTransaction(this.Cancellation)) { for (int i = 0; i < N; i++) { tr.Set(lists[k].Pack((i * K) + k), FdbTuple.Pack(k, i)); } await tr.CommitAsync(); } } // MergeSorting all lists together should produce all integers from 0 to (K*N)-1, in order // we use the last part of the key for sorting using (var tr = db.BeginTransaction(this.Cancellation)) { var merge = tr.MergeSort( lists.Select(list => list.ToSelectorPair()), kvp => location.UnpackLast <int>(kvp.Key) ); Assert.That(merge, Is.Not.Null); Assert.That(merge, Is.InstanceOf <FdbMergeSortIterator <KeyValuePair <Slice, Slice>, int, KeyValuePair <Slice, Slice> > >()); var results = await merge.ToListAsync(); Assert.That(results, Is.Not.Null); Assert.That(results.Count, Is.EqualTo(K * N)); for (int i = 0; i < K * N; i++) { Assert.That(location.Extract(results[i].Key), Is.EqualTo(FdbTuple.Pack(i % K, i))); Assert.That(results[i].Value, Is.EqualTo(FdbTuple.Pack(i % K, i / K))); } } } }
public void Test_Check_Costs() { const int N = 100; var cmp = new CountingComparer <Slice>(Comparer <Slice> .Default); var cola = new ColaOrderedSet <Slice>(cmp); Console.WriteLine(String.Format(CultureInfo.InvariantCulture, "Parameters: N = {0}, Log(N) = {1}, Log2(N) = {2}, N.Log2(N) = {3}", N, Math.Log(N), Math.Log(N, 2), N * Math.Log(N, 2))); Console.WriteLine("Inserting (" + N + " items)"); for (int i = 0; i < N; i++) { cola.Add(FdbTuple.Pack(i << 1)); } Console.WriteLine("> " + cmp.Count + " cmps (" + ((double)cmp.Count / N) + " / insert)"); cola.Debug_Dump(); Console.WriteLine("Full scan (" + (N << 1) + " lookups)"); cmp.Reset(); int n = 0; for (int i = 0; i < (N << 1); i++) { if (cola.Contains(FdbTuple.Pack(i))) { ++n; } } Assert.That(n, Is.EqualTo(N)); Console.WriteLine("> " + cmp.Count + " cmps (" + ((double)cmp.Count / (N << 1)) + " / lookup)"); cmp.Reset(); n = 0; int tail = Math.Min(16, N >> 1); int offset = N - tail; Console.WriteLine("Tail scan (" + tail + " lookups)"); for (int i = 0; i < tail; i++) { if (cola.Contains(FdbTuple.Pack(offset + i))) { ++n; } } Console.WriteLine("> " + cmp.Count + " cmps (" + ((double)cmp.Count / tail) + " / lookup)"); Console.WriteLine("ForEach"); cmp.Reset(); int p = 0; foreach (var x in cola) { Assert.That(FdbTuple.UnpackSingle <int>(x), Is.EqualTo(p << 1)); ++p; } Assert.That(p, Is.EqualTo(N)); Console.WriteLine("> " + cmp.Count + " cmps (" + ((double)cmp.Count / N) + " / item)"); }
public override Slice EncodeComposite(FdbTuple <T1, T2> key, int items) { switch (items) { case 2: return(key.ToSlice()); case 1: return(FdbTuple.Pack <T1>(key.Item1)); default: throw new ArgumentOutOfRangeException("items", items, "Item count must be either 1 or 2"); } }
public void Test_FdbKey_PrettyPrint() { // verify that the pretty printing of keys produce a user friendly output Assert.That(FdbKey.Dump(Slice.Nil), Is.EqualTo("<null>")); Assert.That(FdbKey.Dump(Slice.Empty), Is.EqualTo("<empty>")); Assert.That(FdbKey.Dump(Slice.FromByte(0)), Is.EqualTo("<00>")); Assert.That(FdbKey.Dump(Slice.FromByte(255)), Is.EqualTo("<FF>")); Assert.That(FdbKey.Dump(Slice.Create(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 })), Is.EqualTo("<00><01><02><03><04><05><06><07>")); Assert.That(FdbKey.Dump(Slice.Create(new byte[] { 255, 254, 253, 252, 251, 250, 249, 248 })), Is.EqualTo("<FF><FE><FD><FC><FB><FA><F9><F8>")); Assert.That(FdbKey.Dump(Slice.FromString("hello")), Is.EqualTo("hello")); Assert.That(FdbKey.Dump(Slice.FromString("héllø")), Is.EqualTo("h<C3><A9>ll<C3><B8>")); // tuples should be decoded properly Assert.That(FdbKey.Dump(FdbTuple.Pack(123)), Is.EqualTo("(123,)"), "Singleton tuples should end with a ','"); Assert.That(FdbKey.Dump(FdbTuple.Pack(Slice.FromAscii("hello"))), Is.EqualTo("('hello',)"), "ASCII strings should use single quotes"); Assert.That(FdbKey.Dump(FdbTuple.Pack("héllø")), Is.EqualTo("(\"héllø\",)"), "Unicode strings should use double quotes"); Assert.That(FdbKey.Dump(FdbTuple.Pack(Slice.Create(new byte[] { 1, 2, 3 }))), Is.EqualTo("(<01 02 03>,)")); Assert.That(FdbKey.Dump(FdbTuple.Pack(123, 456)), Is.EqualTo("(123, 456)"), "Elements should be separated with a space, and not end up with ','"); Assert.That(FdbKey.Dump(FdbTuple.Pack(true, false, default(object))), Is.EqualTo("(1, 0, null)"), "Booleans should be displayed as numbers, and null should be in lowercase"); //note: even though it's tempting to using Python's "Nil", it's not very ".NETty" Assert.That(FdbKey.Dump(FdbTuple.Pack(1.0d, Math.PI, Math.E)), Is.EqualTo("(1, 3.1415926535897931, 2.7182818284590451)"), "Doubles should used dot and have full precision (17 digits)"); Assert.That(FdbKey.Dump(FdbTuple.Pack(1.0f, (float)Math.PI, (float)Math.E)), Is.EqualTo("(1, 3.14159274, 2.71828175)"), "Singles should used dot and have full precision (10 digits)"); var guid = Guid.NewGuid(); Assert.That(FdbKey.Dump(FdbTuple.Pack(guid)), Is.EqualTo(String.Format("({0},)", guid.ToString("D"))), "GUIDs should be displayed as a string literal, without quotes"); var uuid128 = Uuid128.NewUuid(); Assert.That(FdbKey.Dump(FdbTuple.Pack(uuid128)), Is.EqualTo(String.Format("({0},)", uuid128.ToString("D"))), "Uuid128s should be displayed as a string literal, without quotes"); var uuid64 = Uuid64.NewUuid(); Assert.That(FdbKey.Dump(FdbTuple.Pack(uuid64)), Is.EqualTo(String.Format("({0},)", uuid64.ToString("D"))), "Uuid64s should be displayed as a string literal, without quotes"); // ranges should be decoded when possible var key = FdbTuple.ToRange(FdbTuple.Create("hello")); // "<02>hello<00><00>" .. "<02>hello<00><FF>" Assert.That(FdbKey.PrettyPrint(key.Begin, FdbKey.PrettyPrintMode.Begin), Is.EqualTo("(\"hello\",).<00>")); Assert.That(FdbKey.PrettyPrint(key.End, FdbKey.PrettyPrintMode.End), Is.EqualTo("(\"hello\",).<FF>")); key = FdbKeyRange.StartsWith(FdbTuple.Pack("hello")); // "<02>hello<00>" .. "<02>hello<01>" Assert.That(FdbKey.PrettyPrint(key.Begin, FdbKey.PrettyPrintMode.Begin), Is.EqualTo("(\"hello\",)")); Assert.That(FdbKey.PrettyPrint(key.End, FdbKey.PrettyPrintMode.End), Is.EqualTo("(\"hello\",) + 1")); var t = FdbTuple.Pack(123); Assert.That(FdbKey.PrettyPrint(t, FdbKey.PrettyPrintMode.Single), Is.EqualTo("(123,)")); Assert.That(FdbKey.PrettyPrint(FdbTuple.ToRange(t).Begin, FdbKey.PrettyPrintMode.Begin), Is.EqualTo("(123,).<00>")); Assert.That(FdbKey.PrettyPrint(FdbTuple.ToRange(t).End, FdbKey.PrettyPrintMode.End), Is.EqualTo("(123,).<FF>")); }
private static async Task HelloWorld(CancellationToken ct) { // Connect to the "DB" database on the local cluster using (var db = await Fdb.OpenAsync()) { // Writes some data in to the database using (var tr = db.BeginTransaction(ct)) { tr.Set(FdbTuple.Pack("Test", 123), Slice.FromString("Hello World!")); tr.Set(FdbTuple.Pack("Test", 456), Slice.FromInt64(DateTime.UtcNow.Ticks)); } } }
public void Test_Simple_String_Codec() { var codec = FdbTupleCodec <string> .Default; Assert.That(codec, Is.Not.Null); Assert.That(codec.EncodeOrdered("héllø Wörld"), Is.EqualTo(FdbTuple.Pack("héllø Wörld"))); Assert.That(codec.EncodeOrdered(String.Empty), Is.EqualTo(FdbTuple.Pack(""))); Assert.That(codec.EncodeOrdered(null), Is.EqualTo(FdbTuple.Pack(default(string)))); Assert.That(codec.DecodeOrdered(FdbTuple.Pack("héllø Wörld")), Is.EqualTo("héllø Wörld")); Assert.That(codec.DecodeOrdered(FdbTuple.Pack(String.Empty)), Is.EqualTo("")); Assert.That(codec.DecodeOrdered(FdbTuple.Pack(default(string))), Is.Null); }
public void Test_Simple_Integer_Codec() { var codec = FdbTupleCodec <int> .Default; Assert.That(codec, Is.Not.Null); Assert.That(codec.EncodeOrdered(0), Is.EqualTo(FdbTuple.Pack(0))); Assert.That(codec.EncodeOrdered(123), Is.EqualTo(FdbTuple.Pack(123))); Assert.That(codec.EncodeOrdered(123456), Is.EqualTo(FdbTuple.Pack(123456))); Assert.That(codec.DecodeOrdered(FdbTuple.Pack(0)), Is.EqualTo(0)); Assert.That(codec.DecodeOrdered(FdbTuple.Pack(123)), Is.EqualTo(123)); Assert.That(codec.DecodeOrdered(FdbTuple.Pack(123456)), Is.EqualTo(123456)); }
public void Test_Tuple_Composite_Encoder() { // encodes a key using 3 parts: (x, y, z) => ordered_key string x = "abc"; long y = 123; Guid z = Guid.NewGuid(); var encoder = KeyValueEncoders.Tuples.CompositeKey <string, long, Guid>(); Assert.That(encoder, Is.Not.Null); // full key encoding // note: EncodeKey(...) is just a shortcurt for packing all items in a tuple, and EncodeComposite(..., count = 3) var data = encoder.EncodeKey(x, y, z); Assert.That(data, Is.EqualTo(FdbTuple.Pack(x, y, z))); var items = encoder.DecodeKey(data); Assert.That(items.Item1, Is.EqualTo(x)); Assert.That(items.Item2, Is.EqualTo(y)); Assert.That(items.Item3, Is.EqualTo(z)); // partial key encoding data = encoder.EncodeComposite(items, 2); Assert.That(data, Is.EqualTo(FdbTuple.Pack(x, y))); items = encoder.DecodeComposite(FdbTuple.Pack(x, y), 2); Assert.That(items.Item1, Is.EqualTo(x)); Assert.That(items.Item2, Is.EqualTo(y)); Assert.That(items.Item3, Is.EqualTo(default(Guid))); data = encoder.EncodeComposite(items, 1); Assert.That(data, Is.EqualTo(FdbTuple.Pack(x))); items = encoder.DecodeComposite(FdbTuple.Pack(x), 1); Assert.That(items.Item1, Is.EqualTo(x)); Assert.That(items.Item2, Is.EqualTo(default(long))); Assert.That(items.Item3, Is.EqualTo(default(Guid))); // should fail if number of items to encode is out of range Assert.That(() => { encoder.EncodeComposite(items, 4); }, Throws.InstanceOf <ArgumentOutOfRangeException>()); Assert.That(() => { encoder.EncodeComposite(items, 0); }, Throws.InstanceOf <ArgumentOutOfRangeException>()); }
public async Task Test_Vector_Fast() { using (var db = await OpenTestPartitionAsync()) { var location = await GetCleanDirectory(db, "ranked_set"); var vector = new FdbRankedSet(location); await db.ReadWriteAsync(async (tr) => { await vector.OpenAsync(tr); await PrintRankedSet(vector, tr); }, this.Cancellation); var rnd = new Random(); for (int i = 0; i < 1000; i++) { await db.ReadWriteAsync((tr) => vector.InsertAsync(tr, FdbTuple.Pack(rnd.Next())), this.Cancellation); } await db.ReadAsync((tr) => PrintRankedSet(vector, tr), this.Cancellation); } }
public async Task Test_Can_Open_Database_With_Non_Empty_GlobalSpace() { // using a tuple prefix using (var db = await Fdb.OpenAsync(null, "DB", new FdbSubspace(FdbTuple.Create("test")), false, this.Cancellation)) { Assert.That(db, Is.Not.Null); Assert.That(db.GlobalSpace, Is.Not.Null); Assert.That(db.GlobalSpace.Key.ToString(), Is.EqualTo("<02>test<00>")); var subspace = db.Partition("hello"); Assert.That(subspace.Key.ToString(), Is.EqualTo("<02>test<00><02>hello<00>")); // keys inside the global space are invlaid Assert.That(db.IsKeyValid(FdbTuple.Pack("test", 123)), Is.True); // keys outside the global space are invlaid Assert.That(db.IsKeyValid(Slice.Create(new byte[] { 42 })), Is.False); } // using a random binary prefix using (var db = await Fdb.OpenAsync(null, "DB", new FdbSubspace(Slice.Create(new byte[] { 42, 255, 0, 90 })), false, this.Cancellation)) { Assert.That(db, Is.Not.Null); Assert.That(db.GlobalSpace, Is.Not.Null); Assert.That(db.GlobalSpace.Key.ToString(), Is.EqualTo("*<FF><00>Z")); var subspace = db.Partition("hello"); Assert.That(subspace.Key.ToString(), Is.EqualTo("*<FF><00>Z<02>hello<00>")); // keys inside the global space are invlaid Assert.That(db.IsKeyValid(Slice.Unescape("*<FF><00>Z123")), Is.True); // keys outside the global space are invlaid Assert.That(db.IsKeyValid(Slice.Create(new byte[] { 123 })), Is.False); Assert.That(db.IsKeyValid(Slice.Unescape("*<FF>")), Is.False); } }
public Slice EncodeValue(T key) { return(FdbTuple.Pack <T>(key)); }
public async Task Test_FdbMap_With_Custom_Key_Encoder() { // Use a table as a backing store for the rules of a Poor Man's firewall, where each keys are the IPEndPoint (tcp only!), and the values are "pass" or "block" // Encode IPEndPoint as the (IP, Port,) encoded with the Tuple codec // note: there is a much simpler way or creating composite keys, this is just a quick and dirty test! var keyEncoder = KeyValueEncoders.Bind <IPEndPoint>( (ipe) => ipe == null ? Slice.Empty : FdbTuple.Pack(ipe.Address, ipe.Port), (packed) => { if (packed.IsNullOrEmpty) { return(default(IPEndPoint)); } var t = FdbTuple.Unpack(packed); return(new IPEndPoint(t.Get <IPAddress>(0), t.Get <int>(1))); } ); var rules = new Dictionary <IPEndPoint, string>() { { new IPEndPoint(IPAddress.Parse("172.16.12.34"), 6667), "block" }, { new IPEndPoint(IPAddress.Parse("192.168.34.56"), 80), "pass" }, { new IPEndPoint(IPAddress.Parse("192.168.34.56"), 443), "pass" } }; using (var db = await OpenTestPartitionAsync()) { var location = await GetCleanDirectory(db, "Collections", "Maps"); var map = new FdbMap <IPEndPoint, string>("Firewall", location.Partition("Hosts"), keyEncoder, KeyValueEncoders.Values.StringEncoder); // import all the rules await db.WriteAsync((tr) => { foreach (var rule in rules) { map.Set(tr, rule.Key, rule.Value); } }, this.Cancellation); #if DEBUG await DumpSubspace(db, location); #endif // test the rules using (var tr = db.BeginTransaction(this.Cancellation)) { var value = await map.GetAsync(tr, new IPEndPoint(IPAddress.Parse("172.16.12.34"), 6667)); Assert.That(value, Is.EqualTo("block")); value = await map.GetAsync(tr, new IPEndPoint(IPAddress.Parse("192.168.34.56"), 443)); Assert.That(value, Is.EqualTo("pass")); var baz = new IPEndPoint(IPAddress.Parse("172.16.12.34"), 80); Assert.That(async() => await map.GetAsync(tr, baz), Throws.InstanceOf <KeyNotFoundException>()); var opt = await map.TryGetAsync(tr, baz); Assert.That(opt.HasValue, Is.False); } } }
public async Task Test_Range_Except() { int K = 3; int N = 100; using (var db = await OpenTestPartitionAsync()) { // get a clean new directory var location = await GetCleanDirectory(db, "Queries", "Except"); // create K lists var lists = Enumerable.Range(0, K).Select(i => location.Partition(i)).ToArray(); // lists[0] contains all multiples of 1 // lists[1] contains all multiples of 2 // lists[k-1] contains all multiples of K // more generally: lists[k][i] = (..., Intersect, k, i * (k + 1)) = (k, i) var series = Enumerable.Range(1, K).Select(k => Enumerable.Range(1, N).Select(x => k * x).ToArray()).ToArray(); //foreach(var serie in series) //{ // Console.WriteLine(String.Join(", ", serie)); //} for (int k = 0; k < K; k++) { //Console.WriteLine("> k = " + k); using (var tr = db.BeginTransaction(this.Cancellation)) { for (int i = 0; i < N; i++) { var key = lists[k].Pack(series[k][i]); var value = FdbTuple.Pack(k, i); //Console.WriteLine("> " + key + " = " + value); tr.Set(key, value); } await tr.CommitAsync(); } } // Intersect all lists together should produce all integers that are prime numbers IEnumerable <int> xs = series[0]; for (int i = 1; i < K; i++) { xs = xs.Except(series[i]); } var expected = xs.ToArray(); Console.WriteLine(String.Join(", ", expected)); using (var tr = db.BeginTransaction(this.Cancellation)) { var merge = tr.Except( lists.Select(list => list.ToSelectorPair()), kvp => location.UnpackLast <int>(kvp.Key) ); Assert.That(merge, Is.Not.Null); Assert.That(merge, Is.InstanceOf <FdbExceptIterator <KeyValuePair <Slice, Slice>, int, KeyValuePair <Slice, Slice> > >()); var results = await merge.ToListAsync(); Assert.That(results, Is.Not.Null); Assert.That(results.Count, Is.EqualTo(expected.Length)); for (int i = 0; i < results.Count; i++) { Assert.That(location.UnpackLast <int>(results[i].Key), Is.EqualTo(expected[i])); } } } }