[#23] Client: Refactoring to optimize memory usage

Signed-off-by: Pavel Gross <p.gross@yando.com>
This commit is contained in:
Pavel Gross 2024-09-11 10:44:30 +03:00
parent 1a02ac2ae7
commit 6562aa27a5
141 changed files with 1722 additions and 896 deletions

View file

@ -1,16 +1,13 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
#
VisualStudioVersion = 17.5.002.0 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}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ClientV2", "src\FrostFS.SDK.ClientV2\FrostFS.SDK.ClientV2.csproj", "{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.Cryptography", "src\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj", "{3D804F4A-B0B2-47A5-B006-BE447BE64B50}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.Cryptography", "src\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj", "{3D804F4A-B0B2-47A5-B006-BE447BE64B50}"
EndProject 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}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ProtosV2", "src\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj", "{5012EF96-9C9E-4E77-BC78-B4111EE54107}"
EndProject 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution 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}.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.ActiveCfg = Release|Any CPU
{3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{5012EF96-9C9E-4E77-BC78-B4111EE54107}.Debug|Any CPU.Build.0 = 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 {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.ActiveCfg = Release|Any CPU

175
README.md
View file

@ -21,137 +21,62 @@ neo-go wallet export -w <path_to_your_wallet> -d <address_from_p1>
### Container ### Container
```csharp ```csharp
using FrostFS.SDK;
using FrostFS.SDK.ClientV2; using FrostFS.SDK.ClientV2;
using FrostFS.SDK.ModelsV2;
using FrostFS.SDK.ModelsV2.Enums;
using FrostFS.SDK.ModelsV2.Netmap;
var fsClient = Client.GetInstance(<your_key>, <your_host>); using Microsoft.Extensions.Options;
// List containers var Key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
var containersIds = await fsClient.ListContainersAsync(); var Host = "http://172.22.33.44:8080";
// Create container var options = Options.Create(new SingleOwnerClientSettings
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(<your_key>, <your_host>);
// 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(<your_key>, <your_host>);
ContainerId containerId = <containerId>;
string fileName = <fileName>;
await PutObjectClientCut(fsClient, containerId, fileName);
static async Task<ObjectId?> PutObjectClientCut(IFrostFSClient fsClient, ContainerId containerId, string fileName)
{ {
List<ObjectId> sentObjectIds = []; Key = Key,
FrostFS.SDK.ModelsV2.Object? currentObject; Host = Host
});
var partSize = 1024 * 1024; using var client = Client.GetSingleOwnerInstance(options);
var buffer = new byte[partSize];
var largeObject = new LargeObject(containerId); await foreach (var cid in client.ListContainersAsync())
{
var split = new Split(); await client.DeleteContainerAsync(new PrmContainerDelete(cid));
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);
} }
``` 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<byte>? chunk = null;
while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
{
ms.Write(chunk.Value.Span);
}
```

View file

@ -1,6 +1,4 @@
 using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Caching.Memory;
