Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API-274] SQL for Map ([API-617], [API-616], [API-431], [API-619], [API-620], [API-432], [API-659], [API-660], [API-661]) #475

Merged
merged 132 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from 102 commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
5544daf
[WIP]
alexb5dh Jun 24, 2021
121b2ea
Add options validation
alexb5dh Jun 29, 2021
b9d4a2b
Fix `HazelcastClient` construction
alexb5dh Jun 29, 2021
9e3cc9e
`SqlService` implementation update
alexb5dh Jun 30, 2021
e61d1c9
Update FIXME comments
alexb5dh Jul 1, 2021
63a56c0
Implement `SqlResult` enumeration
alexb5dh Jul 1, 2021
355a7dd
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Jul 5, 2021
f331851
Add missing words to ReSharper dictionary
alexb5dh Jul 5, 2021
a87a58c
Implement missing codecs
alexb5dh Jul 5, 2021
e828f89
Remove SQL "reserved" codecs
alexb5dh Jul 6, 2021
6d1c079
Add missing docs, comments & update access modifiers
alexb5dh Jul 6, 2021
ad86650
Check column type for `CreateSqlColumnMetadata`
alexb5dh Jul 7, 2021
9112fda
Fix SQL tests init and cleanup
alexb5dh Jul 7, 2021
41dfe18
Get rid of `if #FALSE` in generated codecs
alexb5dh Jul 8, 2021
7b0ce54
Change `CPSubsystem` and `SqlService` initialization in client
alexb5dh Jul 8, 2021
502c6c4
Fixes
alexb5dh Jul 8, 2021
70ac532
Save error details for `HazelcastSqlException`
alexb5dh Jul 8, 2021
0414394
Formatting settings
alexb5dh Jul 8, 2021
3c07be9
Separate query and command methods, update `SqlResult`
alexb5dh Jul 9, 2021
79941ae
Interface for `SqlQueryResult`
alexb5dh Jul 10, 2021
24f2174
Tests cleanup
alexb5dh Jul 10, 2021
1140e74
Refactor `SqlQueryResult` disposing
alexb5dh Jul 10, 2021
13a9d6a
Update `SqlQueryResult`
alexb5dh Jul 10, 2021
665396f
Tests update
alexb5dh Jul 10, 2021
7ed18bf
Code cleanup
alexb5dh Jul 10, 2021
1a25f20
Summary for `ISqlQueryResult`
alexb5dh Jul 10, 2021
7baa028
Jet engine query test
alexb5dh Jul 10, 2021
bc84609
Naming update
alexb5dh Jul 15, 2021
c30c88a
Make `SqlResultType` internal
alexb5dh Jul 15, 2021
e309d15
Formatting
alexb5dh Jul 15, 2021
2157a6a
`OffsetDateTime` format fixes
alexb5dh Jul 15, 2021
3a6c745
Update date/time decoding tests
alexb5dh Jul 15, 2021
461f863
Cancellation token for `ExecuteCommandAsync`
alexb5dh Jul 15, 2021
d253fda
SQL service summary and simplifying extension method
alexb5dh Jul 21, 2021
062ba57
ReSharper formatting config update
alexb5dh Jul 21, 2021
76c6379
Deserialization tests and small tests fix
alexb5dh Jul 21, 2021
bbb3958
Basic querying examples
alexb5dh Jul 21, 2021
cfb9b3c
`BigDecimal` codec fix and optimization
alexb5dh Jul 21, 2021
58d09f2
FIXME comments for some type mapping issues
alexb5dh Jul 21, 2021
8d0740b
Implement custom date/time types and update tests
alexb5dh Jul 22, 2021
7c9583f
Fix `ByteExtensionsTests`
alexb5dh Jul 23, 2021
aecf29d
Code and typo cleanup
alexb5dh Jul 23, 2021
caf3919
`Write*` methods for SQL date/time types
alexb5dh Jul 25, 2021
86abab9
Merge branch 'master' of https://github.com/hazelcast/hazelcast-cshar…
alexb5dh Jul 26, 2021
ce5c578
Update `HLocalDate` format to use int for Year
alexb5dh Jul 26, 2021
14214fa
Summary update
alexb5dh Jul 27, 2021
9f959b7
Serializers for new date/time types
alexb5dh Jul 27, 2021
310f939
Update tests with parameters serialization
alexb5dh Jul 27, 2021
e71f708
Formatting settings update
alexb5dh Jul 27, 2021
f5d137f
Abstract `SqlResult` class
alexb5dh Jul 31, 2021
61c2d2d
`HBigDecimal` implementation
alexb5dh Aug 2, 2021
6bba07c
SQL data types conversion/parsing tests and fixes
alexb5dh Aug 2, 2021
ddf58f6
More data types tests and fixes
alexb5dh Aug 3, 2021
a084454
`HBigDecimal` default serializer and test update
alexb5dh Aug 3, 2021
c4241fc
Separate class for SQL command execution result
alexb5dh Aug 3, 2021
5b89af9
Make `SqlService` methods non-async
alexb5dh Aug 3, 2021
89b0538
Interface fix
alexb5dh Aug 4, 2021
679854e
Add using statements to basic queries example
alexb5dh Aug 4, 2021
b2716f2
Organize tests and fix Jet test
alexb5dh Aug 4, 2021
b95fefa
Fixes
alexb5dh Aug 5, 2021
65f1db5
Tests cleanup
alexb5dh Aug 5, 2021
876066b
More tests
alexb5dh Aug 5, 2021
ec97084
Update, Delete Jet tests
alexb5dh Aug 5, 2021
9917dc8
Cancellation example
alexb5dh Aug 5, 2021
c676c92
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 5, 2021
2c51b31
Summary fix
alexb5dh Aug 5, 2021
b561f94
Add missing `using`s in tests
alexb5dh Aug 6, 2021
16b7d2f
Test `IPortable` fields query
alexb5dh Aug 6, 2021
58ceff8
Support for lowercase T in `HLocalDateTime` string
alexb5dh Aug 6, 2021
5b418bd
[WIP] Documentation
alexb5dh Aug 6, 2021
68cb52b
Documentation fixes
alexb5dh Aug 9, 2021
f21e51c
Add ToC
alexb5dh Aug 9, 2021
c1bd7eb
Format tweaks
alexb5dh Aug 9, 2021
22e2e34
More details on querying
alexb5dh Aug 9, 2021
9bf8ee7
Code cleanup
alexb5dh Aug 9, 2021
709d3a2
Summary update
alexb5dh Aug 9, 2021
5f8f937
Switch to `GetConnectionForSql`
alexb5dh Aug 11, 2021
afabd5e
Fix missed lock for `GetConnectionForSql`
alexb5dh Aug 12, 2021
7a29c41
Add new types for SQL
alexb5dh Aug 16, 2021
51b8a09
Fix and more cases for `ByteExtensionsTests`
alexb5dh Aug 16, 2021
9a1d0ec
Fix and more cases for `ByteExtensionsTests`
alexb5dh Aug 16, 2021
540d5e9
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 19, 2021
40f9232
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 19, 2021
04231e7
Switch to hazelcast-all package
alexb5dh Aug 19, 2021
e654281
Update RC version to 0.8
alexb5dh Aug 19, 2021
80a9cd3
Merge branch 'feature/hazelcast-all-package' into feature/sql-support
alexb5dh Aug 19, 2021
f1a0948
Update server to 5.0-SNAPSHOT in hz script
alexb5dh Aug 19, 2021
762534c
Move jet-enabled config to resource files
alexb5dh Aug 19, 2021
9149f1f
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 19, 2021
c7133cc
`MemberVersion.ToString` fix
alexb5dh Aug 19, 2021
17d9703
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 19, 2021
f389a4b
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 19, 2021
c92c6aa
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 19, 2021
ad7450c
Implement `GetConnectionForSql`
alexb5dh Aug 20, 2021
b9ea5a0
Tests for `GetConnectionForSql` in "dummy" mode
alexb5dh Aug 20, 2021
82590cb
Tests for `FindMemberOfLargerSameVersionGroup`
alexb5dh Aug 20, 2021
79aa067
Move new types to `Models` namespaces instead of `Sql`
alexb5dh Aug 20, 2021
2697878
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 22, 2021
5f7b752
Merge branch 'feature/sql-connection' into feature/sql-support
alexb5dh Aug 22, 2021
5604e08
Merge branch 'feature/sql-types' into feature/sql-support
alexb5dh Aug 22, 2021
31b2baf
Add missing copyright
alexb5dh Aug 22, 2021
3b33604
Merge fixes
alexb5dh Aug 22, 2021
ab4241d
PR fixes
alexb5dh Aug 23, 2021
427f3fe
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 23, 2021
8590817
Move jet_enabled config to Tests project
alexb5dh Aug 24, 2021
80d89af
Update client-protocol version
alexb5dh Aug 24, 2021
30764d1
Remove synchronous `EnumerateOnce`
alexb5dh Aug 24, 2021
ba8e4bc
`SqlQueryResult` changes
alexb5dh Aug 24, 2021
1776f6c
Changes to SQL-connection methods
alexb5dh Aug 24, 2021
fa6dfec
Warning fix
alexb5dh Aug 25, 2021
bb7da81
Tests tweaks
alexb5dh Aug 25, 2021
e711099
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 25, 2021
4add8a9
Tests cleanup
alexb5dh Aug 25, 2021
cc2cbb0
Remove `EnumerateOnceAsync`, implement `IAsyncEnumerable` directly
alexb5dh Aug 25, 2021
eecaad0
Update query cancellation example
alexb5dh Aug 25, 2021
81d6e1c
Remove public `IAsyncEnumerator` implementation
alexb5dh Aug 25, 2021
a3bde31
Cleanup
alexb5dh Aug 25, 2021
1b8e49c
Add missing `CfAwait` calls
alexb5dh Aug 25, 2021
90beda3
Add example for LINQ over `ISqlQueryResult`
alexb5dh Aug 25, 2021
7401bb2
Test for cancellation via `ToListAsync` token
alexb5dh Aug 25, 2021
9f3e40d
Update documentation
alexb5dh Aug 25, 2021
4729535
Fix failing tests ?!
zpqrtbnk Aug 27, 2021
8f6e673
Add tests for async
zpqrtbnk Aug 30, 2021
59991cb
Experiment with the SQL API
zpqrtbnk Aug 30, 2021
c69bda9
Catch TaskCancelledException not OperationCancelledException
zpqrtbnk Aug 31, 2021
3c52680
Fix hz script for 5.0
zpqrtbnk Aug 31, 2021
2ade2d3
Code cleanup
alexb5dh Sep 1, 2021
0fc0091
Docs update
alexb5dh Sep 1, 2021
c34a938
Extension methods with cancellation
alexb5dh Sep 1, 2021
cfe08e6
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Sep 2, 2021
2c1ead1
Merge branch 'master' into feature/sql-support
alexb5dh Sep 2, 2021
c33e82b
Tests fix
alexb5dh Sep 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Hazelcast.Net.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_EXTENDS_COLON/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CN/@EntryIndexedValue">CN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CP/@EntryIndexedValue">CP</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=438E8320080FDC46904A18FD18FF4DCD/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=438E8320080FDC46904A18FD18FF4DCD/Color/@EntryValue">207, 157, 50</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=438E8320080FDC46904A18FD18FF4DCD/MatchComments/@EntryValue">True</s:Boolean>
Expand All @@ -13,6 +22,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=endianness/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=expirations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=multicast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nano/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=partitioner/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=retryable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hzconsole/@EntryIndexedValue">True</s:Boolean>
Expand Down
373 changes: 373 additions & 0 deletions doc/dev/doc/sql.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion hz.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ $params = @(
desc = "whether to run enterprise tests";
info = "Running enterprise tests require an enterprise key, which can be supplied either via the HAZELCAST_ENTERPRISE_KEY environment variable, or the build/enterprise.key file."
},
@{ name = "server"; type = [string]; default = "4.1-SNAPSHOT" # -SNAPSHOT to avoid obsolete certs in JARs
@{ name = "server"; type = [string]; default = "5.0-SNAPSHOT" # -SNAPSHOT to avoid obsolete certs in JARs
parm = "<version>";
desc = "the server version when running tests, the remote controller, or a server";
note = "The server <version> must match a released Hazelcast IMDG server version, e.g. 4.0 or 4.1-SNAPSHOT. Server JARs are automatically downloaded."
Expand Down
78 changes: 78 additions & 0 deletions src/Hazelcast.Net.Examples/Sql/SqlBasicQueryExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Linq;
using System.Threading.Tasks;
using Hazelcast.Models;
using Hazelcast.Sql;
using Microsoft.Extensions.Logging;

namespace Hazelcast.Examples.Sql
{
// ReSharper disable once UnusedMember.Global
public class SqlBasicQueryExample
{
public static async Task Main(params string[] args)
{
var options = new HazelcastOptionsBuilder()
.With(args)
.WithConsoleLogger()
.With("Logging:LogLevel:Hazelcast.Examples", "Information")
.Build();

var logger = options.LoggerFactory.Service.CreateLogger<SqlBasicQueryExample>();
alexb5dh marked this conversation as resolved.
Show resolved Hide resolved

// create a Hazelcast client and connect to a server running on localhost
await using var client = await HazelcastClientFactory.StartNewClientAsync(options);

// get the distributed map from the cluster and populate it
await using var map = await client.GetMapAsync<int, string>(nameof(SqlBasicQueryExample));
await map.SetAllAsync(Enumerable.Range(1, 10).ToDictionary(v => v, v => $"Value #{v}"));

// query and print all rows
{
await using var result = client.Sql.ExecuteQuery($"SELECT __key, this FROM {map.Name}");

var count = 1;
await foreach (var row in result.EnumerateOnceAsync())
logger.LogInformation("Row #{RowCount}: {RowKey}, {RowValue}", count++, row.GetKey<int>(), row.GetValue<string>());
}

// query and print all rows sorted by key descending
{
// index must be added to be able to sort by attribute
await map.AddIndexAsync(IndexType.Sorted, "__key");

await using var result = client.Sql.ExecuteQuery($"SELECT __key, this FROM {map.Name} ORDER BY __key DESC");

var count = 1;
await foreach (var row in result.EnumerateOnceAsync())
logger.LogInformation("Row (sorted) #{RowCount}: {RowKey}, {RowValue}", count++, row.GetKey<int>(), row.GetValue<string>());
}

// query and print rows filtered via parameters
{
var (min, max) = (3, 7);
await using var result = client.Sql.ExecuteQuery(
$"SELECT __key, this FROM {map.Name} WHERE __key >= ? and __key <= ?",
min, max
);

var count = 1;
await foreach (var row in result.EnumerateOnceAsync())
logger.LogInformation("Row (filtered) #{RowCount}: {RowKey}, {RowValue}", count++, row.GetKey<int>(), row.GetValue<string>());
}
}
}
}
108 changes: 108 additions & 0 deletions src/Hazelcast.Net.Examples/Sql/SqlCancellationExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace Hazelcast.Examples.Sql
{
// ReSharper disable once UnusedMember.Global
public class SqlCancellationExample
{
public static async Task Main(params string[] args)
{
var options = new HazelcastOptionsBuilder()
.With(args)
.WithConsoleLogger()
.With("Logging:LogLevel:Hazelcast.Examples", "Information")
.Build();

var logger = options.LoggerFactory.Service.CreateLogger<SqlBasicQueryExample>();

// create a Hazelcast client and connect to a server running on localhost
await using var client = await HazelcastClientFactory.StartNewClientAsync(options);

// FIXME? [Oleksii] clarify if below is correct and OK
// We will use Jet to emulate long-running query.
// To run this example you will need to enable Jet in the cluster configuration via '<jet enabled="true"></jet>'.
// Below is a simple example of such setup:
// "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
// <hazelcast xmlns="http://www.hazelcast.com/schema/config
// xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
// xsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/config/hazelcast-config-5.0.xsd">
// <jet enabled="true"></jet>" +
// </hazelcast>;

// cancel after timeout
alexb5dh marked this conversation as resolved.
Show resolved Hide resolved
{
var timeout = TimeSpan.FromSeconds(10);
logger.LogInformation("Generating values for {Timeout}", timeout);

// infinite stream that will generate 1 sequential long value about every second
await using var result = client.Sql.ExecuteQuery("SELECT * from TABLE(generate_stream(1))");

var cancellationTask = Task.Delay(timeout);

while (!cancellationTask.IsCompleted)
{
var moveNext = result.MoveNextAsync().AsTask();

if (await Task.WhenAny(moveNext, cancellationTask) == cancellationTask)
break;

if (await moveNext)
logger.LogInformation("{Value}", result.Current.GetColumn<long>(0));
else
break;
}
} // result will dispose here, leading to executing query being cancelled

// cancel after user action
{
var timeout = TimeSpan.FromSeconds(10);
logger.LogInformation("Generating values until user action", timeout);

// infinite stream that will generate 1 sequential long value about every second
await using var result = client.Sql.ExecuteQuery("SELECT * from TABLE(generate_stream(1))");

var cancellationSource = new TaskCompletionSource<object>();
var cancellationTask = cancellationSource.Task;

// listening for console input to emulate action, but any other event can be used
_ = Task.Run(() =>
{
logger.LogInformation("Press Enter to stop");
Console.ReadLine();
cancellationSource.SetResult(null);
});

while (!cancellationTask.IsCompleted)
{
var moveNext = result.MoveNextAsync().AsTask();

if (await Task.WhenAny(moveNext, cancellationTask) == cancellationTask)
break;

if (await moveNext)
logger.LogInformation("{Value}", result.Current.GetColumn<long>(0));
else
break;
}
} // result will dispose here, leading to executing query being cancelled

logger.LogInformation("Finished");
}
}
}
54 changes: 54 additions & 0 deletions src/Hazelcast.Net.Testing/Accessors/AccessorBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Reflection;

namespace Hazelcast.Testing.Accessors
{
// TODO [Oleksii] consider adding some caching/delegates
public abstract class AccessorBase<T>
{
public T Instance { get; }

protected AccessorBase(T instance)
{
Instance = instance ?? throw new ArgumentNullException(nameof(instance));
}

protected void SetField<TField>(string fieldName, TField value)
{
var member = GetFieldInfoOrThrow(fieldName);
member.SetValue(Instance, value);
}

protected TField GetField<TField>(string fieldName)
{
var member = GetFieldInfoOrThrow(fieldName);
return (TField)member.GetValue(Instance);
}

protected void SetProperty<TField>(string fieldName, TField value)
{
var member = GetPropertyInfoOrThrow(fieldName);
member.SetValue(Instance, value);
}

protected TField GetProperty<TField>(string fieldName)
{
var member = GetPropertyInfoOrThrow(fieldName);
return (TField)member.GetValue(Instance);
}

private FieldInfo GetFieldInfoOrThrow(string fieldName)
{
var type = Instance.GetType();
return type.GetField(fieldName, BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
?? throw new MissingFieldException(type.FullName, fieldName);
}

private PropertyInfo GetPropertyInfoOrThrow(string fieldName)
{
var type = Instance.GetType();
return type.GetProperty(fieldName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
?? throw new MissingFieldException(type.FullName, fieldName);
}
}
}
24 changes: 24 additions & 0 deletions src/Hazelcast.Net.Testing/Accessors/AccessorExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Hazelcast.Clustering;

namespace Hazelcast.Testing.Accessors
{
internal static class AccessorExtensions
{
public static ClusterMembersAccessor Accessor(this ClusterMembers instance) => new ClusterMembersAccessor(instance);
public static MemberConnectionAccessor Accessor(this MemberConnection instance) => new MemberConnectionAccessor(instance);
}
}
24 changes: 24 additions & 0 deletions src/Hazelcast.Net.Testing/Accessors/ClusterMembersAccessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using Hazelcast.Clustering;

namespace Hazelcast.Testing.Accessors
{
internal class ClusterMembersAccessor: AccessorBase<ClusterMembers>
{
internal ClusterMembersAccessor(ClusterMembers clusterMembers): base(clusterMembers)
{ }

internal MemberTable Members
{
get => GetField<MemberTable>("_members");
set => SetField("_members", value);
}

internal Dictionary<Guid, MemberConnection> Connections
{
get => GetField<Dictionary<Guid, MemberConnection>>("_connections");
set => SetField("_connections", value);
}
}
}
37 changes: 37 additions & 0 deletions src/Hazelcast.Net.Testing/Accessors/MemberConnectionAccessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using Hazelcast.Clustering;

namespace Hazelcast.Testing.Accessors
{
internal class MemberConnectionAccessor: AccessorBase<MemberConnection>
{
public MemberConnectionAccessor(MemberConnection instance): base(instance)
{ }

public bool Active
{
get => GetField<bool>("_active");
set => SetField("_active", value);
}

public Guid MemberId
{
get => GetProperty<Guid>(nameof(MemberConnection.MemberId));
set => SetProperty(nameof(MemberConnection.MemberId), value);
}
}
}
11 changes: 11 additions & 0 deletions src/Hazelcast.Net.Testing/CollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;

namespace Hazelcast.Testing
{
public static class CollectionExtensions
{
public static T GetOrDefault<T>(this IList<T> source, int index) => (source.Count > index || index < 0)
? source[index]
alexb5dh marked this conversation as resolved.
Show resolved Hide resolved
: default;
}
}
Loading