From 66b3b5bc19550f28aa52baf4510f554ca7e70da9 Mon Sep 17 00:00:00 2001 From: Mark Junker Date: Mon, 4 Dec 2023 18:18:10 +0100 Subject: [PATCH 1/3] Use a ConcurrentDictionary to remember which calls did work This is needed to avoid unnecessary EntryPointNotFoundException exceptions, as they massively slow down program execution - especially in development environments. --- .../Client/Native/FbClientFactory.cs | 3 ++- .../Client/Native/FesStatement.cs | 24 +++++++++++-------- .../Common/NativeHelpers.cs | 23 ++++++++++++++---- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs index 98bc44bd8..c80049abc 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs @@ -83,7 +83,8 @@ public static IFbClient Create(string dllName) { result = BuildFbClient(dllName); cache.Add(dllName, result); - ShutdownHelper.RegisterFbClientShutdown(() => NativeHelpers.CallIfExists(() => result.fb_shutdown(0, 0))); + ShutdownHelper.RegisterFbClientShutdown( + () => NativeHelpers.CallIfExists("shutdown", () => result.fb_shutdown(0, 0))); return result; } finally diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs index 8d29d76db..6732f678d 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs @@ -371,11 +371,13 @@ public override void Execute(int timeout, IDescriptorFiller descriptorFiller) descriptorFiller.Fill(_parameters, 0); ClearStatusVector(); - NativeHelpers.CallIfExists(() => - { - _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout); - _database.ProcessStatusVector(_statusVector); - }); + NativeHelpers.CallIfExists( + "set_timeout", + () => + { + _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint) timeout); + _database.ProcessStatusVector(_statusVector); + }); ClearStatusVector(); @@ -441,11 +443,13 @@ public override async ValueTask ExecuteAsync(int timeout, IDescriptorFiller desc await descriptorFiller.FillAsync(_parameters, 0, cancellationToken).ConfigureAwait(false); ClearStatusVector(); - NativeHelpers.CallIfExists(() => - { - _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout); - _database.ProcessStatusVector(_statusVector); - }); + NativeHelpers.CallIfExists( + "set_timeout", + () => + { + _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint) timeout); + _database.ProcessStatusVector(_statusVector); + }); ClearStatusVector(); diff --git a/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs b/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs index f3450e781..cc1859438 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs @@ -16,18 +16,33 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using System.Collections.Concurrent; namespace FirebirdSql.Data.Common; internal static class NativeHelpers { - public static void CallIfExists(Action action) + private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); + + public static void CallIfExists( + string actionId, + Action action) { - try + if (!_cache.TryGetValue(actionId, out var executionAllowed)) + { + try + { + action(); + _cache.TryAdd(actionId, true); + } + catch (EntryPointNotFoundException) + { + _cache.TryAdd(actionId, false); + } + } + else if (executionAllowed) { action(); } - catch (EntryPointNotFoundException) - { } } } From eb0b641c7b073062a4faaf40075ed80e475fad2f Mon Sep 17 00:00:00 2001 From: Mark Junker Date: Sun, 17 Mar 2024 00:39:11 +0100 Subject: [PATCH 2/3] Changes as requested Using nameof(IFBClient.xyz), and StringComparer.Ordinal. --- .../Client/Native/FbClientFactory.cs | 2 +- .../Client/Native/FesStatement.cs | 4 ++-- src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs index c80049abc..c45fe8d71 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs @@ -84,7 +84,7 @@ public static IFbClient Create(string dllName) result = BuildFbClient(dllName); cache.Add(dllName, result); ShutdownHelper.RegisterFbClientShutdown( - () => NativeHelpers.CallIfExists("shutdown", () => result.fb_shutdown(0, 0))); + () => NativeHelpers.CallIfExists(nameof(IFbClient.fb_shutdown), () => result.fb_shutdown(0, 0))); return result; } finally diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs index 6732f678d..d4a8dce79 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs @@ -372,7 +372,7 @@ public override void Execute(int timeout, IDescriptorFiller descriptorFiller) ClearStatusVector(); NativeHelpers.CallIfExists( - "set_timeout", + nameof(IFbClient.fb_dsql_set_timeout), () => { _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint) timeout); @@ -444,7 +444,7 @@ public override async ValueTask ExecuteAsync(int timeout, IDescriptorFiller desc ClearStatusVector(); NativeHelpers.CallIfExists( - "set_timeout", + nameof(IFbClient.fb_dsql_set_timeout), () => { _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint) timeout); diff --git a/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs b/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs index cc1859438..a2018609a 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs @@ -22,7 +22,7 @@ namespace FirebirdSql.Data.Common; internal static class NativeHelpers { - private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(StringComparer.Ordinal); public static void CallIfExists( string actionId, From cd29c894f13cb171bec5bb559d9f1884b744fc1a Mon Sep 17 00:00:00 2001 From: Mark Junker Date: Thu, 11 Jul 2024 16:16:34 +0200 Subject: [PATCH 3/3] Requested changes - No line breaks before arguments - No whitespace between cast operator and casted value --- .../Client/Native/FbClientFactory.cs | 3 +-- .../Client/Native/FesStatement.cs | 4 ++-- src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs | 4 +--- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs index c45fe8d71..c816d19a6 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs @@ -83,8 +83,7 @@ public static IFbClient Create(string dllName) { result = BuildFbClient(dllName); cache.Add(dllName, result); - ShutdownHelper.RegisterFbClientShutdown( - () => NativeHelpers.CallIfExists(nameof(IFbClient.fb_shutdown), () => result.fb_shutdown(0, 0))); + ShutdownHelper.RegisterFbClientShutdown(() => NativeHelpers.CallIfExists(nameof(IFbClient.fb_shutdown), () => result.fb_shutdown(0, 0))); return result; } finally diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs index d4a8dce79..6dc7de2fb 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs @@ -375,7 +375,7 @@ public override void Execute(int timeout, IDescriptorFiller descriptorFiller) nameof(IFbClient.fb_dsql_set_timeout), () => { - _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint) timeout); + _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout); _database.ProcessStatusVector(_statusVector); }); @@ -447,7 +447,7 @@ public override async ValueTask ExecuteAsync(int timeout, IDescriptorFiller desc nameof(IFbClient.fb_dsql_set_timeout), () => { - _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint) timeout); + _database.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout); _database.ProcessStatusVector(_statusVector); }); diff --git a/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs b/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs index a2018609a..25d65ae9d 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Common/NativeHelpers.cs @@ -24,9 +24,7 @@ internal static class NativeHelpers { private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(StringComparer.Ordinal); - public static void CallIfExists( - string actionId, - Action action) + public static void CallIfExists(string actionId, Action action) { if (!_cache.TryGetValue(actionId, out var executionAllowed)) {