namespace FrostFS.SDK.ClientV2 namespace FrostFS.SDK.ClientV2
{ {

View file

@ -1,21 +1,21 @@
using FrostFS.Container; using System;
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.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; 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; namespace FrostFS.SDK.ClientV2;
@ -70,14 +70,14 @@ public class Client : IFrostFSClient
ObjectService.ObjectServiceClient objectService) ObjectService.ObjectServiceClient objectService)
{ {
var ecdsaKey = settings.Value.Key.LoadWif(); var ecdsaKey = settings.Value.Key.LoadWif();
OwnerId.FromKey(ecdsaKey); FrostFsOwner.FromKey(ecdsaKey);
ClientCtx = new ClientEnvironment( ClientCtx = new ClientEnvironment(
client: this, client: this,
key: ecdsaKey, key: ecdsaKey,
owner: OwnerId.FromKey(ecdsaKey), owner: FrostFsOwner.FromKey(ecdsaKey),
channel: InitGrpcChannel(settings.Value.Host, channelOptions), channel: InitGrpcChannel(settings.Value.Host, channelOptions),
version: new Version(2, 13)); version: new FrostFsVersion(2, 13));
ContainerServiceClient = containerService; ContainerServiceClient = containerService;
NetmapServiceClient = netmapService; NetmapServiceClient = netmapService;
@ -98,7 +98,7 @@ public class Client : IFrostFSClient
key: null, key: null,
owner: null, owner: null,
channel: channel, channel: channel,
version: new Version(2, 13)); version: new FrostFsVersion(2, 13));
// TODO: define timeout logic // TODO: define timeout logic
// CheckFrostFsVersionSupport(new Context { Timeout = TimeSpan.FromSeconds(20) }); // CheckFrostFsVersionSupport(new Context { Timeout = TimeSpan.FromSeconds(20) });
@ -117,9 +117,9 @@ public class Client : IFrostFSClient
ClientCtx = new ClientEnvironment( ClientCtx = new ClientEnvironment(
this, this,
key: ecdsaKey, key: ecdsaKey,
owner: OwnerId.FromKey(ecdsaKey), owner: FrostFsOwner.FromKey(ecdsaKey),
channel: channel, channel: channel,
version: new Version(2, 13)); version: new FrostFsVersion(2, 13));
// TODO: define timeout logic // TODO: define timeout logic
CheckFrostFsVersionSupport(new Context { Timeout = TimeSpan.FromSeconds(20)}); CheckFrostFsVersionSupport(new Context { Timeout = TimeSpan.FromSeconds(20)});
@ -135,26 +135,26 @@ public class Client : IFrostFSClient
{ {
if (disposing && !isDisposed) if (disposing && !isDisposed)
{ {
ClientCtx.Dispose(); ClientCtx?.Dispose();
isDisposed = true; isDisposed = true;
} }
} }
#region ContainerImplementation #region ContainerImplementation
public Task<ModelsV2.Container> GetContainerAsync(PrmContainerGet args) public Task<FrostFsContainerInfo> GetContainerAsync(PrmContainerGet args)
{ {
var service = GetContainerService(args); var service = GetContainerService(args);
return service.GetContainerAsync(args); return service.GetContainerAsync(args);
} }
public IAsyncEnumerable<ContainerId> ListContainersAsync(PrmContainerGetAll? args = null) public IAsyncEnumerable<FrostFsContainerId> ListContainersAsync(PrmContainerGetAll? args = null)
{ {
args ??= new PrmContainerGetAll(); args ??= new PrmContainerGetAll();
var service = GetContainerService(args); var service = GetContainerService(args);
return service.ListContainersAsync(args); return service.ListContainersAsync(args);
} }
public Task<ContainerId> CreateContainerAsync(PrmContainerCreate args) public Task<FrostFsContainerId> CreateContainerAsync(PrmContainerCreate args)
{ {
var service = GetContainerService(args); var service = GetContainerService(args);
return service.CreateContainerAsync(args); return service.CreateContainerAsync(args);
@ -168,14 +168,14 @@ public class Client : IFrostFSClient
#endregion #endregion
#region NetworkImplementation #region NetworkImplementation
public Task<NetmapSnapshot> GetNetmapSnapshotAsync(PrmNetmapSnapshot? args) public Task<FrostFsNetmapSnapshot> GetNetmapSnapshotAsync(PrmNetmapSnapshot? args)
{ {
args ??= new PrmNetmapSnapshot(); args ??= new PrmNetmapSnapshot();
var service = GetNetmapService(args); var service = GetNetmapService(args);
return service.GetNetmapSnapshotAsync(args); return service.GetNetmapSnapshotAsync(args);
} }
public Task<ModelsV2.Netmap.NodeInfo> GetNodeInfoAsync(PrmNodeInfo? args) public Task<FrostFsNodeInfo> GetNodeInfoAsync(PrmNodeInfo? args)
{ {
args ??= new PrmNodeInfo(); args ??= new PrmNodeInfo();
var service = GetNetmapService(args); var service = GetNetmapService(args);
@ -191,7 +191,7 @@ public class Client : IFrostFSClient
#endregion #endregion
#region ObjectImplementation #region ObjectImplementation
public Task<ObjectHeader> GetObjectHeadAsync(PrmObjectHeadGet args) public Task<FrostFsObjectHeader> GetObjectHeadAsync(PrmObjectHeadGet args)
{ {
var service = GetObjectService(args); var service = GetObjectService(args);
return service.GetObjectHeadAsync(args); return service.GetObjectHeadAsync(args);
@ -203,13 +203,13 @@ public class Client : IFrostFSClient
return service.GetObjectAsync(args); return service.GetObjectAsync(args);
} }
public Task<ObjectId> PutObjectAsync(PrmObjectPut args) public Task<FrostFsObjectId> PutObjectAsync(PrmObjectPut args)
{ {
var service = GetObjectService(args); var service = GetObjectService(args);
return service.PutObjectAsync(args); return service.PutObjectAsync(args);
} }
public Task<ObjectId> PutSingleObjectAsync(PrmSingleObjectPut args) public Task<FrostFsObjectId> PutSingleObjectAsync(PrmSingleObjectPut args)
{ {
var service = GetObjectService(args); var service = GetObjectService(args);
return service.PutSingleObjectAsync(args); return service.PutSingleObjectAsync(args);
@ -221,7 +221,7 @@ public class Client : IFrostFSClient
return service.DeleteObjectAsync(args); return service.DeleteObjectAsync(args);
} }
public IAsyncEnumerable<ObjectId> SearchObjectsAsync(PrmObjectSearch args) public IAsyncEnumerable<FrostFsObjectId> SearchObjectsAsync(PrmObjectSearch args)
{ {
var service = GetObjectService(args); var service = GetObjectService(args);
return service.SearchObjectsAsync(args); return service.SearchObjectsAsync(args);
@ -229,12 +229,12 @@ public class Client : IFrostFSClient
#endregion #endregion
#region SessionImplementation #region SessionImplementation
public async Task<ModelsV2.SessionToken> CreateSessionAsync(PrmSessionCreate args) public async Task<FrostFsSessionToken> CreateSessionAsync(PrmSessionCreate args)
{ {
var session = await CreateSessionInternalAsync(args); var session = await CreateSessionInternalAsync(args);
var token = session.Serialize(); var token = session.Serialize();
return new ModelsV2.SessionToken(token); return new FrostFsSessionToken(token);
} }
internal Task<Session.SessionToken> CreateSessionInternalAsync(PrmSessionCreate args) internal Task<Session.SessionToken> CreateSessionInternalAsync(PrmSessionCreate args)
@ -245,7 +245,7 @@ public class Client : IFrostFSClient
#endregion #endregion
#region ToolsImplementation #region ToolsImplementation
public ObjectId CalculateObjectId(ObjectHeader header, Context ctx) public FrostFsObjectId CalculateObjectId(FrostFsObjectHeader header, Context ctx)
{ {
if (header == null) if (header == null)
throw new ArgumentNullException(nameof(header)); throw new ArgumentNullException(nameof(header));
@ -286,7 +286,7 @@ public class Client : IFrostFSClient
if (ctx.Context.OwnerId == null) 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) if (ctx.Context.Version == null)

View file

@ -1,6 +1,8 @@
using FrostFS.SDK.Cryptography; using System.Security.Cryptography;
using FrostFS.SDK.Cryptography;
using Google.Protobuf; using Google.Protobuf;
using System.Security.Cryptography;
namespace FrostFS.SDK.ClientV2 namespace FrostFS.SDK.ClientV2
{ {

View file

@ -0,0 +1,7 @@
using System;
namespace FrostFS.SDK.ClientV2;
public class InvalidObjectException() : Exception()
{
}

View file

@ -1,9 +1,8 @@
using FrostFS.SDK.ModelsV2;
using System; using System;
namespace FrostFS.SDK.ClientV2; 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;
} }

View file

@ -21,7 +21,6 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" /> <ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" />
<ProjectReference Include="..\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj" />
<ProjectReference Include="..\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj" /> <ProjectReference Include="..\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -1,7 +1,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using FrostFS.SDK.ModelsV2;
using Grpc.Core; using Grpc.Core;
using Grpc.Core.Interceptors; using Grpc.Core.Interceptors;

View file

@ -1,50 +1,49 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using FrostFS.SDK.ClientV2.Parameters;
using FrostFS.SDK.ModelsV2; using FrostFS.SDK.ClientV2;
using FrostFS.SDK.ModelsV2.Netmap;
namespace FrostFS.SDK.ClientV2.Interfaces; namespace FrostFS.SDK.ClientV2.Interfaces;
public interface IFrostFSClient : IDisposable public interface IFrostFSClient : IDisposable
{ {
#region Network #region Network
Task<NetmapSnapshot> GetNetmapSnapshotAsync(PrmNetmapSnapshot? args = null); Task<FrostFsNetmapSnapshot> GetNetmapSnapshotAsync(PrmNetmapSnapshot? args = null);
Task<NodeInfo> GetNodeInfoAsync(PrmNodeInfo? args = null); Task<FrostFsNodeInfo> GetNodeInfoAsync(PrmNodeInfo? args = null);
Task<NetworkSettings> GetNetworkSettingsAsync(PrmNetworkSettings? args = null); Task<NetworkSettings> GetNetworkSettingsAsync(PrmNetworkSettings? args = null);
#endregion #endregion
#region Session #region Session
Task<SessionToken> CreateSessionAsync(PrmSessionCreate args); Task<FrostFsSessionToken> CreateSessionAsync(PrmSessionCreate args);
#endregion #endregion
#region Container #region Container
Task<ModelsV2.Container> GetContainerAsync(PrmContainerGet args); Task<FrostFsContainerInfo> GetContainerAsync(PrmContainerGet args);
IAsyncEnumerable<ContainerId> ListContainersAsync(PrmContainerGetAll? args = null); IAsyncEnumerable<FrostFsContainerId> ListContainersAsync(PrmContainerGetAll? args = null);
Task<ContainerId> CreateContainerAsync(PrmContainerCreate args); Task<FrostFsContainerId> CreateContainerAsync(PrmContainerCreate args);
Task DeleteContainerAsync(PrmContainerDelete args); Task DeleteContainerAsync(PrmContainerDelete args);
#endregion #endregion
#region Object #region Object
Task<ObjectHeader> GetObjectHeadAsync(PrmObjectHeadGet args); Task<FrostFsObjectHeader> GetObjectHeadAsync(PrmObjectHeadGet args);
Task<FrostFsObject> GetObjectAsync(PrmObjectGet args); Task<FrostFsObject> GetObjectAsync(PrmObjectGet args);
Task<ObjectId> PutObjectAsync(PrmObjectPut putObjectParameters); Task<FrostFsObjectId> PutObjectAsync(PrmObjectPut args);
Task<ObjectId> PutSingleObjectAsync(PrmSingleObjectPut args); Task<FrostFsObjectId> PutSingleObjectAsync(PrmSingleObjectPut args);
Task DeleteObjectAsync(PrmObjectDelete args); Task DeleteObjectAsync(PrmObjectDelete args);
IAsyncEnumerable<ObjectId> SearchObjectsAsync(PrmObjectSearch args); IAsyncEnumerable<FrostFsObjectId> SearchObjectsAsync(PrmObjectSearch args);
#endregion #endregion
#region Tools #region Tools
ObjectId CalculateObjectId(ObjectHeader header, Context ctx); FrostFsObjectId CalculateObjectId(FrostFsObjectHeader header, Context ctx);
#endregion #endregion
} }

View file

@ -1,36 +1,24 @@
using System; using System;
using System.Linq;
using Google.Protobuf;
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ModelsV2.Enums;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class ContainerMapper public static class ContainerMapper
{ {
public static Container.Container ToMessage(this ModelsV2.Container container) public static FrostFsContainerInfo ToModel(this Container.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)
{ {
if (!Enum.IsDefined(typeof(BasicAcl),(int)container.BasicAcl)) if (!Enum.IsDefined(typeof(BasicAcl),(int)container.BasicAcl))
throw new ArgumentException($"Unknown BasicACL rule. Value: '{container.BasicAcl}'."); throw new ArgumentException($"Unknown BasicACL rule. Value: '{container.BasicAcl}'.");
BasicAcl acl = (BasicAcl)container.BasicAcl; BasicAcl acl = (BasicAcl)container.BasicAcl;
return new ModelsV2.Container(acl, container.PlacementPolicy.ToModel()) return new FrostFsContainerInfo(acl,
{ container.PlacementPolicy.ToModel(),
Nonce = container.Nonce.ToUuid(), container.Attributes?.Select(a => new FrostFsAttribute(a.Key, a.Value)).ToList(),
Version = container.Version.ToModel() container.Version?.ToModel(),
}; container.OwnerId?.ToModel(),
container.Nonce?.ToUuid());
} }
} }

View file

@ -1,9 +1,11 @@
using System;
using FrostFS.Refs; using FrostFS.Refs;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ModelsV2;
using Google.Protobuf; using Google.Protobuf;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using System;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
@ -13,16 +15,19 @@ public static class ContainerIdMapper
.SetSlidingExpiration(TimeSpan.FromHours(1)) .SetSlidingExpiration(TimeSpan.FromHours(1))
.SetSize(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 message = new ContainerID
{ {
Value = ByteString.CopyFrom(Base58.Decode(model.Value)) Value = ByteString.CopyFrom(Base58.Decode(model.Value))
}; };
Cache.Containers.Set(model, message, _oneHourExpiration); Cache.Containers.Set(model.Value, message, _oneHourExpiration);
} }
return message!; return message!;

View file

@ -1,4 +1,3 @@
using FrostFS.SDK.ModelsV2;
using FrostFS.Session; using FrostFS.Session;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;

View file

@ -1,14 +1,14 @@
using System.Linq; 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 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.Epoch,
netmap.Body.Netmap.Nodes netmap.Body.Netmap.Nodes
.Select(n => n.ToModel(netmap.MetaHeader.Version)) .Select(n => n.ToModel(netmap.MetaHeader.Version))

View file

@ -1,30 +1,30 @@
using System; using System;
using System.Linq; 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 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); 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 NodeState state = nodeInfo.State switch
{ {
FrostFS.Netmap.NodeInfo.Types.State.Unspecified => NodeState.Unspecified, NodeInfo.Types.State.Unspecified => NodeState.Unspecified,
FrostFS.Netmap.NodeInfo.Types.State.Online => NodeState.Online, NodeInfo.Types.State.Online => NodeState.Online,
FrostFS.Netmap.NodeInfo.Types.State.Offline => NodeState.Offline, NodeInfo.Types.State.Offline => NodeState.Offline,
FrostFS.Netmap.NodeInfo.Types.State.Maintenance => NodeState.Maintenance, NodeInfo.Types.State.Maintenance => NodeState.Maintenance,
_ => throw new ArgumentException($"Unknown NodeState. Value: '{nodeInfo.State}'.") _ => throw new ArgumentException($"Unknown NodeState. Value: '{nodeInfo.State}'.")
}; };
return new NodeInfo( return new FrostFsNodeInfo(
version: version.ToModel(), version: version.ToModel(),
state: state, state: state,
addresses: [.. nodeInfo.Addresses], addresses: [.. nodeInfo.Addresses],

View file

@ -1,11 +1,12 @@
using System.Linq; using System.Linq;
using FrostFS.Netmap; using FrostFS.Netmap;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; namespace FrostFS.SDK.ClientV2;
public static class PlacementPolicyMapper public static class PlacementPolicyMapper
{ {
public static PlacementPolicy ToMessage(this ModelsV2.Netmap.PlacementPolicy placementPolicy) public static PlacementPolicy ToMessage(this FrostFsPlacementPolicy placementPolicy)
{ {
var pp = new PlacementPolicy var pp = new PlacementPolicy
{ {
@ -23,9 +24,9 @@ public static class PlacementPolicyMapper
return pp; 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.Unique,
placementPolicy.Replicas.Select(replica => replica.ToModel()).ToArray() placementPolicy.Replicas.Select(replica => replica.ToModel()).ToArray()
); );

View file

@ -1,10 +1,10 @@
using FrostFS.Netmap; using FrostFS.Netmap;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; namespace FrostFS.SDK.ClientV2;
public static class ReplicaMapper public static class ReplicaMapper
{ {
public static Replica ToMessage(this ModelsV2.Netmap.Replica replica) public static Replica ToMessage(this FrostFsReplica replica)
{ {
return new 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);
} }
} }

View file

@ -1,5 +1,3 @@
using FrostFS.SDK.ModelsV2;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
internal static class ObjectMapper internal static class ObjectMapper
@ -8,7 +6,7 @@ internal static class ObjectMapper
{ {
return new FrostFsObject(obj.Header.ToModel()) return new FrostFsObject(obj.Header.ToModel())
{ {
ObjectId = ObjectId.FromHash(obj.ObjectId.Value.ToByteArray()) ObjectId = FrostFsObjectId.FromHash(obj.ObjectId.Value.ToByteArray())
}; };
} }
} }

View file

@ -1,11 +1,10 @@
using FrostFS.Object; using FrostFS.Object;
using FrostFS.SDK.ModelsV2;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class ObjectAttributeMapper 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 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);
} }
} }

View file

@ -1,7 +1,6 @@
using System; using System;
using FrostFS.Object; using FrostFS.Object;
using FrostFS.SDK.ModelsV2;
using MatchType = FrostFS.Object.MatchType;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
@ -11,11 +10,11 @@ public static class ObjectFilterMapper
{ {
var objMatchTypeName = filter.MatchType switch var objMatchTypeName = filter.MatchType switch
{ {
ModelsV2.Enums.ObjectMatchType.Unspecified => MatchType.Unspecified, FrostFsObjectMatchType.Unspecified => MatchType.Unspecified,
ModelsV2.Enums.ObjectMatchType.Equals => MatchType.StringEqual, FrostFsObjectMatchType.Equals => MatchType.StringEqual,
ModelsV2.Enums.ObjectMatchType.NotEquals => MatchType.StringNotEqual, FrostFsObjectMatchType.NotEquals => MatchType.StringNotEqual,
ModelsV2.Enums.ObjectMatchType.KeyAbsent => MatchType.NotPresent, FrostFsObjectMatchType.KeyAbsent => MatchType.NotPresent,
ModelsV2.Enums.ObjectMatchType.StartsWith => MatchType.CommonPrefix, FrostFsObjectMatchType.StartsWith => MatchType.CommonPrefix,
_ => throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.") _ => throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.")
}; };

View file

@ -1,75 +1,28 @@
using System; using System;
using System.Linq; using System.Linq;
using FrostFS.Object; using FrostFS.Object;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ModelsV2;
using Google.Protobuf;
using ObjectType = FrostFS.Object.ObjectType;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class ObjectHeaderMapper public static class ObjectHeaderMapper
{ {
public static Header ToMessage(this ObjectHeader header) public static FrostFsObjectHeader ToModel(this Header header)
{ {
var objTypeName = header.ObjectType switch var objTypeName = header.ObjectType switch
{ {
ModelsV2.Enums.ObjectType.Regular => ObjectType.Regular, ObjectType.Regular => FrostFsObjectType.Regular,
ModelsV2.Enums.ObjectType.Lock => ObjectType.Lock, ObjectType.Lock => FrostFsObjectType.Lock,
ModelsV2.Enums.ObjectType.Tombstone => ObjectType.Tombstone, ObjectType.Tombstone => FrostFsObjectType.Tombstone,
_ => throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.") _ => throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.")
}; };
var head = new Header FrostFsSplit? split = null;
{
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()
};
if (header.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(), Parent = header.Split.Parent?.ToModel(),
ParentHeader = header.Split.ParentHeader?.ToModel(), ParentHeader = header.Split.ParentHeader?.ToModel(),
@ -77,9 +30,20 @@ public static class ObjectHeaderMapper
}; };
if (header.Split.Children.Count != 0) 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; return model;
} }
} }

View file

@ -1,12 +1,12 @@
using FrostFS.Refs; using FrostFS.Refs;
using FrostFS.SDK.ModelsV2;
using Google.Protobuf; using Google.Protobuf;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class ObjectIdMapper public static class ObjectIdMapper
{ {
public static ObjectID ToMessage(this ObjectId objectId) public static ObjectID ToMessage(this FrostFsObjectId objectId)
{ {
return new 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());
} }
} }

View file

@ -1,9 +1,11 @@
using System;
using FrostFS.Refs; using FrostFS.Refs;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ModelsV2;
using Google.Protobuf; using Google.Protobuf;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using System;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
@ -13,7 +15,7 @@ public static class OwnerIdMapper
.SetSlidingExpiration(TimeSpan.FromHours(1)) .SetSlidingExpiration(TimeSpan.FromHours(1))
.SetSize(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)) if (!Cache.Owners.TryGetValue(model, out OwnerID? message))
{ {
@ -28,11 +30,11 @@ public static class OwnerIdMapper
return message!; 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); Cache.Owners.Set(message, model, _oneHourExpiration);
} }

