From 857389b5a556972676dcaa62a57a59fad2fefe98 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 03:58:33 +0100 Subject: [PATCH 01/42] initial garnet generic host setup --- Directory.Packages.props | 1 + libs/host/Garnet.host.csproj | 2 + libs/host/GarnetApplicationBuilder.cs | 70 +++++++++++ libs/host/GarnetApplicationOptions.cs | 22 ++++ libs/host/GarnetApplicatrion.cs | 81 ++++++++++++ main/GarnetServer/Program.cs | 173 +++++++++++++------------- test/Garnet.test/RespSetTest.cs | 2 +- 7 files changed, 261 insertions(+), 90 deletions(-) create mode 100644 libs/host/GarnetApplicationBuilder.cs create mode 100644 libs/host/GarnetApplicationOptions.cs create mode 100644 libs/host/GarnetApplicatrion.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 0719a40ed8..60462d5b1b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -9,6 +9,7 @@ + diff --git a/libs/host/Garnet.host.csproj b/libs/host/Garnet.host.csproj index 1c1259fec3..afeca6f519 100644 --- a/libs/host/Garnet.host.csproj +++ b/libs/host/Garnet.host.csproj @@ -20,6 +20,8 @@ + + diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs new file mode 100644 index 0000000000..7b8ef56fc9 --- /dev/null +++ b/libs/host/GarnetApplicationBuilder.cs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using Garnet.server; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.Metrics; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Garnet; + +public class GarnetApplicationBuilder : IHostApplicationBuilder +{ + readonly HostApplicationBuilder hostApplicationBuilder; + + internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + { + var configuration = new ConfigurationManager(); + + configuration.AddEnvironmentVariables(prefix: "GARNET_"); + + hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings + { + Args = options.Args, + ApplicationName = options.ApplicationName, + EnvironmentName = options.EnvironmentName, + Configuration = configuration + }); + + hostApplicationBuilder.Logging.ClearProviders(); + hostApplicationBuilder.Logging.AddSimpleConsole(simpleConsoleFormatterOptions => + { + simpleConsoleFormatterOptions.SingleLine = true; + simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; + }); + } + + public GarnetApplication Build() + { + var host = hostApplicationBuilder.Build(); + return new GarnetApplication(host); + } + + public void ConfigureContainer(IServiceProviderFactory factory, + Action configure = null) + where TContainerBuilder : notnull + { + hostApplicationBuilder.ConfigureContainer(factory, configure); + } + + public IDictionary Properties { get; } + + public IConfigurationManager Configuration + => hostApplicationBuilder.Configuration; + + public IHostEnvironment Environment + => hostApplicationBuilder.Environment; + + public ILoggingBuilder Logging + => hostApplicationBuilder.Logging; + + public IMetricsBuilder Metrics + => hostApplicationBuilder.Metrics; + + public IServiceCollection Services + => hostApplicationBuilder.Services; +} \ No newline at end of file diff --git a/libs/host/GarnetApplicationOptions.cs b/libs/host/GarnetApplicationOptions.cs new file mode 100644 index 0000000000..a7a6edfea7 --- /dev/null +++ b/libs/host/GarnetApplicationOptions.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Garnet; + +public class GarnetApplicationOptions +{ + /// + /// The command line arguments. + /// + public string[] Args { get; init; } + + /// + /// The environment name. + /// + public string EnvironmentName { get; init; } + + /// + /// The application name. + /// + public string ApplicationName { get; init; } +} \ No newline at end of file diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs new file mode 100644 index 0000000000..7c9679f18b --- /dev/null +++ b/libs/host/GarnetApplicatrion.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Garnet.common; +using Garnet.server; +using Microsoft.Extensions.Hosting; + +namespace Garnet; + +public class GarnetApplication : IHost +{ + readonly IHost host; + + public GarnetApplication(IHost host) + { + this.host = host; + } + + public Task StartAsync(CancellationToken cancellationToken = default) + => host.StartAsync(cancellationToken); + + public Task StopAsync(CancellationToken cancellationToken = default) + => host.StopAsync(cancellationToken); + + public IServiceProvider Services { get => host.Services; } + + public void Dispose() + { + host.Dispose(); + } + + public void Run() + { + HostingAbstractionsHostExtensions.Run(this); + } + + public Task RunAsync(CancellationToken cancellationToken = default) + { + HostingAbstractionsHostExtensions.RunAsync(this, cancellationToken); + return Task.CompletedTask; + } + + public static GarnetApplicationBuilder CreateHostBuilder(string[] args) + { + MemoryLogger initLogger; + + // Set up an initial memory logger to log messages from configuration parser into memory. + using (var memLogProvider = new MemoryLoggerProvider()) + { + initLogger = (MemoryLogger)memLogProvider.CreateLogger("ArgParser"); + } + + if (!ServerSettingsManager.TryParseCommandLineArguments(args, out var serverSettings, out _, + out var exitGracefully, initLogger)) + { + if (exitGracefully) + System.Environment.Exit(0); + + // Flush logs from memory logger + //initLogger.FlushLogger(logger); + + throw new GarnetException( + "Encountered an error when initializing Garnet server. Please see log messages above for more details."); + } + + var garnetServerOptions = serverSettings.GetServerOptions(null); + + return new (new GarnetApplicationOptions {Args = args}, garnetServerOptions); + } + + public static GarnetApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) + { + return new(new GarnetApplicationOptions + { + Args = args, + }, options); + } +} \ No newline at end of file diff --git a/main/GarnetServer/Program.cs b/main/GarnetServer/Program.cs index 314a6a39ba..a1534e9071 100644 --- a/main/GarnetServer/Program.cs +++ b/main/GarnetServer/Program.cs @@ -3,97 +3,92 @@ using System; using System.Threading; +using Garnet; using Garnet.server; -namespace Garnet +var builder = GarnetApplication.CreateHostBuilder(args); + +var app = builder.Build(); + +app.Run(); + +try { - /// - /// Garnet server entry point - /// - class Program + using var server = new GarnetServer(args); + + // Optional: register custom extensions + RegisterExtensions(server); + + // Start the server + server.Start(); + + Thread.Sleep(Timeout.Infinite); +} +catch (Exception ex) +{ + Console.WriteLine($"Unable to initialize server due to exception: {ex.Message}"); +} + +/// +/// Register new commands with the server. You can access these commands from clients using +/// commands such as db.Execute in StackExchange.Redis. Example: +/// db.Execute("SETIFPM", key, value, prefix); +/// +static void RegisterExtensions(GarnetServer server) +{ + // Register custom command on raw strings (SETIFPM = "set if prefix match") + // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO + var setIfPmCmdInfo = new RespCommandsInfo + { + Name = "SETIFPM", + Arity = 4, + FirstKey = 1, + LastKey = 1, + Step = 1, + Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, + AclCategories = RespAclCategories.String | RespAclCategories.Write, + }; + server.Register.NewCommand("SETIFPM", CommandType.ReadModifyWrite, new SetIfPMCustomCommand(), setIfPmCmdInfo); + + // Register custom command on raw strings (SETWPIFPGT = "set with prefix, if prefix greater than") + server.Register.NewCommand("SETWPIFPGT", CommandType.ReadModifyWrite, new SetWPIFPGTCustomCommand()); + + // Register custom command on raw strings (DELIFM = "delete if value matches") + server.Register.NewCommand("DELIFM", CommandType.ReadModifyWrite, new DeleteIfMatchCustomCommand()); + + // Register custom commands on objects + var factory = new MyDictFactory(); + server.Register.NewType(factory); + server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); + server.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), new RespCommandsInfo { Arity = 3 }); + + // Register stored procedure to run a transactional command + // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO + var readWriteTxCmdInfo = new RespCommandsInfo { - static void Main(string[] args) - { - try - { - using var server = new GarnetServer(args); - - // Optional: register custom extensions - RegisterExtensions(server); - - // Start the server - server.Start(); - - Thread.Sleep(Timeout.Infinite); - } - catch (Exception ex) - { - Console.WriteLine($"Unable to initialize server due to exception: {ex.Message}"); - } - } - - /// - /// Register new commands with the server. You can access these commands from clients using - /// commands such as db.Execute in StackExchange.Redis. Example: - /// db.Execute("SETIFPM", key, value, prefix); - /// - static void RegisterExtensions(GarnetServer server) - { - // Register custom command on raw strings (SETIFPM = "set if prefix match") - // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO - var setIfPmCmdInfo = new RespCommandsInfo - { - Name = "SETIFPM", - Arity = 4, - FirstKey = 1, - LastKey = 1, - Step = 1, - Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, - AclCategories = RespAclCategories.String | RespAclCategories.Write, - }; - server.Register.NewCommand("SETIFPM", CommandType.ReadModifyWrite, new SetIfPMCustomCommand(), setIfPmCmdInfo); - - // Register custom command on raw strings (SETWPIFPGT = "set with prefix, if prefix greater than") - server.Register.NewCommand("SETWPIFPGT", CommandType.ReadModifyWrite, new SetWPIFPGTCustomCommand()); - - // Register custom command on raw strings (DELIFM = "delete if value matches") - server.Register.NewCommand("DELIFM", CommandType.ReadModifyWrite, new DeleteIfMatchCustomCommand()); - - // Register custom commands on objects - var factory = new MyDictFactory(); - server.Register.NewType(factory); - server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); - server.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), new RespCommandsInfo { Arity = 3 }); - - // Register stored procedure to run a transactional command - // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO - var readWriteTxCmdInfo = new RespCommandsInfo - { - Name = "READWRITETX", - Arity = 4, - FirstKey = 1, - LastKey = 3, - Step = 1, - Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, - AclCategories = RespAclCategories.Write, - }; - server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), readWriteTxCmdInfo); - - // Register stored procedure to run a transactional command - server.Register.NewTransactionProc("MSETPX", () => new MSetPxTxn()); - - // Register stored procedure to run a transactional command - server.Register.NewTransactionProc("MGETIFPM", () => new MGetIfPM()); - - // Register stored procedure to run a non-transactional command - server.Register.NewTransactionProc("GETTWOKEYSNOTXN", () => new GetTwoKeysNoTxn(), new RespCommandsInfo { Arity = 3 }); - - // Register sample transactional procedures - server.Register.NewTransactionProc("SAMPLEUPDATETX", () => new SampleUpdateTxn(), new RespCommandsInfo { Arity = 9 }); - server.Register.NewTransactionProc("SAMPLEDELETETX", () => new SampleDeleteTxn(), new RespCommandsInfo { Arity = 6 }); - - server.Register.NewProcedure("SUM", () => new Sum()); - server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - } - } + Name = "READWRITETX", + Arity = 4, + FirstKey = 1, + LastKey = 3, + Step = 1, + Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, + AclCategories = RespAclCategories.Write, + }; + server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), readWriteTxCmdInfo); + + // Register stored procedure to run a transactional command + server.Register.NewTransactionProc("MSETPX", () => new MSetPxTxn()); + + // Register stored procedure to run a transactional command + server.Register.NewTransactionProc("MGETIFPM", () => new MGetIfPM()); + + // Register stored procedure to run a non-transactional command + server.Register.NewTransactionProc("GETTWOKEYSNOTXN", () => new GetTwoKeysNoTxn(), new RespCommandsInfo { Arity = 3 }); + + // Register sample transactional procedures + server.Register.NewTransactionProc("SAMPLEUPDATETX", () => new SampleUpdateTxn(), new RespCommandsInfo { Arity = 9 }); + server.Register.NewTransactionProc("SAMPLEDELETETX", () => new SampleDeleteTxn(), new RespCommandsInfo { Arity = 6 }); + + server.Register.NewProcedure("SUM", () => new Sum()); + server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); } \ No newline at end of file diff --git a/test/Garnet.test/RespSetTest.cs b/test/Garnet.test/RespSetTest.cs index 59344b462d..b922bc1c41 100644 --- a/test/Garnet.test/RespSetTest.cs +++ b/test/Garnet.test/RespSetTest.cs @@ -234,7 +234,7 @@ public void CanUseSScanNoParameters() } catch (RedisServerException e) { - var expectedErrorMessage = string.Format(CmdStrings.GenericErrWrongNumArgs, nameof(Garnet.server.SetOperation.SSCAN)); + var expectedErrorMessage = string.Format(CmdStrings.GenericErrWrongNumArgs, nameof(GarnetApplication.server.SetOperation.SSCAN)); ClassicAssert.AreEqual(expectedErrorMessage, e.Message); } From a82cbc8ec9ca53fc0906a126efb464ee15b47ae2 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 04:27:42 +0100 Subject: [PATCH 02/42] make some test use the generic host --- libs/host/GarnetApplicationBuilder.cs | 9 ++ libs/host/GarnetServerHostedService.cs | 32 +++++ main/GarnetServer/Program.cs | 2 + test/Garnet.test/RespSetTest.cs | 2 +- test/Garnet.test/TestUtils.cs | 176 +++++++++++++++++++++++++ test/Garnet.test/TransactionTests.cs | 18 +-- 6 files changed, 229 insertions(+), 10 deletions(-) create mode 100644 libs/host/GarnetServerHostedService.cs diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 7b8ef56fc9..99c4b77e09 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -36,6 +36,15 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer simpleConsoleFormatterOptions.SingleLine = true; simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; }); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var loggerFactory = sp.GetRequiredService(); + + return new GarnetServer(garnetServerOptions, loggerFactory); + }); + + hostApplicationBuilder.Services.AddHostedService(); } public GarnetApplication Build() diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs new file mode 100644 index 0000000000..a669f80ba2 --- /dev/null +++ b/libs/host/GarnetServerHostedService.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; + +namespace Garnet; + +public class GarnetServerHostedService : IHostedService +{ + readonly GarnetServer server; + + public GarnetServerHostedService(GarnetServer server) + { + this.server = server; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + server.Start(); + + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + server.Dispose(); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/main/GarnetServer/Program.cs b/main/GarnetServer/Program.cs index a1534e9071..3f94782b50 100644 --- a/main/GarnetServer/Program.cs +++ b/main/GarnetServer/Program.cs @@ -12,6 +12,7 @@ app.Run(); +/* try { using var server = new GarnetServer(args); @@ -28,6 +29,7 @@ { Console.WriteLine($"Unable to initialize server due to exception: {ex.Message}"); } +*/ /// /// Register new commands with the server. You can access these commands from clients using diff --git a/test/Garnet.test/RespSetTest.cs b/test/Garnet.test/RespSetTest.cs index b922bc1c41..59344b462d 100644 --- a/test/Garnet.test/RespSetTest.cs +++ b/test/Garnet.test/RespSetTest.cs @@ -234,7 +234,7 @@ public void CanUseSScanNoParameters() } catch (RedisServerException e) { - var expectedErrorMessage = string.Format(CmdStrings.GenericErrWrongNumArgs, nameof(GarnetApplication.server.SetOperation.SSCAN)); + var expectedErrorMessage = string.Format(CmdStrings.GenericErrWrongNumArgs, nameof(Garnet.server.SetOperation.SSCAN)); ClassicAssert.AreEqual(expectedErrorMessage, e.Message); } diff --git a/test/Garnet.test/TestUtils.cs b/test/Garnet.test/TestUtils.cs index 9bf375a706..b0bc63960d 100644 --- a/test/Garnet.test/TestUtils.cs +++ b/test/Garnet.test/TestUtils.cs @@ -179,6 +179,182 @@ internal static void IgnoreIfNotRunningAzureTests() Assert.Ignore("Environment variable RunAzureTests is not defined"); } + /// + /// Create GarnetServer + /// + public static GarnetApplication CreateGarnetApplication( + string logCheckpointDir, + bool disablePubSub = false, + bool tryRecover = false, + bool lowMemory = false, + string MemorySize = default, + string PageSize = default, + bool enableAOF = false, + bool EnableTLS = false, + bool DisableObjects = false, + int metricsSamplingFreq = -1, + bool latencyMonitor = false, + int commitFrequencyMs = 0, + bool commitWait = false, + bool UseAzureStorage = false, + string defaultPassword = null, + bool useAcl = false, // NOTE: Temporary until ACL is enforced as default + string aclFile = null, + string objectStoreHeapMemorySize = default, + string objectStoreIndexSize = "16k", + string objectStoreIndexMaxSize = default, + string objectStoreReadCacheHeapMemorySize = default, + string indexSize = "1m", + string indexMaxSize = default, + string[] extensionBinPaths = null, + bool extensionAllowUnsignedAssemblies = true, + bool getSG = false, + int indexResizeFrequencySecs = 60, + IAuthenticationSettings authenticationSettings = null, + bool enableLua = false, + bool enableReadCache = false, + bool enableObjectStoreReadCache = false, + ILogger logger = null, + IEnumerable loadModulePaths = null, + string pubSubPageSize = null, + bool asyncReplay = false, + LuaMemoryManagementMode luaMemoryMode = LuaMemoryManagementMode.Native, + string luaMemoryLimit = "") + { + if (UseAzureStorage) + IgnoreIfNotRunningAzureTests(); + var _LogDir = logCheckpointDir; + if (UseAzureStorage) + _LogDir = $"{AzureTestContainer}/{AzureTestDirectory}"; + + if (logCheckpointDir != null && !UseAzureStorage) _LogDir = new DirectoryInfo(string.IsNullOrEmpty(_LogDir) ? "." : _LogDir).FullName; + + var _CheckpointDir = logCheckpointDir; + if (UseAzureStorage) + _CheckpointDir = $"{AzureTestContainer}/{AzureTestDirectory}"; + + if (logCheckpointDir != null && !UseAzureStorage) _CheckpointDir = new DirectoryInfo(string.IsNullOrEmpty(_CheckpointDir) ? "." : _CheckpointDir).FullName; + + if (useAcl) + { + if (authenticationSettings != null) + { + throw new ArgumentException($"Cannot set both {nameof(useAcl)} and {nameof(authenticationSettings)}"); + } + + authenticationSettings = new AclAuthenticationPasswordSettings(aclFile, defaultPassword); + } + else if (defaultPassword != null) + { + if (authenticationSettings != null) + { + throw new ArgumentException($"Cannot set both {nameof(defaultPassword)} and {nameof(authenticationSettings)}"); + } + + authenticationSettings = new PasswordAuthenticationSettings(defaultPassword); + } + + // Increase minimum thread pool size to 16 if needed + int threadPoolMinThreads = 0; + ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads); + if (workerThreads < 16 || completionPortThreads < 16) threadPoolMinThreads = 16; + + GarnetServerOptions opts = new(logger) + { + EnableStorageTier = logCheckpointDir != null, + LogDir = _LogDir, + CheckpointDir = _CheckpointDir, + Address = Address, + Port = Port, + DisablePubSub = disablePubSub, + Recover = tryRecover, + IndexSize = indexSize, + ObjectStoreIndexSize = objectStoreIndexSize, + EnableAOF = enableAOF, + EnableLua = enableLua, + CommitFrequencyMs = commitFrequencyMs, + WaitForCommit = commitWait, + TlsOptions = EnableTLS ? new GarnetTlsOptions( + certFileName: certFile, + certPassword: certPassword, + clientCertificateRequired: true, + certificateRevocationCheckMode: X509RevocationMode.NoCheck, + issuerCertificatePath: null, + null, 0, false, null, logger: logger) + : null, + DisableObjects = DisableObjects, + QuietMode = true, + MetricsSamplingFrequency = metricsSamplingFreq, + LatencyMonitor = latencyMonitor, + DeviceFactoryCreator = UseAzureStorage ? + () => new AzureStorageNamedDeviceFactory(AzureEmulatedStorageString, logger) + : () => new LocalStorageNamedDeviceFactory(logger: logger), + AuthSettings = authenticationSettings, + ExtensionBinPaths = extensionBinPaths, + ExtensionAllowUnsignedAssemblies = extensionAllowUnsignedAssemblies, + EnableScatterGatherGet = getSG, + IndexResizeFrequencySecs = indexResizeFrequencySecs, + ThreadPoolMinThreads = threadPoolMinThreads, + LoadModuleCS = loadModulePaths, + EnableReadCache = enableReadCache, + EnableObjectStoreReadCache = enableObjectStoreReadCache, + ReplicationOffsetMaxLag = asyncReplay ? -1 : 0, + LuaOptions = enableLua ? new LuaOptions(luaMemoryMode, luaMemoryLimit, logger) : null, + }; + + if (!string.IsNullOrEmpty(pubSubPageSize)) + opts.PubSubPageSize = pubSubPageSize; + + if (!string.IsNullOrEmpty(objectStoreHeapMemorySize)) + opts.ObjectStoreHeapMemorySize = objectStoreHeapMemorySize; + + if (!string.IsNullOrEmpty(objectStoreReadCacheHeapMemorySize)) + opts.ObjectStoreReadCacheHeapMemorySize = objectStoreReadCacheHeapMemorySize; + + if (indexMaxSize != default) opts.IndexMaxSize = indexMaxSize; + if (objectStoreIndexMaxSize != default) opts.ObjectStoreIndexMaxSize = objectStoreIndexMaxSize; + + if (lowMemory) + { + opts.MemorySize = opts.ObjectStoreLogMemorySize = MemorySize == default ? "1024" : MemorySize; + opts.PageSize = opts.ObjectStorePageSize = PageSize == default ? "512" : PageSize; + if (enableReadCache) + { + opts.ReadCacheMemorySize = opts.MemorySize; + opts.ReadCachePageSize = opts.PageSize; + } + + if (enableObjectStoreReadCache) + { + opts.ObjectStoreReadCacheLogMemorySize = opts.MemorySize; + opts.ObjectStoreReadCachePageSize = opts.PageSize; + } + } + + if (useTestLogger) + { + var builder = GarnetApplication.CreateHostBuilder([], opts); + + builder.Logging.ClearProviders(); + builder.Logging.AddProvider(new NUnitLoggerProvider(TestContext.Progress, + TestContext.CurrentContext.Test.MethodName, null, false, false, LogLevel.Trace)); + builder.Logging.SetMinimumLevel(LogLevel.Trace); + + var app = builder.Build(); + + return app; + } + else + { + + var builder = GarnetApplication.CreateHostBuilder([], opts); + + var app = builder.Build(); + + return app; + } + } + /// /// Create GarnetServer /// diff --git a/test/Garnet.test/TransactionTests.cs b/test/Garnet.test/TransactionTests.cs index aefd400cdc..dbeea0b249 100644 --- a/test/Garnet.test/TransactionTests.cs +++ b/test/Garnet.test/TransactionTests.cs @@ -13,29 +13,29 @@ namespace Garnet.test [TestFixture] public class TransactionTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } - public void SetUpWithLowMemory() + public async Task SetUpWithLowMemory() { TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [Test] From 85fc2f8d95199b11c94f7d32888619b3711c2b01 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 05:18:22 +0100 Subject: [PATCH 03/42] fix disposing --- libs/host/GarnetApplicationBuilder.cs | 12 +++++- libs/host/GarnetApplicatrion.cs | 2 + libs/host/GarnetServerHostedService.cs | 31 +++++++++++---- test/Garnet.test/GarnetBitmapTests.cs | 54 +++++++++++++------------- 4 files changed, 64 insertions(+), 35 deletions(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 99c4b77e09..4b203ae127 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -37,14 +37,24 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; }); + /* hostApplicationBuilder.Services.AddSingleton(sp => { var loggerFactory = sp.GetRequiredService(); return new GarnetServer(garnetServerOptions, loggerFactory); }); + */ - hostApplicationBuilder.Services.AddHostedService(); + hostApplicationBuilder.Services.AddHostedService(sp => + { + var loggerFactory = sp.GetRequiredService(); + var logger = loggerFactory.CreateLogger(); + + //var server = new GarnetServer(garnetServerOptions, loggerFactory); + + return new GarnetServerHostedService(garnetServerOptions, logger, loggerFactory); + }); } public GarnetApplication Build() diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs index 7c9679f18b..7a8e814581 100644 --- a/libs/host/GarnetApplicatrion.cs +++ b/libs/host/GarnetApplicatrion.cs @@ -12,6 +12,8 @@ namespace Garnet; public class GarnetApplication : IHost { + public RegisterApi Register { get; set; } + readonly IHost host; public GarnetApplication(IHost host) diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index a669f80ba2..f020cd8d47 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -1,32 +1,47 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System; using System.Threading; using System.Threading.Tasks; +using Garnet.server; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; namespace Garnet; -public class GarnetServerHostedService : IHostedService +public class GarnetServerHostedService : BackgroundService, IDisposable { readonly GarnetServer server; + readonly ILogger logger; - public GarnetServerHostedService(GarnetServer server) + public GarnetServerHostedService( + GarnetServerOptions garnetServerOptions, + ILogger logger, + ILoggerFactory loggerFactory) + { + this.server = new GarnetServer(garnetServerOptions, loggerFactory); + this.logger = logger; + } + + public GarnetServerHostedService(GarnetServer server, ILogger logger) { this.server = server; + this.logger = logger; } - - public Task StartAsync(CancellationToken cancellationToken) + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) { server.Start(); - return Task.CompletedTask; + logger.LogInformation("Garnet server running at: {time}", DateTimeOffset.Now); + + await Task.CompletedTask; } - public Task StopAsync(CancellationToken cancellationToken) + public void Dispose() { server.Dispose(); - - return Task.CompletedTask; + base.Dispose(); } } \ No newline at end of file diff --git a/test/Garnet.test/GarnetBitmapTests.cs b/test/Garnet.test/GarnetBitmapTests.cs index 627a4984d4..f18ad4a06c 100644 --- a/test/Garnet.test/GarnetBitmapTests.cs +++ b/test/Garnet.test/GarnetBitmapTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using NUnit.Framework; @@ -13,22 +14,23 @@ namespace Garnet.test { public class GarnetBitmapTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + //await server.RunAsync(); + server.RunAsync(); r = new Random(674386); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -438,15 +440,15 @@ public void BitmapBitCountNegativeOffsets() [Test, Order(10)] [Category("BITCOUNT")] - public void BitmapBitCountTest_LTM() + public async Task BitmapBitCountTest_LTM() { int bitmapBytes = 512; - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -635,15 +637,15 @@ public void BitmapBitPosOffsetsTest() [Test, Order(14)] [Category("BITPOS")] - public void BitmapBitPosTest_LTM() + public async Task BitmapBitPosTest_LTM() { int bitmapBytes = 512; - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1280,17 +1282,17 @@ public unsafe void BitmapBitfieldGetTest_PCT([Values(RespCommand.BITFIELD, RespC [Test, Order(23)] [Category("BITFIELD")] - public void BitmapBitfieldGetTest_LTM([Values(RespCommand.BITFIELD, RespCommand.BITFIELD_RO)] RespCommand testCmd) + public async Task BitmapBitfieldGetTest_LTM([Values(RespCommand.BITFIELD, RespCommand.BITFIELD_RO)] RespCommand testCmd) { int bitmapBytes = 512; - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); //MemorySize: "16g", //PageSize: "32m"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1481,17 +1483,17 @@ public void BitmapBitfieldSetTest() [Test, Order(26)] [Category("BITFIELD")] - public void BitmapBitfieldSetTest_LTM() + public async Task BitmapBitfieldSetTest_LTM() { int bitmapBytes = 512; - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); //MemorySize: "16g", //PageSize: "32m"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1947,17 +1949,17 @@ public void BitmapBitfieldSignedIncrTest() [Test, Order(29)] [Category("BITFIELD")] - public void BitmapBitfieldIncrTest_LTM() + public async Task BitmapBitfieldIncrTest_LTM() { int bitmapBytes = 512; - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); //MemorySize: "16g", //PageSize: "32m"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); From f912b9fa3e9febc2bf359dab3ce41b28bc5cb68d Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 05:24:44 +0100 Subject: [PATCH 04/42] update ctor --- libs/host/GarnetApplicationBuilder.cs | 4 ++-- libs/host/GarnetServerHostedService.cs | 11 +---------- test/Garnet.test/GarnetBitmapTests.cs | 3 +-- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 4b203ae127..49dbfe26d6 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -51,9 +51,9 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer var loggerFactory = sp.GetRequiredService(); var logger = loggerFactory.CreateLogger(); - //var server = new GarnetServer(garnetServerOptions, loggerFactory); + var server = new GarnetServer(garnetServerOptions, loggerFactory); - return new GarnetServerHostedService(garnetServerOptions, logger, loggerFactory); + return new GarnetServerHostedService(server, logger); }); } diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index f020cd8d47..beff53988b 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -15,15 +15,6 @@ public class GarnetServerHostedService : BackgroundService, IDisposable readonly GarnetServer server; readonly ILogger logger; - public GarnetServerHostedService( - GarnetServerOptions garnetServerOptions, - ILogger logger, - ILoggerFactory loggerFactory) - { - this.server = new GarnetServer(garnetServerOptions, loggerFactory); - this.logger = logger; - } - public GarnetServerHostedService(GarnetServer server, ILogger logger) { this.server = server; @@ -39,7 +30,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) await Task.CompletedTask; } - public void Dispose() + public override void Dispose() { server.Dispose(); base.Dispose(); diff --git a/test/Garnet.test/GarnetBitmapTests.cs b/test/Garnet.test/GarnetBitmapTests.cs index f18ad4a06c..4fdaa42447 100644 --- a/test/Garnet.test/GarnetBitmapTests.cs +++ b/test/Garnet.test/GarnetBitmapTests.cs @@ -22,8 +22,7 @@ public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); - //await server.RunAsync(); - server.RunAsync(); + await server.RunAsync(); r = new Random(674386); } From cf3c67e5f132960bf36b5546c88d7cd79e6acf26 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 05:31:54 +0100 Subject: [PATCH 05/42] add garnet server using di as transient --- libs/host/GarnetApplicationBuilder.cs | 32 ++++++++++++++------------ libs/host/GarnetServerHostedService.cs | 8 +------ 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 49dbfe26d6..cb5267485f 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -15,11 +15,11 @@ namespace Garnet; public class GarnetApplicationBuilder : IHostApplicationBuilder { readonly HostApplicationBuilder hostApplicationBuilder; - + internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) { var configuration = new ConfigurationManager(); - + configuration.AddEnvironmentVariables(prefix: "GARNET_"); hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings @@ -29,7 +29,7 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer EnvironmentName = options.EnvironmentName, Configuration = configuration }); - + hostApplicationBuilder.Logging.ClearProviders(); hostApplicationBuilder.Logging.AddSimpleConsole(simpleConsoleFormatterOptions => { @@ -37,26 +37,28 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; }); - /* - hostApplicationBuilder.Services.AddSingleton(sp => + hostApplicationBuilder.Services.AddTransient(sp => { var loggerFactory = sp.GetRequiredService(); - + return new GarnetServer(garnetServerOptions, loggerFactory); }); - */ - + + hostApplicationBuilder.Services.AddHostedService(); + + /* hostApplicationBuilder.Services.AddHostedService(sp => { var loggerFactory = sp.GetRequiredService(); var logger = loggerFactory.CreateLogger(); - + var server = new GarnetServer(garnetServerOptions, loggerFactory); return new GarnetServerHostedService(server, logger); }); + */ } - + public GarnetApplication Build() { var host = hostApplicationBuilder.Build(); @@ -71,19 +73,19 @@ public void ConfigureContainer(IServiceProviderFactory Properties { get; } - + public IConfigurationManager Configuration => hostApplicationBuilder.Configuration; - + public IHostEnvironment Environment => hostApplicationBuilder.Environment; - + public ILoggingBuilder Logging => hostApplicationBuilder.Logging; - + public IMetricsBuilder Metrics => hostApplicationBuilder.Metrics; - + public IServiceCollection Services => hostApplicationBuilder.Services; } \ No newline at end of file diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index beff53988b..d70e8df8da 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -10,7 +10,7 @@ namespace Garnet; -public class GarnetServerHostedService : BackgroundService, IDisposable +public class GarnetServerHostedService : BackgroundService { readonly GarnetServer server; readonly ILogger logger; @@ -29,10 +29,4 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) await Task.CompletedTask; } - - public override void Dispose() - { - server.Dispose(); - base.Dispose(); - } } \ No newline at end of file From 41bea023574fee3a57ab1d4e17763b2c40fb12a9 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 05:39:38 +0100 Subject: [PATCH 06/42] add garnert server tcp to di --- libs/host/GarnetApplicationBuilder.cs | 10 +++++++++- libs/server/Servers/GarnetServerTcp.cs | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index cb5267485f..d4bd18f00c 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -30,6 +30,11 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer Configuration = configuration }); + hostApplicationBuilder.Services.AddOptions(); + + var garnetServerOptionsWrapped = Microsoft.Extensions.Options.Options.Create(garnetServerOptions); + hostApplicationBuilder.Services.AddSingleton(garnetServerOptionsWrapped); + hostApplicationBuilder.Logging.ClearProviders(); hostApplicationBuilder.Logging.AddSimpleConsole(simpleConsoleFormatterOptions => { @@ -37,11 +42,14 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; }); + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(sp => { var loggerFactory = sp.GetRequiredService(); + var server = sp.GetRequiredService(); - return new GarnetServer(garnetServerOptions, loggerFactory); + return new GarnetServer(garnetServerOptions, loggerFactory, server); }); hostApplicationBuilder.Services.AddHostedService(); diff --git a/libs/server/Servers/GarnetServerTcp.cs b/libs/server/Servers/GarnetServerTcp.cs index 09a1c4fd71..0045c4db8f 100644 --- a/libs/server/Servers/GarnetServerTcp.cs +++ b/libs/server/Servers/GarnetServerTcp.cs @@ -10,6 +10,7 @@ using Garnet.networking; using Garnet.server.TLS; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Garnet.server { @@ -60,6 +61,25 @@ public IEnumerable ActiveClusterSessions() yield return ((RespServerSession)consumer).clusterSession; } } + + /// + /// Constructor for server + /// + /// + /// + public GarnetServerTcp(IOptions options, ILogger logger) + : base(options.Value.Address, options.Value.Port, 0, logger) + { + this.networkConnectionLimit = options.Value.NetworkConnectionLimit; + this.tlsOptions = options.Value.TlsOptions; + this.networkSendThrottleMax = options.Value.NetworkSendThrottleMax; + var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); + this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); + this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); + servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + acceptEventArg = new SocketAsyncEventArgs(); + acceptEventArg.Completed += AcceptEventArg_Completed; + } /// /// Constructor for server From 70c9edc6e530b77b6d6cd9c3a58a77d609cedd15 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 05:55:39 +0100 Subject: [PATCH 07/42] add new garnet di constructor --- libs/host/GarnetApplicationBuilder.cs | 14 +- libs/host/GarnetApplicatrion.cs | 11 +- libs/host/GarnetServer.cs | 220 +++++++++++++++++++++++--- 3 files changed, 217 insertions(+), 28 deletions(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index d4bd18f00c..b6ccb91242 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using Garnet.cluster; using Garnet.server; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.Metrics; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Garnet; @@ -41,16 +43,26 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer simpleConsoleFormatterOptions.SingleLine = true; simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; }); + + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); + + /* hostApplicationBuilder.Services.AddTransient(sp => { + var options = sp.GetRequiredService>(); var loggerFactory = sp.GetRequiredService(); var server = sp.GetRequiredService(); + var clusterFactory = sp.GetRequiredService(); + var customCommandManager = sp.GetRequiredService(); - return new GarnetServer(garnetServerOptions, loggerFactory, server); + return new GarnetServer(options, loggerFactory, server, clusterFactory, customCommandManager); }); + */ hostApplicationBuilder.Services.AddHostedService(); diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs index 7a8e814581..fcb7bafee7 100644 --- a/libs/host/GarnetApplicatrion.cs +++ b/libs/host/GarnetApplicatrion.cs @@ -6,14 +6,21 @@ using System.Threading.Tasks; using Garnet.common; using Garnet.server; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Garnet; public class GarnetApplication : IHost { - public RegisterApi Register { get; set; } - + public RegisterApi Register + { + get + { + throw new NotImplementedException(); + } + } + readonly IHost host; public GarnetApplication(IHost host) diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index c4af9b8dfe..2b6cdb1ac0 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -14,15 +14,19 @@ using Garnet.server; using Garnet.server.Auth.Settings; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Tsavorite.core; namespace Garnet { - using MainStoreAllocator = SpanByteAllocator>; + using MainStoreAllocator = + SpanByteAllocator>; using MainStoreFunctions = StoreFunctions; - - using ObjectStoreAllocator = GenericAllocator>>; - using ObjectStoreFunctions = StoreFunctions>; + using ObjectStoreAllocator = + GenericAllocator>>; + using ObjectStoreFunctions = + StoreFunctions>; /// /// Implementation Garnet server @@ -30,6 +34,7 @@ namespace Garnet public class GarnetServer : IDisposable { static readonly string version = GetVersion(); + static string GetVersion() { var Version = Assembly.GetExecutingAssembly().GetName().Version; @@ -78,6 +83,143 @@ static string GetVersion() /// Store API /// public StoreApi Store; + + readonly IClusterFactory clusterFactory; + readonly CustomCommandManager customCommandManager; + + /// + /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. + /// + /// Server options + /// Logger factory + /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. + /// + /// + public GarnetServer( + IOptions options, + ILoggerFactory loggerFactory, + IGarnetServer server, + IClusterFactory clusterFactory, + CustomCommandManager customCommandManager) + { + this.server = server; + this.opts = options.Value; + this.loggerFactory = loggerFactory; + this.clusterFactory = clusterFactory; + this.customCommandManager = customCommandManager; + + this.cleanupDir = false; + this.InitializeServerUpdated(); + } + + private void InitializeServerUpdated() + { + Debug.Assert(opts != null); + + if (!opts.QuietMode) + { + var red = "\u001b[31m"; + var magenta = "\u001b[35m"; + var normal = "\u001b[0m"; + + Console.WriteLine($@"{red} _________ + /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} + '. \ / .' {normal}Port: {opts.Port}{red} + '.\ /.' {magenta}https://aka.ms/GetGarnet{red} + '.' + {normal}"); + } + + var clusterFactory = opts.EnableCluster ? this.clusterFactory : null; + + this.logger = this.loggerFactory?.CreateLogger("GarnetServer"); + logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, + IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); + + // Flush initialization logs from memory logger + FlushMemoryLogger(this.initLogger, "ArgParser", this.loggerFactory); + + ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); + ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); + + bool minChanged = false, maxChanged = false; + if (opts.ThreadPoolMinThreads > 0) + { + minThreads = opts.ThreadPoolMinThreads; + minChanged = true; + } + + if (opts.ThreadPoolMinIOCompletionThreads > 0) + { + minCPThreads = opts.ThreadPoolMinIOCompletionThreads; + minChanged = true; + } + + if (opts.ThreadPoolMaxThreads > 0) + { + maxThreads = opts.ThreadPoolMaxThreads; + maxChanged = true; + } + + if (opts.ThreadPoolMaxIOCompletionThreads > 0) + { + maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; + maxChanged = true; + } + + // First try to set the max threads + var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); + + // Set the min threads + if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); + + // Retry to set max threads if it wasn't set in the earlier step + if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); + + CreateMainStore(clusterFactory, out var checkpointDir); + CreateObjectStore(clusterFactory, customCommandManager, checkpointDir, out var objectStoreSizeTracker); + + if (!opts.DisablePubSub) + subscribeBroker = new SubscribeBroker>( + new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, + true); + + CreateAOF(); + + logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); + + if (logger != null) + { + var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); + if (objectStore != null) + configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + + (objectStoreSizeTracker?.TargetSize ?? 0) + + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); + logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); + } + + storeWrapper = new StoreWrapper(version, redisProtocolVersion, server, store, objectStore, + objectStoreSizeTracker, + customCommandManager, appendOnlyFile, opts, clusterFactory: clusterFactory, + loggerFactory: loggerFactory); + + // Create session provider for Garnet + Provider = new GarnetProvider(storeWrapper, subscribeBroker); + + // Create user facing API endpoints + Metrics = new MetricsApi(Provider); + Register = new RegisterApi(Provider); + Store = new StoreApi(storeWrapper); + + server.Register(WireFormat.ASCII, Provider); + + LoadModules(customCommandManager); + } /// /// Create Garnet Server instance using specified command line arguments; use Start to start the server. @@ -86,7 +228,8 @@ static string GetVersion() /// Logger factory /// Clean up directory. /// Override for custom authentication settings. - public GarnetServer(string[] commandLineArgs, ILoggerFactory loggerFactory = null, bool cleanupDir = false, IAuthenticationSettings authenticationSettingsOverride = null) + public GarnetServer(string[] commandLineArgs, ILoggerFactory loggerFactory = null, bool cleanupDir = false, + IAuthenticationSettings authenticationSettingsOverride = null) { Trace.Listeners.Add(new ConsoleTraceListener()); @@ -96,7 +239,8 @@ public GarnetServer(string[] commandLineArgs, ILoggerFactory loggerFactory = nul this.initLogger = (MemoryLogger)memLogProvider.CreateLogger("ArgParser"); } - if (!ServerSettingsManager.TryParseCommandLineArguments(commandLineArgs, out var serverSettings, out _, out var exitGracefully, this.initLogger)) + if (!ServerSettingsManager.TryParseCommandLineArguments(commandLineArgs, out var serverSettings, out _, + out var exitGracefully, this.initLogger)) { if (exitGracefully) Environment.Exit(0); @@ -104,7 +248,8 @@ public GarnetServer(string[] commandLineArgs, ILoggerFactory loggerFactory = nul // Flush logs from memory logger FlushMemoryLogger(this.initLogger, "ArgParser", loggerFactory); - throw new GarnetException("Encountered an error when initializing Garnet server. Please see log messages above for more details."); + throw new GarnetException( + "Encountered an error when initializing Garnet server. Please see log messages above for more details."); } if (loggerFactory == null) @@ -151,7 +296,8 @@ public GarnetServer(string[] commandLineArgs, ILoggerFactory loggerFactory = nul /// Logger factory /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. /// Whether to clean up data folders on dispose - public GarnetServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, IGarnetServer server = null, bool cleanupDir = false) + public GarnetServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, IGarnetServer server = null, + bool cleanupDir = false) { this.server = server; this.opts = opts; @@ -181,7 +327,8 @@ private void InitializeServer() var clusterFactory = opts.EnableCluster ? new ClusterFactory() : null; this.logger = this.loggerFactory?.CreateLogger("GarnetServer"); - logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); + logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, + IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); // Flush initialization logs from memory logger FlushMemoryLogger(this.initLogger, "ArgParser", this.loggerFactory); @@ -197,16 +344,19 @@ private void InitializeServer() minThreads = opts.ThreadPoolMinThreads; minChanged = true; } + if (opts.ThreadPoolMinIOCompletionThreads > 0) { minCPThreads = opts.ThreadPoolMinIOCompletionThreads; minChanged = true; } + if (opts.ThreadPoolMaxThreads > 0) { maxThreads = opts.ThreadPoolMaxThreads; maxChanged = true; } + if (opts.ThreadPoolMaxIOCompletionThreads > 0) { maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; @@ -228,7 +378,9 @@ private void InitializeServer() CreateObjectStore(clusterFactory, customCommandManager, checkpointDir, out var objectStoreSizeTracker); if (!opts.DisablePubSub) - subscribeBroker = new SubscribeBroker>(new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, true); + subscribeBroker = new SubscribeBroker>( + new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, + true); CreateAOF(); @@ -236,17 +388,25 @@ private void InitializeServer() if (logger != null) { - var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); + var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); if (objectStore != null) - configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + (objectStoreSizeTracker?.TargetSize ?? 0) + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); + configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + + (objectStoreSizeTracker?.TargetSize ?? 0) + + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); } // Create Garnet TCP server if none was provided. - this.server ??= new GarnetServerTcp(opts.Address, opts.Port, 0, opts.TlsOptions, opts.NetworkSendThrottleMax, opts.NetworkConnectionLimit, logger); + this.server ??= new GarnetServerTcp(opts.Address, opts.Port, 0, opts.TlsOptions, + opts.NetworkSendThrottleMax, opts.NetworkConnectionLimit, logger); - storeWrapper = new StoreWrapper(version, redisProtocolVersion, server, store, objectStore, objectStoreSizeTracker, - customCommandManager, appendOnlyFile, opts, clusterFactory: clusterFactory, loggerFactory: loggerFactory); + storeWrapper = new StoreWrapper(version, redisProtocolVersion, server, store, objectStore, + objectStoreSizeTracker, + customCommandManager, appendOnlyFile, opts, clusterFactory: clusterFactory, + loggerFactory: loggerFactory); // Create session provider for Garnet Provider = new GarnetProvider(storeWrapper, subscribeBroker); @@ -276,11 +436,13 @@ private void LoadModules(CustomCommandManager customCommandManager) var moduleArgs = moduleCSData.Length > 1 ? moduleCSData.Skip(1).ToArray() : []; if (ModuleUtils.LoadAssemblies([modulePath], null, true, out var loadedAssemblies, out var errorMsg)) { - ModuleRegistrar.Instance.LoadModule(customCommandManager, loadedAssemblies.ToList()[0], moduleArgs, logger, out errorMsg); + ModuleRegistrar.Instance.LoadModule(customCommandManager, loadedAssemblies.ToList()[0], moduleArgs, + logger, out errorMsg); } else { - logger?.LogError("Module {0} failed to load with error {1}", modulePath, Encoding.UTF8.GetString(errorMsg)); + logger?.LogError("Module {0} failed to load with error {1}", modulePath, + Encoding.UTF8.GetString(errorMsg)); } } } @@ -312,7 +474,8 @@ private void CreateMainStore(IClusterFactory clusterFactory, out string checkpoi , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); } - private void CreateObjectStore(IClusterFactory clusterFactory, CustomCommandManager customCommandManager, string CheckpointDir, out CacheSizeTracker objectStoreSizeTracker) + private void CreateObjectStore(IClusterFactory clusterFactory, CustomCommandManager customCommandManager, + string CheckpointDir, out CacheSizeTracker objectStoreSizeTracker) { objectStoreSizeTracker = null; if (!opts.DisableObjects) @@ -341,7 +504,8 @@ private void CreateObjectStore(IClusterFactory clusterFactory, CustomCommandMana , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); if (objHeapMemorySize > 0 || objReadCacheHeapMemorySize > 0) - objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, objReadCacheHeapMemorySize, + objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, + objReadCacheHeapMemorySize, this.loggerFactory); } } @@ -351,11 +515,13 @@ private void CreateAOF() if (opts.EnableAOF) { if (opts.MainMemoryReplication && opts.CommitFrequencyMs != -1) - throw new Exception("Need to set CommitFrequencyMs to -1 (manual commits) with MainMemoryReplication"); + throw new Exception( + "Need to set CommitFrequencyMs to -1 (manual commits) with MainMemoryReplication"); opts.GetAofSettings(out var aofSettings); aofDevice = aofSettings.LogDevice; - appendOnlyFile = new TsavoriteLog(aofSettings, logger: this.loggerFactory?.CreateLogger("TsavoriteLog [aof]")); + appendOnlyFile = new TsavoriteLog(aofSettings, + logger: this.loggerFactory?.CreateLogger("TsavoriteLog [aof]")); if (opts.CommitFrequencyMs < 0 && opts.WaitForCommit) throw new Exception("Cannot use CommitWait with manual commits"); @@ -395,12 +561,12 @@ public void Dispose(bool deleteDir = true) InternalDispose(); if (deleteDir) { - logFactory?.Delete(new FileDescriptor { directoryName = "" }); + logFactory?.Delete(new FileDescriptor {directoryName = ""}); if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) { var ckptdir = opts.DeviceFactoryCreator(); ckptdir.Initialize(opts.CheckpointDir); - ckptdir.Delete(new FileDescriptor { directoryName = "" }); + ckptdir.Delete(new FileDescriptor {directoryName = ""}); } } } @@ -420,6 +586,7 @@ private void InternalDispose() objKvSettings.LogDevice?.Dispose(); objKvSettings.ObjectLogDevice?.Dispose(); } + opts.AuthSettings?.Dispose(); if (disposeLoggerFactory) loggerFactory?.Dispose(); @@ -446,7 +613,9 @@ private static void DeleteDirectory(string path) { Directory.Delete(path, true); } - catch { } + catch + { + } } } @@ -457,7 +626,8 @@ private static void DeleteDirectory(string path) /// The memory logger /// The category name of the destination logger /// Optional logger factory for creating the destination logger - private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, ILoggerFactory dstLoggerFactory = null) + private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, + ILoggerFactory dstLoggerFactory = null) { if (memoryLogger == null) return; From e41983e027c745da7fcb656533e38dea260be85c Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 05:57:22 +0100 Subject: [PATCH 08/42] fix logo --- libs/host/GarnetServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 2b6cdb1ac0..f49332e1b9 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -122,7 +122,7 @@ private void InitializeServerUpdated() var magenta = "\u001b[35m"; var normal = "\u001b[0m"; - Console.WriteLine($@"{red} _________ + Console.WriteLine($@"{red} _________ /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} '. \ / .' {normal}Port: {opts.Port}{red} '.\ /.' {magenta}https://aka.ms/GetGarnet{red} From 17b19268143fa890602a819b2f0c3705b3062e69 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 06:00:24 +0100 Subject: [PATCH 09/42] fix logging --- libs/host/GarnetApplicationBuilder.cs | 1 + libs/host/GarnetServer.cs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index b6ccb91242..e6f5dc8ebc 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -43,6 +43,7 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer simpleConsoleFormatterOptions.SingleLine = true; simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; }); + hostApplicationBuilder.Logging.SetMinimumLevel(garnetServerOptions.LogLevel); hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index f49332e1b9..adda5aad3c 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -91,12 +91,14 @@ static string GetVersion() /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. /// /// Server options + /// Logger /// Logger factory /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. /// /// public GarnetServer( IOptions options, + ILogger logger, ILoggerFactory loggerFactory, IGarnetServer server, IClusterFactory clusterFactory, @@ -104,6 +106,7 @@ public GarnetServer( { this.server = server; this.opts = options.Value; + this.logger = logger; this.loggerFactory = loggerFactory; this.clusterFactory = clusterFactory; this.customCommandManager = customCommandManager; @@ -132,7 +135,6 @@ private void InitializeServerUpdated() var clusterFactory = opts.EnableCluster ? this.clusterFactory : null; - this.logger = this.loggerFactory?.CreateLogger("GarnetServer"); logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); From 8e932a0281792076d87bff5a12d9ebff42f02bfa Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 06:13:09 +0100 Subject: [PATCH 10/42] add store factory --- libs/host/GarnetApplicationBuilder.cs | 2 +- libs/host/GarnetApplicatrion.cs | 1 - libs/host/GarnetServer.cs | 10 ++- libs/host/StoreFactory.cs | 108 ++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 libs/host/StoreFactory.cs diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index e6f5dc8ebc..e162068872 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -10,7 +10,6 @@ using Microsoft.Extensions.Diagnostics.Metrics; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Garnet; @@ -47,6 +46,7 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs index fcb7bafee7..22a030b58d 100644 --- a/libs/host/GarnetApplicatrion.cs +++ b/libs/host/GarnetApplicatrion.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using Garnet.common; using Garnet.server; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Garnet; diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index adda5aad3c..65b1c055bc 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -86,6 +86,7 @@ static string GetVersion() readonly IClusterFactory clusterFactory; readonly CustomCommandManager customCommandManager; + readonly StoreFactory storeFactory; /// /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. @@ -96,13 +97,15 @@ static string GetVersion() /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. /// /// + /// public GarnetServer( IOptions options, ILogger logger, ILoggerFactory loggerFactory, IGarnetServer server, IClusterFactory clusterFactory, - CustomCommandManager customCommandManager) + CustomCommandManager customCommandManager, + StoreFactory storeFactory) { this.server = server; this.opts = options.Value; @@ -110,6 +113,7 @@ public GarnetServer( this.loggerFactory = loggerFactory; this.clusterFactory = clusterFactory; this.customCommandManager = customCommandManager; + this.storeFactory = storeFactory; this.cleanupDir = false; this.InitializeServerUpdated(); @@ -180,8 +184,8 @@ private void InitializeServerUpdated() if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - CreateMainStore(clusterFactory, out var checkpointDir); - CreateObjectStore(clusterFactory, customCommandManager, checkpointDir, out var objectStoreSizeTracker); + this.store = storeFactory.CreateMainStore(out var checkpointDir, out this.kvSettings); + this.objectStore = storeFactory.CreateObjectStore(checkpointDir, out var objectStoreSizeTracker, out this.objKvSettings); if (!opts.DisablePubSub) subscribeBroker = new SubscribeBroker>( diff --git a/libs/host/StoreFactory.cs b/libs/host/StoreFactory.cs new file mode 100644 index 0000000000..fc464e425a --- /dev/null +++ b/libs/host/StoreFactory.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Garnet.server; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +using MainStoreAllocator = + SpanByteAllocator>; +using MainStoreFunctions = StoreFunctions; +using ObjectStoreAllocator = + GenericAllocator>>; +using ObjectStoreFunctions = + StoreFunctions>; + +public class StoreFactory +{ + private readonly IClusterFactory clusterFactory; + private readonly GarnetServerOptions opts; + private readonly ILoggerFactory loggerFactory; + private readonly CustomCommandManager customCommandManager; + + public StoreFactory( + IClusterFactory clusterFactory, + IOptions options, + ILoggerFactory loggerFactory, + CustomCommandManager customCommandManager) + { + this.clusterFactory = options.Value.EnableCluster ? clusterFactory : null; + this.opts = options.Value; + this.loggerFactory = loggerFactory; + this.customCommandManager = customCommandManager; + } + + public TsavoriteKV CreateObjectStore( + string CheckpointDir, out CacheSizeTracker objectStoreSizeTracker, out KVSettings objKvSettings) + { + TsavoriteKV objectStore = null; + objKvSettings = null; + + objectStoreSizeTracker = null; + if (!opts.DisableObjects) + { + objKvSettings = opts.GetObjectStoreSettings(loggerFactory?.CreateLogger("TsavoriteKV [obj]"), + out var objHeapMemorySize, out var objReadCacheHeapMemorySize); + + // Run checkpoint on its own thread to control p99 + objKvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; + objKvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; + + if (opts.EnableCluster) + objKvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager( + opts.DeviceFactoryCreator(), + new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), + isMainStore: false); + else + objKvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager( + opts.DeviceFactoryCreator(), + new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), + removeOutdated: true); + + objectStore = new(objKvSettings + , StoreFunctions.Create(new ByteArrayKeyComparer(), + () => new ByteArrayBinaryObjectSerializer(), + () => new GarnetObjectSerializer(customCommandManager)) + , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); + + if (objHeapMemorySize > 0 || objReadCacheHeapMemorySize > 0) + objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, + objReadCacheHeapMemorySize, + loggerFactory); + } + + return objectStore; + } + + public TsavoriteKV CreateMainStore( + out string checkpointDir, out KVSettings kvSettings) + { + kvSettings = opts.GetSettings(loggerFactory, out var logFactory); + + checkpointDir = opts.CheckpointDir ?? opts.LogDir; + + // Run checkpoint on its own thread to control p99 + kvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; + kvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; + + var checkpointFactory = opts.DeviceFactoryCreator(); + if (opts.EnableCluster) + { + kvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager(checkpointFactory, + new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), isMainStore: true); + } + else + { + kvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(checkpointFactory, + new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), removeOutdated: true); + } + + return new(kvSettings + , StoreFunctions.Create() + , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); + } +} \ No newline at end of file From 8c503e2631ea0ea9d10253b314abafc791cc0004 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 06:15:46 +0100 Subject: [PATCH 11/42] remove unused constructor --- hosting/Windows/Garnet.worker/Worker.cs | 16 ++---- libs/host/GarnetServer.cs | 68 ------------------------- main/GarnetServer/Program.cs | 21 -------- 3 files changed, 4 insertions(+), 101 deletions(-) diff --git a/hosting/Windows/Garnet.worker/Worker.cs b/hosting/Windows/Garnet.worker/Worker.cs index d69adb7e3c..3f96abfe94 100644 --- a/hosting/Windows/Garnet.worker/Worker.cs +++ b/hosting/Windows/Garnet.worker/Worker.cs @@ -22,19 +22,11 @@ public Worker(string[] args) protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - try - { - server = new GarnetServer(args); - - // Start the server - server.Start(); + var builder = GarnetApplication.CreateHostBuilder(args); + + var app = builder.Build(); - await Task.Delay(Timeout.Infinite, stoppingToken).ConfigureAwait(false); - } - catch (Exception ex) - { - Console.WriteLine($"Unable to initialize server due to exception: {ex.Message}"); - } + await app.RunAsync(stoppingToken); } /// diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 65b1c055bc..1d3801ff71 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -227,74 +227,6 @@ private void InitializeServerUpdated() LoadModules(customCommandManager); } - /// - /// Create Garnet Server instance using specified command line arguments; use Start to start the server. - /// - /// Command line arguments - /// Logger factory - /// Clean up directory. - /// Override for custom authentication settings. - public GarnetServer(string[] commandLineArgs, ILoggerFactory loggerFactory = null, bool cleanupDir = false, - IAuthenticationSettings authenticationSettingsOverride = null) - { - Trace.Listeners.Add(new ConsoleTraceListener()); - - // Set up an initial memory logger to log messages from configuration parser into memory. - using (var memLogProvider = new MemoryLoggerProvider()) - { - this.initLogger = (MemoryLogger)memLogProvider.CreateLogger("ArgParser"); - } - - if (!ServerSettingsManager.TryParseCommandLineArguments(commandLineArgs, out var serverSettings, out _, - out var exitGracefully, this.initLogger)) - { - if (exitGracefully) - Environment.Exit(0); - - // Flush logs from memory logger - FlushMemoryLogger(this.initLogger, "ArgParser", loggerFactory); - - throw new GarnetException( - "Encountered an error when initializing Garnet server. Please see log messages above for more details."); - } - - if (loggerFactory == null) - { - // If the main logger factory is created by GarnetServer, it should be disposed when GarnetServer is disposed - disposeLoggerFactory = true; - } - else - { - this.initLogger.LogWarning( - $"Received an external ILoggerFactory object. The following configuration options are ignored: {nameof(serverSettings.FileLogger)}, {nameof(serverSettings.LogLevel)}, {nameof(serverSettings.DisableConsoleLogger)}."); - } - - // If no logger factory is given, set up main logger factory based on parsed configuration values, - // otherwise use given logger factory. - this.loggerFactory = loggerFactory ?? LoggerFactory.Create(builder => - { - if (!serverSettings.DisableConsoleLogger.GetValueOrDefault()) - { - builder.AddSimpleConsole(options => - { - options.SingleLine = true; - options.TimestampFormat = "hh::mm::ss "; - }); - } - - // Optional: Flush log output to file. - if (serverSettings.FileLogger != null) - builder.AddFile(serverSettings.FileLogger); - builder.SetMinimumLevel(serverSettings.LogLevel); - }); - - // Assign values to GarnetServerOptions - this.opts = serverSettings.GetServerOptions(this.loggerFactory.CreateLogger("Options")); - this.opts.AuthSettings = authenticationSettingsOverride ?? this.opts.AuthSettings; - this.cleanupDir = cleanupDir; - this.InitializeServer(); - } - /// /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. /// diff --git a/main/GarnetServer/Program.cs b/main/GarnetServer/Program.cs index 3f94782b50..c38602c693 100644 --- a/main/GarnetServer/Program.cs +++ b/main/GarnetServer/Program.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -using System; -using System.Threading; using Garnet; using Garnet.server; @@ -12,25 +10,6 @@ app.Run(); -/* -try -{ - using var server = new GarnetServer(args); - - // Optional: register custom extensions - RegisterExtensions(server); - - // Start the server - server.Start(); - - Thread.Sleep(Timeout.Infinite); -} -catch (Exception ex) -{ - Console.WriteLine($"Unable to initialize server due to exception: {ex.Message}"); -} -*/ - /// /// Register new commands with the server. You can access these commands from clients using /// commands such as db.Execute in StackExchange.Redis. Example: From edc10be4926324f876d0d160f48240536b94a80b Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 06:35:31 +0100 Subject: [PATCH 12/42] add store wrapper factory --- libs/host/GarnetApplicationBuilder.cs | 1 + libs/host/GarnetServer.cs | 17 ++++-- libs/host/StoreWrapperFactory.cs | 67 ++++++++++++++++++++++ libs/server/StoreWrapper.cs | 80 +++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 libs/host/StoreWrapperFactory.cs diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index e162068872..8846d740eb 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -47,6 +47,7 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 1d3801ff71..f4e78ad8f6 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -87,6 +87,7 @@ static string GetVersion() readonly IClusterFactory clusterFactory; readonly CustomCommandManager customCommandManager; readonly StoreFactory storeFactory; + readonly StoreWrapperFactory storeWrapperFactory; /// /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. @@ -98,6 +99,7 @@ static string GetVersion() /// /// /// + /// public GarnetServer( IOptions options, ILogger logger, @@ -105,7 +107,8 @@ public GarnetServer( IGarnetServer server, IClusterFactory clusterFactory, CustomCommandManager customCommandManager, - StoreFactory storeFactory) + StoreFactory storeFactory, + StoreWrapperFactory storeWrapperFactory) { this.server = server; this.opts = options.Value; @@ -114,6 +117,7 @@ public GarnetServer( this.clusterFactory = clusterFactory; this.customCommandManager = customCommandManager; this.storeFactory = storeFactory; + this.storeWrapperFactory = storeWrapperFactory; this.cleanupDir = false; this.InitializeServerUpdated(); @@ -209,10 +213,15 @@ private void InitializeServerUpdated() logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); } - storeWrapper = new StoreWrapper(version, redisProtocolVersion, server, store, objectStore, + storeWrapper = storeWrapperFactory.Create(version, + server, + store, + objectStore, objectStoreSizeTracker, - customCommandManager, appendOnlyFile, opts, clusterFactory: clusterFactory, - loggerFactory: loggerFactory); + customCommandManager, + appendOnlyFile, + clusterFactory, + loggerFactory); // Create session provider for Garnet Provider = new GarnetProvider(storeWrapper, subscribeBroker); diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/StoreWrapperFactory.cs new file mode 100644 index 0000000000..1dc3ef406b --- /dev/null +++ b/libs/host/StoreWrapperFactory.cs @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using Garnet.cluster; +using Garnet.server; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +using MainStoreAllocator = + SpanByteAllocator>; +using MainStoreFunctions = StoreFunctions; +using ObjectStoreAllocator = + GenericAllocator>>; +using ObjectStoreFunctions = + StoreFunctions>; + +public class StoreWrapperFactory : IDisposable +{ + /// + /// Resp protocol version + /// + readonly string redisProtocolVersion = "7.2.5"; + + readonly StoreFactory storeFactory; + readonly GarnetServerOptions options; + + public StoreWrapperFactory(StoreFactory storeFactory, IOptions options) + { + this.storeFactory = storeFactory; + this.options = options.Value; + } + + public StoreWrapper Create( + string version, + IGarnetServer server, + TsavoriteKV store, + TsavoriteKV objectStore, + CacheSizeTracker objectStoreSizeTracker, + CustomCommandManager customCommandManager, + TsavoriteLog appendOnlyFile, + IClusterFactory clusterFactory, + ILoggerFactory loggerFactory) + { + return new StoreWrapper( + version, + redisProtocolVersion, + server, + store, + objectStore, + objectStoreSizeTracker, + customCommandManager, + appendOnlyFile, + options, + clusterFactory: clusterFactory, + loggerFactory: loggerFactory); + } + + public void Dispose() + { + // TODO release managed resources here + } +} \ No newline at end of file diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index 6da4f7fca5..85c3b37e1c 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -13,6 +13,7 @@ using Garnet.server.ACL; using Garnet.server.Auth.Settings; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Tsavorite.core; namespace Garnet.server @@ -110,7 +111,86 @@ public sealed class StoreWrapper /// NOTE: For now we support only a single database /// public readonly int databaseNum = 1; + + /// + /// Constructor + /// + public StoreWrapper( + string version, + string redisProtocolVersion, + IGarnetServer server, + TsavoriteKV store, + TsavoriteKV objectStore, + CacheSizeTracker objectStoreSizeTracker, + CustomCommandManager customCommandManager, + TsavoriteLog appendOnlyFile, + IOptions options, + AccessControlList accessControlList = null, + IClusterFactory clusterFactory = null, + ILoggerFactory loggerFactory = null + ) + { + this.version = version; + this.redisProtocolVersion = redisProtocolVersion; + this.server = server; + this.startupTime = DateTimeOffset.UtcNow.Ticks; + this.store = store; + this.objectStore = objectStore; + this.appendOnlyFile = appendOnlyFile; + this.serverOptions = options.Value; + lastSaveTime = DateTimeOffset.FromUnixTimeSeconds(0); + this.customCommandManager = customCommandManager; + this.monitor = serverOptions.MetricsSamplingFrequency > 0 ? new GarnetServerMonitor(this, serverOptions, server, loggerFactory?.CreateLogger("GarnetServerMonitor")) : null; + this.objectStoreSizeTracker = objectStoreSizeTracker; + this.loggerFactory = loggerFactory; + this.logger = loggerFactory?.CreateLogger("StoreWrapper"); + this.sessionLogger = loggerFactory?.CreateLogger("Session"); + // TODO Change map size to a reasonable number + this.versionMap = new WatchVersionMap(1 << 16); + this.accessControlList = accessControlList; + this.GarnetObjectSerializer = new GarnetObjectSerializer(this.customCommandManager); + this.loggingFrequncy = TimeSpan.FromSeconds(serverOptions.LoggingFrequency); + if (!serverOptions.DisableObjects) + this.itemBroker = new CollectionItemBroker(); + + // Initialize store scripting cache + if (serverOptions.EnableLua) + this.storeScriptCache = []; + + if (accessControlList == null) + { + // If ACL authentication is enabled, initiate access control list + // NOTE: This is a temporary workflow. ACL should always be initiated and authenticator + // should become a parameter of AccessControlList. + if ((this.serverOptions.AuthSettings != null) && (this.serverOptions.AuthSettings.GetType().BaseType == typeof(AclAuthenticationSettings))) + { + // Create a new access control list and register it with the authentication settings + AclAuthenticationSettings aclAuthenticationSettings = (AclAuthenticationSettings)this.serverOptions.AuthSettings; + + if (!string.IsNullOrEmpty(aclAuthenticationSettings.AclConfigurationFile)) + { + logger?.LogInformation("Reading ACL configuration file '{filepath}'", aclAuthenticationSettings.AclConfigurationFile); + this.accessControlList = new AccessControlList(aclAuthenticationSettings.DefaultPassword, aclAuthenticationSettings.AclConfigurationFile); + } + else + { + // If no configuration file is specified, initiate ACL with default settings + this.accessControlList = new AccessControlList(aclAuthenticationSettings.DefaultPassword); + } + } + else + { + this.accessControlList = new AccessControlList(); + } + } + + if (clusterFactory != null) + clusterProvider = clusterFactory.CreateClusterProvider(this); + ctsCommit = new(); + run_id = Generator.CreateHexId(); + } + /// /// Constructor /// From 6a67bef40d1cb12601b8de0afa5b42ef96016ae2 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 06:55:49 +0100 Subject: [PATCH 13/42] refactor store wrapper factory --- libs/host/GarnetApplicationBuilder.cs | 8 +-- libs/host/GarnetServer.cs | 32 ++---------- libs/host/StoreWrapperFactory.cs | 72 +++++++++++++++++++++++---- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 8846d740eb..a2c26da10a 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -44,10 +44,10 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer }); hostApplicationBuilder.Logging.SetMinimumLevel(garnetServerOptions.LogLevel); - hostApplicationBuilder.Services.AddTransient(); - hostApplicationBuilder.Services.AddTransient(); - hostApplicationBuilder.Services.AddTransient(); - hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddTransient(); diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index f4e78ad8f6..e1f68dbaba 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -85,7 +85,6 @@ static string GetVersion() public StoreApi Store; readonly IClusterFactory clusterFactory; - readonly CustomCommandManager customCommandManager; readonly StoreFactory storeFactory; readonly StoreWrapperFactory storeWrapperFactory; @@ -97,7 +96,6 @@ static string GetVersion() /// Logger factory /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. /// - /// /// /// public GarnetServer( @@ -106,7 +104,6 @@ public GarnetServer( ILoggerFactory loggerFactory, IGarnetServer server, IClusterFactory clusterFactory, - CustomCommandManager customCommandManager, StoreFactory storeFactory, StoreWrapperFactory storeWrapperFactory) { @@ -115,7 +112,6 @@ public GarnetServer( this.logger = logger; this.loggerFactory = loggerFactory; this.clusterFactory = clusterFactory; - this.customCommandManager = customCommandManager; this.storeFactory = storeFactory; this.storeWrapperFactory = storeWrapperFactory; @@ -188,9 +184,6 @@ private void InitializeServerUpdated() if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - this.store = storeFactory.CreateMainStore(out var checkpointDir, out this.kvSettings); - this.objectStore = storeFactory.CreateObjectStore(checkpointDir, out var objectStoreSizeTracker, out this.objKvSettings); - if (!opts.DisablePubSub) subscribeBroker = new SubscribeBroker>( new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, @@ -200,28 +193,15 @@ private void InitializeServerUpdated() logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - if (logger != null) - { - var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + - (store.ReadCache?.MaxMemorySizeBytes ?? 0) + - (appendOnlyFile?.MaxMemorySizeBytes ?? 0); - if (objectStore != null) - configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + - (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + - (objectStoreSizeTracker?.TargetSize ?? 0) + - (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); - logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); - } - storeWrapper = storeWrapperFactory.Create(version, server, - store, - objectStore, - objectStoreSizeTracker, - customCommandManager, appendOnlyFile, clusterFactory, - loggerFactory); + loggerFactory, + out store, + out objectStore, + out kvSettings, + out objKvSettings); // Create session provider for Garnet Provider = new GarnetProvider(storeWrapper, subscribeBroker); @@ -232,8 +212,6 @@ private void InitializeServerUpdated() Store = new StoreApi(storeWrapper); server.Register(WireFormat.ASCII, Provider); - - LoadModules(customCommandManager); } /// diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/StoreWrapperFactory.cs index 1dc3ef406b..299197f23a 100644 --- a/libs/host/StoreWrapperFactory.cs +++ b/libs/host/StoreWrapperFactory.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. using System; +using System.Linq; +using System.Text; using Garnet.cluster; using Garnet.server; using Microsoft.Extensions.Logging; @@ -19,33 +21,61 @@ namespace Garnet; using ObjectStoreFunctions = StoreFunctions>; -public class StoreWrapperFactory : IDisposable +public class StoreWrapperFactory { /// /// Resp protocol version /// readonly string redisProtocolVersion = "7.2.5"; + readonly ILogger logger; readonly StoreFactory storeFactory; readonly GarnetServerOptions options; + readonly CustomCommandManager customCommandManager; - public StoreWrapperFactory(StoreFactory storeFactory, IOptions options) + public StoreWrapperFactory( + ILogger logger, + StoreFactory storeFactory, + IOptions options, + CustomCommandManager customCommandManager) { + this.logger = logger; this.storeFactory = storeFactory; this.options = options.Value; + this.customCommandManager = customCommandManager; } public StoreWrapper Create( string version, IGarnetServer server, - TsavoriteKV store, - TsavoriteKV objectStore, - CacheSizeTracker objectStoreSizeTracker, - CustomCommandManager customCommandManager, TsavoriteLog appendOnlyFile, IClusterFactory clusterFactory, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + out TsavoriteKV store, + out TsavoriteKV objectStore, + out KVSettings kvSettings, + out KVSettings objKvSettings) { + + store = storeFactory.CreateMainStore(out var checkpointDir, out kvSettings); + objectStore = storeFactory.CreateObjectStore(checkpointDir, out var objectStoreSizeTracker, out objKvSettings); + + var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); + if (objectStore != null) + { + + configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + + (objectStoreSizeTracker?.TargetSize ?? 0) + + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); + } + + logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); + + LoadModules(); + return new StoreWrapper( version, redisProtocolVersion, @@ -59,9 +89,31 @@ public StoreWrapper Create( clusterFactory: clusterFactory, loggerFactory: loggerFactory); } - - public void Dispose() + + + private void LoadModules() { - // TODO release managed resources here + if (options.LoadModuleCS == null) + return; + + foreach (var moduleCS in options.LoadModuleCS) + { + var moduleCSData = moduleCS.Split(' ', StringSplitOptions.RemoveEmptyEntries); + if (moduleCSData.Length < 1) + continue; + + var modulePath = moduleCSData[0]; + var moduleArgs = moduleCSData.Length > 1 ? moduleCSData.Skip(1).ToArray() : []; + if (ModuleUtils.LoadAssemblies([modulePath], null, true, out var loadedAssemblies, out var errorMsg)) + { + ModuleRegistrar.Instance.LoadModule(customCommandManager, loadedAssemblies.ToList()[0], moduleArgs, + logger, out errorMsg); + } + else + { + logger?.LogError("Module {0} failed to load with error {1}", modulePath, + Encoding.UTF8.GetString(errorMsg)); + } + } } } \ No newline at end of file From 83d4d6ce360276cfeb0f7b6910f55e21e9f733ad Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 07:06:59 +0100 Subject: [PATCH 14/42] make HyperLogLogTests work with garnet application builder --- libs/server/StoreWrapper.cs | 2 +- test/Garnet.test/HyperLogLogTests.cs | 53 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index 85c3b37e1c..2aa601a4be 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -27,7 +27,7 @@ namespace Garnet.server /// /// Wrapper for store and store-specific information /// - public sealed class StoreWrapper + public sealed class StoreWrapper : IDisposable { internal readonly string version; internal readonly string redisProtocolVersion; diff --git a/test/Garnet.test/HyperLogLogTests.cs b/test/Garnet.test/HyperLogLogTests.cs index 646cfd86d4..1af5ebd030 100644 --- a/test/Garnet.test/HyperLogLogTests.cs +++ b/test/Garnet.test/HyperLogLogTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -12,24 +13,24 @@ namespace Garnet.test { - public unsafe class HyperLogLogTests + public class HyperLogLogTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); r = new Random(674386); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -329,7 +330,7 @@ private static unsafe ulong MurmurHash2x64A(byte* bString, int len, uint seed = [Test] [Repeat(1)] - public void HyperLogLogUpdateReturnTest() + public unsafe void HyperLogLogUpdateReturnTest() { using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -387,7 +388,7 @@ private void RandomString(ref byte[] valuebuffer) [Test] [Repeat(1)] - public void HyperLogLogMultiValueUpdateReturnTest() + public unsafe void HyperLogLogMultiValueUpdateReturnTest() { using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -573,21 +574,21 @@ public void HyperLogLogTestPFADDV2() [TestCase(32)] [TestCase(4096)] [Repeat(1)] - public void HyperLogLogPFADD_LTM(int seqSize) + public async Task HyperLogLogPFADD_LTM(int seqSize) { bool sparse = seqSize < 128 ? true : false; - server.Dispose(); + await server.StopAsync(); if (seqSize < 128) - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "1024", PageSize: "512"); else - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "32k", PageSize: "16k"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -693,14 +694,14 @@ public void HyperLogLogTestPFMERGE_SparseToSparseV2() [Test] [Repeat(10)] - public void HyperLogLogTestPFMERGE_LTM_SparseToSparse() + public async Task HyperLogLogTestPFMERGE_LTM_SparseToSparse() { - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "1024", PageSize: "512"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -803,13 +804,13 @@ public void HyperLogLogTestPFMERGE_SparseToDenseV2() [TestCase(false)] [TestCase(true)] [Repeat(1)] - public void HyperLogLogTestPFMERGE_LTM_SparseToDense(bool reverse) + public async Task HyperLogLogTestPFMERGE_LTM_SparseToDense(bool reverse) { - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "32k", PageSize: "16k"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -912,14 +913,14 @@ public void HyperLogLogTestPFMERGE_DenseToDenseV2() [Test] [Repeat(1)] - public void HyperLogLogTestPFMERGE_LTM_DenseToDense() + public async Task HyperLogLogTestPFMERGE_LTM_DenseToDense() { - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "32k", PageSize: "16k"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); From 6a8165c2d7cfca81631f28db403dd2f2a15431d0 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 07:50:47 +0100 Subject: [PATCH 15/42] add main store and object store wrappers to di --- libs/host/GarnetApplicationBuilder.cs | 30 +++++++++-- libs/host/GarnetServer.cs | 31 ++++-------- libs/host/MainStoreWrapper.cs | 32 ++++++++++++ libs/host/ObjectStoreWrapper.cs | 39 ++++++++++++++ libs/host/StoreFactory.cs | 73 ++++++++++++++++++++++++++- libs/host/StoreWrapperFactory.cs | 57 +++++++++++++++++++-- 6 files changed, 231 insertions(+), 31 deletions(-) create mode 100644 libs/host/MainStoreWrapper.cs create mode 100644 libs/host/ObjectStoreWrapper.cs diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index a2c26da10a..0acc571dbc 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -44,10 +44,34 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer }); hostApplicationBuilder.Logging.SetMinimumLevel(garnetServerOptions.LogLevel); - hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddSingleton(); - hostApplicationBuilder.Services.AddSingleton(); - hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var storeFactory = sp.GetRequiredService(); + + return storeFactory.CreateMainStore(); + }); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var storeFactory = sp.GetRequiredService(); + + return storeFactory.CreateObjectStore(); + }); + + /* + hostApplicationBuilder.Services.AddSingleton(sp => + { + var storeWrapperFactory = sp.GetRequiredService(); + + return storeWrapperFactory.Create(); + }); + */ hostApplicationBuilder.Services.AddTransient(); diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index e1f68dbaba..1a6cfd8d20 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -84,8 +84,6 @@ static string GetVersion() /// public StoreApi Store; - readonly IClusterFactory clusterFactory; - readonly StoreFactory storeFactory; readonly StoreWrapperFactory storeWrapperFactory; /// @@ -103,16 +101,12 @@ public GarnetServer( ILogger logger, ILoggerFactory loggerFactory, IGarnetServer server, - IClusterFactory clusterFactory, - StoreFactory storeFactory, StoreWrapperFactory storeWrapperFactory) { this.server = server; this.opts = options.Value; this.logger = logger; this.loggerFactory = loggerFactory; - this.clusterFactory = clusterFactory; - this.storeFactory = storeFactory; this.storeWrapperFactory = storeWrapperFactory; this.cleanupDir = false; @@ -137,8 +131,6 @@ private void InitializeServerUpdated() {normal}"); } - var clusterFactory = opts.EnableCluster ? this.clusterFactory : null; - logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); @@ -193,16 +185,11 @@ private void InitializeServerUpdated() logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - storeWrapper = storeWrapperFactory.Create(version, - server, + storeWrapper = storeWrapperFactory.Create(version, + server, appendOnlyFile, - clusterFactory, - loggerFactory, - out store, - out objectStore, - out kvSettings, - out objKvSettings); - + loggerFactory); + // Create session provider for Garnet Provider = new GarnetProvider(storeWrapper, subscribeBroker); @@ -501,15 +488,15 @@ private void InternalDispose() Provider?.Dispose(); server.Dispose(); subscribeBroker?.Dispose(); - store.Dispose(); + store?.Dispose(); appendOnlyFile?.Dispose(); aofDevice?.Dispose(); - kvSettings.LogDevice?.Dispose(); + kvSettings?.LogDevice?.Dispose(); if (!opts.DisableObjects) { - objectStore.Dispose(); - objKvSettings.LogDevice?.Dispose(); - objKvSettings.ObjectLogDevice?.Dispose(); + objectStore?.Dispose(); + objKvSettings?.LogDevice?.Dispose(); + objKvSettings?.ObjectLogDevice?.Dispose(); } opts.AuthSettings?.Dispose(); diff --git a/libs/host/MainStoreWrapper.cs b/libs/host/MainStoreWrapper.cs new file mode 100644 index 0000000000..e2071fd8f3 --- /dev/null +++ b/libs/host/MainStoreWrapper.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using Tsavorite.core; + +namespace Garnet; + +using MainStoreAllocator = + SpanByteAllocator>; +using MainStoreFunctions = StoreFunctions; + +public class MainStoreWrapper : IDisposable +{ + public readonly TsavoriteKV store; + + readonly KVSettings kvSettings; + + public MainStoreWrapper(TsavoriteKV store, + KVSettings kvSettings) + { + this.store = store; + this.kvSettings = kvSettings; + } + + public void Dispose() + { + store?.Dispose(); + kvSettings?.LogDevice?.Dispose(); + kvSettings?.Dispose(); + } +} \ No newline at end of file diff --git a/libs/host/ObjectStoreWrapper.cs b/libs/host/ObjectStoreWrapper.cs new file mode 100644 index 0000000000..1230756d27 --- /dev/null +++ b/libs/host/ObjectStoreWrapper.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using Garnet.server; +using Tsavorite.core; + +namespace Garnet; + +using ObjectStoreAllocator = + GenericAllocator>>; +using ObjectStoreFunctions = + StoreFunctions>; + +public class ObjectStoreWrapper : IDisposable +{ + public readonly TsavoriteKV objectStore; + readonly KVSettings objKvSettings; + public readonly CacheSizeTracker objectStoreSizeTracker; + + public ObjectStoreWrapper( + TsavoriteKV objectStore, + KVSettings objKvSettings, + CacheSizeTracker objectStoreSizeTracker) + { + this.objectStore = objectStore; + this.objKvSettings = objKvSettings; + this.objectStoreSizeTracker = objectStoreSizeTracker; + } + + public void Dispose() + { + objectStore?.Dispose(); + objKvSettings?.LogDevice?.Dispose(); + objKvSettings?.ObjectLogDevice?.Dispose(); + objKvSettings?.Dispose(); + } +} \ No newline at end of file diff --git a/libs/host/StoreFactory.cs b/libs/host/StoreFactory.cs index fc464e425a..3c4dbacd1d 100644 --- a/libs/host/StoreFactory.cs +++ b/libs/host/StoreFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System; using Garnet.server; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -17,7 +18,7 @@ namespace Garnet; using ObjectStoreFunctions = StoreFunctions>; -public class StoreFactory +public class StoreFactory { private readonly IClusterFactory clusterFactory; private readonly GarnetServerOptions opts; @@ -105,4 +106,74 @@ public TsavoriteKV C , StoreFunctions.Create() , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); } + + public MainStoreWrapper CreateMainStore() + { + var kvSettings = opts.GetSettings(loggerFactory, out var logFactory); + + var checkpointDir = opts.CheckpointDir ?? opts.LogDir; + + // Run checkpoint on its own thread to control p99 + kvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; + kvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; + + var checkpointFactory = opts.DeviceFactoryCreator(); + if (opts.EnableCluster) + { + kvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager(checkpointFactory, + new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), isMainStore: true); + } + else + { + kvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(checkpointFactory, + new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), removeOutdated: true); + } + + return new (new(kvSettings + , StoreFunctions.Create() + , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)), kvSettings); + } + + public ObjectStoreWrapper CreateObjectStore() + { + TsavoriteKV objectStore = null; + KVSettings objKvSettings = null; + CacheSizeTracker objectStoreSizeTracker = null; + + if (!opts.DisableObjects) + { + var checkpointDir = opts.CheckpointDir ?? opts.LogDir; + + objKvSettings = opts.GetObjectStoreSettings(loggerFactory?.CreateLogger("TsavoriteKV [obj]"), + out var objHeapMemorySize, out var objReadCacheHeapMemorySize); + + // Run checkpoint on its own thread to control p99 + objKvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; + objKvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; + + if (opts.EnableCluster) + objKvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager( + opts.DeviceFactoryCreator(), + new DefaultCheckpointNamingScheme(checkpointDir + "/ObjectStore/checkpoints"), + isMainStore: false); + else + objKvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager( + opts.DeviceFactoryCreator(), + new DefaultCheckpointNamingScheme(checkpointDir + "/ObjectStore/checkpoints"), + removeOutdated: true); + + objectStore = new(objKvSettings + , StoreFunctions.Create(new ByteArrayKeyComparer(), + () => new ByteArrayBinaryObjectSerializer(), + () => new GarnetObjectSerializer(customCommandManager)) + , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); + + if (objHeapMemorySize > 0 || objReadCacheHeapMemorySize > 0) + objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, + objReadCacheHeapMemorySize, + loggerFactory); + } + + return new(objectStore, objKvSettings, objectStoreSizeTracker); + } } \ No newline at end of file diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/StoreWrapperFactory.cs index 299197f23a..9bd10ebe59 100644 --- a/libs/host/StoreWrapperFactory.cs +++ b/libs/host/StoreWrapperFactory.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using System.Text; -using Garnet.cluster; using Garnet.server; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -32,24 +31,73 @@ public class StoreWrapperFactory readonly StoreFactory storeFactory; readonly GarnetServerOptions options; readonly CustomCommandManager customCommandManager; + readonly IClusterFactory clusterFactory; + readonly MainStoreWrapper mainStoreWrapper; + readonly ObjectStoreWrapper objectStoreWrapper; public StoreWrapperFactory( ILogger logger, StoreFactory storeFactory, IOptions options, - CustomCommandManager customCommandManager) + CustomCommandManager customCommandManager, + IClusterFactory clusterFactory, + MainStoreWrapper mainStoreWrapper, + ObjectStoreWrapper objectStoreWrapper) { this.logger = logger; this.storeFactory = storeFactory; this.options = options.Value; - this.customCommandManager = customCommandManager; + this.customCommandManager = customCommandManager; + this.clusterFactory = this.options.EnableCluster ? clusterFactory : null; + this.mainStoreWrapper = mainStoreWrapper; + this.objectStoreWrapper = objectStoreWrapper; + } + + public StoreWrapper Create( + string version, + IGarnetServer server, + TsavoriteLog appendOnlyFile, + ILoggerFactory loggerFactory) + { + var store = mainStoreWrapper.store; + var objectStore = objectStoreWrapper.objectStore; + + var objectStoreSizeTracker = objectStoreWrapper.objectStoreSizeTracker; + + var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); + if (objectStore != null) + { + + configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + + (objectStoreSizeTracker?.TargetSize ?? 0) + + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); + } + + logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); + + LoadModules(); + + return new StoreWrapper( + version, + redisProtocolVersion, + server, + store, + objectStore, + objectStoreSizeTracker, + customCommandManager, + appendOnlyFile, + options, + clusterFactory: clusterFactory, + loggerFactory: loggerFactory); } public StoreWrapper Create( string version, IGarnetServer server, TsavoriteLog appendOnlyFile, - IClusterFactory clusterFactory, ILoggerFactory loggerFactory, out TsavoriteKV store, out TsavoriteKV objectStore, @@ -90,7 +138,6 @@ public StoreWrapper Create( loggerFactory: loggerFactory); } - private void LoadModules() { if (options.LoadModuleCS == null) From 3af03794342265be0294d99aa6e477eb5a1a12d7 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 08:02:58 +0100 Subject: [PATCH 16/42] add aof wrapper --- libs/host/AppendOnlyFileWrapper.cs | 25 ++++++++++++++++++ libs/host/GarnetApplicationBuilder.cs | 37 +++++++++++++++++++++++++++ libs/host/GarnetServer.cs | 12 ++++----- 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 libs/host/AppendOnlyFileWrapper.cs diff --git a/libs/host/AppendOnlyFileWrapper.cs b/libs/host/AppendOnlyFileWrapper.cs new file mode 100644 index 0000000000..2b6d461eb6 --- /dev/null +++ b/libs/host/AppendOnlyFileWrapper.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using Tsavorite.core; + +namespace Garnet; + +public class AppendOnlyFileWrapper : IDisposable +{ + readonly IDevice device; + public readonly TsavoriteLog appendOnlyFile; + + public AppendOnlyFileWrapper(IDevice device, TsavoriteLog appendOnlyFile) + { + this.device = device; + this.appendOnlyFile = appendOnlyFile; + } + + public void Dispose() + { + device?.Dispose(); + appendOnlyFile?.Dispose(); + } +} \ No newline at end of file diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 0acc571dbc..5a834690dc 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -10,6 +10,8 @@ using Microsoft.Extensions.Diagnostics.Metrics; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; namespace Garnet; @@ -49,6 +51,41 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var loggerFactory = sp.GetService(); + + var options = sp.GetRequiredService>(); + var opts = options.Value; + + var appendOnlyFileWrapper = new AppendOnlyFileWrapper(null, null); + + if (opts.EnableAOF) + { + if (opts.MainMemoryReplication && opts.CommitFrequencyMs != -1) + throw new Exception( + "Need to set CommitFrequencyMs to -1 (manual commits) with MainMemoryReplication"); + + opts.GetAofSettings(out var aofSettings); + + var aofDevice = aofSettings.LogDevice; + var appendOnlyFile = new TsavoriteLog(aofSettings, + logger: loggerFactory?.CreateLogger("TsavoriteLog [aof]")); + + appendOnlyFileWrapper = new AppendOnlyFileWrapper(aofDevice, appendOnlyFile); + + if (opts.CommitFrequencyMs < 0 && opts.WaitForCommit) + throw new Exception("Cannot use CommitWait with manual commits"); + + return appendOnlyFileWrapper; + } + + if (opts.CommitFrequencyMs != 0 || opts.WaitForCommit) + throw new Exception("Cannot use CommitFrequencyMs or CommitWait without EnableAOF"); + + return appendOnlyFileWrapper; + }); hostApplicationBuilder.Services.AddSingleton(sp => { diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 1a6cfd8d20..c40b48c3c4 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -85,6 +85,7 @@ static string GetVersion() public StoreApi Store; readonly StoreWrapperFactory storeWrapperFactory; + readonly AppendOnlyFileWrapper appendOnlyFileWrapper; /// /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. @@ -93,21 +94,22 @@ static string GetVersion() /// Logger /// Logger factory /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. - /// - /// /// + /// public GarnetServer( IOptions options, ILogger logger, ILoggerFactory loggerFactory, IGarnetServer server, - StoreWrapperFactory storeWrapperFactory) + StoreWrapperFactory storeWrapperFactory, + AppendOnlyFileWrapper appendOnlyFileWrapper) { this.server = server; this.opts = options.Value; this.logger = logger; this.loggerFactory = loggerFactory; this.storeWrapperFactory = storeWrapperFactory; + this.appendOnlyFileWrapper = appendOnlyFileWrapper; this.cleanupDir = false; this.InitializeServerUpdated(); @@ -181,13 +183,11 @@ private void InitializeServerUpdated() new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, true); - CreateAOF(); - logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); storeWrapper = storeWrapperFactory.Create(version, server, - appendOnlyFile, + appendOnlyFileWrapper.appendOnlyFile, loggerFactory); // Create session provider for Garnet From 58becd1e0d97e230d0f9b6ccdeef336639c746c5 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 08:07:39 +0100 Subject: [PATCH 17/42] refator --- libs/host/GarnetServer.cs | 11 ++--------- libs/host/StoreWrapperFactory.cs | 14 +++++++++----- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index c40b48c3c4..1cd4e0637a 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -85,7 +85,6 @@ static string GetVersion() public StoreApi Store; readonly StoreWrapperFactory storeWrapperFactory; - readonly AppendOnlyFileWrapper appendOnlyFileWrapper; /// /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. @@ -95,21 +94,18 @@ static string GetVersion() /// Logger factory /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. /// - /// public GarnetServer( IOptions options, ILogger logger, ILoggerFactory loggerFactory, IGarnetServer server, - StoreWrapperFactory storeWrapperFactory, - AppendOnlyFileWrapper appendOnlyFileWrapper) + StoreWrapperFactory storeWrapperFactory) { this.server = server; this.opts = options.Value; this.logger = logger; this.loggerFactory = loggerFactory; this.storeWrapperFactory = storeWrapperFactory; - this.appendOnlyFileWrapper = appendOnlyFileWrapper; this.cleanupDir = false; this.InitializeServerUpdated(); @@ -185,10 +181,7 @@ private void InitializeServerUpdated() logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - storeWrapper = storeWrapperFactory.Create(version, - server, - appendOnlyFileWrapper.appendOnlyFile, - loggerFactory); + storeWrapper = storeWrapperFactory.Create(version, server); // Create session provider for Garnet Provider = new GarnetProvider(storeWrapper, subscribeBroker); diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/StoreWrapperFactory.cs index 9bd10ebe59..7c632fdd47 100644 --- a/libs/host/StoreWrapperFactory.cs +++ b/libs/host/StoreWrapperFactory.cs @@ -27,6 +27,7 @@ public class StoreWrapperFactory /// readonly string redisProtocolVersion = "7.2.5"; + readonly ILoggerFactory loggerFactory; readonly ILogger logger; readonly StoreFactory storeFactory; readonly GarnetServerOptions options; @@ -34,16 +35,20 @@ public class StoreWrapperFactory readonly IClusterFactory clusterFactory; readonly MainStoreWrapper mainStoreWrapper; readonly ObjectStoreWrapper objectStoreWrapper; + readonly AppendOnlyFileWrapper appendOnlyFileWrapper; public StoreWrapperFactory( + ILoggerFactory loggerFactory, ILogger logger, StoreFactory storeFactory, IOptions options, CustomCommandManager customCommandManager, IClusterFactory clusterFactory, MainStoreWrapper mainStoreWrapper, - ObjectStoreWrapper objectStoreWrapper) + ObjectStoreWrapper objectStoreWrapper, + AppendOnlyFileWrapper appendOnlyFileWrapper) { + this.loggerFactory = loggerFactory; this.logger = logger; this.storeFactory = storeFactory; this.options = options.Value; @@ -51,16 +56,16 @@ public StoreWrapperFactory( this.clusterFactory = this.options.EnableCluster ? clusterFactory : null; this.mainStoreWrapper = mainStoreWrapper; this.objectStoreWrapper = objectStoreWrapper; + this.appendOnlyFileWrapper = appendOnlyFileWrapper; } public StoreWrapper Create( string version, - IGarnetServer server, - TsavoriteLog appendOnlyFile, - ILoggerFactory loggerFactory) + IGarnetServer server) { var store = mainStoreWrapper.store; var objectStore = objectStoreWrapper.objectStore; + var appendOnlyFile = appendOnlyFileWrapper.appendOnlyFile; var objectStoreSizeTracker = objectStoreWrapper.objectStoreSizeTracker; @@ -98,7 +103,6 @@ public StoreWrapper Create( string version, IGarnetServer server, TsavoriteLog appendOnlyFile, - ILoggerFactory loggerFactory, out TsavoriteKV store, out TsavoriteKV objectStore, out KVSettings kvSettings, From 05cb522233c744b1bc547db4cc460239080e30e5 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 08:41:29 +0100 Subject: [PATCH 18/42] register provider, metrics, registration and store api to di --- libs/host/GarnetApplicationBuilder.cs | 39 ++++++++++++++++++++++++--- libs/host/GarnetProviderFactory.cs | 36 +++++++++++++++++++++++++ libs/host/GarnetServer.cs | 34 +++++++++-------------- libs/host/StoreWrapperFactory.cs | 9 ++++--- libs/server/StoreWrapper.cs | 2 +- 5 files changed, 90 insertions(+), 30 deletions(-) create mode 100644 libs/host/GarnetProviderFactory.cs diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 5a834690dc..b1c9c5db55 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Reflection; using Garnet.cluster; +using Garnet.common; using Garnet.server; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -101,16 +103,38 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer return storeFactory.CreateObjectStore(); }); - /* + hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var options = sp.GetRequiredService>(); + var opts = options.Value; + + return new SubscribeBroker>( + new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, true); + }); + hostApplicationBuilder.Services.AddSingleton(sp => { var storeWrapperFactory = sp.GetRequiredService(); - return storeWrapperFactory.Create(); + var version = GetVersion(); + + return storeWrapperFactory.Create(version); }); - */ - hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var garnetProviderFactory = sp.GetRequiredService(); + + return garnetProviderFactory.Create(); + }); + + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddTransient(); @@ -171,4 +195,11 @@ public IMetricsBuilder Metrics public IServiceCollection Services => hostApplicationBuilder.Services; + + + static string GetVersion() + { + var Version = Assembly.GetExecutingAssembly().GetName().Version; + return $"{Version.Major}.{Version.Minor}.{Version.Build}"; + } } \ No newline at end of file diff --git a/libs/host/GarnetProviderFactory.cs b/libs/host/GarnetProviderFactory.cs new file mode 100644 index 0000000000..433d93c16b --- /dev/null +++ b/libs/host/GarnetProviderFactory.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Garnet.common; +using Garnet.server; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +public class GarnetProviderFactory +{ + readonly GarnetServerOptions options; + readonly SubscribeBroker> subscribeBroker; + readonly StoreWrapper storeWrapper; + + public GarnetProviderFactory( + IOptions options, + SubscribeBroker> subscribeBroker, + StoreWrapper storeWrapper) + { + this.options = options.Value; + this.subscribeBroker = subscribeBroker; + this.storeWrapper = storeWrapper; + } + + public GarnetProvider Create() + { + if (options.DisablePubSub) + { + return new GarnetProvider(storeWrapper, null); + } + + return new GarnetProvider(storeWrapper, subscribeBroker); + } +} \ No newline at end of file diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 1cd4e0637a..5f7db84510 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -84,8 +84,6 @@ static string GetVersion() /// public StoreApi Store; - readonly StoreWrapperFactory storeWrapperFactory; - /// /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. /// @@ -93,19 +91,28 @@ static string GetVersion() /// Logger /// Logger factory /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. - /// + /// + /// + /// + /// public GarnetServer( IOptions options, ILogger logger, ILoggerFactory loggerFactory, - IGarnetServer server, - StoreWrapperFactory storeWrapperFactory) + IGarnetServer server, + GarnetProvider garnetProvider, + MetricsApi metricsApi, + RegisterApi registerApi, + StoreApi storeApi) { this.server = server; this.opts = options.Value; this.logger = logger; this.loggerFactory = loggerFactory; - this.storeWrapperFactory = storeWrapperFactory; + this.Provider = garnetProvider; + this.Metrics = metricsApi; + this.Register = registerApi; + this.Store = storeApi; this.cleanupDir = false; this.InitializeServerUpdated(); @@ -174,23 +181,8 @@ private void InitializeServerUpdated() if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - if (!opts.DisablePubSub) - subscribeBroker = new SubscribeBroker>( - new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, - true); - logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - storeWrapper = storeWrapperFactory.Create(version, server); - - // Create session provider for Garnet - Provider = new GarnetProvider(storeWrapper, subscribeBroker); - - // Create user facing API endpoints - Metrics = new MetricsApi(Provider); - Register = new RegisterApi(Provider); - Store = new StoreApi(storeWrapper); - server.Register(WireFormat.ASCII, Provider); } diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/StoreWrapperFactory.cs index 7c632fdd47..1634e1e1ca 100644 --- a/libs/host/StoreWrapperFactory.cs +++ b/libs/host/StoreWrapperFactory.cs @@ -29,6 +29,7 @@ public class StoreWrapperFactory readonly ILoggerFactory loggerFactory; readonly ILogger logger; + readonly IGarnetServer garnetServer; readonly StoreFactory storeFactory; readonly GarnetServerOptions options; readonly CustomCommandManager customCommandManager; @@ -40,6 +41,7 @@ public class StoreWrapperFactory public StoreWrapperFactory( ILoggerFactory loggerFactory, ILogger logger, + IGarnetServer garnetServer, StoreFactory storeFactory, IOptions options, CustomCommandManager customCommandManager, @@ -50,6 +52,7 @@ public StoreWrapperFactory( { this.loggerFactory = loggerFactory; this.logger = logger; + this.garnetServer = garnetServer; this.storeFactory = storeFactory; this.options = options.Value; this.customCommandManager = customCommandManager; @@ -59,9 +62,7 @@ public StoreWrapperFactory( this.appendOnlyFileWrapper = appendOnlyFileWrapper; } - public StoreWrapper Create( - string version, - IGarnetServer server) + public StoreWrapper Create(string version) { var store = mainStoreWrapper.store; var objectStore = objectStoreWrapper.objectStore; @@ -88,7 +89,7 @@ public StoreWrapper Create( return new StoreWrapper( version, redisProtocolVersion, - server, + garnetServer, store, objectStore, objectStoreSizeTracker, diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index 2aa601a4be..a7af022440 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -27,7 +27,7 @@ namespace Garnet.server /// /// Wrapper for store and store-specific information /// - public sealed class StoreWrapper : IDisposable + public sealed class StoreWrapper { internal readonly string version; internal readonly string redisProtocolVersion; From c9f752ab507658a7e3fde3220e57e487b88f59e8 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 08:44:04 +0100 Subject: [PATCH 19/42] exposes metrics, registration and store apis in GarnetApplication --- libs/host/GarnetApplicatrion.cs | 19 ++++++++++++++++++- main/GarnetServer/Program.cs | 4 +++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs index 22a030b58d..5f31de86dc 100644 --- a/libs/host/GarnetApplicatrion.cs +++ b/libs/host/GarnetApplicatrion.cs @@ -6,17 +6,34 @@ using System.Threading.Tasks; using Garnet.common; using Garnet.server; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Garnet; public class GarnetApplication : IHost { + public MetricsApi Metrics + { + get + { + return host.Services.GetRequiredService(); + } + } + public RegisterApi Register { get { - throw new NotImplementedException(); + return host.Services.GetRequiredService(); + } + } + + public StoreApi Store + { + get + { + return host.Services.GetRequiredService(); } } diff --git a/main/GarnetServer/Program.cs b/main/GarnetServer/Program.cs index c38602c693..12d0abe54b 100644 --- a/main/GarnetServer/Program.cs +++ b/main/GarnetServer/Program.cs @@ -8,6 +8,8 @@ var app = builder.Build(); +RegisterExtensions(app); + app.Run(); /// @@ -15,7 +17,7 @@ /// commands such as db.Execute in StackExchange.Redis. Example: /// db.Execute("SETIFPM", key, value, prefix); /// -static void RegisterExtensions(GarnetServer server) +static void RegisterExtensions(GarnetApplication server) { // Register custom command on raw strings (SETIFPM = "set if prefix match") // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO From 24a075f60f32a1382f324a717a9a43f47f423a23 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 08:51:59 +0100 Subject: [PATCH 20/42] make more test use the GarnetApplication --- test/Garnet.test/RespSetTest.cs | 12 +++---- test/Garnet.test/RespTests.cs | 54 ++++++++++++++++---------------- test/Garnet.test/RespTlsTests.cs | 12 +++---- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/test/Garnet.test/RespSetTest.cs b/test/Garnet.test/RespSetTest.cs index 59344b462d..d362fd086c 100644 --- a/test/Garnet.test/RespSetTest.cs +++ b/test/Garnet.test/RespSetTest.cs @@ -17,20 +17,20 @@ namespace Garnet.test [TestFixture] public class RespSetTest { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTests.cs b/test/Garnet.test/RespTests.cs index 670b0f4f69..338f12bf5f 100644 --- a/test/Garnet.test/RespTests.cs +++ b/test/Garnet.test/RespTests.cs @@ -20,22 +20,22 @@ namespace Garnet.test [TestFixture] public class RespTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: false); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: false); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -1359,13 +1359,13 @@ public void SingleDelete() } [Test] - public void SingleDeleteWithObjectStoreDisabled() + public async Task SingleDeleteWithObjectStoreDisabled() { TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); var key = "delKey"; var value = "1234"; @@ -1391,13 +1391,13 @@ private string GetRandomString(int len) } [Test] - public void SingleDeleteWithObjectStoreDisable_LTM() + public async Task SingleDeleteWithObjectStoreDisable_LTM() { TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1431,14 +1431,14 @@ public void SingleDeleteWithObjectStoreDisable_LTM() } [Test] - public void MultiKeyDelete([Values] bool withoutObjectStore) + public async Task MultiKeyDelete([Values] bool withoutObjectStore) { if (withoutObjectStore) { TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1499,14 +1499,14 @@ public void MultiKeyDeleteObjectStore() } [Test] - public void MultiKeyUnlink([Values] bool withoutObjectStore) + public async Task MultiKeyUnlink([Values] bool withoutObjectStore) { if (withoutObjectStore) { TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1565,14 +1565,14 @@ public void MultiKeyUnlinkObjectStore() } [Test] - public void SingleExists([Values] bool withoutObjectStore) + public async Task SingleExists([Values] bool withoutObjectStore) { if (withoutObjectStore) { TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1830,14 +1830,14 @@ public void SingleRenameWithExpiry() } [Test] - public void SingleRenameKeyEdgeCase([Values] bool withoutObjectStore) + public async Task SingleRenameKeyEdgeCase([Values] bool withoutObjectStore) { if (withoutObjectStore) { TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -3730,13 +3730,13 @@ public void HelloTest1() } [Test] - public void AsyncTest1() + public async Task AsyncTest1() { // Set up low-memory database TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); + await server.RunAsync(); string firstKey = null, firstValue = null, lastKey = null, lastValue = null; diff --git a/test/Garnet.test/RespTlsTests.cs b/test/Garnet.test/RespTlsTests.cs index 7e61240516..4ec8fb0f5f 100644 --- a/test/Garnet.test/RespTlsTests.cs +++ b/test/Garnet.test/RespTlsTests.cs @@ -17,20 +17,20 @@ namespace Garnet.test [TestFixture] public class RespTlsTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, EnableTLS: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, EnableTLS: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } From 1eb3d3876d1001cd62f4ae8b28b53a4b069ea070 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 08:56:36 +0100 Subject: [PATCH 21/42] refactor and reformat --- hosting/Windows/Garnet.worker/Worker.cs | 2 +- libs/host/AppendOnlyFileWrapper.cs | 2 +- libs/host/GarnetApplicationBuilder.cs | 41 ++++--------------- libs/host/GarnetApplicatrion.cs | 16 ++++---- libs/host/GarnetProviderFactory.cs | 4 +- libs/host/GarnetServer.cs | 12 +++--- libs/host/GarnetServerHostedService.cs | 8 ++-- libs/host/MainStoreWrapper.cs | 4 +- libs/host/ObjectStoreWrapper.cs | 2 +- libs/host/StoreFactory.cs | 22 +++++----- libs/host/StoreWrapperFactory.cs | 54 ++++++++++++------------- libs/server/Servers/GarnetServerTcp.cs | 2 +- libs/server/StoreWrapper.cs | 6 +-- test/Garnet.test/TestUtils.cs | 8 ++-- 14 files changed, 79 insertions(+), 104 deletions(-) diff --git a/hosting/Windows/Garnet.worker/Worker.cs b/hosting/Windows/Garnet.worker/Worker.cs index 3f96abfe94..6afaf69bc8 100644 --- a/hosting/Windows/Garnet.worker/Worker.cs +++ b/hosting/Windows/Garnet.worker/Worker.cs @@ -23,7 +23,7 @@ public Worker(string[] args) protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var builder = GarnetApplication.CreateHostBuilder(args); - + var app = builder.Build(); await app.RunAsync(stoppingToken); diff --git a/libs/host/AppendOnlyFileWrapper.cs b/libs/host/AppendOnlyFileWrapper.cs index 2b6d461eb6..0d83252ba0 100644 --- a/libs/host/AppendOnlyFileWrapper.cs +++ b/libs/host/AppendOnlyFileWrapper.cs @@ -16,7 +16,7 @@ public AppendOnlyFileWrapper(IDevice device, TsavoriteLog appendOnlyFile) this.device = device; this.appendOnlyFile = appendOnlyFile; } - + public void Dispose() { device?.Dispose(); diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index b1c9c5db55..522a4c213d 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -36,7 +36,7 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer }); hostApplicationBuilder.Services.AddOptions(); - + var garnetServerOptionsWrapped = Microsoft.Extensions.Options.Options.Create(garnetServerOptions); hostApplicationBuilder.Services.AddSingleton(garnetServerOptionsWrapped); @@ -47,7 +47,7 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; }); hostApplicationBuilder.Logging.SetMinimumLevel(garnetServerOptions.LogLevel); - + hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); @@ -88,21 +88,21 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer return appendOnlyFileWrapper; }); - + hostApplicationBuilder.Services.AddSingleton(sp => { var storeFactory = sp.GetRequiredService(); return storeFactory.CreateMainStore(); }); - + hostApplicationBuilder.Services.AddSingleton(sp => { var storeFactory = sp.GetRequiredService(); return storeFactory.CreateObjectStore(); }); - + hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddSingleton(sp => @@ -131,39 +131,14 @@ internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServer return garnetProviderFactory.Create(); }); - + hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddTransient(); - - /* - hostApplicationBuilder.Services.AddTransient(sp => - { - var options = sp.GetRequiredService>(); - var loggerFactory = sp.GetRequiredService(); - var server = sp.GetRequiredService(); - var clusterFactory = sp.GetRequiredService(); - var customCommandManager = sp.GetRequiredService(); - - return new GarnetServer(options, loggerFactory, server, clusterFactory, customCommandManager); - }); - */ hostApplicationBuilder.Services.AddHostedService(); - - /* - hostApplicationBuilder.Services.AddHostedService(sp => - { - var loggerFactory = sp.GetRequiredService(); - var logger = loggerFactory.CreateLogger(); - - var server = new GarnetServer(garnetServerOptions, loggerFactory); - - return new GarnetServerHostedService(server, logger); - }); - */ } public GarnetApplication Build() @@ -195,8 +170,8 @@ public IMetricsBuilder Metrics public IServiceCollection Services => hostApplicationBuilder.Services; - - + + static string GetVersion() { var Version = Assembly.GetExecutingAssembly().GetName().Version; diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs index 5f31de86dc..cfb4ce4315 100644 --- a/libs/host/GarnetApplicatrion.cs +++ b/libs/host/GarnetApplicatrion.cs @@ -20,7 +20,7 @@ public MetricsApi Metrics return host.Services.GetRequiredService(); } } - + public RegisterApi Register { get @@ -28,8 +28,8 @@ public RegisterApi Register return host.Services.GetRequiredService(); } } - - public StoreApi Store + + public StoreApi Store { get { @@ -38,16 +38,16 @@ public StoreApi Store } readonly IHost host; - + public GarnetApplication(IHost host) { this.host = host; } - public Task StartAsync(CancellationToken cancellationToken = default) + public Task StartAsync(CancellationToken cancellationToken = default) => host.StartAsync(cancellationToken); - public Task StopAsync(CancellationToken cancellationToken = default) + public Task StopAsync(CancellationToken cancellationToken = default) => host.StopAsync(cancellationToken); public IServiceProvider Services { get => host.Services; } @@ -56,7 +56,7 @@ public void Dispose() { host.Dispose(); } - + public void Run() { HostingAbstractionsHostExtensions.Run(this); @@ -93,7 +93,7 @@ public static GarnetApplicationBuilder CreateHostBuilder(string[] args) var garnetServerOptions = serverSettings.GetServerOptions(null); - return new (new GarnetApplicationOptions {Args = args}, garnetServerOptions); + return new(new GarnetApplicationOptions { Args = args }, garnetServerOptions); } public static GarnetApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) diff --git a/libs/host/GarnetProviderFactory.cs b/libs/host/GarnetProviderFactory.cs index 433d93c16b..90266d0650 100644 --- a/libs/host/GarnetProviderFactory.cs +++ b/libs/host/GarnetProviderFactory.cs @@ -13,7 +13,7 @@ public class GarnetProviderFactory readonly GarnetServerOptions options; readonly SubscribeBroker> subscribeBroker; readonly StoreWrapper storeWrapper; - + public GarnetProviderFactory( IOptions options, SubscribeBroker> subscribeBroker, @@ -30,7 +30,7 @@ public GarnetProvider Create() { return new GarnetProvider(storeWrapper, null); } - + return new GarnetProvider(storeWrapper, subscribeBroker); } } \ No newline at end of file diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 5f7db84510..04a91a60e4 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -83,7 +83,7 @@ static string GetVersion() /// Store API /// public StoreApi Store; - + /// /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. /// @@ -96,9 +96,9 @@ static string GetVersion() /// /// public GarnetServer( - IOptions options, + IOptions options, ILogger logger, - ILoggerFactory loggerFactory, + ILoggerFactory loggerFactory, IGarnetServer server, GarnetProvider garnetProvider, MetricsApi metricsApi, @@ -113,7 +113,7 @@ public GarnetServer( this.Metrics = metricsApi; this.Register = registerApi; this.Store = storeApi; - + this.cleanupDir = false; this.InitializeServerUpdated(); } @@ -458,12 +458,12 @@ public void Dispose(bool deleteDir = true) InternalDispose(); if (deleteDir) { - logFactory?.Delete(new FileDescriptor {directoryName = ""}); + logFactory?.Delete(new FileDescriptor { directoryName = "" }); if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) { var ckptdir = opts.DeviceFactoryCreator(); ckptdir.Initialize(opts.CheckpointDir); - ckptdir.Delete(new FileDescriptor {directoryName = ""}); + ckptdir.Delete(new FileDescriptor { directoryName = "" }); } } } diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index d70e8df8da..0a231a684a 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -10,11 +10,11 @@ namespace Garnet; -public class GarnetServerHostedService : BackgroundService +public class GarnetServerHostedService : BackgroundService { readonly GarnetServer server; readonly ILogger logger; - + public GarnetServerHostedService(GarnetServer server, ILogger logger) { this.server = server; @@ -24,9 +24,9 @@ public GarnetServerHostedService(GarnetServer server, ILogger store; - + public readonly TsavoriteKV store; + readonly KVSettings kvSettings; public MainStoreWrapper(TsavoriteKV store, diff --git a/libs/host/ObjectStoreWrapper.cs b/libs/host/ObjectStoreWrapper.cs index 1230756d27..c9b88f4eb7 100644 --- a/libs/host/ObjectStoreWrapper.cs +++ b/libs/host/ObjectStoreWrapper.cs @@ -18,7 +18,7 @@ public class ObjectStoreWrapper : IDisposable public readonly TsavoriteKV objectStore; readonly KVSettings objKvSettings; public readonly CacheSizeTracker objectStoreSizeTracker; - + public ObjectStoreWrapper( TsavoriteKV objectStore, KVSettings objKvSettings, diff --git a/libs/host/StoreFactory.cs b/libs/host/StoreFactory.cs index 3c4dbacd1d..53a7c5140b 100644 --- a/libs/host/StoreFactory.cs +++ b/libs/host/StoreFactory.cs @@ -18,7 +18,7 @@ namespace Garnet; using ObjectStoreFunctions = StoreFunctions>; -public class StoreFactory +public class StoreFactory { private readonly IClusterFactory clusterFactory; private readonly GarnetServerOptions opts; @@ -26,8 +26,8 @@ public class StoreFactory private readonly CustomCommandManager customCommandManager; public StoreFactory( - IClusterFactory clusterFactory, - IOptions options, + IClusterFactory clusterFactory, + IOptions options, ILoggerFactory loggerFactory, CustomCommandManager customCommandManager) { @@ -42,7 +42,7 @@ public TsavoriteKV objectStore = null; objKvSettings = null; - + objectStoreSizeTracker = null; if (!opts.DisableObjects) { @@ -75,7 +75,7 @@ public TsavoriteKV C , StoreFunctions.Create() , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); } - + public MainStoreWrapper CreateMainStore() { var kvSettings = opts.GetSettings(loggerFactory, out var logFactory); @@ -129,21 +129,21 @@ public MainStoreWrapper CreateMainStore() new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), removeOutdated: true); } - return new (new(kvSettings + return new(new(kvSettings , StoreFunctions.Create() , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)), kvSettings); } - + public ObjectStoreWrapper CreateObjectStore() { TsavoriteKV objectStore = null; KVSettings objKvSettings = null; CacheSizeTracker objectStoreSizeTracker = null; - + if (!opts.DisableObjects) { var checkpointDir = opts.CheckpointDir ?? opts.LogDir; - + objKvSettings = opts.GetObjectStoreSettings(loggerFactory?.CreateLogger("TsavoriteKV [obj]"), out var objHeapMemorySize, out var objReadCacheHeapMemorySize); @@ -173,7 +173,7 @@ public ObjectStoreWrapper CreateObjectStore() objReadCacheHeapMemorySize, loggerFactory); } - + return new(objectStore, objKvSettings, objectStoreSizeTracker); } } \ No newline at end of file diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/StoreWrapperFactory.cs index 1634e1e1ca..acc079150c 100644 --- a/libs/host/StoreWrapperFactory.cs +++ b/libs/host/StoreWrapperFactory.cs @@ -20,13 +20,13 @@ namespace Garnet; using ObjectStoreFunctions = StoreFunctions>; -public class StoreWrapperFactory +public class StoreWrapperFactory { /// /// Resp protocol version /// readonly string redisProtocolVersion = "7.2.5"; - + readonly ILoggerFactory loggerFactory; readonly ILogger logger; readonly IGarnetServer garnetServer; @@ -37,12 +37,12 @@ public class StoreWrapperFactory readonly MainStoreWrapper mainStoreWrapper; readonly ObjectStoreWrapper objectStoreWrapper; readonly AppendOnlyFileWrapper appendOnlyFileWrapper; - + public StoreWrapperFactory( ILoggerFactory loggerFactory, ILogger logger, IGarnetServer garnetServer, - StoreFactory storeFactory, + StoreFactory storeFactory, IOptions options, CustomCommandManager customCommandManager, IClusterFactory clusterFactory, @@ -55,48 +55,48 @@ public StoreWrapperFactory( this.garnetServer = garnetServer; this.storeFactory = storeFactory; this.options = options.Value; - this.customCommandManager = customCommandManager; + this.customCommandManager = customCommandManager; this.clusterFactory = this.options.EnableCluster ? clusterFactory : null; this.mainStoreWrapper = mainStoreWrapper; this.objectStoreWrapper = objectStoreWrapper; this.appendOnlyFileWrapper = appendOnlyFileWrapper; } - + public StoreWrapper Create(string version) { var store = mainStoreWrapper.store; var objectStore = objectStoreWrapper.objectStore; var appendOnlyFile = appendOnlyFileWrapper.appendOnlyFile; - + var objectStoreSizeTracker = objectStoreWrapper.objectStoreSizeTracker; - + var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); if (objectStore != null) { - + configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + (objectStoreSizeTracker?.TargetSize ?? 0) + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); } - + logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); - + LoadModules(); - + return new StoreWrapper( - version, + version, redisProtocolVersion, - garnetServer, + garnetServer, store, objectStore, objectStoreSizeTracker, - customCommandManager, + customCommandManager, appendOnlyFile, options, - clusterFactory: clusterFactory, + clusterFactory: clusterFactory, loggerFactory: loggerFactory); } @@ -109,40 +109,40 @@ public StoreWrapper Create( out KVSettings kvSettings, out KVSettings objKvSettings) { - + store = storeFactory.CreateMainStore(out var checkpointDir, out kvSettings); objectStore = storeFactory.CreateObjectStore(checkpointDir, out var objectStoreSizeTracker, out objKvSettings); - + var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); if (objectStore != null) { - + configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + (objectStoreSizeTracker?.TargetSize ?? 0) + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); } - + logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); - + LoadModules(); - + return new StoreWrapper( - version, + version, redisProtocolVersion, - server, + server, store, objectStore, objectStoreSizeTracker, - customCommandManager, + customCommandManager, appendOnlyFile, options, - clusterFactory: clusterFactory, + clusterFactory: clusterFactory, loggerFactory: loggerFactory); } - + private void LoadModules() { if (options.LoadModuleCS == null) diff --git a/libs/server/Servers/GarnetServerTcp.cs b/libs/server/Servers/GarnetServerTcp.cs index 0045c4db8f..ba8478a779 100644 --- a/libs/server/Servers/GarnetServerTcp.cs +++ b/libs/server/Servers/GarnetServerTcp.cs @@ -61,7 +61,7 @@ public IEnumerable ActiveClusterSessions() yield return ((RespServerSession)consumer).clusterSession; } } - + /// /// Constructor for server /// diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index a7af022440..e45a822faf 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -27,7 +27,7 @@ namespace Garnet.server /// /// Wrapper for store and store-specific information /// - public sealed class StoreWrapper + public sealed class StoreWrapper { internal readonly string version; internal readonly string redisProtocolVersion; @@ -111,7 +111,7 @@ public sealed class StoreWrapper /// NOTE: For now we support only a single database /// public readonly int databaseNum = 1; - + /// /// Constructor /// @@ -190,7 +190,7 @@ public StoreWrapper( ctsCommit = new(); run_id = Generator.CreateHexId(); } - + /// /// Constructor /// diff --git a/test/Garnet.test/TestUtils.cs b/test/Garnet.test/TestUtils.cs index b0bc63960d..4012b810ad 100644 --- a/test/Garnet.test/TestUtils.cs +++ b/test/Garnet.test/TestUtils.cs @@ -339,22 +339,22 @@ public static GarnetApplication CreateGarnetApplication( builder.Logging.AddProvider(new NUnitLoggerProvider(TestContext.Progress, TestContext.CurrentContext.Test.MethodName, null, false, false, LogLevel.Trace)); builder.Logging.SetMinimumLevel(LogLevel.Trace); - + var app = builder.Build(); return app; } else { - + var builder = GarnetApplication.CreateHostBuilder([], opts); - + var app = builder.Build(); return app; } } - + /// /// Create GarnetServer /// From 51475951e02c3c2791bd6bdf9d046f8773a5c5e1 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 10:29:52 +0100 Subject: [PATCH 22/42] add garnet application to more tests --- libs/host/GarnetApplicatrion.cs | 2 + test/Garnet.test/CacheSizeTrackerTests.cs | 17 +-- test/Garnet.test/GarnetClientTests.cs | 59 ++++++--- .../GarnetJSON/JsonCommandsTest.cs | 38 +++--- test/Garnet.test/IndexGrowthTests.cs | 49 ++++--- test/Garnet.test/LuaScriptTests.cs | 12 +- test/Garnet.test/RespAdminCommandsTests.cs | 103 ++++++++------- test/Garnet.test/RespAofAzureTests.cs | 122 ++++++++++-------- 8 files changed, 231 insertions(+), 171 deletions(-) diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs index cfb4ce4315..1c299dbbea 100644 --- a/libs/host/GarnetApplicatrion.cs +++ b/libs/host/GarnetApplicatrion.cs @@ -36,6 +36,8 @@ public StoreApi Store return host.Services.GetRequiredService(); } } + + internal GarnetProvider Provider => host.Services.GetRequiredService(); readonly IHost host; diff --git a/test/Garnet.test/CacheSizeTrackerTests.cs b/test/Garnet.test/CacheSizeTrackerTests.cs index 41dfabddf5..34284e09ad 100644 --- a/test/Garnet.test/CacheSizeTrackerTests.cs +++ b/test/Garnet.test/CacheSizeTrackerTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -17,16 +18,16 @@ namespace Garnet.test [TestFixture] public class CacheSizeTrackerTests { - GarnetServer server; + GarnetApplication server; TsavoriteKV objStore; CacheSizeTracker cacheSizeTracker; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, MemorySize: "2k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreHeapMemorySize: "5k"); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "2k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreHeapMemorySize: "5k"); + await server.RunAsync(); objStore = server.Provider.StoreWrapper.objectStore; cacheSizeTracker = server.Provider.StoreWrapper.objectStoreSizeTracker; } @@ -90,11 +91,11 @@ public void IncreaseEmptyPageCountTest() } [Test] - public void ReadCacheIncreaseEmptyPageCountTest() + public async Task ReadCacheIncreaseEmptyPageCountTest() { - server?.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, MemorySize: "1k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreReadCacheHeapMemorySize: "1k", enableObjectStoreReadCache: true); - server.Start(); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "1k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreReadCacheHeapMemorySize: "1k", enableObjectStoreReadCache: true); + await server.RunAsync(); objStore = server.Provider.StoreWrapper.objectStore; cacheSizeTracker = server.Provider.StoreWrapper.objectStoreSizeTracker; diff --git a/test/Garnet.test/GarnetClientTests.cs b/test/Garnet.test/GarnetClientTests.cs index 56498b2fcc..7cb7032ebe 100644 --- a/test/Garnet.test/GarnetClientTests.cs +++ b/test/Garnet.test/GarnetClientTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Garnet.common; +using Microsoft.Extensions.Hosting; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -117,10 +118,10 @@ static void WaitAndReset(ManualResetEventSlim e) } [Test] - public void SetGetWithCallback([Values] bool useTLS) + public async Task SetGetWithCallback([Values] bool useTLS) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, EnableTLS: useTLS); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, EnableTLS: useTLS); + await server.RunAsync(); using var db = TestUtils.GetGarnetClient(useTLS); db.Connect(); @@ -142,13 +143,15 @@ public void SetGetWithCallback([Values] bool useTLS) e.Set(); }); e.Wait(); + + await server.StopAsync(); } [Test] - public void SimpleMetricsTest([Values] bool recordLatency) + public async Task SimpleMetricsTest([Values] bool recordLatency) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(recordLatency: recordLatency); db.Connect(); @@ -174,13 +177,15 @@ public void SimpleMetricsTest([Values] bool recordLatency) db.Dispose(); metrics = db.GetLatencyMetrics(); ClassicAssert.AreEqual(0, metrics.Length); // Should be 0 after dispose + + await server.StopAsync(); } [Test] public async Task SimpleStringArrayTest([Values] bool stringParams) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -190,13 +195,15 @@ public async Task SimpleStringArrayTest([Values] bool stringParams) int.Parse(await db.ExecuteForStringResultAsync(Encoding.ASCII.GetBytes("$6\r\nINCRBY\r\n"), [Encoding.ASCII.GetBytes("myKey"), Encoding.ASCII.GetBytes("10")])); ClassicAssert.AreEqual(10, n); + + await server.StopAsync(); } [Test] public async Task SimpleNoArgsTest() { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -206,14 +213,16 @@ public async Task SimpleNoArgsTest() result = await db.ExecuteForStringResultAsync("ASKING"); ClassicAssert.AreEqual("OK", result); + + await server.StopAsync(); } [Test] public async Task SimpleIncrTest([Values] bool stringParams) { ManualResetEventSlim e = new(); - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var key = "mykey"; var db = TestUtils.GetGarnetClient(); @@ -268,14 +277,16 @@ public async Task SimpleIncrTest([Values] bool stringParams) }); } WaitAndReset(e); + + await server.StopAsync(); } [Test] public async Task SimpleDecrTest([Values] bool stringParams) { ManualResetEventSlim e = new(); - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var key = "mykey"; var db = TestUtils.GetGarnetClient(); @@ -330,13 +341,15 @@ public async Task SimpleDecrTest([Values] bool stringParams) }); } WaitAndReset(e); + + await server.StopAsync(); } [Test] public async Task CanUseSetNxStringResultAsync() { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -349,13 +362,15 @@ public async Task CanUseSetNxStringResultAsync() var resultMykey = await db.StringGetAsync("mykey"); ClassicAssert.AreEqual("Hello", resultMykey); + + await server.StopAsync(); } [Test] public async Task CanUseMGetTests([Values] bool disableObjectStore) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObjectStore); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObjectStore); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -416,6 +431,8 @@ public async Task CanUseMGetTests([Values] bool disableObjectStore) } tokenSource.Dispose(); + + await server.StopAsync(); } private async Task ReadValuesMGet(string[] keys, CancellationToken t) @@ -461,8 +478,8 @@ private void SimpleStringArrayCallback(long context, string[] result, string err public async Task CanDoBulkDeleteTests([Values] bool useStringType) { //KeyDeleteAsync - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -552,6 +569,8 @@ public async Task CanDoBulkDeleteTests([Values] bool useStringType) var result = await db.ExecuteForStringResultAsync("EXISTS", [key]); ClassicAssert.AreEqual("0", result); } + + await server.StopAsync(); } private static async Task DeleteKeysWithCT(string[] keys, Memory[] keysMB, ManualResetEventSlim mreObj, CancellationToken t, bool useMemoryType = false) diff --git a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs index 7ed66c9d36..2249cc1511 100644 --- a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs +++ b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs @@ -5,6 +5,7 @@ using System.IO; using System.Reflection; using System.Threading; +using System.Threading.Tasks; using Garnet.server; using GarnetJSON; using NUnit.Framework; @@ -16,22 +17,22 @@ namespace Garnet.test [TestFixture] class JsonCommandsTest { - GarnetServer server; + GarnetApplication server; string binPath; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); binPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, extensionAllowUnsignedAssemblies: true, extensionBinPaths: [binPath]); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, extensionAllowUnsignedAssemblies: true, extensionBinPaths: [binPath]); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -84,7 +85,7 @@ public void JsonSetGetTests() } [Test] - public void SaveRecoverTest() + public async Task SaveRecoverTest() { string key = "key"; RegisterCustomCommand(); @@ -102,10 +103,11 @@ public void SaveRecoverTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); RegisterCustomCommand(); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -116,12 +118,13 @@ public void SaveRecoverTest() } [Test] - public void AofUpsertRecoverTest() + public async Task AofUpsertRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(); - server.Start(); + await server.RunAsync(); var key = "aofkey"; using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -133,10 +136,11 @@ public void AofUpsertRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { diff --git a/test/Garnet.test/IndexGrowthTests.cs b/test/Garnet.test/IndexGrowthTests.cs index c08d2f90cb..53be339f94 100644 --- a/test/Garnet.test/IndexGrowthTests.cs +++ b/test/Garnet.test/IndexGrowthTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -12,7 +13,7 @@ namespace Garnet.test [TestFixture] public class IndexGrowthTests { - GarnetServer server; + GarnetApplication server; private int indexResizeTaskDelaySeconds = 10; private int indexResizeWaitCycles = 2; @@ -23,17 +24,21 @@ public void Setup() } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + } + TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } [Test] - public void IndexGrowthTest() + public async Task IndexGrowthTest() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, indexSize: "64", indexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, indexSize: "64", indexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var store = server.Provider.StoreWrapper.store; @@ -68,10 +73,10 @@ public void IndexGrowthTest() } [Test] - public void ObjectStoreIndexGrowthTest() + public async Task ObjectStoreIndexGrowthTest() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "64", objectStoreIndexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "64", objectStoreIndexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var objectStore = server.Provider.StoreWrapper.objectStore; @@ -115,10 +120,10 @@ private static void VerifyObjectStoreSetMembers(IDatabase db, RedisKey[] keys, R } [Test] - public void IndexGrowthTestWithDiskReadAndCheckpoint() + public async Task IndexGrowthTestWithDiskReadAndCheckpoint() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, indexSize: "512", indexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, indexSize: "512", indexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var store = server.Provider.StoreWrapper.store; @@ -166,9 +171,10 @@ public void IndexGrowthTestWithDiskReadAndCheckpoint() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, indexSize: "512", indexMaxSize: "1k"); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, indexSize: "512", indexMaxSize: "1k"); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -179,10 +185,10 @@ public void IndexGrowthTestWithDiskReadAndCheckpoint() } [Test] - public void ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() + public async Task ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var objectStore = server.Provider.StoreWrapper.objectStore; @@ -230,9 +236,10 @@ public void ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k"); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k"); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { diff --git a/test/Garnet.test/LuaScriptTests.cs b/test/Garnet.test/LuaScriptTests.cs index 8b531401f6..ef82031213 100644 --- a/test/Garnet.test/LuaScriptTests.cs +++ b/test/Garnet.test/LuaScriptTests.cs @@ -23,7 +23,7 @@ public class LuaScriptTests private readonly LuaMemoryManagementMode allocMode; private readonly string limitBytes; - protected GarnetServer server; + protected GarnetApplication server; public LuaScriptTests(LuaMemoryManagementMode allocMode, string limitBytes) { @@ -32,17 +32,17 @@ public LuaScriptTests(LuaMemoryManagementMode allocMode, string limitBytes) } [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableLua: true, luaMemoryMode: allocMode, luaMemoryLimit: limitBytes); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableLua: true, luaMemoryMode: allocMode, luaMemoryLimit: limitBytes); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespAdminCommandsTests.cs b/test/Garnet.test/RespAdminCommandsTests.cs index 7bf4f07f06..95fbc7122b 100644 --- a/test/Garnet.test/RespAdminCommandsTests.cs +++ b/test/Garnet.test/RespAdminCommandsTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Garnet.server; +using Microsoft.Extensions.Hosting; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -17,20 +18,20 @@ namespace Garnet.test [TestFixture] public class RespAdminCommandsTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -157,13 +158,13 @@ public void SeSaveTest() } [Test] - public void SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) + public async Task SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) { if (useAzure) TestUtils.IgnoreIfNotRunningAzureTests(); - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObj, UseAzureStorage: useAzure); - server.Start(); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, UseAzureStorage: useAzure); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -176,9 +177,10 @@ public void SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, UseAzureStorage: useAzure); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, UseAzureStorage: useAzure); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -189,7 +191,7 @@ public void SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) } [Test] - public void SeSaveRecoverObjectTest() + public async Task SeSaveRecoverObjectTest() { var key = "SeSaveRecoverTestObjectKey"; var ldata = new RedisValue[] { "a", "b", "c", "d" }; @@ -208,9 +210,10 @@ public void SeSaveRecoverObjectTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -223,7 +226,7 @@ public void SeSaveRecoverObjectTest() } [Test] - public void SeSaveRecoverCustomObjectTest() + public async Task SeSaveRecoverCustomObjectTest() { string key = "key"; string field = "field1"; @@ -247,11 +250,12 @@ public void SeSaveRecoverCustomObjectTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); server.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), new RespCommandsInfo { Arity = 3 }); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -262,7 +266,7 @@ public void SeSaveRecoverCustomObjectTest() } [Test] - public void SeSaveRecoverCustomScriptTest() + public async Task SeSaveRecoverCustomScriptTest() { static void ValidateServerData(IDatabase db, string strKey, string strValue, string listKey, string listValue) { @@ -293,10 +297,11 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -309,13 +314,14 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str [TestCase(63, 2, 1)] [TestCase(16, 16, 1)] [TestCase(5, 64, 1)] - public void SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemorySize, int pageSize) + public async Task SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemorySize, int pageSize) { string sizeToString(int size) => size + "k"; - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, MemorySize: sizeToString(memorySize), PageSize: sizeToString(pageSize)); - server.Start(); + //server.Dispose(); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: sizeToString(memorySize), PageSize: sizeToString(pageSize)); + await server.RunAsync(); var ldata = new RedisValue[] { "a", "b", "c", "d" }; var ldataArr = ldata.Select(x => x).Reverse().ToArray(); @@ -334,9 +340,10 @@ public void SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemoryS while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, MemorySize: sizeToString(recoveryMemorySize), PageSize: sizeToString(pageSize), objectStoreHeapMemorySize: "64k"); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, MemorySize: sizeToString(recoveryMemorySize), PageSize: sizeToString(pageSize), objectStoreHeapMemorySize: "64k"); + await server.RunAsync(); ClassicAssert.LessOrEqual(server.Provider.StoreWrapper.objectStore.MaxAllocatedPageCount, (recoveryMemorySize / pageSize) + 1); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -358,13 +365,14 @@ public void SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemoryS [TestCase("16k", "16k")] [TestCase("5k", "8k")] [TestCase("5k", "64k")] - public void SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemorySize) + public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemorySize) { bool disableObj = true; - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObj, lowMemory: true, MemorySize: memorySize, PageSize: "512", enableAOF: true); - server.Start(); + //server.Dispose(); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, lowMemory: true, MemorySize: memorySize, PageSize: "512", enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -401,9 +409,10 @@ public void SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemo db.Execute("COMMITAOF"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObj, tryRecover: true, lowMemory: true, MemorySize: recoveryMemorySize, PageSize: "512", enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, tryRecover: true, lowMemory: true, MemorySize: recoveryMemorySize, PageSize: "512", enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -417,11 +426,12 @@ public void SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemo } [Test] - public void SeAofRecoverTest() + public async Task SeAofRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -431,9 +441,10 @@ public void SeAofRecoverTest() db.Execute("COMMITAOF"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true, tryRecover: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, tryRecover: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { diff --git a/test/Garnet.test/RespAofAzureTests.cs b/test/Garnet.test/RespAofAzureTests.cs index 9787ba1e74..7f45ad1949 100644 --- a/test/Garnet.test/RespAofAzureTests.cs +++ b/test/Garnet.test/RespAofAzureTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -12,7 +13,7 @@ namespace Garnet.test [TestFixture] public class RespAofAzureTests { - GarnetServer server; + GarnetApplication server; static readonly SortedSetEntry[] entries = [ new SortedSetEntry("a", 1), @@ -28,20 +29,23 @@ public class RespAofAzureTests ]; [SetUp] - public void Setup() + public async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true, UseAzureStorage: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true, UseAzureStorage: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + } } [Test] - public void AofUpsertStoreRecoverTest() + public async Task AofUpsertStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -51,9 +55,10 @@ public void AofUpsertStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -66,7 +71,7 @@ public void AofUpsertStoreRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitRecoverTest() + public async Task AofUpsertStoreAutoCommitRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -76,9 +81,10 @@ public void AofUpsertStoreAutoCommitRecoverTest() } server.Store.WaitForCommit(); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -91,11 +97,12 @@ public void AofUpsertStoreAutoCommitRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() + public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -103,9 +110,10 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey1", "SeAofUpsertRecoverTestValue1"); db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -118,7 +126,7 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() } [Test] - public void AofUpsertStoreCkptRecoverTest() + public async Task AofUpsertStoreCkptRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -136,9 +144,10 @@ public void AofUpsertStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -153,7 +162,7 @@ public void AofUpsertStoreCkptRecoverTest() } [Test] - public void AofRMWStoreRecoverTest() + public async Task AofRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -163,9 +172,10 @@ public void AofRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -178,7 +188,7 @@ public void AofRMWStoreRecoverTest() } [Test] - public void AofDeleteStoreRecoverTest() + public async Task AofDeleteStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -198,9 +208,10 @@ public void AofDeleteStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -215,7 +226,7 @@ public void AofDeleteStoreRecoverTest() } [Test] - public void AofExpiryRMWStoreRecoverTest() + public async Task AofExpiryRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -233,9 +244,10 @@ public void AofExpiryRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -248,7 +260,7 @@ public void AofExpiryRMWStoreRecoverTest() } [Test] - public void AofRMWObjectStoreRecoverTest() + public async Task AofRMWObjectStoreRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -267,9 +279,10 @@ public void AofRMWObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -285,7 +298,7 @@ public void AofRMWObjectStoreRecoverTest() } [Test] - public void AofDeleteObjectStoreRecoverTest() + public async Task AofDeleteObjectStoreRecoverTest() { var key1 = "AofDeleteObjectStoreRecoverTestKey1"; var key2 = "AofDeleteObjectStoreRecoverTestKey2"; @@ -313,9 +326,10 @@ public void AofDeleteObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -328,7 +342,7 @@ public void AofDeleteObjectStoreRecoverTest() } [Test] - public void AofRMWObjectStoreCopyUpdateRecoverTest() + public async Task AofRMWObjectStoreCopyUpdateRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -349,9 +363,10 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() db.SortedSetAdd("AofRMWObjectStoreRecoverTestKey" + 1, newEntries); } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -367,7 +382,7 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() } [Test] - public void AofMultiRMWStoreCkptRecoverTest() + public async Task AofMultiRMWStoreCkptRecoverTest() { long ret = 0; using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -404,9 +419,10 @@ public void AofMultiRMWStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { From b984d20928404d6fdc1d896a3e8431f70b2a9915 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 11:03:47 +0100 Subject: [PATCH 23/42] convert more tests to GarnetApplication --- test/Garnet.test/RespAofTests.cs | 213 ++++++++++-------- .../RespBlockingCollectionTests.cs | 12 +- test/Garnet.test/RespCommandTests.cs | 13 +- test/Garnet.test/RespCustomCommandTests.cs | 12 +- test/Garnet.test/RespEtagTests.cs | 52 ++--- test/Garnet.test/RespGetLowMemoryTests.cs | 12 +- test/Garnet.test/RespHashTests.cs | 12 +- test/Garnet.test/RespInfoTests.cs | 13 +- test/Garnet.test/RespListGarnetClientTests.cs | 12 +- test/Garnet.test/RespListTests.cs | 12 +- test/Garnet.test/RespLowMemoryTests.cs | 13 +- test/Garnet.test/RespMetricsTest.cs | 16 +- test/Garnet.test/RespModuleTests.cs | 21 +- test/Garnet.test/RespPubSubTests.cs | 9 +- test/Garnet.test/RespScanCommandsTests.cs | 13 +- .../RespSortedSetGarnetClientTests.cs | 12 +- test/Garnet.test/RespSortedSetGeoTests.cs | 13 +- test/Garnet.test/RespSortedSetTests.cs | 12 +- test/Garnet.test/RespTransactionProcTests.cs | 13 +- 19 files changed, 261 insertions(+), 224 deletions(-) diff --git a/test/Garnet.test/RespAofTests.cs b/test/Garnet.test/RespAofTests.cs index 90e8bb61e4..9f2c0d2fa5 100644 --- a/test/Garnet.test/RespAofTests.cs +++ b/test/Garnet.test/RespAofTests.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Garnet.server; +using Microsoft.Extensions.Hosting; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -15,7 +17,7 @@ namespace Garnet.test [TestFixture] public class RespAofTests { - GarnetServer server; + GarnetApplication server; private IReadOnlyDictionary respCustomCommandsInfo; static readonly SortedSetEntry[] entries = @@ -33,24 +35,24 @@ public class RespAofTests ]; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); ClassicAssert.IsTrue(TestUtils.TryGetCustomCommandsInfo(out respCustomCommandsInfo)); ClassicAssert.IsNotNull(respCustomCommandsInfo); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } [Test] - public void AofUpsertStoreRecoverTest() + public async Task AofUpsertStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -60,9 +62,10 @@ public void AofUpsertStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -75,7 +78,7 @@ public void AofUpsertStoreRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitRecoverTest() + public async Task AofUpsertStoreAutoCommitRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -85,9 +88,10 @@ public void AofUpsertStoreAutoCommitRecoverTest() } server.Store.WaitForCommit(); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -101,11 +105,12 @@ public void AofUpsertStoreAutoCommitRecoverTest() [Test] [CancelAfter(10_000)] - public void AofUpsertStoreCommitTaskRecoverTest() + public async Task AofUpsertStoreCommitTaskRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitFrequencyMs: 100); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitFrequencyMs: 100); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -115,9 +120,10 @@ public void AofUpsertStoreCommitTaskRecoverTest() } server.Store.WaitForCommit(); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -130,11 +136,12 @@ public void AofUpsertStoreCommitTaskRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() + public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -142,9 +149,10 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey1", "SeAofUpsertRecoverTestValue1"); db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -157,11 +165,12 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() } [Test] - public void AofTransactionStoreAutoCommitCommitWaitRecoverTest() + public async Task AofTransactionStoreAutoCommitCommitWaitRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -172,9 +181,10 @@ public void AofTransactionStoreAutoCommitCommitWaitRecoverTest() ClassicAssert.IsTrue(transaction.Execute()); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -187,7 +197,7 @@ public void AofTransactionStoreAutoCommitCommitWaitRecoverTest() } [Test] - public void AofUpsertStoreCkptRecoverTest() + public async Task AofUpsertStoreCkptRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -205,9 +215,10 @@ public void AofUpsertStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -222,7 +233,7 @@ public void AofUpsertStoreCkptRecoverTest() } [Test] - public void AofRMWStoreRecoverTest() + public async Task AofRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -236,9 +247,10 @@ public void AofRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -254,7 +266,7 @@ public void AofRMWStoreRecoverTest() } [Test] - public void AofDeleteStoreRecoverTest() + public async Task AofDeleteStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -274,9 +286,10 @@ public void AofDeleteStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -291,7 +304,7 @@ public void AofDeleteStoreRecoverTest() } [Test] - public void AofExpiryRMWStoreRecoverTest() + public async Task AofExpiryRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -309,9 +322,10 @@ public void AofExpiryRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -324,7 +338,7 @@ public void AofExpiryRMWStoreRecoverTest() } [Test] - public void AofRMWObjectStoreRecoverTest() + public async Task AofRMWObjectStoreRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -343,9 +357,10 @@ public void AofRMWObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -361,7 +376,7 @@ public void AofRMWObjectStoreRecoverTest() } [Test] - public void AofDeleteObjectStoreRecoverTest() + public async Task AofDeleteObjectStoreRecoverTest() { var key1 = "AofDeleteObjectStoreRecoverTestKey1"; var key2 = "AofDeleteObjectStoreRecoverTestKey2"; @@ -389,9 +404,10 @@ public void AofDeleteObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -404,7 +420,7 @@ public void AofDeleteObjectStoreRecoverTest() } [Test] - public void AofRMWObjectStoreCopyUpdateRecoverTest() + public async Task AofRMWObjectStoreCopyUpdateRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -425,9 +441,10 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() db.SortedSetAdd("AofRMWObjectStoreRecoverTestKey" + 1, newEntries); } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -443,7 +460,7 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() } [Test] - public void AofUpsertObjectStoreRecoverTest() + public async Task AofUpsertObjectStoreRecoverTest() { var origList = new RedisValue[] { "a", "b", "c", "d" }; var key1 = "lkey1"; @@ -468,9 +485,10 @@ public void AofUpsertObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -482,19 +500,20 @@ public void AofUpsertObjectStoreRecoverTest() } [Test] - public void AofUpsertCustomObjectRecoverTest() + public async Task AofUpsertCustomObjectRecoverTest() { - void RegisterCustomCommand(GarnetServer gServer) + void RegisterCustomCommand(GarnetApplication gServer) { var factory = new MyDictFactory(); gServer.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), respCustomCommandsInfo["MYDICTSET"]); gServer.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), respCustomCommandsInfo["MYDICTGET"]); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(server); - server.Start(); + await server.RunAsync(); var mainKey1 = "key1"; var subKey = "subKey"; @@ -518,10 +537,11 @@ void RegisterCustomCommand(GarnetServer gServer) } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(server); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -533,7 +553,7 @@ void RegisterCustomCommand(GarnetServer gServer) } [Test] - public void AofUpsertCustomScriptRecoverTest() + public async Task AofUpsertCustomScriptRecoverTest() { static void ValidateServerData(IDatabase db, string strKey, string strValue, string listKey, string listValue) { @@ -544,10 +564,11 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str ClassicAssert.AreEqual(listValue, (string)retList[0]); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - server.Start(); + await server.RunAsync(); var strKey = "StrKey"; var strValue = "StrValue"; @@ -562,10 +583,11 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -574,7 +596,7 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str } [Test] - public void AofMultiRMWStoreCkptRecoverTest() + public async Task AofMultiRMWStoreCkptRecoverTest() { long ret = 0; using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -611,9 +633,10 @@ public void AofMultiRMWStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -624,7 +647,7 @@ public void AofMultiRMWStoreCkptRecoverTest() } [Test] - public void AofListObjectStoreRecoverTest() + public async Task AofListObjectStoreRecoverTest() { var key = "AofListObjectStoreRecoverTest"; var ldata = new RedisValue[] { "a", "b", "c", "d" }; @@ -642,9 +665,10 @@ public void AofListObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + //server.Dispose(false); + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -656,7 +680,7 @@ public void AofListObjectStoreRecoverTest() } [Test] - public void AofCustomTxnRecoverTest() + public async Task AofCustomTxnRecoverTest() { server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), new RespCommandsInfo { Arity = 4 }); string readkey = "readme"; @@ -676,11 +700,12 @@ public void AofCustomTxnRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); + //server.Dispose(false); + await server.StopAsync(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), new RespCommandsInfo { Arity = 4 }); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { diff --git a/test/Garnet.test/RespBlockingCollectionTests.cs b/test/Garnet.test/RespBlockingCollectionTests.cs index 6292038e48..1229923df0 100644 --- a/test/Garnet.test/RespBlockingCollectionTests.cs +++ b/test/Garnet.test/RespBlockingCollectionTests.cs @@ -12,21 +12,21 @@ namespace Garnet.test { public class RespBlockingCollectionTests { - GarnetServer server; + GarnetApplication server; private TaskFactory taskFactory = new(); [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespCommandTests.cs b/test/Garnet.test/RespCommandTests.cs index 175fa9cb18..a146c00b99 100644 --- a/test/Garnet.test/RespCommandTests.cs +++ b/test/Garnet.test/RespCommandTests.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using NUnit.Framework; @@ -21,7 +22,7 @@ namespace Garnet.test [TestFixture] public class RespCommandTests { - GarnetServer server; + GarnetApplication server; private string extTestDir; private IReadOnlyDictionary respCommandsInfo; private IReadOnlyDictionary externalRespCommandsInfo; @@ -51,7 +52,7 @@ public class RespCommandTests ]; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); extTestDir = Path.Combine(TestUtils.MethodTestDir, "test"); @@ -75,15 +76,15 @@ .. respCommandsInfo.Values.Where(ci => ci.IsInternal).Select(ci => ci.Command) .Union(respSubCommandsInfo.Values.Where(sc => sc.IsInternal).Select(sc => sc.Command)) ]; - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: true, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, extensionBinPaths: [extTestDir]); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(extTestDir)?.FullName); } diff --git a/test/Garnet.test/RespCustomCommandTests.cs b/test/Garnet.test/RespCustomCommandTests.cs index 7e4752c3e0..b73b6c575c 100644 --- a/test/Garnet.test/RespCustomCommandTests.cs +++ b/test/Garnet.test/RespCustomCommandTests.cs @@ -225,28 +225,28 @@ public override unsafe void Main(TGarnetApi garnetApi, ref CustomPro [TestFixture] public class RespCustomCommandTests { - GarnetServer server; + GarnetApplication server; private string _extTestDir1; private string _extTestDir2; [SetUp] - public void Setup() + public async Task Setup() { _extTestDir1 = Path.Combine(TestUtils.MethodTestDir, "test1"); _extTestDir2 = Path.Combine(TestUtils.MethodTestDir, "test2"); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, extensionBinPaths: [_extTestDir1, _extTestDir2], extensionAllowUnsignedAssemblies: true); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(_extTestDir1)?.FullName); } diff --git a/test/Garnet.test/RespEtagTests.cs b/test/Garnet.test/RespEtagTests.cs index 3bd15c489e..bb310bd5f2 100644 --- a/test/Garnet.test/RespEtagTests.cs +++ b/test/Garnet.test/RespEtagTests.cs @@ -16,22 +16,22 @@ namespace Garnet.test [TestFixture] public class RespEtagTests { - private GarnetServer server; + private GarnetApplication server; private Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: false); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: false); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -976,13 +976,13 @@ public void SingleDeleteForEtagSetData() } [Test] - public void SingleDeleteWithObjectStoreDisabledForEtagSetData() + public async Task SingleDeleteWithObjectStoreDisabledForEtagSetData() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); var key = "delKey"; var value = "1234"; @@ -1009,13 +1009,13 @@ private string GetRandomString(int len) } [Test] - public void SingleDeleteWithObjectStoreDisable_LTMForEtagSetData() + public async Task SingleDeleteWithObjectStoreDisable_LTMForEtagSetData() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1049,14 +1049,14 @@ public void SingleDeleteWithObjectStoreDisable_LTMForEtagSetData() } [Test] - public void MultiKeyDeleteForEtagSetData([Values] bool withoutObjectStore) + public async Task MultiKeyDeleteForEtagSetData([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1084,14 +1084,14 @@ public void MultiKeyDeleteForEtagSetData([Values] bool withoutObjectStore) } [Test] - public void MultiKeyUnlinkForEtagSetData([Values] bool withoutObjectStore) + public async Task MultiKeyUnlinkForEtagSetData([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1118,14 +1118,14 @@ public void MultiKeyUnlinkForEtagSetData([Values] bool withoutObjectStore) } [Test] - public void SingleExistsForEtagSetData([Values] bool withoutObjectStore) + public async Task SingleExistsForEtagSetData([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/RespGetLowMemoryTests.cs b/test/Garnet.test/RespGetLowMemoryTests.cs index ff39389a7e..e9723c1aa5 100644 --- a/test/Garnet.test/RespGetLowMemoryTests.cs +++ b/test/Garnet.test/RespGetLowMemoryTests.cs @@ -14,22 +14,22 @@ namespace Garnet.test [TestFixture] public class RespGetLowMemoryTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(335); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, getSG: true, disablePubSub: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, getSG: true, disablePubSub: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespHashTests.cs b/test/Garnet.test/RespHashTests.cs index c8f5f01e56..442d936706 100644 --- a/test/Garnet.test/RespHashTests.cs +++ b/test/Garnet.test/RespHashTests.cs @@ -16,22 +16,22 @@ namespace Garnet.test [TestFixture] public class RespHashTests { - GarnetServer server; + GarnetApplication server; static readonly HashEntry[] entries = new HashEntry[100]; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespInfoTests.cs b/test/Garnet.test/RespInfoTests.cs index c6c5e077f9..54a18cc3f1 100644 --- a/test/Garnet.test/RespInfoTests.cs +++ b/test/Garnet.test/RespInfoTests.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -13,22 +14,22 @@ namespace Garnet.test [TestFixture] public class RespInfoTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: true, latencyMonitor: true, metricsSamplingFreq: 1, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, latencyMonitor: true, metricsSamplingFreq: 1, DisableObjects: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespListGarnetClientTests.cs b/test/Garnet.test/RespListGarnetClientTests.cs index 44137a37e3..fa7e6c79e5 100644 --- a/test/Garnet.test/RespListGarnetClientTests.cs +++ b/test/Garnet.test/RespListGarnetClientTests.cs @@ -12,14 +12,14 @@ namespace Garnet.test [TestFixture] public class RespListGarnetClientTests { - private GarnetServer server; + private GarnetApplication server; [OneTimeSetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } private static object[] LeftPushTestCases = @@ -271,9 +271,9 @@ private static async Task ValidateListContentAsync(GarnetClient db, string key, } [OneTimeTearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespListTests.cs b/test/Garnet.test/RespListTests.cs index fbf140c13d..ec58819a47 100644 --- a/test/Garnet.test/RespListTests.cs +++ b/test/Garnet.test/RespListTests.cs @@ -17,22 +17,22 @@ namespace Garnet.test [TestFixture] class RespListTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespLowMemoryTests.cs b/test/Garnet.test/RespLowMemoryTests.cs index 091d100637..3a6208ee25 100644 --- a/test/Garnet.test/RespLowMemoryTests.cs +++ b/test/Garnet.test/RespLowMemoryTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -11,20 +12,20 @@ namespace Garnet.test [TestFixture] public class RespLowMemoryTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespMetricsTest.cs b/test/Garnet.test/RespMetricsTest.cs index 024cd94954..884af257a9 100644 --- a/test/Garnet.test/RespMetricsTest.cs +++ b/test/Garnet.test/RespMetricsTest.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Garnet.common; using Microsoft.Extensions.Logging; using NUnit.Framework; @@ -15,14 +16,14 @@ namespace Garnet.test [TestFixture] public class RespMetricsTest { - GarnetServer server; + GarnetApplication server; ILoggerFactory loggerFactory; Random r; - private void StartServer(int metricsSamplingFreq = -1, bool latencyMonitor = false) + private async Task StartServer(int metricsSamplingFreq = -1, bool latencyMonitor = false) { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, metricsSamplingFreq: metricsSamplingFreq, latencyMonitor: latencyMonitor); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, metricsSamplingFreq: metricsSamplingFreq, latencyMonitor: latencyMonitor); + await server.RunAsync(); } [SetUp] @@ -35,9 +36,12 @@ public void Setup() } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + } TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); } diff --git a/test/Garnet.test/RespModuleTests.cs b/test/Garnet.test/RespModuleTests.cs index 9cfb898fc7..9cac5300b3 100644 --- a/test/Garnet.test/RespModuleTests.cs +++ b/test/Garnet.test/RespModuleTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -13,27 +14,27 @@ namespace Garnet.test [TestFixture] public class RespModuleTests { - GarnetServer server; + GarnetApplication server; private string testModuleDir; string binPath; [SetUp] - public void Setup() + public async Task Setup() { testModuleDir = Path.Combine(TestUtils.MethodTestDir, "testModules"); binPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, extensionBinPaths: [testModuleDir, binPath], extensionAllowUnsignedAssemblies: true); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(testModuleDir)?.FullName); } @@ -176,7 +177,7 @@ public void TestModuleLoad() [Test] - public void TestModuleLoadUsingGarnetOptions() + public async Task TestModuleLoadUsingGarnetOptions() { var onLoad = @"context.Initialize(""TestModule1"", 1); @@ -192,11 +193,11 @@ public void TestModuleLoadUsingGarnetOptions() var module1Path = CreateTestModule(onLoad, "TestModule1.dll"); var module2Path = CreateTestModule(onLoad2, "TestModule2.dll"); - server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + await server.StopAsync(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, loadModulePaths: [module1Path, module2Path]); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/RespPubSubTests.cs b/test/Garnet.test/RespPubSubTests.cs index 35b1d63168..c9a9cc498e 100644 --- a/test/Garnet.test/RespPubSubTests.cs +++ b/test/Garnet.test/RespPubSubTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Security.Cryptography; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -14,14 +15,14 @@ namespace Garnet.test [TestFixture] class RespPubSubTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, pubSubPageSize: "256k"); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, pubSubPageSize: "256k"); + await server.RunAsync(); } [TearDown] diff --git a/test/Garnet.test/RespScanCommandsTests.cs b/test/Garnet.test/RespScanCommandsTests.cs index bba4077d18..1ca489d40f 100644 --- a/test/Garnet.test/RespScanCommandsTests.cs +++ b/test/Garnet.test/RespScanCommandsTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -15,23 +16,23 @@ namespace Garnet.test [TestFixture] public class RespScanCommandsTests { - GarnetServer server; + GarnetApplication server; private IReadOnlyDictionary respCustomCommandsInfo; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); ClassicAssert.IsTrue(TestUtils.TryGetCustomCommandsInfo(out respCustomCommandsInfo)); ClassicAssert.IsNotNull(respCustomCommandsInfo); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetGarnetClientTests.cs b/test/Garnet.test/RespSortedSetGarnetClientTests.cs index ef7d456381..fe6617a610 100644 --- a/test/Garnet.test/RespSortedSetGarnetClientTests.cs +++ b/test/Garnet.test/RespSortedSetGarnetClientTests.cs @@ -21,7 +21,7 @@ namespace Garnet.test [TestFixture] public class RespSortedSetGarnetClientTests { - protected GarnetServer server; + protected GarnetApplication server; ManualResetEventSlim waiter; const int maxIterations = 3; @@ -41,19 +41,19 @@ public class RespSortedSetGarnetClientTests [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, enableAOF: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, enableAOF: true); + await server.RunAsync(); waiter = new ManualResetEventSlim(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetGeoTests.cs b/test/Garnet.test/RespSortedSetGeoTests.cs index b7c6d1cc88..21f387fa71 100644 --- a/test/Garnet.test/RespSortedSetGeoTests.cs +++ b/test/Garnet.test/RespSortedSetGeoTests.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using NUnit.Framework; @@ -16,7 +17,7 @@ namespace Garnet.test [TestFixture] public class RespSortedSetGeoTests { - GarnetServer server; + GarnetApplication server; readonly string[,] cities = new string[,] { {"-74.0059413", "40.7127837", "New York"}, {"-118.2436849", "34.0522342", "Los Angeles"}, @@ -126,17 +127,17 @@ public class RespSortedSetGeoTests [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetTests.cs b/test/Garnet.test/RespSortedSetTests.cs index 3abfaa67c2..223d2810d8 100644 --- a/test/Garnet.test/RespSortedSetTests.cs +++ b/test/Garnet.test/RespSortedSetTests.cs @@ -27,7 +27,7 @@ namespace Garnet.test [TestFixture] public class RespSortedSetTests { - protected GarnetServer server; + protected GarnetApplication server; static readonly SortedSetEntry[] entries = [ @@ -73,18 +73,18 @@ public class RespSortedSetTests [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTransactionProcTests.cs b/test/Garnet.test/RespTransactionProcTests.cs index b3f3c05c29..def39afe81 100644 --- a/test/Garnet.test/RespTransactionProcTests.cs +++ b/test/Garnet.test/RespTransactionProcTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.Threading; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -12,20 +13,20 @@ namespace Garnet.test [TestFixture] public class RespTransactionProcTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } From 1ab35ab355f36f1f45d3189ec044446277d8bed5 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 12:26:12 +0100 Subject: [PATCH 24/42] fix formating --- libs/host/GarnetApplicatrion.cs | 2 +- test/Garnet.test/GarnetClientTests.cs | 12 ++++++------ test/Garnet.test/IndexGrowthTests.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs index 1c299dbbea..ca324d5840 100644 --- a/libs/host/GarnetApplicatrion.cs +++ b/libs/host/GarnetApplicatrion.cs @@ -36,7 +36,7 @@ public StoreApi Store return host.Services.GetRequiredService(); } } - + internal GarnetProvider Provider => host.Services.GetRequiredService(); readonly IHost host; diff --git a/test/Garnet.test/GarnetClientTests.cs b/test/Garnet.test/GarnetClientTests.cs index 7cb7032ebe..54c59945f3 100644 --- a/test/Garnet.test/GarnetClientTests.cs +++ b/test/Garnet.test/GarnetClientTests.cs @@ -143,7 +143,7 @@ public async Task SetGetWithCallback([Values] bool useTLS) e.Set(); }); e.Wait(); - + await server.StopAsync(); } @@ -177,7 +177,7 @@ public async Task SimpleMetricsTest([Values] bool recordLatency) db.Dispose(); metrics = db.GetLatencyMetrics(); ClassicAssert.AreEqual(0, metrics.Length); // Should be 0 after dispose - + await server.StopAsync(); } @@ -195,7 +195,7 @@ public async Task SimpleStringArrayTest([Values] bool stringParams) int.Parse(await db.ExecuteForStringResultAsync(Encoding.ASCII.GetBytes("$6\r\nINCRBY\r\n"), [Encoding.ASCII.GetBytes("myKey"), Encoding.ASCII.GetBytes("10")])); ClassicAssert.AreEqual(10, n); - + await server.StopAsync(); } @@ -213,7 +213,7 @@ public async Task SimpleNoArgsTest() result = await db.ExecuteForStringResultAsync("ASKING"); ClassicAssert.AreEqual("OK", result); - + await server.StopAsync(); } @@ -277,7 +277,7 @@ public async Task SimpleIncrTest([Values] bool stringParams) }); } WaitAndReset(e); - + await server.StopAsync(); } @@ -431,7 +431,7 @@ public async Task CanUseMGetTests([Values] bool disableObjectStore) } tokenSource.Dispose(); - + await server.StopAsync(); } diff --git a/test/Garnet.test/IndexGrowthTests.cs b/test/Garnet.test/IndexGrowthTests.cs index 53be339f94..9a59cb7fde 100644 --- a/test/Garnet.test/IndexGrowthTests.cs +++ b/test/Garnet.test/IndexGrowthTests.cs @@ -30,7 +30,7 @@ public async Task TearDown() { await server.StopAsync(); } - + TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } From 7e20bae84d0bae4233dcc7af9a48bd63c95e884d Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 13:04:49 +0100 Subject: [PATCH 25/42] remove refactor TestUtils and fix cluster tests --- .../ClusterAuthCommsTests.cs | 7 +- .../ClusterManagementTests.cs | 6 +- .../ClusterReplicationTests.cs | 38 ++-- .../Garnet.test.cluster/ClusterTestContext.cs | 14 +- test/Garnet.test/ObjectTestsForOutput.cs | 12 +- test/Garnet.test/ReadCacheTests.cs | 9 +- .../Resp/ACL/AclConfigurationFileTests.cs | 42 ++-- test/Garnet.test/Resp/ACL/AclTest.cs | 7 +- test/Garnet.test/Resp/ACL/BasicTests.cs | 6 +- test/Garnet.test/Resp/ACL/DeleteUserTests.cs | 6 +- test/Garnet.test/Resp/ACL/ParallelTests.cs | 6 +- test/Garnet.test/Resp/ACL/RespCommandTests.cs | 12 +- test/Garnet.test/Resp/ACL/SetUserTests.cs | 70 +++---- .../Resp/GarnetAuthenticatorTests.cs | 6 +- test/Garnet.test/TestUtils.cs | 180 +----------------- 15 files changed, 136 insertions(+), 285 deletions(-) diff --git a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs index 2f26bcae7f..da4438cb46 100644 --- a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs +++ b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -195,7 +196,7 @@ public void ClusterSimpleFailoverAuth() [Test, Order(4)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterSimpleACLReload() + public async Task ClusterSimpleACLReload() { ClusterStartupWithoutAuthCreds(useDefaultUserForInterNodeComms: true); @@ -214,9 +215,9 @@ public void ClusterSimpleACLReload() context.clusterTestUtils.AclLoad(1, logger: context.logger); // Restart node with new ACL file - context.nodes[0].Dispose(false); + await context.nodes[0].StopAsync(); context.nodes[0] = context.CreateInstance(context.clusterTestUtils.GetEndPoint(0).Port, useAcl: true, cleanClusterConfig: false); - context.nodes[0].Start(); + await context.nodes[0].RunAsync(); context.CreateConnection(clientCreds: cc[0]); diff --git a/test/Garnet.test.cluster/ClusterManagementTests.cs b/test/Garnet.test.cluster/ClusterManagementTests.cs index dcaff8956b..a890abc32b 100644 --- a/test/Garnet.test.cluster/ClusterManagementTests.cs +++ b/test/Garnet.test.cluster/ClusterManagementTests.cs @@ -376,7 +376,7 @@ public void ClusterKeySlotTest() //[Test, Order(5)] //[Category("CLUSTER")] - public void ClusterRestartNodeDropGossip() + public async Task ClusterRestartNodeDropGossip() { var logger = context.loggerFactory.CreateLogger("ClusterRestartNodeDropGossip"); context.CreateInstances(defaultShards); @@ -385,7 +385,7 @@ public void ClusterRestartNodeDropGossip() var restartingNode = 2; // Dispose node and delete data - context.nodes[restartingNode].Dispose(deleteDir: true); + await context.nodes[restartingNode].RunAsync(); context.nodes[restartingNode] = context.CreateInstance( context.clusterTestUtils.GetEndPoint(restartingNode).Port, @@ -395,7 +395,7 @@ public void ClusterRestartNodeDropGossip() timeout: 60, gossipDelay: 1, cleanClusterConfig: false); - context.nodes[restartingNode].Start(); + await context.nodes[restartingNode].RunAsync(); context.CreateConnection(); Thread.Sleep(5000); diff --git a/test/Garnet.test.cluster/ClusterReplicationTests.cs b/test/Garnet.test.cluster/ClusterReplicationTests.cs index cdccac8a3c..eccca0d3df 100644 --- a/test/Garnet.test.cluster/ClusterReplicationTests.cs +++ b/test/Garnet.test.cluster/ClusterReplicationTests.cs @@ -142,7 +142,7 @@ public void ClusterSRTest([Values] bool disableObjects) [Test, Order(2)] [Category("REPLICATION")] - public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; @@ -179,7 +179,7 @@ public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Val context.ValidateKVCollectionAgainstReplica(ref context.kvPairs, 1); // Shutdown secondary - context.nodes[1].Dispose(false); + await context.nodes[1].StopAsync(); Thread.Sleep(TimeSpan.FromSeconds(2)); @@ -198,7 +198,7 @@ public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Val timeout: timeout, useTLS: useTLS, cleanClusterConfig: false); - context.nodes[1].Start(); + await context.nodes[1].RunAsync(); context.CreateConnection(useTLS: useTLS); // Validate synchronization was success @@ -208,7 +208,7 @@ public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Val [Test, Order(3)] [Category("REPLICATION")] - public void ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; @@ -253,7 +253,7 @@ public void ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool d context.clusterTestUtils.WaitCheckpoint(1, replicaLastSaveTime, logger: context.logger); // Shutdown secondary - context.nodes[1].Dispose(false); + await context.nodes[1].StopAsync(); Thread.Sleep(TimeSpan.FromSeconds(2)); // New insert @@ -272,7 +272,7 @@ public void ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool d useTLS: useTLS, cleanClusterConfig: false, asyncReplay: asyncReplay); - context.nodes[1].Start(); + await context.nodes[1].RunAsync(); context.CreateConnection(useTLS: useTLS); for (int i = 1; i < replica_count; i++) context.clusterTestUtils.WaitForReplicaRecovery(i, context.logger); @@ -302,7 +302,7 @@ public void ClusterCheckpointRetrieveDelta([Values] bool performRMW) public void ClusterSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) => ClusterSRPrimaryCheckpointRetrieve(performRMW: performRMW, disableObjects: disableObjects, lowMemory: lowMemory, manySegments: manySegments, false, false); - void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bool lowMemory, bool manySegments, bool disableStorageTier, bool incrementalSnapshots) + async Task ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bool lowMemory, bool manySegments, bool disableStorageTier, bool incrementalSnapshots) { // Test many segments on or off with lowMemory manySegments = lowMemory && manySegments; @@ -335,7 +335,7 @@ void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bo context.kvPairsObj = []; context.logger?.LogTrace("Test disposing node 1"); - context.nodes[1].Dispose(false); + await context.nodes[1].StopAsync(); Thread.Sleep(TimeSpan.FromSeconds(1)); // Populate Primary @@ -371,7 +371,7 @@ void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bo SegmentSize: manySegments ? "4k" : "1g", DisableStorageTier: disableStorageTier, asyncReplay: asyncReplay); - context.nodes[replicaIndex].Start(); + await context.nodes[replicaIndex].RunAsync(); context.CreateConnection(useTLS: useTLS); context.clusterTestUtils.WaitForReplicaAofSync(primaryIndex, replicaIndex, context.logger); @@ -442,7 +442,7 @@ public void ClusterSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Test, Order(8)] [Category("REPLICATION")] - public void ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; @@ -481,7 +481,7 @@ public void ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disa if (!disableObjects) objectStoreCurrentAofAddress = context.clusterTestUtils.GetObjectStoreCurrentAofAddress(0, context.logger); - context.nodes[0].Dispose(false); + await context.nodes[0].RunAsync(); Thread.Sleep(TimeSpan.FromSeconds(1)); // Restart Primary @@ -494,7 +494,7 @@ public void ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disa useTLS: useTLS, cleanClusterConfig: false, asyncReplay: asyncReplay); - context.nodes[0].Start(); + await context.nodes[0].RunAsync(); context.CreateConnection(useTLS: useTLS); var storeRecoveredAofAddress = context.clusterTestUtils.GetStoreRecoveredAofAddress(0, context.logger); @@ -901,7 +901,7 @@ public void ClusterDivergentCheckpointMMFastCommitTest([Values] bool disableObje mainMemoryReplication: mainMemoryReplication, fastCommit: true); - void ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bool ckptBeforeDivergence, bool multiCheckpointAfterDivergence, bool mainMemoryReplication, bool fastCommit) + async Task ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bool ckptBeforeDivergence, bool multiCheckpointAfterDivergence, bool mainMemoryReplication, bool fastCommit) { var set = false; var replica_count = 2;// Per primary @@ -979,7 +979,7 @@ void ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bool ckp context.clusterTestUtils.WaitForReplicaAofSync(oldPrimaryIndex, replicaIndex, context.logger); // Dispose primary - context.nodes[oldPrimaryIndex].Dispose(false); + await context.nodes[oldPrimaryIndex].StopAsync(); context.nodes[oldPrimaryIndex] = null; // Re-assign slots to replica manually since failover option was not @@ -1063,7 +1063,7 @@ public void ClusterReplicateFails() } [Test, Order(22)] - public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) + public async Task ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) { var replica_count = 1;// Per primary var primary_count = 1; @@ -1105,9 +1105,9 @@ public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) context.ValidateKVCollectionAgainstReplica(ref context.kvPairs, replicaNodeIndex); // Dispose primary and delete data - context.nodes[primaryNodeIndex].Dispose(true); + await context.nodes[primaryNodeIndex].StopAsync(); // Dispose primary but do not delete data - context.nodes[replicaNodeIndex].Dispose(false); + await context.nodes[primaryNodeIndex].StopAsync(); // Restart primary and do not recover context.nodes[primaryNodeIndex] = context.CreateInstance( @@ -1122,7 +1122,7 @@ public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) useTLS: useTLS, cleanClusterConfig: true, asyncReplay: asyncReplay); - context.nodes[primaryNodeIndex].Start(); + await context.nodes[primaryNodeIndex].RunAsync(); // Restart secondary and recover context.nodes[replicaNodeIndex] = context.CreateInstance( @@ -1137,7 +1137,7 @@ public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) useTLS: useTLS, cleanClusterConfig: true, asyncReplay: asyncReplay); - context.nodes[replicaNodeIndex].Start(); + await context.nodes[replicaNodeIndex].RunAsync(); context.CreateConnection(useTLS: useTLS); // Assert primary version is 1 and replica has recovered to previous checkpoint diff --git a/test/Garnet.test.cluster/ClusterTestContext.cs b/test/Garnet.test.cluster/ClusterTestContext.cs index 8bc92d8668..cbf3e2ffc0 100644 --- a/test/Garnet.test.cluster/ClusterTestContext.cs +++ b/test/Garnet.test.cluster/ClusterTestContext.cs @@ -22,7 +22,7 @@ public class ClusterTestContext { public CredentialManager credManager; public string TestFolder; - public GarnetServer[] nodes = null; + public GarnetApplication[] nodes = null; public EndPointCollection endpoints; public TextWriter logTextWriter = TestContext.Progress; public ILoggerFactory loggerFactory; @@ -100,7 +100,7 @@ public void RegisterCustomTxn(string name, Func proc /// /// /// - public void CreateInstances( + public async Task CreateInstances( int shards, bool cleanClusterConfig = true, bool tryRecover = false, @@ -166,7 +166,7 @@ public void CreateInstances( luaMemoryLimit: luaMemoryLimit); foreach (var node in nodes) - node.Start(); + await node.RunAsync(); } /// @@ -195,7 +195,7 @@ public void CreateInstances( /// /// /// - public GarnetServer CreateInstance( + public GarnetApplication CreateInstance( int Port, bool cleanClusterConfig = true, bool disableEpochCollision = false, @@ -252,7 +252,11 @@ public GarnetServer CreateInstance( authPassword: clusterCreds.password, certificates: certificates); - return new GarnetServer(opts, loggerFactory); + var builder = GarnetApplication.CreateHostBuilder([], opts); + + var app = builder.Build(); + + return app; } diff --git a/test/Garnet.test/ObjectTestsForOutput.cs b/test/Garnet.test/ObjectTestsForOutput.cs index bcaf7b256a..8bca7b5a46 100644 --- a/test/Garnet.test/ObjectTestsForOutput.cs +++ b/test/Garnet.test/ObjectTestsForOutput.cs @@ -11,21 +11,21 @@ namespace Garnet.test [TestFixture] public class ObjectTestsForOutput { - protected GarnetServer server; + protected GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: false); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: false); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/ReadCacheTests.cs b/test/Garnet.test/ReadCacheTests.cs index 80aa968484..1cc0cad7fc 100644 --- a/test/Garnet.test/ReadCacheTests.cs +++ b/test/Garnet.test/ReadCacheTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -10,14 +11,14 @@ namespace Garnet.test [TestFixture] public class ReadCacheTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); + await server.RunAsync(); } [TearDown] diff --git a/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs b/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs index bac1958332..c36c6d116f 100644 --- a/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs +++ b/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs @@ -29,8 +29,8 @@ public async Task EmptyInput() File.CreateText(configurationFile).Close(); // Ensure Garnet starts up with default user only - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -51,8 +51,8 @@ public async Task NoDefaultRule() File.WriteAllText(configurationFile, "user testA on >password123 +@admin\r\nuser testB on >passw0rd >password +@admin "); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -77,8 +77,8 @@ public async Task WithDefaultRule() File.WriteAllText(configurationFile, "user testA on >password123 +@admin +@slow\r\nuser testB on >passw0rd >password +@admin\r\nuser default on nopass +@admin +@slow"); // Start up Garnet with a defined default user password - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -117,8 +117,8 @@ public async Task AclLoad() File.WriteAllText(configurationFile, originalConfigurationFile); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -188,8 +188,8 @@ public async Task AclLoadErrors() File.WriteAllText(configurationFile, originalConfigurationFile); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -243,8 +243,8 @@ public async Task DuplicateUserNames() var configurationFile = Path.Join(TestUtils.MethodTestDir, "users.acl"); File.WriteAllText(configurationFile, $"user test on >{DummyPassword} +@admin\r\nuser test off"); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -279,8 +279,10 @@ public void BadInputNonexistingFile() // NOTE: Do not create the configuration file var configurationFile = Path.Join(TestUtils.MethodTestDir, "users.acl"); + // TODO propagate the ACLException to builder + // Garnet should ignore the non-existing configuration file and start up with default user - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } /// @@ -294,8 +296,10 @@ public void BadInputMalformedStatement() var configurationFile = Path.Join(TestUtils.MethodTestDir, "users.acl"); File.WriteAllText(configurationFile, "user test on >password123 +@admin\r\nuser testB badinput on >passw0rd >password +@admin "); + // TODO propagate the ACLException to builder + // Ensure Garnet starts up and just ignores the malformed statement - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } // Test numeric RespCommand rejected @@ -313,7 +317,7 @@ public void BadInputMalformedStatement() File.WriteAllText(configurationFile, "user test on >password123 +none"); // Ensure Garnet starts up and just ignores the malformed statement - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } @@ -323,12 +327,12 @@ public void BadInputMalformedStatement() File.WriteAllText(configurationFile, "user test on >password123 +invalid"); // Ensure Garnet starts up and just ignores the malformed statement - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } } [Test] - public void AclSave() + public async Task AclSave() { // Create a modified ACL that (1) removes two users, (2) adds one user, (3) removes one password and (4) removes the default user var originalConfigurationFile = @@ -342,8 +346,8 @@ public void AclSave() File.WriteAllText(configurationFile, originalConfigurationFile); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/Resp/ACL/AclTest.cs b/test/Garnet.test/Resp/ACL/AclTest.cs index 9f5e614cda..725dde9ee8 100644 --- a/test/Garnet.test/Resp/ACL/AclTest.cs +++ b/test/Garnet.test/Resp/ACL/AclTest.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.IO; +using System.Threading.Tasks; using NUnit.Framework; namespace Garnet.test.Resp.ACL @@ -44,7 +45,7 @@ abstract class AclTest /// /// Garnet server instance to use in the tests. /// - protected GarnetServer server = null; + protected GarnetApplication server = null; /// /// Creates working directory @@ -60,11 +61,11 @@ public virtual void BaseSetup() /// Cleans up any running working instances /// [TearDown] - public virtual void BaseTearDown() + public virtual async Task BaseTearDown() { if (server != null) { - server.Dispose(); + await server.StopAsync(); server = null; } diff --git a/test/Garnet.test/Resp/ACL/BasicTests.cs b/test/Garnet.test/Resp/ACL/BasicTests.cs index bdbaa63651..1845a7e266 100644 --- a/test/Garnet.test/Resp/ACL/BasicTests.cs +++ b/test/Garnet.test/Resp/ACL/BasicTests.cs @@ -19,10 +19,10 @@ internal class BasicTests : AclTest /// Creates and starts the Garnet test server /// [SetUp] - public virtual void Setup() + public virtual async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); } /// diff --git a/test/Garnet.test/Resp/ACL/DeleteUserTests.cs b/test/Garnet.test/Resp/ACL/DeleteUserTests.cs index 69b142d32c..13dbe95212 100644 --- a/test/Garnet.test/Resp/ACL/DeleteUserTests.cs +++ b/test/Garnet.test/Resp/ACL/DeleteUserTests.cs @@ -18,10 +18,10 @@ class DeleteUserTests : AclTest /// Creates and starts the Garnet test server /// [SetUp] - public virtual void Setup() + public virtual async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); } /// diff --git a/test/Garnet.test/Resp/ACL/ParallelTests.cs b/test/Garnet.test/Resp/ACL/ParallelTests.cs index 129ff99027..0eb524e2fe 100644 --- a/test/Garnet.test/Resp/ACL/ParallelTests.cs +++ b/test/Garnet.test/Resp/ACL/ParallelTests.cs @@ -18,10 +18,10 @@ internal class ParallelTests : AclTest /// Creates and starts the Garnet test server /// [SetUp] - public virtual void Setup() + public virtual async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); } /// diff --git a/test/Garnet.test/Resp/ACL/RespCommandTests.cs b/test/Garnet.test/Resp/ACL/RespCommandTests.cs index f9a72c56fc..ddf9980dc9 100644 --- a/test/Garnet.test/Resp/ACL/RespCommandTests.cs +++ b/test/Garnet.test/Resp/ACL/RespCommandTests.cs @@ -24,14 +24,14 @@ public class RespCommandTests private IReadOnlyDictionary respCustomCommandsInfo; - private GarnetServer server; + private GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, defaultPassword: DefaultPassword, useAcl: true, enableLua: true); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, defaultPassword: DefaultPassword, useAcl: true, enableLua: true); // Register custom commands so we can test ACL'ing them ClassicAssert.IsTrue(TestUtils.TryGetCustomCommandsInfo(out respCustomCommandsInfo)); @@ -42,13 +42,13 @@ public void Setup() server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), new RespCommandsInfo { Arity = 4 }); server.Register.NewProcedure("SUM", () => new Sum()); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/Resp/ACL/SetUserTests.cs b/test/Garnet.test/Resp/ACL/SetUserTests.cs index 669e233531..5434b3c80c 100644 --- a/test/Garnet.test/Resp/ACL/SetUserTests.cs +++ b/test/Garnet.test/Resp/ACL/SetUserTests.cs @@ -20,11 +20,11 @@ class SetUserTests : AclTest /// Tests that new connections start with default user when no users are defined /// [Test] - public void PasswordlessDefaultUserTest() + public async Task PasswordlessDefaultUserTest() { // Create a new test server without password - should automatically login default user - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); // Check user is authenticated as default using var lightClientRequest = TestUtils.CreateRequest(); @@ -43,8 +43,8 @@ public void PasswordlessDefaultUserTest() public async Task ProtectedDefaultUserErrorHandlingTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -68,8 +68,8 @@ public async Task ProtectedDefaultUserErrorHandlingTest() public async Task ProtectedDefaultUserLoginImplicitTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -90,8 +90,8 @@ public async Task ProtectedDefaultUserLoginImplicitTest() public async Task ProtectedDefaultUserLoginExplicitTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -113,8 +113,8 @@ public async Task ProtectedDefaultUserLoginExplicitTest() public async Task EnableAndDisableUsers() { // Create a new test server without default password - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -168,8 +168,8 @@ public async Task EnableAndDisableUsers() public async Task AddPasswordFromCleartextTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -198,8 +198,8 @@ public async Task AddPasswordFromCleartextTest() public async Task AddPasswordFromHashTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -228,8 +228,8 @@ public async Task AddPasswordFromHashTest() public async Task RemovePasswordFromCleartextTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -260,8 +260,8 @@ public async Task RemovePasswordFromCleartextTest() public async Task RemovePasswordFromHashTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -292,8 +292,8 @@ public async Task RemovePasswordFromHashTest() public async Task AddDuplicatePasswordTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -325,8 +325,8 @@ public async Task AddDuplicatePasswordTest() public async Task PasswordlessUserTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -348,8 +348,8 @@ public async Task PasswordlessUserTest() public async Task ResetPasswordsTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -392,8 +392,8 @@ public async Task AddAndRemoveCategoryTest() const string TestCategory = "admin"; // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -448,8 +448,8 @@ public async Task AddAndRemoveCategoryTest() public async Task ResetUser() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -493,8 +493,8 @@ public async Task ResetUser() public async Task BadInputEmpty() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -518,8 +518,8 @@ public async Task BadInputEmpty() public async Task BadInputUnknownOperation() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -543,8 +543,8 @@ public async Task BadInputUnknownOperation() public async Task KeyPatternsWildcard() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); diff --git a/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs b/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs index af92c5dd47..9e75cf4e16 100644 --- a/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs +++ b/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs @@ -77,8 +77,8 @@ public async Task InvalidatingAuthorizationAsync() return true; }; - using GarnetServer server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, authenticationSettings: authSettings); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, authenticationSettings: authSettings); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -108,6 +108,8 @@ public async Task InvalidatingAuthorizationAsync() await c.ExecuteAsync("AUTH", "foo", "bar"); ClassicAssert.AreEqual(3, authCalls); + + await server.StopAsync(); } } } \ No newline at end of file diff --git a/test/Garnet.test/TestUtils.cs b/test/Garnet.test/TestUtils.cs index 4012b810ad..fbf3586f63 100644 --- a/test/Garnet.test/TestUtils.cs +++ b/test/Garnet.test/TestUtils.cs @@ -355,174 +355,6 @@ public static GarnetApplication CreateGarnetApplication( } } - /// - /// Create GarnetServer - /// - public static GarnetServer CreateGarnetServer( - string logCheckpointDir, - bool disablePubSub = false, - bool tryRecover = false, - bool lowMemory = false, - string MemorySize = default, - string PageSize = default, - bool enableAOF = false, - bool EnableTLS = false, - bool DisableObjects = false, - int metricsSamplingFreq = -1, - bool latencyMonitor = false, - int commitFrequencyMs = 0, - bool commitWait = false, - bool UseAzureStorage = false, - string defaultPassword = null, - bool useAcl = false, // NOTE: Temporary until ACL is enforced as default - string aclFile = null, - string objectStoreHeapMemorySize = default, - string objectStoreIndexSize = "16k", - string objectStoreIndexMaxSize = default, - string objectStoreReadCacheHeapMemorySize = default, - string indexSize = "1m", - string indexMaxSize = default, - string[] extensionBinPaths = null, - bool extensionAllowUnsignedAssemblies = true, - bool getSG = false, - int indexResizeFrequencySecs = 60, - IAuthenticationSettings authenticationSettings = null, - bool enableLua = false, - bool enableReadCache = false, - bool enableObjectStoreReadCache = false, - ILogger logger = null, - IEnumerable loadModulePaths = null, - string pubSubPageSize = null, - bool asyncReplay = false, - LuaMemoryManagementMode luaMemoryMode = LuaMemoryManagementMode.Native, - string luaMemoryLimit = "") - { - if (UseAzureStorage) - IgnoreIfNotRunningAzureTests(); - var _LogDir = logCheckpointDir; - if (UseAzureStorage) - _LogDir = $"{AzureTestContainer}/{AzureTestDirectory}"; - - if (logCheckpointDir != null && !UseAzureStorage) _LogDir = new DirectoryInfo(string.IsNullOrEmpty(_LogDir) ? "." : _LogDir).FullName; - - var _CheckpointDir = logCheckpointDir; - if (UseAzureStorage) - _CheckpointDir = $"{AzureTestContainer}/{AzureTestDirectory}"; - - if (logCheckpointDir != null && !UseAzureStorage) _CheckpointDir = new DirectoryInfo(string.IsNullOrEmpty(_CheckpointDir) ? "." : _CheckpointDir).FullName; - - if (useAcl) - { - if (authenticationSettings != null) - { - throw new ArgumentException($"Cannot set both {nameof(useAcl)} and {nameof(authenticationSettings)}"); - } - - authenticationSettings = new AclAuthenticationPasswordSettings(aclFile, defaultPassword); - } - else if (defaultPassword != null) - { - if (authenticationSettings != null) - { - throw new ArgumentException($"Cannot set both {nameof(defaultPassword)} and {nameof(authenticationSettings)}"); - } - - authenticationSettings = new PasswordAuthenticationSettings(defaultPassword); - } - - // Increase minimum thread pool size to 16 if needed - int threadPoolMinThreads = 0; - ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads); - if (workerThreads < 16 || completionPortThreads < 16) threadPoolMinThreads = 16; - - GarnetServerOptions opts = new(logger) - { - EnableStorageTier = logCheckpointDir != null, - LogDir = _LogDir, - CheckpointDir = _CheckpointDir, - Address = Address, - Port = Port, - DisablePubSub = disablePubSub, - Recover = tryRecover, - IndexSize = indexSize, - ObjectStoreIndexSize = objectStoreIndexSize, - EnableAOF = enableAOF, - EnableLua = enableLua, - CommitFrequencyMs = commitFrequencyMs, - WaitForCommit = commitWait, - TlsOptions = EnableTLS ? new GarnetTlsOptions( - certFileName: certFile, - certPassword: certPassword, - clientCertificateRequired: true, - certificateRevocationCheckMode: X509RevocationMode.NoCheck, - issuerCertificatePath: null, - null, 0, false, null, logger: logger) - : null, - DisableObjects = DisableObjects, - QuietMode = true, - MetricsSamplingFrequency = metricsSamplingFreq, - LatencyMonitor = latencyMonitor, - DeviceFactoryCreator = UseAzureStorage ? - () => new AzureStorageNamedDeviceFactory(AzureEmulatedStorageString, logger) - : () => new LocalStorageNamedDeviceFactory(logger: logger), - AuthSettings = authenticationSettings, - ExtensionBinPaths = extensionBinPaths, - ExtensionAllowUnsignedAssemblies = extensionAllowUnsignedAssemblies, - EnableScatterGatherGet = getSG, - IndexResizeFrequencySecs = indexResizeFrequencySecs, - ThreadPoolMinThreads = threadPoolMinThreads, - LoadModuleCS = loadModulePaths, - EnableReadCache = enableReadCache, - EnableObjectStoreReadCache = enableObjectStoreReadCache, - ReplicationOffsetMaxLag = asyncReplay ? -1 : 0, - LuaOptions = enableLua ? new LuaOptions(luaMemoryMode, luaMemoryLimit, logger) : null, - }; - - if (!string.IsNullOrEmpty(pubSubPageSize)) - opts.PubSubPageSize = pubSubPageSize; - - if (!string.IsNullOrEmpty(objectStoreHeapMemorySize)) - opts.ObjectStoreHeapMemorySize = objectStoreHeapMemorySize; - - if (!string.IsNullOrEmpty(objectStoreReadCacheHeapMemorySize)) - opts.ObjectStoreReadCacheHeapMemorySize = objectStoreReadCacheHeapMemorySize; - - if (indexMaxSize != default) opts.IndexMaxSize = indexMaxSize; - if (objectStoreIndexMaxSize != default) opts.ObjectStoreIndexMaxSize = objectStoreIndexMaxSize; - - if (lowMemory) - { - opts.MemorySize = opts.ObjectStoreLogMemorySize = MemorySize == default ? "1024" : MemorySize; - opts.PageSize = opts.ObjectStorePageSize = PageSize == default ? "512" : PageSize; - if (enableReadCache) - { - opts.ReadCacheMemorySize = opts.MemorySize; - opts.ReadCachePageSize = opts.PageSize; - } - - if (enableObjectStoreReadCache) - { - opts.ObjectStoreReadCacheLogMemorySize = opts.MemorySize; - opts.ObjectStoreReadCachePageSize = opts.PageSize; - } - } - - if (useTestLogger) - { - var loggerFactory = LoggerFactory.Create(builder => - { - builder.AddProvider(new NUnitLoggerProvider(TestContext.Progress, TestContext.CurrentContext.Test.MethodName, null, false, false, LogLevel.Trace)); - builder.SetMinimumLevel(LogLevel.Trace); - }); - - return new GarnetServer(opts, loggerFactory); - } - else - { - return new GarnetServer(opts); - } - } - /// /// Create logger factory for given TextWriter and loglevel /// E.g. Use with TestContext.Progress to print logs while test is running. @@ -543,7 +375,7 @@ public static ILoggerFactory CreateLoggerFactoryInstance(TextWriter textWriter, }); } - public static GarnetServer[] CreateGarnetCluster( + public static GarnetApplication[] CreateGarnetCluster( string checkpointDir, EndPointCollection endpoints, bool disablePubSub = false, @@ -581,7 +413,7 @@ public static GarnetServer[] CreateGarnetCluster( { if (UseAzureStorage) IgnoreIfNotRunningAzureTests(); - GarnetServer[] nodes = new GarnetServer[endpoints.Count]; + var nodes = new GarnetApplication[endpoints.Count]; for (int i = 0; i < nodes.Length; i++) { IPEndPoint endpoint = (IPEndPoint)endpoints[i]; @@ -631,7 +463,13 @@ public static GarnetServer[] CreateGarnetCluster( TestContext.Progress.WriteLine($"Waiting for Port {opts.Port} to become available for {TestContext.CurrentContext.WorkerId}:{iter++}"); Thread.Sleep(1000); } - nodes[i] = new GarnetServer(opts, loggerFactory); + + var builder = GarnetApplication.CreateHostBuilder([], opts); + + var app = builder.Build(); + + nodes[i] = app; + } return nodes; } From f1e0896a40ee108ad62f91ad86b244226f20420e Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 13:15:49 +0100 Subject: [PATCH 26/42] refactor and await teardown --- .../GarnetJSON/JsonCommandsTest.cs | 3 --- test/Garnet.test/IndexGrowthTests.cs | 2 -- test/Garnet.test/ReadCacheTests.cs | 4 ++-- test/Garnet.test/RespAdminCommandsTests.cs | 10 -------- test/Garnet.test/RespAofAzureTests.cs | 12 ---------- test/Garnet.test/RespAofTests.cs | 23 ------------------- test/Garnet.test/RespPubSubTests.cs | 4 ++-- test/Garnet.test/RespTests.cs | 14 +++++------ test/Garnet.test/TransactionTests.cs | 2 +- 9 files changed, 12 insertions(+), 62 deletions(-) diff --git a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs index 2249cc1511..0abf168625 100644 --- a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs +++ b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs @@ -103,7 +103,6 @@ public async Task SaveRecoverTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); RegisterCustomCommand(); @@ -120,7 +119,6 @@ public async Task SaveRecoverTest() [Test] public async Task AofUpsertRecoverTest() { - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(); @@ -136,7 +134,6 @@ public async Task AofUpsertRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(); diff --git a/test/Garnet.test/IndexGrowthTests.cs b/test/Garnet.test/IndexGrowthTests.cs index 9a59cb7fde..8961165199 100644 --- a/test/Garnet.test/IndexGrowthTests.cs +++ b/test/Garnet.test/IndexGrowthTests.cs @@ -171,7 +171,6 @@ public async Task IndexGrowthTestWithDiskReadAndCheckpoint() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, indexSize: "512", indexMaxSize: "1k"); await server.RunAsync(); @@ -236,7 +235,6 @@ public async Task ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k"); await server.RunAsync(); diff --git a/test/Garnet.test/ReadCacheTests.cs b/test/Garnet.test/ReadCacheTests.cs index 1cc0cad7fc..170a6f1430 100644 --- a/test/Garnet.test/ReadCacheTests.cs +++ b/test/Garnet.test/ReadCacheTests.cs @@ -22,9 +22,9 @@ public async Task Setup() } [TearDown] - public void TearDown() + public async void TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespAdminCommandsTests.cs b/test/Garnet.test/RespAdminCommandsTests.cs index 95fbc7122b..a27f7a2143 100644 --- a/test/Garnet.test/RespAdminCommandsTests.cs +++ b/test/Garnet.test/RespAdminCommandsTests.cs @@ -177,7 +177,6 @@ public async Task SeSaveRecoverTest([Values] bool disableObj, [Values] bool useA while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, UseAzureStorage: useAzure); await server.RunAsync(); @@ -210,7 +209,6 @@ public async Task SeSaveRecoverObjectTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); await server.RunAsync(); @@ -250,7 +248,6 @@ public async Task SeSaveRecoverCustomObjectTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); @@ -297,7 +294,6 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); @@ -318,7 +314,6 @@ public async Task SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryM { string sizeToString(int size) => size + "k"; - //server.Dispose(); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: sizeToString(memorySize), PageSize: sizeToString(pageSize)); await server.RunAsync(); @@ -340,7 +335,6 @@ public async Task SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryM while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, MemorySize: sizeToString(recoveryMemorySize), PageSize: sizeToString(pageSize), objectStoreHeapMemorySize: "64k"); await server.RunAsync(); @@ -369,7 +363,6 @@ public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recove { bool disableObj = true; - //server.Dispose(); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, lowMemory: true, MemorySize: memorySize, PageSize: "512", enableAOF: true); await server.RunAsync(); @@ -409,7 +402,6 @@ public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recove db.Execute("COMMITAOF"); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, tryRecover: true, lowMemory: true, MemorySize: recoveryMemorySize, PageSize: "512", enableAOF: true); await server.RunAsync(); @@ -428,7 +420,6 @@ public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recove [Test] public async Task SeAofRecoverTest() { - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); await server.RunAsync(); @@ -441,7 +432,6 @@ public async Task SeAofRecoverTest() db.Execute("COMMITAOF"); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, tryRecover: true); await server.RunAsync(); diff --git a/test/Garnet.test/RespAofAzureTests.cs b/test/Garnet.test/RespAofAzureTests.cs index 7f45ad1949..c8c1ab1c7d 100644 --- a/test/Garnet.test/RespAofAzureTests.cs +++ b/test/Garnet.test/RespAofAzureTests.cs @@ -55,7 +55,6 @@ public async Task AofUpsertStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -81,7 +80,6 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() } server.Store.WaitForCommit(); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -99,7 +97,6 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() [Test] public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true, UseAzureStorage: true); await server.RunAsync(); @@ -110,7 +107,6 @@ public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey1", "SeAofUpsertRecoverTestValue1"); db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -144,7 +140,6 @@ public async Task AofUpsertStoreCkptRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -172,7 +167,6 @@ public async Task AofRMWStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -208,7 +202,6 @@ public async Task AofDeleteStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -244,7 +237,6 @@ public async Task AofExpiryRMWStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -279,7 +271,6 @@ public async Task AofRMWObjectStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -326,7 +317,6 @@ public async Task AofDeleteObjectStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -363,7 +353,6 @@ public async Task AofRMWObjectStoreCopyUpdateRecoverTest() db.SortedSetAdd("AofRMWObjectStoreRecoverTestKey" + 1, newEntries); } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -419,7 +408,6 @@ public async Task AofMultiRMWStoreCkptRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); diff --git a/test/Garnet.test/RespAofTests.cs b/test/Garnet.test/RespAofTests.cs index 9f2c0d2fa5..7e976ff134 100644 --- a/test/Garnet.test/RespAofTests.cs +++ b/test/Garnet.test/RespAofTests.cs @@ -62,7 +62,6 @@ public async Task AofUpsertStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -88,7 +87,6 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() } server.Store.WaitForCommit(); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -107,7 +105,6 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() [CancelAfter(10_000)] public async Task AofUpsertStoreCommitTaskRecoverTest() { - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitFrequencyMs: 100); await server.RunAsync(); @@ -120,7 +117,6 @@ public async Task AofUpsertStoreCommitTaskRecoverTest() } server.Store.WaitForCommit(); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -138,7 +134,6 @@ public async Task AofUpsertStoreCommitTaskRecoverTest() [Test] public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); await server.RunAsync(); @@ -149,7 +144,6 @@ public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey1", "SeAofUpsertRecoverTestValue1"); db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -167,7 +161,6 @@ public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() [Test] public async Task AofTransactionStoreAutoCommitCommitWaitRecoverTest() { - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); await server.RunAsync(); @@ -181,7 +174,6 @@ public async Task AofTransactionStoreAutoCommitCommitWaitRecoverTest() ClassicAssert.IsTrue(transaction.Execute()); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -215,7 +207,6 @@ public async Task AofUpsertStoreCkptRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -247,7 +238,6 @@ public async Task AofRMWStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -286,7 +276,6 @@ public async Task AofDeleteStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -322,7 +311,6 @@ public async Task AofExpiryRMWStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -357,7 +345,6 @@ public async Task AofRMWObjectStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -404,7 +391,6 @@ public async Task AofDeleteObjectStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -441,7 +427,6 @@ public async Task AofRMWObjectStoreCopyUpdateRecoverTest() db.SortedSetAdd("AofRMWObjectStoreRecoverTestKey" + 1, newEntries); } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -485,7 +470,6 @@ public async Task AofUpsertObjectStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -509,7 +493,6 @@ void RegisterCustomCommand(GarnetApplication gServer) gServer.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), respCustomCommandsInfo["MYDICTGET"]); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(server); @@ -537,7 +520,6 @@ void RegisterCustomCommand(GarnetApplication gServer) } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(server); @@ -564,7 +546,6 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str ClassicAssert.AreEqual(listValue, (string)retList[0]); } - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); @@ -583,7 +564,6 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); @@ -633,7 +613,6 @@ public async Task AofMultiRMWStoreCkptRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -665,7 +644,6 @@ public async Task AofListObjectStoreRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -700,7 +678,6 @@ public async Task AofCustomTxnRecoverTest() } server.Store.CommitAOF(true); - //server.Dispose(false); await server.StopAsync(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); diff --git a/test/Garnet.test/RespPubSubTests.cs b/test/Garnet.test/RespPubSubTests.cs index c9a9cc498e..ef12898cc9 100644 --- a/test/Garnet.test/RespPubSubTests.cs +++ b/test/Garnet.test/RespPubSubTests.cs @@ -26,9 +26,9 @@ public async Task Setup() } [TearDown] - public void TearDown() + public async void TearDown() { - server.Dispose(); + await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTests.cs b/test/Garnet.test/RespTests.cs index 338f12bf5f..a59b050f1a 100644 --- a/test/Garnet.test/RespTests.cs +++ b/test/Garnet.test/RespTests.cs @@ -1361,7 +1361,7 @@ public void SingleDelete() [Test] public async Task SingleDeleteWithObjectStoreDisabled() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); @@ -1393,7 +1393,7 @@ private string GetRandomString(int len) [Test] public async Task SingleDeleteWithObjectStoreDisable_LTM() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); @@ -1435,7 +1435,7 @@ public async Task MultiKeyDelete([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); await server.RunAsync(); @@ -1503,7 +1503,7 @@ public async Task MultiKeyUnlink([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); await server.RunAsync(); @@ -1569,7 +1569,7 @@ public async Task SingleExists([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); await server.RunAsync(); @@ -1834,7 +1834,7 @@ public async Task SingleRenameKeyEdgeCase([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); await server.RunAsync(); @@ -3733,7 +3733,7 @@ public void HelloTest1() public async Task AsyncTest1() { // Set up low-memory database - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); await server.RunAsync(); diff --git a/test/Garnet.test/TransactionTests.cs b/test/Garnet.test/TransactionTests.cs index dbeea0b249..a8d8c0c386 100644 --- a/test/Garnet.test/TransactionTests.cs +++ b/test/Garnet.test/TransactionTests.cs @@ -32,7 +32,7 @@ public async Task TearDown() public async Task SetUpWithLowMemory() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); await server.RunAsync(); From 80592ff5141a26793300b730aab8724ae695ac65 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 15:05:50 +0100 Subject: [PATCH 27/42] fix more cluster tests --- playground/TstRunner/Program.cs | 9 +- .../ClusterAadAuthTests.cs | 15 +- .../ClusterAuthCommsTests.cs | 18 +- .../ClusterManagementTests.cs | 60 +++---- .../ClusterMigrateTLSTests.cs | 47 ++--- .../ClusterMigrateTests.cs | 113 ++++++------ .../ClusterNegativeTests.cs | 9 +- .../ClusterRedirectTests.cs | 11 +- .../ClusterReplicationTLSTests.cs | 39 ++-- .../ClusterReplicationTests.cs | 168 +++++++++--------- .../Garnet.test.cluster/ClusterTestContext.cs | 5 +- .../ClusterSlotVerificationTests.cs | 5 +- test/Garnet.test/CacheSizeTrackerTests.cs | 7 +- test/Garnet.test/TestUtils.cs | 2 +- 14 files changed, 261 insertions(+), 247 deletions(-) diff --git a/playground/TstRunner/Program.cs b/playground/TstRunner/Program.cs index ad8d1b36a2..8f54557eed 100644 --- a/playground/TstRunner/Program.cs +++ b/playground/TstRunner/Program.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Threading.Tasks; using Garnet.test; using Garnet.test.cluster; @@ -10,7 +11,7 @@ namespace TstRunner { public class Program { - static void Main() + static async Task Main() { //Trace.Listeners.Add(new ConsoleTraceListener()); @@ -42,7 +43,7 @@ static void Main() clusterReplicationTests.SetLogTextWriter(Console.Out); var clusterReplicationTestItems = clusterReplicationTests.GetUnitTests(); foreach (var item in clusterReplicationTestItems) - RunTest(clusterReplicationTests, item.Item1, item.Item2); + await RunTest(clusterReplicationTests, item.Item1, item.Item2); swatch.Stop(); Console.WriteLine($">>>>>>>>>> run: {i++} duration (sec):{swatch.ElapsedMilliseconds / 1000}"); @@ -50,14 +51,14 @@ static void Main() } } - private static void RunTest(T test, Action testCase, string name = "") + private static async Task RunTest(T test, Task testCase, string name = "") { dynamic ctest = test; try { Console.WriteLine($"\tStarted {name} on {DateTime.Now}"); ctest.Setup(); - testCase(); + await testCase; } finally { diff --git a/test/Garnet.test.cluster/ClusterAadAuthTests.cs b/test/Garnet.test.cluster/ClusterAadAuthTests.cs index 86d6bce69d..47f981ca85 100644 --- a/test/Garnet.test.cluster/ClusterAadAuthTests.cs +++ b/test/Garnet.test.cluster/ClusterAadAuthTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Claims; +using System.Threading.Tasks; using Garnet.server.Auth.Settings; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; @@ -39,7 +40,7 @@ public void TearDown() [Test, Order(1)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ValidateClusterAuthWithObjectId() + public async Task ValidateClusterAuthWithObjectId() { var nodes = 2; var audience = Guid.NewGuid().ToString(); @@ -56,12 +57,12 @@ public void ValidateClusterAuthWithObjectId() var authSettings = new AadAuthenticationSettings([appId], [audience], [issuer], new MockIssuerSigningTokenProvider(new List { tokenGenerator.SecurityKey }, context.logger), true); var token = tokenGenerator.CreateToken(tokenClaims, DateTime.Now.AddMinutes(10)); - ValidateConnectionsWithToken(objId, token, nodes, authSettings); + await ValidateConnectionsWithToken(objId, token, nodes, authSettings); } [Test, Order(2)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ValidateClusterAuthWithGroupOid() + public async Task ValidateClusterAuthWithGroupOid() { var nodes = 2; var audience = Guid.NewGuid().ToString(); @@ -79,16 +80,15 @@ public void ValidateClusterAuthWithGroupOid() }; var authSettings = new AadAuthenticationSettings([appId], [audience], [issuer], new MockIssuerSigningTokenProvider(new List { tokenGenerator.SecurityKey }, context.logger), true); var token = tokenGenerator.CreateToken(tokenClaims, DateTime.Now.AddMinutes(10)); - ValidateConnectionsWithToken(groupIds.First(), token, nodes, authSettings); + await ValidateConnectionsWithToken(groupIds.First(), token, nodes, authSettings); } - private void ValidateConnectionsWithToken(string aclUsername, string token, int nodeCount, AadAuthenticationSettings authenticationSettings) + private async Task ValidateConnectionsWithToken(string aclUsername, string token, int nodeCount, AadAuthenticationSettings authenticationSettings) { var userCredential = new ServerCredential { user = aclUsername, IsAdmin = true, IsClearText = true }; var clientCredentials = new ServerCredential { user = aclUsername, password = token }; context.GenerateCredentials([userCredential]); - context.CreateInstances(nodeCount, useAcl: true, clusterCreds: clientCredentials, authenticationSettings: authenticationSettings); - + await context.CreateInstances(nodeCount, useAcl: true, clusterCreds: clientCredentials, authenticationSettings: authenticationSettings); context.CreateConnection(useTLS: false, clientCreds: clientCredentials); @@ -99,7 +99,6 @@ private void ValidateConnectionsWithToken(string aclUsername, string token, int var ex = Assert.Throws(() => context.clusterTestUtils.Authenticate(i, "randomUserId", clientCredentials.password, context.logger)); ClassicAssert.AreEqual("WRONGPASS Invalid username/password combination", ex.Message); } - } } } \ No newline at end of file diff --git a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs index da4438cb46..783cdcc4bf 100644 --- a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs +++ b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs @@ -34,7 +34,7 @@ public void TearDown() [Test, Order(1)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) + public async Task ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) { var nodes = 6; @@ -44,12 +44,12 @@ public void ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) if (useDefaultUserForInterNodeComms) { // Create instances, feed generated acl file and use default user for cluster auth - context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("default")); + await context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("default")); } else { // Create instances, feed generated acl file and use admin user for cluster auth - context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("admin")); + await context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("admin")); } context.CreateConnection(useTLS: false, clientCreds: context.credManager.GetUserCredentials("admin")); @@ -66,7 +66,7 @@ public void ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) [Test, Order(2)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterNodeComms) + public async Task ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterNodeComms) { var shards = 3; @@ -74,7 +74,7 @@ public void ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterN context.GenerateCredentials(); // Create instances but do not provide credentials through server options - context.CreateInstances(shards, useAcl: true); + await context.CreateInstances(shards, useAcl: true); // Connect as admin context.CreateConnection(clientCreds: context.credManager.GetUserCredentials("admin")); @@ -112,14 +112,14 @@ public void ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterN [Test, Order(3)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterReplicationAuth() + public async Task ClusterReplicationAuth() { var shards = 3; // Generate default ACL file context.GenerateCredentials(); // Create instances but do not provide credentials through server options - context.CreateInstances(shards, useAcl: true, enableAOF: true); + await context.CreateInstances(shards, useAcl: true, enableAOF: true); // Connect as admin context.CreateConnection(clientCreds: context.credManager.GetUserCredentials("admin")); @@ -179,10 +179,10 @@ public void ClusterReplicationAuth() [Test, Order(4)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterSimpleFailoverAuth() + public async Task ClusterSimpleFailoverAuth() { // Setup single primary populate and then attach replicas - ClusterReplicationAuth(); + await ClusterReplicationAuth(); context.ClusterFailoveSpinWait(replicaNodeIndex: 1, logger: context.logger); diff --git a/test/Garnet.test.cluster/ClusterManagementTests.cs b/test/Garnet.test.cluster/ClusterManagementTests.cs index a890abc32b..2a1798e3a1 100644 --- a/test/Garnet.test.cluster/ClusterManagementTests.cs +++ b/test/Garnet.test.cluster/ClusterManagementTests.cs @@ -38,11 +38,11 @@ public void TearDown() [Test, Order(1)] [TestCase(0, 16383)] [TestCase(1234, 5678)] - public void ClusterSlotsTest(int startSlot, int endSlot) + public async Task ClusterSlotsTest(int startSlot, int endSlot) { var slotRanges = new List<(int, int)>[1]; slotRanges[0] = [(startSlot, endSlot)]; - context.CreateInstances(defaultShards); + await context.CreateInstances(defaultShards); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(customSlotRanges: slotRanges, logger: context.logger); @@ -58,9 +58,9 @@ public void ClusterSlotsTest(int startSlot, int endSlot) } [Test, Order(2)] - public void ClusterSlotRangesTest() + public async Task ClusterSlotRangesTest() { - context.CreateInstances(defaultShards); + await context.CreateInstances(defaultShards); context.CreateConnection(); var slotRanges = new List<(int, int)>[3]; slotRanges[0] = [(5680, 6150), (12345, 14567)]; @@ -97,10 +97,10 @@ public void ClusterSlotRangesTest() } [Test, Order(3)] - public void ClusterForgetTest() + public async Task ClusterForgetTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -127,10 +127,10 @@ public void ClusterForgetTest() } [Test, Order(4)] - public void ClusterResetTest() + public async Task ClusterResetTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -172,10 +172,10 @@ public void ClusterResetTest() } [Test, Order(4)] - public void ClusterResetFailsForMasterWithKeysInSlotsTest() + public async Task ClusterResetFailsForMasterWithKeysInSlotsTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -202,10 +202,10 @@ public void ClusterResetFailsForMasterWithKeysInSlotsTest() } [Test, Order(4)] - public void ClusterResetFailsForMasterWithKeysInSlotsObjectStoreTest() + public async Task ClusterResetFailsForMasterWithKeysInSlotsObjectStoreTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); context.kvPairsObj = new Dictionary>(); @@ -229,10 +229,10 @@ public void ClusterResetFailsForMasterWithKeysInSlotsObjectStoreTest() } [Test, Order(4)] - public void ClusterResetAfterFLushAllTest() + public async Task ClusterResetAfterFLushAllTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); context.kvPairsObj = new Dictionary>(); @@ -289,7 +289,7 @@ private void VerifyClusterResetFails(bool softReset = true) public async Task ClusterResetDisposesGossipConnections() { var node_count = 3; - context.CreateInstances(node_count, metricsSamplingFrequency: 1); + await context.CreateInstances(node_count, metricsSamplingFrequency: 1); context.CreateConnection(); var endpoints = context.clusterTestUtils.GetEndpoints(); for (int i = 0; i < endpoints.Length - 1; i++) @@ -323,10 +323,10 @@ private string GetStat(IServer server, string section, string statName) } [Test, Order(5)] - public void ClusterKeySlotTest() + public async Task ClusterKeySlotTest() { var node_count = 1; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); (string, int)[] testCases = [("6e6bzswz8}", 7038), @@ -379,7 +379,7 @@ public void ClusterKeySlotTest() public async Task ClusterRestartNodeDropGossip() { var logger = context.loggerFactory.CreateLogger("ClusterRestartNodeDropGossip"); - context.CreateInstances(defaultShards); + await context.CreateInstances(defaultShards); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: logger); @@ -409,10 +409,10 @@ public async Task ClusterRestartNodeDropGossip() } [Test, Order(7)] - public void ClusterClientList() + public async Task ClusterClientList() { const int NodeCount = 4; - context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); + await context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(NodeCount / 2, 1, logger: context.logger); @@ -455,10 +455,10 @@ public void ClusterClientList() } [Test, Order(7)] - public void ClusterClientKill() + public async Task ClusterClientKill() { const int NodeCount = 4; - context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); + await context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(NodeCount / 2, 1, logger: context.logger); @@ -470,12 +470,12 @@ public void ClusterClientKill() } [Test, Order(7)] - public void ClusterClientKillSlave() + public async Task ClusterClientKillSlave() { // Test SLAVE separately - it's equivalent to REPLICA, but needed for compatibility const int NodeCount = 4; - context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); + await context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(NodeCount / 2, 1, logger: context.logger); @@ -485,10 +485,10 @@ public void ClusterClientKillSlave() } [Test, Order(8)] - public void FailoverBadOptions() + public async Task FailoverBadOptions() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -520,10 +520,10 @@ public void FailoverBadOptions() } [Test, Order(9)] - public void ClusterFailoverBadOptions() + public async Task ClusterFailoverBadOptions() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -555,10 +555,10 @@ public void ClusterFailoverBadOptions() } [Test, Order(10)] - public void ClusterSetSlotBadOptions() + public async Task ClusterSetSlotBadOptions() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); diff --git a/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs b/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs index 85f47f96ab..5f07bb6033 100644 --- a/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs +++ b/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Threading.Tasks; using NUnit.Framework; namespace Garnet.test.cluster { [TestFixture, NonParallelizable] - public unsafe class ClusterTLSMT + public class ClusterTLSMT { ClusterMigrateTests tests; @@ -26,57 +27,57 @@ public void TearDown() [Test, Order(1)] [Category("CLUSTER")] - public void ClusterTLSInitialize() - => tests.ClusterSimpleInitialize(); + public async Task ClusterTLSInitialize() + => await tests.ClusterSimpleInitialize(); [Test, Order(2)] [Category("CLUSTER")] - public void ClusterTLSSlotInfo() - => tests.ClusterSimpleSlotInfo(); + public async Task ClusterTLSSlotInfo() + => await tests.ClusterSimpleSlotInfo(); [Test, Order(3)] [Category("CLUSTER")] - public void ClusterTLSAddDelSlots() - => tests.ClusterAddDelSlots(); + public async Task ClusterTLSAddDelSlots() + => await tests.ClusterAddDelSlots(); [Test, Order(4)] [Category("CLUSTER")] - public void ClusterTLSSlotChangeStatus() - => tests.ClusterSlotChangeStatus(); + public async Task ClusterTLSSlotChangeStatus() + => await tests.ClusterSlotChangeStatus(); [Test, Order(5)] [Category("CLUSTER")] - public void ClusterTLSRedirectMessage() - => tests.ClusterRedirectMessage(); + public async Task ClusterTLSRedirectMessage() + => await tests.ClusterRedirectMessage(); [Test, Order(6)] [Category("CLUSTER")] - public void ClusterTLSMigrateSlots() - => tests.ClusterSimpleMigrateSlots(); + public async Task ClusterTLSMigrateSlots() + => await tests.ClusterSimpleMigrateSlots(); [Test, Order(7)] [Category("CLUSTER")] - public void ClusterTLSMigrateSlotsExpiry() - => tests.ClusterSimpleMigrateSlotsExpiry(); + public async Task ClusterTLSMigrateSlotsExpiry() + => await tests.ClusterSimpleMigrateSlotsExpiry(); [Test, Order(8)] [Category("CLUSTER")] - public void ClusterTLSMigrateSlotsWithObjects() - => tests.ClusterSimpleMigrateSlotsWithObjects(); + public async Task ClusterTLSMigrateSlotsWithObjects() + => await tests.ClusterSimpleMigrateSlotsWithObjects(); [Test, Order(9)] [Category("CLUSTER")] - public void ClusterTLSMigrateKeys() - => tests.ClusterSimpleMigrateKeys(); + public async Task ClusterTLSMigrateKeys() + => await tests.ClusterSimpleMigrateKeys(); [Test, Order(10)] [Category("CLUSTER")] - public void ClusterTLSMigrateKeysWithObjects() - => tests.ClusterSimpleMigrateKeysWithObjects(); + public async Task ClusterTLSMigrateKeysWithObjects() + => await tests.ClusterSimpleMigrateKeysWithObjects(); [Test, Order(11)] [Category("CLUSTER")] - public void ClusterTLSMigratetWithReadWrite() - => tests.ClusterSimpleMigrateWithReadWrite(); + public async Task ClusterTLSMigratetWithReadWrite() + => await tests.ClusterSimpleMigrateWithReadWrite(); } } \ No newline at end of file diff --git a/test/Garnet.test.cluster/ClusterMigrateTests.cs b/test/Garnet.test.cluster/ClusterMigrateTests.cs index 7ddc728d53..549beac2e3 100644 --- a/test/Garnet.test.cluster/ClusterMigrateTests.cs +++ b/test/Garnet.test.cluster/ClusterMigrateTests.cs @@ -18,36 +18,36 @@ namespace Garnet.test.cluster { [TestFixture(false), NonParallelizable] - public unsafe class ClusterMigrateTests(bool UseTLS) + public class ClusterMigrateTests(bool UseTLS) { const int testTimeout = 100000; - public (Action, string)[] GetUnitTests() + public (Task, string)[] GetUnitTests() { - (Action, string)[] x = + (Task, string)[] x = [ //1 - new(ClusterSimpleInitialize, "ClusterSimpleInitialize()"), + new(ClusterSimpleInitialize(), "ClusterSimpleInitialize()"), //2 - new(ClusterSimpleSlotInfo, "ClusterSimpleSlotInfo()"), + new(ClusterSimpleSlotInfo(), "ClusterSimpleSlotInfo()"), //3 - new(ClusterAddDelSlots, "ClusterAddDelSlots()"), + new(ClusterAddDelSlots(), "ClusterAddDelSlots()"), //4 - new(ClusterSlotChangeStatus, "ClusterSlotChangeStatus()"), + new(ClusterSlotChangeStatus(), "ClusterSlotChangeStatus()"), //5 - new(ClusterRedirectMessage, "ClusterRedirectMessage()"), + new(ClusterRedirectMessage(), "ClusterRedirectMessage()"), //6 - new(ClusterSimpleMigrateSlots, "ClusterSimpleMigrateSlots()"), + new(ClusterSimpleMigrateSlots(), "ClusterSimpleMigrateSlots()"), //7 - new(ClusterSimpleMigrateSlotsExpiry, "ClusterSimpleMigrateSlotsExpiry()"), + new(ClusterSimpleMigrateSlotsExpiry(), "ClusterSimpleMigrateSlotsExpiry()"), //8 - new(ClusterSimpleMigrateSlotsWithObjects, "ClusterSimpleMigrateSlotsWithObjects()"), + new(ClusterSimpleMigrateSlotsWithObjects(), "ClusterSimpleMigrateSlotsWithObjects()"), //9 - new(ClusterSimpleMigrateKeys, "ClusterSimpleMigrateKeys()"), + new(ClusterSimpleMigrateKeys(), "ClusterSimpleMigrateKeys()"), //10 - new(ClusterSimpleMigrateKeysWithObjects, "ClusterSimpleMigrateKeysWithObjects()"), + new(ClusterSimpleMigrateKeysWithObjects(), "ClusterSimpleMigrateKeysWithObjects()"), //11 - new(ClusterSimpleMigrateWithReadWrite, "ClusterSimpleMigrateWithReadWrite()"), + new(ClusterSimpleMigrateWithReadWrite(), "ClusterSimpleMigrateWithReadWrite()"), ]; return x; } @@ -234,9 +234,9 @@ private void CreateMultiSlotData( [Test, Order(1)] [Category("CLUSTER")] - public void ClusterSimpleInitialize() + public async Task ClusterSimpleInitialize() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.logger.LogDebug("0. ClusterSimpleInitialize started"); @@ -254,9 +254,9 @@ public void ClusterSimpleInitialize() [Test, Order(2)] [Category("CLUSTER")] - public void ClusterSimpleSlotInfo() + public async Task ClusterSimpleSlotInfo() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.logger.LogDebug("0. ClusterSimpleSlotInfoTest started"); @@ -283,9 +283,9 @@ public void ClusterSimpleSlotInfo() [Test, Order(3)] [Category("CLUSTER")] - public void ClusterAddDelSlots() + public async Task ClusterAddDelSlots() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.logger.LogDebug("0. ClusterAddDelSlotsTest started"); @@ -360,10 +360,10 @@ public void ClusterAddDelSlots() [Test, Order(4)] [Category("CLUSTER")] - public void ClusterSlotChangeStatus() + public async Task ClusterSlotChangeStatus() { context.logger.LogDebug("0. ClusterSlotChangeStatusTest started"); - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); var sourcePortIndex = 1; @@ -508,11 +508,11 @@ public void ClusterSlotChangeStatus() [Test, Order(5)] [Category("CLUSTER")] - public void ClusterRedirectMessage() + public async Task ClusterRedirectMessage() { context.logger.LogDebug("0. ClusterRedirectMessageTest started"); var Shards = 2; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); var key = Encoding.ASCII.GetBytes("{abc}0"); @@ -565,12 +565,12 @@ public void ClusterRedirectMessage() [Test, Order(6)] [Category("CLUSTER")] - public void ClusterSimpleMigrateSlots() + public async Task ClusterSimpleMigrateSlots() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsTest started"); var Port = TestUtils.Port; var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -653,10 +653,10 @@ public void ClusterSimpleMigrateSlots() [Test, Order(7)] [Category("CLUSTER")] - public void ClusterSimpleMigrateSlotsExpiry() + public async Task ClusterSimpleMigrateSlotsExpiry() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsExpiryTest started"); - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -839,12 +839,12 @@ private string DoZCOUNT(int nodeIndex, byte[] key, out int count, out string add [Test, Order(8)] [Category("CLUSTER")] - public void ClusterSimpleMigrateSlotsWithObjects() + public async Task ClusterSimpleMigrateSlotsWithObjects() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsWithObjectsTest started"); var Port = TestUtils.Port; var Shards = defaultShards; - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -895,10 +895,10 @@ public void ClusterSimpleMigrateSlotsWithObjects() [Test, Order(9)] [Category("CLUSTER")] - public void ClusterSimpleMigrateKeys() + public async Task ClusterSimpleMigrateKeys() { context.logger.LogDebug("0. ClusterSimpleMigrateKeysTest started"); - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1003,12 +1003,12 @@ public void ClusterSimpleMigrateKeys() [Test, Order(10)] [Category("CLUSTER")] - public void ClusterSimpleMigrateKeysWithObjects() + public async Task ClusterSimpleMigrateKeysWithObjects() { context.logger.LogDebug("0. ClusterSimpleMigrateKeysWithObjectsTest started"); var Port = TestUtils.Port; var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1231,11 +1231,11 @@ private void OperateOnSlotsTask(Dictionary> data [Test, Order(11)] [Category("CLUSTER")] - public void ClusterSimpleMigrateWithReadWrite() + public async Task ClusterSimpleMigrateWithReadWrite() { context.logger.LogDebug("0. ClusterSimpleMigrateTestWithReadWrite started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1291,9 +1291,9 @@ public void ClusterSimpleMigrateWithReadWrite() [Test, Order(12)] [Category("CLUSTER")] - public void ClusterSimpleTxn() + public async Task ClusterSimpleTxn() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); List<(string, ICollection)> commands = []; @@ -1337,11 +1337,11 @@ public void ClusterSimpleTxn() [Test, Order(13)] [Category("CLUSTER")] [TestCaseSource("_slotranges")] - public void ClusterSimpleMigrateSlotsRanges(List migrateRange) + public async Task ClusterSimpleMigrateSlotsRanges(List migrateRange) { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsRanges started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1389,11 +1389,11 @@ public void ClusterSimpleMigrateSlotsRanges(List migrateRange) [Test, Order(14)] [Category("CLUSTER")] [TestCaseSource("_slotranges")] - public void ClusterSimpleMigrateWithAuth(List migrateRange) + public async Task ClusterSimpleMigrateWithAuth(List migrateRange) { context.logger.LogDebug("0. ClusterSimpleMigrateWithAuth started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1441,11 +1441,11 @@ public void ClusterSimpleMigrateWithAuth(List migrateRange) [Test, Order(15)] [Category("CLUSTER")] - public void ClusterAllowWritesDuringMigrateTest() + public async Task ClusterAllowWritesDuringMigrateTest() { context.logger.LogDebug("0. ClusterSimpleMigrateTestWithReadWrite started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1570,11 +1570,11 @@ Task WriteWorkload(IPEndPoint endPoint, byte[] key, int keyLen = 16) [Test, Order(16)] [Category("CLUSTER")] - public void ClusterMigrateForgetTest() + public async Task ClusterMigrateForgetTest() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsRanges started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1611,10 +1611,10 @@ public void ClusterMigrateForgetTest() [Test, Order(17)] [Category("CLUSTER")] - public void ClusterMigrateDataSlotsRange() + public async Task ClusterMigrateDataSlotsRange() { var Shards = 2; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var srcNodeIndex = 0; @@ -1706,10 +1706,10 @@ public void ClusterMigrateIncreasingPayload([Values] bool expiration, [Values] b ClusterMigrateExpirationWithVaryingPayload(expiration, data); } - private void ClusterMigrateExpirationWithVaryingPayload(bool expiration, List<(byte[], byte[])> data) + private async void ClusterMigrateExpirationWithVaryingPayload(bool expiration, List<(byte[], byte[])> data) { var Shards = 2; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var srcNodeIndex = 0; @@ -1777,14 +1777,14 @@ private void ClusterMigrateExpirationWithVaryingPayload(bool expiration, List<(b [Order(20), CancelAfter(testTimeout)] [TestCase(true)] [TestCase(false)] - public void ClusterMigrateSlotWalk(bool slots, CancellationToken cancellationToken) + public async Task ClusterMigrateSlotWalk(bool slots, CancellationToken cancellationToken) { var sourceNode = 0; var shards = 5; var targetNode = shards - 1; var slotCount = 10; - SetupInstances(sourceNode, out var nodeIds, out var nodeEndpoints); + var (nodeIds, nodeEndpoints) = await SetupInstances(sourceNode); for (var slot = 0; slot < slotCount; slot++) { @@ -1884,9 +1884,12 @@ void MigrateSlots() ValidateConfig(); - void SetupInstances(int sourceNode, out string[] nodeIds, out IPEndPoint[] nodeEndpoints) + async Task<(string[] nodeIds, IPEndPoint[] nodeEndpoints)> SetupInstances(int sourceNode) { - context.CreateInstances(shards, useTLS: UseTLS); + string[] nodeIds = null; + IPEndPoint[] nodeEndpoints = null; + + await context.CreateInstances(shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); // Assign all slots to first node @@ -1912,6 +1915,8 @@ void SetupInstances(int sourceNode, out string[] nodeIds, out IPEndPoint[] nodeE nodeEndpoints = new IPEndPoint[shards]; for (var i = 0; i < shards; i++) nodeEndpoints[i] = context.clusterTestUtils.GetEndPoint(i); + + return (nodeIds, nodeEndpoints); } void ValidateConfig() diff --git a/test/Garnet.test.cluster/ClusterNegativeTests.cs b/test/Garnet.test.cluster/ClusterNegativeTests.cs index 71b2ac8a76..f4a91a4b9b 100644 --- a/test/Garnet.test.cluster/ClusterNegativeTests.cs +++ b/test/Garnet.test.cluster/ClusterNegativeTests.cs @@ -8,6 +8,7 @@ using System.Net.Sockets; using System.Text; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -75,9 +76,9 @@ public void TearDown() [TestCase("BEGIN_REPLICA_RECOVER", new int[] { 0, 1, 2, 3, 4, 5, 6, 8, 9 })] [TestCase("FAILSTOPWRITES", new int[] { 0, 2, 3, 4 })] [TestCase("FAILREPLICATIONOFFSET", new int[] { 0, 2, 3, 4 })] - public void ClusterCommandWrongParameters(string subcommand, params int[] invalidCount) + public async Task ClusterCommandWrongParameters(string subcommand, params int[] invalidCount) { - context.CreateInstances(1); + await context.CreateInstances(1); using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); socket.NoDelay = true; @@ -111,9 +112,9 @@ public void ClusterCommandWrongParameters(string subcommand, params int[] invali [Category("CLUSTER")] [TestCase(1024)] [TestCase(10240)] - public void ClusterAddSlotsPartialPackage(int chunkSize) + public async Task ClusterAddSlotsPartialPackage(int chunkSize) { - context.CreateInstances(1); + await context.CreateInstances(1); using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); socket.NoDelay = true; socket.Connect(IPAddress.Loopback, 7000); diff --git a/test/Garnet.test.cluster/ClusterRedirectTests.cs b/test/Garnet.test.cluster/ClusterRedirectTests.cs index cdf6607b01..f550eebd6a 100644 --- a/test/Garnet.test.cluster/ClusterRedirectTests.cs +++ b/test/Garnet.test.cluster/ClusterRedirectTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.common; using Microsoft.Extensions.Logging; using NUnit.Framework; @@ -12,7 +13,7 @@ namespace Garnet.test.cluster { [TestFixture, NonParallelizable] - public unsafe class ClusterRedirectTests + public class ClusterRedirectTests { ClusterTestContext context; @@ -638,13 +639,13 @@ private void SendToMigratingNode( [Test, Order(1)] [Category("CLUSTER")] - public void ClusterSingleKeyRedirectionTests() + public async Task ClusterSingleKeyRedirectionTests() { context.logger.LogDebug("0. ClusterSingleKeyRedirectionTests started"); var Port = ClusterTestContext.Port; var Shards = context.defaultShards; - context.CreateInstances(Shards, cleanClusterConfig: true); + await context.CreateInstances(Shards, cleanClusterConfig: true); context.CreateConnection(); var connections = ClusterTestUtils.CreateLightRequestConnections(Enumerable.Range(Port, Shards).ToArray()); @@ -703,13 +704,13 @@ public void ClusterSingleKeyRedirectionTests() [Test, Order(2)] [Category("CLUSTER")] - public void ClusterMultiKeyRedirectionTests() + public async Task ClusterMultiKeyRedirectionTests() { context.logger.LogDebug("0. ClusterMultiKeyRedirectionTests started"); var Port = ClusterTestContext.Port; var Shards = context.defaultShards; - context.CreateInstances(Shards, cleanClusterConfig: true); + await context.CreateInstances(Shards, cleanClusterConfig: true); context.CreateConnection(); var connections = ClusterTestUtils.CreateLightRequestConnections(Enumerable.Range(Port, Shards).ToArray()); diff --git a/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs b/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs index 766819b0ec..0ced891586 100644 --- a/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs +++ b/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Threading.Tasks; using NUnit.Framework; namespace Garnet.test.cluster { [TestFixture, NonParallelizable] - public unsafe class ClusterTLSRT + public class ClusterTLSRT { ClusterReplicationTests tests; @@ -26,47 +27,47 @@ public void TearDown() [Test, Order(1)] [Category("REPLICATION")] - public void ClusterTLSR([Values] bool disableObjects) - => tests.ClusterSRTest(disableObjects); + public async Task ClusterTLSR([Values] bool disableObjects) + => await tests.ClusterSRTest(disableObjects); [Test, Order(2)] [Category("REPLICATION")] - public void ClusterTLSRCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterSRNoCheckpointRestartSecondary(performRMW, disableObjects); + public async Task ClusterTLSRCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterSRNoCheckpointRestartSecondary(performRMW, disableObjects); [Test, Order(3)] [Category("REPLICATION")] - public void ClusterTLSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterSRPrimaryCheckpoint(performRMW, disableObjects); + public async Task ClusterTLSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterSRPrimaryCheckpoint(performRMW, disableObjects); [Test, Order(4)] [Category("REPLICATION")] - public void ClusterTLSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) - => tests.ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, lowMemory, manySegments); + public async Task ClusterTLSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) + => await tests.ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, lowMemory, manySegments); [Test, Order(5)] [Category("REPLICATION")] - public void ClusterTLSCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterCheckpointRetrieveDisableStorageTier(performRMW, disableObjects); + public async Task ClusterTLSCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterCheckpointRetrieveDisableStorageTier(performRMW, disableObjects); [Test, Order(6)] [Category("REPLICATION")] - public void ClusterTLSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) - => tests.ClusterSRAddReplicaAfterPrimaryCheckpoint(performRMW, disableObjects, lowMemory); + public async Task ClusterTLSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) + => await tests.ClusterSRAddReplicaAfterPrimaryCheckpoint(performRMW, disableObjects, lowMemory); [Test, Order(7)] [Category("REPLICATION")] - public void ClusterTLSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterSRPrimaryRestart(performRMW, disableObjects); + public async Task ClusterTLSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterSRPrimaryRestart(performRMW, disableObjects); [Test, Order(8)] [Category("REPLICATION")] - public void ClusterTLSRRedirectWrites() - => tests.ClusterSRRedirectWrites(); + public async Task ClusterTLSRRedirectWrites() + => await tests.ClusterSRRedirectWrites(); [Test, Order(9)] [Category("REPLICATION")] - public void ClusterTLSRReplicaOfTest([Values] bool performRMW) - => tests.ClusterSRReplicaOfTest(performRMW); + public async Task ClusterTLSRReplicaOfTest([Values] bool performRMW) + => await tests.ClusterSRReplicaOfTest(performRMW); } } \ No newline at end of file diff --git a/test/Garnet.test.cluster/ClusterReplicationTests.cs b/test/Garnet.test.cluster/ClusterReplicationTests.cs index eccca0d3df..ec319c85d9 100644 --- a/test/Garnet.test.cluster/ClusterReplicationTests.cs +++ b/test/Garnet.test.cluster/ClusterReplicationTests.cs @@ -19,61 +19,61 @@ namespace Garnet.test.cluster [TestFixture(false, false), NonParallelizable] public class ClusterReplicationTests(bool UseTLS = false, bool asyncReplay = false) { - public (Action, string)[] GetUnitTests() + public (Task, string)[] GetUnitTests() { - var x = new (Action, string)[39]; + var x = new (Task, string)[39]; //1 - x[0] = new(() => ClusterSRTest(true), "ClusterSRTest(true)"); - x[1] = new(() => ClusterSRTest(false), "ClusterSRTest(false)"); + x[0] = new(ClusterSRTest(true), "ClusterSRTest(true)"); + x[1] = new(ClusterSRTest(false), "ClusterSRTest(false)"); //2 - x[2] = new(() => ClusterSRNoCheckpointRestartSecondary(false, false), "ClusterSRNoCheckpointRestartSecondary(false, false)"); - x[3] = new(() => ClusterSRNoCheckpointRestartSecondary(false, true), "ClusterSRNoCheckpointRestartSecondary(false, true)"); - x[4] = new(() => ClusterSRNoCheckpointRestartSecondary(true, false), "ClusterSRNoCheckpointRestartSecondary(true, false)"); - x[5] = new(() => ClusterSRNoCheckpointRestartSecondary(true, true), "ClusterSRNoCheckpointRestartSecondary(true, true)"); + x[2] = new(ClusterSRNoCheckpointRestartSecondary(false, false), "ClusterSRNoCheckpointRestartSecondary(false, false)"); + x[3] = new(ClusterSRNoCheckpointRestartSecondary(false, true), "ClusterSRNoCheckpointRestartSecondary(false, true)"); + x[4] = new(ClusterSRNoCheckpointRestartSecondary(true, false), "ClusterSRNoCheckpointRestartSecondary(true, false)"); + x[5] = new(ClusterSRNoCheckpointRestartSecondary(true, true), "ClusterSRNoCheckpointRestartSecondary(true, true)"); //3 - x[6] = new(() => ClusterSRPrimaryCheckpoint(false, false), "ClusterSRPrimaryCheckpoint(false, false)"); - x[7] = new(() => ClusterSRPrimaryCheckpoint(false, true), "ClusterSRPrimaryCheckpoint(false, true)"); - x[8] = new(() => ClusterSRPrimaryCheckpoint(true, false), "ClusterSRPrimaryCheckpoint(true, false)"); - x[9] = new(() => ClusterSRPrimaryCheckpoint(true, true), "ClusterSRPrimaryCheckpoint(true, true)"); + x[6] = new(ClusterSRPrimaryCheckpoint(false, false), "ClusterSRPrimaryCheckpoint(false, false)"); + x[7] = new(ClusterSRPrimaryCheckpoint(false, true), "ClusterSRPrimaryCheckpoint(false, true)"); + x[8] = new(ClusterSRPrimaryCheckpoint(true, false), "ClusterSRPrimaryCheckpoint(true, false)"); + x[9] = new(ClusterSRPrimaryCheckpoint(true, true), "ClusterSRPrimaryCheckpoint(true, true)"); //4 - x[10] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, false)"); - x[11] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, true)"); - x[12] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, false)"); - x[13] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, true)"); - x[14] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, false)"); - x[15] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, true)"); - x[16] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, false)"); - x[17] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, true)"); - x[18] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false)"); - x[19] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, true)"); - x[20] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, false)"); - x[21] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, true)"); - x[22] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, false)"); - x[23] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, true)"); - x[24] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, false)"); - x[25] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, true)"); + x[10] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, false)"); + x[11] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, true)"); + x[12] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, false)"); + x[13] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, true)"); + x[14] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, false)"); + x[15] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, true)"); + x[16] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, false)"); + x[17] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, true)"); + x[18] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false)"); + x[19] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, true)"); + x[20] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, false)"); + x[21] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, true)"); + x[22] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, false)"); + x[23] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, true)"); + x[24] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, false)"); + x[25] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, true)"); //5 - x[26] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false)"); - x[27] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true)"); - x[28] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false)"); - x[29] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true)"); - x[30] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false)"); - x[31] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true)"); - x[32] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false)"); - x[33] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true)"); + x[26] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false)"); + x[27] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true)"); + x[28] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false)"); + x[29] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true)"); + x[30] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false)"); + x[31] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true)"); + x[32] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false)"); + x[33] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true)"); //6 - x[34] = new(() => ClusterSRPrimaryRestart(false, false), "ClusterSRPrimaryRestart(false, false)"); - x[35] = new(() => ClusterSRPrimaryRestart(false, true), "ClusterSRPrimaryRestart(false, true)"); - x[36] = new(() => ClusterSRPrimaryRestart(true, false), "ClusterSRPrimaryRestart(true, false)"); - x[37] = new(() => ClusterSRPrimaryRestart(true, true), "ClusterSRPrimaryRestart(true, true)"); + x[34] = new(ClusterSRPrimaryRestart(false, false), "ClusterSRPrimaryRestart(false, false)"); + x[35] = new(ClusterSRPrimaryRestart(false, true), "ClusterSRPrimaryRestart(false, true)"); + x[36] = new(ClusterSRPrimaryRestart(true, false), "ClusterSRPrimaryRestart(true, false)"); + x[37] = new(ClusterSRPrimaryRestart(true, true), "ClusterSRPrimaryRestart(true, true)"); //7 - x[38] = new(ClusterSRRedirectWrites, "ClusterSRRedirectWrites()"); + x[38] = new(ClusterSRRedirectWrites(), "ClusterSRRedirectWrites()"); return x; } @@ -105,13 +105,13 @@ public void TearDown() [Test, Order(1)] [Category("REPLICATION")] - public void ClusterSRTest([Values] bool disableObjects) + public async Task ClusterSRTest([Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + primary_count * replica_count; ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -148,7 +148,7 @@ public async Task ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -214,7 +214,7 @@ public async Task ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -285,22 +285,22 @@ public async Task ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] [Test, Order(4)] [Category("REPLICATION")] - public void ClusterCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) { - ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, false, false, true, false); + await ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, false, false, true, false); } [Test, Order(5)] [Category("REPLICATION")] - public void ClusterCheckpointRetrieveDelta([Values] bool performRMW) + public async Task ClusterCheckpointRetrieveDelta([Values] bool performRMW) { - ClusterSRPrimaryCheckpointRetrieve(performRMW, true, false, false, false, true); + await ClusterSRPrimaryCheckpointRetrieve(performRMW, true, false, false, false, true); } [Test, Order(6)] [Category("REPLICATION")] - public void ClusterSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) - => ClusterSRPrimaryCheckpointRetrieve(performRMW: performRMW, disableObjects: disableObjects, lowMemory: lowMemory, manySegments: manySegments, false, false); + public async Task ClusterSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) + => await ClusterSRPrimaryCheckpointRetrieve(performRMW: performRMW, disableObjects: disableObjects, lowMemory: lowMemory, manySegments: manySegments, false, false); async Task ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bool lowMemory, bool manySegments, bool disableStorageTier, bool incrementalSnapshots) { @@ -313,7 +313,7 @@ async Task ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjec var primary_count = 1; var nodes_count = primary_count + primary_count * replica_count; ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, lowMemory: lowMemory, SegmentSize: manySegments ? "4k" : "1g", DisableStorageTier: disableStorageTier, EnableIncrementalSnapshots: incrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, lowMemory: lowMemory, SegmentSize: manySegments ? "4k" : "1g", DisableStorageTier: disableStorageTier, EnableIncrementalSnapshots: incrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -383,13 +383,13 @@ async Task ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjec [Test, Order(7)] [Category("REPLICATION")] - public void ClusterSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) + public async Task ClusterSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: lowMemory, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: lowMemory, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, new List<(int, int)>() { (0, 16383) }, true, context.logger)); @@ -448,7 +448,7 @@ public async Task ClusterSRPrimaryRestart([Values] bool performRMW, [Values] boo var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, new List<(int, int)>() { (0, 16383) }, true, context.logger)); @@ -509,13 +509,13 @@ public async Task ClusterSRPrimaryRestart([Values] bool performRMW, [Values] boo [Test, Order(9)] [Category("REPLICATION")] - public void ClusterSRRedirectWrites() + public async Task ClusterSRRedirectWrites() { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -537,10 +537,10 @@ public void ClusterSRRedirectWrites() [Test, Order(10)] [Category("REPLICATION")] - public void ClusterSRReplicaOfTest([Values] bool performRMW) + public async Task ClusterSRReplicaOfTest([Values] bool performRMW) { var nodes_count = 2; - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, [(0, 16383)], true, context.logger)); @@ -573,13 +573,13 @@ public void ClusterSRReplicaOfTest([Values] bool performRMW) [Test, Order(11)] [Category("REPLICATION")] - public void ClusterReplicationSimpleFailover([Values] bool performRMW, [Values] bool checkpoint) + public async Task ClusterReplicationSimpleFailover([Values] bool performRMW, [Values] bool checkpoint) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -643,13 +643,13 @@ public void ClusterReplicationSimpleFailover([Values] bool performRMW, [Values] [Test, Order(12)] [Category("REPLICATION")] - public void ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] bool takePrimaryCheckpoint, [Values] bool takeNewPrimaryCheckpoint, [Values] bool enableIncrementalSnapshots) + public async Task ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] bool takePrimaryCheckpoint, [Values] bool takeNewPrimaryCheckpoint, [Values] bool enableIncrementalSnapshots) { var replica_count = 2; // Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -693,7 +693,7 @@ public void ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] boo context.ValidateKVCollectionAgainstReplica(ref context.kvPairs, 1); // Simulate primary crash - context.nodes[0].Dispose(); + context.nodes[0].StopAsync(); context.nodes[0] = null; // Takeover as new primary @@ -724,13 +724,13 @@ public void ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] boo [Test, Order(13)] [Category("REPLICATION")] - public void ClusterReplicationCheckpointCleanupTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool enableIncrementalSnapshots) + public async Task ClusterReplicationCheckpointCleanupTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool enableIncrementalSnapshots) { var replica_count = 1;//Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: true, SegmentSize: "4k", EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: true, SegmentSize: "4k", EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, [(0, 16383)], true, context.logger)); context.clusterTestUtils.BumpEpoch(0, logger: context.logger); @@ -757,13 +757,13 @@ public void ClusterReplicationCheckpointCleanupTest([Values] bool performRMW, [V [Test, Order(14)] [Category("REPLICATION")] - public void ClusterMainMemoryReplicationAttachReplicas() + public async Task ClusterMainMemoryReplicationAttachReplicas() { var replica_count = 2; // Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: true, OnDemandCheckpoint: true, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: true, OnDemandCheckpoint: true, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, new List<(int, int)>() { (0, 16383) }, true)); @@ -801,13 +801,13 @@ public void ClusterMainMemoryReplicationAttachReplicas() [Test, Order(15)] [Category("REPLICATION")] - public void ClusterDontKnowReplicaFailTest([Values] bool performRMW, [Values] bool MainMemoryReplication, [Values] bool onDemandCheckpoint, [Values] bool useReplicaOf) + public async Task ClusterDontKnowReplicaFailTest([Values] bool performRMW, [Values] bool MainMemoryReplication, [Values] bool onDemandCheckpoint, [Values] bool useReplicaOf) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: MainMemoryReplication, OnDemandCheckpoint: onDemandCheckpoint, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: MainMemoryReplication, OnDemandCheckpoint: onDemandCheckpoint, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var primaryNodeIndex = 0; @@ -854,13 +854,13 @@ public void ClusterDontKnowReplicaFailTest([Values] bool performRMW, [Values] bo [Test, Order(16)] [Category("REPLICATION")] - public void ClusterDivergentReplicasTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) - => ClusterDivergentReplicasTest(performRMW, disableObjects, ckptBeforeDivergence, false, false, fastCommit: false); + public async Task ClusterDivergentReplicasTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) + => await ClusterDivergentReplicasTest(performRMW, disableObjects, ckptBeforeDivergence, false, false, fastCommit: false); [Test, Order(17)] [Category("REPLICATION")] - public void ClusterDivergentCheckpointTest([Values] bool performRMW, [Values] bool disableObjects) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentCheckpointTest([Values] bool performRMW, [Values] bool disableObjects) + => await ClusterDivergentReplicasTest( performRMW, disableObjects, ckptBeforeDivergence: true, @@ -870,8 +870,8 @@ public void ClusterDivergentCheckpointTest([Values] bool performRMW, [Values] bo [Test, Order(18)] [Category("REPLICATION")] - public void ClusterDivergentReplicasMMTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentReplicasMMTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) + => await ClusterDivergentReplicasTest( performRMW, disableObjects, ckptBeforeDivergence, @@ -881,8 +881,8 @@ public void ClusterDivergentReplicasMMTest([Values] bool performRMW, [Values] bo [Test, Order(19)] [Category("REPLICATION")] - public void ClusterDivergentCheckpointMMTest([Values] bool performRMW, [Values] bool disableObjects) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentCheckpointMMTest([Values] bool performRMW, [Values] bool disableObjects) + => await ClusterDivergentReplicasTest( performRMW, disableObjects, ckptBeforeDivergence: true, @@ -892,8 +892,8 @@ public void ClusterDivergentCheckpointMMTest([Values] bool performRMW, [Values] [Test, Order(20)] [Category("REPLICATION")] - public void ClusterDivergentCheckpointMMFastCommitTest([Values] bool disableObjects, [Values] bool mainMemoryReplication) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentCheckpointMMFastCommitTest([Values] bool disableObjects, [Values] bool mainMemoryReplication) + => await ClusterDivergentReplicasTest( performRMW: false, disableObjects: disableObjects, ckptBeforeDivergence: true, @@ -908,7 +908,7 @@ async Task ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bo var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, MainMemoryReplication: mainMemoryReplication, CommitFrequencyMs: mainMemoryReplication ? -1 : 0, OnDemandCheckpoint: mainMemoryReplication, FastCommit: fastCommit, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, MainMemoryReplication: mainMemoryReplication, CommitFrequencyMs: mainMemoryReplication ? -1 : 0, OnDemandCheckpoint: mainMemoryReplication, FastCommit: fastCommit, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); _ = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -1029,7 +1029,7 @@ async Task ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bo [Test, Order(21)] [Category("REPLICATION")] - public void ClusterReplicateFails() + public async Task ClusterReplicateFails() { const string UserName = "temp-user"; const string Password = "temp-password"; @@ -1042,7 +1042,7 @@ public void ClusterReplicateFails() ServerCredential userCreds = new(UserName, Password, IsAdmin: true, UsedForClusterAuth: false, IsClearText: true); context.GenerateCredentials([userCreds, clusterCreds]); - context.CreateInstances(2, disableObjects: true, disablePubSub: true, enableAOF: true, clusterCreds: clusterCreds, useAcl: true, MainMemoryReplication: true, CommitFrequencyMs: -1, asyncReplay: asyncReplay); + await context.CreateInstances(2, disableObjects: true, disablePubSub: true, enableAOF: true, clusterCreds: clusterCreds, useAcl: true, MainMemoryReplication: true, CommitFrequencyMs: -1, asyncReplay: asyncReplay); var primaryEndpoint = (IPEndPoint)context.endpoints.First(); var replicaEndpoint = (IPEndPoint)context.endpoints.Last(); @@ -1071,7 +1071,7 @@ public async Task ClusterReplicationCheckpointAlignmentTest([Values] bool perfor var primaryNodeIndex = 0; var replicaNodeIndex = 1; ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: false, MainMemoryReplication: true, CommitFrequencyMs: -1, OnDemandCheckpoint: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: false, MainMemoryReplication: true, CommitFrequencyMs: -1, OnDemandCheckpoint: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); _ = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); diff --git a/test/Garnet.test.cluster/ClusterTestContext.cs b/test/Garnet.test.cluster/ClusterTestContext.cs index cbf3e2ffc0..224ee7af4e 100644 --- a/test/Garnet.test.cluster/ClusterTestContext.cs +++ b/test/Garnet.test.cluster/ClusterTestContext.cs @@ -64,7 +64,7 @@ public void TearDown() waiter?.Dispose(); clusterTestUtils?.Dispose(); loggerFactory?.Dispose(); - if (!Task.Run(() => DisposeCluster()).Wait(TimeSpan.FromSeconds(15))) + if (!Task.Run(async () => await DisposeCluster()).Wait(TimeSpan.FromSeconds(15))) logger?.LogError("Timed out waiting for DisposeCluster"); if (!Task.Run(() => TestUtils.DeleteDirectory(TestFolder, true)).Wait(TimeSpan.FromSeconds(15))) logger?.LogError("Timed out waiting for DisposeCluster"); @@ -263,7 +263,7 @@ public GarnetApplication CreateInstance( /// /// Dispose created instances /// - public void DisposeCluster() + public async Task DisposeCluster() { if (nodes != null) { @@ -272,6 +272,7 @@ public void DisposeCluster() if (nodes[i] != null) { logger.LogDebug("\t a. Dispose node {testName}", TestContext.CurrentContext.Test.Name); + await nodes[i].StopAsync(); nodes[i].Dispose(); nodes[i] = null; logger.LogDebug("\t b. Dispose node {testName}", TestContext.CurrentContext.Test.Name); diff --git a/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs b/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs index 938d54cf44..00a826117a 100644 --- a/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs +++ b/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using Microsoft.Extensions.Logging; @@ -195,12 +196,12 @@ private void ResetSlot() } [OneTimeSetUp] - public void OneTimeSetUp() + public async Task OneTimeSetUp() { context = new ClusterTestContext(); context.Setup([]); - context.CreateInstances(3, enableLua: true); + await context.CreateInstances(3, enableLua: true); context.RegisterCustomTxn( "CLUSTERGETPROC", diff --git a/test/Garnet.test/CacheSizeTrackerTests.cs b/test/Garnet.test/CacheSizeTrackerTests.cs index 34284e09ad..c88f2f964d 100644 --- a/test/Garnet.test/CacheSizeTrackerTests.cs +++ b/test/Garnet.test/CacheSizeTrackerTests.cs @@ -33,9 +33,12 @@ public async Task Setup() } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + } TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/TestUtils.cs b/test/Garnet.test/TestUtils.cs index fbf3586f63..4cc53fac0e 100644 --- a/test/Garnet.test/TestUtils.cs +++ b/test/Garnet.test/TestUtils.cs @@ -180,7 +180,7 @@ internal static void IgnoreIfNotRunningAzureTests() } /// - /// Create GarnetServer + /// Create GarnetApplication /// public static GarnetApplication CreateGarnetApplication( string logCheckpointDir, From ec2859cf152081e83641d3602b8fe73680598026 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 15:35:58 +0100 Subject: [PATCH 28/42] start removing unused code --- libs/host/GarnetServer.cs | 300 +--------------------------- libs/host/StoreFactory.cs | 70 ------- libs/host/StoreWrapperFactory.cs | 43 ---- test/Garnet.test/ReadCacheTests.cs | 2 +- test/Garnet.test/RespPubSubTests.cs | 2 +- 5 files changed, 4 insertions(+), 413 deletions(-) diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 04a91a60e4..14b75f003f 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -45,19 +45,9 @@ static string GetVersion() private readonly GarnetServerOptions opts; private IGarnetServer server; - private TsavoriteKV store; - private TsavoriteKV objectStore; - private IDevice aofDevice; - private TsavoriteLog appendOnlyFile; - private SubscribeBroker> subscribeBroker; - private KVSettings kvSettings; - private KVSettings objKvSettings; - private INamedDeviceFactory logFactory; - private MemoryLogger initLogger; private ILogger logger; private readonly ILoggerFactory loggerFactory; private readonly bool cleanupDir; - private bool disposeLoggerFactory; /// /// Store and associated information used by this Garnet server @@ -140,7 +130,7 @@ private void InitializeServerUpdated() IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); // Flush initialization logs from memory logger - FlushMemoryLogger(this.initLogger, "ArgParser", this.loggerFactory); + FlushMemoryLogger(null, "ArgParser", this.loggerFactory); ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); @@ -185,250 +175,7 @@ private void InitializeServerUpdated() server.Register(WireFormat.ASCII, Provider); } - - /// - /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. - /// - /// Server options - /// Logger factory - /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. - /// Whether to clean up data folders on dispose - public GarnetServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, IGarnetServer server = null, - bool cleanupDir = false) - { - this.server = server; - this.opts = opts; - this.loggerFactory = loggerFactory; - this.cleanupDir = cleanupDir; - this.InitializeServer(); - } - - private void InitializeServer() - { - Debug.Assert(opts != null); - - if (!opts.QuietMode) - { - var red = "\u001b[31m"; - var magenta = "\u001b[35m"; - var normal = "\u001b[0m"; - - Console.WriteLine($@"{red} _________ - /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} - '. \ / .' {normal}Port: {opts.Port}{red} - '.\ /.' {magenta}https://aka.ms/GetGarnet{red} - '.' -{normal}"); - } - - var clusterFactory = opts.EnableCluster ? new ClusterFactory() : null; - - this.logger = this.loggerFactory?.CreateLogger("GarnetServer"); - logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, - IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); - - // Flush initialization logs from memory logger - FlushMemoryLogger(this.initLogger, "ArgParser", this.loggerFactory); - - var customCommandManager = new CustomCommandManager(); - - ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); - ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); - - bool minChanged = false, maxChanged = false; - if (opts.ThreadPoolMinThreads > 0) - { - minThreads = opts.ThreadPoolMinThreads; - minChanged = true; - } - - if (opts.ThreadPoolMinIOCompletionThreads > 0) - { - minCPThreads = opts.ThreadPoolMinIOCompletionThreads; - minChanged = true; - } - - if (opts.ThreadPoolMaxThreads > 0) - { - maxThreads = opts.ThreadPoolMaxThreads; - maxChanged = true; - } - - if (opts.ThreadPoolMaxIOCompletionThreads > 0) - { - maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; - maxChanged = true; - } - - // First try to set the max threads - var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); - - // Set the min threads - if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); - - // Retry to set max threads if it wasn't set in the earlier step - if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - - CreateMainStore(clusterFactory, out var checkpointDir); - CreateObjectStore(clusterFactory, customCommandManager, checkpointDir, out var objectStoreSizeTracker); - - if (!opts.DisablePubSub) - subscribeBroker = new SubscribeBroker>( - new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, - true); - - CreateAOF(); - - logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - - if (logger != null) - { - var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + - (store.ReadCache?.MaxMemorySizeBytes ?? 0) + - (appendOnlyFile?.MaxMemorySizeBytes ?? 0); - if (objectStore != null) - configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + - (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + - (objectStoreSizeTracker?.TargetSize ?? 0) + - (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); - logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); - } - - // Create Garnet TCP server if none was provided. - this.server ??= new GarnetServerTcp(opts.Address, opts.Port, 0, opts.TlsOptions, - opts.NetworkSendThrottleMax, opts.NetworkConnectionLimit, logger); - - storeWrapper = new StoreWrapper(version, redisProtocolVersion, server, store, objectStore, - objectStoreSizeTracker, - customCommandManager, appendOnlyFile, opts, clusterFactory: clusterFactory, - loggerFactory: loggerFactory); - - // Create session provider for Garnet - Provider = new GarnetProvider(storeWrapper, subscribeBroker); - - // Create user facing API endpoints - Metrics = new MetricsApi(Provider); - Register = new RegisterApi(Provider); - Store = new StoreApi(storeWrapper); - - server.Register(WireFormat.ASCII, Provider); - - LoadModules(customCommandManager); - } - - private void LoadModules(CustomCommandManager customCommandManager) - { - if (opts.LoadModuleCS == null) - return; - - foreach (var moduleCS in opts.LoadModuleCS) - { - var moduleCSData = moduleCS.Split(' ', StringSplitOptions.RemoveEmptyEntries); - if (moduleCSData.Length < 1) - continue; - - var modulePath = moduleCSData[0]; - var moduleArgs = moduleCSData.Length > 1 ? moduleCSData.Skip(1).ToArray() : []; - if (ModuleUtils.LoadAssemblies([modulePath], null, true, out var loadedAssemblies, out var errorMsg)) - { - ModuleRegistrar.Instance.LoadModule(customCommandManager, loadedAssemblies.ToList()[0], moduleArgs, - logger, out errorMsg); - } - else - { - logger?.LogError("Module {0} failed to load with error {1}", modulePath, - Encoding.UTF8.GetString(errorMsg)); - } - } - } - - private void CreateMainStore(IClusterFactory clusterFactory, out string checkpointDir) - { - kvSettings = opts.GetSettings(loggerFactory, out logFactory); - - checkpointDir = opts.CheckpointDir ?? opts.LogDir; - - // Run checkpoint on its own thread to control p99 - kvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; - kvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; - - var checkpointFactory = opts.DeviceFactoryCreator(); - if (opts.EnableCluster) - { - kvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager(checkpointFactory, - new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), isMainStore: true, logger); - } - else - { - kvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(checkpointFactory, - new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), removeOutdated: true); - } - - store = new(kvSettings - , StoreFunctions.Create() - , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); - } - - private void CreateObjectStore(IClusterFactory clusterFactory, CustomCommandManager customCommandManager, - string CheckpointDir, out CacheSizeTracker objectStoreSizeTracker) - { - objectStoreSizeTracker = null; - if (!opts.DisableObjects) - { - objKvSettings = opts.GetObjectStoreSettings(this.loggerFactory?.CreateLogger("TsavoriteKV [obj]"), - out var objHeapMemorySize, out var objReadCacheHeapMemorySize); - - // Run checkpoint on its own thread to control p99 - objKvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; - objKvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; - - if (opts.EnableCluster) - objKvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager( - opts.DeviceFactoryCreator(), - new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), - isMainStore: false, logger); - else - objKvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(opts.DeviceFactoryCreator(), - new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), - removeOutdated: true); - - objectStore = new(objKvSettings - , StoreFunctions.Create(new ByteArrayKeyComparer(), - () => new ByteArrayBinaryObjectSerializer(), - () => new GarnetObjectSerializer(customCommandManager)) - , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); - - if (objHeapMemorySize > 0 || objReadCacheHeapMemorySize > 0) - objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, - objReadCacheHeapMemorySize, - this.loggerFactory); - } - } - - private void CreateAOF() - { - if (opts.EnableAOF) - { - if (opts.MainMemoryReplication && opts.CommitFrequencyMs != -1) - throw new Exception( - "Need to set CommitFrequencyMs to -1 (manual commits) with MainMemoryReplication"); - - opts.GetAofSettings(out var aofSettings); - aofDevice = aofSettings.LogDevice; - appendOnlyFile = new TsavoriteLog(aofSettings, - logger: this.loggerFactory?.CreateLogger("TsavoriteLog [aof]")); - - if (opts.CommitFrequencyMs < 0 && opts.WaitForCommit) - throw new Exception("Cannot use CommitWait with manual commits"); - return; - } - - if (opts.CommitFrequencyMs != 0 || opts.WaitForCommit) - throw new Exception("Cannot use CommitFrequencyMs or CommitWait without EnableAOF"); - } - + /// /// Start server instance /// @@ -458,7 +205,6 @@ public void Dispose(bool deleteDir = true) InternalDispose(); if (deleteDir) { - logFactory?.Delete(new FileDescriptor { directoryName = "" }); if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) { var ckptdir = opts.DeviceFactoryCreator(); @@ -472,48 +218,6 @@ private void InternalDispose() { Provider?.Dispose(); server.Dispose(); - subscribeBroker?.Dispose(); - store?.Dispose(); - appendOnlyFile?.Dispose(); - aofDevice?.Dispose(); - kvSettings?.LogDevice?.Dispose(); - if (!opts.DisableObjects) - { - objectStore?.Dispose(); - objKvSettings?.LogDevice?.Dispose(); - objKvSettings?.ObjectLogDevice?.Dispose(); - } - - opts.AuthSettings?.Dispose(); - if (disposeLoggerFactory) - loggerFactory?.Dispose(); - } - - private static void DeleteDirectory(string path) - { - if (path == null) return; - - // Exceptions may happen due to a handle briefly remaining held after Dispose(). - try - { - foreach (string directory in Directory.GetDirectories(path)) - { - DeleteDirectory(directory); - } - - Directory.Delete(path, true); - } - catch (Exception ex) when (ex is IOException || - ex is UnauthorizedAccessException) - { - try - { - Directory.Delete(path, true); - } - catch - { - } - } } /// diff --git a/libs/host/StoreFactory.cs b/libs/host/StoreFactory.cs index 53a7c5140b..aade30179f 100644 --- a/libs/host/StoreFactory.cs +++ b/libs/host/StoreFactory.cs @@ -37,76 +37,6 @@ public StoreFactory( this.customCommandManager = customCommandManager; } - public TsavoriteKV CreateObjectStore( - string CheckpointDir, out CacheSizeTracker objectStoreSizeTracker, out KVSettings objKvSettings) - { - TsavoriteKV objectStore = null; - objKvSettings = null; - - objectStoreSizeTracker = null; - if (!opts.DisableObjects) - { - objKvSettings = opts.GetObjectStoreSettings(loggerFactory?.CreateLogger("TsavoriteKV [obj]"), - out var objHeapMemorySize, out var objReadCacheHeapMemorySize); - - // Run checkpoint on its own thread to control p99 - objKvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; - objKvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; - - if (opts.EnableCluster) - objKvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager( - opts.DeviceFactoryCreator(), - new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), - isMainStore: false); - else - objKvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager( - opts.DeviceFactoryCreator(), - new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), - removeOutdated: true); - - objectStore = new(objKvSettings - , StoreFunctions.Create(new ByteArrayKeyComparer(), - () => new ByteArrayBinaryObjectSerializer(), - () => new GarnetObjectSerializer(customCommandManager)) - , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); - - if (objHeapMemorySize > 0 || objReadCacheHeapMemorySize > 0) - objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, - objReadCacheHeapMemorySize, - loggerFactory); - } - - return objectStore; - } - - public TsavoriteKV CreateMainStore( - out string checkpointDir, out KVSettings kvSettings) - { - kvSettings = opts.GetSettings(loggerFactory, out var logFactory); - - checkpointDir = opts.CheckpointDir ?? opts.LogDir; - - // Run checkpoint on its own thread to control p99 - kvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; - kvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; - - var checkpointFactory = opts.DeviceFactoryCreator(); - if (opts.EnableCluster) - { - kvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager(checkpointFactory, - new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), isMainStore: true); - } - else - { - kvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(checkpointFactory, - new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), removeOutdated: true); - } - - return new(kvSettings - , StoreFunctions.Create() - , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); - } - public MainStoreWrapper CreateMainStore() { var kvSettings = opts.GetSettings(loggerFactory, out var logFactory); diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/StoreWrapperFactory.cs index acc079150c..ae99b2cd9b 100644 --- a/libs/host/StoreWrapperFactory.cs +++ b/libs/host/StoreWrapperFactory.cs @@ -100,49 +100,6 @@ public StoreWrapper Create(string version) loggerFactory: loggerFactory); } - public StoreWrapper Create( - string version, - IGarnetServer server, - TsavoriteLog appendOnlyFile, - out TsavoriteKV store, - out TsavoriteKV objectStore, - out KVSettings kvSettings, - out KVSettings objKvSettings) - { - - store = storeFactory.CreateMainStore(out var checkpointDir, out kvSettings); - objectStore = storeFactory.CreateObjectStore(checkpointDir, out var objectStoreSizeTracker, out objKvSettings); - - var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + - (store.ReadCache?.MaxMemorySizeBytes ?? 0) + - (appendOnlyFile?.MaxMemorySizeBytes ?? 0); - if (objectStore != null) - { - - configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + - (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + - (objectStoreSizeTracker?.TargetSize ?? 0) + - (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); - } - - logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); - - LoadModules(); - - return new StoreWrapper( - version, - redisProtocolVersion, - server, - store, - objectStore, - objectStoreSizeTracker, - customCommandManager, - appendOnlyFile, - options, - clusterFactory: clusterFactory, - loggerFactory: loggerFactory); - } - private void LoadModules() { if (options.LoadModuleCS == null) diff --git a/test/Garnet.test/ReadCacheTests.cs b/test/Garnet.test/ReadCacheTests.cs index 170a6f1430..b0b4e921f6 100644 --- a/test/Garnet.test/ReadCacheTests.cs +++ b/test/Garnet.test/ReadCacheTests.cs @@ -22,7 +22,7 @@ public async Task Setup() } [TearDown] - public async void TearDown() + public async Task TearDown() { await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); diff --git a/test/Garnet.test/RespPubSubTests.cs b/test/Garnet.test/RespPubSubTests.cs index ef12898cc9..c3a77ffad7 100644 --- a/test/Garnet.test/RespPubSubTests.cs +++ b/test/Garnet.test/RespPubSubTests.cs @@ -26,7 +26,7 @@ public async Task Setup() } [TearDown] - public async void TearDown() + public async Task TearDown() { await server.StopAsync(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); From 3ebc8b66f4b27d15703deb27246d3af04a14298f Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Thu, 23 Jan 2025 15:59:51 +0100 Subject: [PATCH 29/42] refactor --- .../BDN.benchmark/Cluster/ClusterContext.cs | 16 +++++++------- .../Embedded/EmbeddedRespServer.cs | 4 +++- .../Embedded/GarnetEmbeddedApplication.cs | 21 +++++++++++++++++++ .../GarnetEmbeddedApplicationBuilder.cs | 20 ++++++++++++++++++ libs/host/GarnetApplicationBuilder.cs | 2 +- libs/host/GarnetServer.cs | 2 +- .../Garnet.test.cluster/ClusterConfigTests.cs | 8 ++++--- 7 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs create mode 100644 benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs diff --git a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs index c6a375ff5c..0cd075cc4e 100644 --- a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs +++ b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs @@ -10,7 +10,7 @@ namespace BDN.benchmark.Cluster { - unsafe class ClusterContext + class ClusterContext { EmbeddedRespServer server; RespServerSession session; @@ -22,10 +22,11 @@ unsafe class ClusterContext public Request[] singleMGetMSet; public Request singleCTXNSET; - public void Dispose() + public Task Dispose() { session.Dispose(); server.Dispose(); + return Task.CompletedTask; } public void SetupSingleInstance(bool disableSlotVerification = false) @@ -39,12 +40,13 @@ public void SetupSingleInstance(bool disableSlotVerification = false) }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) opt.CheckpointDir = "/tmp"; + server = new EmbeddedRespServer(opt); session = server.GetRespSession(); _ = server.Register.NewTransactionProc(CustomTxnSet.CommandName, () => new CustomTxnSet(), new RespCommandsInfo { Arity = CustomTxnSet.Arity }); } - public void AddSlotRange(List<(int, int)> slotRanges) + public unsafe void AddSlotRange(List<(int, int)> slotRanges) { foreach (var slotRange in slotRanges) { @@ -56,7 +58,7 @@ public void AddSlotRange(List<(int, int)> slotRanges) } } - public void CreateGetSet(int keySize = 8, int valueSize = 32, int batchSize = 100) + public unsafe void CreateGetSet(int keySize = 8, int valueSize = 32, int batchSize = 100) { var pairs = new (byte[], byte[])[batchSize]; for (var i = 0; i < batchSize; i++) @@ -93,7 +95,7 @@ public void CreateGetSet(int keySize = 8, int valueSize = 32, int batchSize = 10 singleGetSet = [getReq, setReq]; } - public void CreateMGetMSet(int keySize = 8, int valueSize = 32, int batchSize = 100) + public unsafe void CreateMGetMSet(int keySize = 8, int valueSize = 32, int batchSize = 100) { var pairs = new (byte[], byte[])[batchSize]; for (var i = 0; i < batchSize; i++) @@ -134,7 +136,7 @@ public void CreateMGetMSet(int keySize = 8, int valueSize = 32, int batchSize = singleMGetMSet = [mGetReq, mSetReq]; } - public void CreateCTXNSET(int keySize = 8, int batchSize = 100) + public unsafe void CreateCTXNSET(int keySize = 8, int batchSize = 100) { var keys = new byte[8][]; for (var i = 0; i < 8; i++) @@ -163,7 +165,7 @@ public void CreateCTXNSET(int keySize = 8, int batchSize = 100) singleCTXNSET = ctxnsetReq; } - public void Consume(byte* ptr, int length) + public unsafe void Consume(byte* ptr, int length) => session.TryConsumeMessages(ptr, length); } diff --git a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs index bae520f373..10f7c6ac3c 100644 --- a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs +++ b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs @@ -23,7 +23,9 @@ internal sealed class EmbeddedRespServer : GarnetServer /// Server options to configure the base GarnetServer instance /// Logger factory to configure the base GarnetServer instance /// Server network - public EmbeddedRespServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, GarnetServerEmbedded server = null) : base(opts, loggerFactory, server) + public EmbeddedRespServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, GarnetServerEmbedded server = null) + //: base(opts, loggerFactory, server) + : base(null, null, loggerFactory, server, null, null, null, null) { this.garnetServerEmbedded = server; this.subscribeBroker = opts.DisablePubSub ? null : diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs new file mode 100644 index 0000000000..113c8ddc1e --- /dev/null +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Garnet; +using Garnet.server; +using Microsoft.Extensions.Hosting; + +namespace Embedded.server; + +public class GarnetEmbeddedApplication : GarnetApplication +{ + public GarnetEmbeddedApplication(IHost host) + : base(host) + { + } + + public static new GarnetEmbeddedApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) + { + return new GarnetEmbeddedApplicationBuilder(new GarnetApplicationOptions { Args = args, }, options); + } +} \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs new file mode 100644 index 0000000000..c8f7f7d70a --- /dev/null +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Garnet; +using Garnet.server; +namespace Embedded.server; + +public class GarnetEmbeddedApplicationBuilder : GarnetApplicationBuilder +{ + public GarnetEmbeddedApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + : base(options, garnetServerOptions) + { + } + + public new GarnetEmbeddedApplication Build() + { + throw new NotImplementedException(); + } + +} \ No newline at end of file diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 522a4c213d..f5cd98ec43 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -21,7 +21,7 @@ public class GarnetApplicationBuilder : IHostApplicationBuilder { readonly HostApplicationBuilder hostApplicationBuilder; - internal GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) { var configuration = new ConfigurationManager(); diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 14b75f003f..971053b480 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -175,7 +175,7 @@ private void InitializeServerUpdated() server.Register(WireFormat.ASCII, Provider); } - + /// /// Start server instance /// diff --git a/test/Garnet.test.cluster/ClusterConfigTests.cs b/test/Garnet.test.cluster/ClusterConfigTests.cs index 8e5eda8f60..18255b561e 100644 --- a/test/Garnet.test.cluster/ClusterConfigTests.cs +++ b/test/Garnet.test.cluster/ClusterConfigTests.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.cluster; using Garnet.common; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Internal; @@ -62,7 +64,7 @@ public void ClusterConfigInitializesUnassignedWorkerTest() [Test, Order(2)] [Category("CLUSTER-CONFIG"), CancelAfter(1000)] - public void ClusterForgetAfterNodeRestartTest() + public async Task ClusterForgetAfterNodeRestartTest() { int nbInstances = 4; context.CreateInstances(4); @@ -70,9 +72,9 @@ public void ClusterForgetAfterNodeRestartTest() var (shards, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); // Restart node with new ACL file - context.nodes[0].Dispose(false); + await context.nodes[0].StopAsync(); context.nodes[0] = context.CreateInstance(context.clusterTestUtils.GetEndPoint(0).Port, useAcl: true, cleanClusterConfig: false); - context.nodes[0].Start(); + await context.nodes[0].RunAsync(); context.CreateConnection(); var firstNode = context.nodes[0]; From 496c731541c52e24dca0f66fd01eb7121cb404b6 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 01:31:05 +0100 Subject: [PATCH 30/42] fix some disposing issues --- libs/host/GarnetServer.cs | 1 - libs/server/Providers/GarnetProvider.cs | 9 +-------- libs/server/StoreWrapper.cs | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index 971053b480..e381cab4c7 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -216,7 +216,6 @@ public void Dispose(bool deleteDir = true) private void InternalDispose() { - Provider?.Dispose(); server.Dispose(); } diff --git a/libs/server/Providers/GarnetProvider.cs b/libs/server/Providers/GarnetProvider.cs index 10665c94c1..afc6d2ff32 100644 --- a/libs/server/Providers/GarnetProvider.cs +++ b/libs/server/Providers/GarnetProvider.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System; using System.Threading; using Garnet.common; using Garnet.networking; @@ -52,14 +53,6 @@ public void Start() public void Recover() => storeWrapper.Recover(); - /// - /// Dispose - /// - public void Dispose() - { - storeWrapper.Dispose(); - } - /// public override SpanByteFunctionsForServer GetFunctions() => new(); diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index e45a822faf..d5ff17d8c2 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -27,7 +27,7 @@ namespace Garnet.server /// /// Wrapper for store and store-specific information /// - public sealed class StoreWrapper + public sealed class StoreWrapper : IDisposable { internal readonly string version; internal readonly string redisProtocolVersion; From 075959fcface304d7eb189012ea8df28ea2e212b Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 01:40:22 +0100 Subject: [PATCH 31/42] fix typo --- test/Garnet.test.cluster/ClusterReplicationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Garnet.test.cluster/ClusterReplicationTests.cs b/test/Garnet.test.cluster/ClusterReplicationTests.cs index ec319c85d9..f5516e2f99 100644 --- a/test/Garnet.test.cluster/ClusterReplicationTests.cs +++ b/test/Garnet.test.cluster/ClusterReplicationTests.cs @@ -1107,7 +1107,7 @@ public async Task ClusterReplicationCheckpointAlignmentTest([Values] bool perfor // Dispose primary and delete data await context.nodes[primaryNodeIndex].StopAsync(); // Dispose primary but do not delete data - await context.nodes[primaryNodeIndex].StopAsync(); + await context.nodes[replicaNodeIndex].StopAsync(); // Restart primary and do not recover context.nodes[primaryNodeIndex] = context.CreateInstance( From 0007744e00531de65b064f927338a450d0e840e8 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 01:47:37 +0100 Subject: [PATCH 32/42] fix tests --- test/Garnet.test.cluster/ClusterNegativeTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Garnet.test.cluster/ClusterNegativeTests.cs b/test/Garnet.test.cluster/ClusterNegativeTests.cs index f4a91a4b9b..a5734f188b 100644 --- a/test/Garnet.test.cluster/ClusterNegativeTests.cs +++ b/test/Garnet.test.cluster/ClusterNegativeTests.cs @@ -112,9 +112,9 @@ public async Task ClusterCommandWrongParameters(string subcommand, params int[] [Category("CLUSTER")] [TestCase(1024)] [TestCase(10240)] - public async Task ClusterAddSlotsPartialPackage(int chunkSize) + public void ClusterAddSlotsPartialPackage(int chunkSize) { - await context.CreateInstances(1); + context.CreateInstances(1).GetAwaiter().GetResult(); using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); socket.NoDelay = true; socket.Connect(IPAddress.Loopback, 7000); From 1b4dcae78fa4a3facbc23eb786b209c8d04f7099 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 02:38:03 +0100 Subject: [PATCH 33/42] refactor --- hosting/Windows/Garnet.worker/Program.cs | 21 +- hosting/Windows/Garnet.worker/Worker.cs | 52 --- .../{ => Factories}/GarnetProviderFactory.cs | 2 +- libs/host/{ => Factories}/StoreFactory.cs | 6 +- .../{ => Factories}/StoreWrapperFactory.cs | 16 +- libs/host/GarnetApplicationBuilder.cs | 4 +- libs/host/GarnetServer.cs | 356 +++++++---------- libs/host/GarnetServerHostedService.cs | 2 +- .../{ => Wrappers}/AppendOnlyFileWrapper.cs | 2 +- libs/host/{ => Wrappers}/MainStoreWrapper.cs | 2 +- .../host/{ => Wrappers}/ObjectStoreWrapper.cs | 2 +- libs/server/Servers/GarnetServerTcp.cs | 367 +++++++++--------- 12 files changed, 349 insertions(+), 483 deletions(-) delete mode 100644 hosting/Windows/Garnet.worker/Worker.cs rename libs/host/{ => Factories}/GarnetProviderFactory.cs (96%) rename libs/host/{ => Factories}/StoreFactory.cs (94%) rename libs/host/{ => Factories}/StoreWrapperFactory.cs (84%) rename libs/host/{ => Wrappers}/AppendOnlyFileWrapper.cs (90%) rename libs/host/{ => Wrappers}/MainStoreWrapper.cs (95%) rename libs/host/{ => Wrappers}/ObjectStoreWrapper.cs (96%) diff --git a/hosting/Windows/Garnet.worker/Program.cs b/hosting/Windows/Garnet.worker/Program.cs index 8418da8671..854d7c4ab4 100644 --- a/hosting/Windows/Garnet.worker/Program.cs +++ b/hosting/Windows/Garnet.worker/Program.cs @@ -5,19 +5,12 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -class Program -{ - static void Main(string[] args) - { - var builder = Host.CreateApplicationBuilder(args); - builder.Services.AddHostedService(_ => new Worker(args)); +var builder = GarnetApplication.CreateHostBuilder(args); - builder.Services.AddWindowsService(options => - { - options.ServiceName = "Microsoft Garnet Server"; - }); +builder.Services.AddWindowsService(options => +{ + options.ServiceName = "Microsoft Garnet Server"; +}); - var host = builder.Build(); - host.Run(); - } -} \ No newline at end of file +var app = builder.Build(); +app.Run(); \ No newline at end of file diff --git a/hosting/Windows/Garnet.worker/Worker.cs b/hosting/Windows/Garnet.worker/Worker.cs deleted file mode 100644 index 6afaf69bc8..0000000000 --- a/hosting/Windows/Garnet.worker/Worker.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; - -namespace Garnet -{ - public class Worker : BackgroundService - { - private bool _isDisposed = false; - private readonly string[] args; - - private GarnetServer server; - - public Worker(string[] args) - { - this.args = args; - } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - var builder = GarnetApplication.CreateHostBuilder(args); - - var app = builder.Build(); - - await app.RunAsync(stoppingToken); - } - - /// - /// Triggered when the application host is performing a graceful shutdown. - /// - /// Indicates that the shutdown process should no longer be graceful. - public override async Task StopAsync(CancellationToken cancellationToken) - { - Dispose(); - await base.StopAsync(cancellationToken).ConfigureAwait(false); - } - - public override void Dispose() - { - if (_isDisposed) - { - return; - } - server?.Dispose(); - _isDisposed = true; - } - } -} \ No newline at end of file diff --git a/libs/host/GarnetProviderFactory.cs b/libs/host/Factories/GarnetProviderFactory.cs similarity index 96% rename from libs/host/GarnetProviderFactory.cs rename to libs/host/Factories/GarnetProviderFactory.cs index 90266d0650..e1b9162fef 100644 --- a/libs/host/GarnetProviderFactory.cs +++ b/libs/host/Factories/GarnetProviderFactory.cs @@ -8,7 +8,7 @@ namespace Garnet; -public class GarnetProviderFactory +internal class GarnetProviderFactory { readonly GarnetServerOptions options; readonly SubscribeBroker> subscribeBroker; diff --git a/libs/host/StoreFactory.cs b/libs/host/Factories/StoreFactory.cs similarity index 94% rename from libs/host/StoreFactory.cs rename to libs/host/Factories/StoreFactory.cs index aade30179f..9802c886ba 100644 --- a/libs/host/StoreFactory.cs +++ b/libs/host/Factories/StoreFactory.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -using System; using Garnet.server; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -9,16 +8,13 @@ namespace Garnet; -using MainStoreAllocator = - SpanByteAllocator>; -using MainStoreFunctions = StoreFunctions; using ObjectStoreAllocator = GenericAllocator>>; using ObjectStoreFunctions = StoreFunctions>; -public class StoreFactory +internal class StoreFactory { private readonly IClusterFactory clusterFactory; private readonly GarnetServerOptions opts; diff --git a/libs/host/StoreWrapperFactory.cs b/libs/host/Factories/StoreWrapperFactory.cs similarity index 84% rename from libs/host/StoreWrapperFactory.cs rename to libs/host/Factories/StoreWrapperFactory.cs index ae99b2cd9b..1627618682 100644 --- a/libs/host/StoreWrapperFactory.cs +++ b/libs/host/Factories/StoreWrapperFactory.cs @@ -7,20 +7,10 @@ using Garnet.server; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Tsavorite.core; namespace Garnet; -using MainStoreAllocator = - SpanByteAllocator>; -using MainStoreFunctions = StoreFunctions; -using ObjectStoreAllocator = - GenericAllocator>>; -using ObjectStoreFunctions = - StoreFunctions>; - -public class StoreWrapperFactory +internal class StoreWrapperFactory { /// /// Resp protocol version @@ -30,7 +20,6 @@ public class StoreWrapperFactory readonly ILoggerFactory loggerFactory; readonly ILogger logger; readonly IGarnetServer garnetServer; - readonly StoreFactory storeFactory; readonly GarnetServerOptions options; readonly CustomCommandManager customCommandManager; readonly IClusterFactory clusterFactory; @@ -42,7 +31,6 @@ public StoreWrapperFactory( ILoggerFactory loggerFactory, ILogger logger, IGarnetServer garnetServer, - StoreFactory storeFactory, IOptions options, CustomCommandManager customCommandManager, IClusterFactory clusterFactory, @@ -53,7 +41,6 @@ public StoreWrapperFactory( this.loggerFactory = loggerFactory; this.logger = logger; this.garnetServer = garnetServer; - this.storeFactory = storeFactory; this.options = options.Value; this.customCommandManager = customCommandManager; this.clusterFactory = this.options.EnableCluster ? clusterFactory : null; @@ -75,7 +62,6 @@ public StoreWrapper Create(string version) (appendOnlyFile?.MaxMemorySizeBytes ?? 0); if (objectStore != null) { - configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + (objectStoreSizeTracker?.TargetSize ?? 0) + diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index f5cd98ec43..05e4e589dc 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -103,7 +103,7 @@ public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOp return storeFactory.CreateObjectStore(); }); - hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddSingleton(sp => { @@ -136,7 +136,7 @@ public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOp hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddSingleton(); - hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddHostedService(); } diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index e381cab4c7..0512d18b62 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -3,257 +3,201 @@ using System; using System.Diagnostics; -using System.IO; -using System.Linq; using System.Reflection; -using System.Text; using System.Threading; -using Garnet.cluster; -using Garnet.common; using Garnet.networking; using Garnet.server; -using Garnet.server.Auth.Settings; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Tsavorite.core; -namespace Garnet +namespace Garnet; + +/// +/// Implementation Garnet server +/// +internal class GarnetServer : IDisposable { - using MainStoreAllocator = - SpanByteAllocator>; - using MainStoreFunctions = StoreFunctions; - using ObjectStoreAllocator = - GenericAllocator>>; - using ObjectStoreFunctions = - StoreFunctions>; + static readonly string version = GetVersion(); + + static string GetVersion() + { + var Version = Assembly.GetExecutingAssembly().GetName().Version; + return $"{Version.Major}.{Version.Minor}.{Version.Build}"; + } + + private readonly GarnetProvider provider; + private readonly GarnetServerOptions opts; + private readonly IGarnetServer server; + private readonly ILogger logger; + private readonly ILoggerFactory loggerFactory; + private readonly bool cleanupDir; /// - /// Implementation Garnet server + /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. /// - public class GarnetServer : IDisposable + /// Server options + /// Logger + /// Logger factory + /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. + /// + public GarnetServer( + IOptions options, + ILogger logger, + ILoggerFactory loggerFactory, + IGarnetServer server, + GarnetProvider garnetProvider) + { + this.server = server; + this.opts = options.Value; + this.logger = logger; + this.loggerFactory = loggerFactory; + this.provider = garnetProvider; + + this.cleanupDir = false; + this.InitializeServerUpdated(); + } + + private void InitializeServerUpdated() { - static readonly string version = GetVersion(); + Debug.Assert(opts != null); - static string GetVersion() + if (!opts.QuietMode) { - var Version = Assembly.GetExecutingAssembly().GetName().Version; - return $"{Version.Major}.{Version.Minor}.{Version.Build}"; + var red = "\u001b[31m"; + var magenta = "\u001b[35m"; + var normal = "\u001b[0m"; + + Console.WriteLine($@"{red} _________ + /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} + '. \ / .' {normal}Port: {opts.Port}{red} + '.\ /.' {magenta}https://aka.ms/GetGarnet{red} + '.' + {normal}"); } - internal GarnetProvider Provider; + logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, + IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); - private readonly GarnetServerOptions opts; - private IGarnetServer server; - private ILogger logger; - private readonly ILoggerFactory loggerFactory; - private readonly bool cleanupDir; + // Flush initialization logs from memory logger + FlushMemoryLogger(null, "ArgParser", this.loggerFactory); - /// - /// Store and associated information used by this Garnet server - /// - protected StoreWrapper storeWrapper; + ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); + ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); - /// - /// Resp protocol version - /// - readonly string redisProtocolVersion = "7.2.5"; - - /// - /// Metrics API - /// - public MetricsApi Metrics; - - /// - /// Command registration API - /// - public RegisterApi Register; - - /// - /// Store API - /// - public StoreApi Store; - - /// - /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. - /// - /// Server options - /// Logger - /// Logger factory - /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. - /// - /// - /// - /// - public GarnetServer( - IOptions options, - ILogger logger, - ILoggerFactory loggerFactory, - IGarnetServer server, - GarnetProvider garnetProvider, - MetricsApi metricsApi, - RegisterApi registerApi, - StoreApi storeApi) + bool minChanged = false, maxChanged = false; + if (opts.ThreadPoolMinThreads > 0) { - this.server = server; - this.opts = options.Value; - this.logger = logger; - this.loggerFactory = loggerFactory; - this.Provider = garnetProvider; - this.Metrics = metricsApi; - this.Register = registerApi; - this.Store = storeApi; - - this.cleanupDir = false; - this.InitializeServerUpdated(); + minThreads = opts.ThreadPoolMinThreads; + minChanged = true; } - private void InitializeServerUpdated() + if (opts.ThreadPoolMinIOCompletionThreads > 0) { - Debug.Assert(opts != null); - - if (!opts.QuietMode) - { - var red = "\u001b[31m"; - var magenta = "\u001b[35m"; - var normal = "\u001b[0m"; - - Console.WriteLine($@"{red} _________ - /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} - '. \ / .' {normal}Port: {opts.Port}{red} - '.\ /.' {magenta}https://aka.ms/GetGarnet{red} - '.' - {normal}"); - } - - logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, - IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); - - // Flush initialization logs from memory logger - FlushMemoryLogger(null, "ArgParser", this.loggerFactory); - - ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); - ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); - - bool minChanged = false, maxChanged = false; - if (opts.ThreadPoolMinThreads > 0) - { - minThreads = opts.ThreadPoolMinThreads; - minChanged = true; - } - - if (opts.ThreadPoolMinIOCompletionThreads > 0) - { - minCPThreads = opts.ThreadPoolMinIOCompletionThreads; - minChanged = true; - } + minCPThreads = opts.ThreadPoolMinIOCompletionThreads; + minChanged = true; + } - if (opts.ThreadPoolMaxThreads > 0) - { - maxThreads = opts.ThreadPoolMaxThreads; - maxChanged = true; - } + if (opts.ThreadPoolMaxThreads > 0) + { + maxThreads = opts.ThreadPoolMaxThreads; + maxChanged = true; + } - if (opts.ThreadPoolMaxIOCompletionThreads > 0) - { - maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; - maxChanged = true; - } + if (opts.ThreadPoolMaxIOCompletionThreads > 0) + { + maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; + maxChanged = true; + } - // First try to set the max threads - var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); + // First try to set the max threads + var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); - // Set the min threads - if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); + // Set the min threads + if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); - // Retry to set max threads if it wasn't set in the earlier step - if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); + // Retry to set max threads if it wasn't set in the earlier step + if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); + logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - server.Register(WireFormat.ASCII, Provider); - } + server.Register(WireFormat.ASCII, provider); + } - /// - /// Start server instance - /// - public void Start() - { - Provider.Recover(); - server.Start(); - Provider.Start(); - if (!opts.QuietMode) - Console.WriteLine("* Ready to accept connections"); - } + /// + /// Start server instance + /// + public void Start() + { + provider.Recover(); + server.Start(); + provider.Start(); + if (!opts.QuietMode) + Console.WriteLine("* Ready to accept connections"); + } - /// - /// Dispose store (including log and checkpoint directory) - /// - public void Dispose() - { - Dispose(cleanupDir); - } + /// + /// Dispose store (including log and checkpoint directory) + /// + public void Dispose() + { + server?.Dispose(); + Dispose(cleanupDir); + } - /// - /// Dispose, optionally deleting logs and checkpoints - /// - /// Whether to delete logs and checkpoints - public void Dispose(bool deleteDir = true) + /// + /// Dispose, optionally deleting logs and checkpoints + /// + /// Whether to delete logs and checkpoints + public void Dispose(bool deleteDir = true) + { + if (deleteDir) { - InternalDispose(); - if (deleteDir) + if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) { - if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) - { - var ckptdir = opts.DeviceFactoryCreator(); - ckptdir.Initialize(opts.CheckpointDir); - ckptdir.Delete(new FileDescriptor { directoryName = "" }); - } + var ckptdir = opts.DeviceFactoryCreator(); + ckptdir.Initialize(opts.CheckpointDir); + ckptdir.Delete(new FileDescriptor { directoryName = "" }); } } + } - private void InternalDispose() - { - server.Dispose(); - } + /// + /// Flushes MemoryLogger entries into a destination logger. + /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. + /// + /// The memory logger + /// The category name of the destination logger + /// Optional logger factory for creating the destination logger + private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, + ILoggerFactory dstLoggerFactory = null) + { + if (memoryLogger == null) return; - /// - /// Flushes MemoryLogger entries into a destination logger. - /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. - /// - /// The memory logger - /// The category name of the destination logger - /// Optional logger factory for creating the destination logger - private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, - ILoggerFactory dstLoggerFactory = null) + // If no logger factory supplied, create a default console logger + var disposeDstLoggerFactory = false; + if (dstLoggerFactory == null) { - if (memoryLogger == null) return; - - // If no logger factory supplied, create a default console logger - var disposeDstLoggerFactory = false; - if (dstLoggerFactory == null) + dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => { - dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => - { - options.SingleLine = true; - options.TimestampFormat = "hh::mm::ss "; - }).SetMinimumLevel(LogLevel.Information)); - disposeDstLoggerFactory = true; - } + options.SingleLine = true; + options.TimestampFormat = "hh::mm::ss "; + }).SetMinimumLevel(LogLevel.Information)); + disposeDstLoggerFactory = true; + } - // Create the destination logger - var dstLogger = dstLoggerFactory.CreateLogger(categoryName); + // Create the destination logger + var dstLogger = dstLoggerFactory.CreateLogger(categoryName); - // Flush all entries from the memory logger into the destination logger - memoryLogger.FlushLogger(dstLogger); + // Flush all entries from the memory logger into the destination logger + memoryLogger.FlushLogger(dstLogger); - // If a default console logger factory was created, it is no longer needed - if (disposeDstLoggerFactory) - { - dstLoggerFactory.Dispose(); - } + // If a default console logger factory was created, it is no longer needed + if (disposeDstLoggerFactory) + { + dstLoggerFactory.Dispose(); } } } \ No newline at end of file diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index 0a231a684a..6aca429e0b 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -10,7 +10,7 @@ namespace Garnet; -public class GarnetServerHostedService : BackgroundService +internal class GarnetServerHostedService : BackgroundService { readonly GarnetServer server; readonly ILogger logger; diff --git a/libs/host/AppendOnlyFileWrapper.cs b/libs/host/Wrappers/AppendOnlyFileWrapper.cs similarity index 90% rename from libs/host/AppendOnlyFileWrapper.cs rename to libs/host/Wrappers/AppendOnlyFileWrapper.cs index 0d83252ba0..9886e7b5c6 100644 --- a/libs/host/AppendOnlyFileWrapper.cs +++ b/libs/host/Wrappers/AppendOnlyFileWrapper.cs @@ -6,7 +6,7 @@ namespace Garnet; -public class AppendOnlyFileWrapper : IDisposable +internal class AppendOnlyFileWrapper : IDisposable { readonly IDevice device; public readonly TsavoriteLog appendOnlyFile; diff --git a/libs/host/MainStoreWrapper.cs b/libs/host/Wrappers/MainStoreWrapper.cs similarity index 95% rename from libs/host/MainStoreWrapper.cs rename to libs/host/Wrappers/MainStoreWrapper.cs index 2cb4bb6f29..f6dc6c27ce 100644 --- a/libs/host/MainStoreWrapper.cs +++ b/libs/host/Wrappers/MainStoreWrapper.cs @@ -10,7 +10,7 @@ namespace Garnet; SpanByteAllocator>; using MainStoreFunctions = StoreFunctions; -public class MainStoreWrapper : IDisposable +internal class MainStoreWrapper : IDisposable { public readonly TsavoriteKV store; diff --git a/libs/host/ObjectStoreWrapper.cs b/libs/host/Wrappers/ObjectStoreWrapper.cs similarity index 96% rename from libs/host/ObjectStoreWrapper.cs rename to libs/host/Wrappers/ObjectStoreWrapper.cs index c9b88f4eb7..3bb8301def 100644 --- a/libs/host/ObjectStoreWrapper.cs +++ b/libs/host/Wrappers/ObjectStoreWrapper.cs @@ -13,7 +13,7 @@ namespace Garnet; using ObjectStoreFunctions = StoreFunctions>; -public class ObjectStoreWrapper : IDisposable +internal class ObjectStoreWrapper : IDisposable { public readonly TsavoriteKV objectStore; readonly KVSettings objKvSettings; diff --git a/libs/server/Servers/GarnetServerTcp.cs b/libs/server/Servers/GarnetServerTcp.cs index ba8478a779..a23461f44d 100644 --- a/libs/server/Servers/GarnetServerTcp.cs +++ b/libs/server/Servers/GarnetServerTcp.cs @@ -12,232 +12,231 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace Garnet.server +namespace Garnet.server; + +/// +/// Garnet server for TCP +/// +public class GarnetServerTcp : GarnetServerBase, IServerHook, IDisposable { - /// - /// Garnet server for TCP - /// - public class GarnetServerTcp : GarnetServerBase, IServerHook + readonly SocketAsyncEventArgs acceptEventArg; + readonly Socket servSocket; + readonly IGarnetTlsOptions tlsOptions; + readonly int networkSendThrottleMax; + readonly NetworkBufferSettings networkBufferSettings; + readonly LimitedFixedBufferPool networkPool; + readonly int networkConnectionLimit; + + public IPEndPoint GetEndPoint { - readonly SocketAsyncEventArgs acceptEventArg; - readonly Socket servSocket; - readonly IGarnetTlsOptions tlsOptions; - readonly int networkSendThrottleMax; - readonly NetworkBufferSettings networkBufferSettings; - readonly LimitedFixedBufferPool networkPool; - readonly int networkConnectionLimit; - - public IPEndPoint GetEndPoint + get { - get - { - var ip = string.IsNullOrEmpty(Address) ? IPAddress.Any : IPAddress.Parse(Address); - return new IPEndPoint(ip, Port); - } + var ip = string.IsNullOrEmpty(Address) ? IPAddress.Any : IPAddress.Parse(Address); + return new IPEndPoint(ip, Port); } + } - /// - /// Get active consumers - /// - public override IEnumerable ActiveConsumers() + /// + /// Get active consumers + /// + public override IEnumerable ActiveConsumers() + { + foreach (var kvp in activeHandlers) { - foreach (var kvp in activeHandlers) - { - var consumer = kvp.Key.Session; - if (consumer != null) - yield return consumer; - } + var consumer = kvp.Key.Session; + if (consumer != null) + yield return consumer; } + } - /// - /// Get active consumers - /// - public IEnumerable ActiveClusterSessions() + /// + /// Get active consumers + /// + public IEnumerable ActiveClusterSessions() + { + foreach (var kvp in activeHandlers) { - foreach (var kvp in activeHandlers) - { - var consumer = kvp.Key.Session; - if (consumer != null) - yield return ((RespServerSession)consumer).clusterSession; - } + var consumer = kvp.Key.Session; + if (consumer != null) + yield return ((RespServerSession)consumer).clusterSession; } + } - /// - /// Constructor for server - /// - /// - /// - public GarnetServerTcp(IOptions options, ILogger logger) - : base(options.Value.Address, options.Value.Port, 0, logger) - { - this.networkConnectionLimit = options.Value.NetworkConnectionLimit; - this.tlsOptions = options.Value.TlsOptions; - this.networkSendThrottleMax = options.Value.NetworkSendThrottleMax; - var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); - this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); - this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); - servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - acceptEventArg = new SocketAsyncEventArgs(); - acceptEventArg.Completed += AcceptEventArg_Completed; - } + /// + /// Constructor for server + /// + /// + /// + public GarnetServerTcp(IOptions options, ILogger logger) + : base(options.Value.Address, options.Value.Port, 0, logger) + { + this.networkConnectionLimit = options.Value.NetworkConnectionLimit; + this.tlsOptions = options.Value.TlsOptions; + this.networkSendThrottleMax = options.Value.NetworkSendThrottleMax; + var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); + this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); + this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); + servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + acceptEventArg = new SocketAsyncEventArgs(); + acceptEventArg.Completed += AcceptEventArg_Completed; + } - /// - /// Constructor for server - /// - /// - /// - /// - /// - /// - /// - public GarnetServerTcp(string address, int port, int networkBufferSize = default, IGarnetTlsOptions tlsOptions = null, int networkSendThrottleMax = 8, int networkConnectionLimit = -1, ILogger logger = null) - : base(address, port, networkBufferSize, logger) - { - this.networkConnectionLimit = networkConnectionLimit; - this.tlsOptions = tlsOptions; - this.networkSendThrottleMax = networkSendThrottleMax; - var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); - this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); - this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); - servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - acceptEventArg = new SocketAsyncEventArgs(); - acceptEventArg.Completed += AcceptEventArg_Completed; - } + /// + /// Constructor for server + /// + /// + /// + /// + /// + /// + /// + public GarnetServerTcp(string address, int port, int networkBufferSize = default, IGarnetTlsOptions tlsOptions = null, int networkSendThrottleMax = 8, int networkConnectionLimit = -1, ILogger logger = null) + : base(address, port, networkBufferSize, logger) + { + this.networkConnectionLimit = networkConnectionLimit; + this.tlsOptions = tlsOptions; + this.networkSendThrottleMax = networkSendThrottleMax; + var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); + this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); + this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); + servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + acceptEventArg = new SocketAsyncEventArgs(); + acceptEventArg.Completed += AcceptEventArg_Completed; + } - /// - /// Dispose - /// - public override void Dispose() - { - base.Dispose(); - servSocket.Dispose(); - acceptEventArg.UserToken = null; - acceptEventArg.Dispose(); - networkPool?.Dispose(); - } + /// + /// Dispose + /// + public override void Dispose() + { + base.Dispose(); + servSocket.Dispose(); + acceptEventArg.UserToken = null; + acceptEventArg.Dispose(); + networkPool?.Dispose(); + } - /// - /// Start listening to incoming requests - /// - public override void Start() - { - var endPoint = GetEndPoint; - servSocket.Bind(endPoint); - servSocket.Listen(512); - if (!servSocket.AcceptAsync(acceptEventArg)) - AcceptEventArg_Completed(null, acceptEventArg); - } + /// + /// Start listening to incoming requests + /// + public override void Start() + { + var endPoint = GetEndPoint; + servSocket.Bind(endPoint); + servSocket.Listen(512); + if (!servSocket.AcceptAsync(acceptEventArg)) + AcceptEventArg_Completed(null, acceptEventArg); + } - private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) + private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) + { + try { - try + do { - do - { - if (!HandleNewConnection(e)) break; - e.AcceptSocket = null; - } while (!servSocket.AcceptAsync(e)); - } - // socket disposed - catch (ObjectDisposedException) { } + if (!HandleNewConnection(e)) break; + e.AcceptSocket = null; + } while (!servSocket.AcceptAsync(e)); } + // socket disposed + catch (ObjectDisposedException) { } + } - private unsafe bool HandleNewConnection(SocketAsyncEventArgs e) + private unsafe bool HandleNewConnection(SocketAsyncEventArgs e) + { + if (e.SocketError != SocketError.Success) { - if (e.SocketError != SocketError.Success) - { - e.Dispose(); - return false; - } + e.Dispose(); + return false; + } - e.AcceptSocket.NoDelay = true; + e.AcceptSocket.NoDelay = true; - // Ok to create new event args on accept because we assume a connection to be long-running - string remoteEndpointName = e.AcceptSocket.RemoteEndPoint?.ToString(); - logger?.LogDebug("Accepted TCP connection from {remoteEndpoint}", remoteEndpointName); + // Ok to create new event args on accept because we assume a connection to be long-running + string remoteEndpointName = e.AcceptSocket.RemoteEndPoint?.ToString(); + logger?.LogDebug("Accepted TCP connection from {remoteEndpoint}", remoteEndpointName); - ServerTcpNetworkHandler handler = null; - if (activeHandlerCount >= 0) + ServerTcpNetworkHandler handler = null; + if (activeHandlerCount >= 0) + { + var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); + if (currentActiveHandlerCount > 0 && (networkConnectionLimit == -1 || currentActiveHandlerCount <= networkConnectionLimit)) { - var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); - if (currentActiveHandlerCount > 0 && (networkConnectionLimit == -1 || currentActiveHandlerCount <= networkConnectionLimit)) + try { - try - { - handler = new ServerTcpNetworkHandler(this, e.AcceptSocket, networkBufferSettings, networkPool, tlsOptions != null, networkSendThrottleMax: networkSendThrottleMax, logger: logger); - if (!activeHandlers.TryAdd(handler, default)) - throw new Exception("Unable to add handler to dictionary"); - - handler.Start(tlsOptions?.TlsServerOptions, remoteEndpointName); - incr_conn_recv(); - return true; - } - catch (Exception ex) - { - logger?.LogError(ex, "Error starting network handler"); - Interlocked.Decrement(ref activeHandlerCount); - handler?.Dispose(); - } + handler = new ServerTcpNetworkHandler(this, e.AcceptSocket, networkBufferSettings, networkPool, tlsOptions != null, networkSendThrottleMax: networkSendThrottleMax, logger: logger); + if (!activeHandlers.TryAdd(handler, default)) + throw new Exception("Unable to add handler to dictionary"); + + handler.Start(tlsOptions?.TlsServerOptions, remoteEndpointName); + incr_conn_recv(); + return true; } - else + catch (Exception ex) { + logger?.LogError(ex, "Error starting network handler"); Interlocked.Decrement(ref activeHandlerCount); - e.AcceptSocket.Dispose(); + handler?.Dispose(); } } - return true; + else + { + Interlocked.Decrement(ref activeHandlerCount); + e.AcceptSocket.Dispose(); + } } + return true; + } - /// - /// Create session (message consumer) given incoming bytes - /// - /// - /// - /// - /// - public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) - { - session = null; + /// + /// Create session (message consumer) given incoming bytes + /// + /// + /// + /// + /// + public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) + { + session = null; - // We need at least 4 bytes to determine session - if (bytes.Length < 4) - return false; + // We need at least 4 bytes to determine session + if (bytes.Length < 4) + return false; - WireFormat protocol = WireFormat.ASCII; + WireFormat protocol = WireFormat.ASCII; - if (!GetSessionProviders().TryGetValue(protocol, out var provider)) - { - var input = System.Text.Encoding.ASCII.GetString(bytes); - logger?.LogError("Cannot identify wire protocol {bytes}", input); - throw new Exception($"Unsupported incoming wire format {protocol} {input}"); - } + if (!GetSessionProviders().TryGetValue(protocol, out var provider)) + { + var input = System.Text.Encoding.ASCII.GetString(bytes); + logger?.LogError("Cannot identify wire protocol {bytes}", input); + throw new Exception($"Unsupported incoming wire format {protocol} {input}"); + } - if (!AddSession(protocol, ref provider, networkSender, out session)) - throw new Exception($"Unable to add session"); + if (!AddSession(protocol, ref provider, networkSender, out session)) + throw new Exception($"Unable to add session"); - return true; - } + return true; + } - /// - public void DisposeMessageConsumer(INetworkHandler session) + /// + public void DisposeMessageConsumer(INetworkHandler session) + { + if (activeHandlers.TryRemove(session, out _)) { - if (activeHandlers.TryRemove(session, out _)) + Interlocked.Decrement(ref activeHandlerCount); + incr_conn_disp(); + try { - Interlocked.Decrement(ref activeHandlerCount); - incr_conn_disp(); - try - { - session.Session?.Dispose(); - } - catch (Exception ex) - { - logger?.LogError(ex, "Error disposing RespServerSession"); - } + session.Session?.Dispose(); + } + catch (Exception ex) + { + logger?.LogError(ex, "Error disposing RespServerSession"); } } + } - public void Purge() => networkPool.Purge(); + public void Purge() => networkPool.Purge(); - public string GetBufferPoolStats() => networkPool.GetStats(); - } + public string GetBufferPoolStats() => networkPool.GetStats(); } \ No newline at end of file From 0ef801b39a9e33c4682519af65fc98186c377e36 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 03:20:43 +0100 Subject: [PATCH 34/42] move code from GarnetServer to GarnetServerHostedService --- .../BDN.benchmark/Cluster/ClusterContext.cs | 13 +- .../Embedded/EmbeddedRespServer.cs | 48 +++-- libs/host/GarnetApplicationBuilder.cs | 2 - libs/host/GarnetServer.cs | 203 ------------------ libs/host/GarnetServerHostedService.cs | 165 +++++++++++++- 5 files changed, 193 insertions(+), 238 deletions(-) delete mode 100644 libs/host/GarnetServer.cs diff --git a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs index 0cd075cc4e..eb8d817ade 100644 --- a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs +++ b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs @@ -12,7 +12,7 @@ namespace BDN.benchmark.Cluster { class ClusterContext { - EmbeddedRespServer server; + GarnetEmbeddedApplication server; RespServerSession session; readonly BenchUtils benchUtils = new(); readonly int port = 7000; @@ -22,11 +22,10 @@ class ClusterContext public Request[] singleMGetMSet; public Request singleCTXNSET; - public Task Dispose() + public async Task Dispose() { session.Dispose(); - server.Dispose(); - return Task.CompletedTask; + await server.StopAsync(); } public void SetupSingleInstance(bool disableSlotVerification = false) @@ -41,8 +40,12 @@ public void SetupSingleInstance(bool disableSlotVerification = false) if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) opt.CheckpointDir = "/tmp"; - server = new EmbeddedRespServer(opt); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opt); + + server = builder.Build(); + session = server.GetRespSession(); + _ = server.Register.NewTransactionProc(CustomTxnSet.CommandName, () => new CustomTxnSet(), new RespCommandsInfo { Arity = CustomTxnSet.Arity }); } diff --git a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs index 10f7c6ac3c..d93653d606 100644 --- a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs +++ b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs @@ -5,6 +5,7 @@ using Garnet.common; using Garnet.server; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Tsavorite.core; namespace Embedded.server @@ -14,27 +15,23 @@ namespace Embedded.server /// internal sealed class EmbeddedRespServer : GarnetServer { - readonly GarnetServerEmbedded garnetServerEmbedded; - readonly SubscribeBroker> subscribeBroker; - - /// - /// Creates an EmbeddedRespServer instance - /// - /// Server options to configure the base GarnetServer instance - /// Logger factory to configure the base GarnetServer instance - /// Server network - public EmbeddedRespServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, GarnetServerEmbedded server = null) - //: base(opts, loggerFactory, server) - : base(null, null, loggerFactory, server, null, null, null, null) + readonly StoreWrapper store; + readonly GarnetServerEmbedded server; + readonly SubscribeBroker> subscriberBroker; + + public EmbeddedRespServer( + IOptions options, + ILogger logger, + ILoggerFactory loggerFactory, + GarnetServerEmbedded server, + GarnetProvider provider, + SubscribeBroker> subscriberBroker, + StoreWrapper store) + : base(options, logger, loggerFactory, server, provider) { - this.garnetServerEmbedded = server; - this.subscribeBroker = opts.DisablePubSub ? null : - new SubscribeBroker>( - new SpanByteKeySerializer(), - null, - opts.PubSubPageSizeBytes(), - opts.SubscriberRefreshFrequencyMs, - true); + this.store = store; + this.server = server; + this.subscriberBroker = subscriberBroker; } /// @@ -42,7 +39,7 @@ public EmbeddedRespServer(GarnetServerOptions opts, ILoggerFactory loggerFactory /// public new void Dispose() => base.Dispose(); - public StoreWrapper StoreWrapper => storeWrapper; + public StoreWrapper StoreWrapper => store; /// /// Return a direct RESP session to this server @@ -50,12 +47,17 @@ public EmbeddedRespServer(GarnetServerOptions opts, ILoggerFactory loggerFactory /// A new RESP server session internal RespServerSession GetRespSession() { - return new RespServerSession(0, new EmbeddedNetworkSender(), storeWrapper, subscribeBroker: subscribeBroker, null, true); + return new RespServerSession(0, + new EmbeddedNetworkSender(), + store, + subscribeBroker: this.subscriberBroker, + null, + true); } internal EmbeddedNetworkHandler GetNetworkHandler() { - return garnetServerEmbedded.CreateNetworkHandler(); + return server.CreateNetworkHandler(); } } } \ No newline at end of file diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 05e4e589dc..2c8e62be2b 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -136,8 +136,6 @@ public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOp hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddSingleton(); - hostApplicationBuilder.Services.AddSingleton(); - hostApplicationBuilder.Services.AddHostedService(); } diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs deleted file mode 100644 index 0512d18b62..0000000000 --- a/libs/host/GarnetServer.cs +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -using System; -using System.Diagnostics; -using System.Reflection; -using System.Threading; -using Garnet.networking; -using Garnet.server; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Tsavorite.core; - -namespace Garnet; - -/// -/// Implementation Garnet server -/// -internal class GarnetServer : IDisposable -{ - static readonly string version = GetVersion(); - - static string GetVersion() - { - var Version = Assembly.GetExecutingAssembly().GetName().Version; - return $"{Version.Major}.{Version.Minor}.{Version.Build}"; - } - - private readonly GarnetProvider provider; - private readonly GarnetServerOptions opts; - private readonly IGarnetServer server; - private readonly ILogger logger; - private readonly ILoggerFactory loggerFactory; - private readonly bool cleanupDir; - - /// - /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. - /// - /// Server options - /// Logger - /// Logger factory - /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. - /// - public GarnetServer( - IOptions options, - ILogger logger, - ILoggerFactory loggerFactory, - IGarnetServer server, - GarnetProvider garnetProvider) - { - this.server = server; - this.opts = options.Value; - this.logger = logger; - this.loggerFactory = loggerFactory; - this.provider = garnetProvider; - - this.cleanupDir = false; - this.InitializeServerUpdated(); - } - - private void InitializeServerUpdated() - { - Debug.Assert(opts != null); - - if (!opts.QuietMode) - { - var red = "\u001b[31m"; - var magenta = "\u001b[35m"; - var normal = "\u001b[0m"; - - Console.WriteLine($@"{red} _________ - /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} - '. \ / .' {normal}Port: {opts.Port}{red} - '.\ /.' {magenta}https://aka.ms/GetGarnet{red} - '.' - {normal}"); - } - - logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, - IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); - - // Flush initialization logs from memory logger - FlushMemoryLogger(null, "ArgParser", this.loggerFactory); - - ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); - ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); - - bool minChanged = false, maxChanged = false; - if (opts.ThreadPoolMinThreads > 0) - { - minThreads = opts.ThreadPoolMinThreads; - minChanged = true; - } - - if (opts.ThreadPoolMinIOCompletionThreads > 0) - { - minCPThreads = opts.ThreadPoolMinIOCompletionThreads; - minChanged = true; - } - - if (opts.ThreadPoolMaxThreads > 0) - { - maxThreads = opts.ThreadPoolMaxThreads; - maxChanged = true; - } - - if (opts.ThreadPoolMaxIOCompletionThreads > 0) - { - maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; - maxChanged = true; - } - - // First try to set the max threads - var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); - - // Set the min threads - if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); - - // Retry to set max threads if it wasn't set in the earlier step - if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - - logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - - server.Register(WireFormat.ASCII, provider); - } - - /// - /// Start server instance - /// - public void Start() - { - provider.Recover(); - server.Start(); - provider.Start(); - if (!opts.QuietMode) - Console.WriteLine("* Ready to accept connections"); - } - - /// - /// Dispose store (including log and checkpoint directory) - /// - public void Dispose() - { - server?.Dispose(); - Dispose(cleanupDir); - } - - /// - /// Dispose, optionally deleting logs and checkpoints - /// - /// Whether to delete logs and checkpoints - public void Dispose(bool deleteDir = true) - { - if (deleteDir) - { - if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) - { - var ckptdir = opts.DeviceFactoryCreator(); - ckptdir.Initialize(opts.CheckpointDir); - ckptdir.Delete(new FileDescriptor { directoryName = "" }); - } - } - } - - /// - /// Flushes MemoryLogger entries into a destination logger. - /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. - /// - /// The memory logger - /// The category name of the destination logger - /// Optional logger factory for creating the destination logger - private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, - ILoggerFactory dstLoggerFactory = null) - { - if (memoryLogger == null) return; - - // If no logger factory supplied, create a default console logger - var disposeDstLoggerFactory = false; - if (dstLoggerFactory == null) - { - dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => - { - options.SingleLine = true; - options.TimestampFormat = "hh::mm::ss "; - }).SetMinimumLevel(LogLevel.Information)); - disposeDstLoggerFactory = true; - } - - // Create the destination logger - var dstLogger = dstLoggerFactory.CreateLogger(categoryName); - - // Flush all entries from the memory logger into the destination logger - memoryLogger.FlushLogger(dstLogger); - - // If a default console logger factory was created, it is no longer needed - if (disposeDstLoggerFactory) - { - dstLoggerFactory.Dispose(); - } - } -} \ No newline at end of file diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index 6aca429e0b..e4924b8337 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -2,31 +2,186 @@ // Licensed under the MIT license. using System; +using System.Diagnostics; +using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Garnet.networking; using Garnet.server; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; namespace Garnet; internal class GarnetServerHostedService : BackgroundService { - readonly GarnetServer server; - readonly ILogger logger; - - public GarnetServerHostedService(GarnetServer server, ILogger logger) + private readonly GarnetProvider provider; + private readonly GarnetServerOptions opts; + private readonly IGarnetServer server; + private readonly ILogger logger; + private readonly ILoggerFactory loggerFactory; + private readonly bool cleanupDir; + + public GarnetServerHostedService( + IOptions options, + ILogger logger, + ILoggerFactory loggerFactory, + IGarnetServer server, + GarnetProvider garnetProvider) { this.server = server; + this.opts = options.Value; this.logger = logger; + this.loggerFactory = loggerFactory; + this.provider = garnetProvider; + + this.cleanupDir = false; + this.InitializeServerUpdated(); + } + + private void InitializeServerUpdated() + { + Debug.Assert(opts != null); + + if (!opts.QuietMode) + { + var red = "\u001b[31m"; + var magenta = "\u001b[35m"; + var normal = "\u001b[0m"; + + Console.WriteLine($@"{red} _________ + /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} + '. \ / .' {normal}Port: {opts.Port}{red} + '.\ /.' {magenta}https://aka.ms/GetGarnet{red} + '.' + {normal}"); + } + + logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, + IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); + + // Flush initialization logs from memory logger + FlushMemoryLogger(null, "ArgParser", this.loggerFactory); + + ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); + ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); + + bool minChanged = false, maxChanged = false; + if (opts.ThreadPoolMinThreads > 0) + { + minThreads = opts.ThreadPoolMinThreads; + minChanged = true; + } + + if (opts.ThreadPoolMinIOCompletionThreads > 0) + { + minCPThreads = opts.ThreadPoolMinIOCompletionThreads; + minChanged = true; + } + + if (opts.ThreadPoolMaxThreads > 0) + { + maxThreads = opts.ThreadPoolMaxThreads; + maxChanged = true; + } + + if (opts.ThreadPoolMaxIOCompletionThreads > 0) + { + maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; + maxChanged = true; + } + + // First try to set the max threads + var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); + + // Set the min threads + if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); + + // Retry to set max threads if it wasn't set in the earlier step + if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); + + logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); + + server.Register(WireFormat.ASCII, provider); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { + provider.Recover(); server.Start(); - + provider.Start(); + + if (!opts.QuietMode) + { + logger.LogInformation("* Ready to accept connections"); + } + logger.LogInformation("Garnet server running at: {time}", DateTimeOffset.Now); await Task.CompletedTask; } + + public override async Task StopAsync(CancellationToken cancellationToken) + { + if (cleanupDir) + { + if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) + { + var ckptdir = opts.DeviceFactoryCreator(); + ckptdir.Initialize(opts.CheckpointDir); + ckptdir.Delete(new FileDescriptor { directoryName = "" }); + } + } + + await base.StopAsync(cancellationToken); + } + + static readonly string version = GetVersion(); + + static string GetVersion() + { + var Version = Assembly.GetExecutingAssembly().GetName().Version; + return $"{Version.Major}.{Version.Minor}.{Version.Build}"; + } + + /// + /// Flushes MemoryLogger entries into a destination logger. + /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. + /// + /// The memory logger + /// The category name of the destination logger + /// Optional logger factory for creating the destination logger + private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, + ILoggerFactory dstLoggerFactory = null) + { + if (memoryLogger == null) return; + + // If no logger factory supplied, create a default console logger + var disposeDstLoggerFactory = false; + if (dstLoggerFactory == null) + { + dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => + { + options.SingleLine = true; + options.TimestampFormat = "hh::mm::ss "; + }).SetMinimumLevel(LogLevel.Information)); + disposeDstLoggerFactory = true; + } + + // Create the destination logger + var dstLogger = dstLoggerFactory.CreateLogger(categoryName); + + // Flush all entries from the memory logger into the destination logger + memoryLogger.FlushLogger(dstLogger); + + // If a default console logger factory was created, it is no longer needed + if (disposeDstLoggerFactory) + { + dstLoggerFactory.Dispose(); + } + } } \ No newline at end of file From 17711c36493090c08b403c1f9ca1068c3907ccac Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 04:09:00 +0100 Subject: [PATCH 35/42] fix Embedded.perftest --- .../BDN.benchmark/Cluster/ClusterContext.cs | 6 +- .../Embedded/EmbeddedRespServer.cs | 101 +++++++------ libs/host/GarnetServerHostedService.cs | 14 +- .../EmbeddedPerformanceTest.cs | 4 +- .../GarnetEmbeddedApplicationBuilder.cs | 33 +++++ playground/Embedded.perftest/Program.cs | 139 +++++++++--------- 6 files changed, 169 insertions(+), 128 deletions(-) create mode 100644 playground/Embedded.perftest/GarnetEmbeddedApplicationBuilder.cs diff --git a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs index eb8d817ade..1291edcb6e 100644 --- a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs +++ b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs @@ -41,11 +41,11 @@ public void SetupSingleInstance(bool disableSlotVerification = false) opt.CheckpointDir = "/tmp"; var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opt); - + server = builder.Build(); - + session = server.GetRespSession(); - + _ = server.Register.NewTransactionProc(CustomTxnSet.CommandName, () => new CustomTxnSet(), new RespCommandsInfo { Arity = CustomTxnSet.Arity }); } diff --git a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs index d93653d606..f41d810c87 100644 --- a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs +++ b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs @@ -1,63 +1,66 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using Embedded.perftest; using Garnet; using Garnet.common; using Garnet.server; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.DependencyInjection; using Tsavorite.core; -namespace Embedded.server +namespace Embedded.server; + +/// +/// Implements an embedded Garnet RESP server +/// +internal sealed class GarnetEmbeddedApplication { + readonly StoreWrapper store; + readonly SubscribeBroker> subscriberBroker; + readonly GarnetApplication app; + + public GarnetEmbeddedApplication(GarnetApplication app) + { + this.app = app; + this.store = app.Services.GetRequiredService(); + this.subscriberBroker = + app.Services.GetRequiredService>>(); + } + + public static new GarnetEmbeddedApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) + { + return new(new GarnetApplicationOptions + { + Args = args, + }, options); + } + + /// + /// Dispose server + /// + public new void Dispose() => app.Dispose(); + + public StoreWrapper StoreWrapper => store; + /// - /// Implements an embedded Garnet RESP server + /// Return a direct RESP session to this server /// - internal sealed class EmbeddedRespServer : GarnetServer + /// A new RESP server session + internal RespServerSession GetRespSession() { - readonly StoreWrapper store; - readonly GarnetServerEmbedded server; - readonly SubscribeBroker> subscriberBroker; - - public EmbeddedRespServer( - IOptions options, - ILogger logger, - ILoggerFactory loggerFactory, - GarnetServerEmbedded server, - GarnetProvider provider, - SubscribeBroker> subscriberBroker, - StoreWrapper store) - : base(options, logger, loggerFactory, server, provider) - { - this.store = store; - this.server = server; - this.subscriberBroker = subscriberBroker; - } - - /// - /// Dispose server - /// - public new void Dispose() => base.Dispose(); - - public StoreWrapper StoreWrapper => store; - - /// - /// Return a direct RESP session to this server - /// - /// A new RESP server session - internal RespServerSession GetRespSession() - { - return new RespServerSession(0, - new EmbeddedNetworkSender(), - store, - subscribeBroker: this.subscriberBroker, - null, - true); - } - - internal EmbeddedNetworkHandler GetNetworkHandler() - { - return server.CreateNetworkHandler(); - } + return new RespServerSession(0, + new EmbeddedNetworkSender(), + store, + subscribeBroker: this.subscriberBroker, + null, + true); + } + + internal EmbeddedNetworkHandler GetNetworkHandler() + { + var iServer = this.app.Services.GetRequiredService(); + var server = (GarnetServerEmbedded)iServer; + + return server.CreateNetworkHandler(); } } \ No newline at end of file diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index e4924b8337..14774511f0 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -23,7 +23,7 @@ internal class GarnetServerHostedService : BackgroundService private readonly ILogger logger; private readonly ILoggerFactory loggerFactory; private readonly bool cleanupDir; - + public GarnetServerHostedService( IOptions options, ILogger logger, @@ -40,7 +40,7 @@ public GarnetServerHostedService( this.cleanupDir = false; this.InitializeServerUpdated(); } - + private void InitializeServerUpdated() { Debug.Assert(opts != null); @@ -114,12 +114,12 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) provider.Recover(); server.Start(); provider.Start(); - + if (!opts.QuietMode) { logger.LogInformation("* Ready to accept connections"); } - + logger.LogInformation("Garnet server running at: {time}", DateTimeOffset.Now); await Task.CompletedTask; @@ -136,10 +136,10 @@ public override async Task StopAsync(CancellationToken cancellationToken) ckptdir.Delete(new FileDescriptor { directoryName = "" }); } } - + await base.StopAsync(cancellationToken); } - + static readonly string version = GetVersion(); static string GetVersion() @@ -147,7 +147,7 @@ static string GetVersion() var Version = Assembly.GetExecutingAssembly().GetName().Version; return $"{Version.Major}.{Version.Minor}.{Version.Build}"; } - + /// /// Flushes MemoryLogger entries into a destination logger. /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. diff --git a/playground/Embedded.perftest/EmbeddedPerformanceTest.cs b/playground/Embedded.perftest/EmbeddedPerformanceTest.cs index e7eaf898c8..277bee8d11 100644 --- a/playground/Embedded.perftest/EmbeddedPerformanceTest.cs +++ b/playground/Embedded.perftest/EmbeddedPerformanceTest.cs @@ -25,7 +25,7 @@ internal class EmbeddedPerformanceTest /// /// Embedded server instance to issue commands to /// - readonly EmbeddedRespServer server; + readonly GarnetEmbeddedApplication server; /// /// Logger used to log test progress @@ -48,7 +48,7 @@ internal class EmbeddedPerformanceTest /// Test options. /// Factory to create the status logger for the test /// Thrown if given configuration is invalid. - public EmbeddedPerformanceTest(EmbeddedRespServer server, Options opts, ILoggerFactory loggerFactory) + public EmbeddedPerformanceTest(GarnetEmbeddedApplication server, Options opts, ILoggerFactory loggerFactory) { this.server = server; this.opts = opts; diff --git a/playground/Embedded.perftest/GarnetEmbeddedApplicationBuilder.cs b/playground/Embedded.perftest/GarnetEmbeddedApplicationBuilder.cs new file mode 100644 index 0000000000..22eb894965 --- /dev/null +++ b/playground/Embedded.perftest/GarnetEmbeddedApplicationBuilder.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Linq; +using Embedded.server; +using Garnet; +using Garnet.server; +using Microsoft.Extensions.DependencyInjection; + +namespace Embedded.perftest; + +internal class GarnetEmbeddedApplicationBuilder : GarnetApplicationBuilder +{ + internal GarnetEmbeddedApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + : base(options, garnetServerOptions) + { + } + + public new GarnetEmbeddedApplication Build() + { + var serviceDescriptor = base.Services + .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IGarnetServer)); + + base.Services.Remove(serviceDescriptor); + + base.Services.AddSingleton(); + + var app = base.Build(); + + return new GarnetEmbeddedApplication(app); + } +} \ No newline at end of file diff --git a/playground/Embedded.perftest/Program.cs b/playground/Embedded.perftest/Program.cs index 914ab0b170..243c32c960 100644 --- a/playground/Embedded.perftest/Program.cs +++ b/playground/Embedded.perftest/Program.cs @@ -4,90 +4,95 @@ using System; using CommandLine; using Embedded.server; +using Garnet; using Garnet.common; using Garnet.server; using Microsoft.Extensions.Logging; -namespace Embedded.perftest +namespace Embedded.perftest; + +/// +/// Performance test for the core processing loop of embedded (in-process) Garnet instances. +/// +/// NOTE: This performance test is designed to specifically stress-test the core RESP processing loop +/// of Garnet and, as such, tries to keep actual data manipulation minimal. +/// In its current form this is not a replacement for a full benchmark that can execute +/// on a larger data set. +/// +internal class Program { - /// - /// Performance test for the core processing loop of embedded (in-process) Garnet instances. - /// - /// NOTE: This performance test is designed to specifically stress-test the core RESP processing loop - /// of Garnet and, as such, tries to keep actual data manipulation minimal. - /// In its current form this is not a replacement for a full benchmark that can execute - /// on a larger data set. - /// - internal class Program + static void Main(string[] args) { - static void Main(string[] args) + // Parse and initialize test parameters + ParserResult result = Parser.Default.ParseArguments(args); + + if (result.Tag == ParserResultType.NotParsed) { - // Parse and initialize test parameters - ParserResult result = Parser.Default.ParseArguments(args); + return; + } - if (result.Tag == ParserResultType.NotParsed) - { - return; - } + var opts = result.MapResult(o => o, xs => new Options()); - var opts = result.MapResult(o => o, xs => new Options()); + var loggerFactory = CreateLoggerFactory(opts); - var loggerFactory = CreateLoggerFactory(opts); + // Create embedded Garnet server in-process + GarnetServerOptions opt = new GarnetServerOptions + { + QuietMode = true + }; - // Create embedded Garnet server in-process - GarnetServerOptions opt = new GarnetServerOptions - { - QuietMode = true - }; - using var server = new EmbeddedRespServer(opt, loggerFactory); + //using var server = new EmbeddedRespServer(opt, loggerFactory); - PrintBenchmarkConfig(opts); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opt); - // Run performance test - var perfTest = new EmbeddedPerformanceTest(server, opts, loggerFactory); - perfTest.Run(); + var app = builder.Build(); - return; - } + PrintBenchmarkConfig(opts); + + // Run performance test + var perfTest = new EmbeddedPerformanceTest(app, opts, loggerFactory); + perfTest.Run(); + + return; + } - /// - /// Create logger factory with the given test options - /// - static ILoggerFactory CreateLoggerFactory(Options opts) + /// + /// Create logger factory with the given test options + /// + static ILoggerFactory CreateLoggerFactory(Options opts) + { + return LoggerFactory.Create(builder => { - return LoggerFactory.Create(builder => + // Unless disabled, add console logger provider + if (!opts.DisableConsoleLogger) { - // Unless disabled, add console logger provider - if (!opts.DisableConsoleLogger) - { - builder.AddProvider(new PerformanceTestLoggerProvider(Console.Out)); - } - - // Optional: Flush log output to file. - if (opts.FileLogger != null) - { - builder.AddFile(opts.FileLogger); - } - - // Set logging level - builder.SetMinimumLevel(opts.LogLevel); - }); - } + builder.AddProvider(new PerformanceTestLoggerProvider(Console.Out)); + } - /// - /// Print a human-readable representation of the given test options - /// - /// Options to print - static void PrintBenchmarkConfig(Options opts) - { - Console.WriteLine("============== Configuration =============="); - Console.WriteLine($"Run time : {opts.RunTime} seconds"); - Console.WriteLine($"# Threads : {String.Join(", ", opts.NumThreads)}"); - Console.WriteLine($"Batch Size : {opts.BatchSize} operations"); - Console.WriteLine($"OpWorkload : {String.Join(", ", opts.OpWorkload)}"); - Console.WriteLine($"OpPercent : {String.Join(", ", opts.OpPercent)}"); - Console.WriteLine($"RNG Seed : {opts.Seed}"); - Console.WriteLine("==========================================="); - } + // Optional: Flush log output to file. + if (opts.FileLogger != null) + { + builder.AddFile(opts.FileLogger); + } + + // Set logging level + builder.SetMinimumLevel(opts.LogLevel); + }); + } + + /// + /// Print a human-readable representation of the given test options + /// + /// Options to print + static void PrintBenchmarkConfig(Options opts) + { + Console.WriteLine("============== Configuration =============="); + Console.WriteLine($"Run time : {opts.RunTime} seconds"); + Console.WriteLine($"# Threads : {String.Join(", ", opts.NumThreads)}"); + Console.WriteLine($"Batch Size : {opts.BatchSize} operations"); + Console.WriteLine($"OpWorkload : {String.Join(", ", opts.OpWorkload)}"); + Console.WriteLine($"OpPercent : {String.Join(", ", opts.OpPercent)}"); + Console.WriteLine($"RNG Seed : {opts.Seed}"); + Console.WriteLine("==========================================="); } } \ No newline at end of file From 49dd859001370795343a7114dfb2aceb52bd3f81 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 05:23:19 +0100 Subject: [PATCH 36/42] fix build --- .../BDN.benchmark/Cluster/ClusterContext.cs | 3 +- .../Embedded/EmbeddedRespServer.cs | 66 ------------------- .../Embedded/GarnetEmbeddedApplication.cs | 59 +++++++++++++++-- .../GarnetEmbeddedApplicationBuilder.cs | 18 +++-- .../BDN.benchmark/Lua/LuaRunnerOperations.cs | 14 +++- .../Lua/LuaScriptCacheOperations.cs | 8 ++- .../BDN.benchmark/Network/NetworkBase.cs | 6 +- .../Operations/OperationsBase.cs | 6 +- .../Operations/PubSubOperations.cs | 3 +- .../Operations/ScriptOperations.cs | 5 +- 10 files changed, 101 insertions(+), 87 deletions(-) delete mode 100644 benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs diff --git a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs index 1291edcb6e..b5ba60e991 100644 --- a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs +++ b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs @@ -26,6 +26,7 @@ public async Task Dispose() { session.Dispose(); await server.StopAsync(); + server.Dispose(); } public void SetupSingleInstance(bool disableSlotVerification = false) @@ -43,7 +44,7 @@ public void SetupSingleInstance(bool disableSlotVerification = false) var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opt); server = builder.Build(); - + session = server.GetRespSession(); _ = server.Register.NewTransactionProc(CustomTxnSet.CommandName, () => new CustomTxnSet(), new RespCommandsInfo { Arity = CustomTxnSet.Arity }); diff --git a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs deleted file mode 100644 index f41d810c87..0000000000 --- a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -using Embedded.perftest; -using Garnet; -using Garnet.common; -using Garnet.server; -using Microsoft.Extensions.DependencyInjection; -using Tsavorite.core; - -namespace Embedded.server; - -/// -/// Implements an embedded Garnet RESP server -/// -internal sealed class GarnetEmbeddedApplication -{ - readonly StoreWrapper store; - readonly SubscribeBroker> subscriberBroker; - readonly GarnetApplication app; - - public GarnetEmbeddedApplication(GarnetApplication app) - { - this.app = app; - this.store = app.Services.GetRequiredService(); - this.subscriberBroker = - app.Services.GetRequiredService>>(); - } - - public static new GarnetEmbeddedApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) - { - return new(new GarnetApplicationOptions - { - Args = args, - }, options); - } - - /// - /// Dispose server - /// - public new void Dispose() => app.Dispose(); - - public StoreWrapper StoreWrapper => store; - - /// - /// Return a direct RESP session to this server - /// - /// A new RESP server session - internal RespServerSession GetRespSession() - { - return new RespServerSession(0, - new EmbeddedNetworkSender(), - store, - subscribeBroker: this.subscriberBroker, - null, - true); - } - - internal EmbeddedNetworkHandler GetNetworkHandler() - { - var iServer = this.app.Services.GetRequiredService(); - var server = (GarnetServerEmbedded)iServer; - - return server.CreateNetworkHandler(); - } -} \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs index 113c8ddc1e..1b99ea47bb 100644 --- a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs @@ -2,20 +2,71 @@ // Licensed under the MIT license. using Garnet; +using Garnet.common; using Garnet.server; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Tsavorite.core; namespace Embedded.server; -public class GarnetEmbeddedApplication : GarnetApplication +internal sealed class GarnetEmbeddedApplication { - public GarnetEmbeddedApplication(IHost host) - : base(host) + public RegisterApi Register => app.Register; + + readonly StoreWrapper store; + readonly SubscribeBroker> subscriberBroker; + readonly GarnetApplication app; + + public GarnetEmbeddedApplication(GarnetApplication app) { + this.app = app; + this.store = app.Services.GetRequiredService(); + this.subscriberBroker = + app.Services.GetRequiredService>>(); } public static new GarnetEmbeddedApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) { - return new GarnetEmbeddedApplicationBuilder(new GarnetApplicationOptions { Args = args, }, options); + return new(new GarnetApplicationOptions + { + Args = args, + }, options); + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + await app.StopAsync(cancellationToken); + } + + /// + /// Dispose server + /// + public new void Dispose() => app.Dispose(); + + public StoreWrapper StoreWrapper => store; + + /// + /// Return a direct RESP session to this server + /// + /// A new RESP server session + internal RespServerSession GetRespSession() + { + return new RespServerSession(0, + new EmbeddedNetworkSender(), + store, + subscribeBroker: this.subscriberBroker, + null, + true); + } + + internal EmbeddedNetworkHandler GetNetworkHandler() + { + var server = app.Services + .GetServices() + .OfType() + .FirstOrDefault(); + + return server?.CreateNetworkHandler(); } } \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs index c8f7f7d70a..5706620d50 100644 --- a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs @@ -3,18 +3,28 @@ using Garnet; using Garnet.server; +using Microsoft.Extensions.DependencyInjection; + namespace Embedded.server; -public class GarnetEmbeddedApplicationBuilder : GarnetApplicationBuilder +internal class GarnetEmbeddedApplicationBuilder : GarnetApplicationBuilder { - public GarnetEmbeddedApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + internal GarnetEmbeddedApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) : base(options, garnetServerOptions) { } public new GarnetEmbeddedApplication Build() { - throw new NotImplementedException(); - } + var serviceDescriptor = base.Services + .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IGarnetServer)); + + base.Services.Remove(serviceDescriptor); + base.Services.AddSingleton(); + + var app = base.Build(); + + return new GarnetEmbeddedApplication(app); + } } \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs b/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs index a100249efe..8b0d2fe403 100644 --- a/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs +++ b/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs @@ -3,6 +3,7 @@ using BenchmarkDotNet.Attributes; using Embedded.server; +using Garnet; using Garnet.server; namespace BDN.benchmark.Lua @@ -11,7 +12,7 @@ namespace BDN.benchmark.Lua /// Benchmark for non-script running operations in LuaRunner /// [MemoryDiagnoser] - public unsafe class LuaRunnerOperations + public class LuaRunnerOperations { private const string SmallScript = "return nil"; @@ -147,7 +148,7 @@ public IEnumerable LuaParamsProvider() new(LuaMemoryManagementMode.Managed, true), ]; - private EmbeddedRespServer server; + private GarnetEmbeddedApplication server; private RespServerSession session; private LuaRunner paramsRunner; @@ -162,7 +163,14 @@ public void GlobalSetup() { opts = Params.CreateOptions(); - server = new EmbeddedRespServer(new GarnetServerOptions() { EnableLua = true, QuietMode = true, LuaOptions = opts }); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], new GarnetServerOptions + { + EnableLua = true, + QuietMode = true, + LuaOptions = opts + }); + + server = builder.Build(); session = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs b/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs index 430a92ca59..14272431e5 100644 --- a/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs +++ b/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs @@ -30,7 +30,7 @@ public IEnumerable LuaParamsProvider() new(LuaMemoryManagementMode.Managed, true), ]; - private EmbeddedRespServer server; + private GarnetEmbeddedApplication server; private StoreWrapper storeWrapper; private SessionScriptCache sessionScriptCache; private RespServerSession session; @@ -44,7 +44,11 @@ public void GlobalSetup() { var options = Params.CreateOptions(); - server = new EmbeddedRespServer(new GarnetServerOptions() { EnableLua = true, QuietMode = true, LuaOptions = options }); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], + new GarnetServerOptions() {EnableLua = true, QuietMode = true, LuaOptions = options}); + + server = builder.Build(); + storeWrapper = server.StoreWrapper; sessionScriptCache = new SessionScriptCache(storeWrapper, new GarnetNoAuthAuthenticator()); session = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Network/NetworkBase.cs b/benchmark/BDN.benchmark/Network/NetworkBase.cs index c76820a350..1f6294543f 100644 --- a/benchmark/BDN.benchmark/Network/NetworkBase.cs +++ b/benchmark/BDN.benchmark/Network/NetworkBase.cs @@ -32,7 +32,7 @@ public IEnumerable NetworkParamsProvider() /// in order to stress the network layer. /// const int batchSize = 1; - EmbeddedRespServer server; + GarnetEmbeddedApplication server; EmbeddedNetworkHandler networkHandler; /// @@ -47,7 +47,9 @@ public virtual void GlobalSetup() DisablePubSub = true, }; - server = new EmbeddedRespServer(opts, null, new GarnetServerEmbedded()); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + + server = builder.Build(); networkHandler = server.GetNetworkHandler(); // Send a PING message to warm up the session diff --git a/benchmark/BDN.benchmark/Operations/OperationsBase.cs b/benchmark/BDN.benchmark/Operations/OperationsBase.cs index 16be016871..73b42d980e 100644 --- a/benchmark/BDN.benchmark/Operations/OperationsBase.cs +++ b/benchmark/BDN.benchmark/Operations/OperationsBase.cs @@ -41,7 +41,7 @@ public IEnumerable OperationParamsProvider() /// 100 us = 1 Mops/sec /// internal const int batchSize = 100; - internal EmbeddedRespServer server; + internal GarnetEmbeddedApplication server; internal RespServerSession session; internal RespServerSession subscribeSession; @@ -79,7 +79,9 @@ public virtual void GlobalSetup() opts.AuthSettings = new AclAuthenticationPasswordSettings(aclFile); } - server = new EmbeddedRespServer(opts, null, new GarnetServerEmbedded()); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + + server = builder.Build(); session = server.GetRespSession(); } finally diff --git a/benchmark/BDN.benchmark/Operations/PubSubOperations.cs b/benchmark/BDN.benchmark/Operations/PubSubOperations.cs index a2414d8405..4b8d9f2e2c 100644 --- a/benchmark/BDN.benchmark/Operations/PubSubOperations.cs +++ b/benchmark/BDN.benchmark/Operations/PubSubOperations.cs @@ -27,7 +27,8 @@ public override void GlobalSetup() DisablePubSub = false, }; - server = new EmbeddedRespServer(opts, null, new GarnetServerEmbedded()); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + server = builder.Build(); session = server.GetRespSession(); subscribeSession = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Operations/ScriptOperations.cs b/benchmark/BDN.benchmark/Operations/ScriptOperations.cs index b8298912eb..d04c59eaa0 100644 --- a/benchmark/BDN.benchmark/Operations/ScriptOperations.cs +++ b/benchmark/BDN.benchmark/Operations/ScriptOperations.cs @@ -187,7 +187,7 @@ public static IEnumerable LuaParamsProvider() /// 100 us = 1 Mops/sec /// internal const int batchSize = 100; - internal EmbeddedRespServer server; + internal GarnetEmbeddedApplication server; internal RespServerSession session; /// @@ -203,7 +203,8 @@ public void GlobalSetup() LuaOptions = Params.CreateOptions(), }; - server = new EmbeddedRespServer(opts); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + server = builder.Build(); session = server.GetRespSession(); From 41522300ca64500c7fd9254499f1c12b535c29fa Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 05:31:46 +0100 Subject: [PATCH 37/42] fix formating --- .../BDN.benchmark/Cluster/ClusterContext.cs | 2 +- .../Embedded/GarnetEmbeddedApplication.cs | 10 +- .../Embedded/GarnetServerEmbedded.cs | 125 +++++++++--------- .../BDN.benchmark/Lua/LuaRunnerOperations.cs | 8 +- .../Lua/LuaScriptCacheOperations.cs | 6 +- .../BDN.benchmark/Network/NetworkBase.cs | 2 +- .../Operations/OperationsBase.cs | 2 +- 7 files changed, 78 insertions(+), 77 deletions(-) diff --git a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs index b5ba60e991..e7f0e590ca 100644 --- a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs +++ b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs @@ -44,7 +44,7 @@ public void SetupSingleInstance(bool disableSlotVerification = false) var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opt); server = builder.Build(); - + session = server.GetRespSession(); _ = server.Register.NewTransactionProc(CustomTxnSet.CommandName, () => new CustomTxnSet(), new RespCommandsInfo { Arity = CustomTxnSet.Arity }); diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs index 1b99ea47bb..941822b678 100644 --- a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs @@ -13,11 +13,11 @@ namespace Embedded.server; internal sealed class GarnetEmbeddedApplication { public RegisterApi Register => app.Register; - + readonly StoreWrapper store; readonly SubscribeBroker> subscriberBroker; readonly GarnetApplication app; - + public GarnetEmbeddedApplication(GarnetApplication app) { this.app = app; @@ -26,7 +26,7 @@ public GarnetEmbeddedApplication(GarnetApplication app) app.Services.GetRequiredService>>(); } - public static new GarnetEmbeddedApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) + public static GarnetEmbeddedApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) { return new(new GarnetApplicationOptions { @@ -42,7 +42,7 @@ public async Task StopAsync(CancellationToken cancellationToken = default) /// /// Dispose server /// - public new void Dispose() => app.Dispose(); + public void Dispose() => app.Dispose(); public StoreWrapper StoreWrapper => store; @@ -67,6 +67,8 @@ internal EmbeddedNetworkHandler GetNetworkHandler() .OfType() .FirstOrDefault(); + Console.WriteLine(server); + return server?.CreateNetworkHandler(); } } \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs b/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs index 63fe7d90ec..99687f0109 100644 --- a/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs +++ b/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs @@ -9,93 +9,92 @@ using Garnet.server; using Microsoft.Extensions.Logging; -namespace Embedded.server +namespace Embedded.server; + +internal class GarnetServerEmbedded : GarnetServerBase, IServerHook { - internal class GarnetServerEmbedded : GarnetServerBase, IServerHook + public GarnetServerEmbedded() : base("0.0.0.0", 0, 1 << 10) { - public GarnetServerEmbedded() : base("0.0.0.0", 0, 1 << 10) - { - } + } - public EmbeddedNetworkHandler CreateNetworkHandler(SslClientAuthenticationOptions tlsOptions = null, string remoteEndpointName = null) - { - var networkSender = new EmbeddedNetworkSender(); - var networkSettings = new NetworkBufferSettings(); - var networkPool = networkSettings.CreateBufferPool(); - EmbeddedNetworkHandler handler = null; + public EmbeddedNetworkHandler CreateNetworkHandler(SslClientAuthenticationOptions tlsOptions = null, string remoteEndpointName = null) + { + var networkSender = new EmbeddedNetworkSender(); + var networkSettings = new NetworkBufferSettings(); + var networkPool = networkSettings.CreateBufferPool(); + EmbeddedNetworkHandler handler = null; - if (activeHandlerCount >= 0) + if (activeHandlerCount >= 0) + { + var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); + if (currentActiveHandlerCount > 0) { - var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); - if (currentActiveHandlerCount > 0) + try { - try - { - handler = new EmbeddedNetworkHandler(this, networkSender, networkSettings, networkPool, tlsOptions != null); - if (!activeHandlers.TryAdd(handler, default)) - throw new Exception("Unable to add handler to dictionary"); + handler = new EmbeddedNetworkHandler(this, networkSender, networkSettings, networkPool, tlsOptions != null); + if (!activeHandlers.TryAdd(handler, default)) + throw new Exception("Unable to add handler to dictionary"); - handler.Start(tlsOptions, remoteEndpointName); - incr_conn_recv(); - return handler; - } - catch (Exception ex) - { - logger?.LogError(ex, "Error starting network handler"); - Interlocked.Decrement(ref activeHandlerCount); - handler?.Dispose(); - } + handler.Start(tlsOptions, remoteEndpointName); + incr_conn_recv(); + return handler; } - else + catch (Exception ex) { + logger?.LogError(ex, "Error starting network handler"); Interlocked.Decrement(ref activeHandlerCount); + handler?.Dispose(); } } - return handler; - } - - public void DisposeMessageConsumer(INetworkHandler session) - { - if (activeHandlers.TryRemove(session, out _)) + else { Interlocked.Decrement(ref activeHandlerCount); - incr_conn_disp(); - try - { - session.Session?.Dispose(); - } - catch (Exception ex) - { - logger?.LogError(ex, "Error disposing RespServerSession"); - } } } + return handler; + } - public override void Start() + public void DisposeMessageConsumer(INetworkHandler session) + { + if (activeHandlers.TryRemove(session, out _)) { + Interlocked.Decrement(ref activeHandlerCount); + incr_conn_disp(); + try + { + session.Session?.Dispose(); + } + catch (Exception ex) + { + logger?.LogError(ex, "Error disposing RespServerSession"); + } } + } - public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) - { - session = null; - - // We need at least 4 bytes to determine session - if (bytes.Length < 4) - return false; + public override void Start() + { + } - WireFormat protocol = WireFormat.ASCII; + public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) + { + session = null; - if (!GetSessionProviders().TryGetValue(protocol, out var provider)) - { - var input = System.Text.Encoding.ASCII.GetString(bytes); - logger?.LogError("Cannot identify wire protocol {bytes}", input); - throw new Exception($"Unsupported incoming wire format {protocol} {input}"); - } + // We need at least 4 bytes to determine session + if (bytes.Length < 4) + return false; - if (!AddSession(protocol, ref provider, networkSender, out session)) - throw new Exception($"Unable to add session"); + WireFormat protocol = WireFormat.ASCII; - return true; + if (!GetSessionProviders().TryGetValue(protocol, out var provider)) + { + var input = System.Text.Encoding.ASCII.GetString(bytes); + logger?.LogError("Cannot identify wire protocol {bytes}", input); + throw new Exception($"Unsupported incoming wire format {protocol} {input}"); } + + if (!AddSession(protocol, ref provider, networkSender, out session)) + throw new Exception($"Unable to add session"); + + return true; } } \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs b/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs index 8b0d2fe403..e4431fe236 100644 --- a/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs +++ b/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs @@ -165,11 +165,11 @@ public void GlobalSetup() var builder = GarnetEmbeddedApplication.CreateHostBuilder([], new GarnetServerOptions { - EnableLua = true, - QuietMode = true, - LuaOptions = opts + EnableLua = true, + QuietMode = true, + LuaOptions = opts }); - + server = builder.Build(); session = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs b/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs index 14272431e5..efda07487a 100644 --- a/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs +++ b/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs @@ -45,10 +45,10 @@ public void GlobalSetup() var options = Params.CreateOptions(); var builder = GarnetEmbeddedApplication.CreateHostBuilder([], - new GarnetServerOptions() {EnableLua = true, QuietMode = true, LuaOptions = options}); - + new GarnetServerOptions() { EnableLua = true, QuietMode = true, LuaOptions = options }); + server = builder.Build(); - + storeWrapper = server.StoreWrapper; sessionScriptCache = new SessionScriptCache(storeWrapper, new GarnetNoAuthAuthenticator()); session = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Network/NetworkBase.cs b/benchmark/BDN.benchmark/Network/NetworkBase.cs index 1f6294543f..d922555d82 100644 --- a/benchmark/BDN.benchmark/Network/NetworkBase.cs +++ b/benchmark/BDN.benchmark/Network/NetworkBase.cs @@ -48,7 +48,7 @@ public virtual void GlobalSetup() }; var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); - + server = builder.Build(); networkHandler = server.GetNetworkHandler(); diff --git a/benchmark/BDN.benchmark/Operations/OperationsBase.cs b/benchmark/BDN.benchmark/Operations/OperationsBase.cs index 73b42d980e..4f79511e75 100644 --- a/benchmark/BDN.benchmark/Operations/OperationsBase.cs +++ b/benchmark/BDN.benchmark/Operations/OperationsBase.cs @@ -80,7 +80,7 @@ public virtual void GlobalSetup() } var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); - + server = builder.Build(); session = server.GetRespSession(); } From 1cc015394b2c38d7a66e5adb981bcb4d021b1d80 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 05:43:30 +0100 Subject: [PATCH 38/42] fix linking --- benchmark/BDN.benchmark/BDN.benchmark.csproj | 4 + .../Embedded/GarnetEmbeddedApplication.cs | 5 +- .../GarnetEmbeddedApplicationBuilder.cs | 18 ++++- libs/server/StoreWrapper.cs | 80 ------------------- .../Embedded.perftest.csproj | 3 +- 5 files changed, 24 insertions(+), 86 deletions(-) diff --git a/benchmark/BDN.benchmark/BDN.benchmark.csproj b/benchmark/BDN.benchmark/BDN.benchmark.csproj index 71c1961eee..99fc55eafe 100644 --- a/benchmark/BDN.benchmark/BDN.benchmark.csproj +++ b/benchmark/BDN.benchmark/BDN.benchmark.csproj @@ -29,4 +29,8 @@ + + + + diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs index 941822b678..dbecf59b5a 100644 --- a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs @@ -1,11 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Garnet; using Garnet.common; using Garnet.server; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Tsavorite.core; namespace Embedded.server; diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs index 5706620d50..527809b17a 100644 --- a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Linq; using Garnet; using Garnet.server; using Microsoft.Extensions.DependencyInjection; @@ -16,12 +17,21 @@ internal GarnetEmbeddedApplicationBuilder(GarnetApplicationOptions options, Garn public new GarnetEmbeddedApplication Build() { - var serviceDescriptor = base.Services - .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IGarnetServer)); + { + var serviceDescriptor = base.Services + .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(StoreWrapper)); - base.Services.Remove(serviceDescriptor); + base.Services.Remove(serviceDescriptor); + } - base.Services.AddSingleton(); + { + var serviceDescriptor = base.Services + .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IGarnetServer)); + + base.Services.Remove(serviceDescriptor); + + base.Services.AddSingleton(); + } var app = base.Build(); diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index d5ff17d8c2..2af62e8f71 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -13,7 +13,6 @@ using Garnet.server.ACL; using Garnet.server.Auth.Settings; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Tsavorite.core; namespace Garnet.server @@ -112,85 +111,6 @@ public sealed class StoreWrapper : IDisposable /// public readonly int databaseNum = 1; - /// - /// Constructor - /// - public StoreWrapper( - string version, - string redisProtocolVersion, - IGarnetServer server, - TsavoriteKV store, - TsavoriteKV objectStore, - CacheSizeTracker objectStoreSizeTracker, - CustomCommandManager customCommandManager, - TsavoriteLog appendOnlyFile, - IOptions options, - AccessControlList accessControlList = null, - IClusterFactory clusterFactory = null, - ILoggerFactory loggerFactory = null - ) - { - this.version = version; - this.redisProtocolVersion = redisProtocolVersion; - this.server = server; - this.startupTime = DateTimeOffset.UtcNow.Ticks; - this.store = store; - this.objectStore = objectStore; - this.appendOnlyFile = appendOnlyFile; - this.serverOptions = options.Value; - lastSaveTime = DateTimeOffset.FromUnixTimeSeconds(0); - this.customCommandManager = customCommandManager; - this.monitor = serverOptions.MetricsSamplingFrequency > 0 ? new GarnetServerMonitor(this, serverOptions, server, loggerFactory?.CreateLogger("GarnetServerMonitor")) : null; - this.objectStoreSizeTracker = objectStoreSizeTracker; - this.loggerFactory = loggerFactory; - this.logger = loggerFactory?.CreateLogger("StoreWrapper"); - this.sessionLogger = loggerFactory?.CreateLogger("Session"); - // TODO Change map size to a reasonable number - this.versionMap = new WatchVersionMap(1 << 16); - this.accessControlList = accessControlList; - this.GarnetObjectSerializer = new GarnetObjectSerializer(this.customCommandManager); - this.loggingFrequncy = TimeSpan.FromSeconds(serverOptions.LoggingFrequency); - - if (!serverOptions.DisableObjects) - this.itemBroker = new CollectionItemBroker(); - - // Initialize store scripting cache - if (serverOptions.EnableLua) - this.storeScriptCache = []; - - if (accessControlList == null) - { - // If ACL authentication is enabled, initiate access control list - // NOTE: This is a temporary workflow. ACL should always be initiated and authenticator - // should become a parameter of AccessControlList. - if ((this.serverOptions.AuthSettings != null) && (this.serverOptions.AuthSettings.GetType().BaseType == typeof(AclAuthenticationSettings))) - { - // Create a new access control list and register it with the authentication settings - AclAuthenticationSettings aclAuthenticationSettings = (AclAuthenticationSettings)this.serverOptions.AuthSettings; - - if (!string.IsNullOrEmpty(aclAuthenticationSettings.AclConfigurationFile)) - { - logger?.LogInformation("Reading ACL configuration file '{filepath}'", aclAuthenticationSettings.AclConfigurationFile); - this.accessControlList = new AccessControlList(aclAuthenticationSettings.DefaultPassword, aclAuthenticationSettings.AclConfigurationFile); - } - else - { - // If no configuration file is specified, initiate ACL with default settings - this.accessControlList = new AccessControlList(aclAuthenticationSettings.DefaultPassword); - } - } - else - { - this.accessControlList = new AccessControlList(); - } - } - - if (clusterFactory != null) - clusterProvider = clusterFactory.CreateClusterProvider(this); - ctsCommit = new(); - run_id = Generator.CreateHexId(); - } - /// /// Constructor /// diff --git a/playground/Embedded.perftest/Embedded.perftest.csproj b/playground/Embedded.perftest/Embedded.perftest.csproj index 9ac00ea182..9d2418946b 100644 --- a/playground/Embedded.perftest/Embedded.perftest.csproj +++ b/playground/Embedded.perftest/Embedded.perftest.csproj @@ -12,7 +12,8 @@ - + + From b5eb325fab619b8d0badad584b882744ffe9acb9 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 06:22:34 +0100 Subject: [PATCH 39/42] refactor --- libs/host/GarnetApplicationBuilder.cs | 3 +-- test/Garnet.test/RespInfoTests.cs | 2 +- test/Garnet.test/RespMetricsTest.cs | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 2c8e62be2b..36ba42fb47 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -51,6 +51,7 @@ public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOp hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); hostApplicationBuilder.Services.AddSingleton(); @@ -123,8 +124,6 @@ public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOp return storeWrapperFactory.Create(version); }); - hostApplicationBuilder.Services.AddSingleton(); - hostApplicationBuilder.Services.AddSingleton(sp => { var garnetProviderFactory = sp.GetRequiredService(); diff --git a/test/Garnet.test/RespInfoTests.cs b/test/Garnet.test/RespInfoTests.cs index 54a18cc3f1..afb144a40a 100644 --- a/test/Garnet.test/RespInfoTests.cs +++ b/test/Garnet.test/RespInfoTests.cs @@ -54,7 +54,7 @@ public void ResetStatsTest() infoResult = db.Execute("INFO").ToString(); infoResultArr = infoResult.Split("\r\n"); totalFound = infoResultArr.First(x => x.StartsWith("total_found")); - ClassicAssert.AreEqual("total_found:1", totalFound, "Expected total_foudn to be incremented to 1 after a successful request."); + ClassicAssert.AreEqual("total_found:1", totalFound, "Expected total_found to be incremented to 1 after a successful request."); var result = db.Execute("INFO", "RESET"); ClassicAssert.IsNotNull(result); diff --git a/test/Garnet.test/RespMetricsTest.cs b/test/Garnet.test/RespMetricsTest.cs index 884af257a9..be1d4d22cd 100644 --- a/test/Garnet.test/RespMetricsTest.cs +++ b/test/Garnet.test/RespMetricsTest.cs @@ -46,9 +46,9 @@ public async Task TearDown() } [Test] - public void MetricsDisabledTest() + public async Task MetricsDisabledTest() { - StartServer(); + await StartServer(); var logger = loggerFactory.CreateLogger(TestContext.CurrentContext.Test.Name); var infoMetrics = server.Metrics.GetInfoMetrics().ToArray(); From c496dd0321f162768bdc3a64389bc110a57e44aa Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Fri, 24 Jan 2025 08:51:17 +0100 Subject: [PATCH 40/42] refactor --- libs/host/GarnetApplicationBuilder.cs | 2 +- libs/host/GarnetServerHostedService.cs | 7 ++++--- test/Garnet.test.cluster/ClusterTestContext.cs | 1 - test/Garnet.test/RespMetricsTest.cs | 4 ++-- test/Garnet.test/TransactionTests.cs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index 36ba42fb47..cedc565e5d 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -104,7 +104,7 @@ public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOp return storeFactory.CreateObjectStore(); }); - hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddSingleton(sp => { diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index 14774511f0..9b919c32dd 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -125,8 +125,11 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) await Task.CompletedTask; } - public override async Task StopAsync(CancellationToken cancellationToken) + public override void Dispose() { + base.Dispose(); + server?.Dispose(); + if (cleanupDir) { if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) @@ -136,8 +139,6 @@ public override async Task StopAsync(CancellationToken cancellationToken) ckptdir.Delete(new FileDescriptor { directoryName = "" }); } } - - await base.StopAsync(cancellationToken); } static readonly string version = GetVersion(); diff --git a/test/Garnet.test.cluster/ClusterTestContext.cs b/test/Garnet.test.cluster/ClusterTestContext.cs index 224ee7af4e..b3e58cccea 100644 --- a/test/Garnet.test.cluster/ClusterTestContext.cs +++ b/test/Garnet.test.cluster/ClusterTestContext.cs @@ -273,7 +273,6 @@ public async Task DisposeCluster() { logger.LogDebug("\t a. Dispose node {testName}", TestContext.CurrentContext.Test.Name); await nodes[i].StopAsync(); - nodes[i].Dispose(); nodes[i] = null; logger.LogDebug("\t b. Dispose node {testName}", TestContext.CurrentContext.Test.Name); } diff --git a/test/Garnet.test/RespMetricsTest.cs b/test/Garnet.test/RespMetricsTest.cs index be1d4d22cd..ed92653b25 100644 --- a/test/Garnet.test/RespMetricsTest.cs +++ b/test/Garnet.test/RespMetricsTest.cs @@ -75,9 +75,9 @@ public async Task MetricsDisabledTest() } [Test] - public void MetricsEnabledTest() + public async Task MetricsEnabledTest() { - StartServer(1, true); + await StartServer(1, true); var logger = loggerFactory.CreateLogger(TestContext.CurrentContext.Test.Name); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/TransactionTests.cs b/test/Garnet.test/TransactionTests.cs index a8d8c0c386..1083b6fcbb 100644 --- a/test/Garnet.test/TransactionTests.cs +++ b/test/Garnet.test/TransactionTests.cs @@ -323,7 +323,7 @@ public async Task WatchNonExistentKey() [Test] public async Task WatchKeyFromDisk() { - SetUpWithLowMemory(); + await SetUpWithLowMemory(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { var db = redis.GetDatabase(0); From c79d8942330b320b397400c028012e8938722256 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Sat, 25 Jan 2025 01:31:14 +0100 Subject: [PATCH 41/42] remove server dispose --- libs/host/GarnetServerHostedService.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index 9b919c32dd..6bdca86ac3 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -125,10 +125,9 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) await Task.CompletedTask; } - public override void Dispose() + public override async Task StopAsync(CancellationToken cancellationToken) { - base.Dispose(); - server?.Dispose(); + await base.StopAsync(cancellationToken); if (cleanupDir) { From c5525df6601371d722a66406b3fe287970d70d75 Mon Sep 17 00:00:00 2001 From: Tomas Pelak Date: Sat, 25 Jan 2025 14:10:55 +0100 Subject: [PATCH 42/42] also dispose server after stopping it --- .../BDN.benchmark/Cluster/ClusterContext.cs | 1 + libs/host/GarnetApplicationBuilder.cs | 2 + libs/host/GarnetServer.cs | 203 ++++++++++++++++++ libs/host/GarnetServerHostedService.cs | 154 +------------ .../ClusterAuthCommsTests.cs | 1 + .../Garnet.test.cluster/ClusterConfigTests.cs | 1 + .../ClusterReplicationTests.cs | 10 +- .../Garnet.test.cluster/ClusterTestContext.cs | 1 + test/Garnet.test/CacheSizeTrackerTests.cs | 2 + test/Garnet.test/GarnetBitmapTests.cs | 6 + test/Garnet.test/GarnetClientTests.cs | 9 + .../GarnetJSON/JsonCommandsTest.cs | 4 + test/Garnet.test/HyperLogLogTests.cs | 5 + test/Garnet.test/IndexGrowthTests.cs | 3 + test/Garnet.test/LuaScriptTests.cs | 1 + test/Garnet.test/ObjectTestsForOutput.cs | 1 + test/Garnet.test/ReadCacheTests.cs | 1 + test/Garnet.test/Resp/ACL/AclTest.cs | 1 + test/Garnet.test/Resp/ACL/RespCommandTests.cs | 1 + .../Resp/GarnetAuthenticatorTests.cs | 1 + test/Garnet.test/RespAdminCommandsTests.cs | 12 ++ test/Garnet.test/RespAofAzureTests.cs | 13 ++ test/Garnet.test/RespAofTests.cs | 24 +++ .../RespBlockingCollectionTests.cs | 1 + test/Garnet.test/RespCommandTests.cs | 1 + test/Garnet.test/RespCustomCommandTests.cs | 1 + test/Garnet.test/RespEtagTests.cs | 1 + test/Garnet.test/RespGetLowMemoryTests.cs | 1 + test/Garnet.test/RespHashTests.cs | 1 + test/Garnet.test/RespInfoTests.cs | 1 + test/Garnet.test/RespListGarnetClientTests.cs | 1 + test/Garnet.test/RespListTests.cs | 1 + test/Garnet.test/RespLowMemoryTests.cs | 1 + test/Garnet.test/RespMetricsTest.cs | 1 + test/Garnet.test/RespModuleTests.cs | 2 + test/Garnet.test/RespPubSubTests.cs | 1 + test/Garnet.test/RespScanCommandsTests.cs | 1 + test/Garnet.test/RespSetTest.cs | 1 + .../RespSortedSetGarnetClientTests.cs | 1 + test/Garnet.test/RespSortedSetGeoTests.cs | 1 + test/Garnet.test/RespSortedSetTests.cs | 1 + test/Garnet.test/RespTests.cs | 1 + test/Garnet.test/RespTlsTests.cs | 1 + test/Garnet.test/RespTransactionProcTests.cs | 1 + test/Garnet.test/TransactionTests.cs | 1 + 45 files changed, 328 insertions(+), 152 deletions(-) create mode 100644 libs/host/GarnetServer.cs diff --git a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs index e7f0e590ca..1a23233f4a 100644 --- a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs +++ b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs @@ -27,6 +27,7 @@ public async Task Dispose() session.Dispose(); await server.StopAsync(); server.Dispose(); + server.Dispose(); } public void SetupSingleInstance(bool disableSlotVerification = false) diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs index cedc565e5d..cf5a54ed83 100644 --- a/libs/host/GarnetApplicationBuilder.cs +++ b/libs/host/GarnetApplicationBuilder.cs @@ -135,6 +135,8 @@ public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOp hostApplicationBuilder.Services.AddSingleton(); hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddHostedService(); } diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs new file mode 100644 index 0000000000..4fa56e86f7 --- /dev/null +++ b/libs/host/GarnetServer.cs @@ -0,0 +1,203 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Threading; +using Garnet.networking; +using Garnet.server; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +/// +/// Implementation Garnet server +/// +internal class GarnetServer : IDisposable +{ + static readonly string version = GetVersion(); + + static string GetVersion() + { + var Version = Assembly.GetExecutingAssembly().GetName().Version; + return $"{Version.Major}.{Version.Minor}.{Version.Build}"; + } + + private readonly GarnetProvider provider; + private readonly GarnetServerOptions opts; + private readonly IGarnetServer server; + private readonly ILogger logger; + private readonly ILoggerFactory loggerFactory; + private readonly bool cleanupDir; + + /// + /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. + /// + /// Server options + /// Logger + /// Logger factory + /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. + /// + public GarnetServer( + IOptions options, + ILogger logger, + ILoggerFactory loggerFactory, + IGarnetServer server, + GarnetProvider garnetProvider) + { + this.server = server; + this.opts = options.Value; + this.logger = logger; + this.loggerFactory = loggerFactory; + this.provider = garnetProvider; + + this.cleanupDir = false; + this.InitializeServerUpdated(); + } + + private void InitializeServerUpdated() + { + Debug.Assert(opts != null); + + if (!opts.QuietMode) + { + var red = "\u001b[31m"; + var magenta = "\u001b[35m"; + var normal = "\u001b[0m"; + + Console.WriteLine($@"{red} _________ + /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} + '. \ / .' {normal}Port: {opts.Port}{red} + '.\ /.' {magenta}https://aka.ms/GetGarnet{red} + '.' + {normal}"); + } + + logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, + IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); + + // Flush initialization logs from memory logger + FlushMemoryLogger(null, "ArgParser", this.loggerFactory); + + ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); + ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); + + bool minChanged = false, maxChanged = false; + if (opts.ThreadPoolMinThreads > 0) + { + minThreads = opts.ThreadPoolMinThreads; + minChanged = true; + } + + if (opts.ThreadPoolMinIOCompletionThreads > 0) + { + minCPThreads = opts.ThreadPoolMinIOCompletionThreads; + minChanged = true; + } + + if (opts.ThreadPoolMaxThreads > 0) + { + maxThreads = opts.ThreadPoolMaxThreads; + maxChanged = true; + } + + if (opts.ThreadPoolMaxIOCompletionThreads > 0) + { + maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; + maxChanged = true; + } + + // First try to set the max threads + var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); + + // Set the min threads + if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); + + // Retry to set max threads if it wasn't set in the earlier step + if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); + + logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); + + server.Register(WireFormat.ASCII, provider); + } + + /// + /// Start server instance + /// + public void Start() + { + provider.Recover(); + server.Start(); + provider.Start(); + if (!opts.QuietMode) + Console.WriteLine("* Ready to accept connections"); + } + + /// + /// Dispose store (including log and checkpoint directory) + /// + public void Dispose() + { + server?.Dispose(); + Dispose(cleanupDir); + } + + /// + /// Dispose, optionally deleting logs and checkpoints + /// + /// Whether to delete logs and checkpoints + public void Dispose(bool deleteDir = true) + { + if (deleteDir) + { + if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) + { + var ckptdir = opts.DeviceFactoryCreator(); + ckptdir.Initialize(opts.CheckpointDir); + ckptdir.Delete(new FileDescriptor { directoryName = "" }); + } + } + } + + /// + /// Flushes MemoryLogger entries into a destination logger. + /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. + /// + /// The memory logger + /// The category name of the destination logger + /// Optional logger factory for creating the destination logger + private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, + ILoggerFactory dstLoggerFactory = null) + { + if (memoryLogger == null) return; + + // If no logger factory supplied, create a default console logger + var disposeDstLoggerFactory = false; + if (dstLoggerFactory == null) + { + dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => + { + options.SingleLine = true; + options.TimestampFormat = "hh::mm::ss "; + }).SetMinimumLevel(LogLevel.Information)); + disposeDstLoggerFactory = true; + } + + // Create the destination logger + var dstLogger = dstLoggerFactory.CreateLogger(categoryName); + + // Flush all entries from the memory logger into the destination logger + memoryLogger.FlushLogger(dstLogger); + + // If a default console logger factory was created, it is no longer needed + if (disposeDstLoggerFactory) + { + dstLoggerFactory.Dispose(); + } + } +} \ No newline at end of file diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs index 6bdca86ac3..e068b071fd 100644 --- a/libs/host/GarnetServerHostedService.cs +++ b/libs/host/GarnetServerHostedService.cs @@ -17,171 +17,23 @@ namespace Garnet; internal class GarnetServerHostedService : BackgroundService { - private readonly GarnetProvider provider; - private readonly GarnetServerOptions opts; - private readonly IGarnetServer server; private readonly ILogger logger; - private readonly ILoggerFactory loggerFactory; - private readonly bool cleanupDir; + private readonly GarnetServer server; public GarnetServerHostedService( - IOptions options, ILogger logger, - ILoggerFactory loggerFactory, - IGarnetServer server, - GarnetProvider garnetProvider) + GarnetServer server) { - this.server = server; - this.opts = options.Value; this.logger = logger; - this.loggerFactory = loggerFactory; - this.provider = garnetProvider; - - this.cleanupDir = false; - this.InitializeServerUpdated(); - } - - private void InitializeServerUpdated() - { - Debug.Assert(opts != null); - - if (!opts.QuietMode) - { - var red = "\u001b[31m"; - var magenta = "\u001b[35m"; - var normal = "\u001b[0m"; - - Console.WriteLine($@"{red} _________ - /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} - '. \ / .' {normal}Port: {opts.Port}{red} - '.\ /.' {magenta}https://aka.ms/GetGarnet{red} - '.' - {normal}"); - } - - logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, - IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); - - // Flush initialization logs from memory logger - FlushMemoryLogger(null, "ArgParser", this.loggerFactory); - - ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); - ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); - - bool minChanged = false, maxChanged = false; - if (opts.ThreadPoolMinThreads > 0) - { - minThreads = opts.ThreadPoolMinThreads; - minChanged = true; - } - - if (opts.ThreadPoolMinIOCompletionThreads > 0) - { - minCPThreads = opts.ThreadPoolMinIOCompletionThreads; - minChanged = true; - } - - if (opts.ThreadPoolMaxThreads > 0) - { - maxThreads = opts.ThreadPoolMaxThreads; - maxChanged = true; - } - - if (opts.ThreadPoolMaxIOCompletionThreads > 0) - { - maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; - maxChanged = true; - } - - // First try to set the max threads - var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); - - // Set the min threads - if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); - - // Retry to set max threads if it wasn't set in the earlier step - if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - - logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - - server.Register(WireFormat.ASCII, provider); + this.server = server; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - provider.Recover(); server.Start(); - provider.Start(); - - if (!opts.QuietMode) - { - logger.LogInformation("* Ready to accept connections"); - } logger.LogInformation("Garnet server running at: {time}", DateTimeOffset.Now); await Task.CompletedTask; } - - public override async Task StopAsync(CancellationToken cancellationToken) - { - await base.StopAsync(cancellationToken); - - if (cleanupDir) - { - if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) - { - var ckptdir = opts.DeviceFactoryCreator(); - ckptdir.Initialize(opts.CheckpointDir); - ckptdir.Delete(new FileDescriptor { directoryName = "" }); - } - } - } - - static readonly string version = GetVersion(); - - static string GetVersion() - { - var Version = Assembly.GetExecutingAssembly().GetName().Version; - return $"{Version.Major}.{Version.Minor}.{Version.Build}"; - } - - /// - /// Flushes MemoryLogger entries into a destination logger. - /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. - /// - /// The memory logger - /// The category name of the destination logger - /// Optional logger factory for creating the destination logger - private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, - ILoggerFactory dstLoggerFactory = null) - { - if (memoryLogger == null) return; - - // If no logger factory supplied, create a default console logger - var disposeDstLoggerFactory = false; - if (dstLoggerFactory == null) - { - dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => - { - options.SingleLine = true; - options.TimestampFormat = "hh::mm::ss "; - }).SetMinimumLevel(LogLevel.Information)); - disposeDstLoggerFactory = true; - } - - // Create the destination logger - var dstLogger = dstLoggerFactory.CreateLogger(categoryName); - - // Flush all entries from the memory logger into the destination logger - memoryLogger.FlushLogger(dstLogger); - - // If a default console logger factory was created, it is no longer needed - if (disposeDstLoggerFactory) - { - dstLoggerFactory.Dispose(); - } - } } \ No newline at end of file diff --git a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs index 783cdcc4bf..445181e0c0 100644 --- a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs +++ b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs @@ -216,6 +216,7 @@ public async Task ClusterSimpleACLReload() // Restart node with new ACL file await context.nodes[0].StopAsync(); + context.nodes[0].Dispose(); ; context.nodes[0] = context.CreateInstance(context.clusterTestUtils.GetEndPoint(0).Port, useAcl: true, cleanClusterConfig: false); await context.nodes[0].RunAsync(); diff --git a/test/Garnet.test.cluster/ClusterConfigTests.cs b/test/Garnet.test.cluster/ClusterConfigTests.cs index 18255b561e..220ea52c84 100644 --- a/test/Garnet.test.cluster/ClusterConfigTests.cs +++ b/test/Garnet.test.cluster/ClusterConfigTests.cs @@ -73,6 +73,7 @@ public async Task ClusterForgetAfterNodeRestartTest() // Restart node with new ACL file await context.nodes[0].StopAsync(); + context.nodes[0].Dispose(); ; context.nodes[0] = context.CreateInstance(context.clusterTestUtils.GetEndPoint(0).Port, useAcl: true, cleanClusterConfig: false); await context.nodes[0].RunAsync(); context.CreateConnection(); diff --git a/test/Garnet.test.cluster/ClusterReplicationTests.cs b/test/Garnet.test.cluster/ClusterReplicationTests.cs index f5516e2f99..52d986dcde 100644 --- a/test/Garnet.test.cluster/ClusterReplicationTests.cs +++ b/test/Garnet.test.cluster/ClusterReplicationTests.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Azure.Core; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -180,6 +181,7 @@ public async Task ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW // Shutdown secondary await context.nodes[1].StopAsync(); + context.nodes[1].Dispose(); Thread.Sleep(TimeSpan.FromSeconds(2)); @@ -254,6 +256,7 @@ public async Task ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] // Shutdown secondary await context.nodes[1].StopAsync(); + context.nodes[1].Dispose(); ; Thread.Sleep(TimeSpan.FromSeconds(2)); // New insert @@ -336,6 +339,7 @@ async Task ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjec context.logger?.LogTrace("Test disposing node 1"); await context.nodes[1].StopAsync(); + context.nodes[1].Dispose(); ; Thread.Sleep(TimeSpan.FromSeconds(1)); // Populate Primary @@ -693,7 +697,8 @@ public async Task ClusterFailoverAttachReplicas([Values] bool performRMW, [Value context.ValidateKVCollectionAgainstReplica(ref context.kvPairs, 1); // Simulate primary crash - context.nodes[0].StopAsync(); + await context.nodes[0].StopAsync(); + context.nodes[0].Dispose(); context.nodes[0] = null; // Takeover as new primary @@ -980,6 +985,7 @@ async Task ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bo // Dispose primary await context.nodes[oldPrimaryIndex].StopAsync(); + context.nodes[oldPrimaryIndex].Dispose(); ; context.nodes[oldPrimaryIndex] = null; // Re-assign slots to replica manually since failover option was not @@ -1106,8 +1112,10 @@ public async Task ClusterReplicationCheckpointAlignmentTest([Values] bool perfor // Dispose primary and delete data await context.nodes[primaryNodeIndex].StopAsync(); + context.nodes[primaryNodeIndex].Dispose(); // Dispose primary but do not delete data await context.nodes[replicaNodeIndex].StopAsync(); + context.nodes[replicaNodeIndex].Dispose(); // Restart primary and do not recover context.nodes[primaryNodeIndex] = context.CreateInstance( diff --git a/test/Garnet.test.cluster/ClusterTestContext.cs b/test/Garnet.test.cluster/ClusterTestContext.cs index b3e58cccea..224ee7af4e 100644 --- a/test/Garnet.test.cluster/ClusterTestContext.cs +++ b/test/Garnet.test.cluster/ClusterTestContext.cs @@ -273,6 +273,7 @@ public async Task DisposeCluster() { logger.LogDebug("\t a. Dispose node {testName}", TestContext.CurrentContext.Test.Name); await nodes[i].StopAsync(); + nodes[i].Dispose(); nodes[i] = null; logger.LogDebug("\t b. Dispose node {testName}", TestContext.CurrentContext.Test.Name); } diff --git a/test/Garnet.test/CacheSizeTrackerTests.cs b/test/Garnet.test/CacheSizeTrackerTests.cs index c88f2f964d..91e14ff7e3 100644 --- a/test/Garnet.test/CacheSizeTrackerTests.cs +++ b/test/Garnet.test/CacheSizeTrackerTests.cs @@ -38,6 +38,7 @@ public async Task TearDown() if (server != null) { await server.StopAsync(); + server.Dispose(); } TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -97,6 +98,7 @@ public void IncreaseEmptyPageCountTest() public async Task ReadCacheIncreaseEmptyPageCountTest() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "1k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreReadCacheHeapMemorySize: "1k", enableObjectStoreReadCache: true); await server.RunAsync(); objStore = server.Provider.StoreWrapper.objectStore; diff --git a/test/Garnet.test/GarnetBitmapTests.cs b/test/Garnet.test/GarnetBitmapTests.cs index 4fdaa42447..c4d812f342 100644 --- a/test/Garnet.test/GarnetBitmapTests.cs +++ b/test/Garnet.test/GarnetBitmapTests.cs @@ -30,6 +30,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -443,6 +444,7 @@ public async Task BitmapBitCountTest_LTM() { int bitmapBytes = 512; await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), @@ -640,6 +642,7 @@ public async Task BitmapBitPosTest_LTM() { int bitmapBytes = 512; await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), @@ -1285,6 +1288,7 @@ public async Task BitmapBitfieldGetTest_LTM([Values(RespCommand.BITFIELD, RespCo { int bitmapBytes = 512; await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), @@ -1486,6 +1490,7 @@ public async Task BitmapBitfieldSetTest_LTM() { int bitmapBytes = 512; await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), @@ -1952,6 +1957,7 @@ public async Task BitmapBitfieldIncrTest_LTM() { int bitmapBytes = 512; await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), diff --git a/test/Garnet.test/GarnetClientTests.cs b/test/Garnet.test/GarnetClientTests.cs index 54c59945f3..8d362472ff 100644 --- a/test/Garnet.test/GarnetClientTests.cs +++ b/test/Garnet.test/GarnetClientTests.cs @@ -145,6 +145,7 @@ public async Task SetGetWithCallback([Values] bool useTLS) e.Wait(); await server.StopAsync(); + server.Dispose(); } [Test] @@ -179,6 +180,7 @@ public async Task SimpleMetricsTest([Values] bool recordLatency) ClassicAssert.AreEqual(0, metrics.Length); // Should be 0 after dispose await server.StopAsync(); + server.Dispose(); } [Test] @@ -197,6 +199,7 @@ public async Task SimpleStringArrayTest([Values] bool stringParams) ClassicAssert.AreEqual(10, n); await server.StopAsync(); + server.Dispose(); } [Test] @@ -215,6 +218,7 @@ public async Task SimpleNoArgsTest() ClassicAssert.AreEqual("OK", result); await server.StopAsync(); + server.Dispose(); } [Test] @@ -279,6 +283,7 @@ public async Task SimpleIncrTest([Values] bool stringParams) WaitAndReset(e); await server.StopAsync(); + server.Dispose(); } [Test] @@ -343,6 +348,7 @@ public async Task SimpleDecrTest([Values] bool stringParams) WaitAndReset(e); await server.StopAsync(); + server.Dispose(); } [Test] @@ -364,6 +370,7 @@ public async Task CanUseSetNxStringResultAsync() ClassicAssert.AreEqual("Hello", resultMykey); await server.StopAsync(); + server.Dispose(); } [Test] @@ -433,6 +440,7 @@ public async Task CanUseMGetTests([Values] bool disableObjectStore) tokenSource.Dispose(); await server.StopAsync(); + server.Dispose(); } private async Task ReadValuesMGet(string[] keys, CancellationToken t) @@ -571,6 +579,7 @@ public async Task CanDoBulkDeleteTests([Values] bool useStringType) } await server.StopAsync(); + server.Dispose(); } private static async Task DeleteKeysWithCT(string[] keys, Memory[] keysMB, ManualResetEventSlim mreObj, CancellationToken t, bool useMemoryType = false) diff --git a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs index 0abf168625..9f5b4cfe7b 100644 --- a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs +++ b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs @@ -33,6 +33,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -104,6 +105,7 @@ public async Task SaveRecoverTest() } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); RegisterCustomCommand(); await server.RunAsync(); @@ -120,6 +122,7 @@ public async Task SaveRecoverTest() public async Task AofUpsertRecoverTest() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(); await server.RunAsync(); @@ -135,6 +138,7 @@ public async Task AofUpsertRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(); await server.RunAsync(); diff --git a/test/Garnet.test/HyperLogLogTests.cs b/test/Garnet.test/HyperLogLogTests.cs index 1af5ebd030..5a819d46ad 100644 --- a/test/Garnet.test/HyperLogLogTests.cs +++ b/test/Garnet.test/HyperLogLogTests.cs @@ -31,6 +31,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -578,6 +579,7 @@ public async Task HyperLogLogPFADD_LTM(int seqSize) { bool sparse = seqSize < 128 ? true : false; await server.StopAsync(); + server.Dispose(); if (seqSize < 128) server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, @@ -697,6 +699,7 @@ public void HyperLogLogTestPFMERGE_SparseToSparseV2() public async Task HyperLogLogTestPFMERGE_LTM_SparseToSparse() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "1024", @@ -807,6 +810,7 @@ public void HyperLogLogTestPFMERGE_SparseToDenseV2() public async Task HyperLogLogTestPFMERGE_LTM_SparseToDense(bool reverse) { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "32k", PageSize: "16k"); @@ -916,6 +920,7 @@ public void HyperLogLogTestPFMERGE_DenseToDenseV2() public async Task HyperLogLogTestPFMERGE_LTM_DenseToDense() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "32k", diff --git a/test/Garnet.test/IndexGrowthTests.cs b/test/Garnet.test/IndexGrowthTests.cs index 8961165199..9282c66385 100644 --- a/test/Garnet.test/IndexGrowthTests.cs +++ b/test/Garnet.test/IndexGrowthTests.cs @@ -29,6 +29,7 @@ public async Task TearDown() if (server != null) { await server.StopAsync(); + server.Dispose(); } TestUtils.DeleteDirectory(TestUtils.MethodTestDir); @@ -172,6 +173,7 @@ public async Task IndexGrowthTestWithDiskReadAndCheckpoint() } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, indexSize: "512", indexMaxSize: "1k"); await server.RunAsync(); @@ -236,6 +238,7 @@ public async Task ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k"); await server.RunAsync(); diff --git a/test/Garnet.test/LuaScriptTests.cs b/test/Garnet.test/LuaScriptTests.cs index ef82031213..57ecec6ca4 100644 --- a/test/Garnet.test/LuaScriptTests.cs +++ b/test/Garnet.test/LuaScriptTests.cs @@ -43,6 +43,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/ObjectTestsForOutput.cs b/test/Garnet.test/ObjectTestsForOutput.cs index 8bca7b5a46..080d2e0bb5 100644 --- a/test/Garnet.test/ObjectTestsForOutput.cs +++ b/test/Garnet.test/ObjectTestsForOutput.cs @@ -26,6 +26,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/ReadCacheTests.cs b/test/Garnet.test/ReadCacheTests.cs index b0b4e921f6..2aa6a3cbb0 100644 --- a/test/Garnet.test/ReadCacheTests.cs +++ b/test/Garnet.test/ReadCacheTests.cs @@ -25,6 +25,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/Resp/ACL/AclTest.cs b/test/Garnet.test/Resp/ACL/AclTest.cs index 725dde9ee8..034a19a4e6 100644 --- a/test/Garnet.test/Resp/ACL/AclTest.cs +++ b/test/Garnet.test/Resp/ACL/AclTest.cs @@ -66,6 +66,7 @@ public virtual async Task BaseTearDown() if (server != null) { await server.StopAsync(); + server.Dispose(); server = null; } diff --git a/test/Garnet.test/Resp/ACL/RespCommandTests.cs b/test/Garnet.test/Resp/ACL/RespCommandTests.cs index ddf9980dc9..00054918f6 100644 --- a/test/Garnet.test/Resp/ACL/RespCommandTests.cs +++ b/test/Garnet.test/Resp/ACL/RespCommandTests.cs @@ -49,6 +49,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs b/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs index 9e75cf4e16..889033f9c6 100644 --- a/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs +++ b/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs @@ -110,6 +110,7 @@ public async Task InvalidatingAuthorizationAsync() ClassicAssert.AreEqual(3, authCalls); await server.StopAsync(); + server.Dispose(); } } } \ No newline at end of file diff --git a/test/Garnet.test/RespAdminCommandsTests.cs b/test/Garnet.test/RespAdminCommandsTests.cs index a27f7a2143..ef05d8bbf5 100644 --- a/test/Garnet.test/RespAdminCommandsTests.cs +++ b/test/Garnet.test/RespAdminCommandsTests.cs @@ -32,6 +32,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -163,6 +164,7 @@ public async Task SeSaveRecoverTest([Values] bool disableObj, [Values] bool useA if (useAzure) TestUtils.IgnoreIfNotRunningAzureTests(); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, UseAzureStorage: useAzure); await server.RunAsync(); @@ -178,6 +180,7 @@ public async Task SeSaveRecoverTest([Values] bool disableObj, [Values] bool useA } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, UseAzureStorage: useAzure); await server.RunAsync(); @@ -210,6 +213,7 @@ public async Task SeSaveRecoverObjectTest() } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); await server.RunAsync(); @@ -249,6 +253,7 @@ public async Task SeSaveRecoverCustomObjectTest() } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); server.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), new RespCommandsInfo { Arity = 3 }); @@ -295,6 +300,7 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); await server.RunAsync(); @@ -315,6 +321,7 @@ public async Task SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryM string sizeToString(int size) => size + "k"; await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: sizeToString(memorySize), PageSize: sizeToString(pageSize)); await server.RunAsync(); @@ -336,6 +343,7 @@ public async Task SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryM } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, MemorySize: sizeToString(recoveryMemorySize), PageSize: sizeToString(pageSize), objectStoreHeapMemorySize: "64k"); await server.RunAsync(); @@ -364,6 +372,7 @@ public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recove bool disableObj = true; await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, lowMemory: true, MemorySize: memorySize, PageSize: "512", enableAOF: true); await server.RunAsync(); @@ -403,6 +412,7 @@ public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recove } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, tryRecover: true, lowMemory: true, MemorySize: recoveryMemorySize, PageSize: "512", enableAOF: true); await server.RunAsync(); @@ -421,6 +431,7 @@ public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recove public async Task SeAofRecoverTest() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); await server.RunAsync(); @@ -433,6 +444,7 @@ public async Task SeAofRecoverTest() } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, tryRecover: true); await server.RunAsync(); diff --git a/test/Garnet.test/RespAofAzureTests.cs b/test/Garnet.test/RespAofAzureTests.cs index c8c1ab1c7d..ff7a17b689 100644 --- a/test/Garnet.test/RespAofAzureTests.cs +++ b/test/Garnet.test/RespAofAzureTests.cs @@ -41,6 +41,7 @@ public async Task TearDown() if (server != null) { await server.StopAsync(); + server.Dispose(); } } @@ -56,6 +57,7 @@ public async Task AofUpsertStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -81,6 +83,7 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() server.Store.WaitForCommit(); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -98,6 +101,7 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true, UseAzureStorage: true); await server.RunAsync(); @@ -108,6 +112,7 @@ public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -141,6 +146,7 @@ public async Task AofUpsertStoreCkptRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -168,6 +174,7 @@ public async Task AofRMWStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -203,6 +210,7 @@ public async Task AofDeleteStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -238,6 +246,7 @@ public async Task AofExpiryRMWStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -272,6 +281,7 @@ public async Task AofRMWObjectStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -318,6 +328,7 @@ public async Task AofDeleteObjectStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -354,6 +365,7 @@ public async Task AofRMWObjectStoreCopyUpdateRecoverTest() } server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); @@ -409,6 +421,7 @@ public async Task AofMultiRMWStoreCkptRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); await server.RunAsync(); diff --git a/test/Garnet.test/RespAofTests.cs b/test/Garnet.test/RespAofTests.cs index 7e976ff134..81004bac31 100644 --- a/test/Garnet.test/RespAofTests.cs +++ b/test/Garnet.test/RespAofTests.cs @@ -48,6 +48,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -63,6 +64,7 @@ public async Task AofUpsertStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -88,6 +90,7 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() server.Store.WaitForCommit(); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -106,6 +109,7 @@ public async Task AofUpsertStoreAutoCommitRecoverTest() public async Task AofUpsertStoreCommitTaskRecoverTest() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitFrequencyMs: 100); await server.RunAsync(); @@ -118,6 +122,7 @@ public async Task AofUpsertStoreCommitTaskRecoverTest() server.Store.WaitForCommit(); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -135,6 +140,7 @@ public async Task AofUpsertStoreCommitTaskRecoverTest() public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); await server.RunAsync(); @@ -145,6 +151,7 @@ public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -162,6 +169,7 @@ public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() public async Task AofTransactionStoreAutoCommitCommitWaitRecoverTest() { await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); await server.RunAsync(); @@ -175,6 +183,7 @@ public async Task AofTransactionStoreAutoCommitCommitWaitRecoverTest() ClassicAssert.IsTrue(transaction.Execute()); } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -208,6 +217,7 @@ public async Task AofUpsertStoreCkptRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -239,6 +249,7 @@ public async Task AofRMWStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -277,6 +288,7 @@ public async Task AofDeleteStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -312,6 +324,7 @@ public async Task AofExpiryRMWStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -346,6 +359,7 @@ public async Task AofRMWObjectStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -392,6 +406,7 @@ public async Task AofDeleteObjectStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -428,6 +443,7 @@ public async Task AofRMWObjectStoreCopyUpdateRecoverTest() } server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -471,6 +487,7 @@ public async Task AofUpsertObjectStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -494,6 +511,7 @@ void RegisterCustomCommand(GarnetApplication gServer) } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(server); await server.RunAsync(); @@ -521,6 +539,7 @@ void RegisterCustomCommand(GarnetApplication gServer) server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(server); await server.RunAsync(); @@ -547,6 +566,7 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str } await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); await server.RunAsync(); @@ -565,6 +585,7 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); await server.RunAsync(); @@ -614,6 +635,7 @@ public async Task AofMultiRMWStoreCkptRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -645,6 +667,7 @@ public async Task AofListObjectStoreRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); await server.RunAsync(); @@ -679,6 +702,7 @@ public async Task AofCustomTxnRecoverTest() server.Store.CommitAOF(true); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), new RespCommandsInfo { Arity = 4 }); diff --git a/test/Garnet.test/RespBlockingCollectionTests.cs b/test/Garnet.test/RespBlockingCollectionTests.cs index 1229923df0..2add91147f 100644 --- a/test/Garnet.test/RespBlockingCollectionTests.cs +++ b/test/Garnet.test/RespBlockingCollectionTests.cs @@ -27,6 +27,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespCommandTests.cs b/test/Garnet.test/RespCommandTests.cs index a146c00b99..a01ab74d83 100644 --- a/test/Garnet.test/RespCommandTests.cs +++ b/test/Garnet.test/RespCommandTests.cs @@ -85,6 +85,7 @@ .. respCommandsInfo.Values.Where(ci => ci.IsInternal).Select(ci => ci.Command) public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(extTestDir)?.FullName); } diff --git a/test/Garnet.test/RespCustomCommandTests.cs b/test/Garnet.test/RespCustomCommandTests.cs index b73b6c575c..e2d089939a 100644 --- a/test/Garnet.test/RespCustomCommandTests.cs +++ b/test/Garnet.test/RespCustomCommandTests.cs @@ -247,6 +247,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(_extTestDir1)?.FullName); } diff --git a/test/Garnet.test/RespEtagTests.cs b/test/Garnet.test/RespEtagTests.cs index bb310bd5f2..fd75795e34 100644 --- a/test/Garnet.test/RespEtagTests.cs +++ b/test/Garnet.test/RespEtagTests.cs @@ -32,6 +32,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespGetLowMemoryTests.cs b/test/Garnet.test/RespGetLowMemoryTests.cs index e9723c1aa5..dd89f0c792 100644 --- a/test/Garnet.test/RespGetLowMemoryTests.cs +++ b/test/Garnet.test/RespGetLowMemoryTests.cs @@ -30,6 +30,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespHashTests.cs b/test/Garnet.test/RespHashTests.cs index 442d936706..df05969674 100644 --- a/test/Garnet.test/RespHashTests.cs +++ b/test/Garnet.test/RespHashTests.cs @@ -32,6 +32,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespInfoTests.cs b/test/Garnet.test/RespInfoTests.cs index afb144a40a..b3df9e9ebc 100644 --- a/test/Garnet.test/RespInfoTests.cs +++ b/test/Garnet.test/RespInfoTests.cs @@ -30,6 +30,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespListGarnetClientTests.cs b/test/Garnet.test/RespListGarnetClientTests.cs index fa7e6c79e5..0e8239167e 100644 --- a/test/Garnet.test/RespListGarnetClientTests.cs +++ b/test/Garnet.test/RespListGarnetClientTests.cs @@ -274,6 +274,7 @@ private static async Task ValidateListContentAsync(GarnetClient db, string key, public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespListTests.cs b/test/Garnet.test/RespListTests.cs index ec58819a47..e59c733c89 100644 --- a/test/Garnet.test/RespListTests.cs +++ b/test/Garnet.test/RespListTests.cs @@ -33,6 +33,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespLowMemoryTests.cs b/test/Garnet.test/RespLowMemoryTests.cs index 3a6208ee25..33a06d8f18 100644 --- a/test/Garnet.test/RespLowMemoryTests.cs +++ b/test/Garnet.test/RespLowMemoryTests.cs @@ -26,6 +26,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespMetricsTest.cs b/test/Garnet.test/RespMetricsTest.cs index ed92653b25..a7581a2f2e 100644 --- a/test/Garnet.test/RespMetricsTest.cs +++ b/test/Garnet.test/RespMetricsTest.cs @@ -41,6 +41,7 @@ public async Task TearDown() if (server != null) { await server.StopAsync(); + server.Dispose(); } TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); } diff --git a/test/Garnet.test/RespModuleTests.cs b/test/Garnet.test/RespModuleTests.cs index 878ec8343d..c70a799f93 100644 --- a/test/Garnet.test/RespModuleTests.cs +++ b/test/Garnet.test/RespModuleTests.cs @@ -35,6 +35,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(testModuleDir)?.FullName); } @@ -194,6 +195,7 @@ public async Task TestModuleLoadUsingGarnetOptions() var module1Path = CreateTestModule(onLoad, "TestModule1.dll"); var module2Path = CreateTestModule(onLoad2, "TestModule2.dll"); await server.StopAsync(); + server.Dispose(); server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, loadModulePaths: [module1Path, module2Path]); diff --git a/test/Garnet.test/RespPubSubTests.cs b/test/Garnet.test/RespPubSubTests.cs index c3a77ffad7..fb6197e5ca 100644 --- a/test/Garnet.test/RespPubSubTests.cs +++ b/test/Garnet.test/RespPubSubTests.cs @@ -29,6 +29,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespScanCommandsTests.cs b/test/Garnet.test/RespScanCommandsTests.cs index 1ca489d40f..173f6ba270 100644 --- a/test/Garnet.test/RespScanCommandsTests.cs +++ b/test/Garnet.test/RespScanCommandsTests.cs @@ -33,6 +33,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSetTest.cs b/test/Garnet.test/RespSetTest.cs index d362fd086c..32ecfe658c 100644 --- a/test/Garnet.test/RespSetTest.cs +++ b/test/Garnet.test/RespSetTest.cs @@ -31,6 +31,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetGarnetClientTests.cs b/test/Garnet.test/RespSortedSetGarnetClientTests.cs index fe6617a610..e8c0a97678 100644 --- a/test/Garnet.test/RespSortedSetGarnetClientTests.cs +++ b/test/Garnet.test/RespSortedSetGarnetClientTests.cs @@ -54,6 +54,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetGeoTests.cs b/test/Garnet.test/RespSortedSetGeoTests.cs index 21f387fa71..84f93f8c4e 100644 --- a/test/Garnet.test/RespSortedSetGeoTests.cs +++ b/test/Garnet.test/RespSortedSetGeoTests.cs @@ -138,6 +138,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetTests.cs b/test/Garnet.test/RespSortedSetTests.cs index 223d2810d8..385057ad54 100644 --- a/test/Garnet.test/RespSortedSetTests.cs +++ b/test/Garnet.test/RespSortedSetTests.cs @@ -85,6 +85,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTests.cs b/test/Garnet.test/RespTests.cs index a59b050f1a..b2b47e5cd3 100644 --- a/test/Garnet.test/RespTests.cs +++ b/test/Garnet.test/RespTests.cs @@ -36,6 +36,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTlsTests.cs b/test/Garnet.test/RespTlsTests.cs index 4ec8fb0f5f..7c1b4e3dd7 100644 --- a/test/Garnet.test/RespTlsTests.cs +++ b/test/Garnet.test/RespTlsTests.cs @@ -31,6 +31,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTransactionProcTests.cs b/test/Garnet.test/RespTransactionProcTests.cs index def39afe81..bf0eb03765 100644 --- a/test/Garnet.test/RespTransactionProcTests.cs +++ b/test/Garnet.test/RespTransactionProcTests.cs @@ -27,6 +27,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/TransactionTests.cs b/test/Garnet.test/TransactionTests.cs index 1083b6fcbb..bb6beccab2 100644 --- a/test/Garnet.test/TransactionTests.cs +++ b/test/Garnet.test/TransactionTests.cs @@ -27,6 +27,7 @@ public async Task Setup() public async Task TearDown() { await server.StopAsync(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); }