public static IApplicationBuilder UseFoundationDb(this IApplicationBuilder builder, Action <IFdbDatabaseProvider> setup) { var provider = builder.ApplicationServices.GetRequiredService <IFdbDatabaseProvider>(); var lifetime = builder.ApplicationServices.GetRequiredService <IApplicationLifetime>(); var cts = new CancellationTokenSource(); lifetime.ApplicationStarted.Register(() => { var options = builder.ApplicationServices.GetRequiredService <IOptions <FdbDatabaseProviderOptions> >().Value; //Console.WriteLine("Initializing FDB client..."); Fdb.Start(options.ApiVersion); //Console.WriteLine("Start FDB connection..."); provider.Start(cts.Token); }); lifetime.ApplicationStopping.Register(() => { cts.Cancel(); provider.Stop(); }); lifetime.ApplicationStopped.Register(() => { cts.Dispose(); //Console.WriteLine("Stopping FDB database..."); provider.Dispose(); //Console.WriteLine("Stopping FDB client..."); Fdb.Stop(); }); return(builder); }
public async Task Test_Can_Open_Database() { //README: if your default cluster is remote, you need to be connected to the netword, or it will fail. // the hard way using (var cluster = await Fdb.CreateClusterAsync(null, this.Cancellation)) { Assert.That(cluster, Is.Not.Null); Assert.That(cluster.Path, Is.Null); using (var db = await cluster.OpenDatabaseAsync("DB", KeySubspace.Empty, false, this.Cancellation)) { Assert.That(db, Is.Not.Null, "Should return a valid object"); Assert.That(db.Name, Is.EqualTo("DB"), "FdbDatabase.Name should match"); Assert.That(db.Cluster, Is.SameAs(cluster), "FdbDatabase.Cluster should point to the parent cluster"); } } // the easy way using (var db = await Fdb.OpenAsync()) { Assert.That(db, Is.Not.Null); Assert.That(db.Name, Is.EqualTo("DB")); Assert.That(db.Cluster, Is.Not.Null); Assert.That(db.Cluster.Path, Is.Null); } }
public static void Main(string[] args) { //TODO: move this to the main, and add a command line argument to on/off ? try { if (Console.LargestWindowWidth > 0 && Console.LargestWindowHeight > 0) { Console.WindowWidth = 160; Console.WindowHeight = 60; } } catch { // this sometimes fail on small screen sizes } // Initialize FDB try { Fdb.Start(Fdb.GetMaxSafeApiVersion(200, Fdb.GetDefaultApiVersion())); using (var go = new CancellationTokenSource()) { MainAsync(args, go.Token).GetAwaiter().GetResult(); } } finally { Fdb.Stop(); StdOut("Bye"); } }
public void RunAfterAnyTests() { using (_source) using (_database) { } Fdb.Stop(); }
public async Task Test_FdbDatabase_Key_Validation() { using (var db = await Fdb.OpenAsync()) { // IsKeyValid Assert.That(db.IsKeyValid(Slice.Nil), Is.False, "Null key is invalid"); Assert.That(db.IsKeyValid(Slice.Empty), Is.True, "Empty key is allowed"); Assert.That(db.IsKeyValid(Slice.FromString("hello")), Is.True); Assert.That(db.IsKeyValid(Slice.Create(Fdb.MaxKeySize + 1)), Is.False, "Key is too large"); Assert.That(db.IsKeyValid(Fdb.System.Coordinators), Is.True, "System keys are valid"); // EnsureKeyIsValid Assert.That(() => db.EnsureKeyIsValid(Slice.Nil), Throws.InstanceOf <ArgumentException>()); Assert.That(() => db.EnsureKeyIsValid(Slice.Empty), Throws.Nothing); Assert.That(() => db.EnsureKeyIsValid(Slice.FromString("hello")), Throws.Nothing); Assert.That(() => db.EnsureKeyIsValid(Slice.Create(Fdb.MaxKeySize + 1)), Throws.InstanceOf <ArgumentException>()); Assert.That(() => db.EnsureKeyIsValid(Fdb.System.Coordinators), Throws.Nothing); // EnsureKeyIsValid ref Assert.That(() => { Slice key = Slice.Nil; db.EnsureKeyIsValid(ref key); }, Throws.InstanceOf <ArgumentException>()); Assert.That(() => { Slice key = Slice.Empty; db.EnsureKeyIsValid(ref key); }, Throws.Nothing); Assert.That(() => { Slice key = Slice.FromString("hello"); db.EnsureKeyIsValid(ref key); }, Throws.Nothing); Assert.That(() => { Slice key = Slice.Create(Fdb.MaxKeySize + 1); db.EnsureKeyIsValid(ref key); }, Throws.InstanceOf <ArgumentException>()); Assert.That(() => { Slice key = Fdb.System.Coordinators; db.EnsureKeyIsValid(ref key); }, Throws.Nothing); } }
static void TestRandomAllocFree() { var pool = stackalloc Pool[1]; Init(pool); const int len = 200; var ptrs = new System.Collections.Generic.List <long>(); for (int i = 0; i < len; i += 1) { int size = Fdb.Random(1, 1000); ptrs.Add((long)Pool.Alloc(pool, size)); if (pool->shift != 0) { long shift = pool->shift; for (int j = 0; j < ptrs.Count - 1; j += 1) { ptrs[j] += shift; } pool->shift = 0; } if (Fdb.Random(0, 2) == 0) // 1/3 chance to free { int idx = Fdb.Random(0, ptrs.Count - 1); Pool.Free(pool, (void *)ptrs[idx]); ptrs.RemoveAt(idx); } } for (int i = 0; i < ptrs.Count; i += 1) { Pool.Free(pool, (void *)ptrs[i]); } // the first *real* free node should be 0x54 long (containing all space) Should.Equal("*(int *)(pool->arr + 0x28)", *(int *)(pool->arr + 0x18), pool->len - 11 * 4); }
public async Task Test_Open_Or_CreateCluster_With_Corrupted_ClusterFile_Should_Fail() { // Using a corrupted cluster file should fail with "ConnectionStringInvalid" // write some random bytes into a cluster file string path = System.IO.Path.GetTempFileName(); try { var rnd = new Random(); var bytes = new byte[128]; rnd.NextBytes(bytes); System.IO.File.WriteAllBytes(path, bytes); await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.CreateClusterAsync(path, this.Cancellation), FdbError.ConnectionStringInvalid, "Should fail if file is corrupted"); await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.OpenAsync(new FdbConnectionOptions { ClusterFile = path }, this.Cancellation), FdbError.ConnectionStringInvalid, "Should fail if file is corrupted"); } finally { System.IO.File.Delete(path); } }
public FdbFixture() { const int fallbackFdbApiVersion = 520; var apiVersion = Environment.GetEnvironmentVariable("FdbApiVersion"); var serverVersion = Environment.GetEnvironmentVariable("FdbServerVersion"); if (apiVersion == null || !int.TryParse(apiVersion, out int fdbApiVersion)) { fdbApiVersion = fallbackFdbApiVersion; } var availableVersions = Enum.GetNames(typeof(FdbServerVersion)); if (serverVersion != null && availableVersions.Contains(serverVersion)) { _serverVersion = (FdbServerVersion)Enum.Parse(typeof(FdbServerVersion), serverVersion); } else { _serverVersion = FdbServerVersion.v6_0_15; } EnsureApiVersionAndServerVersionCompatible(fdbApiVersion, _serverVersion); Fdb = Fdb.Instance; Fdb.SelectApiVersion(fdbApiVersion); }
public async Task Test_Open_Or_CreateCluster_With_Invalid_ClusterFile_Path_Should_Fail() { // Missing/Invalid cluster files should fail with "NoClusterFileFound" // file not found await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.CreateClusterAsync(@".\file_not_found.cluster", this.Cancellation), FdbError.NoClusterFileFound, "Should fail if cluster file is missing"); await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.OpenAsync(new FdbConnectionOptions { ClusterFile = @".\file_not_found.cluster" }, this.Cancellation), FdbError.NoClusterFileFound, "Should fail if cluster file is missing"); // unreachable path await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.CreateClusterAsync(@"C:\..\..\fdb.cluster", this.Cancellation), FdbError.NoClusterFileFound, "Should fail if path is malformed"); await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.OpenAsync(new FdbConnectionOptions { ClusterFile = @"C:\..\..\fdb.cluster" }, this.Cancellation), FdbError.NoClusterFileFound, "Should fail if path is malformed"); // malformed path await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.CreateClusterAsync(@"FOO:\invalid$path!/fdb.cluster", this.Cancellation), FdbError.NoClusterFileFound, "Should fail if path is malformed"); await TestHelpers.AssertThrowsFdbErrorAsync(() => Fdb.OpenAsync(new FdbConnectionOptions { ClusterFile = @"FOO:\invalid$path!/fdb.cluster" }, this.Cancellation), FdbError.NoClusterFileFound, "Should fail if path is malformed"); }
static void TestPushRemovePush() { const int len = 1000; var arr = new System.Collections.Generic.List <int>(); var lst = stackalloc PtrLst[1]; Init(lst); for (int i = 0; i < len; i += 1) { int v = Fdb.Random(0, len); arr.Add(v); Push(lst, (void *)v); } for (int i = 0; i < len >> 1; i += 1) { int idx = Fdb.Random(0, arr.Count); arr.RemoveAt(idx); RemoveAt(lst, idx); } for (int i = 0; i < len; i += 1) { int v = Fdb.Random(0, len); arr.Add(v); Push(lst, (void *)v); } void **ptr = lst->arr; for (int i = 0; i < arr.Count; i += 1) { Should.Equal("(int)ptr[i]", (int)ptr[i], arr[i]); } }
public static void Remove(PtrLst *self, void *ptr) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); int oldCount = self->count; #endif void **arr = self->arr; int i = 0, len = self->count; while (i < len && arr[i] != ptr) { i += 1; } if (i < len) // arr[i] == p // for (len = self->count -= 1; i < len; i += 1) arr[i] = arr[i + 1]; { byte *src = (byte *)(arr + i); int size = self->size; int count = self->count -= 1; Mem.Memmove(src, src + size, (count - i) * size); } #if FDB else { Fdb.Error("{0:X} does not exist in PtrLst {1:X}", (ulong)ptr, (ulong)self); } Should.Equal("self->count", self->count, oldCount - 1); #endif }
public static void Main(string[] args) { //TODO: move this to the main, and add a command line argument to on/off ? if (Console.LargestWindowWidth > 0 && Console.LargestWindowHeight > 0) { Console.WindowWidth = 160; Console.WindowHeight = 60; } // Initialize FDB //note: always use the latest version available Fdb.UseApiVersion(Fdb.GetMaxSafeApiVersion()); try { Fdb.Start(); using (var go = new CancellationTokenSource()) { MainAsync(args, go.Token).GetAwaiter().GetResult(); } } finally { Fdb.Stop(); Console.WriteLine("Bye"); } }
private static Task <IFdbDatabase> ChangeDatabase(FdbConnectionOptions options, CancellationToken ct) { options.DefaultTimeout = TimeSpan.FromSeconds(30); options.DefaultRetryLimit = 50; Program.StdOut("Connecting to cluster...", ConsoleColor.Gray); return(Fdb.OpenAsync(options, ct)); }
public Task <IFdbDatabaseHandler> OpenDatabaseAsync(string databaseName, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <IFdbDatabaseHandler>(cancellationToken)); } var future = FdbNative.ClusterCreateDatabase(m_handle, databaseName); return(FdbFuture.CreateTaskFromHandle( future, (h) => { DatabaseHandle database; var err = FdbNative.FutureGetDatabase(h, out database); if (err != FdbError.Success) { database.Dispose(); throw Fdb.MapToException(err); } var handler = new FdbNativeDatabase(database); return (IFdbDatabaseHandler)handler; }, cancellationToken )); }
public async Task Test_Check_Timeout_On_Non_Existing_Database() { string clusterPath = Path.Combine(TestContext.CurrentContext.WorkDirectory, "notfound.cluster"); File.WriteAllText(clusterPath, "local:[email protected]:4566"); var options = new FdbConnectionOptions { ClusterFile = clusterPath }; using (var db = await Fdb.OpenAsync(options, this.Cancellation)) { bool exists = false; var err = FdbError.Success; try { using (var tr = await db.BeginReadOnlyTransactionAsync(this.Cancellation)) { tr.Timeout = 250; // ms Log("check ..."); await tr.GetAsync(Slice.FromString("key_not_found")); Log("Uhoh ...?"); exists = true; } } catch (FdbException e) { err = e.Code; } Assert.That(exists, Is.False); Assert.That(err, Is.EqualTo(FdbError.TransactionTimedOut)); } }
static void TestRandomExpand() { var pool = stackalloc Pool[1]; Init(pool); const int len = 200; var ptrs = stackalloc byte *[len]; for (int i = 0; i < len; i += 1) { int size = Fdb.Random(1, 1000); ptrs[i] = (byte *)Pool.Alloc(pool, size); if (pool->shift != 0) { long shift = pool->shift; for (int j = 0; j < i; j += 1) { ptrs[j] += shift; } pool->shift = 0; } } for (int i = 0; i < len; i += 1) { Pool.Free(pool, ptrs[i]); } // the first *real* free node should be 0x54 long (containing all space) Should.Equal("*(int *)(pool->arr + 0x28)", *(int *)(pool->arr + 0x18), pool->len - 11 * 4); }
public async Task Test_Compare_Implementations() { for (int mode = 1; mode <= 6; mode++) { Console.WriteLine("#### SCENARIO " + mode + " ####"); using (var db = await Fdb.OpenAsync(this.Cancellation)) { using (var tr = db.BeginTransaction(this.Cancellation)) { await tr.GetReadVersionAsync(); switch (mode) { case 1: await Scenario1(tr); break; case 2: await Scenario2(tr); break; case 3: await Scenario3(tr); break; case 4: await Scenario4(tr); break; case 5: await Scenario5(tr); break; case 6: await Scenario6(tr); break; } await tr.CommitAsync(); } } using (var db = MemoryDatabase.CreateNew("DB")) { using (var tr = db.BeginTransaction(FdbTransactionMode.Default, this.Cancellation)) { await tr.GetReadVersionAsync(); switch (mode) { case 1: await Scenario1(tr); break; case 2: await Scenario2(tr); break; case 3: await Scenario3(tr); break; case 4: await Scenario4(tr); break; case 5: await Scenario5(tr); break; case 6: await Scenario6(tr); break; } await tr.CommitAsync(); } db.Debug_Dump(); } } }
public async Task Test_Can_Connect_To_Local_Cluster() { using (var cluster = await Fdb.CreateClusterAsync(this.Cancellation)) { Assert.That(cluster, Is.Not.Null, "Should return a valid object"); Assert.That(cluster.Path, Is.Null, "FdbCluster.Path should be null"); } }
public void Test_Open_Database_With_Cancelled_Token_Should_Fail() { using (var cts = new CancellationTokenSource()) { cts.Cancel(); Assert.That(async() => await Fdb.OpenAsync(cts.Token), Throws.InstanceOf <OperationCanceledException>()); } }
public static async Task <IFdbDatabase> OpenDefaultAsync(this Fdb fdb) { using (var cluster = await fdb.OpenDefaultClusterAsync().ConfigureAwait(false)) { var database = await cluster.OpenDefaultDatabaseAsync().ConfigureAwait(false); return(database); } }
/// <summary>Extract a chunk of result from a completed Future</summary> /// <param name="h">Handle to the completed Future</param> /// <param name="more">Receives true if there are more result, or false if all results have been transmitted</param> /// <param name="first">Receives the first key in the page, or default if page is empty</param> /// <param name="last">Receives the last key in the page, or default if page is empty</param> /// <returns>Array of key/value pairs, or an exception</returns> private static KeyValuePair <Slice, Slice>[] GetKeyValueArrayResultValuesOnly(FutureHandle h, out bool more, out Slice first, out Slice last) { var err = FdbNative.FutureGetKeyValueArrayValuesOnly(h, out var result, out more, out first, out last); Fdb.DieOnError(err); //note: result can only be null if an error occured! Contract.Ensures(result != null); return(result); }
public void Test_Connecting_To_Cluster_With_Cancelled_Token_Should_Fail() { using (var cts = new CancellationTokenSource()) { cts.Cancel(); Assert.Throws <OperationCanceledException>(() => Fdb.CreateClusterAsync(cts.Token).GetAwaiter().GetResult()); } }
public void Test_Fdb_GetErrorMessage() { Assert.That(Fdb.GetErrorMessage(FdbError.Success), Is.EqualTo("success")); Assert.That(Fdb.GetErrorMessage(FdbError.OperationFailed), Is.EqualTo("operation_failed")); Assert.That(Fdb.GetErrorMessage(FdbError.TimedOut), Is.EqualTo("timed_out")); Assert.That(Fdb.GetErrorMessage(FdbError.PastVersion), Is.EqualTo("past_version")); }
public long GetCommittedVersion() { var err = FdbNative.TransactionGetCommittedVersion(m_handle, out long version); #if DEBUG_TRANSACTIONS Debug.WriteLine("FdbTransaction[" + m_id + "].GetCommittedVersion() => err=" + err + ", version=" + version); #endif Fdb.DieOnError(err); return(version); }
public void Test_Fdb_MapToException() { Assert.That(Fdb.MapToException(FdbError.Success), Is.Null); Assert.That(Fdb.MapToException(FdbError.OperationFailed), Is.InstanceOf <FdbException>().And.Property("Code").EqualTo(FdbError.OperationFailed)); Assert.That(Fdb.MapToException(FdbError.TimedOut), Is.InstanceOf <TimeoutException>()); Assert.That(Fdb.MapToException(FdbError.LargeAllocFailed), Is.InstanceOf <OutOfMemoryException>()); }
private static KeyValuePair <Slice, Slice>[] GetKeyValueArrayResult(FutureHandle h, out bool more) { KeyValuePair <Slice, Slice>[] result; var err = FdbNative.FutureGetKeyValueArray(h, out result, out more); Fdb.DieOnError(err); //note: result can only be null if an error occured! Contract.Ensures(result != null); return(result); }
public async Task Test_Can_Open_Local_Database() { //README: if your test database is remote, and you don't have FDB running locally, this test will fail and you should ignore this one. using (var db = await Fdb.OpenAsync(this.Cancellation)) { Assert.That(db, Is.Not.Null, "Should return a valid database"); Assert.That(db.ClusterFile, Is.Null, "Cluster path should be null (default)"); } }
/// <summary>Extract a chunk of result from a completed Future</summary> /// <param name="h">Handle to the completed Future</param> /// <param name="more">Receives true if there are more result, or false if all results have been transmitted</param> /// <param name="first">Receives the first key in the page, or default if page is empty</param> /// <param name="last">Receives the last key in the page, or default if page is empty</param> /// <returns>Array of key/value pairs, or an exception</returns> private static KeyValuePair <Slice, Slice>[] GetKeyValueArrayResultKeysOnly(FutureHandle h, out bool more, out Slice first, out Slice last) { var err = FdbNative.FutureGetKeyValueArrayKeysOnly(h, out var result, out more); Fdb.DieOnError(err); //note: result can only be null if an error occured! Contract.Ensures(result != null); first = result.Length > 0 ? result[0].Key : default; last = result.Length > 0 ? result[result.Length - 1].Key : default; return(result); }
private static Task <IFdbDatabase> ChangeDatabase(string clusterFile, string dbName, string[] partition, CancellationToken ct) { if (partition == null || partition.Length == 0) { return(Fdb.OpenAsync(clusterFile, dbName, ct)); } else { return(Fdb.Directory.OpenNamedPartitionAsync(clusterFile, dbName, partition, false, ct)); } }
/// <summary>Connect to the local test partition</summary> public static Task <IFdbDatabase> OpenTestPartitionAsync(CancellationToken ct) { var options = new FdbConnectionOptions { ClusterFile = TestClusterFile, Root = FdbPath.Absolute(FdbPathSegment.Partition("Tests"), FdbPathSegment.Create("Fdb"), FdbPathSegment.Partition(Environment.MachineName)), DefaultTimeout = TimeSpan.FromMilliseconds(DefaultTimeout), }; return(Fdb.OpenAsync(options, ct)); }