View file

@ -1,12 +1,12 @@
using System; using System;
using FrostFS.SDK.ModelsV2;
using Google.Protobuf; using Google.Protobuf;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class SignatureMapper 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 var scheme = signature.Scheme switch
{ {

View file

@ -1,19 +1,18 @@
using System; using System;
using FrostFS.SDK.ModelsV2.Enums;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class StatusMapper 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) 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 return codeName is null
? throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'.") ? 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);
} }
} }

View file

@ -1,6 +1,7 @@
using System.Collections; using System.Collections;
using System.Threading; using System.Threading;
using Version = FrostFS.Refs.Version;
using FrostFS.Refs;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
@ -10,7 +11,7 @@ public static class VersionMapper
private static readonly Hashtable _cacheModels = []; private static readonly Hashtable _cacheModels = [];
private static SpinLock _spinlock = new(); 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; var key = model.Major << 16 + model.Minor;
@ -31,7 +32,7 @@ public static class VersionMapper
} }
catch (System.ArgumentException) catch (System.ArgumentException)
{ {
// ignore attempt to add duplicate error. // ignore attempt to add duplicate
} }
finally finally
{ {
@ -43,7 +44,7 @@ public static class VersionMapper
return (Version)_cacheMessages[key]; 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; var key = (int)message.Major << 16 + (int)message.Minor;
@ -53,14 +54,14 @@ public static class VersionMapper
try try
{ {
_spinlock.Enter(ref lockTaken); _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); _cacheModels.Add(key, model);
return model; return model;
} }
catch (System.ArgumentException) catch (System.ArgumentException)
{ {
// ignore attempt to add duplicate error. // ignore attempt to add duplicate
} }
finally finally
{ {
@ -69,6 +70,6 @@ public static class VersionMapper
} }
} }
return (ModelsV2.Version)_cacheModels[key]; return (FrostFsVersion)_cacheModels[key];
} }
} }

View file

@ -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<string>? CheckFields()
{
List<string>? errors = null;
if (string.IsNullOrWhiteSpace(Host))
(errors ??= []).Add(string.Format(errorTemplate, nameof(Host)));
return errors;
}
protected static void ThrowException(List<string> 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<string>? CheckFields()
{
List<string>? errors = base.CheckFields();
if (string.IsNullOrWhiteSpace(Key))
(errors ??= []).Add(string.Format(errorTemplate, nameof(Key)));
return errors;
}
}

