From 6562aa27a56d3b908dae8638628a83b1c1b8bafd Mon Sep 17 00:00:00 2001 From: Pavel Gross Date: Wed, 11 Sep 2024 10:44:30 +0300 Subject: [PATCH 1/2] [#23] Client: Refactoring to optimize memory usage Signed-off-by: Pavel Gross --- FrostFS.SDK.sln | 11 +- README.md | 175 +++++------------ src/FrostFS.SDK.ClientV2/Cache.cs | 4 +- src/FrostFS.SDK.ClientV2/Client.cs | 70 +++---- src/FrostFS.SDK.ClientV2/CllientKey.cs | 6 +- .../Exceptions/InvalidObjectException.cs | 7 + .../Exceptions/ResponseException.cs | 5 +- .../FrostFS.SDK.ClientV2.csproj | 1 - .../Interceptors/MetricsInterceptor.cs | 2 +- .../Interfaces/IFrostFSClient.cs | 27 ++- src/FrostFS.SDK.ClientV2/Mappers/Container.cs | 28 +-- .../Mappers/ContainerId.cs | 15 +- .../Mappers/MetaHeader.cs | 1 - .../Mappers/Netmap/Netmap.cs | 10 +- .../Mappers/Netmap/NodeInfo.cs | 22 +-- .../Mappers/Netmap/PlacementPolicy.cs | 9 +- .../Mappers/Netmap/Replica.cs | 8 +- .../Mappers/Object/Object.cs | 4 +- .../Mappers/Object/ObjectAttributeMapper.cs | 7 +- .../Mappers/Object/ObjectFilterMapper.cs | 13 +- .../Mappers/Object/ObjectHeaderMapper.cs | 74 ++----- .../Mappers/Object/ObjectId.cs | 8 +- src/FrostFS.SDK.ClientV2/Mappers/OwnerId.cs | 14 +- .../Mappers/SignatureMapper.cs | 4 +- src/FrostFS.SDK.ClientV2/Mappers/Status.cs | 11 +- src/FrostFS.SDK.ClientV2/Mappers/Version.cs | 15 +- .../Models/Client/ClientSettings.cs | 63 ++++++ .../Models/Containers/FrostFsContainerId.cs | 62 ++++++ .../Models/Containers/FrostFsContainerInfo.cs | 107 ++++++++++ .../Models/Enums/BasicAcl.cs | 21 ++ .../Models/Enums/FrostFsObjectMatchType.cs} | 4 +- .../Models/Enums/FrostFsObjectType.cs | 8 + .../Models/Enums/FrostFsStatusCode.cs} | 4 +- .../Models/Enums/NodeState.cs | 9 + .../Models/Enums/SignatureScheme.cs | 8 + .../Models/Misc/CallStatistics.cs | 7 + .../Models/Misc/CheckSum.cs | 20 ++ .../Models/Misc/Constants.cs | 52 +++++ .../Models/Netmap/FrostFsNetmapSnapshot.cs | 10 + .../Models/Netmap/FrostFsNodeInfo.cs} | 9 +- .../Models/Netmap/FrostFsPlacementPolicy.cs} | 10 +- .../Models/Netmap/FrostFsReplica.cs} | 8 +- .../Models/Netmap/FrostFsVersion.cs | 31 +++ .../Models/Object/FrostFsAttribute.cs | 8 + .../Models/Object/FrostFsLargeObject.cs | 9 + .../Models/Object/FrostFsLinkObject.cs | 13 ++ .../Models/Object/FrostFsObject.cs | 64 ++++++ .../Models/Object/FrostFsObjectFilter.cs | 111 +++++++++++ .../Models/Object/FrostFsObjectHeader.cs | 85 ++++++++ .../Models/Object/FrostFsObjectId.cs | 28 +++ .../Models/Object/FrostFsOwner.cs | 38 ++++ .../Models/Object/FrostFsSplit.cs | 24 +++ .../Models/Object/IObjectReader.cs | 10 + .../Models/Object/SplitId.cs | 62 ++++++ .../Models/Response/FrostFsResponseStatus.cs | 14 ++ .../Models/Response/FrostFsSignature.cs | 10 + .../Models/Response/MetaHeader.cs | 20 ++ .../Models/Session/FrostFsSessionToken.cs | 6 + .../Parameters/Context.cs | 23 ++- .../Parameters/Credentials.cs | 9 +- .../Parameters/IContext.cs | 2 +- .../Parameters/ISessionToken.cs | 6 +- .../Parameters/PrmBase.cs | 2 +- .../Parameters/PrmContainerCreate.cs | 11 +- .../Parameters/PrmContainerDelete.cs | 10 +- .../Parameters/PrmContainerGet.cs | 8 +- .../Parameters/PrmContainerGetAll.cs | 2 +- .../Parameters/PrmNetmapSnapshot.cs | 2 +- .../Parameters/PrmNetworkSettings.cs | 2 +- .../Parameters/PrmNodeInfo.cs | 2 +- .../Parameters/PrmObjectDelete.cs | 12 +- .../Parameters/PrmObjectGet.cs | 12 +- .../Parameters/PrmObjectHeadGet.cs | 12 +- .../Parameters/PrmObjectPut.cs | 7 +- .../Parameters/PrmObjectSearch.cs | 12 +- .../Parameters/PrmSessionCreate.cs | 2 +- .../Parameters/PrmSingleObjectPut.cs | 6 +- .../Parameters/PrmWait.cs | 3 +- .../Services/ContainerServiceProvider.cs | 39 ++-- .../Services/NetmapServiceProvider.cs | 12 +- .../Services/ObjectServiceProvider.cs | 60 +++--- .../Services/SessionServiceProvider.cs | 3 +- .../Services/Shared/ContextAccessor.cs | 2 - .../Services/Shared/SessionProvider.cs | 4 +- .../Tools/ClientEnvironment.cs | 14 +- src/FrostFS.SDK.ClientV2/Tools/Object.cs | 12 +- .../Tools/ObjectReader.cs | 7 +- .../Tools/ObjectStreamer.cs | 2 +- src/FrostFS.SDK.ClientV2/Tools/ObjectTools.cs | 30 +-- src/FrostFS.SDK.ClientV2/Tools/Range.cs | 35 +--- .../Tools/RequestConstructor.cs | 1 - .../Tools/RequestSigner.cs | 10 +- .../Tools/SearchReader.cs | 8 +- src/FrostFS.SDK.ClientV2/Tools/Verifier.cs | 12 +- .../Client/ClientSettings.cs | 10 +- .../Containers/Container.cs | 13 -- .../Containers/ContainerId.cs | 2 +- .../Containers/FrostFsContainer.cs | 11 ++ src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs | 2 +- .../Enums/FrostFsObjectMatchType.cs | 10 + .../Enums/FrostFsObjectType.cs | 8 + .../Enums/FrostFsStatusCode.cs | 22 +++ src/FrostFS.SDK.ModelsV2/Enums/NodeState.cs | 2 +- src/FrostFS.SDK.ModelsV2/Enums/ObjectType.cs | 8 - .../Enums/SignatureScheme.cs | 7 +- .../Misc/CallStatistics.cs | 4 +- src/FrostFS.SDK.ModelsV2/Misc/CheckSum.cs | 2 +- src/FrostFS.SDK.ModelsV2/Misc/Constants.cs | 2 +- .../Netmap/FrostFsNodeInfo.cs | 18 ++ .../Netmap/FrostFsPlacementPolicy.cs | 28 +++ .../Netmap/FrostFsReplica.cs | 15 ++ .../Netmap/{Version.cs => FrostFsVersion.cs} | 6 +- src/FrostFS.SDK.ModelsV2/Netmap/NetmapInfo.cs | 6 +- .../Object/FrostFsObject.cs | 19 +- .../Object/IObjectReader.cs | 4 +- .../Object/ObjectAttribute.cs | 2 +- .../Object/ObjectFilter.cs | 38 ++-- .../Object/ObjectHeader.cs | 9 +- src/FrostFS.SDK.ModelsV2/Object/ObjectId.cs | 4 +- src/FrostFS.SDK.ModelsV2/Object/OwnerId.cs | 2 +- src/FrostFS.SDK.ModelsV2/Object/SplitId.cs | 30 ++- src/FrostFS.SDK.ModelsV2/Object/Splitter.cs | 7 +- .../Response/FrostFsResponseStatus.cs | 14 ++ .../Response/FrostFsSignature.cs | 10 + .../Response/MetaHeader.cs | 8 +- .../Response/ResponseStatus.cs | 16 -- .../Response/Signature.cs | 8 - .../Session/FrostFsSessionToken.cs | 6 + .../Session/SessionToken.cs | 6 - src/FrostFS.SDK.Tests/ContainerTest.cs | 19 +- src/FrostFS.SDK.Tests/MetricsInterceptor.cs | 39 ++++ .../Mocks/AsyncStreamReaderMock.cs | 15 +- .../Mocks/ClientStreamWriter.cs | 5 +- .../ContainerServiceBase.cs | 12 +- .../ContainerServiceMocks/GetContainerMock.cs | 3 +- src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs | 6 +- src/FrostFS.SDK.Tests/NetworkTest.cs | 13 +- src/FrostFS.SDK.Tests/ObjectTest.cs | 36 ++-- src/FrostFS.SDK.Tests/SessionTests.cs | 15 +- src/FrostFS.SDK.Tests/SmokeTests.cs | 185 ++++++------------ src/FrostFS.SDK.Tests/SmokeTestsBase.cs | 29 +++ 141 files changed, 1722 insertions(+), 896 deletions(-) create mode 100644 src/FrostFS.SDK.ClientV2/Exceptions/InvalidObjectException.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Client/ClientSettings.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerId.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerInfo.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Enums/BasicAcl.cs rename src/{FrostFS.SDK.ModelsV2/Enums/ObjectMatchType.cs => FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectMatchType.cs} (59%) create mode 100644 src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectType.cs rename src/{FrostFS.SDK.ModelsV2/Enums/StatusCode.cs => FrostFS.SDK.ClientV2/Models/Enums/FrostFsStatusCode.cs} (88%) create mode 100644 src/FrostFS.SDK.ClientV2/Models/Enums/NodeState.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Enums/SignatureScheme.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Misc/CallStatistics.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Misc/CheckSum.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Misc/Constants.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNetmapSnapshot.cs rename src/{FrostFS.SDK.ModelsV2/Netmap/NodeInfo.cs => FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNodeInfo.cs} (74%) rename src/{FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs => FrostFS.SDK.ClientV2/Models/Netmap/FrostFsPlacementPolicy.cs} (59%) rename src/{FrostFS.SDK.ModelsV2/Netmap/Replica.cs => FrostFS.SDK.ClientV2/Models/Netmap/FrostFsReplica.cs} (60%) create mode 100644 src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsVersion.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsAttribute.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLargeObject.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLinkObject.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObject.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectHeader.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectId.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsOwner.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/FrostFsSplit.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/IObjectReader.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Object/SplitId.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Response/FrostFsResponseStatus.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Response/FrostFsSignature.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Response/MetaHeader.cs create mode 100644 src/FrostFS.SDK.ClientV2/Models/Session/FrostFsSessionToken.cs delete mode 100644 src/FrostFS.SDK.ModelsV2/Containers/Container.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Containers/FrostFsContainer.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectMatchType.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectType.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Enums/FrostFsStatusCode.cs delete mode 100644 src/FrostFS.SDK.ModelsV2/Enums/ObjectType.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Netmap/FrostFsNodeInfo.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Netmap/FrostFsPlacementPolicy.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Netmap/FrostFsReplica.cs rename src/FrostFS.SDK.ModelsV2/Netmap/{Version.cs => FrostFsVersion.cs} (64%) create mode 100644 src/FrostFS.SDK.ModelsV2/Response/FrostFsResponseStatus.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Response/FrostFsSignature.cs delete mode 100644 src/FrostFS.SDK.ModelsV2/Response/ResponseStatus.cs delete mode 100644 src/FrostFS.SDK.ModelsV2/Response/Signature.cs create mode 100644 src/FrostFS.SDK.ModelsV2/Session/FrostFsSessionToken.cs delete mode 100644 src/FrostFS.SDK.ModelsV2/Session/SessionToken.cs create mode 100644 src/FrostFS.SDK.Tests/MetricsInterceptor.cs create mode 100644 src/FrostFS.SDK.Tests/SmokeTestsBase.cs diff --git a/FrostFS.SDK.sln b/FrostFS.SDK.sln index c192375..f0c0d87 100644 --- a/FrostFS.SDK.sln +++ b/FrostFS.SDK.sln @@ -1,16 +1,13 @@ + Microsoft Visual Studio Solution File, Format Version 12.00 -# VisualStudioVersion = 17.5.002.0 - Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ClientV2", "src\FrostFS.SDK.ClientV2\FrostFS.SDK.ClientV2.csproj", "{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.Cryptography", "src\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj", "{3D804F4A-B0B2-47A5-B006-BE447BE64B50}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ModelsV2", "src\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj", "{14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ProtosV2", "src\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj", "{5012EF96-9C9E-4E77-BC78-B4111EE54107}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.Tests", "src\FrostFS.SDK.Tests\FrostFS.SDK.Tests.csproj", "{8FDA7E0D-9C75-4874-988E-6592CD28F76C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.Tests", "src\FrostFS.SDK.Tests\FrostFS.SDK.Tests.csproj", "{8FDA7E0D-9C75-4874-988E-6592CD28F76C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -26,10 +23,6 @@ Global {3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Release|Any CPU.Build.0 = Release|Any CPU - {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Release|Any CPU.Build.0 = Release|Any CPU {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Debug|Any CPU.Build.0 = Debug|Any CPU {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/README.md b/README.md index 89ab89a..d2e5fab 100644 --- a/README.md +++ b/README.md @@ -21,137 +21,62 @@ neo-go wallet export -w -d ### Container ```csharp +using FrostFS.SDK; using FrostFS.SDK.ClientV2; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Enums; -using FrostFS.SDK.ModelsV2.Netmap; -var fsClient = Client.GetInstance(, ); +using Microsoft.Extensions.Options; -// List containers -var containersIds = await fsClient.ListContainersAsync(); +var Key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq"; +var Host = "http://172.22.33.44:8080"; -// Create container -var placementPolicy = new PlacementPolicy(true, new Replica(1)); -var containerId = await fsClient.CreateContainerAsync( - new Container( - BasicAcl.PublicRW, - placementPolicy - ) -); - -// Get container -var container = await fsClient.GetContainerAsync(cId); - -// Delete container -await fsClient.DeleteContainerAsync(containerId); -``` - -### Object - -```csharp -using FrostFS.SDK.ClientV2; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Enums; -using FrostFS.SDK.ModelsV2.Netmap; - -var fsClient = Client.GetInstance(, ); - -// Search regular objects -var objectsIds = await fsClient.SearchObjectAsync( - cId, - ObjectFilter.RootFilter() -); - -// Put object -var f = File.OpenRead("cat.jpg"); -var cat = new ObjectHeader( - containerId: cId, - type: ObjectType.Regular, - new ObjectAttribute("Filename", "cat.jpg") -); -var oId = await fsClient.PutObjectAsync(cat, f); - -// Get object header -var objHeader = await fsClient.GetObjectHeadAsync(cId, oId); - -// Get object -var obj = await fsClient.GetObjectAsync(cId, oId); -``` - -### Custom client cut -```csharp - -using FrostFS.SDK.ClientV2; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Enums; -using FrostFS.SDK.ModelsV2.Netmap; -using FrostFS.SDK.ClientV2.Extensions; -using FrostFS.SDK.ClientV2.Interfaces; - -var fsClient = Client.GetInstance(, ); - -ContainerId containerId = ; -string fileName = ; - -await PutObjectClientCut(fsClient, containerId, fileName); - -static async Task PutObjectClientCut(IFrostFSClient fsClient, ContainerId containerId, string fileName) +var options = Options.Create(new SingleOwnerClientSettings { - List sentObjectIds = []; - FrostFS.SDK.ModelsV2.Object? currentObject; + Key = Key, + Host = Host +}); - var partSize = 1024 * 1024; - var buffer = new byte[partSize]; +using var client = Client.GetSingleOwnerInstance(options); - var largeObject = new LargeObject(containerId); - - var split = new Split(); - - var fileInfo = new FileInfo(fileName); - var fullLength = (ulong)fileInfo.Length; - var fileNameAttribute = new ObjectAttribute("fileName", fileInfo.Name); - - using var stream = File.OpenRead(fileName); - while (true) - { - var bytesCount = await stream.ReadAsync(buffer.AsMemory(0, partSize)); - - split.Previous = sentObjectIds.LastOrDefault(); - - largeObject.AppendBlock(buffer, bytesCount); - - currentObject = new FrostFS.SDK.ModelsV2.Object(containerId, bytesCount < partSize ? buffer.Take(bytesCount).ToArray() : buffer) - .AddAttribute(fileNameAttribute) - .SetSplit(split); - - if (largeObject.PayloadLength == fullLength) - break; - - var objectId = await fsClient.PutSingleObjectAsync(currentObject); - sentObjectIds.Add(objectId); - } - - if (sentObjectIds.Any()) - { - largeObject.CalculateHash() - .AddAttribute(fileNameAttribute); - - currentObject.SetParent(largeObject); - - var objectId = await fsClient.PutSingleObjectAsync(currentObject); - sentObjectIds.Add(objectId); - - var linkObject = new LinkObject(containerId, split.SplitId, largeObject) - .AddChildren(sentObjectIds) - .AddAttribute(fileNameAttribute); - - _ = await fsClient.PutSingleObjectAsync(linkObject); - - return currentObject.GetParentId(); - } - - return await fsClient.PutSingleObjectAsync(currentObject); +await foreach (var cid in client.ListContainersAsync()) +{ + await client.DeleteContainerAsync(new PrmContainerDelete(cid)); } -``` \ No newline at end of file +var placementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)); + +var createContainerParam = new PrmContainerCreate( + new FrostFsContainerInfo(BasicAcl.PublicRW, new FrostFsPlacementPolicy(true, new FrostFsReplica(1)))); + +var containerId = await client.CreateContainerAsync(createContainerParam); + +using var fileStream = File.OpenRead(@"C:\Users\Paul\Pictures\cat.jpeg"); + +var param = new PrmObjectPut +{ + Header = new FrostFsObjectHeader( + containerId: containerId, + type: FrostFsObjectType.Regular, + [new FrostFsAttribute("fileName", "test")]), + Payload = fileStream +}; + +FrostFsObjectId objectId = await client.PutObjectAsync(param); + +var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); + +await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId) { Filters = [filter] })) +{ + var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objId)); +} + +var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId)); + +var downloadedBytes = new byte[@object.Header.PayloadLength]; +MemoryStream ms = new(downloadedBytes); + +ReadOnlyMemory? chunk = null; +while ((chunk = await @object.ObjectReader!.ReadChunk()) != null) +{ + ms.Write(chunk.Value.Span); +} +``` diff --git a/src/FrostFS.SDK.ClientV2/Cache.cs b/src/FrostFS.SDK.ClientV2/Cache.cs index a41c8b9..19ec83b 100644 --- a/src/FrostFS.SDK.ClientV2/Cache.cs +++ b/src/FrostFS.SDK.ClientV2/Cache.cs @@ -1,6 +1,4 @@ - - -using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Caching.Memory; namespace FrostFS.SDK.ClientV2 { diff --git a/src/FrostFS.SDK.ClientV2/Client.cs b/src/FrostFS.SDK.ClientV2/Client.cs index 0142c03..6d47be5 100644 --- a/src/FrostFS.SDK.ClientV2/Client.cs +++ b/src/FrostFS.SDK.ClientV2/Client.cs @@ -1,21 +1,21 @@ -using FrostFS.Container; -using FrostFS.Netmap; -using FrostFS.Object; -using FrostFS.SDK.ClientV2.Interfaces; -using FrostFS.SDK.ClientV2.Parameters; -using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Netmap; -using FrostFS.Session; -using Grpc.Core; -using Grpc.Core.Interceptors; -using Grpc.Net.Client; -using Microsoft.Extensions.Options; -using System; +using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; -using Version = FrostFS.SDK.ModelsV2.Version; + +using FrostFS.Container; +using FrostFS.Netmap; +using FrostFS.Object; +using FrostFS.SDK.ClientV2.Interfaces; +using FrostFS.SDK.ClientV2; +using FrostFS.SDK.Cryptography; +using FrostFS.Session; + +using Grpc.Core; +using Grpc.Core.Interceptors; +using Grpc.Net.Client; + +using Microsoft.Extensions.Options; namespace FrostFS.SDK.ClientV2; @@ -70,14 +70,14 @@ public class Client : IFrostFSClient ObjectService.ObjectServiceClient objectService) { var ecdsaKey = settings.Value.Key.LoadWif(); - OwnerId.FromKey(ecdsaKey); + FrostFsOwner.FromKey(ecdsaKey); ClientCtx = new ClientEnvironment( client: this, key: ecdsaKey, - owner: OwnerId.FromKey(ecdsaKey), + owner: FrostFsOwner.FromKey(ecdsaKey), channel: InitGrpcChannel(settings.Value.Host, channelOptions), - version: new Version(2, 13)); + version: new FrostFsVersion(2, 13)); ContainerServiceClient = containerService; NetmapServiceClient = netmapService; @@ -98,7 +98,7 @@ public class Client : IFrostFSClient key: null, owner: null, channel: channel, - version: new Version(2, 13)); + version: new FrostFsVersion(2, 13)); // TODO: define timeout logic // CheckFrostFsVersionSupport(new Context { Timeout = TimeSpan.FromSeconds(20) }); @@ -117,9 +117,9 @@ public class Client : IFrostFSClient ClientCtx = new ClientEnvironment( this, key: ecdsaKey, - owner: OwnerId.FromKey(ecdsaKey), + owner: FrostFsOwner.FromKey(ecdsaKey), channel: channel, - version: new Version(2, 13)); + version: new FrostFsVersion(2, 13)); // TODO: define timeout logic CheckFrostFsVersionSupport(new Context { Timeout = TimeSpan.FromSeconds(20)}); @@ -135,26 +135,26 @@ public class Client : IFrostFSClient { if (disposing && !isDisposed) { - ClientCtx.Dispose(); + ClientCtx?.Dispose(); isDisposed = true; } } #region ContainerImplementation - public Task GetContainerAsync(PrmContainerGet args) + public Task GetContainerAsync(PrmContainerGet args) { var service = GetContainerService(args); return service.GetContainerAsync(args); } - public IAsyncEnumerable ListContainersAsync(PrmContainerGetAll? args = null) + public IAsyncEnumerable ListContainersAsync(PrmContainerGetAll? args = null) { args ??= new PrmContainerGetAll(); var service = GetContainerService(args); return service.ListContainersAsync(args); } - public Task CreateContainerAsync(PrmContainerCreate args) + public Task CreateContainerAsync(PrmContainerCreate args) { var service = GetContainerService(args); return service.CreateContainerAsync(args); @@ -168,14 +168,14 @@ public class Client : IFrostFSClient #endregion #region NetworkImplementation - public Task GetNetmapSnapshotAsync(PrmNetmapSnapshot? args) + public Task GetNetmapSnapshotAsync(PrmNetmapSnapshot? args) { args ??= new PrmNetmapSnapshot(); var service = GetNetmapService(args); return service.GetNetmapSnapshotAsync(args); } - public Task GetNodeInfoAsync(PrmNodeInfo? args) + public Task GetNodeInfoAsync(PrmNodeInfo? args) { args ??= new PrmNodeInfo(); var service = GetNetmapService(args); @@ -191,7 +191,7 @@ public class Client : IFrostFSClient #endregion #region ObjectImplementation - public Task GetObjectHeadAsync(PrmObjectHeadGet args) + public Task GetObjectHeadAsync(PrmObjectHeadGet args) { var service = GetObjectService(args); return service.GetObjectHeadAsync(args); @@ -203,13 +203,13 @@ public class Client : IFrostFSClient return service.GetObjectAsync(args); } - public Task PutObjectAsync(PrmObjectPut args) + public Task PutObjectAsync(PrmObjectPut args) { var service = GetObjectService(args); return service.PutObjectAsync(args); } - public Task PutSingleObjectAsync(PrmSingleObjectPut args) + public Task PutSingleObjectAsync(PrmSingleObjectPut args) { var service = GetObjectService(args); return service.PutSingleObjectAsync(args); @@ -221,7 +221,7 @@ public class Client : IFrostFSClient return service.DeleteObjectAsync(args); } - public IAsyncEnumerable SearchObjectsAsync(PrmObjectSearch args) + public IAsyncEnumerable SearchObjectsAsync(PrmObjectSearch args) { var service = GetObjectService(args); return service.SearchObjectsAsync(args); @@ -229,12 +229,12 @@ public class Client : IFrostFSClient #endregion #region SessionImplementation - public async Task CreateSessionAsync(PrmSessionCreate args) + public async Task CreateSessionAsync(PrmSessionCreate args) { var session = await CreateSessionInternalAsync(args); var token = session.Serialize(); - return new ModelsV2.SessionToken(token); + return new FrostFsSessionToken(token); } internal Task CreateSessionInternalAsync(PrmSessionCreate args) @@ -245,7 +245,7 @@ public class Client : IFrostFSClient #endregion #region ToolsImplementation - public ObjectId CalculateObjectId(ObjectHeader header, Context ctx) + public FrostFsObjectId CalculateObjectId(FrostFsObjectHeader header, Context ctx) { if (header == null) throw new ArgumentNullException(nameof(header)); @@ -286,7 +286,7 @@ public class Client : IFrostFSClient if (ctx.Context.OwnerId == null) { - ctx.Context.OwnerId = ClientCtx.Owner ?? OwnerId.FromKey(ctx.Context.Key); + ctx.Context.OwnerId = ClientCtx.Owner ?? FrostFsOwner.FromKey(ctx.Context.Key); } if (ctx.Context.Version == null) diff --git a/src/FrostFS.SDK.ClientV2/CllientKey.cs b/src/FrostFS.SDK.ClientV2/CllientKey.cs index e415a98..5b10485 100644 --- a/src/FrostFS.SDK.ClientV2/CllientKey.cs +++ b/src/FrostFS.SDK.ClientV2/CllientKey.cs @@ -1,6 +1,8 @@ -using FrostFS.SDK.Cryptography; +using System.Security.Cryptography; + +using FrostFS.SDK.Cryptography; + using Google.Protobuf; -using System.Security.Cryptography; namespace FrostFS.SDK.ClientV2 { diff --git a/src/FrostFS.SDK.ClientV2/Exceptions/InvalidObjectException.cs b/src/FrostFS.SDK.ClientV2/Exceptions/InvalidObjectException.cs new file mode 100644 index 0000000..f2a8ea7 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Exceptions/InvalidObjectException.cs @@ -0,0 +1,7 @@ +using System; + +namespace FrostFS.SDK.ClientV2; + +public class InvalidObjectException() : Exception() +{ +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Exceptions/ResponseException.cs b/src/FrostFS.SDK.ClientV2/Exceptions/ResponseException.cs index d72f173..ad3c63e 100644 --- a/src/FrostFS.SDK.ClientV2/Exceptions/ResponseException.cs +++ b/src/FrostFS.SDK.ClientV2/Exceptions/ResponseException.cs @@ -1,9 +1,8 @@ -using FrostFS.SDK.ModelsV2; using System; namespace FrostFS.SDK.ClientV2; -public class ResponseException(ResponseStatus status) : Exception() +public class ResponseException(FrostFsResponseStatus status) : Exception() { - public ResponseStatus Status { get; set; } = status; + public FrostFsResponseStatus Status { get; set; } = status; } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj b/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj index f811e53..5f423dd 100644 --- a/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj +++ b/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj @@ -21,7 +21,6 @@ - diff --git a/src/FrostFS.SDK.ClientV2/Interceptors/MetricsInterceptor.cs b/src/FrostFS.SDK.ClientV2/Interceptors/MetricsInterceptor.cs index c395629..dc439f9 100644 --- a/src/FrostFS.SDK.ClientV2/Interceptors/MetricsInterceptor.cs +++ b/src/FrostFS.SDK.ClientV2/Interceptors/MetricsInterceptor.cs @@ -1,7 +1,7 @@ using System; using System.Diagnostics; using System.Threading.Tasks; -using FrostFS.SDK.ModelsV2; + using Grpc.Core; using Grpc.Core.Interceptors; diff --git a/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs b/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs index 500a9c2..80608d0 100644 --- a/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs +++ b/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs @@ -1,50 +1,49 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using FrostFS.SDK.ClientV2.Parameters; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Netmap; + +using FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2.Interfaces; public interface IFrostFSClient : IDisposable { #region Network - Task GetNetmapSnapshotAsync(PrmNetmapSnapshot? args = null); + Task GetNetmapSnapshotAsync(PrmNetmapSnapshot? args = null); - Task GetNodeInfoAsync(PrmNodeInfo? args = null); + Task GetNodeInfoAsync(PrmNodeInfo? args = null); Task GetNetworkSettingsAsync(PrmNetworkSettings? args = null); #endregion #region Session - Task CreateSessionAsync(PrmSessionCreate args); + Task CreateSessionAsync(PrmSessionCreate args); #endregion #region Container - Task GetContainerAsync(PrmContainerGet args); + Task GetContainerAsync(PrmContainerGet args); - IAsyncEnumerable ListContainersAsync(PrmContainerGetAll? args = null); + IAsyncEnumerable ListContainersAsync(PrmContainerGetAll? args = null); - Task CreateContainerAsync(PrmContainerCreate args); + Task CreateContainerAsync(PrmContainerCreate args); Task DeleteContainerAsync(PrmContainerDelete args); #endregion #region Object - Task GetObjectHeadAsync(PrmObjectHeadGet args); + Task GetObjectHeadAsync(PrmObjectHeadGet args); Task GetObjectAsync(PrmObjectGet args); - Task PutObjectAsync(PrmObjectPut putObjectParameters); + Task PutObjectAsync(PrmObjectPut args); - Task PutSingleObjectAsync(PrmSingleObjectPut args); + Task PutSingleObjectAsync(PrmSingleObjectPut args); Task DeleteObjectAsync(PrmObjectDelete args); - IAsyncEnumerable SearchObjectsAsync(PrmObjectSearch args); + IAsyncEnumerable SearchObjectsAsync(PrmObjectSearch args); #endregion #region Tools - ObjectId CalculateObjectId(ObjectHeader header, Context ctx); + FrostFsObjectId CalculateObjectId(FrostFsObjectHeader header, Context ctx); #endregion } diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Container.cs b/src/FrostFS.SDK.ClientV2/Mappers/Container.cs index 83bfb32..181de40 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Container.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Container.cs @@ -1,36 +1,24 @@ using System; +using System.Linq; -using Google.Protobuf; - -using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2.Enums; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; public static class ContainerMapper { - public static Container.Container ToMessage(this ModelsV2.Container container) - { - return new Container.Container - { - BasicAcl = (uint)container.BasicAcl, - PlacementPolicy = container.PlacementPolicy.ToMessage(), - Nonce = ByteString.CopyFrom(container.Nonce.ToBytes()) - }; - } - - public static ModelsV2.Container ToModel(this Container.Container container) + public static FrostFsContainerInfo ToModel(this Container.Container container) { if (!Enum.IsDefined(typeof(BasicAcl),(int)container.BasicAcl)) throw new ArgumentException($"Unknown BasicACL rule. Value: '{container.BasicAcl}'."); BasicAcl acl = (BasicAcl)container.BasicAcl; - return new ModelsV2.Container(acl, container.PlacementPolicy.ToModel()) - { - Nonce = container.Nonce.ToUuid(), - Version = container.Version.ToModel() - }; + return new FrostFsContainerInfo(acl, + container.PlacementPolicy.ToModel(), + container.Attributes?.Select(a => new FrostFsAttribute(a.Key, a.Value)).ToList(), + container.Version?.ToModel(), + container.OwnerId?.ToModel(), + container.Nonce?.ToUuid()); } } diff --git a/src/FrostFS.SDK.ClientV2/Mappers/ContainerId.cs b/src/FrostFS.SDK.ClientV2/Mappers/ContainerId.cs index 65199ca..f5feccc 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/ContainerId.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/ContainerId.cs @@ -1,9 +1,11 @@ +using System; + using FrostFS.Refs; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; + using Google.Protobuf; + using Microsoft.Extensions.Caching.Memory; -using System; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; @@ -13,16 +15,19 @@ public static class ContainerIdMapper .SetSlidingExpiration(TimeSpan.FromHours(1)) .SetSize(1); - public static ContainerID ToMessage(this ContainerId model) + public static ContainerID ToMessage(this FrostFsContainerId model) { - if (!Cache.Containers.TryGetValue(model, out ContainerID? message)) + if (model.Value == null) + throw new ArgumentNullException(nameof(model)); + + if (!Cache.Containers.TryGetValue(model.Value, out ContainerID? message)) { message = new ContainerID { Value = ByteString.CopyFrom(Base58.Decode(model.Value)) }; - Cache.Containers.Set(model, message, _oneHourExpiration); + Cache.Containers.Set(model.Value, message, _oneHourExpiration); } return message!; diff --git a/src/FrostFS.SDK.ClientV2/Mappers/MetaHeader.cs b/src/FrostFS.SDK.ClientV2/Mappers/MetaHeader.cs index 360ddd4..6b4901c 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/MetaHeader.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/MetaHeader.cs @@ -1,4 +1,3 @@ -using FrostFS.SDK.ModelsV2; using FrostFS.Session; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Netmap.cs b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Netmap.cs index 7d44809..31a8a0f 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Netmap.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Netmap.cs @@ -1,14 +1,14 @@ using System.Linq; -using FrostFS.Netmap; -using FrostFS.SDK.ModelsV2.Netmap; -namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; +using FrostFS.Netmap; + +namespace FrostFS.SDK.ClientV2; public static class NetmapMapper { - public static NetmapSnapshot ToModel(this NetmapSnapshotResponse netmap) + public static FrostFsNetmapSnapshot ToModel(this NetmapSnapshotResponse netmap) { - return new NetmapSnapshot( + return new FrostFsNetmapSnapshot( netmap.Body.Netmap.Epoch, netmap.Body.Netmap.Nodes .Select(n => n.ToModel(netmap.MetaHeader.Version)) diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/NodeInfo.cs b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/NodeInfo.cs index da87dfd..86e5ff0 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/NodeInfo.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/NodeInfo.cs @@ -1,30 +1,30 @@ using System; using System.Linq; -using FrostFS.Netmap; -using FrostFS.SDK.ModelsV2.Enums; -using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo; -namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; +using FrostFS.Netmap; +using FrostFS.SDK.ClientV2.Mappers.GRPC; + +namespace FrostFS.SDK.ClientV2; public static class NodeInfoMapper { - public static NodeInfo ToModel(this LocalNodeInfoResponse.Types.Body node) + public static FrostFsNodeInfo ToModel(this LocalNodeInfoResponse.Types.Body node) { return node.NodeInfo.ToModel(node.Version); } - public static NodeInfo ToModel(this FrostFS.Netmap.NodeInfo nodeInfo, Refs.Version version) + public static FrostFsNodeInfo ToModel(this NodeInfo nodeInfo, Refs.Version version) { NodeState state = nodeInfo.State switch { - FrostFS.Netmap.NodeInfo.Types.State.Unspecified => NodeState.Unspecified, - FrostFS.Netmap.NodeInfo.Types.State.Online => NodeState.Online, - FrostFS.Netmap.NodeInfo.Types.State.Offline => NodeState.Offline, - FrostFS.Netmap.NodeInfo.Types.State.Maintenance => NodeState.Maintenance, + NodeInfo.Types.State.Unspecified => NodeState.Unspecified, + NodeInfo.Types.State.Online => NodeState.Online, + NodeInfo.Types.State.Offline => NodeState.Offline, + NodeInfo.Types.State.Maintenance => NodeState.Maintenance, _ => throw new ArgumentException($"Unknown NodeState. Value: '{nodeInfo.State}'.") }; - return new NodeInfo( + return new FrostFsNodeInfo( version: version.ToModel(), state: state, addresses: [.. nodeInfo.Addresses], diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/PlacementPolicy.cs b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/PlacementPolicy.cs index 47b51fa..2f66ed8 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/PlacementPolicy.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/PlacementPolicy.cs @@ -1,11 +1,12 @@ using System.Linq; + using FrostFS.Netmap; -namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; +namespace FrostFS.SDK.ClientV2; public static class PlacementPolicyMapper { - public static PlacementPolicy ToMessage(this ModelsV2.Netmap.PlacementPolicy placementPolicy) + public static PlacementPolicy ToMessage(this FrostFsPlacementPolicy placementPolicy) { var pp = new PlacementPolicy { @@ -23,9 +24,9 @@ public static class PlacementPolicyMapper return pp; } - public static ModelsV2.Netmap.PlacementPolicy ToModel(this PlacementPolicy placementPolicy) + public static FrostFsPlacementPolicy ToModel(this PlacementPolicy placementPolicy) { - return new ModelsV2.Netmap.PlacementPolicy( + return new FrostFsPlacementPolicy( placementPolicy.Unique, placementPolicy.Replicas.Select(replica => replica.ToModel()).ToArray() ); diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Replica.cs b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Replica.cs index 215a127..422891d 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Replica.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Netmap/Replica.cs @@ -1,10 +1,10 @@ using FrostFS.Netmap; -namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; +namespace FrostFS.SDK.ClientV2; public static class ReplicaMapper { - public static Replica ToMessage(this ModelsV2.Netmap.Replica replica) + public static Replica ToMessage(this FrostFsReplica replica) { return new Replica { @@ -13,8 +13,8 @@ public static class ReplicaMapper }; } - public static ModelsV2.Netmap.Replica ToModel(this Replica replica) + public static FrostFsReplica ToModel(this Replica replica) { - return new ModelsV2.Netmap.Replica((int)replica.Count, replica.Selector); + return new FrostFsReplica((int)replica.Count, replica.Selector); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Object/Object.cs b/src/FrostFS.SDK.ClientV2/Mappers/Object/Object.cs index bda31fe..0e10ffe 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Object/Object.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Object/Object.cs @@ -1,5 +1,3 @@ -using FrostFS.SDK.ModelsV2; - namespace FrostFS.SDK.ClientV2.Mappers.GRPC; internal static class ObjectMapper @@ -8,7 +6,7 @@ internal static class ObjectMapper { return new FrostFsObject(obj.Header.ToModel()) { - ObjectId = ObjectId.FromHash(obj.ObjectId.Value.ToByteArray()) + ObjectId = FrostFsObjectId.FromHash(obj.ObjectId.Value.ToByteArray()) }; } } diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectAttributeMapper.cs b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectAttributeMapper.cs index 7528152..de596ad 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectAttributeMapper.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectAttributeMapper.cs @@ -1,11 +1,10 @@ using FrostFS.Object; -using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; public static class ObjectAttributeMapper { - public static Header.Types.Attribute ToMessage(this ObjectAttribute attribute) + public static Header.Types.Attribute ToMessage(this FrostFsAttribute attribute) { return new Header.Types.Attribute { @@ -14,8 +13,8 @@ public static class ObjectAttributeMapper }; } - public static ObjectAttribute ToModel(this Header.Types.Attribute attribute) + public static FrostFsAttribute ToModel(this Header.Types.Attribute attribute) { - return new ObjectAttribute(attribute.Key, attribute.Value); + return new FrostFsAttribute(attribute.Key, attribute.Value); } } diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs index 8353f5f..e59f51b 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs @@ -1,7 +1,6 @@ using System; + using FrostFS.Object; -using FrostFS.SDK.ModelsV2; -using MatchType = FrostFS.Object.MatchType; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; @@ -11,11 +10,11 @@ public static class ObjectFilterMapper { var objMatchTypeName = filter.MatchType switch { - ModelsV2.Enums.ObjectMatchType.Unspecified => MatchType.Unspecified, - ModelsV2.Enums.ObjectMatchType.Equals => MatchType.StringEqual, - ModelsV2.Enums.ObjectMatchType.NotEquals => MatchType.StringNotEqual, - ModelsV2.Enums.ObjectMatchType.KeyAbsent => MatchType.NotPresent, - ModelsV2.Enums.ObjectMatchType.StartsWith => MatchType.CommonPrefix, + FrostFsObjectMatchType.Unspecified => MatchType.Unspecified, + FrostFsObjectMatchType.Equals => MatchType.StringEqual, + FrostFsObjectMatchType.NotEquals => MatchType.StringNotEqual, + FrostFsObjectMatchType.KeyAbsent => MatchType.NotPresent, + FrostFsObjectMatchType.StartsWith => MatchType.CommonPrefix, _ => throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.") }; diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectHeaderMapper.cs b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectHeaderMapper.cs index 282e42e..fb4c77d 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectHeaderMapper.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectHeaderMapper.cs @@ -1,75 +1,28 @@ using System; using System.Linq; + using FrostFS.Object; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; -using Google.Protobuf; -using ObjectType = FrostFS.Object.ObjectType; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; public static class ObjectHeaderMapper { - public static Header ToMessage(this ObjectHeader header) + public static FrostFsObjectHeader ToModel(this Header header) { var objTypeName = header.ObjectType switch { - ModelsV2.Enums.ObjectType.Regular => ObjectType.Regular, - ModelsV2.Enums.ObjectType.Lock => ObjectType.Lock, - ModelsV2.Enums.ObjectType.Tombstone => ObjectType.Tombstone, + ObjectType.Regular => FrostFsObjectType.Regular, + ObjectType.Lock => FrostFsObjectType.Lock, + ObjectType.Tombstone => FrostFsObjectType.Tombstone, _ => throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.") }; - var head = new Header - { - OwnerId = header!.OwnerId != null ? header.OwnerId.ToMessage() : null, - Version = header!.Version != null ? header.Version.ToMessage() : null, - ContainerId = header.ContainerId.ToMessage(), - ObjectType = objTypeName, - PayloadLength = header.PayloadLength - }; - - foreach (var attribute in header.Attributes) - { - head.Attributes.Add(attribute.ToMessage()); - } - - var split = header.Split; - if (split != null) - { - head.Split = new Header.Types.Split - { - SplitId = split.SplitId != null ? ByteString.CopyFrom(split.SplitId.ToBinary()) : null - }; - } - - return head; - } - - public static ObjectHeader ToModel(this Header header) - { - var objTypeName = header.ObjectType switch - { - ObjectType.Regular => ModelsV2.Enums.ObjectType.Regular, - ObjectType.Lock => ModelsV2.Enums.ObjectType.Lock, - ObjectType.Tombstone => ModelsV2.Enums.ObjectType.Tombstone, - _ => throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.") - }; - - var model = new ObjectHeader( - new ContainerId(Base58.Encode(header.ContainerId.Value.ToByteArray())), - objTypeName, - header.Attributes.Select(attribute => attribute.ToModel()).ToArray() - ) - { - PayloadLength = header.PayloadLength, - Version = header.Version.ToModel(), - OwnerId = header.OwnerId.ToModel() - }; + FrostFsSplit? split = null; if (header.Split != null) { - model.Split = new Split(new SplitId(header.Split.SplitId.ToUuid())) + split = new FrostFsSplit(new SplitId(header.Split.SplitId.ToUuid())) { Parent = header.Split.Parent?.ToModel(), ParentHeader = header.Split.ParentHeader?.ToModel(), @@ -77,9 +30,20 @@ public static class ObjectHeaderMapper }; if (header.Split.Children.Count != 0) - model.Split.Children.AddRange(header.Split.Children.Select(x => x.ToModel())); + split.Children.AddRange(header.Split.Children.Select(x => x.ToModel())); } + var model = new FrostFsObjectHeader( + new FrostFsContainerId(Base58.Encode(header.ContainerId.Value.ToByteArray())), + objTypeName, + header.Attributes.Select(attribute => attribute.ToModel()).ToArray(), + split, + header.OwnerId.ToModel(), + header.Version.ToModel()) + { + PayloadLength = header.PayloadLength, + }; + return model; } } diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectId.cs b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectId.cs index c9afe0c..d20a915 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectId.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectId.cs @@ -1,12 +1,12 @@ using FrostFS.Refs; -using FrostFS.SDK.ModelsV2; + using Google.Protobuf; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; public static class ObjectIdMapper { - public static ObjectID ToMessage(this ObjectId objectId) + public static ObjectID ToMessage(this FrostFsObjectId objectId) { return new ObjectID { @@ -14,8 +14,8 @@ public static class ObjectIdMapper }; } - public static ObjectId ToModel(this ObjectID objectId) + public static FrostFsObjectId ToModel(this ObjectID objectId) { - return ObjectId.FromHash(objectId.Value.ToByteArray()); + return FrostFsObjectId.FromHash(objectId.Value.ToByteArray()); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Mappers/OwnerId.cs b/src/FrostFS.SDK.ClientV2/Mappers/OwnerId.cs index de8db49..ff81321 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/OwnerId.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/OwnerId.cs @@ -1,9 +1,11 @@ +using System; + using FrostFS.Refs; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; + using Google.Protobuf; + using Microsoft.Extensions.Caching.Memory; -using System; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; @@ -13,7 +15,7 @@ public static class OwnerIdMapper .SetSlidingExpiration(TimeSpan.FromHours(1)) .SetSize(1); - public static OwnerID ToMessage(this OwnerId model) + public static OwnerID ToMessage(this FrostFsOwner model) { if (!Cache.Owners.TryGetValue(model, out OwnerID? message)) { @@ -28,11 +30,11 @@ public static class OwnerIdMapper return message!; } - public static OwnerId ToModel(this OwnerID message) + public static FrostFsOwner ToModel(this OwnerID message) { - if (!Cache.Owners.TryGetValue(message, out OwnerId? model)) + if (!Cache.Owners.TryGetValue(message, out FrostFsOwner? model)) { - model = new OwnerId(Base58.Encode(message.Value.ToByteArray())); + model = new FrostFsOwner(Base58.Encode(message.Value.ToByteArray())); Cache.Owners.Set(message, model, _oneHourExpiration); } diff --git a/src/FrostFS.SDK.ClientV2/Mappers/SignatureMapper.cs b/src/FrostFS.SDK.ClientV2/Mappers/SignatureMapper.cs index 4343d4d..0b280cf 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/SignatureMapper.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/SignatureMapper.cs @@ -1,12 +1,12 @@ using System; -using FrostFS.SDK.ModelsV2; + using Google.Protobuf; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; public static class SignatureMapper { - public static Refs.Signature ToMessage(this Signature signature) + public static Refs.Signature ToMessage(this FrostFsSignature signature) { var scheme = signature.Scheme switch { diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Status.cs b/src/FrostFS.SDK.ClientV2/Mappers/Status.cs index d489239..d3555ac 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Status.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Status.cs @@ -1,19 +1,18 @@ using System; -using FrostFS.SDK.ModelsV2.Enums; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; public static class StatusMapper { - public static ModelsV2.ResponseStatus ToModel(this Status.Status status) + public static FrostFsResponseStatus ToModel(this Status.Status status) { if (status is null) - return new ModelsV2.ResponseStatus(StatusCode.Success); + return new FrostFsResponseStatus(FrostFsStatusCode.Success); + + var codeName = Enum.GetName(typeof(FrostFsStatusCode), status.Code); - var codeName = Enum.GetName(typeof(StatusCode), status.Code); - return codeName is null ? throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'.") - : new ModelsV2.ResponseStatus((StatusCode)Enum.Parse(typeof(StatusCode), codeName), status.Message); + : new FrostFsResponseStatus((FrostFsStatusCode)status.Code, status.Message); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Version.cs b/src/FrostFS.SDK.ClientV2/Mappers/Version.cs index df2066c..f17509a 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Version.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Version.cs @@ -1,6 +1,7 @@ using System.Collections; using System.Threading; -using Version = FrostFS.Refs.Version; + +using FrostFS.Refs; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; @@ -10,7 +11,7 @@ public static class VersionMapper private static readonly Hashtable _cacheModels = []; private static SpinLock _spinlock = new(); - public static Version ToMessage(this ModelsV2.Version model) + public static Version ToMessage(this FrostFsVersion model) { var key = model.Major << 16 + model.Minor; @@ -31,7 +32,7 @@ public static class VersionMapper } catch (System.ArgumentException) { - // ignore attempt to add duplicate error. + // ignore attempt to add duplicate } finally { @@ -43,7 +44,7 @@ public static class VersionMapper return (Version)_cacheMessages[key]; } - public static ModelsV2.Version ToModel(this Version message) + public static FrostFsVersion ToModel(this Version message) { var key = (int)message.Major << 16 + (int)message.Minor; @@ -53,14 +54,14 @@ public static class VersionMapper try { _spinlock.Enter(ref lockTaken); - var model = new ModelsV2.Version((int)message.Major, (int)message.Minor); + var model = new FrostFsVersion((int)message.Major, (int)message.Minor); _cacheModels.Add(key, model); return model; } catch (System.ArgumentException) { - // ignore attempt to add duplicate error. + // ignore attempt to add duplicate } finally { @@ -69,6 +70,6 @@ public static class VersionMapper } } - return (ModelsV2.Version)_cacheModels[key]; + return (FrostFsVersion)_cacheModels[key]; } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Client/ClientSettings.cs b/src/FrostFS.SDK.ClientV2/Models/Client/ClientSettings.cs new file mode 100644 index 0000000..650c7d6 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Client/ClientSettings.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FrostFS.SDK; + +public class ClientSettings +{ + protected static readonly string errorTemplate = "{0} is required parameter"; + + public string Host { get; set; } = string.Empty; + + public virtual void Validate() + { + var errors = CheckFields(); + if (errors != null) + ThrowException(errors); + } + + protected List? CheckFields() + { + List? errors = null; + + if (string.IsNullOrWhiteSpace(Host)) + (errors ??= []).Add(string.Format(errorTemplate, nameof(Host))); + + return errors; + } + + protected static void ThrowException(List errors) + { + StringBuilder messages = new(); + + foreach (var error in errors) + { + messages.AppendLine(error); + } + + throw new ArgumentException(messages.ToString()); + } +} + +public class SingleOwnerClientSettings : ClientSettings +{ + public string Key { get; set; } = string.Empty; + + public override void Validate() + { + var errors = CheckFields(); + if (errors != null) + ThrowException(errors); + } + + protected new List? CheckFields() + { + List? errors = base.CheckFields(); + + if (string.IsNullOrWhiteSpace(Key)) + (errors ??= []).Add(string.Format(errorTemplate, nameof(Key))); + + return errors; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerId.cs b/src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerId.cs new file mode 100644 index 0000000..895f25a --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerId.cs @@ -0,0 +1,62 @@ +using FrostFS.Refs; +using FrostFS.SDK.Cryptography; + +using FrostFS.SDK.ClientV2.Mappers.GRPC; +using FrostFS.SDK.ClientV2; + +namespace FrostFS.SDK; + +public class FrostFsContainerId +{ + private string? modelId; + private ContainerID? containerID; + + public FrostFsContainerId(string id) + { + this.modelId = id; + } + + internal FrostFsContainerId(ContainerID id) + { + this.containerID = id; + } + + public string Value + { + get + { + if (this.modelId != null) + return this.modelId; + + if (containerID != null) + { + this.modelId = Base58.Encode(containerID.Value.ToByteArray()); + return this.modelId; + } + + throw new InvalidObjectException(); + } + } + + internal ContainerID ContainerID + { + get + { + if (this.containerID != null) + return this.containerID; + + if (modelId != null) + { + this.containerID = this.ToMessage(); + return this.containerID; + } + + throw new InvalidObjectException(); + } + } + + public override string ToString() + { + return Value; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerInfo.cs b/src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerInfo.cs new file mode 100644 index 0000000..4a4d140 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Containers/FrostFsContainerInfo.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using FrostFS.SDK.ClientV2; +using FrostFS.SDK.Cryptography; +using FrostFS.SDK.ClientV2.Mappers.GRPC; + +using Google.Protobuf; + +namespace FrostFS.SDK; + +public class FrostFsContainerInfo +{ + private Container.Container.Types.Attribute[]? grpsAttributes; + private List? attributes; + private FrostFsPlacementPolicy? placementPolicy; + private Guid? nonce; + + private Container.Container container; + + public FrostFsContainerInfo( + BasicAcl basicAcl, + FrostFsPlacementPolicy placementPolicy, + List? attributes = null, + FrostFsVersion? version = null, + FrostFsOwner? owner = null, + Guid? nonce = null) + { + BasicAcl = basicAcl; + this.placementPolicy = placementPolicy; + this.attributes = attributes; + Version = version; + Owner = owner; + this.nonce = nonce; + } + + internal FrostFsContainerInfo(Container.Container container) + { + this.container = container; + } + + public Guid Nonce + { + get + { + nonce ??= container?.Nonce != null ? container.Nonce.ToUuid() : Guid.NewGuid(); + return nonce.Value; + } + } + + public BasicAcl BasicAcl { get; private set; } + + public FrostFsPlacementPolicy? PlacementPolicy + { + get + { + placementPolicy ??= container.PlacementPolicy?.ToModel(); + return placementPolicy; + } + } + + public List? Attributes + { + get + { + if (attributes == null && grpsAttributes != null) + attributes = grpsAttributes.Select(a => new FrostFsAttribute(a.Key, a.Value)).ToList(); + + return attributes; + } + } + + public FrostFsVersion? Version { get; private set; } + + public FrostFsOwner? Owner { get; private set; } + + internal Container.Container.Types.Attribute[]? GetGrpsAttributes() + { + grpsAttributes ??= Attributes? + .Select(a => new Container.Container.Types.Attribute { Key = a.Key, Value = a.Value }) + .ToArray(); + + return grpsAttributes; + } + + internal Container.Container GetContainer() + { + if (this.container == null) + { + this.container = new Container.Container() + { + BasicAcl = (uint)BasicAcl, + PlacementPolicy = PlacementPolicy.ToMessage(), + Nonce = ByteString.CopyFrom(Nonce.ToBytes()), + OwnerId = Owner?.OwnerID, + Version = Version?.Version + }; + + var attribs = GetGrpsAttributes(); + if (attribs != null) + this.container.Attributes.AddRange(attribs); + } + + return this.container; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Enums/BasicAcl.cs b/src/FrostFS.SDK.ClientV2/Models/Enums/BasicAcl.cs new file mode 100644 index 0000000..dd3252b --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Enums/BasicAcl.cs @@ -0,0 +1,21 @@ +using System.ComponentModel; + +namespace FrostFS.SDK; + +public enum BasicAcl +{ + [Description("Not defined ACL")] + NotDefined = 0x00000000, + + [Description("Basic ACL for private container")] + Private = 0x1C8C8CCC, + + [Description("Basic ACL for public RO container")] + PublicRO = 0x1FBF8CFF, + + [Description("Basic ACL for public RW container")] + PublicRW = 0x1FBFBFFF, + + [Description("Basic ACL for public append container")] + PublicAppend = 0x1FBF9FFF, +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/ObjectMatchType.cs b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectMatchType.cs similarity index 59% rename from src/FrostFS.SDK.ModelsV2/Enums/ObjectMatchType.cs rename to src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectMatchType.cs index 4d6026c..1fdeb60 100644 --- a/src/FrostFS.SDK.ModelsV2/Enums/ObjectMatchType.cs +++ b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectMatchType.cs @@ -1,6 +1,6 @@ -namespace FrostFS.SDK.ModelsV2.Enums; +namespace FrostFS.SDK; -public enum ObjectMatchType +public enum FrostFsObjectMatchType { Unspecified = 0, Equals = 1, diff --git a/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectType.cs b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectType.cs new file mode 100644 index 0000000..793fe2e --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectType.cs @@ -0,0 +1,8 @@ +namespace FrostFS.SDK; + +public enum FrostFsObjectType +{ + Regular = 0, + Tombstone = 1, + Lock = 3 +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/StatusCode.cs b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsStatusCode.cs similarity index 88% rename from src/FrostFS.SDK.ModelsV2/Enums/StatusCode.cs rename to src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsStatusCode.cs index df0fa57..7eb185c 100644 --- a/src/FrostFS.SDK.ModelsV2/Enums/StatusCode.cs +++ b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsStatusCode.cs @@ -1,6 +1,6 @@ -namespace FrostFS.SDK.ModelsV2.Enums; +namespace FrostFS.SDK; -public enum StatusCode +public enum FrostFsStatusCode { Success = 0, Internal = 1024, diff --git a/src/FrostFS.SDK.ClientV2/Models/Enums/NodeState.cs b/src/FrostFS.SDK.ClientV2/Models/Enums/NodeState.cs new file mode 100644 index 0000000..2821e55 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Enums/NodeState.cs @@ -0,0 +1,9 @@ +namespace FrostFS.SDK; + +public enum NodeState +{ + Unspecified = 0, + Online = 1, + Offline = 2, + Maintenance = 3 +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Enums/SignatureScheme.cs b/src/FrostFS.SDK.ClientV2/Models/Enums/SignatureScheme.cs new file mode 100644 index 0000000..4b5634c --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Enums/SignatureScheme.cs @@ -0,0 +1,8 @@ +namespace FrostFS.SDK; + +public enum SignatureScheme +{ + EcdsaSha512, + EcdsaRfc6979Sha256, + EcdsaRfc6979Sha256WalletConnect +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Misc/CallStatistics.cs b/src/FrostFS.SDK.ClientV2/Models/Misc/CallStatistics.cs new file mode 100644 index 0000000..706b3f2 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Misc/CallStatistics.cs @@ -0,0 +1,7 @@ +namespace FrostFS.SDK; + +public class CallStatistics +{ + public string? MethodName { get; set; } + public long ElapsedMicroSeconds { get; set; } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Misc/CheckSum.cs b/src/FrostFS.SDK.ClientV2/Models/Misc/CheckSum.cs new file mode 100644 index 0000000..82017f9 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Misc/CheckSum.cs @@ -0,0 +1,20 @@ +using FrostFS.SDK.Cryptography; +using System; + +namespace FrostFS.SDK; + +public class CheckSum +{ + // type is always Sha256 + public byte[]? Hash { get; set; } + + public static CheckSum CreateCheckSum(byte[] content) + { + return new CheckSum { Hash = content.Sha256() }; + } + + public override string ToString() + { + return BitConverter.ToString(Hash).Replace("-", ""); + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Misc/Constants.cs b/src/FrostFS.SDK.ClientV2/Models/Misc/Constants.cs new file mode 100644 index 0000000..332a3e3 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Misc/Constants.cs @@ -0,0 +1,52 @@ +namespace FrostFS.SDK; + +public class Constants +{ + public const int ObjectChunkSize = 3 * (1 << 20); + public const int Sha256HashLength = 32; + + // HeaderPrefix is a prefix of key to object header value or property. + public const string HeaderPrefix = "$Object:"; + + // FilterHeaderVersion is a filter key to "version" field of the object header. + public const string FilterHeaderVersion = HeaderPrefix + "version"; + + // FilterHeaderObjectID is a filter key to "object_id" field of the object. + public const string FilterHeaderObjectID = HeaderPrefix + "objectID"; + + // FilterHeaderContainerID is a filter key to "container_id" field of the object header. + public const string FilterHeaderContainerID = HeaderPrefix + "containerID"; + + // FilterHeaderOwnerID is a filter key to "owner_id" field of the object header. + public const string FilterHeaderOwnerID = HeaderPrefix + "ownerID"; + + // FilterHeaderCreationEpoch is a filter key to "creation_epoch" field of the object header. + public const string FilterHeaderCreationEpoch = HeaderPrefix + "creationEpoch"; + + // FilterHeaderPayloadLength is a filter key to "payload_length" field of the object header. + public const string FilterHeaderPayloadLength = HeaderPrefix + "payloadLength"; + + // FilterHeaderPayloadHash is a filter key to "payload_hash" field of the object header. + public const string FilterHeaderPayloadHash = HeaderPrefix + "payloadHash"; + + // FilterHeaderObjectType is a filter key to "object_type" field of the object header. + public const string FilterHeaderObjectType = HeaderPrefix + "objectType"; + + // FilterHeaderHomomorphicHash is a filter key to "homomorphic_hash" field of the object header. + public const string FilterHeaderHomomorphicHash = HeaderPrefix + "homomorphicHash"; + + // FilterHeaderParent is a filter key to "split.parent" field of the object header. + public const string FilterHeaderParent = HeaderPrefix + "split.parent"; + + // FilterHeaderSplitID is a filter key to "split.splitID" field of the object header. + public const string FilterHeaderSplitID = HeaderPrefix + "split.splitID"; + + // FilterHeaderECParent is a filter key to "ec.parent" field of the object header. + public const string FilterHeaderECParent = HeaderPrefix + "ec.parent"; + + // FilterPropertyRoot is a filter key to check if regular object is on top of split hierarchy. + public const string FilterHeaderRoot = HeaderPrefix + "ROOT"; + + // FilterPropertyPhy is a filter key to check if an object physically stored on a node. + public const string FilterHeaderPhy = HeaderPrefix + "PHY"; +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNetmapSnapshot.cs b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNetmapSnapshot.cs new file mode 100644 index 0000000..3033ec6 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNetmapSnapshot.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace FrostFS.SDK; + +public class FrostFsNetmapSnapshot(ulong epoch, IReadOnlyList nodeInfoCollection) +{ + public ulong Epoch { get; private set; } = epoch; + + public IReadOnlyList NodeInfoCollection { get; private set; } = nodeInfoCollection; +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/NodeInfo.cs b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNodeInfo.cs similarity index 74% rename from src/FrostFS.SDK.ModelsV2/Netmap/NodeInfo.cs rename to src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNodeInfo.cs index 8fa4704..9581b21 100644 --- a/src/FrostFS.SDK.ModelsV2/Netmap/NodeInfo.cs +++ b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsNodeInfo.cs @@ -1,18 +1,17 @@ using System; using System.Collections.Generic; -using FrostFS.SDK.ModelsV2.Enums; -namespace FrostFS.SDK.ModelsV2.Netmap; +namespace FrostFS.SDK; -public class NodeInfo( - Version version, +public class FrostFsNodeInfo( + FrostFsVersion version, NodeState state, IReadOnlyCollection addresses, IReadOnlyDictionary attributes, ReadOnlyMemory publicKey) { public NodeState State { get; private set; } = state; - public Version Version { get; private set; } = version; + public FrostFsVersion Version { get; private set; } = version; public IReadOnlyCollection Addresses { get; private set; } = addresses; public IReadOnlyDictionary Attributes { get; private set; } = attributes; public ReadOnlyMemory PublicKey { get; private set; } = publicKey; diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsPlacementPolicy.cs similarity index 59% rename from src/FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs rename to src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsPlacementPolicy.cs index bb7b1a3..410598c 100644 --- a/src/FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs +++ b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsPlacementPolicy.cs @@ -1,16 +1,16 @@ using System; using System.Linq; -namespace FrostFS.SDK.ModelsV2.Netmap; +namespace FrostFS.SDK; -public class PlacementPolicy(bool unique, params Replica[] replicas) : IComparable +public class FrostFsPlacementPolicy(bool unique, params FrostFsReplica[] replicas) : IComparable { - public Replica[] Replicas { get; private set; } = replicas; + public FrostFsReplica[] Replicas { get; private set; } = replicas; public bool Unique { get; private set; } = unique; - public int CompareTo(PlacementPolicy other) + public int CompareTo(FrostFsPlacementPolicy other) { - var notEqual = other == null + var notEqual = other == null || Unique != other.Unique || Replicas.Length != other.Replicas.Length; diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/Replica.cs b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsReplica.cs similarity index 60% rename from src/FrostFS.SDK.ModelsV2/Netmap/Replica.cs rename to src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsReplica.cs index a6aeac9..8fd1bd9 100644 --- a/src/FrostFS.SDK.ModelsV2/Netmap/Replica.cs +++ b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsReplica.cs @@ -1,14 +1,14 @@ -namespace FrostFS.SDK.ModelsV2.Netmap; +namespace FrostFS.SDK; -public class Replica +public class FrostFsReplica { public int Count { get; set; } public string Selector { get; set; } - public Replica(int count, string? selector = null) + public FrostFsReplica(int count, string? selector = null) { selector ??= string.Empty; - + Count = count; Selector = selector; } diff --git a/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsVersion.cs b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsVersion.cs new file mode 100644 index 0000000..da66403 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Netmap/FrostFsVersion.cs @@ -0,0 +1,31 @@ +using FrostFS.Refs; +using FrostFS.SDK.ClientV2.Mappers.GRPC; + +namespace FrostFS.SDK; + +public class FrostFsVersion(int major, int minor) +{ + public Version version; + + public int Major { get; set; } = major; + public int Minor { get; set; } = minor; + + internal Version Version + { + get + { + this.version ??= this.ToMessage(); + return this.version; + } + } + + public bool IsSupported(FrostFsVersion version) + { + return Major == version.Major; + } + + public override string ToString() + { + return $"v{Major}.{Minor}"; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsAttribute.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsAttribute.cs new file mode 100644 index 0000000..8a69fd4 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsAttribute.cs @@ -0,0 +1,8 @@ +namespace FrostFS.SDK; + +public class FrostFsAttribute(string key, string value) +{ + public string Key { get; set; } = key; + + public string Value { get; set; } = value; +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLargeObject.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLargeObject.cs new file mode 100644 index 0000000..12a95c6 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLargeObject.cs @@ -0,0 +1,9 @@ +namespace FrostFS.SDK; + +public class FrostFsLargeObject(FrostFsContainerId container) : FrostFsObject(container) +{ + public ulong PayloadLength + { + get { return Header!.PayloadLength; } + } +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLinkObject.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLinkObject.cs new file mode 100644 index 0000000..5b9e349 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsLinkObject.cs @@ -0,0 +1,13 @@ +namespace FrostFS.SDK; + +public class FrostFsLinkObject : FrostFsObject +{ + public FrostFsLinkObject(FrostFsContainerId containerId, SplitId splitId, FrostFsObjectHeader largeObjectHeader) + : base(containerId) + { + Header!.Split = new FrostFsSplit(splitId) + { + ParentHeader = largeObjectHeader + }; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObject.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObject.cs new file mode 100644 index 0000000..5ee8b8e --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObject.cs @@ -0,0 +1,64 @@ +using System; + +namespace FrostFS.SDK; + +public class FrostFsObject +{ + /// + /// Creates new instance from ObjectHeader + /// + /// + public FrostFsObject(FrostFsObjectHeader header) + { + Header = header; + } + + /// + /// Creates new instance with specified parameters + /// + /// + /// + public FrostFsObject(FrostFsContainerId container, FrostFsObjectType objectType = FrostFsObjectType.Regular) + { + Header = new FrostFsObjectHeader(containerId: container, type: objectType); + } + + /// + /// Header contains metadata for the object + /// + /// + public FrostFsObjectHeader Header { get; set; } + + /// + /// The value is calculated internally as a hash of ObjectHeader. Do not use pre-calculated value is the object has been changed. + /// + public FrostFsObjectId? ObjectId + { + get; set; + } + + /// + /// The size of payload cannot exceed MaxObjectSize value from NetworkSettings + /// Used only for PutSingleObject method + /// + /// Buffer for output data + public byte[] Payload { get; set; } = []; + + /// + /// A payload is obtained via stream reader + /// + /// Reader for received data + public IObjectReader? ObjectReader { get; set; } + + /// + /// Applied only for the last Object in chain in case of manual multipart uploading + /// + /// Parent for multipart object + public void SetParent(FrostFsObjectHeader largeObjectHeader) + { + if (Header?.Split == null) + throw new Exception("The object is not initialized properly"); + + Header.Split.ParentHeader = largeObjectHeader; + } +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs new file mode 100644 index 0000000..e9552bf --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs @@ -0,0 +1,111 @@ +namespace FrostFS.SDK; + +public interface IObjectFilter +{ + public FrostFsObjectMatchType MatchType { get; set; } + public string Key { get; set; } + + string? GetSerializedValue(); +} + +public abstract class FrostFsObjectFilter(FrostFsObjectMatchType matchType, string key, T value) : IObjectFilter +{ + public FrostFsObjectMatchType MatchType { get; set; } = matchType; + public string Key { get; set; } = key; + + public T Value { get; set; } = value; + + public string? GetSerializedValue() + { + return Value?.ToString(); + } +} + +/// +/// Creates filter to search by Attribute +/// +/// Match type +/// Attribute key +/// Attribute value +public class FilterByAttribute(FrostFsObjectMatchType matchType, string key, string value) : FrostFsObjectFilter(matchType, key, value) { } + +/// +/// Creates filter to search by ObjectId +/// +/// Match type +/// ObjectId +public class FilterByObjectId(FrostFsObjectMatchType matchType, FrostFsObjectId objectId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderObjectID, objectId) { } + +/// +/// Creates filter to search by OwnerId +/// +/// Match type +/// ObjectId +public class FilterByOwnerId(FrostFsObjectMatchType matchType, FrostFsOwner ownerId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderOwnerID, ownerId) { } + +/// +/// Creates filter to search by Version +/// +/// Match type +/// Version +public class FilterByVersion(FrostFsObjectMatchType matchType, FrostFsVersion version) : FrostFsObjectFilter(matchType, Constants.FilterHeaderVersion, version) { } + +/// +/// Creates filter to search by ContainerId +/// +/// Match type +/// ContainerId +public class FilterByContainerId(FrostFsObjectMatchType matchType, FrostFsContainerId containerId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderContainerID, containerId) { } + +/// +/// Creates filter to search by creation Epoch +/// +/// Match type +/// Creation Epoch +public class FilterByEpoch(FrostFsObjectMatchType matchType, ulong epoch) : FrostFsObjectFilter(matchType, Constants.FilterHeaderCreationEpoch, epoch) { } + +/// +/// Creates filter to search by Payload Length +/// +/// Match type +/// Payload Length +public class FilterByPayloadLength(FrostFsObjectMatchType matchType, ulong payloadLength) : FrostFsObjectFilter(matchType, Constants.FilterHeaderPayloadLength, payloadLength) { } + +/// +/// Creates filter to search by Payload Hash +/// +/// Match type +/// Payload Hash +public class FilterByPayloadHash(FrostFsObjectMatchType matchType, CheckSum payloadHash) : FrostFsObjectFilter(matchType, Constants.FilterHeaderPayloadHash, payloadHash) { } + +/// +/// Creates filter to search by Parent +/// +/// Match type +/// Parent +public class FilterByParent(FrostFsObjectMatchType matchType, FrostFsObjectId parentId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderParent, parentId) { } + +/// +/// Creates filter to search by SplitId +/// +/// Match type +/// SplitId +public class FilterBySplitId(FrostFsObjectMatchType matchType, SplitId splitId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderSplitID, splitId) { } + +/// +/// Creates filter to search by Payload Hash +/// +/// Match type +/// Payload Hash +public class FilterByECParent(FrostFsObjectMatchType matchType, FrostFsObjectId ecParentId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderECParent, ecParentId) { } + +/// +/// Creates filter to search Root objects +/// +public class FilterByRootObject() : FrostFsObjectFilter(FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderRoot, string.Empty) { } + +/// +/// Creates filter to search objects that are physically stored on the server +/// (FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderPhy, string.Empty) { } + diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectHeader.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectHeader.cs new file mode 100644 index 0000000..e384ece --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectHeader.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using FrostFS.Object; + +using FrostFS.SDK.ClientV2.Mappers.GRPC; + +namespace FrostFS.SDK; + +public class FrostFsObjectHeader( + FrostFsContainerId containerId, + FrostFsObjectType type = FrostFsObjectType.Regular, + FrostFsAttribute[]? attributes = null, + FrostFsSplit? split = null, + FrostFsOwner? owner = null, + FrostFsVersion? version = null) +{ + private Header header; + private Container.Container.Types.Attribute[]? grpsAttributes; + + public List Attributes { get; internal set; } = attributes != null ? [.. attributes] : []; + + public FrostFsContainerId ContainerId { get; } = containerId; + + public ulong PayloadLength { get; set; } + + public byte[]? PayloadCheckSum { get; set; } + + public FrostFsObjectType ObjectType { get; } = type; + + public FrostFsOwner? OwnerId { get; internal set; } = owner; + + public FrostFsVersion? Version { get; internal set; } = version; + + public FrostFsSplit? Split { get; internal set; } = split; + + internal Container.Container.Types.Attribute[]? GetGrpsAttributes() + { + grpsAttributes ??= Attributes? + .Select(a => new Container.Container.Types.Attribute { Key = a.Key, Value = a.Value }) + .ToArray(); + + return grpsAttributes; + } + + public Header GetHeader() + { + if (header == null) + { + var objTypeName = ObjectType switch + { + FrostFsObjectType.Regular => Object.ObjectType.Regular, + FrostFsObjectType.Lock => Object.ObjectType.Lock, + FrostFsObjectType.Tombstone => Object.ObjectType.Tombstone, + _ => throw new ArgumentException($"Unknown ObjectType. Value: '{ObjectType}'.") + }; + + this.header = new Header + { + OwnerId = OwnerId?.ToMessage(), + Version = Version?.ToMessage(), + ContainerId = ContainerId.ToMessage(), + ObjectType = objTypeName, + PayloadLength = PayloadLength + }; + + foreach (var attribute in Attributes) + { + this.header.Attributes.Add(attribute.ToMessage()); + } + + var split = Split; + if (split != null) + { + this.header.Split = new Header.Types.Split + { + SplitId = split!.SplitId != null ? split.SplitId.GetSplitId() : null + }; + } + } + + return this.header; + } +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectId.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectId.cs new file mode 100644 index 0000000..4e4dbf0 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectId.cs @@ -0,0 +1,28 @@ +using System; + +using FrostFS.SDK.Cryptography; + +namespace FrostFS.SDK; + +public class FrostFsObjectId(string id) +{ + public string Value { get; } = id; + + public static FrostFsObjectId FromHash(byte[] hash) + { + if (hash.Length != Constants.Sha256HashLength) + throw new FormatException("ObjectID must be a sha256 hash."); + + return new FrostFsObjectId(Base58.Encode(hash)); + } + + public byte[] ToHash() + { + return Base58.Decode(Value); + } + + public override string ToString() + { + return Value; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsOwner.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsOwner.cs new file mode 100644 index 0000000..d249d80 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsOwner.cs @@ -0,0 +1,38 @@ +using System.Security.Cryptography; + +using FrostFS.Refs; +using FrostFS.SDK.ClientV2.Mappers.GRPC; +using FrostFS.SDK.Cryptography; + +namespace FrostFS.SDK; + +public class FrostFsOwner(string id) +{ + private OwnerID ownerID; + + public string Value { get; } = id; + + public static FrostFsOwner FromKey(ECDsa key) + { + return new FrostFsOwner(key.PublicKey().PublicKeyToAddress()); + } + + internal OwnerID OwnerID + { + get + { + ownerID ??= this.ToMessage(); + return ownerID; + } + } + + public byte[] ToHash() + { + return Base58.Decode(Value); + } + + public override string ToString() + { + return Value; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsSplit.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsSplit.cs new file mode 100644 index 0000000..947662f --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsSplit.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace FrostFS.SDK; + +public class FrostFsSplit(SplitId splitId) +{ + public FrostFsSplit() : this(new SplitId()) + { + } + + public SplitId SplitId { get; private set; } = splitId; + + public FrostFsObjectId? Parent { get; set; } + + public FrostFsObjectId? Previous { get; set; } + + public FrostFsSignature? ParentSignature { get; set; } + + public FrostFsObjectHeader? ParentHeader { get; set; } + + public List Children { get; } = []; + + public Refs.Signature ParentSignatureGrpc { get; set; } +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/IObjectReader.cs b/src/FrostFS.SDK.ClientV2/Models/Object/IObjectReader.cs new file mode 100644 index 0000000..51211fd --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/IObjectReader.cs @@ -0,0 +1,10 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace FrostFS.SDK; + +public interface IObjectReader : IDisposable +{ + Task?> ReadChunk(CancellationToken cancellationToken = default); +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/SplitId.cs b/src/FrostFS.SDK.ClientV2/Models/Object/SplitId.cs new file mode 100644 index 0000000..bb8e617 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Object/SplitId.cs @@ -0,0 +1,62 @@ +using FrostFS.SDK.Cryptography; + +using Google.Protobuf; + +using System; + +namespace FrostFS.SDK; + +public class SplitId +{ + private readonly Guid id; + + private ByteString? _message; + + public SplitId() + { + id = Guid.NewGuid(); + } + + public SplitId(Guid guid) + { + id = guid; + } + + private SplitId(byte[] binary) + { + id = new Guid(binary); + } + + private SplitId(string str) + { + id = new Guid(str); + } + + public static SplitId CreateFromBinary(byte[] binaryData) + { + return new SplitId(binaryData); + } + + public static SplitId CreateFromString(string stringData) + { + return new SplitId(stringData); + } + + public override string ToString() + { + return id.ToString(); + } + + public byte[]? ToBinary() + { + if (id == Guid.Empty) + return null; + + return id.ToBytes(); + } + + public ByteString? GetSplitId() + { + return _message ??= ByteString.CopyFrom(ToBinary()); + } +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Response/FrostFsResponseStatus.cs b/src/FrostFS.SDK.ClientV2/Models/Response/FrostFsResponseStatus.cs new file mode 100644 index 0000000..b5e5831 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Response/FrostFsResponseStatus.cs @@ -0,0 +1,14 @@ +namespace FrostFS.SDK; + +public class FrostFsResponseStatus(FrostFsStatusCode code, string? message = null) +{ + public FrostFsStatusCode Code { get; set; } = code; + public string Message { get; set; } = message ?? string.Empty; + + public bool IsSuccess => Code == FrostFsStatusCode.Success; + + public override string ToString() + { + return $"Response status: {Code}. Message: {Message}."; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Response/FrostFsSignature.cs b/src/FrostFS.SDK.ClientV2/Models/Response/FrostFsSignature.cs new file mode 100644 index 0000000..d7ca6b6 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Response/FrostFsSignature.cs @@ -0,0 +1,10 @@ +namespace FrostFS.SDK; + +public class FrostFsSignature +{ + public byte[]? Key { get; set; } + + public byte[]? Sign { get; set; } + + public SignatureScheme Scheme { get; set; } +} diff --git a/src/FrostFS.SDK.ClientV2/Models/Response/MetaHeader.cs b/src/FrostFS.SDK.ClientV2/Models/Response/MetaHeader.cs new file mode 100644 index 0000000..36dad09 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Response/MetaHeader.cs @@ -0,0 +1,20 @@ +namespace FrostFS.SDK; + +public class MetaHeader(FrostFsVersion version, int epoch, int ttl) +{ + public FrostFsVersion Version { get; set; } = version; + public int Epoch { get; set; } = epoch; + public int Ttl { get; set; } = ttl; + + public static MetaHeader Default() + { + return new MetaHeader( + new FrostFsVersion( + major: 2, + minor: 13 + ), + epoch: 0, + ttl: 2 + ); + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Models/Session/FrostFsSessionToken.cs b/src/FrostFS.SDK.ClientV2/Models/Session/FrostFsSessionToken.cs new file mode 100644 index 0000000..8954780 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Models/Session/FrostFsSessionToken.cs @@ -0,0 +1,6 @@ +namespace FrostFS.SDK; + +public class FrostFsSessionToken(byte[] token) +{ + public byte[] Token { get; private set; } = token; +} diff --git a/src/FrostFS.SDK.ClientV2/Parameters/Context.cs b/src/FrostFS.SDK.ClientV2/Parameters/Context.cs index ca3728a..f1704a9 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/Context.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/Context.cs @@ -2,9 +2,11 @@ using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Threading; -using FrostFS.SDK.ModelsV2; + using FrostFS.SDK.Cryptography; + using Google.Protobuf; + using Grpc.Core.Interceptors; namespace FrostFS.SDK.ClientV2; @@ -13,13 +15,13 @@ public class Context() { private List? interceptors; - private ByteString publicKeyCache; + private ByteString? publicKeyCache; public ECDsa Key { get; set; } - public OwnerId OwnerId { get; set; } + public FrostFsOwner OwnerId { get; set; } - public ModelsV2.Version Version { get; set; } + public FrostFsVersion Version { get; set; } public CancellationToken CancellationToken { get; set; } = default; @@ -35,16 +37,13 @@ public class Context() set { this.interceptors = value; } } - public ByteString PublicKeyCache + public ByteString? GetPublicKeyCache() { - get + if (publicKeyCache == null && Key != null) { - if (publicKeyCache == null) - { - publicKeyCache = ByteString.CopyFrom(Key.PublicKey()); - } - - return publicKeyCache; + publicKeyCache = ByteString.CopyFrom(Key.PublicKey()); } + + return publicKeyCache; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/Credentials.cs b/src/FrostFS.SDK.ClientV2/Parameters/Credentials.cs index a4915c3..ebc7558 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/Credentials.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/Credentials.cs @@ -1,11 +1,10 @@ -using FrostFS.SDK.ModelsV2; -using System.Security.Cryptography; +using System.Security.Cryptography; -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; -public class Credentials(ECDsa key, OwnerId ownerId) +public class Credentials(ECDsa key, FrostFsOwner ownerId) { public ECDsa Key { get; } = key; - public OwnerId OwnerId { get; } = ownerId; + public FrostFsOwner OwnerId { get; } = ownerId; } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/IContext.cs b/src/FrostFS.SDK.ClientV2/Parameters/IContext.cs index c48dc8a..bd333f7 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/IContext.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/IContext.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public interface IContext { diff --git a/src/FrostFS.SDK.ClientV2/Parameters/ISessionToken.cs b/src/FrostFS.SDK.ClientV2/Parameters/ISessionToken.cs index c5ac1da..cc3ed0f 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/ISessionToken.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/ISessionToken.cs @@ -1,6 +1,4 @@ -using FrostFS.SDK.ModelsV2; - -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public interface ISessionToken { @@ -10,5 +8,5 @@ public interface ISessionToken /// member. The session has a limited validity period, and applies to a strictly defined set of operations. /// /// Instance of the session obtained from the server - SessionToken? SessionToken { get; set; } + FrostFsSessionToken? SessionToken { get; set; } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmBase.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmBase.cs index 09ca363..1aedefe 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmBase.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmBase.cs @@ -1,6 +1,6 @@ using System.Collections.Specialized; -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public class PrmBase() : IContext { diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerCreate.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerCreate.cs index a2a3315..01f87a8 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerCreate.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerCreate.cs @@ -1,11 +1,8 @@ -using FrostFS.SDK.ModelsV2; -using System.Security.Cryptography; +namespace FrostFS.SDK.ClientV2; -namespace FrostFS.SDK.ClientV2.Parameters; - -public sealed class PrmContainerCreate(ModelsV2.Container container) : PrmBase, ISessionToken +public sealed class PrmContainerCreate(FrostFsContainerInfo container) : PrmBase, ISessionToken { - public ModelsV2.Container Container { get; set; } = container; + public FrostFsContainerInfo Container { get; set; } = container; /// /// Since the container becomes available with some delay, it needs to poll the container status @@ -16,5 +13,5 @@ public sealed class PrmContainerCreate(ModelsV2.Container container) : PrmBase, /// /// Blank session token /// - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerDelete.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerDelete.cs index 63308aa..c97e80f 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerDelete.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerDelete.cs @@ -1,10 +1,8 @@ -using FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK.ClientV2; -namespace FrostFS.SDK.ClientV2.Parameters; - -public sealed class PrmContainerDelete(ContainerId containerId) : PrmBase, ISessionToken +public sealed class PrmContainerDelete(FrostFsContainerId containerId) : PrmBase, ISessionToken { - public ContainerId ContainerId { get; set; } = containerId; + public FrostFsContainerId ContainerId { get; set; } = containerId; /// /// Since the container is removed with some delay, it needs to poll the container status @@ -12,5 +10,5 @@ public sealed class PrmContainerDelete(ContainerId containerId) : PrmBase, ISess /// Rules for polling the result public PrmWait? WaitParams { get; set; } - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGet.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGet.cs index cebdaca..f0c734b 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGet.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGet.cs @@ -1,8 +1,6 @@ -using FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK.ClientV2; -namespace FrostFS.SDK.ClientV2.Parameters; - -public sealed class PrmContainerGet(ContainerId containerId) : PrmBase +public sealed class PrmContainerGet(FrostFsContainerId container) : PrmBase { - public ContainerId ContainerId { get; set; } = containerId; + public FrostFsContainerId Container { get; set; } = container; } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGetAll.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGetAll.cs index b365188..b7d3980 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGetAll.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmContainerGetAll.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public sealed class PrmContainerGetAll() : PrmBase() { diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmNetmapSnapshot.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmNetmapSnapshot.cs index e8387dc..f129109 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmNetmapSnapshot.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmNetmapSnapshot.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public sealed class PrmNetmapSnapshot() : PrmBase { diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmNetworkSettings.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmNetworkSettings.cs index c82db6e..3e82ff5 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmNetworkSettings.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmNetworkSettings.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public sealed class PrmNetworkSettings() : PrmBase { diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmNodeInfo.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmNodeInfo.cs index 2b3b661..7a3d1dc 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmNodeInfo.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmNodeInfo.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public sealed class PrmNodeInfo() : PrmBase { diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectDelete.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectDelete.cs index 3195bb8..f1dad65 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectDelete.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectDelete.cs @@ -1,13 +1,11 @@ -using FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK.ClientV2; -namespace FrostFS.SDK.ClientV2.Parameters; - -public sealed class PrmObjectDelete(ContainerId containerId, ObjectId objectId) : PrmBase, ISessionToken +public sealed class PrmObjectDelete(FrostFsContainerId containerId, FrostFsObjectId objectId) : PrmBase, ISessionToken { - public ContainerId ContainerId { get; set; } = containerId; + public FrostFsContainerId ContainerId { get; set; } = containerId; - public ObjectId ObjectId { get; set; } = objectId; + public FrostFsObjectId ObjectId { get; set; } = objectId; /// - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectGet.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectGet.cs index 07e717f..81a1e2f 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectGet.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectGet.cs @@ -1,13 +1,11 @@ -using FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK.ClientV2; -namespace FrostFS.SDK.ClientV2.Parameters; - -public sealed class PrmObjectGet(ContainerId containerId, ObjectId objectId) : PrmBase, ISessionToken +public sealed class PrmObjectGet(FrostFsContainerId containerId, FrostFsObjectId objectId) : PrmBase, ISessionToken { - public ContainerId ContainerId { get; set; } = containerId; + public FrostFsContainerId ContainerId { get; set; } = containerId; - public ObjectId ObjectId { get; set; } = objectId; + public FrostFsObjectId ObjectId { get; set; } = objectId; /// - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectHeadGet.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectHeadGet.cs index f5a9b77..67919aa 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectHeadGet.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectHeadGet.cs @@ -1,13 +1,11 @@ -using FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK.ClientV2; -namespace FrostFS.SDK.ClientV2.Parameters; - -public sealed class PrmObjectHeadGet(ContainerId containerId, ObjectId objectId) : PrmBase, ISessionToken +public sealed class PrmObjectHeadGet(FrostFsContainerId containerId, FrostFsObjectId objectId) : PrmBase, ISessionToken { - public ContainerId ContainerId { get; set; } = containerId; + public FrostFsContainerId ContainerId { get; set; } = containerId; - public ObjectId ObjectId { get; set; } = objectId; + public FrostFsObjectId ObjectId { get; set; } = objectId; /// - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectPut.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectPut.cs index e2c7a51..0be09e8 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectPut.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectPut.cs @@ -1,7 +1,6 @@ using System.IO; -using FrostFS.SDK.ModelsV2; -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public sealed class PrmObjectPut : PrmBase, ISessionToken { @@ -10,7 +9,7 @@ public sealed class PrmObjectPut : PrmBase, ISessionToken /// Optional parameters ike Attributes can be provided as well. /// /// Header with required parameters to create an object - public ObjectHeader? Header { get; set; } + public FrostFsObjectHeader? Header { get; set; } /// /// A stream with source data @@ -37,7 +36,7 @@ public sealed class PrmObjectPut : PrmBase, ISessionToken public byte[]? CustomBuffer { get; set; } /// - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } internal int MaxObjectSizeCache { get; set; } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectSearch.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectSearch.cs index 778b4a0..a9310dd 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectSearch.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmObjectSearch.cs @@ -1,14 +1,14 @@ -using FrostFS.SDK.ModelsV2; -using System.Collections.Generic; -namespace FrostFS.SDK.ClientV2.Parameters; +using System.Collections.Generic; -public sealed class PrmObjectSearch(ContainerId containerId, params IObjectFilter[] filters) : PrmBase, ISessionToken +namespace FrostFS.SDK.ClientV2; + +public sealed class PrmObjectSearch(FrostFsContainerId containerId, params IObjectFilter[] filters) : PrmBase, ISessionToken { /// /// Defines container for the search /// /// - public ContainerId ContainerId { get; set; } = containerId; + public FrostFsContainerId ContainerId { get; set; } = containerId; /// /// Defines the search criteria @@ -17,5 +17,5 @@ public sealed class PrmObjectSearch(ContainerId containerId, params IObjectFilte public IEnumerable Filters { get; set; } = filters; /// - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmSessionCreate.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmSessionCreate.cs index 2afc76f..d7bcdb6 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmSessionCreate.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmSessionCreate.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public sealed class PrmSessionCreate(ulong expiration) : PrmBase { diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmSingleObjectPut.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmSingleObjectPut.cs index fc22bf7..3a8fa5d 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmSingleObjectPut.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmSingleObjectPut.cs @@ -1,11 +1,9 @@ -using FrostFS.SDK.ModelsV2; - -namespace FrostFS.SDK.ClientV2.Parameters; +namespace FrostFS.SDK.ClientV2; public sealed class PrmSingleObjectPut(FrostFsObject frostFsObject) : PrmBase, ISessionToken { public FrostFsObject FrostFsObject { get; set; } = frostFsObject; /// - public SessionToken? SessionToken { get; set; } + public FrostFsSessionToken? SessionToken { get; set; } } diff --git a/src/FrostFS.SDK.ClientV2/Parameters/PrmWait.cs b/src/FrostFS.SDK.ClientV2/Parameters/PrmWait.cs index 86e32d7..d914719 100644 --- a/src/FrostFS.SDK.ClientV2/Parameters/PrmWait.cs +++ b/src/FrostFS.SDK.ClientV2/Parameters/PrmWait.cs @@ -1,5 +1,6 @@ using System; -namespace FrostFS.SDK.ClientV2.Parameters; + +namespace FrostFS.SDK.ClientV2; public class PrmWait(TimeSpan timeout, TimeSpan pollInterval) { diff --git a/src/FrostFS.SDK.ClientV2/Services/ContainerServiceProvider.cs b/src/FrostFS.SDK.ClientV2/Services/ContainerServiceProvider.cs index 5811a3b..d959a5c 100644 --- a/src/FrostFS.SDK.ClientV2/Services/ContainerServiceProvider.cs +++ b/src/FrostFS.SDK.ClientV2/Services/ContainerServiceProvider.cs @@ -3,12 +3,11 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Threading.Tasks; -using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; +using FrostFS.SDK.ClientV2; using FrostFS.Container; using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ClientV2.Parameters; +using FrostFS.SDK.ClientV2; using FrostFS.Refs; using FrostFS.Session; @@ -18,14 +17,14 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient { readonly SessionProvider sessions = new(context); - public async ValueTask GetOrCreateSession(ISessionToken args, Context ctx) + public async ValueTask GetOrCreateSession(ISessionToken args, Context ctx) { return await sessions.GetOrCreateSession(args, ctx); } - internal async Task GetContainerAsync(PrmContainerGet args) + internal async Task GetContainerAsync(PrmContainerGet args) { - GetRequest request = GetContainerRequest(args.ContainerId.ToMessage(), args.XHeaders, args.Context!); + GetRequest request = GetContainerRequest(args.Container.ContainerID, args.XHeaders, args.Context!); var response = await service.GetAsync(request, null, args.Context!.Deadline, args.Context.CancellationToken); @@ -34,15 +33,15 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient return response.Body.Container.ToModel(); } - internal async IAsyncEnumerable ListContainersAsync(PrmContainerGetAll args) + internal async IAsyncEnumerable ListContainersAsync(PrmContainerGetAll args) { var ctx = args.Context!; var request = new ListRequest { - Body = new ListRequest.Types.Body + Body = new () { - OwnerId = ctx.OwnerId.ToMessage() + OwnerId = ctx.OwnerId.ToMessage() } }; @@ -55,16 +54,18 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient foreach (var cid in response.Body.ContainerIds) { - yield return new ContainerId(Base58.Encode(cid.Value.ToByteArray())); + yield return new FrostFsContainerId(Base58.Encode(cid.Value.ToByteArray())); } } - internal async Task CreateContainerAsync(PrmContainerCreate args) + internal async Task CreateContainerAsync(PrmContainerCreate args) { var ctx = args.Context!; - var grpcContainer = args.Container.ToMessage(); - grpcContainer.OwnerId = ctx.OwnerId.ToMessage(); - grpcContainer.Version = ctx.Version.ToMessage(); + + var grpcContainer = args.Container.GetContainer(); + + grpcContainer.OwnerId ??= ctx.OwnerId.ToMessage(); + grpcContainer.Version ??= ctx.Version.ToMessage(); var request = new PutRequest { @@ -81,9 +82,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient null, ContainerSessionContext.Types.Verb.Put, ctx.Key, - ctx.PublicKeyCache); - - var v = sessionToken.Body.OwnerId == grpcContainer.OwnerId; + ctx.GetPublicKeyCache()); request.AddMetaHeader(args.XHeaders, sessionToken); @@ -95,7 +94,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient await WaitForContainer(WaitExpects.Exists, response.Body.ContainerId, args.WaitParams, ctx); - return new ContainerId(Base58.Encode(response.Body.ContainerId.Value.ToByteArray())); + return new FrostFsContainerId(response.Body.ContainerId); } internal async Task DeleteContainerAsync(PrmContainerDelete args) @@ -116,7 +115,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient request.Body.ContainerId, ContainerSessionContext.Types.Verb.Delete, ctx.Key, - ctx.PublicKeyCache); + ctx.GetPublicKeyCache()); request.AddMetaHeader(args.XHeaders, sessionToken); @@ -193,7 +192,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient if (DateTime.UtcNow >= deadLine) throw new TimeoutException(); - if (ex.Status.Code != ModelsV2.Enums.StatusCode.ContainerNotFound) + if (ex.Status.Code != FrostFsStatusCode.ContainerNotFound) throw; if (expect == WaitExpects.Removed) diff --git a/src/FrostFS.SDK.ClientV2/Services/NetmapServiceProvider.cs b/src/FrostFS.SDK.ClientV2/Services/NetmapServiceProvider.cs index 60c7e1f..98523ac 100644 --- a/src/FrostFS.SDK.ClientV2/Services/NetmapServiceProvider.cs +++ b/src/FrostFS.SDK.ClientV2/Services/NetmapServiceProvider.cs @@ -1,13 +1,11 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using FrostFS.Netmap; -using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; -using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo; -using FrostFS.SDK.ModelsV2.Netmap; +using FrostFS.Netmap; +using FrostFS.SDK.ClientV2; + using static FrostFS.Netmap.NetworkConfig.Types; -using FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2; @@ -40,7 +38,7 @@ internal class NetmapServiceProvider : ContextAccessor return settings; } - internal async Task GetLocalNodeInfoAsync(PrmNodeInfo args) + internal async Task GetLocalNodeInfoAsync(PrmNodeInfo args) { var ctx = args.Context!; var request = new LocalNodeInfoRequest @@ -72,7 +70,7 @@ internal class NetmapServiceProvider : ContextAccessor return response; } - internal async Task GetNetmapSnapshotAsync(PrmNetmapSnapshot args) + internal async Task GetNetmapSnapshotAsync(PrmNetmapSnapshot args) { var ctx = args.Context!; diff --git a/src/FrostFS.SDK.ClientV2/Services/ObjectServiceProvider.cs b/src/FrostFS.SDK.ClientV2/Services/ObjectServiceProvider.cs index 95106b7..bf8acf2 100644 --- a/src/FrostFS.SDK.ClientV2/Services/ObjectServiceProvider.cs +++ b/src/FrostFS.SDK.ClientV2/Services/ObjectServiceProvider.cs @@ -1,23 +1,23 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Google.Protobuf; - using FrostFS.Object; using FrostFS.Refs; +using FrostFS.SDK.ClientV2.Extensions; using FrostFS.SDK.ClientV2.Mappers.GRPC; +using FrostFS.SDK.ClientV2; using FrostFS.SDK.Cryptography; using FrostFS.Session; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ClientV2.Extensions; -using FrostFS.SDK.ClientV2.Parameters; -using System.Buffers; + +using Google.Protobuf; namespace FrostFS.SDK.ClientV2; -internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, ClientEnvironment env) : ContextAccessor(env), ISessionProvider +internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, ClientEnvironment env) + : ContextAccessor(env), ISessionProvider { readonly SessionProvider sessions = new (env); @@ -26,16 +26,17 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C return await sessions.GetOrCreateSession(args, ctx); } - internal async Task GetObjectHeadAsync(PrmObjectHeadGet args) + internal async Task GetObjectHeadAsync(PrmObjectHeadGet args) { var ctx = args.Context!; + var request = new HeadRequest { Body = new HeadRequest.Types.Body { Address = new Address { - ContainerId = args.ContainerId.ToMessage(), + ContainerId = args.ContainerId.ContainerID, ObjectId = args.ObjectId.ToMessage() } } @@ -119,7 +120,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C Verifier.CheckResponse(response); } - internal async IAsyncEnumerable SearchObjectsAsync(PrmObjectSearch args) + internal async IAsyncEnumerable SearchObjectsAsync(PrmObjectSearch args) { var ctx = args.Context!; var request = new SearchRequest @@ -149,11 +150,11 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C await foreach (var oid in objectsIds) { - yield return ObjectId.FromHash(oid.Value.ToByteArray()); + yield return FrostFsObjectId.FromHash(oid.Value.ToByteArray()); } } - internal async Task PutObjectAsync(PrmObjectPut args) + internal async Task PutObjectAsync(PrmObjectPut args) { if (args.Header == null) throw new ArgumentException("Value cannot be null", nameof(args.Header)); @@ -174,17 +175,14 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C } } - internal async Task PutSingleObjectAsync(PrmSingleObjectPut args) + internal async Task PutSingleObjectAsync(PrmSingleObjectPut args) { var ctx = args.Context!; var grpcObject = ObjectTools.CreateObject(args.FrostFsObject, ctx); var request = new PutSingleRequest { - Body = new PutSingleRequest.Types.Body() - { - Object = grpcObject - } + Body = new () { Object = grpcObject } }; var sessionToken = await GetOrCreateSession(args, ctx); @@ -202,15 +200,15 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C Verifier.CheckResponse(response); - return ObjectId.FromHash(grpcObject.ObjectId.Value.ToByteArray()); + return FrostFsObjectId.FromHash(grpcObject.ObjectId.Value.ToByteArray()); } - private async Task PutClientCutObject(PrmObjectPut args) + private async Task PutClientCutObject(PrmObjectPut args) { var ctx = args.Context!; var tokenRaw = await GetOrCreateSession(args, ctx); - var token = new ModelsV2.SessionToken(tokenRaw.Serialize()); + var token = new FrostFsSessionToken(tokenRaw.Serialize()); args.SessionToken = token; @@ -237,9 +235,9 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C var restPart = (restBytes % (ulong)objectSize) > 0 ? 1 : 0; var objectsCount = fullLength > 0 ? (int)(restBytes / (ulong)objectSize) + restPart : 0; - List sentObjectIds = new(objectsCount); + List sentObjectIds = new(objectsCount); - Split? split = null; + FrostFsSplit? split = null; // keep attributes for the large object var attributes = args.Header!.Attributes; @@ -249,7 +247,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C { if (split == null) { - split = new Split(); + split = new FrostFsSplit(); args.Header!.Attributes = []; } @@ -266,7 +264,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C // send the last part and create linkObject if (sentObjectIds.Count > 0) { - var largeObjectHeader = new ObjectHeader(header.ContainerId) { PayloadLength = fullLength }; + var largeObjectHeader = new FrostFsObjectHeader(header.ContainerId) { PayloadLength = fullLength }; largeObjectHeader.Attributes.AddRange(attributes); @@ -276,7 +274,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C sentObjectIds.Add(result.ObjectId); - var linkObject = new LinkObject(header.ContainerId, split!.SplitId, largeObjectHeader) + var linkObject = new FrostFsLinkObject(header.ContainerId, split!.SplitId, largeObjectHeader) .AddChildren(sentObjectIds); _ = await PutSingleObjectAsync(new PrmSingleObjectPut(linkObject) { Context = args.Context}); @@ -290,9 +288,9 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C return singlePartResult.ObjectId; } - struct PutObjectResult(ObjectId objectId, int objectSize) + struct PutObjectResult(FrostFsObjectId objectId, int objectSize) { - public ObjectId ObjectId = objectId; + public FrostFsObjectId ObjectId = objectId; public int ObjectSize = objectSize; } @@ -359,7 +357,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C var response = await stream.Close(); Verifier.CheckResponse(response); - return new PutObjectResult(ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray()), sentBytes); + return new PutObjectResult(FrostFsObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray()), sentBytes); } finally { @@ -374,10 +372,10 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C { var header = args.Header!; - header.OwnerId = ctx.OwnerId; - header.Version = ctx.Version; + header.OwnerId ??= ctx.OwnerId; + header.Version ??= ctx.Version; - var grpcHeader = header.ToMessage(); + var grpcHeader = header.GetHeader(); if (header.Split != null) { diff --git a/src/FrostFS.SDK.ClientV2/Services/SessionServiceProvider.cs b/src/FrostFS.SDK.ClientV2/Services/SessionServiceProvider.cs index 104fa4c..4498b3c 100644 --- a/src/FrostFS.SDK.ClientV2/Services/SessionServiceProvider.cs +++ b/src/FrostFS.SDK.ClientV2/Services/SessionServiceProvider.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; + using FrostFS.SDK.ClientV2.Mappers.GRPC; -using FrostFS.SDK.ClientV2.Parameters; +using FrostFS.SDK.ClientV2; using FrostFS.Session; namespace FrostFS.SDK.ClientV2; diff --git a/src/FrostFS.SDK.ClientV2/Services/Shared/ContextAccessor.cs b/src/FrostFS.SDK.ClientV2/Services/Shared/ContextAccessor.cs index 75edcc6..05797de 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Shared/ContextAccessor.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Shared/ContextAccessor.cs @@ -4,5 +4,3 @@ internal class ContextAccessor(ClientEnvironment context) { protected ClientEnvironment Context { get; set; } = context; } - - diff --git a/src/FrostFS.SDK.ClientV2/Services/Shared/SessionProvider.cs b/src/FrostFS.SDK.ClientV2/Services/Shared/SessionProvider.cs index ccfec71..d1cc432 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Shared/SessionProvider.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Shared/SessionProvider.cs @@ -1,6 +1,6 @@ - using System.Threading.Tasks; -using FrostFS.SDK.ClientV2.Parameters; + +using FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2; diff --git a/src/FrostFS.SDK.ClientV2/Tools/ClientEnvironment.cs b/src/FrostFS.SDK.ClientV2/Tools/ClientEnvironment.cs index 14ccd40..1ac5183 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/ClientEnvironment.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/ClientEnvironment.cs @@ -1,20 +1,20 @@ -using FrostFS.SDK.ModelsV2; -using Grpc.Net.Client; using System; -using System.Security.Cryptography; using System.Buffers; +using System.Security.Cryptography; + +using Grpc.Net.Client; namespace FrostFS.SDK.ClientV2; -public class ClientEnvironment(Client client, ECDsa? key, OwnerId? owner, GrpcChannel channel, ModelsV2.Version version) : IDisposable +public class ClientEnvironment(Client client, ECDsa? key, FrostFsOwner? owner, GrpcChannel channel, FrostFsVersion version) : IDisposable { private ArrayPool _arrayPool; - internal OwnerId? Owner { get; } = owner; + internal FrostFsOwner? Owner { get; } = owner; internal GrpcChannel Channel { get; private set; } = channel; - internal ModelsV2.Version Version { get; } = version; + internal FrostFsVersion Version { get; } = version; internal NetworkSettings? NetworkSettings { get; set; } @@ -42,7 +42,7 @@ public class ClientEnvironment(Client client, ECDsa? key, OwnerId? owner, GrpcCh { if (disposing) { - Channel.Dispose(); + Channel?.Dispose(); } } } diff --git a/src/FrostFS.SDK.ClientV2/Tools/Object.cs b/src/FrostFS.SDK.ClientV2/Tools/Object.cs index 0dd931e..05d957c 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/Object.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/Object.cs @@ -1,7 +1,5 @@ - using System; using System.Collections.Generic; -using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2.Extensions; @@ -21,29 +19,29 @@ public static class ObjectExtensions public static FrostFsObject AddAttribute(this FrostFsObject obj, string key, string value) { - obj.AddAttribute(new ObjectAttribute(key, value)); + obj.AddAttribute(new FrostFsAttribute(key, value)); return obj; } - public static FrostFsObject AddAttribute(this FrostFsObject obj, ObjectAttribute attribute) + public static FrostFsObject AddAttribute(this FrostFsObject obj, FrostFsAttribute attribute) { obj.Header.Attributes.Add(attribute); return obj; } - public static FrostFsObject AddAttributes(this FrostFsObject obj, IEnumerable attributes) + public static FrostFsObject AddAttributes(this FrostFsObject obj, IEnumerable attributes) { obj.Header.Attributes.AddRange(attributes); return obj; } - public static FrostFsObject SetSplit(this FrostFsObject obj, Split? split) + public static FrostFsObject SetSplit(this FrostFsObject obj, FrostFsSplit? split) { obj.Header.Split = split; return obj; } - public static LinkObject AddChildren(this LinkObject linkObject, IEnumerable objectIds) + public static FrostFsLinkObject AddChildren(this FrostFsLinkObject linkObject, IEnumerable objectIds) { linkObject.Header.Split!.Children.AddRange(objectIds); return linkObject; diff --git a/src/FrostFS.SDK.ClientV2/Tools/ObjectReader.cs b/src/FrostFS.SDK.ClientV2/Tools/ObjectReader.cs index 647a7ad..07c4793 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/ObjectReader.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/ObjectReader.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Grpc.Core; using FrostFS.Object; -using FrostFS.SDK.ModelsV2; using System.Threading; namespace FrostFS.SDK.ClientV2; @@ -33,7 +32,7 @@ public class ObjectReader(AsyncServerStreamingCall call) : IObjectR }; } - public async Task ReadChunk(CancellationToken cancellationToken = default) + public async Task?> ReadChunk(CancellationToken cancellationToken = default) { if (!await Call.ResponseStream.MoveNext(cancellationToken)) return null; @@ -44,14 +43,14 @@ public class ObjectReader(AsyncServerStreamingCall call) : IObjectR if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk) throw new InvalidOperationException("unexpected message type"); - return response.Body.Chunk.ToByteArray(); + return response.Body.Chunk.Memory; } public void Dispose() { if (!disposed) { - Call.Dispose(); + Call?.Dispose(); GC.SuppressFinalize(this); disposed = true; diff --git a/src/FrostFS.SDK.ClientV2/Tools/ObjectStreamer.cs b/src/FrostFS.SDK.ClientV2/Tools/ObjectStreamer.cs index 11858c3..9350282 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/ObjectStreamer.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/ObjectStreamer.cs @@ -30,6 +30,6 @@ internal class ObjectStreamer(AsyncClientStreamingCall public void Dispose() { - Call.Dispose(); + Call?.Dispose(); } } diff --git a/src/FrostFS.SDK.ClientV2/Tools/ObjectTools.cs b/src/FrostFS.SDK.ClientV2/Tools/ObjectTools.cs index 321724a..64c09cd 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/ObjectTools.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/ObjectTools.cs @@ -6,13 +6,12 @@ using FrostFS.Object; using FrostFS.Refs; using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2; internal class ObjectTools { - internal static ObjectId CalculateObjectId(ObjectHeader header, Context ctx) + internal static FrostFsObjectId CalculateObjectId(FrostFsObjectHeader header, Context ctx) { var grpcHeader = CreateHeader(header, [], ctx); @@ -24,10 +23,10 @@ internal class ObjectTools internal static Object.Object CreateObject(FrostFsObject @object, Context ctx) { - @object.Header.OwnerId = ctx.OwnerId; - @object.Header.Version = ctx.Version; + @object.Header.OwnerId ??= ctx.OwnerId; + @object.Header.Version ??= ctx.Version; - var grpcHeader = @object.Header.ToMessage(); + var grpcHeader = @object.Header.GetHeader(); grpcHeader.PayloadLength = (ulong)@object.Payload.Length; grpcHeader.PayloadHash = Sha256Checksum(@object.Payload); @@ -47,18 +46,21 @@ internal class ObjectTools obj.Signature = new Refs.Signature { - Key = ctx.PublicKeyCache, + Key = ctx.GetPublicKeyCache(), Sign = ByteString.CopyFrom(ctx.Key.SignData(obj.ObjectId.ToByteArray())), }; return obj; } - internal static void SetSplitValues(Header grpcHeader, ModelsV2.Split split, Context ctx) + internal static void SetSplitValues(Header grpcHeader, FrostFsSplit split, Context ctx) { + if (split == null) + return; + grpcHeader.Split = new Header.Types.Split { - SplitId = split.SplitId != null ? ByteString.CopyFrom(split.SplitId.ToBinary()) : null + SplitId = split.SplitId?.GetSplitId() }; if (split.Children != null && split.Children.Count != 0) @@ -72,7 +74,7 @@ internal class ObjectTools grpcHeader.Split.ParentHeader = grpcParentHeader; grpcHeader.Split.ParentSignature = new Refs.Signature { - Key = ctx.PublicKeyCache, + Key = ctx.GetPublicKeyCache(), Sign = ByteString.CopyFrom(ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray())), }; @@ -82,13 +84,13 @@ internal class ObjectTools grpcHeader.Split.Previous = split.Previous?.ToMessage(); } - internal static Header CreateHeader(ObjectHeader header, byte[]? payload, Context ctx) + internal static Header CreateHeader(FrostFsObjectHeader header, byte[]? payload, Context ctx) { - var grpcHeader = header.ToMessage(); - - grpcHeader.OwnerId = ctx.OwnerId.ToMessage(); - grpcHeader.Version = ctx.Version.ToMessage(); + header.OwnerId ??= ctx.OwnerId; + header.Version ??= ctx.Version; + var grpcHeader = header.GetHeader(); + if (payload != null) // && payload.Length > 0 grpcHeader.PayloadHash = Sha256Checksum(payload); diff --git a/src/FrostFS.SDK.ClientV2/Tools/Range.cs b/src/FrostFS.SDK.ClientV2/Tools/Range.cs index 9c989c1..eae7b50 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/Range.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/Range.cs @@ -24,10 +24,8 @@ namespace System public Index(int value, bool fromEnd = false) { if (value < 0) - { throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - } - + if (fromEnd) _value = ~value; else @@ -52,10 +50,8 @@ namespace System public static Index FromStart(int value) { if (value < 0) - { throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - } - + return new Index(value); } @@ -65,10 +61,8 @@ namespace System public static Index FromEnd(int value) { if (value < 0) - { throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - } - + return new Index(~value); } @@ -77,14 +71,7 @@ namespace System { get { - if (_value < 0) - { - return ~_value; - } - else - { - return _value; - } + return _value < 0 ? ~_value : _value; } } @@ -202,6 +189,7 @@ namespace System { int start; var startIndex = Start; + if (startIndex.IsFromEnd) start = length - startIndex.Value; else @@ -209,16 +197,15 @@ namespace System int end; var endIndex = End; + if (endIndex.IsFromEnd) end = length - endIndex.Value; else end = endIndex.Value; if ((uint)end > (uint)length || (uint)start > (uint)end) - { throw new ArgumentOutOfRangeException(nameof(length)); - } - + return (start, end - start); } } @@ -234,10 +221,8 @@ namespace System.Runtime.CompilerServices public static T[] GetSubArray(T[] array, Range range) { if (array == null) - { throw new ArgumentNullException(nameof(array)); - } - + (int offset, int length) = range.GetOffsetAndLength(array.Length); if (default(T) != null || typeof(T[]) == array.GetType()) @@ -245,10 +230,8 @@ namespace System.Runtime.CompilerServices // We know the type of the array to be exactly T[]. if (length == 0) - { return []; - } - + var dest = new T[length]; Array.Copy(array, offset, dest, 0, length); return dest; diff --git a/src/FrostFS.SDK.ClientV2/Tools/RequestConstructor.cs b/src/FrostFS.SDK.ClientV2/Tools/RequestConstructor.cs index 2bbba92..c12d280 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/RequestConstructor.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/RequestConstructor.cs @@ -5,7 +5,6 @@ using System.Security.Cryptography; using FrostFS.Refs; using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; using FrostFS.SDK.ProtosV2.Interfaces; using FrostFS.Session; diff --git a/src/FrostFS.SDK.ClientV2/Tools/RequestSigner.cs b/src/FrostFS.SDK.ClientV2/Tools/RequestSigner.cs index f5057eb..c2d80f7 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/RequestSigner.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/RequestSigner.cs @@ -1,6 +1,11 @@ using System; using System.Security.Cryptography; +using FrostFS.Refs; +using FrostFS.SDK.Cryptography; +using FrostFS.SDK.ProtosV2.Interfaces; +using FrostFS.Session; + using Google.Protobuf; using Org.BouncyCastle.Asn1.Sec; @@ -9,11 +14,6 @@ using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Math; -using FrostFS.Refs; -using FrostFS.SDK.Cryptography; -using FrostFS.Session; -using FrostFS.SDK.ProtosV2.Interfaces; - namespace FrostFS.SDK.ClientV2; public static class RequestSigner diff --git a/src/FrostFS.SDK.ClientV2/Tools/SearchReader.cs b/src/FrostFS.SDK.ClientV2/Tools/SearchReader.cs index 6bc72df..1bcf398 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/SearchReader.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/SearchReader.cs @@ -1,13 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; -using Grpc.Core; - using FrostFS.Object; using FrostFS.Refs; -using System.Threading; + +using Grpc.Core; namespace FrostFS.SDK.ClientV2; @@ -29,6 +29,6 @@ internal class SearchReader(AsyncServerStreamingCall call) : IDi public void Dispose() { - Call.Dispose(); + Call?.Dispose(); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Tools/Verifier.cs b/src/FrostFS.SDK.ClientV2/Tools/Verifier.cs index bd8ddec..2640e45 100644 --- a/src/FrostFS.SDK.ClientV2/Tools/Verifier.cs +++ b/src/FrostFS.SDK.ClientV2/Tools/Verifier.cs @@ -1,6 +1,12 @@ using System; using System.Security.Cryptography; +using FrostFS.Refs; +using FrostFS.SDK.ClientV2.Mappers.GRPC; +using FrostFS.SDK.Cryptography; +using FrostFS.SDK.ProtosV2.Interfaces; +using FrostFS.Session; + using Google.Protobuf; using Org.BouncyCastle.Asn1.Sec; @@ -9,12 +15,6 @@ using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Math; -using FrostFS.Refs; -using FrostFS.SDK.ClientV2.Mappers.GRPC; -using FrostFS.SDK.Cryptography; -using FrostFS.Session; -using FrostFS.SDK.ProtosV2.Interfaces; - namespace FrostFS.SDK.ClientV2; public static class Verifier diff --git a/src/FrostFS.SDK.ModelsV2/Client/ClientSettings.cs b/src/FrostFS.SDK.ModelsV2/Client/ClientSettings.cs index c2abf26..80ba47a 100644 --- a/src/FrostFS.SDK.ModelsV2/Client/ClientSettings.cs +++ b/src/FrostFS.SDK.ModelsV2/Client/ClientSettings.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Text; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class ClientSettings { @@ -13,7 +13,7 @@ public class ClientSettings public virtual void Validate() { var errors = CheckFields(); - if (errors != null) + if (errors != null) ThrowException(errors); } @@ -28,7 +28,7 @@ public class ClientSettings } protected static void ThrowException(List errors) - { + { StringBuilder messages = new(); foreach (var error in errors) @@ -48,7 +48,7 @@ public class SingleOwnerClientSettings : ClientSettings { var errors = CheckFields(); if (errors != null) - ThrowException(errors); + ThrowException(errors); } protected List? CheckFields() @@ -59,5 +59,5 @@ public class SingleOwnerClientSettings : ClientSettings (errors ??= []).Add(string.Format(errorTemplate, nameof(Key))); return errors; - } + } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Containers/Container.cs b/src/FrostFS.SDK.ModelsV2/Containers/Container.cs deleted file mode 100644 index 02543b3..0000000 --- a/src/FrostFS.SDK.ModelsV2/Containers/Container.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using FrostFS.SDK.ModelsV2.Enums; -using FrostFS.SDK.ModelsV2.Netmap; - -namespace FrostFS.SDK.ModelsV2; - -public class Container(BasicAcl basicAcl, PlacementPolicy placementPolicy) -{ - public Guid Nonce { get; set; } = Guid.NewGuid(); - public BasicAcl BasicAcl { get; set; } = basicAcl; - public PlacementPolicy PlacementPolicy { get; set; } = placementPolicy; - public Version? Version { get; set; } -} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Containers/ContainerId.cs b/src/FrostFS.SDK.ModelsV2/Containers/ContainerId.cs index 349eb1c..4543dcd 100644 --- a/src/FrostFS.SDK.ModelsV2/Containers/ContainerId.cs +++ b/src/FrostFS.SDK.ModelsV2/Containers/ContainerId.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class ContainerId(string id) { diff --git a/src/FrostFS.SDK.ModelsV2/Containers/FrostFsContainer.cs b/src/FrostFS.SDK.ModelsV2/Containers/FrostFsContainer.cs new file mode 100644 index 0000000..45d3b58 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Containers/FrostFsContainer.cs @@ -0,0 +1,11 @@ +using System; + +namespace FrostFS.SDK; + +public class FrostFsContainer(BasicAcl basicAcl, FrostFsPlacementPolicy placementPolicy) +{ + public Guid Nonce { get; set; } = Guid.NewGuid(); + public BasicAcl BasicAcl { get; set; } = basicAcl; + public FrostFsPlacementPolicy PlacementPolicy { get; set; } = placementPolicy; + public FrostFsVersion? Version { get; set; } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs b/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs index 9418039..dd3252b 100644 --- a/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs +++ b/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace FrostFS.SDK.ModelsV2.Enums; +namespace FrostFS.SDK; public enum BasicAcl { diff --git a/src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectMatchType.cs b/src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectMatchType.cs new file mode 100644 index 0000000..1fdeb60 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectMatchType.cs @@ -0,0 +1,10 @@ +namespace FrostFS.SDK; + +public enum FrostFsObjectMatchType +{ + Unspecified = 0, + Equals = 1, + NotEquals = 2, + KeyAbsent = 3, + StartsWith = 4 +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectType.cs b/src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectType.cs new file mode 100644 index 0000000..793fe2e --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Enums/FrostFsObjectType.cs @@ -0,0 +1,8 @@ +namespace FrostFS.SDK; + +public enum FrostFsObjectType +{ + Regular = 0, + Tombstone = 1, + Lock = 3 +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/FrostFsStatusCode.cs b/src/FrostFS.SDK.ModelsV2/Enums/FrostFsStatusCode.cs new file mode 100644 index 0000000..7eb185c --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Enums/FrostFsStatusCode.cs @@ -0,0 +1,22 @@ +namespace FrostFS.SDK; + +public enum FrostFsStatusCode +{ + Success = 0, + Internal = 1024, + WrongMagicNumber = 1025, + SignatureVerificationFailure = 1026, + NodeUnderMaintenance = 1027, + ObjectAccessDenied = 2048, + ObjectNotFound = 2049, + ObjectLocked = 2050, + LockNotRegularObject = 2051, + ObjectAlreadyRemoved = 2052, + OutOfRange = 2053, + ContainerNotFound = 3072, + EAclNotFound = 3073, + ContainerAccessDenied = 3074, + TokenNotFound = 4096, + TokenExpired = 4097, + ApeManagerAccessDenied = 5120 +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/NodeState.cs b/src/FrostFS.SDK.ModelsV2/Enums/NodeState.cs index 2293c0f..2821e55 100644 --- a/src/FrostFS.SDK.ModelsV2/Enums/NodeState.cs +++ b/src/FrostFS.SDK.ModelsV2/Enums/NodeState.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ModelsV2.Enums; +namespace FrostFS.SDK; public enum NodeState { diff --git a/src/FrostFS.SDK.ModelsV2/Enums/ObjectType.cs b/src/FrostFS.SDK.ModelsV2/Enums/ObjectType.cs deleted file mode 100644 index 6f8a905..0000000 --- a/src/FrostFS.SDK.ModelsV2/Enums/ObjectType.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace FrostFS.SDK.ModelsV2.Enums; - -public enum ObjectType -{ - Regular = 0, - Tombstone = 1, - Lock = 3 -} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/SignatureScheme.cs b/src/FrostFS.SDK.ModelsV2/Enums/SignatureScheme.cs index bd6c41d..4b5634c 100644 --- a/src/FrostFS.SDK.ModelsV2/Enums/SignatureScheme.cs +++ b/src/FrostFS.SDK.ModelsV2/Enums/SignatureScheme.cs @@ -1,7 +1,8 @@ -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; -public enum SignatureScheme { +public enum SignatureScheme +{ EcdsaSha512, EcdsaRfc6979Sha256, EcdsaRfc6979Sha256WalletConnect - } +} diff --git a/src/FrostFS.SDK.ModelsV2/Misc/CallStatistics.cs b/src/FrostFS.SDK.ModelsV2/Misc/CallStatistics.cs index a6cbcbf..706b3f2 100644 --- a/src/FrostFS.SDK.ModelsV2/Misc/CallStatistics.cs +++ b/src/FrostFS.SDK.ModelsV2/Misc/CallStatistics.cs @@ -1,7 +1,7 @@ -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class CallStatistics -{ +{ public string? MethodName { get; set; } public long ElapsedMicroSeconds { get; set; } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Misc/CheckSum.cs b/src/FrostFS.SDK.ModelsV2/Misc/CheckSum.cs index 872038b..82017f9 100644 --- a/src/FrostFS.SDK.ModelsV2/Misc/CheckSum.cs +++ b/src/FrostFS.SDK.ModelsV2/Misc/CheckSum.cs @@ -1,7 +1,7 @@ using FrostFS.SDK.Cryptography; using System; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class CheckSum { diff --git a/src/FrostFS.SDK.ModelsV2/Misc/Constants.cs b/src/FrostFS.SDK.ModelsV2/Misc/Constants.cs index 4b72aa1..332a3e3 100644 --- a/src/FrostFS.SDK.ModelsV2/Misc/Constants.cs +++ b/src/FrostFS.SDK.ModelsV2/Misc/Constants.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class Constants { diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsNodeInfo.cs b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsNodeInfo.cs new file mode 100644 index 0000000..9581b21 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsNodeInfo.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace FrostFS.SDK; + +public class FrostFsNodeInfo( + FrostFsVersion version, + NodeState state, + IReadOnlyCollection addresses, + IReadOnlyDictionary attributes, + ReadOnlyMemory publicKey) +{ + public NodeState State { get; private set; } = state; + public FrostFsVersion Version { get; private set; } = version; + public IReadOnlyCollection Addresses { get; private set; } = addresses; + public IReadOnlyDictionary Attributes { get; private set; } = attributes; + public ReadOnlyMemory PublicKey { get; private set; } = publicKey; +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsPlacementPolicy.cs b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsPlacementPolicy.cs new file mode 100644 index 0000000..410598c --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsPlacementPolicy.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; + +namespace FrostFS.SDK; + +public class FrostFsPlacementPolicy(bool unique, params FrostFsReplica[] replicas) : IComparable +{ + public FrostFsReplica[] Replicas { get; private set; } = replicas; + public bool Unique { get; private set; } = unique; + + public int CompareTo(FrostFsPlacementPolicy other) + { + var notEqual = other == null + || Unique != other.Unique + || Replicas.Length != other.Replicas.Length; + + if (notEqual) + return 1; + + foreach (var replica in Replicas) + { + if (!other!.Replicas.Any(r => r.Count == replica.Count && r.Selector == replica.Selector)) + return 1; + } + + return 0; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsReplica.cs b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsReplica.cs new file mode 100644 index 0000000..8fd1bd9 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsReplica.cs @@ -0,0 +1,15 @@ +namespace FrostFS.SDK; + +public class FrostFsReplica +{ + public int Count { get; set; } + public string Selector { get; set; } + + public FrostFsReplica(int count, string? selector = null) + { + selector ??= string.Empty; + + Count = count; + Selector = selector; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/Version.cs b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsVersion.cs similarity index 64% rename from src/FrostFS.SDK.ModelsV2/Netmap/Version.cs rename to src/FrostFS.SDK.ModelsV2/Netmap/FrostFsVersion.cs index 88bdee2..06c3ca2 100644 --- a/src/FrostFS.SDK.ModelsV2/Netmap/Version.cs +++ b/src/FrostFS.SDK.ModelsV2/Netmap/FrostFsVersion.cs @@ -1,11 +1,11 @@ -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; -public class Version(int major, int minor) +public class FrostFsVersion(int major, int minor) { public int Major { get; set; } = major; public int Minor { get; set; } = minor; - public bool IsSupported(Version version) + public bool IsSupported(FrostFsVersion version) { return Major == version.Major; } diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/NetmapInfo.cs b/src/FrostFS.SDK.ModelsV2/Netmap/NetmapInfo.cs index fb8dba1..a371564 100644 --- a/src/FrostFS.SDK.ModelsV2/Netmap/NetmapInfo.cs +++ b/src/FrostFS.SDK.ModelsV2/Netmap/NetmapInfo.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; -namespace FrostFS.SDK.ModelsV2.Netmap; +namespace FrostFS.SDK; -public class NetmapSnapshot(ulong epoch, IReadOnlyList nodeInfoCollection) +public class NetmapSnapshot(ulong epoch, IReadOnlyList nodeInfoCollection) { public ulong Epoch { get; private set; } = epoch; - public IReadOnlyList NodeInfoCollection { get; private set; } = nodeInfoCollection; + public IReadOnlyList NodeInfoCollection { get; private set; } = nodeInfoCollection; } \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Object/FrostFsObject.cs b/src/FrostFS.SDK.ModelsV2/Object/FrostFsObject.cs index 1443abf..e382ec5 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/FrostFsObject.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/FrostFsObject.cs @@ -1,7 +1,6 @@ using System; -using FrostFS.SDK.ModelsV2.Enums; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class FrostFsObject { @@ -11,7 +10,7 @@ public class FrostFsObject /// public FrostFsObject(ObjectHeader header) { - Header = header; + Header = header; } /// @@ -19,17 +18,17 @@ public class FrostFsObject /// /// /// - public FrostFsObject(ContainerId container, ObjectType objectType = ObjectType.Regular) + public FrostFsObject(ContainerId container, FrostFsObjectType objectType = FrostFsObjectType.Regular) { - Header = new ObjectHeader(containerId: container, type: objectType); + Header = new ObjectHeader(containerId: container, type: objectType); } - + /// /// Header contains metadata for the object /// /// public ObjectHeader Header { get; set; } - + /// /// The value is calculated internally as a hash of ObjectHeader. Do not use pre-calculated value is the object has been changed. /// @@ -50,7 +49,7 @@ public class FrostFsObject /// /// Reader for received data public IObjectReader? ObjectReader { get; set; } - + /// /// Applied only for the last Object in chain in case of manual multipart uploading /// @@ -74,11 +73,11 @@ public class LargeObject(ContainerId container) : FrostFsObject(container) public class LinkObject : FrostFsObject { - public LinkObject(ContainerId containerId, SplitId splitId, ObjectHeader largeObjectHeader) : base (containerId) + public LinkObject(ContainerId containerId, SplitId splitId, ObjectHeader largeObjectHeader) : base(containerId) { Header!.Split = new Split(splitId) { - ParentHeader = largeObjectHeader + ParentHeader = largeObjectHeader }; } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Object/IObjectReader.cs b/src/FrostFS.SDK.ModelsV2/Object/IObjectReader.cs index 4c5ce3d..51211fd 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/IObjectReader.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/IObjectReader.cs @@ -2,9 +2,9 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public interface IObjectReader : IDisposable { - Task ReadChunk(CancellationToken cancellationToken = default); + Task?> ReadChunk(CancellationToken cancellationToken = default); } diff --git a/src/FrostFS.SDK.ModelsV2/Object/ObjectAttribute.cs b/src/FrostFS.SDK.ModelsV2/Object/ObjectAttribute.cs index 92d38b2..110db12 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/ObjectAttribute.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/ObjectAttribute.cs @@ -1,4 +1,4 @@ -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class ObjectAttribute(string key, string value) { diff --git a/src/FrostFS.SDK.ModelsV2/Object/ObjectFilter.cs b/src/FrostFS.SDK.ModelsV2/Object/ObjectFilter.cs index fbed30c..40f654d 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/ObjectFilter.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/ObjectFilter.cs @@ -1,18 +1,16 @@ -using FrostFS.SDK.ModelsV2.Enums; - -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public interface IObjectFilter { - public ObjectMatchType MatchType { get; set; } + public FrostFsObjectMatchType MatchType { get; set; } public string Key { get; set; } - + string? GetSerializedValue(); } -public abstract class ObjectFilter(ObjectMatchType matchType, string key, T value) : IObjectFilter +public abstract class ObjectFilter(FrostFsObjectMatchType matchType, string key, T value) : IObjectFilter { - public ObjectMatchType MatchType { get; set; } = matchType; + public FrostFsObjectMatchType MatchType { get; set; } = matchType; public string Key { get; set; } = key; public T Value { get; set; } = value; @@ -29,85 +27,85 @@ public abstract class ObjectFilter(ObjectMatchType matchType, string key, T v /// Match type /// Attribute key /// Attribute value -public class FilterByAttribute(ObjectMatchType matchType, string key, string value) : ObjectFilter(matchType, key, value) { } +public class FilterByAttribute(FrostFsObjectMatchType matchType, string key, string value) : ObjectFilter(matchType, key, value) { } /// /// Creates filter to search by ObjectId /// /// Match type /// ObjectId -public class FilterByObjectId(ObjectMatchType matchType, ObjectId objectId) : ObjectFilter(matchType, Constants.FilterHeaderObjectID, objectId) { } +public class FilterByObjectId(FrostFsObjectMatchType matchType, ObjectId objectId) : ObjectFilter(matchType, Constants.FilterHeaderObjectID, objectId) { } /// /// Creates filter to search by OwnerId /// /// Match type /// ObjectId -public class FilterByOwnerId(ObjectMatchType matchType, OwnerId ownerId) : ObjectFilter(matchType, Constants.FilterHeaderOwnerID, ownerId) {} +public class FilterByOwnerId(FrostFsObjectMatchType matchType, OwnerId ownerId) : ObjectFilter(matchType, Constants.FilterHeaderOwnerID, ownerId) { } /// /// Creates filter to search by Version /// /// Match type /// Version -public class FilterByVersion(ObjectMatchType matchType, Version version) : ObjectFilter(matchType, Constants.FilterHeaderVersion, version) {} +public class FilterByVersion(FrostFsObjectMatchType matchType, FrostFsVersion version) : ObjectFilter(matchType, Constants.FilterHeaderVersion, version) { } /// /// Creates filter to search by ContainerId /// /// Match type /// ContainerId -public class FilterByContainerId(ObjectMatchType matchType, ContainerId containerId) : ObjectFilter(matchType, Constants.FilterHeaderContainerID, containerId) {} +public class FilterByContainerId(FrostFsObjectMatchType matchType, ContainerId containerId) : ObjectFilter(matchType, Constants.FilterHeaderContainerID, containerId) { } /// /// Creates filter to search by creation Epoch /// /// Match type /// Creation Epoch -public class FilterByEpoch(ObjectMatchType matchType, ulong epoch) : ObjectFilter(matchType, Constants.FilterHeaderCreationEpoch, epoch) {} +public class FilterByEpoch(FrostFsObjectMatchType matchType, ulong epoch) : ObjectFilter(matchType, Constants.FilterHeaderCreationEpoch, epoch) { } /// /// Creates filter to search by Payload Length /// /// Match type /// Payload Length -public class FilterByPayloadLength(ObjectMatchType matchType, ulong payloadLength) : ObjectFilter(matchType, Constants.FilterHeaderPayloadLength, payloadLength) {} +public class FilterByPayloadLength(FrostFsObjectMatchType matchType, ulong payloadLength) : ObjectFilter(matchType, Constants.FilterHeaderPayloadLength, payloadLength) { } /// /// Creates filter to search by Payload Hash /// /// Match type /// Payload Hash -public class FilterByPayloadHash(ObjectMatchType matchType, CheckSum payloadHash) : ObjectFilter(matchType, Constants.FilterHeaderPayloadHash, payloadHash) {} +public class FilterByPayloadHash(FrostFsObjectMatchType matchType, CheckSum payloadHash) : ObjectFilter(matchType, Constants.FilterHeaderPayloadHash, payloadHash) { } /// /// Creates filter to search by Parent /// /// Match type /// Parent -public class FilterByParent(ObjectMatchType matchType, ObjectId parentId) : ObjectFilter(matchType, Constants.FilterHeaderParent, parentId) {} +public class FilterByParent(FrostFsObjectMatchType matchType, ObjectId parentId) : ObjectFilter(matchType, Constants.FilterHeaderParent, parentId) { } /// /// Creates filter to search by SplitId /// /// Match type /// SplitId -public class FilterBySplitId(ObjectMatchType matchType, SplitId splitId) : ObjectFilter(matchType, Constants.FilterHeaderSplitID, splitId) {} +public class FilterBySplitId(FrostFsObjectMatchType matchType, SplitId splitId) : ObjectFilter(matchType, Constants.FilterHeaderSplitID, splitId) { } /// /// Creates filter to search by Payload Hash /// /// Match type /// Payload Hash -public class FilterByECParent(ObjectMatchType matchType, ObjectId ecParentId) : ObjectFilter(matchType, Constants.FilterHeaderECParent, ecParentId) {} +public class FilterByECParent(FrostFsObjectMatchType matchType, ObjectId ecParentId) : ObjectFilter(matchType, Constants.FilterHeaderECParent, ecParentId) { } /// /// Creates filter to search Root objects /// -public class FilterByRootObject() : ObjectFilter(ObjectMatchType.Unspecified, Constants.FilterHeaderRoot, string.Empty) {} +public class FilterByRootObject() : ObjectFilter(FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderRoot, string.Empty) { } /// /// Creates filter to search objects that are physically stored on the server /// (ObjectMatchType.Unspecified, Constants.FilterHeaderPhy, string.Empty) {} +public class FilterByPhysicallyStored() : ObjectFilter(FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderPhy, string.Empty) { } diff --git a/src/FrostFS.SDK.ModelsV2/Object/ObjectHeader.cs b/src/FrostFS.SDK.ModelsV2/Object/ObjectHeader.cs index 715f903..3e3ecd3 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/ObjectHeader.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/ObjectHeader.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -using FrostFS.SDK.ModelsV2.Enums; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class ObjectHeader( ContainerId containerId, - ObjectType type = ObjectType.Regular, + FrostFsObjectType type = FrostFsObjectType.Regular, params ObjectAttribute[] attributes ) { @@ -19,9 +18,9 @@ public class ObjectHeader( public byte[]? PayloadCheckSum { get; set; } - public ObjectType ObjectType { get; set; } = type; + public FrostFsObjectType ObjectType { get; set; } = type; - public Version? Version { get; set; } + public FrostFsVersion? Version { get; set; } public Split? Split { get; set; } } diff --git a/src/FrostFS.SDK.ModelsV2/Object/ObjectId.cs b/src/FrostFS.SDK.ModelsV2/Object/ObjectId.cs index 74e6bfb..9072361 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/ObjectId.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/ObjectId.cs @@ -2,7 +2,7 @@ using FrostFS.SDK.Cryptography; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class ObjectId(string id) { @@ -12,7 +12,7 @@ public class ObjectId(string id) { if (hash.Length != Constants.Sha256HashLength) throw new FormatException("ObjectID must be a sha256 hash."); - + return new ObjectId(Base58.Encode(hash)); } diff --git a/src/FrostFS.SDK.ModelsV2/Object/OwnerId.cs b/src/FrostFS.SDK.ModelsV2/Object/OwnerId.cs index b930bb7..5da87ef 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/OwnerId.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/OwnerId.cs @@ -2,7 +2,7 @@ using System.Security.Cryptography; using FrostFS.SDK.Cryptography; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class OwnerId(string id) { diff --git a/src/FrostFS.SDK.ModelsV2/Object/SplitId.cs b/src/FrostFS.SDK.ModelsV2/Object/SplitId.cs index 111f632..8af45c1 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/SplitId.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/SplitId.cs @@ -1,30 +1,35 @@ using FrostFS.SDK.Cryptography; + +using Google.Protobuf; + using System; -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class SplitId { - private Guid id; + private readonly Guid id; + + ByteString? _message; public SplitId() { - this.id = Guid.NewGuid(); + id = Guid.NewGuid(); } public SplitId(Guid guid) { - this.id = guid; + id = guid; } private SplitId(byte[] binary) { - this.id = new Guid(binary); + id = new Guid(binary); } private SplitId(string str) { - this.id = new Guid(str); + id = new Guid(str); } public static SplitId CreateFromBinary(byte[] binaryData) @@ -35,18 +40,23 @@ public class SplitId public static SplitId CreateFromString(string stringData) { return new SplitId(stringData); - } + } public override string ToString() { - return this.id.ToString(); + return id.ToString(); } public byte[]? ToBinary() { - if (this.id == Guid.Empty) + if (id == Guid.Empty) return null; - return this.id.ToBytes(); + return id.ToBytes(); + } + + public ByteString? GetMessage() + { + return _message ??= ByteString.CopyFrom(ToBinary()); } } diff --git a/src/FrostFS.SDK.ModelsV2/Object/Splitter.cs b/src/FrostFS.SDK.ModelsV2/Object/Splitter.cs index 3fb55df..64b3515 100644 --- a/src/FrostFS.SDK.ModelsV2/Object/Splitter.cs +++ b/src/FrostFS.SDK.ModelsV2/Object/Splitter.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; - -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; public class Split(SplitId splitId) { @@ -14,8 +13,8 @@ public class Split(SplitId splitId) public ObjectId? Parent { get; set; } public ObjectId? Previous { get; set; } - - public Signature? ParentSignature { get; set; } + + public FrostFsSignature? ParentSignature { get; set; } public ObjectHeader? ParentHeader { get; set; } diff --git a/src/FrostFS.SDK.ModelsV2/Response/FrostFsResponseStatus.cs b/src/FrostFS.SDK.ModelsV2/Response/FrostFsResponseStatus.cs new file mode 100644 index 0000000..b5e5831 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Response/FrostFsResponseStatus.cs @@ -0,0 +1,14 @@ +namespace FrostFS.SDK; + +public class FrostFsResponseStatus(FrostFsStatusCode code, string? message = null) +{ + public FrostFsStatusCode Code { get; set; } = code; + public string Message { get; set; } = message ?? string.Empty; + + public bool IsSuccess => Code == FrostFsStatusCode.Success; + + public override string ToString() + { + return $"Response status: {Code}. Message: {Message}."; + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Response/FrostFsSignature.cs b/src/FrostFS.SDK.ModelsV2/Response/FrostFsSignature.cs new file mode 100644 index 0000000..d7ca6b6 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Response/FrostFsSignature.cs @@ -0,0 +1,10 @@ +namespace FrostFS.SDK; + +public class FrostFsSignature +{ + public byte[]? Key { get; set; } + + public byte[]? Sign { get; set; } + + public SignatureScheme Scheme { get; set; } +} diff --git a/src/FrostFS.SDK.ModelsV2/Response/MetaHeader.cs b/src/FrostFS.SDK.ModelsV2/Response/MetaHeader.cs index d2b84a2..36dad09 100644 --- a/src/FrostFS.SDK.ModelsV2/Response/MetaHeader.cs +++ b/src/FrostFS.SDK.ModelsV2/Response/MetaHeader.cs @@ -1,15 +1,15 @@ -namespace FrostFS.SDK.ModelsV2; +namespace FrostFS.SDK; -public class MetaHeader(Version version, int epoch, int ttl) +public class MetaHeader(FrostFsVersion version, int epoch, int ttl) { - public Version Version { get; set; } = version; + public FrostFsVersion Version { get; set; } = version; public int Epoch { get; set; } = epoch; public int Ttl { get; set; } = ttl; public static MetaHeader Default() { return new MetaHeader( - new Version( + new FrostFsVersion( major: 2, minor: 13 ), diff --git a/src/FrostFS.SDK.ModelsV2/Response/ResponseStatus.cs b/src/FrostFS.SDK.ModelsV2/Response/ResponseStatus.cs deleted file mode 100644 index f58e1bb..0000000 --- a/src/FrostFS.SDK.ModelsV2/Response/ResponseStatus.cs +++ /dev/null @@ -1,16 +0,0 @@ -using FrostFS.SDK.ModelsV2.Enums; - -namespace FrostFS.SDK.ModelsV2; - -public class ResponseStatus(StatusCode code, string? message = null) -{ - public StatusCode Code { get; set; } = code; - public string Message { get; set; } = message ?? string.Empty; - - public bool IsSuccess => Code == StatusCode.Success; - - public override string ToString() - { - return $"Response status: {Code}. Message: {Message}."; - } -} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Response/Signature.cs b/src/FrostFS.SDK.ModelsV2/Response/Signature.cs deleted file mode 100644 index 1d36e1c..0000000 --- a/src/FrostFS.SDK.ModelsV2/Response/Signature.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace FrostFS.SDK.ModelsV2; - -public class Signature -{ - public byte[]? Key { get; set; } - public byte[]? Sign { get; set; } - public SignatureScheme Scheme { get; set; } -} diff --git a/src/FrostFS.SDK.ModelsV2/Session/FrostFsSessionToken.cs b/src/FrostFS.SDK.ModelsV2/Session/FrostFsSessionToken.cs new file mode 100644 index 0000000..8954780 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Session/FrostFsSessionToken.cs @@ -0,0 +1,6 @@ +namespace FrostFS.SDK; + +public class FrostFsSessionToken(byte[] token) +{ + public byte[] Token { get; private set; } = token; +} diff --git a/src/FrostFS.SDK.ModelsV2/Session/SessionToken.cs b/src/FrostFS.SDK.ModelsV2/Session/SessionToken.cs deleted file mode 100644 index 2865ca3..0000000 --- a/src/FrostFS.SDK.ModelsV2/Session/SessionToken.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace FrostFS.SDK.ModelsV2; - -public class SessionToken(byte[] token) -{ - public byte[] Token { get; private set; } = token; -} diff --git a/src/FrostFS.SDK.Tests/ContainerTest.cs b/src/FrostFS.SDK.Tests/ContainerTest.cs index 0af0e70..fcfcb39 100644 --- a/src/FrostFS.SDK.Tests/ContainerTest.cs +++ b/src/FrostFS.SDK.Tests/ContainerTest.cs @@ -1,14 +1,11 @@ -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; +using FrostFS.SDK.ClientV2; using FrostFS.SDK.ClientV2.Mappers.GRPC; +using FrostFS.SDK.ClientV2.Interfaces; +using FrostFS.SDK.ClientV2; using FrostFS.SDK.Cryptography; using Microsoft.Extensions.Options; -using FrostFS.SDK.ModelsV2.Netmap; -using FrostFS.SDK.ModelsV2.Enums; using Google.Protobuf; -using FrostFS.SDK.ClientV2.Interfaces; -using FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.Tests; @@ -29,8 +26,8 @@ public abstract class ContainerTestsBase Mocker = new ContainerMocker(this.key) { - PlacementPolicy = new PlacementPolicy(true, new Replica(1)), - Version = new ModelsV2.Version(2, 13), + PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)), + Version = new FrostFsVersion(2, 13), ContainerGuid = Guid.NewGuid() }; } @@ -52,7 +49,7 @@ public class ContainerTest : ContainerTestsBase [Fact] public async void CreateContainerTest() { - var param = new PrmContainerCreate(new ModelsV2.Container(BasicAcl.PublicRW, Mocker.PlacementPolicy)); + var param = new PrmContainerCreate(new FrostFsContainerInfo(BasicAcl.PublicRW, Mocker.PlacementPolicy)); var result = await GetClient().CreateContainerAsync(param); @@ -64,7 +61,7 @@ public class ContainerTest : ContainerTestsBase [Fact] public async void GetContainerTest() { - var cid = new ContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes())); + var cid = new FrostFsContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes())); Mocker.Acl = BasicAcl.PublicRO; @@ -102,7 +99,7 @@ public class ContainerTest : ContainerTestsBase public async void DeleteContainerAsyncTest() { Mocker.ReturnContainerRemoved = true; - var cid = new ContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes())); + var cid = new FrostFsContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes())); await GetClient().DeleteContainerAsync(new PrmContainerDelete(cid)); diff --git a/src/FrostFS.SDK.Tests/MetricsInterceptor.cs b/src/FrostFS.SDK.Tests/MetricsInterceptor.cs new file mode 100644 index 0000000..cc6b438 --- /dev/null +++ b/src/FrostFS.SDK.Tests/MetricsInterceptor.cs @@ -0,0 +1,39 @@ +using Grpc.Core; +using Grpc.Core.Interceptors; + +using System.Diagnostics; + +namespace FrostFS.SDK.SmokeTests; + +public class MetricsInterceptor() : Interceptor +{ + public override AsyncUnaryCall AsyncUnaryCall( + TRequest request, + ClientInterceptorContext context, + AsyncUnaryCallContinuation continuation) + { + var call = continuation(request, context); + + return new AsyncUnaryCall( + HandleUnaryResponse(call), + call.ResponseHeadersAsync, + call.GetStatus, + call.GetTrailers, + call.Dispose); + } + + private static async Task HandleUnaryResponse(AsyncUnaryCall call) + { + var watch = new Stopwatch(); + watch.Start(); + + var response = await call.ResponseAsync; + + watch.Stop(); + + // Do something with call info + // var elapsed = watch.ElapsedTicks * 1_000_000/Stopwatch.Frequency; + + return response; + } +} diff --git a/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs b/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs index 3603a92..a8ddbbd 100644 --- a/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs +++ b/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs @@ -1,17 +1,18 @@ +using System.Security.Cryptography; + using FrostFS.Object; -using FrostFS.Session; -using Google.Protobuf; -using Grpc.Core; using FrostFS.SDK.ClientV2; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.Cryptography; -using System.Security.Cryptography; +using FrostFS.Session; + +using Google.Protobuf; + +using Grpc.Core; namespace FrostFS.SDK.Tests; -public class AsyncStreamReaderMock(string key, ObjectHeader objectHeader) : ServiceBase(key), IAsyncStreamReader +public class AsyncStreamReaderMock(string key, FrostFsObjectHeader objectHeader) : ServiceBase(key), IAsyncStreamReader { public GetResponse Current { diff --git a/src/FrostFS.SDK.Tests/Mocks/ClientStreamWriter.cs b/src/FrostFS.SDK.Tests/Mocks/ClientStreamWriter.cs index fb1fe2d..56746e4 100644 --- a/src/FrostFS.SDK.Tests/Mocks/ClientStreamWriter.cs +++ b/src/FrostFS.SDK.Tests/Mocks/ClientStreamWriter.cs @@ -21,8 +21,9 @@ public class ClientStreamWriter : IClientStreamWriter } public Task WriteAsync(IRequest message) - { - Messages.Add(message); + { + Object.PutRequest pr = new((Object.PutRequest)message); + Messages.Add(pr); return Task.CompletedTask; } } diff --git a/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs b/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs index 7cf2690..4235f71 100644 --- a/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs +++ b/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs @@ -3,8 +3,6 @@ using FrostFS.Container; using Moq; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2.Enums; -using FrostFS.SDK.ModelsV2.Netmap; using FrostFS.Session; using Google.Protobuf; @@ -19,18 +17,18 @@ public abstract class ServiceBase(string key) { public string StringKey { get; private set; } = key; public ECDsa Key { get; private set; } = key.LoadWif(); - public ModelsV2.Version Version { get; set; } = DefaultVersion; + public FrostFsVersion Version { get; set; } = DefaultVersion; public BasicAcl Acl { get; set; } = DefaultAcl; - public PlacementPolicy PlacementPolicy { get; set; } = DefaultPlacementPolicy; + public FrostFsPlacementPolicy PlacementPolicy { get; set; } = DefaultPlacementPolicy; - public static ModelsV2.Version DefaultVersion { get; } = new(2, 13); + public static FrostFsVersion DefaultVersion { get; } = new(2, 13); public static BasicAcl DefaultAcl { get; } = BasicAcl.PublicRW; - public static PlacementPolicy DefaultPlacementPolicy { get; } = new PlacementPolicy(true, new Replica(1)); + public static FrostFsPlacementPolicy DefaultPlacementPolicy { get; } = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)); public Metadata Metadata { get; protected set; } public DateTime? DateTime { get; protected set; } - public CancellationToken CancellationToken { get; protected set; } + public CancellationToken CancellationToken { get; protected set; } public CancellationTokenSource CancellationTokenSource { get; protected set; } = new CancellationTokenSource(); public static Metadata ResponseMetaData => []; diff --git a/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/GetContainerMock.cs b/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/GetContainerMock.cs index 34f6173..c76cc9f 100644 --- a/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/GetContainerMock.cs +++ b/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/GetContainerMock.cs @@ -5,8 +5,7 @@ using Moq; using FrostFS.SDK.Cryptography; using FrostFS.SDK.ClientV2; -using FrostFS.SDK.ModelsV2.Netmap; -using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; + using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.Session; using FrostFS.Refs; diff --git a/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs b/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs index 099398d..7e26a3e 100644 --- a/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs +++ b/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs @@ -2,7 +2,6 @@ using Google.Protobuf; using Grpc.Core; using Moq; using FrostFS.SDK.ClientV2; -using FrostFS.SDK.ModelsV2; using FrostFS.Object; using FrostFS.SDK.ClientV2.Mappers.GRPC; using System.Security.Cryptography; @@ -184,14 +183,13 @@ public class ObjectMocker(string key) : ObjectServiceBase(key) () => { }); }); } - return mock; } - public ObjectId? ObjectId { get; set; } + public FrostFsObjectId? ObjectId { get; set; } - public ObjectHeader? ObjectHeader { get; set; } + public FrostFsObjectHeader? ObjectHeader { get; set; } public Header? HeadResponse { get; set; } diff --git a/src/FrostFS.SDK.Tests/NetworkTest.cs b/src/FrostFS.SDK.Tests/NetworkTest.cs index 0fce906..11a7ff0 100644 --- a/src/FrostFS.SDK.Tests/NetworkTest.cs +++ b/src/FrostFS.SDK.Tests/NetworkTest.cs @@ -1,12 +1,13 @@ using FrostFS.Netmap; using FrostFS.SDK.ClientV2; using FrostFS.SDK.ClientV2.Interfaces; -using FrostFS.SDK.ClientV2.Parameters; +using FrostFS.SDK.ClientV2; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Enums; + using Google.Protobuf; + using Microsoft.Extensions.Options; + using System.Security.Cryptography; namespace FrostFS.SDK.Tests; @@ -17,10 +18,10 @@ public abstract class NetworkTestsBase protected IOptions Settings { get; set; } - protected ModelsV2.Version Version { get; set; } = new ModelsV2.Version(2, 13); + protected FrostFsVersion Version { get; set; } = new FrostFsVersion(2, 13); protected ECDsa ECDsaKey { get; set; } - protected OwnerId OwnerId { get; set; } + protected FrostFsOwner OwnerId { get; set; } protected NetworkMocker Mocker { get; set; } protected NetworkTestsBase() @@ -32,7 +33,7 @@ public abstract class NetworkTestsBase }); ECDsaKey = key.LoadWif(); - OwnerId = OwnerId.FromKey(ECDsaKey); + OwnerId = FrostFsOwner.FromKey(ECDsaKey); Mocker = new NetworkMocker(this.key); } diff --git a/src/FrostFS.SDK.Tests/ObjectTest.cs b/src/FrostFS.SDK.Tests/ObjectTest.cs index db20741..37fe81a 100644 --- a/src/FrostFS.SDK.Tests/ObjectTest.cs +++ b/src/FrostFS.SDK.Tests/ObjectTest.cs @@ -2,13 +2,13 @@ using FrostFS.Refs; using FrostFS.SDK.ClientV2; using FrostFS.SDK.ClientV2.Interfaces; using FrostFS.SDK.ClientV2.Mappers.GRPC; -using FrostFS.SDK.ClientV2.Parameters; +using FrostFS.SDK.ClientV2; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Enums; -using FrostFS.SDK.ModelsV2.Netmap; + using Google.Protobuf; + using Microsoft.Extensions.Options; + using System.Security.Cryptography; using System.Text; @@ -19,7 +19,7 @@ public abstract class ObjectTestsBase protected static readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq"; protected IOptions Settings { get; set; } - protected ContainerId ContainerId { get; set; } + protected FrostFsContainerId ContainerId { get; set; } protected NetworkMocker NetworkMocker { get; set; } = new NetworkMocker(key); protected SessionMocker SessionMocker { get; set; } = new SessionMocker(key); @@ -38,18 +38,20 @@ public abstract class ObjectTestsBase Mocker = new ObjectMocker(key) { - PlacementPolicy = new PlacementPolicy(true, new Replica(1)), - Version = new ModelsV2.Version(2, 13), + PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)), + Version = new FrostFsVersion(2, 13), ContainerGuid = Guid.NewGuid() }; - ContainerId = new ContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes())); + ContainerId = new FrostFsContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes())); - Mocker.ObjectHeader = new(ContainerId, ModelsV2.Enums.ObjectType.Regular, [new ObjectAttribute("k", "v")]) - { - Version = new ModelsV2.Version(2, 13), - OwnerId = OwnerId.FromKey(ecdsaKey) - }; + Mocker.ObjectHeader = new( + ContainerId, + FrostFsObjectType.Regular, + [new FrostFsAttribute("k", "v")], + null, + FrostFsOwner.FromKey(ecdsaKey), + new FrostFsVersion(2, 13)); } protected IFrostFSClient GetClient() @@ -75,8 +77,8 @@ public class ObjectTest : ObjectTestsBase var ctx = new Context { Key = ecdsaKey, - OwnerId = OwnerId.FromKey(ecdsaKey), - Version = new ModelsV2.Version(2, 13) }; + OwnerId = FrostFsOwner.FromKey(ecdsaKey), + Version = new FrostFsVersion(2, 13) }; var objectId = client.CalculateObjectId(Mocker.ObjectHeader!, ctx); @@ -218,7 +220,7 @@ public class ObjectTest : ObjectTestsBase Assert.Equal("k", linkObject.Header.Split.ParentHeader.Attributes[0].Key); Assert.Equal("v", linkObject.Header.Split.ParentHeader.Attributes[0].Value); - var modelObjId = ObjectId.FromHash(linkObject.Header.Split.Parent.Value.ToByteArray()); + var modelObjId = FrostFsObjectId.FromHash(linkObject.Header.Split.Parent.Value.ToByteArray()); Assert.Equal(result.Value, modelObjId.ToString()); } @@ -256,7 +258,7 @@ public class ObjectTest : ObjectTestsBase Assert.Equal(Mocker.HeadResponse!.PayloadLength, response.PayloadLength); - Assert.Equal(ObjectType.Regular, response.ObjectType); + Assert.Equal(FrostFsObjectType.Regular, response.ObjectType); Assert.Single(response.Attributes); diff --git a/src/FrostFS.SDK.Tests/SessionTests.cs b/src/FrostFS.SDK.Tests/SessionTests.cs index 8b3dc1a..7eda05e 100644 --- a/src/FrostFS.SDK.Tests/SessionTests.cs +++ b/src/FrostFS.SDK.Tests/SessionTests.cs @@ -1,12 +1,11 @@ using FrostFS.SDK.ClientV2; using FrostFS.SDK.ClientV2.Interfaces; using FrostFS.SDK.ClientV2.Mappers.GRPC; -using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; -using FrostFS.SDK.ClientV2.Parameters; +using FrostFS.SDK.ClientV2; using FrostFS.SDK.Cryptography; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Netmap; + using Microsoft.Extensions.Options; + using System.Security.Cryptography; namespace FrostFS.SDK.Tests; @@ -19,7 +18,7 @@ public abstract class SessionTestsBase protected ECDsa ECDsaKey { get; set; } - protected OwnerId OwnerId { get; set; } + protected FrostFsOwner OwnerId { get; set; } protected SessionMocker Mocker { get; set; } protected SessionTestsBase() @@ -31,12 +30,12 @@ public abstract class SessionTestsBase }); ECDsaKey = key.LoadWif(); - OwnerId = OwnerId.FromKey(ECDsaKey); + OwnerId = FrostFsOwner.FromKey(ECDsaKey); Mocker = new SessionMocker(this.key) { - PlacementPolicy = new PlacementPolicy(true, new Replica(1)), - Version = new ModelsV2.Version(2, 13) + PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)), + Version = new FrostFsVersion(2, 13) }; } diff --git a/src/FrostFS.SDK.Tests/SmokeTests.cs b/src/FrostFS.SDK.Tests/SmokeTests.cs index aff3298..f344303 100644 --- a/src/FrostFS.SDK.Tests/SmokeTests.cs +++ b/src/FrostFS.SDK.Tests/SmokeTests.cs @@ -1,45 +1,14 @@ using System.Security.Cryptography; using FrostFS.SDK.ClientV2; using FrostFS.SDK.ClientV2.Interfaces; -using FrostFS.SDK.ModelsV2; -using FrostFS.SDK.ModelsV2.Enums; -using FrostFS.SDK.ModelsV2.Netmap; using FrostFS.SDK.Cryptography; - -using Grpc.Core; using Microsoft.Extensions.Options; -using Grpc.Core.Interceptors; -using System.Diagnostics; using static FrostFS.Session.SessionToken.Types.Body; -using FrostFS.SDK.ClientV2.Parameters; -using FrostFS.SDK.Tests; +using FrostFS.SDK.ClientV2; namespace FrostFS.SDK.SmokeTests; -public abstract class SmokeTestsBase -{ - protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq"; - protected readonly string url = "http://172.23.32.4:8080"; - - protected ECDsa Key { get; } - - protected OwnerId OwnerId { get; } - - protected ModelsV2.Version Version { get; } - - protected Context Ctx { get; } - - protected SmokeTestsBase() - { - Key = key.LoadWif(); - OwnerId = OwnerId.FromKey(Key); - Version = new ModelsV2.Version(2, 13); - - Ctx = new Context { Key = Key, OwnerId = OwnerId, Version = Version }; - } -} - public class SmokeTests : SmokeTestsBase { private static readonly PrmWait lightWait = new (100, 1); @@ -134,7 +103,7 @@ public class SmokeTests : SmokeTestsBase var token = await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue)); var createContainerParam = new PrmContainerCreate( - new ModelsV2.Container(BasicAcl.PublicRW, new PlacementPolicy(true, new Replica(1)))); + new FrostFsContainerInfo(BasicAcl.PublicRW, new FrostFsPlacementPolicy(true, new FrostFsReplica(1)))); createContainerParam.XHeaders.Add("key1", "value1"); @@ -144,10 +113,10 @@ public class SmokeTests : SmokeTestsBase var param = new PrmObjectPut { - Header = new ObjectHeader( + Header = new FrostFsObjectHeader( containerId: containerId, - type: ModelsV2.Enums.ObjectType.Regular, - new ObjectAttribute("fileName", "test")), + type: FrostFsObjectType.Regular, + [new FrostFsAttribute("fileName", "test")]), Payload = new MemoryStream(bytes), ClientCut = false, SessionToken = token @@ -160,10 +129,10 @@ public class SmokeTests : SmokeTestsBase var downloadedBytes = new byte[@object.Header.PayloadLength]; MemoryStream ms = new(downloadedBytes); - byte[]? chunk = null; + ReadOnlyMemory? chunk = null; while ((chunk = await @object.ObjectReader!.ReadChunk()) != null) { - ms.Write(chunk); + ms.Write(chunk.Value.Span); } Assert.Equal(MD5.HashData(bytes), MD5.HashData(downloadedBytes)); @@ -179,7 +148,7 @@ public class SmokeTests : SmokeTestsBase await Cleanup(client); var createContainerParam = new PrmContainerCreate( - new ModelsV2.Container(BasicAcl.PublicRW, new PlacementPolicy(true, new Replica(1)))) + new FrostFsContainerInfo(BasicAcl.PublicRW, new FrostFsPlacementPolicy(true, new FrostFsReplica(1)))) { WaitParams = lightWait }; @@ -188,22 +157,20 @@ public class SmokeTests : SmokeTestsBase var bytes = new byte[] { 1, 2, 3 }; - var ParentHeader = new ObjectHeader( + var ParentHeader = new FrostFsObjectHeader( containerId: containerId, - type: ModelsV2.Enums.ObjectType.Regular) + type: FrostFsObjectType.Regular) { PayloadLength = 3 }; var param = new PrmObjectPut { - Header = new ObjectHeader( + Header = new FrostFsObjectHeader( containerId: containerId, - type: ModelsV2.Enums.ObjectType.Regular, - new ObjectAttribute("fileName", "test")) - { - Split = new Split(), - }, + type: FrostFsObjectType.Regular, + [new FrostFsAttribute("fileName", "test")], + new FrostFsSplit()), Payload = new MemoryStream(bytes), ClientCut = false }; @@ -216,30 +183,30 @@ public class SmokeTests : SmokeTestsBase var networkInfo = await client.GetNetmapSnapshotAsync(); - await CheckFilter(client, containerId, new FilterByContainerId(ObjectMatchType.Equals, containerId)); + await CheckFilter(client, containerId, new FilterByContainerId(FrostFsObjectMatchType.Equals, containerId)); - await CheckFilter(client, containerId, new FilterByOwnerId(ObjectMatchType.Equals, OwnerId.FromKey(ecdsaKey))); + await CheckFilter(client, containerId, new FilterByOwnerId(FrostFsObjectMatchType.Equals, FrostFsOwner.FromKey(ecdsaKey))); - await CheckFilter(client, containerId, new FilterBySplitId(ObjectMatchType.Equals, param.Header.Split.SplitId)); + await CheckFilter(client, containerId, new FilterBySplitId(FrostFsObjectMatchType.Equals, param.Header.Split.SplitId)); - await CheckFilter(client, containerId, new FilterByAttribute(ObjectMatchType.Equals, "fileName", "test")); + await CheckFilter(client, containerId, new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test")); - await CheckFilter(client, containerId, new FilterByObjectId(ObjectMatchType.Equals, objectId)); + await CheckFilter(client, containerId, new FilterByObjectId(FrostFsObjectMatchType.Equals, objectId)); - await CheckFilter(client, containerId, new FilterByVersion(ObjectMatchType.Equals, networkInfo.NodeInfoCollection[0].Version)); + await CheckFilter(client, containerId, new FilterByVersion(FrostFsObjectMatchType.Equals, networkInfo.NodeInfoCollection[0].Version)); - await CheckFilter(client, containerId, new FilterByEpoch(ObjectMatchType.Equals, networkInfo.Epoch)); + await CheckFilter(client, containerId, new FilterByEpoch(FrostFsObjectMatchType.Equals, networkInfo.Epoch)); - await CheckFilter(client, containerId, new FilterByPayloadLength(ObjectMatchType.Equals, 3)); + await CheckFilter(client, containerId, new FilterByPayloadLength(FrostFsObjectMatchType.Equals, 3)); var checkSum = CheckSum.CreateCheckSum(bytes); - await CheckFilter(client, containerId, new FilterByPayloadHash(ObjectMatchType.Equals, checkSum)); + await CheckFilter(client, containerId, new FilterByPayloadHash(FrostFsObjectMatchType.Equals, checkSum)); await CheckFilter(client, containerId, new FilterByPhysicallyStored()); } - private static async Task CheckFilter(IFrostFSClient client, ContainerId containerId, IObjectFilter filter) + private static async Task CheckFilter(IFrostFSClient client, FrostFsContainerId containerId, IObjectFilter filter) { var resultObjectsCount = 0; @@ -276,14 +243,14 @@ public class SmokeTests : SmokeTestsBase }; var createContainerParam = new PrmContainerCreate( - new ModelsV2.Container(BasicAcl.PublicRW, new PlacementPolicy(true, new Replica(1)))) + new FrostFsContainerInfo(BasicAcl.PublicRW, new FrostFsPlacementPolicy(true, new FrostFsReplica(1)),[new ("testKey", "testValue")])) { Context = ctx }; - var containerId = await client.CreateContainerAsync(createContainerParam); + var createdContainer = await client.CreateContainerAsync(createContainerParam); - var container = await client.GetContainerAsync(new PrmContainerGet(containerId) { Context = ctx }); + var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer) { Context = ctx }); Assert.NotNull(container); Assert.True(callbackInvoked); @@ -291,10 +258,10 @@ public class SmokeTests : SmokeTestsBase var param = new PrmObjectPut { - Header = new ObjectHeader( - containerId: containerId, - type: ModelsV2.Enums.ObjectType.Regular, - new ObjectAttribute("fileName", "test")), + Header = new FrostFsObjectHeader( + containerId: createdContainer, + type: FrostFsObjectType.Regular, + [new FrostFsAttribute("fileName", "test")]), Payload = new MemoryStream(bytes), ClientCut = false, Context = new Context @@ -305,14 +272,14 @@ public class SmokeTests : SmokeTestsBase var objectId = await client.PutObjectAsync(param); - var filter = new FilterByAttribute(ObjectMatchType.Equals, "fileName", "test"); + var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); bool hasObject = false; - await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId) { Filters = [filter] })) + await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(createdContainer) { Filters = [filter] })) { hasObject = true; - var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId)); + var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(createdContainer, objectId)); Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength); Assert.Single(objHeader.Attributes); Assert.Equal("fileName", objHeader.Attributes.First().Key); @@ -321,15 +288,15 @@ public class SmokeTests : SmokeTestsBase Assert.True(hasObject); - var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId)); + var @object = await client.GetObjectAsync(new PrmObjectGet(createdContainer, objectId)); var downloadedBytes = new byte[@object.Header.PayloadLength]; MemoryStream ms = new(downloadedBytes); - byte[]? chunk = null; + ReadOnlyMemory? chunk = null; while ((chunk = await @object.ObjectReader!.ReadChunk()) != null) { - ms.Write(chunk); + ms.Write(chunk.Value.Span); } Assert.Equal(MD5.HashData(bytes), MD5.HashData(downloadedBytes)); @@ -361,24 +328,24 @@ public class SmokeTests : SmokeTestsBase }; var createContainerParam = new PrmContainerCreate( - new ModelsV2.Container(BasicAcl.PublicRW, new PlacementPolicy(true, new Replica(1)))) + new FrostFsContainerInfo(BasicAcl.PublicRW, new FrostFsPlacementPolicy(true, new FrostFsReplica(1)))) { Context = ctx }; - var containerId = await client.CreateContainerAsync(createContainerParam); + var container = await client.CreateContainerAsync(createContainerParam); - var container = await client.GetContainerAsync(new PrmContainerGet(containerId) { Context = ctx }); - Assert.NotNull(container); + var containerInfo = await client.GetContainerAsync(new PrmContainerGet(container) { Context = ctx }); + Assert.NotNull(containerInfo); var bytes = GetRandomBytes(objectSize); var param = new PrmObjectPut { - Header = new ObjectHeader( - containerId: containerId, - type: ModelsV2.Enums.ObjectType.Regular, - new ObjectAttribute("fileName", "test")), + Header = new FrostFsObjectHeader( + containerId: container, + type: FrostFsObjectType.Regular, + [new FrostFsAttribute("fileName", "test")]), Payload = new MemoryStream(bytes), ClientCut = false, Context = new Context @@ -390,14 +357,14 @@ public class SmokeTests : SmokeTestsBase var objectId = await client.PutObjectAsync(param); - var filter = new FilterByAttribute(ObjectMatchType.Equals, "fileName", "test"); + var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); bool hasObject = false; - await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId) { Filters = [filter], SessionToken = token })) + await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(container) { Filters = [filter], SessionToken = token })) { hasObject = true; - var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId) { SessionToken = token }); + var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(container, objectId) { SessionToken = token }); Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength); Assert.Single(objHeader.Attributes); Assert.Equal("fileName", objHeader.Attributes.First().Key); @@ -406,15 +373,15 @@ public class SmokeTests : SmokeTestsBase Assert.True(hasObject); - var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId) { SessionToken = token }); + var @object = await client.GetObjectAsync(new PrmObjectGet(container, objectId) { SessionToken = token }); var downloadedBytes = new byte[@object.Header.PayloadLength]; MemoryStream ms = new(downloadedBytes); - byte[]? chunk = null; + ReadOnlyMemory? chunk = null; while ((chunk = await @object.ObjectReader!.ReadChunk()) != null) { - ms.Write(chunk); + ms.Write(chunk.Value.Span); } Assert.Equal(MD5.HashData(bytes), MD5.HashData(downloadedBytes)); @@ -440,7 +407,7 @@ public class SmokeTests : SmokeTestsBase await Cleanup(client); - var createContainerParam = new PrmContainerCreate(new ModelsV2.Container(BasicAcl.PublicRW, new PlacementPolicy(true, new Replica(1)))) + var createContainerParam = new PrmContainerCreate(new FrostFsContainerInfo(BasicAcl.PublicRW, new FrostFsPlacementPolicy(true, new FrostFsReplica(1)))) { WaitParams = lightWait }; @@ -461,17 +428,17 @@ public class SmokeTests : SmokeTestsBase var param = new PrmObjectPut { - Header = new ObjectHeader( + Header = new FrostFsObjectHeader( containerId: containerId, - type: ModelsV2.Enums.ObjectType.Regular, - new ObjectAttribute("fileName", "test")), + type: FrostFsObjectType.Regular, + [new FrostFsAttribute("fileName", "test")]), Payload = new MemoryStream(bytes), ClientCut = true }; var objectId = await client.PutObjectAsync(param); - var filter = new FilterByAttribute(ObjectMatchType.Equals, "fileName", "test"); + var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); bool hasObject = false; await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId, filter))) @@ -492,10 +459,10 @@ public class SmokeTests : SmokeTestsBase var downloadedBytes = new byte[@object.Header.PayloadLength]; MemoryStream ms = new(downloadedBytes); - byte[]? chunk = null; + ReadOnlyMemory? chunk = null; while ((chunk = await @object.ObjectReader!.ReadChunk()) != null) { - ms.Write(chunk); + ms.Write(chunk.Value.Span); } Assert.Equal(MD5.HashData(bytes), MD5.HashData(downloadedBytes)); @@ -506,7 +473,7 @@ public class SmokeTests : SmokeTestsBase var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)); - IAsyncEnumerator? enumerator = null; + IAsyncEnumerator? enumerator = null; do { if (deadline <= DateTime.UtcNow) @@ -554,37 +521,3 @@ public class SmokeTests : SmokeTestsBase } } } - - -public class MetricsInterceptor() : Interceptor -{ - public override AsyncUnaryCall AsyncUnaryCall( - TRequest request, - ClientInterceptorContext context, - AsyncUnaryCallContinuation continuation) - { - var call = continuation(request, context); - - return new AsyncUnaryCall( - HandleUnaryResponse(call), - call.ResponseHeadersAsync, - call.GetStatus, - call.GetTrailers, - call.Dispose); - } - - private static async Task HandleUnaryResponse(AsyncUnaryCall call) - { - var watch = new Stopwatch(); - watch.Start(); - - var response = await call.ResponseAsync; - - watch.Stop(); - - // Do something with call info - // var elapsed = watch.ElapsedTicks * 1_000_000/Stopwatch.Frequency; - - return response; - } -} diff --git a/src/FrostFS.SDK.Tests/SmokeTestsBase.cs b/src/FrostFS.SDK.Tests/SmokeTestsBase.cs new file mode 100644 index 0000000..60e4a20 --- /dev/null +++ b/src/FrostFS.SDK.Tests/SmokeTestsBase.cs @@ -0,0 +1,29 @@ +using System.Security.Cryptography; + +using FrostFS.SDK.ClientV2; +using FrostFS.SDK.Cryptography; + +namespace FrostFS.SDK.SmokeTests; + +public abstract class SmokeTestsBase +{ + protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq"; + protected readonly string url = "http://172.23.32.4:8080"; + + protected ECDsa Key { get; } + + protected FrostFsOwner OwnerId { get; } + + protected FrostFsVersion Version { get; } + + protected Context Ctx { get; } + + protected SmokeTestsBase() + { + Key = key.LoadWif(); + OwnerId = FrostFsOwner.FromKey(Key); + Version = new FrostFsVersion(2, 13); + + Ctx = new Context { Key = Key, OwnerId = OwnerId, Version = Version }; + } +} -- 2.45.2 From 704ce41173df55f3cd5814ef30e31d1bc343e2b4 Mon Sep 17 00:00:00 2001 From: Pavel Gross Date: Thu, 12 Sep 2024 11:56:26 +0300 Subject: [PATCH 2/2] [#23] Client: Refactoring to optimize memory usage Signed-off-by: Pavel Gross --- README.md | 2 +- .../Mappers/Object/ObjectFilterMapper.cs | 10 +++--- ...ObjectMatchType.cs => FrostFsMatchType.cs} | 2 +- .../Models/Object/FrostFsObjectFilter.cs | 32 +++++++++---------- src/FrostFS.SDK.Tests/SmokeTests.cs | 24 +++++++------- 5 files changed, 35 insertions(+), 35 deletions(-) rename src/FrostFS.SDK.ClientV2/Models/Enums/{FrostFsObjectMatchType.cs => FrostFsMatchType.cs} (77%) diff --git a/README.md b/README.md index d2e5fab..eccf0a2 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ var param = new PrmObjectPut FrostFsObjectId objectId = await client.PutObjectAsync(param); -var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); +var filter = new FilterByAttribute(FrostFsMatchType.Equals, "fileName", "test"); await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId) { Filters = [filter] })) { diff --git a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs index e59f51b..0303213 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/Object/ObjectFilterMapper.cs @@ -10,11 +10,11 @@ public static class ObjectFilterMapper { var objMatchTypeName = filter.MatchType switch { - FrostFsObjectMatchType.Unspecified => MatchType.Unspecified, - FrostFsObjectMatchType.Equals => MatchType.StringEqual, - FrostFsObjectMatchType.NotEquals => MatchType.StringNotEqual, - FrostFsObjectMatchType.KeyAbsent => MatchType.NotPresent, - FrostFsObjectMatchType.StartsWith => MatchType.CommonPrefix, + FrostFsMatchType.Unspecified => MatchType.Unspecified, + FrostFsMatchType.Equals => MatchType.StringEqual, + FrostFsMatchType.NotEquals => MatchType.StringNotEqual, + FrostFsMatchType.KeyAbsent => MatchType.NotPresent, + FrostFsMatchType.StartsWith => MatchType.CommonPrefix, _ => throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.") }; diff --git a/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectMatchType.cs b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsMatchType.cs similarity index 77% rename from src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectMatchType.cs rename to src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsMatchType.cs index 1fdeb60..b9b3659 100644 --- a/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsObjectMatchType.cs +++ b/src/FrostFS.SDK.ClientV2/Models/Enums/FrostFsMatchType.cs @@ -1,6 +1,6 @@ namespace FrostFS.SDK; -public enum FrostFsObjectMatchType +public enum FrostFsMatchType { Unspecified = 0, Equals = 1, diff --git a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs index e9552bf..feae9bd 100644 --- a/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs +++ b/src/FrostFS.SDK.ClientV2/Models/Object/FrostFsObjectFilter.cs @@ -2,15 +2,15 @@ namespace FrostFS.SDK; public interface IObjectFilter { - public FrostFsObjectMatchType MatchType { get; set; } + public FrostFsMatchType MatchType { get; set; } public string Key { get; set; } string? GetSerializedValue(); } -public abstract class FrostFsObjectFilter(FrostFsObjectMatchType matchType, string key, T value) : IObjectFilter +public abstract class FrostFsObjectFilter(FrostFsMatchType matchType, string key, T value) : IObjectFilter { - public FrostFsObjectMatchType MatchType { get; set; } = matchType; + public FrostFsMatchType MatchType { get; set; } = matchType; public string Key { get; set; } = key; public T Value { get; set; } = value; @@ -27,85 +27,85 @@ public abstract class FrostFsObjectFilter(FrostFsObjectMatchType matchType, s /// Match type /// Attribute key /// Attribute value -public class FilterByAttribute(FrostFsObjectMatchType matchType, string key, string value) : FrostFsObjectFilter(matchType, key, value) { } +public class FilterByAttribute(FrostFsMatchType matchType, string key, string value) : FrostFsObjectFilter(matchType, key, value) { } /// /// Creates filter to search by ObjectId /// /// Match type /// ObjectId -public class FilterByObjectId(FrostFsObjectMatchType matchType, FrostFsObjectId objectId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderObjectID, objectId) { } +public class FilterByObjectId(FrostFsMatchType matchType, FrostFsObjectId objectId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderObjectID, objectId) { } /// /// Creates filter to search by OwnerId /// /// Match type /// ObjectId -public class FilterByOwnerId(FrostFsObjectMatchType matchType, FrostFsOwner ownerId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderOwnerID, ownerId) { } +public class FilterByOwnerId(FrostFsMatchType matchType, FrostFsOwner ownerId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderOwnerID, ownerId) { } /// /// Creates filter to search by Version /// /// Match type /// Version -public class FilterByVersion(FrostFsObjectMatchType matchType, FrostFsVersion version) : FrostFsObjectFilter(matchType, Constants.FilterHeaderVersion, version) { } +public class FilterByVersion(FrostFsMatchType matchType, FrostFsVersion version) : FrostFsObjectFilter(matchType, Constants.FilterHeaderVersion, version) { } /// /// Creates filter to search by ContainerId /// /// Match type /// ContainerId -public class FilterByContainerId(FrostFsObjectMatchType matchType, FrostFsContainerId containerId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderContainerID, containerId) { } +public class FilterByContainerId(FrostFsMatchType matchType, FrostFsContainerId containerId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderContainerID, containerId) { } /// /// Creates filter to search by creation Epoch /// /// Match type /// Creation Epoch -public class FilterByEpoch(FrostFsObjectMatchType matchType, ulong epoch) : FrostFsObjectFilter(matchType, Constants.FilterHeaderCreationEpoch, epoch) { } +public class FilterByEpoch(FrostFsMatchType matchType, ulong epoch) : FrostFsObjectFilter(matchType, Constants.FilterHeaderCreationEpoch, epoch) { } /// /// Creates filter to search by Payload Length /// /// Match type /// Payload Length -public class FilterByPayloadLength(FrostFsObjectMatchType matchType, ulong payloadLength) : FrostFsObjectFilter(matchType, Constants.FilterHeaderPayloadLength, payloadLength) { } +public class FilterByPayloadLength(FrostFsMatchType matchType, ulong payloadLength) : FrostFsObjectFilter(matchType, Constants.FilterHeaderPayloadLength, payloadLength) { } /// /// Creates filter to search by Payload Hash /// /// Match type /// Payload Hash -public class FilterByPayloadHash(FrostFsObjectMatchType matchType, CheckSum payloadHash) : FrostFsObjectFilter(matchType, Constants.FilterHeaderPayloadHash, payloadHash) { } +public class FilterByPayloadHash(FrostFsMatchType matchType, CheckSum payloadHash) : FrostFsObjectFilter(matchType, Constants.FilterHeaderPayloadHash, payloadHash) { } /// /// Creates filter to search by Parent /// /// Match type /// Parent -public class FilterByParent(FrostFsObjectMatchType matchType, FrostFsObjectId parentId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderParent, parentId) { } +public class FilterByParent(FrostFsMatchType matchType, FrostFsObjectId parentId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderParent, parentId) { } /// /// Creates filter to search by SplitId /// /// Match type /// SplitId -public class FilterBySplitId(FrostFsObjectMatchType matchType, SplitId splitId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderSplitID, splitId) { } +public class FilterBySplitId(FrostFsMatchType matchType, SplitId splitId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderSplitID, splitId) { } /// /// Creates filter to search by Payload Hash /// /// Match type /// Payload Hash -public class FilterByECParent(FrostFsObjectMatchType matchType, FrostFsObjectId ecParentId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderECParent, ecParentId) { } +public class FilterByECParent(FrostFsMatchType matchType, FrostFsObjectId ecParentId) : FrostFsObjectFilter(matchType, Constants.FilterHeaderECParent, ecParentId) { } /// /// Creates filter to search Root objects /// -public class FilterByRootObject() : FrostFsObjectFilter(FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderRoot, string.Empty) { } +public class FilterByRootObject() : FrostFsObjectFilter(FrostFsMatchType.Unspecified, Constants.FilterHeaderRoot, string.Empty) { } /// /// Creates filter to search objects that are physically stored on the server /// (FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderPhy, string.Empty) { } +public class FilterByPhysicallyStored() : FrostFsObjectFilter(FrostFsMatchType.Unspecified, Constants.FilterHeaderPhy, string.Empty) { } diff --git a/src/FrostFS.SDK.Tests/SmokeTests.cs b/src/FrostFS.SDK.Tests/SmokeTests.cs index f344303..548d757 100644 --- a/src/FrostFS.SDK.Tests/SmokeTests.cs +++ b/src/FrostFS.SDK.Tests/SmokeTests.cs @@ -183,25 +183,25 @@ public class SmokeTests : SmokeTestsBase var networkInfo = await client.GetNetmapSnapshotAsync(); - await CheckFilter(client, containerId, new FilterByContainerId(FrostFsObjectMatchType.Equals, containerId)); + await CheckFilter(client, containerId, new FilterByContainerId(FrostFsMatchType.Equals, containerId)); - await CheckFilter(client, containerId, new FilterByOwnerId(FrostFsObjectMatchType.Equals, FrostFsOwner.FromKey(ecdsaKey))); + await CheckFilter(client, containerId, new FilterByOwnerId(FrostFsMatchType.Equals, FrostFsOwner.FromKey(ecdsaKey))); - await CheckFilter(client, containerId, new FilterBySplitId(FrostFsObjectMatchType.Equals, param.Header.Split.SplitId)); + await CheckFilter(client, containerId, new FilterBySplitId(FrostFsMatchType.Equals, param.Header.Split.SplitId)); - await CheckFilter(client, containerId, new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test")); + await CheckFilter(client, containerId, new FilterByAttribute(FrostFsMatchType.Equals, "fileName", "test")); - await CheckFilter(client, containerId, new FilterByObjectId(FrostFsObjectMatchType.Equals, objectId)); + await CheckFilter(client, containerId, new FilterByObjectId(FrostFsMatchType.Equals, objectId)); - await CheckFilter(client, containerId, new FilterByVersion(FrostFsObjectMatchType.Equals, networkInfo.NodeInfoCollection[0].Version)); + await CheckFilter(client, containerId, new FilterByVersion(FrostFsMatchType.Equals, networkInfo.NodeInfoCollection[0].Version)); - await CheckFilter(client, containerId, new FilterByEpoch(FrostFsObjectMatchType.Equals, networkInfo.Epoch)); + await CheckFilter(client, containerId, new FilterByEpoch(FrostFsMatchType.Equals, networkInfo.Epoch)); - await CheckFilter(client, containerId, new FilterByPayloadLength(FrostFsObjectMatchType.Equals, 3)); + await CheckFilter(client, containerId, new FilterByPayloadLength(FrostFsMatchType.Equals, 3)); var checkSum = CheckSum.CreateCheckSum(bytes); - await CheckFilter(client, containerId, new FilterByPayloadHash(FrostFsObjectMatchType.Equals, checkSum)); + await CheckFilter(client, containerId, new FilterByPayloadHash(FrostFsMatchType.Equals, checkSum)); await CheckFilter(client, containerId, new FilterByPhysicallyStored()); } @@ -272,7 +272,7 @@ public class SmokeTests : SmokeTestsBase var objectId = await client.PutObjectAsync(param); - var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); + var filter = new FilterByAttribute(FrostFsMatchType.Equals, "fileName", "test"); bool hasObject = false; await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(createdContainer) { Filters = [filter] })) @@ -357,7 +357,7 @@ public class SmokeTests : SmokeTestsBase var objectId = await client.PutObjectAsync(param); - var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); + var filter = new FilterByAttribute(FrostFsMatchType.Equals, "fileName", "test"); bool hasObject = false; await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(container) { Filters = [filter], SessionToken = token })) @@ -438,7 +438,7 @@ public class SmokeTests : SmokeTestsBase var objectId = await client.PutObjectAsync(param); - var filter = new FilterByAttribute(FrostFsObjectMatchType.Equals, "fileName", "test"); + var filter = new FilterByAttribute(FrostFsMatchType.Equals, "fileName", "test"); bool hasObject = false; await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId, filter))) -- 2.45.2