View file

@ -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;
}
}

View file

@ -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<FrostFsAttribute>? attributes;
private FrostFsPlacementPolicy? placementPolicy;
private Guid? nonce;
private Container.Container container;
public FrostFsContainerInfo(
BasicAcl basicAcl,
FrostFsPlacementPolicy placementPolicy,
List<FrostFsAttribute>? 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<FrostFsAttribute>? 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;
}
}

View file

@ -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,
}

View file

@ -1,6 +1,6 @@
namespace FrostFS.SDK.ModelsV2.Enums; namespace FrostFS.SDK;
public enum ObjectMatchType public enum FrostFsObjectMatchType
{ {
Unspecified = 0, Unspecified = 0,
Equals = 1, Equals = 1,

View file

@ -0,0 +1,8 @@
namespace FrostFS.SDK;
public enum FrostFsObjectType
{
Regular = 0,
Tombstone = 1,
Lock = 3
}

View file

@ -1,6 +1,6 @@
namespace FrostFS.SDK.ModelsV2.Enums; namespace FrostFS.SDK;
public enum StatusCode public enum FrostFsStatusCode
{ {
Success = 0, Success = 0,
Internal = 1024, Internal = 1024,

View file

@ -0,0 +1,9 @@
namespace FrostFS.SDK;
public enum NodeState
{
Unspecified = 0,
Online = 1,
Offline = 2,
Maintenance = 3
}

View file

@ -0,0 +1,8 @@
namespace FrostFS.SDK;
public enum SignatureScheme
{
EcdsaSha512,
EcdsaRfc6979Sha256,
EcdsaRfc6979Sha256WalletConnect
}

View file

@ -0,0 +1,7 @@
namespace FrostFS.SDK;
public class CallStatistics
{
public string? MethodName { get; set; }
public long ElapsedMicroSeconds { get; set; }
}

View file

@ -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("-", "");
}
}

View file

@ -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";
}

View file

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace FrostFS.SDK;
public class FrostFsNetmapSnapshot(ulong epoch, IReadOnlyList<FrostFsNodeInfo> nodeInfoCollection)
{
public ulong Epoch { get; private set; } = epoch;
public IReadOnlyList<FrostFsNodeInfo> NodeInfoCollection { get; private set; } = nodeInfoCollection;
}

View file

@ -1,18 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using FrostFS.SDK.ModelsV2.Enums;
namespace FrostFS.SDK.ModelsV2.Netmap; namespace FrostFS.SDK;
public class NodeInfo( public class FrostFsNodeInfo(
Version version, FrostFsVersion version,
NodeState state, NodeState state,
IReadOnlyCollection<string> addresses, IReadOnlyCollection<string> addresses,
IReadOnlyDictionary<string, string> attributes, IReadOnlyDictionary<string, string> attributes,
ReadOnlyMemory<byte> publicKey) ReadOnlyMemory<byte> publicKey)
{ {
public NodeState State { get; private set; } = state; public NodeState State { get; private set; } = state;
public Version Version { get; private set; } = version; public FrostFsVersion Version { get; private set; } = version;
public IReadOnlyCollection<string> Addresses { get; private set; } = addresses; public IReadOnlyCollection<string> Addresses { get; private set; } = addresses;
public IReadOnlyDictionary<string, string> Attributes { get; private set; } = attributes; public IReadOnlyDictionary<string, string> Attributes { get; private set; } = attributes;
public ReadOnlyMemory<byte> PublicKey { get; private set; } = publicKey; public ReadOnlyMemory<byte> PublicKey { get; private set; } = publicKey;

View file

@ -1,16 +1,16 @@
using System; using System;
using System.Linq; using System.Linq;
namespace FrostFS.SDK.ModelsV2.Netmap; namespace FrostFS.SDK;
public class PlacementPolicy(bool unique, params Replica[] replicas) : IComparable<PlacementPolicy> public class FrostFsPlacementPolicy(bool unique, params FrostFsReplica[] replicas) : IComparable<FrostFsPlacementPolicy>
{ {
public Replica[] Replicas { get; private set; } = replicas; public FrostFsReplica[] Replicas { get; private set; } = replicas;
public bool Unique { get; private set; } = unique; 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 || Unique != other.Unique
|| Replicas.Length != other.Replicas.Length; || Replicas.Length != other.Replicas.Length;

View file

@ -1,14 +1,14 @@
namespace FrostFS.SDK.ModelsV2.Netmap; namespace FrostFS.SDK;
public class Replica public class FrostFsReplica
{ {
public int Count { get; set; } public int Count { get; set; }
public string Selector { get; set; } public string Selector { get; set; }
public Replica(int count, string? selector = null) public FrostFsReplica(int count, string? selector = null)
{ {
selector ??= string.Empty; selector ??= string.Empty;
Count = count; Count = count;
Selector = selector; Selector = selector;
} }

View file

@ -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}";
}
}

View file

@ -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;
}

View file

@ -0,0 +1,9 @@
namespace FrostFS.SDK;
public class FrostFsLargeObject(FrostFsContainerId container) : FrostFsObject(container)
{
public ulong PayloadLength
{
get { return Header!.PayloadLength; }
}
}

View file

@ -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
};
}
}

View file

@ -0,0 +1,64 @@
using System;
namespace FrostFS.SDK;
public class FrostFsObject
{
/// <summary>
/// Creates new instance from <c>ObjectHeader</c>
/// </summary>
/// <param name="header"></param> <summary>
public FrostFsObject(FrostFsObjectHeader header)
{
Header = header;
}
/// <summary>
/// Creates new instance with specified parameters
/// </summary>
/// <param name="container"></param>
/// <param name="objectType"></param>
public FrostFsObject(FrostFsContainerId container, FrostFsObjectType objectType = FrostFsObjectType.Regular)
{
Header = new FrostFsObjectHeader(containerId: container, type: objectType);
}
/// <summary>
/// Header contains metadata for the object
/// </summary>
/// <value></value>
public FrostFsObjectHeader Header { get; set; }
/// <summary>
/// The value is calculated internally as a hash of ObjectHeader. Do not use pre-calculated value is the object has been changed.
/// </summary>
public FrostFsObjectId? ObjectId
{
get; set;
}
/// <summary>
/// The size of payload cannot exceed <c>MaxObjectSize</c> value from <c>NetworkSettings</c>
/// Used only for PutSingleObject method
/// </summary>
/// <value>Buffer for output data</value>
public byte[] Payload { get; set; } = [];
/// <summary>
/// A payload is obtained via stream reader
/// </summary>
/// <value>Reader for received data</value>
public IObjectReader? ObjectReader { get; set; }
/// <summary>
/// Applied only for the last Object in chain in case of manual multipart uploading
/// </summary>
/// <param name="largeObject">Parent for multipart object</param>
public void SetParent(FrostFsObjectHeader largeObjectHeader)
{
if (Header?.Split == null)
throw new Exception("The object is not initialized properly");
Header.Split.ParentHeader = largeObjectHeader;
}
}

View file

@ -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<T>(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();
}
}
/// <summary>
/// Creates filter to search by Attribute
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="key">Attribute key</param>
/// <param name="value">Attribute value</param>
public class FilterByAttribute(FrostFsObjectMatchType matchType, string key, string value) : FrostFsObjectFilter<string>(matchType, key, value) { }
/// <summary>
/// Creates filter to search by ObjectId
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="objectId">ObjectId</param>
public class FilterByObjectId(FrostFsObjectMatchType matchType, FrostFsObjectId objectId) : FrostFsObjectFilter<FrostFsObjectId>(matchType, Constants.FilterHeaderObjectID, objectId) { }
/// <summary>
/// Creates filter to search by OwnerId
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="ownerId">ObjectId</param>
public class FilterByOwnerId(FrostFsObjectMatchType matchType, FrostFsOwner ownerId) : FrostFsObjectFilter<FrostFsOwner>(matchType, Constants.FilterHeaderOwnerID, ownerId) { }
/// <summary>
/// Creates filter to search by Version
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="version">Version</param>
public class FilterByVersion(FrostFsObjectMatchType matchType, FrostFsVersion version) : FrostFsObjectFilter<FrostFsVersion>(matchType, Constants.FilterHeaderVersion, version) { }
/// <summary>
/// Creates filter to search by ContainerId
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="containerId">ContainerId</param>
public class FilterByContainerId(FrostFsObjectMatchType matchType, FrostFsContainerId containerId) : FrostFsObjectFilter<FrostFsContainerId>(matchType, Constants.FilterHeaderContainerID, containerId) { }
/// <summary>
/// Creates filter to search by creation Epoch
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="epoch">Creation Epoch</param>
public class FilterByEpoch(FrostFsObjectMatchType matchType, ulong epoch) : FrostFsObjectFilter<ulong>(matchType, Constants.FilterHeaderCreationEpoch, epoch) { }
/// <summary>
/// Creates filter to search by Payload Length
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="payloadLength">Payload Length</param>
public class FilterByPayloadLength(FrostFsObjectMatchType matchType, ulong payloadLength) : FrostFsObjectFilter<ulong>(matchType, Constants.FilterHeaderPayloadLength, payloadLength) { }
/// <summary>
/// Creates filter to search by Payload Hash
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="payloadHash">Payload Hash</param>
public class FilterByPayloadHash(FrostFsObjectMatchType matchType, CheckSum payloadHash) : FrostFsObjectFilter<CheckSum>(matchType, Constants.FilterHeaderPayloadHash, payloadHash) { }
/// <summary>
/// Creates filter to search by Parent
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="parentId">Parent</param>
public class FilterByParent(FrostFsObjectMatchType matchType, FrostFsObjectId parentId) : FrostFsObjectFilter<FrostFsObjectId>(matchType, Constants.FilterHeaderParent, parentId) { }
/// <summary>
/// Creates filter to search by SplitId
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="splitId">SplitId</param>
public class FilterBySplitId(FrostFsObjectMatchType matchType, SplitId splitId) : FrostFsObjectFilter<SplitId>(matchType, Constants.FilterHeaderSplitID, splitId) { }
/// <summary>
/// Creates filter to search by Payload Hash
/// </summary>
/// <param name="matchType">Match type</param>
/// <param name="ecParentId">Payload Hash</param>
public class FilterByECParent(FrostFsObjectMatchType matchType, FrostFsObjectId ecParentId) : FrostFsObjectFilter<FrostFsObjectId>(matchType, Constants.FilterHeaderECParent, ecParentId) { }
/// <summary>
/// Creates filter to search Root objects
/// </summary>
public class FilterByRootObject() : FrostFsObjectFilter<string>(FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderRoot, string.Empty) { }
/// <summary>
/// Creates filter to search objects that are physically stored on the server
/// </summary
public class FilterByPhysicallyStored() : FrostFsObjectFilter<string>(FrostFsObjectMatchType.Unspecified, Constants.FilterHeaderPhy, string.Empty) { }

View file

@ -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<FrostFsAttribute> 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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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<FrostFsObjectId> Children { get; } = [];
public Refs.Signature ParentSignatureGrpc { get; set; }
}

View file

@ -0,0 +1,10 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace FrostFS.SDK;
public interface IObjectReader : IDisposable
{
Task<ReadOnlyMemory<byte>?> ReadChunk(CancellationToken cancellationToken = default);
}

View file

@ -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());
}
}

View file

@ -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}.";
}
}

View file

@ -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; }
}

View file

@ -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
);
}
}

View file

@ -0,0 +1,6 @@
namespace FrostFS.SDK;
public class FrostFsSessionToken(byte[] token)
{
public byte[] Token { get; private set; } = token;
}

View file

@ -2,9 +2,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading; using System.Threading;
using FrostFS.SDK.ModelsV2;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using Google.Protobuf; using Google.Protobuf;
using Grpc.Core.Interceptors; using Grpc.Core.Interceptors;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;
@ -13,13 +15,13 @@ public class Context()
{ {
private List<Interceptor>? interceptors; private List<Interceptor>? interceptors;
private ByteString publicKeyCache; private ByteString? publicKeyCache;
public ECDsa Key { get; set; } 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; public CancellationToken CancellationToken { get; set; } = default;
@ -35,16 +37,13 @@ public class Context()
set { this.interceptors = value; } set { this.interceptors = value; }
} }
public ByteString PublicKeyCache public ByteString? GetPublicKeyCache()
{ {
get if (publicKeyCache == null && Key != null)
{ {
if (publicKeyCache == null) publicKeyCache = ByteString.CopyFrom(Key.PublicKey());
{
publicKeyCache = ByteString.CopyFrom(Key.PublicKey());
}
return publicKeyCache;
} }
return publicKeyCache;
} }
} }

View file

@ -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 ECDsa Key { get; } = key;
public OwnerId OwnerId { get; } = ownerId; public FrostFsOwner OwnerId { get; } = ownerId;
} }

View file

@ -1,4 +1,4 @@
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public interface IContext public interface IContext
{ {

View file

@ -1,6 +1,4 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2.Parameters;
public interface ISessionToken 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. /// member. The session has a limited validity period, and applies to a strictly defined set of operations.
/// </summary> /// </summary>
/// <value>Instance of the session obtained from the server</value> /// <value>Instance of the session obtained from the server</value>
SessionToken? SessionToken { get; set; } FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,6 +1,6 @@
using System.Collections.Specialized; using System.Collections.Specialized;
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public class PrmBase() : IContext public class PrmBase() : IContext
{ {

View file

@ -1,11 +1,8 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
using System.Security.Cryptography;
namespace FrostFS.SDK.ClientV2.Parameters; public sealed class PrmContainerCreate(FrostFsContainerInfo container) : PrmBase, ISessionToken
public sealed class PrmContainerCreate(ModelsV2.Container container) : PrmBase, ISessionToken
{ {
public ModelsV2.Container Container { get; set; } = container; public FrostFsContainerInfo Container { get; set; } = container;
/// <summary> /// <summary>
/// Since the container becomes available with some delay, it needs to poll the container status /// 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,
/// <summary> /// <summary>
/// Blank session token /// Blank session token
/// </summary> /// </summary>
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,10 +1,8 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2.Parameters; public sealed class PrmContainerDelete(FrostFsContainerId containerId) : PrmBase, ISessionToken
public sealed class PrmContainerDelete(ContainerId containerId) : PrmBase, ISessionToken
{ {
public ContainerId ContainerId { get; set; } = containerId; public FrostFsContainerId ContainerId { get; set; } = containerId;
/// <summary> /// <summary>
/// Since the container is removed with some delay, it needs to poll the container status /// 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
/// <value>Rules for polling the result</value> /// <value>Rules for polling the result</value>
public PrmWait? WaitParams { get; set; } public PrmWait? WaitParams { get; set; }
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,8 +1,6 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2.Parameters; public sealed class PrmContainerGet(FrostFsContainerId container) : PrmBase
public sealed class PrmContainerGet(ContainerId containerId) : PrmBase
{ {
public ContainerId ContainerId { get; set; } = containerId; public FrostFsContainerId Container { get; set; } = container;
} }

View file

@ -1,4 +1,4 @@
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public sealed class PrmContainerGetAll() : PrmBase() public sealed class PrmContainerGetAll() : PrmBase()
{ {

View file

@ -1,4 +1,4 @@
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public sealed class PrmNetmapSnapshot() : PrmBase public sealed class PrmNetmapSnapshot() : PrmBase
{ {

View file

@ -1,4 +1,4 @@
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public sealed class PrmNetworkSettings() : PrmBase public sealed class PrmNetworkSettings() : PrmBase
{ {

View file

@ -1,4 +1,4 @@
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public sealed class PrmNodeInfo() : PrmBase public sealed class PrmNodeInfo() : PrmBase
{ {

View file

@ -1,13 +1,11 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2.Parameters; public sealed class PrmObjectDelete(FrostFsContainerId containerId, FrostFsObjectId objectId) : PrmBase, ISessionToken
public sealed class PrmObjectDelete(ContainerId containerId, ObjectId 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;
/// <inheritdoc /> /// <inheritdoc />
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,13 +1,11 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2.Parameters; public sealed class PrmObjectGet(FrostFsContainerId containerId, FrostFsObjectId objectId) : PrmBase, ISessionToken
public sealed class PrmObjectGet(ContainerId containerId, ObjectId 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;
/// <inheritdoc /> /// <inheritdoc />
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,13 +1,11 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2.Parameters; public sealed class PrmObjectHeadGet(FrostFsContainerId containerId, FrostFsObjectId objectId) : PrmBase, ISessionToken
public sealed class PrmObjectHeadGet(ContainerId containerId, ObjectId 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;
/// <inheritdoc /> /// <inheritdoc />
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,7 +1,6 @@
using System.IO; using System.IO;
using FrostFS.SDK.ModelsV2;
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public sealed class PrmObjectPut : PrmBase, ISessionToken public sealed class PrmObjectPut : PrmBase, ISessionToken
{ {
@ -10,7 +9,7 @@ public sealed class PrmObjectPut : PrmBase, ISessionToken
/// Optional parameters ike <c>Attributes</c> can be provided as well. /// Optional parameters ike <c>Attributes</c> can be provided as well.
/// </summary> /// </summary>
/// <value>Header with required parameters to create an object</value> /// <value>Header with required parameters to create an object</value>
public ObjectHeader? Header { get; set; } public FrostFsObjectHeader? Header { get; set; }
/// <summary> /// <summary>
/// A stream with source data /// A stream with source data
@ -37,7 +36,7 @@ public sealed class PrmObjectPut : PrmBase, ISessionToken
public byte[]? CustomBuffer { get; set; } public byte[]? CustomBuffer { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
internal int MaxObjectSizeCache { get; set; } internal int MaxObjectSizeCache { get; set; }

View file

@ -1,14 +1,14 @@
using FrostFS.SDK.ModelsV2; using System.Collections.Generic;
using System.Collections.Generic;
namespace FrostFS.SDK.ClientV2.Parameters;
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
{ {
/// <summary> /// <summary>
/// Defines container for the search /// Defines container for the search
/// </summary> /// </summary>
/// <value></value> /// <value></value>
public ContainerId ContainerId { get; set; } = containerId; public FrostFsContainerId ContainerId { get; set; } = containerId;
/// <summary> /// <summary>
/// Defines the search criteria /// Defines the search criteria
@ -17,5 +17,5 @@ public sealed class PrmObjectSearch(ContainerId containerId, params IObjectFilte
public IEnumerable<IObjectFilter> Filters { get; set; } = filters; public IEnumerable<IObjectFilter> Filters { get; set; } = filters;
/// <inheritdoc /> /// <inheritdoc />
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,4 +1,4 @@
namespace FrostFS.SDK.ClientV2.Parameters; namespace FrostFS.SDK.ClientV2;
public sealed class PrmSessionCreate(ulong expiration) : PrmBase public sealed class PrmSessionCreate(ulong expiration) : PrmBase
{ {

View file

@ -1,11 +1,9 @@
using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2.Parameters;
public sealed class PrmSingleObjectPut(FrostFsObject frostFsObject) : PrmBase, ISessionToken public sealed class PrmSingleObjectPut(FrostFsObject frostFsObject) : PrmBase, ISessionToken
{ {
public FrostFsObject FrostFsObject { get; set; } = frostFsObject; public FrostFsObject FrostFsObject { get; set; } = frostFsObject;
/// <inheritdoc /> /// <inheritdoc />
public SessionToken? SessionToken { get; set; } public FrostFsSessionToken? SessionToken { get; set; }
} }

View file

@ -1,5 +1,6 @@
using System; using System;
namespace FrostFS.SDK.ClientV2.Parameters;
namespace FrostFS.SDK.ClientV2;
public class PrmWait(TimeSpan timeout, TimeSpan pollInterval) public class PrmWait(TimeSpan timeout, TimeSpan pollInterval)
{ {

View file

@ -3,12 +3,11 @@ using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Threading.Tasks; using System.Threading.Tasks;
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; using FrostFS.SDK.ClientV2;
using FrostFS.Container; using FrostFS.Container;
using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.ClientV2.Mappers.GRPC;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ModelsV2; using FrostFS.SDK.ClientV2;
using FrostFS.SDK.ClientV2.Parameters;
using FrostFS.Refs; using FrostFS.Refs;
using FrostFS.Session; using FrostFS.Session;
@ -18,14 +17,14 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
{ {
readonly SessionProvider sessions = new(context); readonly SessionProvider sessions = new(context);
public async ValueTask<Session.SessionToken> GetOrCreateSession(ISessionToken args, Context ctx) public async ValueTask<SessionToken> GetOrCreateSession(ISessionToken args, Context ctx)
{ {
return await sessions.GetOrCreateSession(args, ctx); return await sessions.GetOrCreateSession(args, ctx);
} }
internal async Task<ModelsV2.Container> GetContainerAsync(PrmContainerGet args) internal async Task<FrostFsContainerInfo> 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); 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(); return response.Body.Container.ToModel();
} }
internal async IAsyncEnumerable<ContainerId> ListContainersAsync(PrmContainerGetAll args) internal async IAsyncEnumerable<FrostFsContainerId> ListContainersAsync(PrmContainerGetAll args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
var request = new ListRequest 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) 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<ContainerId> CreateContainerAsync(PrmContainerCreate args) internal async Task<FrostFsContainerId> CreateContainerAsync(PrmContainerCreate args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
var grpcContainer = args.Container.ToMessage();
grpcContainer.OwnerId = ctx.OwnerId.ToMessage(); var grpcContainer = args.Container.GetContainer();
grpcContainer.Version = ctx.Version.ToMessage();
grpcContainer.OwnerId ??= ctx.OwnerId.ToMessage();
grpcContainer.Version ??= ctx.Version.ToMessage();
var request = new PutRequest var request = new PutRequest
{ {
@ -81,9 +82,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
null, null,
ContainerSessionContext.Types.Verb.Put, ContainerSessionContext.Types.Verb.Put,
ctx.Key, ctx.Key,
ctx.PublicKeyCache); ctx.GetPublicKeyCache());
var v = sessionToken.Body.OwnerId == grpcContainer.OwnerId;
request.AddMetaHeader(args.XHeaders, sessionToken); request.AddMetaHeader(args.XHeaders, sessionToken);
@ -95,7 +94,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
await WaitForContainer(WaitExpects.Exists, response.Body.ContainerId, args.WaitParams, ctx); 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) internal async Task DeleteContainerAsync(PrmContainerDelete args)
@ -116,7 +115,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
request.Body.ContainerId, request.Body.ContainerId,
ContainerSessionContext.Types.Verb.Delete, ContainerSessionContext.Types.Verb.Delete,
ctx.Key, ctx.Key,
ctx.PublicKeyCache); ctx.GetPublicKeyCache());
request.AddMetaHeader(args.XHeaders, sessionToken); request.AddMetaHeader(args.XHeaders, sessionToken);
@ -193,7 +192,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
if (DateTime.UtcNow >= deadLine) if (DateTime.UtcNow >= deadLine)
throw new TimeoutException(); throw new TimeoutException();
if (ex.Status.Code != ModelsV2.Enums.StatusCode.ContainerNotFound) if (ex.Status.Code != FrostFsStatusCode.ContainerNotFound)
throw; throw;
if (expect == WaitExpects.Removed) if (expect == WaitExpects.Removed)

View file

@ -1,13 +1,11 @@
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; 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 static FrostFS.Netmap.NetworkConfig.Types;
using FrostFS.SDK.ClientV2.Parameters;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;
@ -40,7 +38,7 @@ internal class NetmapServiceProvider : ContextAccessor
return settings; return settings;
} }
internal async Task<NodeInfo> GetLocalNodeInfoAsync(PrmNodeInfo args) internal async Task<FrostFsNodeInfo> GetLocalNodeInfoAsync(PrmNodeInfo args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
var request = new LocalNodeInfoRequest var request = new LocalNodeInfoRequest
@ -72,7 +70,7 @@ internal class NetmapServiceProvider : ContextAccessor
return response; return response;
} }
internal async Task<NetmapSnapshot> GetNetmapSnapshotAsync(PrmNetmapSnapshot args) internal async Task<FrostFsNetmapSnapshot> GetNetmapSnapshotAsync(PrmNetmapSnapshot args)
{ {
var ctx = args.Context!; var ctx = args.Context!;

View file

@ -1,23 +1,23 @@
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Google.Protobuf;
using FrostFS.Object; using FrostFS.Object;
using FrostFS.Refs; using FrostFS.Refs;
using FrostFS.SDK.ClientV2.Extensions;
using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.ClientV2.Mappers.GRPC;
using FrostFS.SDK.ClientV2;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.Session; using FrostFS.Session;
using FrostFS.SDK.ModelsV2;
using FrostFS.SDK.ClientV2.Extensions; using Google.Protobuf;
using FrostFS.SDK.ClientV2.Parameters;
using System.Buffers;
namespace FrostFS.SDK.ClientV2; 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); readonly SessionProvider sessions = new (env);
@ -26,16 +26,17 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
return await sessions.GetOrCreateSession(args, ctx); return await sessions.GetOrCreateSession(args, ctx);
} }
internal async Task<ObjectHeader> GetObjectHeadAsync(PrmObjectHeadGet args) internal async Task<FrostFsObjectHeader> GetObjectHeadAsync(PrmObjectHeadGet args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
var request = new HeadRequest var request = new HeadRequest
{ {
Body = new HeadRequest.Types.Body Body = new HeadRequest.Types.Body
{ {
Address = new Address Address = new Address
{ {
ContainerId = args.ContainerId.ToMessage(), ContainerId = args.ContainerId.ContainerID,
ObjectId = args.ObjectId.ToMessage() ObjectId = args.ObjectId.ToMessage()
} }
} }
@ -119,7 +120,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
Verifier.CheckResponse(response); Verifier.CheckResponse(response);
} }
internal async IAsyncEnumerable<ObjectId> SearchObjectsAsync(PrmObjectSearch args) internal async IAsyncEnumerable<FrostFsObjectId> SearchObjectsAsync(PrmObjectSearch args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
var request = new SearchRequest var request = new SearchRequest
@ -149,11 +150,11 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
await foreach (var oid in objectsIds) await foreach (var oid in objectsIds)
{ {
yield return ObjectId.FromHash(oid.Value.ToByteArray()); yield return FrostFsObjectId.FromHash(oid.Value.ToByteArray());
} }
} }
internal async Task<ObjectId> PutObjectAsync(PrmObjectPut args) internal async Task<FrostFsObjectId> PutObjectAsync(PrmObjectPut args)
{ {
if (args.Header == null) if (args.Header == null)
throw new ArgumentException("Value cannot be null", nameof(args.Header)); throw new ArgumentException("Value cannot be null", nameof(args.Header));
@ -174,17 +175,14 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
} }
} }
internal async Task<ObjectId> PutSingleObjectAsync(PrmSingleObjectPut args) internal async Task<FrostFsObjectId> PutSingleObjectAsync(PrmSingleObjectPut args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
var grpcObject = ObjectTools.CreateObject(args.FrostFsObject, ctx); var grpcObject = ObjectTools.CreateObject(args.FrostFsObject, ctx);
var request = new PutSingleRequest var request = new PutSingleRequest
{ {
Body = new PutSingleRequest.Types.Body() Body = new () { Object = grpcObject }
{
Object = grpcObject
}
}; };
var sessionToken = await GetOrCreateSession(args, ctx); var sessionToken = await GetOrCreateSession(args, ctx);
@ -202,15 +200,15 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
Verifier.CheckResponse(response); Verifier.CheckResponse(response);
return ObjectId.FromHash(grpcObject.ObjectId.Value.ToByteArray()); return FrostFsObjectId.FromHash(grpcObject.ObjectId.Value.ToByteArray());
} }
private async Task<ObjectId> PutClientCutObject(PrmObjectPut args) private async Task<FrostFsObjectId> PutClientCutObject(PrmObjectPut args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
var tokenRaw = await GetOrCreateSession(args, ctx); var tokenRaw = await GetOrCreateSession(args, ctx);
var token = new ModelsV2.SessionToken(tokenRaw.Serialize()); var token = new FrostFsSessionToken(tokenRaw.Serialize());
args.SessionToken = token; args.SessionToken = token;
@ -237,9 +235,9 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
var restPart = (restBytes % (ulong)objectSize) > 0 ? 1 : 0; var restPart = (restBytes % (ulong)objectSize) > 0 ? 1 : 0;
var objectsCount = fullLength > 0 ? (int)(restBytes / (ulong)objectSize) + restPart : 0; var objectsCount = fullLength > 0 ? (int)(restBytes / (ulong)objectSize) + restPart : 0;
List<ObjectId> sentObjectIds = new(objectsCount); List<FrostFsObjectId> sentObjectIds = new(objectsCount);
Split? split = null; FrostFsSplit? split = null;
// keep attributes for the large object // keep attributes for the large object
var attributes = args.Header!.Attributes; var attributes = args.Header!.Attributes;
@ -249,7 +247,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
{ {
if (split == null) if (split == null)
{ {
split = new Split(); split = new FrostFsSplit();
args.Header!.Attributes = []; args.Header!.Attributes = [];
} }
@ -266,7 +264,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
// send the last part and create linkObject // send the last part and create linkObject
if (sentObjectIds.Count > 0) if (sentObjectIds.Count > 0)
{ {
var largeObjectHeader = new ObjectHeader(header.ContainerId) { PayloadLength = fullLength }; var largeObjectHeader = new FrostFsObjectHeader(header.ContainerId) { PayloadLength = fullLength };
largeObjectHeader.Attributes.AddRange(attributes); largeObjectHeader.Attributes.AddRange(attributes);
@ -276,7 +274,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
sentObjectIds.Add(result.ObjectId); sentObjectIds.Add(result.ObjectId);
var linkObject = new LinkObject(header.ContainerId, split!.SplitId, largeObjectHeader) var linkObject = new FrostFsLinkObject(header.ContainerId, split!.SplitId, largeObjectHeader)
.AddChildren(sentObjectIds); .AddChildren(sentObjectIds);
_ = await PutSingleObjectAsync(new PrmSingleObjectPut(linkObject) { Context = args.Context}); _ = await PutSingleObjectAsync(new PrmSingleObjectPut(linkObject) { Context = args.Context});
@ -290,9 +288,9 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
return singlePartResult.ObjectId; 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; public int ObjectSize = objectSize;
} }
@ -359,7 +357,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
var response = await stream.Close(); var response = await stream.Close();
Verifier.CheckResponse(response); 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 finally
{ {
@ -374,10 +372,10 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
{ {
var header = args.Header!; var header = args.Header!;
header.OwnerId = ctx.OwnerId; header.OwnerId ??= ctx.OwnerId;
header.Version = ctx.Version; header.Version ??= ctx.Version;
var grpcHeader = header.ToMessage(); var grpcHeader = header.GetHeader();
if (header.Split != null) if (header.Split != null)
{ {

View file

@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.ClientV2.Mappers.GRPC;
using FrostFS.SDK.ClientV2.Parameters; using FrostFS.SDK.ClientV2;
using FrostFS.Session; using FrostFS.Session;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;

View file

@ -4,5 +4,3 @@ internal class ContextAccessor(ClientEnvironment context)
{ {
protected ClientEnvironment Context { get; set; } = context; protected ClientEnvironment Context { get; set; } = context;
} }

View file

@ -1,6 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using FrostFS.SDK.ClientV2.Parameters;
using FrostFS.SDK.ClientV2;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;

View file

@ -1,20 +1,20 @@
using FrostFS.SDK.ModelsV2;
using Grpc.Net.Client;
using System; using System;
using System.Security.Cryptography;
using System.Buffers; using System.Buffers;
using System.Security.Cryptography;
using Grpc.Net.Client;
namespace FrostFS.SDK.ClientV2; 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<byte> _arrayPool; private ArrayPool<byte> _arrayPool;
internal OwnerId? Owner { get; } = owner; internal FrostFsOwner? Owner { get; } = owner;
internal GrpcChannel Channel { get; private set; } = channel; internal GrpcChannel Channel { get; private set; } = channel;
internal ModelsV2.Version Version { get; } = version; internal FrostFsVersion Version { get; } = version;
internal NetworkSettings? NetworkSettings { get; set; } internal NetworkSettings? NetworkSettings { get; set; }
@ -42,7 +42,7 @@ public class ClientEnvironment(Client client, ECDsa? key, OwnerId? owner, GrpcCh
{ {
if (disposing) if (disposing)
{ {
Channel.Dispose(); Channel?.Dispose();
} }
} }
} }

View file

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using FrostFS.SDK.ModelsV2;
namespace FrostFS.SDK.ClientV2.Extensions; namespace FrostFS.SDK.ClientV2.Extensions;
@ -21,29 +19,29 @@ public static class ObjectExtensions
public static FrostFsObject AddAttribute(this FrostFsObject obj, string key, string value) 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; 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); obj.Header.Attributes.Add(attribute);
return obj; return obj;
} }
public static FrostFsObject AddAttributes(this FrostFsObject obj, IEnumerable<ObjectAttribute> attributes) public static FrostFsObject AddAttributes(this FrostFsObject obj, IEnumerable<FrostFsAttribute> attributes)
{ {
obj.Header.Attributes.AddRange(attributes); obj.Header.Attributes.AddRange(attributes);
return obj; return obj;
} }
public static FrostFsObject SetSplit(this FrostFsObject obj, Split? split) public static FrostFsObject SetSplit(this FrostFsObject obj, FrostFsSplit? split)
{ {
obj.Header.Split = split; obj.Header.Split = split;
return obj; return obj;
} }
public static LinkObject AddChildren(this LinkObject linkObject, IEnumerable<ObjectId> objectIds) public static FrostFsLinkObject AddChildren(this FrostFsLinkObject linkObject, IEnumerable<FrostFsObjectId> objectIds)
{ {
linkObject.Header.Split!.Children.AddRange(objectIds); linkObject.Header.Split!.Children.AddRange(objectIds);
return linkObject; return linkObject;

View file

@ -4,7 +4,6 @@ using System.Threading.Tasks;
using Grpc.Core; using Grpc.Core;
using FrostFS.Object; using FrostFS.Object;
using FrostFS.SDK.ModelsV2;
using System.Threading; using System.Threading;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;
@ -33,7 +32,7 @@ public class ObjectReader(AsyncServerStreamingCall<GetResponse> call) : IObjectR
}; };
} }
public async Task<byte[]?> ReadChunk(CancellationToken cancellationToken = default) public async Task<ReadOnlyMemory<byte>?> ReadChunk(CancellationToken cancellationToken = default)
{ {
if (!await Call.ResponseStream.MoveNext(cancellationToken)) if (!await Call.ResponseStream.MoveNext(cancellationToken))
return null; return null;
@ -44,14 +43,14 @@ public class ObjectReader(AsyncServerStreamingCall<GetResponse> call) : IObjectR
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk) if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk)
throw new InvalidOperationException("unexpected message type"); throw new InvalidOperationException("unexpected message type");
return response.Body.Chunk.ToByteArray(); return response.Body.Chunk.Memory;
} }
public void Dispose() public void Dispose()
{ {
if (!disposed) if (!disposed)
{ {
Call.Dispose(); Call?.Dispose();
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
disposed = true; disposed = true;

View file

@ -30,6 +30,6 @@ internal class ObjectStreamer(AsyncClientStreamingCall<PutRequest, PutResponse>
public void Dispose() public void Dispose()
{ {
Call.Dispose(); Call?.Dispose();
} }
} }

View file

@ -6,13 +6,12 @@ using FrostFS.Object;
using FrostFS.Refs; using FrostFS.Refs;
using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.ClientV2.Mappers.GRPC;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ModelsV2;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;
internal class ObjectTools internal class ObjectTools
{ {
internal static ObjectId CalculateObjectId(ObjectHeader header, Context ctx) internal static FrostFsObjectId CalculateObjectId(FrostFsObjectHeader header, Context ctx)
{ {
var grpcHeader = CreateHeader(header, [], ctx); var grpcHeader = CreateHeader(header, [], ctx);
@ -24,10 +23,10 @@ internal class ObjectTools
internal static Object.Object CreateObject(FrostFsObject @object, Context ctx) internal static Object.Object CreateObject(FrostFsObject @object, Context ctx)
{ {
@object.Header.OwnerId = ctx.OwnerId; @object.Header.OwnerId ??= ctx.OwnerId;
@object.Header.Version = ctx.Version; @object.Header.Version ??= ctx.Version;
var grpcHeader = @object.Header.ToMessage(); var grpcHeader = @object.Header.GetHeader();
grpcHeader.PayloadLength = (ulong)@object.Payload.Length; grpcHeader.PayloadLength = (ulong)@object.Payload.Length;
grpcHeader.PayloadHash = Sha256Checksum(@object.Payload); grpcHeader.PayloadHash = Sha256Checksum(@object.Payload);
@ -47,18 +46,21 @@ internal class ObjectTools
obj.Signature = new Refs.Signature obj.Signature = new Refs.Signature
{ {
Key = ctx.PublicKeyCache, Key = ctx.GetPublicKeyCache(),
Sign = ByteString.CopyFrom(ctx.Key.SignData(obj.ObjectId.ToByteArray())), Sign = ByteString.CopyFrom(ctx.Key.SignData(obj.ObjectId.ToByteArray())),
}; };
return obj; 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 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) if (split.Children != null && split.Children.Count != 0)
@ -72,7 +74,7 @@ internal class ObjectTools
grpcHeader.Split.ParentHeader = grpcParentHeader; grpcHeader.Split.ParentHeader = grpcParentHeader;
grpcHeader.Split.ParentSignature = new Refs.Signature grpcHeader.Split.ParentSignature = new Refs.Signature
{ {
Key = ctx.PublicKeyCache, Key = ctx.GetPublicKeyCache(),
Sign = ByteString.CopyFrom(ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray())), Sign = ByteString.CopyFrom(ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray())),
}; };
@ -82,13 +84,13 @@ internal class ObjectTools
grpcHeader.Split.Previous = split.Previous?.ToMessage(); 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(); header.OwnerId ??= ctx.OwnerId;
header.Version ??= ctx.Version;
grpcHeader.OwnerId = ctx.OwnerId.ToMessage();
grpcHeader.Version = ctx.Version.ToMessage();
var grpcHeader = header.GetHeader();
if (payload != null) // && payload.Length > 0 if (payload != null) // && payload.Length > 0
grpcHeader.PayloadHash = Sha256Checksum(payload); grpcHeader.PayloadHash = Sha256Checksum(payload);

View file

@ -24,10 +24,8 @@ namespace System
public Index(int value, bool fromEnd = false) public Index(int value, bool fromEnd = false)
{ {
if (value < 0) if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
}
if (fromEnd) if (fromEnd)
_value = ~value; _value = ~value;
else else
@ -52,10 +50,8 @@ namespace System
public static Index FromStart(int value) public static Index FromStart(int value)
{ {
if (value < 0) if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
}
return new Index(value); return new Index(value);
} }
@ -65,10 +61,8 @@ namespace System
public static Index FromEnd(int value) public static Index FromEnd(int value)
{ {
if (value < 0) if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
}
return new Index(~value); return new Index(~value);
} }
@ -77,14 +71,7 @@ namespace System
{ {
get get
{ {
if (_value < 0) return _value < 0 ? ~_value : _value;
{
return ~_value;
}
else
{
return _value;
}
} }
} }
@ -202,6 +189,7 @@ namespace System
{ {
int start; int start;
var startIndex = Start; var startIndex = Start;
if (startIndex.IsFromEnd) if (startIndex.IsFromEnd)
start = length - startIndex.Value; start = length - startIndex.Value;
else else
@ -209,16 +197,15 @@ namespace System
int end; int end;
var endIndex = End; var endIndex = End;
if (endIndex.IsFromEnd) if (endIndex.IsFromEnd)
end = length - endIndex.Value; end = length - endIndex.Value;
else else
end = endIndex.Value; end = endIndex.Value;
if ((uint)end > (uint)length || (uint)start > (uint)end) if ((uint)end > (uint)length || (uint)start > (uint)end)
{
throw new ArgumentOutOfRangeException(nameof(length)); throw new ArgumentOutOfRangeException(nameof(length));
}
return (start, end - start); return (start, end - start);
} }
} }
@ -234,10 +221,8 @@ namespace System.Runtime.CompilerServices
public static T[] GetSubArray<T>(T[] array, Range range) public static T[] GetSubArray<T>(T[] array, Range range)
{ {
if (array == null) if (array == null)
{
throw new ArgumentNullException(nameof(array)); throw new ArgumentNullException(nameof(array));
}
(int offset, int length) = range.GetOffsetAndLength(array.Length); (int offset, int length) = range.GetOffsetAndLength(array.Length);
if (default(T) != null || typeof(T[]) == array.GetType()) 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[]. // We know the type of the array to be exactly T[].
if (length == 0) if (length == 0)
{
return []; return [];
}
var dest = new T[length]; var dest = new T[length];
Array.Copy(array, offset, dest, 0, length); Array.Copy(array, offset, dest, 0, length);
return dest; return dest;

View file

@ -5,7 +5,6 @@ using System.Security.Cryptography;
using FrostFS.Refs; using FrostFS.Refs;
using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.ClientV2.Mappers.GRPC;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ModelsV2;
using FrostFS.SDK.ProtosV2.Interfaces; using FrostFS.SDK.ProtosV2.Interfaces;
using FrostFS.Session; using FrostFS.Session;

View file

@ -1,6 +1,11 @@
using System; using System;
using System.Security.Cryptography; using System.Security.Cryptography;
using FrostFS.Refs;
using FrostFS.SDK.Cryptography;
using FrostFS.SDK.ProtosV2.Interfaces;
using FrostFS.Session;
using Google.Protobuf; using Google.Protobuf;
using Org.BouncyCastle.Asn1.Sec; using Org.BouncyCastle.Asn1.Sec;
@ -9,11 +14,6 @@ using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math; using Org.BouncyCastle.Math;
using FrostFS.Refs;
using FrostFS.SDK.Cryptography;
using FrostFS.Session;
using FrostFS.SDK.ProtosV2.Interfaces;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;
public static class RequestSigner public static class RequestSigner

View file

@ -1,13 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core;
using FrostFS.Object; using FrostFS.Object;
using FrostFS.Refs; using FrostFS.Refs;
using System.Threading;
using Grpc.Core;
namespace FrostFS.SDK.ClientV2; namespace FrostFS.SDK.ClientV2;
@ -29,6 +29,6 @@ internal class SearchReader(AsyncServerStreamingCall<SearchResponse> call) : IDi
public void Dispose() public void Dispose()
{ {
Call.Dispose(); Call?.Dispose();
} }
} }

View file

@ -1,6 +1,12 @@
using System; using System;
using System.Security.Cryptography; 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 Google.Protobuf;
using Org.BouncyCastle.Asn1.Sec; using Org.BouncyCastle.Asn1.Sec;
@ -9,12 +15,6 @@ using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math; 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; namespace FrostFS.SDK.ClientV2;
public static class Verifier public static class Verifier

View file

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace FrostFS.SDK.ModelsV2; namespace FrostFS.SDK;
public class ClientSettings public class ClientSettings
{ {
@ -13,7 +13,7 @@ public class ClientSettings
public virtual void Validate() public virtual void Validate()
{ {
var errors = CheckFields(); var errors = CheckFields();
if (errors != null) if (errors != null)
ThrowException(errors); ThrowException(errors);
} }
@ -28,7 +28,7 @@ public class ClientSettings
} }
protected static void ThrowException(List<string> errors) protected static void ThrowException(List<string> errors)
{ {
StringBuilder messages = new(); StringBuilder messages = new();
foreach (var error in errors) foreach (var error in errors)
@ -48,7 +48,7 @@ public class SingleOwnerClientSettings : ClientSettings
{ {
var errors = CheckFields(); var errors = CheckFields();
if (errors != null) if (errors != null)
ThrowException(errors); ThrowException(errors);
} }
protected List<string>? CheckFields() protected List<string>? CheckFields()
@ -59,5 +59,5 @@ public class SingleOwnerClientSettings : ClientSettings
(errors ??= []).Add(string.Format(errorTemplate, nameof(Key))); (errors ??= []).Add(string.Format(errorTemplate, nameof(Key)));
return errors; return errors;
} }
} }

View file

@ -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; }
}

View file

@ -1,4 +1,4 @@
namespace FrostFS.SDK.ModelsV2; namespace FrostFS.SDK;
public class ContainerId(string id) public class ContainerId(string id)
{ {

View file

@ -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; }
}

View file

@ -1,6 +1,6 @@
using System.ComponentModel; using System.ComponentModel;
namespace FrostFS.SDK.ModelsV2.Enums; namespace FrostFS.SDK;
public enum BasicAcl public enum BasicAcl
{ {

View file

@ -0,0 +1,10 @@
namespace FrostFS.SDK;
public enum FrostFsObjectMatchType
{
Unspecified = 0,
Equals = 1,
NotEquals = 2,
KeyAbsent = 3,
StartsWith = 4
}

Some files were not shown because too many files have changed in this diff Show more