[#10] MetricsAndOptions #10
84 changed files with 2314 additions and 1016 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -18,6 +18,7 @@ vendor/
|
||||||
# IDE
|
# IDE
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
.vs
|
||||||
|
|
||||||
# coverage
|
# coverage
|
||||||
coverage.txt
|
coverage.txt
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
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
|
||||||
MinimumVisualStudioVersion =
|
|
||||||
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}"
|
||||||
|
@ -10,6 +10,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ModelsV2", "src
|
||||||
EndProject
|
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}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -32,8 +34,9 @@ Global
|
||||||
{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
|
||||||
{5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.Build.0 = Release|Any CPU
|
{5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
{8FDA7E0D-9C75-4874-988E-6592CD28F76C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
{8FDA7E0D-9C75-4874-988E-6592CD28F76C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
HideSolutionNode = FALSE
|
{8FDA7E0D-9C75-4874-988E-6592CD28F76C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8FDA7E0D-9C75-4874-988E-6592CD28F76C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
143
README.md
143
README.md
|
@ -25,133 +25,50 @@ using FrostFS.SDK.ClientV2;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
using FrostFS.SDK.ModelsV2.Netmap;
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
var fsClient = Client.GetInstance(<your_key>, <your_host>);
|
|
||||||
|
|
||||||
// List containers
|
var options = Options.Create(new ClientSettings
|
||||||
var containersIds = await fsClient.ListContainersAsync();
|
{
|
||||||
|
Key = <your_key>,
|
||||||
|
Host = <your_host>
|
||||||
|
});
|
||||||
|
|
||||||
|
var fsClient = Client.GetInstance(options);
|
||||||
|
|
||||||
|
// Mertics
|
||||||
|
fsClient.GrpcInvoked += (sender, info) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Invoked: {info.MethodName}. Elapsed time: {info.ElapsedTimeMicroSec}");
|
||||||
|
};
|
||||||
|
|
||||||
// Create container
|
|
||||||
var placementPolicy = new PlacementPolicy(true, new Replica(1));
|
var placementPolicy = new PlacementPolicy(true, new Replica(1));
|
||||||
var containerId = await fsClient.CreateContainerAsync(
|
|
||||||
new Container(
|
|
||||||
BasicAcl.PublicRW,
|
|
||||||
placementPolicy
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get container
|
var containerId = await fsClient.CreateContainerAsync(new Container(BasicAcl.PublicRW, placementPolicy));
|
||||||
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
|
// Put object
|
||||||
var f = File.OpenRead("cat.jpg");
|
var fileStream = File.OpenRead("cat.jpg");
|
||||||
var cat = new ObjectHeader(
|
var header = new ObjectHeader(
|
||||||
containerId: cId,
|
containerId: containerId,
|
||||||
type: ObjectType.Regular,
|
type: ObjectType.Regular,
|
||||||
new ObjectAttribute("Filename", "cat.jpg")
|
new ObjectAttribute("Filename", "cat.jpg")
|
||||||
);
|
);
|
||||||
var oId = await fsClient.PutObjectAsync(cat, f);
|
|
||||||
|
|
||||||
// Get object header
|
var param = new PutObjectParameters
|
||||||
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 = [];
|
Header = header,
|
||||||
FrostFS.SDK.ModelsV2.Object? currentObject;
|
Payload = fileStream
|
||||||
|
};
|
||||||
|
|
||||||
var partSize = 1024 * 1024;
|
var oId = await fsClient.PutObjectAsync(param);
|
||||||
var buffer = new byte[partSize];
|
|
||||||
|
|
||||||
var largeObject = new LargeObject(containerId);
|
// Search regular objects
|
||||||
|
await foreach (var objId in fsClient.SearchObjectsAsync(containerId, [ObjectFilter.RootFilter()]))
|
||||||
|
{
|
||||||
|
// Get object header
|
||||||
|
var info = await fsClient.GetObjectHeadAsync(containerId, objId);
|
||||||
|
|
||||||
var split = new Split();
|
// Get object
|
||||||
|
var obj = await fsClient.GetObjectAsync(containerId, oId);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.Cryptography;
|
using System.Data.Common;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FrostFS.Container;
|
using FrostFS.Container;
|
||||||
using FrostFS.Netmap;
|
using FrostFS.Netmap;
|
||||||
|
@ -9,77 +8,203 @@ using FrostFS.Object;
|
||||||
using FrostFS.SDK.ClientV2.Interfaces;
|
using FrostFS.SDK.ClientV2.Interfaces;
|
||||||
using FrostFS.SDK.Cryptography;
|
using FrostFS.SDK.Cryptography;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
using FrostFS.Session;
|
using FrostFS.Session;
|
||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
using static FrostFS.Netmap.NetworkConfig.Types;
|
using Microsoft.Extensions.Options;
|
||||||
using Version = FrostFS.SDK.ModelsV2.Version;
|
using Version = FrostFS.SDK.ModelsV2.Version;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
public partial class Client: IFrostFSClient
|
public class Client : IFrostFSClient, IDisposable
|
||||||
{
|
{
|
||||||
private GrpcChannel? _channel;
|
private bool isDisposed;
|
||||||
private readonly ECDsa _key;
|
|
||||||
public readonly OwnerId OwnerId;
|
|
||||||
public readonly Version Version = new(2, 13);
|
|
||||||
|
|
||||||
private readonly Dictionary<string, ulong> NetworkSettings = [];
|
internal ClientEnvironment ClientCtx { get; set; }
|
||||||
|
|
||||||
private ContainerService.ContainerServiceClient? _containerServiceClient;
|
public static IFrostFSClient GetInstance(IOptions<ClientSettings> options)
|
||||||
private NetmapService.NetmapServiceClient? _netmapServiceClient;
|
|
||||||
private ObjectService.ObjectServiceClient? _objectServiceClient;
|
|
||||||
private SessionService.SessionServiceClient? _sessionServiceClient;
|
|
||||||
|
|
||||||
public static IFrostFSClient GetInstance(string key, string host)
|
|
||||||
{
|
{
|
||||||
return new Client(key, host);
|
return new Client(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Client(string key, string host)
|
/// <summary>
|
||||||
|
/// For test only. Provide custom implementation or mock object to inject required logic instead of internal gRPC client.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">User's key</param>
|
||||||
|
/// <param name="containerService">ContainerService.ContainerServiceClient implementation</param>
|
||||||
|
/// <param name="netmapService">Netmap.NetmapService.NetmapServiceClient implementation</param>
|
||||||
|
/// <param name="sessionService">Session.SessionService.SessionServiceClient implementation</param>
|
||||||
|
/// <param name="objectService">Object.ObjectService.ObjectServiceClient implementation</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IFrostFSClient GetTestInstance(
|
||||||
|
IOptions<ClientSettings> settings,
|
||||||
|
NetmapService.NetmapServiceClient netmapService,
|
||||||
|
SessionService.SessionServiceClient sessionService,
|
||||||
|
ContainerService.ContainerServiceClient containerService,
|
||||||
|
ObjectService.ObjectServiceClient objectService)
|
||||||
{
|
{
|
||||||
// TODO: Развязать клиент и реализацию GRPC
|
return new Client(settings, containerService, netmapService, sessionService, objectService);
|
||||||
_key = key.LoadWif();
|
}
|
||||||
OwnerId = OwnerId.FromKey(_key);
|
|
||||||
InitGrpcChannel(host);
|
private Client(
|
||||||
InitContainerClient();
|
IOptions<ClientSettings> settings,
|
||||||
InitNetmapClient();
|
ContainerService.ContainerServiceClient containerService,
|
||||||
InitObjectClient();
|
NetmapService.NetmapServiceClient netmapService,
|
||||||
InitSessionClient();
|
SessionService.SessionServiceClient sessionService,
|
||||||
|
ObjectService.ObjectServiceClient objectService)
|
||||||
|
{
|
||||||
|
var ecdsaKey = settings.Value.Key.LoadWif();
|
||||||
|
OwnerId.FromKey(ecdsaKey);
|
||||||
|
|
||||||
|
ClientCtx = new ClientEnvironment(
|
||||||
|
key: ecdsaKey,
|
||||||
|
owner: OwnerId.FromKey(ecdsaKey),
|
||||||
|
channel: InitGrpcChannel(settings.Value.Host),
|
||||||
|
version: new Version(2, 13));
|
||||||
|
|
||||||
|
ClientCtx.ContainerService = new ContainerServiceProvider(containerService, ClientCtx);
|
||||||
|
ClientCtx.NetmapService = new NetmapServiceProvider(netmapService, ClientCtx);
|
||||||
|
ClientCtx.SessionService = new SessionServiceProvider(sessionService, ClientCtx);
|
||||||
|
ClientCtx.ObjectService = new ObjectServiceProvider(objectService, ClientCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Client(IOptions<ClientSettings> options)
|
||||||
|
{
|
||||||
|
var clientSettings = (options?.Value) ?? throw new ArgumentException("Options must be initialized");
|
||||||
|
|
||||||
|
clientSettings.Validate();
|
||||||
|
|
||||||
|
var ecdsaKey = clientSettings.Key.LoadWif();
|
||||||
|
var channel = InitGrpcChannel(clientSettings.Host);
|
||||||
|
|
||||||
|
ClientCtx = new ClientEnvironment(
|
||||||
|
key: ecdsaKey,
|
||||||
|
owner: OwnerId.FromKey(ecdsaKey),
|
||||||
|
channel: InitGrpcChannel(clientSettings.Host),
|
||||||
|
version: new Version(2, 13));
|
||||||
|
|
||||||
|
ClientCtx.ContainerService = new ContainerServiceProvider(new ContainerService.ContainerServiceClient(channel), ClientCtx);
|
||||||
|
ClientCtx.NetmapService = new NetmapServiceProvider(new NetmapService.NetmapServiceClient(channel), ClientCtx);
|
||||||
|
ClientCtx.SessionService = new SessionServiceProvider(new SessionService.SessionServiceClient(channel), ClientCtx);
|
||||||
|
ClientCtx.ObjectService = new ObjectServiceProvider(new ObjectService.ObjectServiceClient(channel), ClientCtx);
|
||||||
|
|
||||||
CheckFrostFsVersionSupport();
|
CheckFrostFsVersionSupport();
|
||||||
|
|
||||||
InitNetworkInfoAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void InitNetworkInfoAsync()
|
event EventHandler<GrpcCallInfo> IFrostFSClient.GrpcInvoked
|
||||||
{
|
{
|
||||||
var info = await GetNetworkInfoAsync();
|
add
|
||||||
|
|
||||||
foreach (var param in info.Body.NetworkInfo.NetworkConfig.Parameters)
|
|
||||||
{
|
{
|
||||||
SetNetworksParam(param);
|
ClientCtx.GrpcInvokedEvent += value;
|
||||||
|
}
|
||||||
|
remove
|
||||||
|
{
|
||||||
|
ClientCtx.GrpcInvokedEvent -= value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetNetworksParam(Parameter param)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
var key = Encoding.UTF8.GetString(param.Key.ToByteArray());
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
var encodedValue = param.Value.ToByteArray();
|
|
||||||
|
|
||||||
ulong val = 0;
|
|
||||||
for (var i = encodedValue.Length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
val = (val << 8) + encodedValue[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkSettings.Add(key, val);
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && !isDisposed)
|
||||||
|
{
|
||||||
|
ClientCtx.Dispose();
|
||||||
|
isDisposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void CheckFrostFsVersionSupport()
|
public Task<ModelsV2.Container> GetContainerAsync(ContainerId containerId, Context? ctx = null)
|
||||||
{
|
{
|
||||||
var localNodeInfo = await GetLocalNodeInfoAsync();
|
ValidateEnvironment(ref ctx);
|
||||||
if (!localNodeInfo.Version.IsSupported(Version))
|
return ClientCtx.ContainerService!.GetContainerAsync(containerId, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<ContainerId> ListContainersAsync(Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ContainerService!.ListContainersAsync(ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ContainerId> CreateContainerAsync(ModelsV2.Container container, Context? ctx = null)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ContainerService!.CreateContainerAsync(container, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task DeleteContainerAsync(ContainerId containerId, Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ContainerService!.DeleteContainerAsync(containerId, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<NetmapSnapshot> GetNetmapSnapshotAsync(Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.NetmapService!.GetNetmapSnapshotAsync(ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ModelsV2.Netmap.NodeInfo> GetNodeInfoAsync(Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.NetmapService!.GetLocalNodeInfoAsync(ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ObjectHeader> GetObjectHeadAsync(ContainerId containerId, ObjectId objectId, Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ObjectService!.GetObjectHeadAsync(containerId, objectId, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ModelsV2.Object> GetObjectAsync(ContainerId containerId, ObjectId objectId, Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ObjectService!.GetObjectAsync(containerId, objectId, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ObjectId> PutObjectAsync(PutObjectParameters putObjectParameters, Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ObjectService!.PutObjectAsync(putObjectParameters, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ObjectId> PutSingleObjectAsync(ModelsV2.Object obj, Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ObjectService!.PutSingleObjectAsync(obj, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task DeleteObjectAsync(ContainerId containerId, ObjectId objectId, Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ObjectService!.DeleteObjectAsync(containerId, objectId, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<ObjectId> SearchObjectsAsync(
|
||||||
|
ContainerId containerId,
|
||||||
|
IEnumerable<ObjectFilter> filters,
|
||||||
|
Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
return ClientCtx.ObjectService!.SearchObjectsAsync(containerId, filters, ctx!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectId CalculateObjectId(ObjectHeader header)
|
||||||
|
{
|
||||||
|
return ClientCtx.ObjectService!.CalculateObjectId(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void CheckFrostFsVersionSupport(Context? ctx = default)
|
||||||
|
{
|
||||||
|
ValidateEnvironment(ref ctx);
|
||||||
|
var localNodeInfo = await ClientCtx.NetmapService!.GetLocalNodeInfoAsync(ctx!);
|
||||||
|
|
||||||
|
if (!localNodeInfo.Version.IsSupported(ClientCtx.Version))
|
||||||
{
|
{
|
||||||
var msg = $"FrostFS {localNodeInfo.Version} is not supported.";
|
var msg = $"FrostFS {localNodeInfo.Version} is not supported.";
|
||||||
Console.WriteLine(msg);
|
Console.WriteLine(msg);
|
||||||
|
@ -87,7 +212,18 @@ public partial class Client: IFrostFSClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitGrpcChannel(string host)
|
private void ValidateEnvironment(ref Context? ctx)
|
||||||
|
{
|
||||||
|
if (isDisposed)
|
||||||
|
throw new Exception("Client is disposed.");
|
||||||
|
|
||||||
|
if (ClientCtx == null || !ClientCtx.Initialized)
|
||||||
|
throw new Exception("Client is not initialized.");
|
||||||
|
|
||||||
|
ctx ??= new Context();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GrpcChannel InitGrpcChannel(string host)
|
||||||
{
|
{
|
||||||
Uri uri;
|
Uri uri;
|
||||||
try
|
try
|
||||||
|
@ -116,30 +252,10 @@ public partial class Client: IFrostFSClient
|
||||||
throw new ArgumentException(msg);
|
throw new ArgumentException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
_channel = GrpcChannel.ForAddress(uri, new GrpcChannelOptions
|
return GrpcChannel.ForAddress(uri, new GrpcChannelOptions
|
||||||
{
|
{
|
||||||
Credentials = grpcCredentials,
|
Credentials = grpcCredentials,
|
||||||
HttpHandler = new System.Net.Http.HttpClientHandler()
|
HttpHandler = new System.Net.Http.HttpClientHandler()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitContainerClient()
|
|
||||||
{
|
|
||||||
_containerServiceClient = new ContainerService.ContainerServiceClient(_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitNetmapClient()
|
|
||||||
{
|
|
||||||
_netmapServiceClient = new NetmapService.NetmapServiceClient(_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitObjectClient()
|
|
||||||
{
|
|
||||||
_objectServiceClient = new ObjectService.ObjectServiceClient(_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitSessionClient()
|
|
||||||
{
|
|
||||||
_sessionServiceClient = new SessionService.SessionServiceClient(_channel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,14 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<PackageReference Include="Moq.AutoMock" Version="3.5.0" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
|
||||||
|
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,34 +1,39 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Interfaces;
|
namespace FrostFS.SDK.ClientV2.Interfaces;
|
||||||
|
|
||||||
public interface IFrostFSClient
|
public interface IFrostFSClient
|
||||||
{
|
{
|
||||||
Task<ModelsV2.Container> GetContainerAsync(ContainerId containerId);
|
Task<ModelsV2.Container> GetContainerAsync(ContainerId containerId, Context? context = default);
|
||||||
|
|
||||||
IAsyncEnumerable<ContainerId> ListContainersAsync();
|
IAsyncEnumerable<ContainerId> ListContainersAsync(Context? context = default);
|
||||||
|
|
||||||
Task<ContainerId> CreateContainerAsync(ModelsV2.Container container);
|
Task<ContainerId> CreateContainerAsync(ModelsV2.Container container, Context? context = default);
|
||||||
|
|
||||||
Task DeleteContainerAsync(ContainerId containerId);
|
Task DeleteContainerAsync(ContainerId containerId, Context? context = default);
|
||||||
|
|
||||||
Task<ObjectHeader> GetObjectHeadAsync(ContainerId containerId, ObjectId objectId);
|
Task<ObjectHeader> GetObjectHeadAsync(ContainerId containerId, ObjectId objectId, Context? context = default);
|
||||||
|
|
||||||
|
Task<ModelsV2.Object> GetObjectAsync(ContainerId containerId, ObjectId objectId, Context? context = default);
|
||||||
|
|
||||||
Task<ModelsV2.Object> GetObjectAsync(ContainerId containerId, ObjectId objectId);
|
Task<ObjectId> PutObjectAsync(PutObjectParameters putObjectParameters, Context? context = default);
|
||||||
|
|
||||||
Task<ObjectId> PutObjectAsync(ObjectHeader header, Stream payload, CancellationToken cancellationToken = default);
|
Task<ObjectId> PutSingleObjectAsync(ModelsV2.Object obj, Context? context = default);
|
||||||
|
|
||||||
Task<ObjectId> PutObjectAsync(ObjectHeader header, byte[] payload, CancellationToken cancellationToken = default);
|
Task DeleteObjectAsync(ContainerId containerId, ObjectId objectId, Context? context = default);
|
||||||
|
|
||||||
Task<ObjectId> PutSingleObjectAsync(ModelsV2.Object obj, CancellationToken cancellationToken = default);
|
IAsyncEnumerable<ObjectId> SearchObjectsAsync(ContainerId cid, IEnumerable<ObjectFilter> filters, Context? context = default);
|
||||||
|
|
||||||
Task DeleteObjectAsync(ContainerId containerId, ObjectId objectId);
|
Task<NetmapSnapshot> GetNetmapSnapshotAsync(Context? context = default);
|
||||||
|
|
||||||
IAsyncEnumerable<ObjectId> SearchObjectsAsync(ContainerId cid, params ObjectFilter[] filters);
|
Task<NodeInfo> GetNodeInfoAsync(Context? context = default);
|
||||||
|
|
||||||
|
ObjectId CalculateObjectId(ObjectHeader header);
|
||||||
|
|
||||||
|
event EventHandler<GrpcCallInfo> GrpcInvoked;
|
||||||
}
|
}
|
|
@ -22,16 +22,12 @@ public static class ContainerMapper
|
||||||
|
|
||||||
public static ModelsV2.Container ToModel(this Container.Container container)
|
public static ModelsV2.Container ToModel(this Container.Container container)
|
||||||
{
|
{
|
||||||
var basicAclName = Enum.GetName(typeof(BasicAcl), container.BasicAcl);
|
if (!Enum.IsDefined(typeof(BasicAcl),(int)container.BasicAcl))
|
||||||
if (basicAclName is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Unknown BasicACL rule. Value: '{container.BasicAcl}'.");
|
throw new ArgumentException($"Unknown BasicACL rule. Value: '{container.BasicAcl}'.");
|
||||||
}
|
|
||||||
|
|
||||||
return new ModelsV2.Container(
|
BasicAcl acl = (BasicAcl)container.BasicAcl;
|
||||||
(BasicAcl)Enum.Parse(typeof(BasicAcl), basicAclName),
|
|
||||||
container.PlacementPolicy.ToModel()
|
return new ModelsV2.Container(acl, container.PlacementPolicy.ToModel())
|
||||||
)
|
|
||||||
{
|
{
|
||||||
Nonce = container.Nonce.ToUuid(),
|
Nonce = container.Nonce.ToUuid(),
|
||||||
Version = container.Version.ToModel()
|
Version = container.Version.ToModel()
|
|
@ -1,24 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
using FrostFS.Netmap;
|
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
|
||||||
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
|
||||||
|
|
||||||
public static class NodeInfoMapper
|
|
||||||
{
|
|
||||||
public static NodeInfo ToModel(this LocalNodeInfoResponse.Types.Body nodeInfo)
|
|
||||||
{
|
|
||||||
var nodeStateName = Enum.GetName(typeof(NodeState), nodeInfo.NodeInfo.State);
|
|
||||||
if (nodeStateName is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Unknown NodeState. Value: '{nodeInfo.NodeInfo.State}'.");
|
|
||||||
}
|
|
||||||
return new NodeInfo
|
|
||||||
{
|
|
||||||
State = (NodeState)Enum.Parse(typeof(NodeState), nodeStateName),
|
|
||||||
Version = nodeInfo.Version.ToModel()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
15
src/FrostFS.SDK.ClientV2/Mappers/Netmap/Netmap.cs
Normal file
15
src/FrostFS.SDK.ClientV2/Mappers/Netmap/Netmap.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System.Linq;
|
||||||
|
using FrostFS.Netmap;
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
|
||||||
|
public static class NetmapMapper
|
||||||
|
{
|
||||||
|
public static NetmapSnapshot ToModel(this NetmapSnapshotResponse netmap)
|
||||||
|
{
|
||||||
|
return new NetmapSnapshot(
|
||||||
|
netmap.Body.Netmap.Epoch,
|
||||||
|
netmap.Body.Netmap.Nodes.Select(n => n.ToModel(netmap.MetaHeader.Version)).ToArray());
|
||||||
|
}
|
||||||
|
}
|
35
src/FrostFS.SDK.ClientV2/Mappers/Netmap/NodeInfo.cs
Normal file
35
src/FrostFS.SDK.ClientV2/Mappers/Netmap/NodeInfo.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using FrostFS.Netmap;
|
||||||
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
|
||||||
|
public static class NodeInfoMapper
|
||||||
|
{
|
||||||
|
public static NodeInfo ToModel(this LocalNodeInfoResponse.Types.Body node)
|
||||||
|
{
|
||||||
|
return node.NodeInfo.ToModel(node.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NodeInfo ToModel(this FrostFS.Netmap.NodeInfo nodeInfo, Refs.Version version)
|
||||||
|
{
|
||||||
|
NodeState state = nodeInfo.State switch
|
||||||
|
{
|
||||||
|
FrostFS.Netmap.NodeInfo.Types.State.Unspecified => NodeState.Unspecified,
|
||||||
|
FrostFS.Netmap.NodeInfo.Types.State.Online => NodeState.Online,
|
||||||
|
FrostFS.Netmap.NodeInfo.Types.State.Offline => NodeState.Offline,
|
||||||
|
FrostFS.Netmap.NodeInfo.Types.State.Maintenance => NodeState.Maintenance,
|
||||||
|
_ => throw new ArgumentException($"Unknown NodeState. Value: '{nodeInfo.State}'.")
|
||||||
|
};
|
||||||
|
|
||||||
|
return new NodeInfo(
|
||||||
|
version: version.ToModel(),
|
||||||
|
state: state,
|
||||||
|
addresses: [.. nodeInfo.Addresses],
|
||||||
|
attributes: nodeInfo.Attributes.ToDictionary(n => n.Key, n => n.Value),
|
||||||
|
publicKey: nodeInfo.PublicKey.ToByteArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
14
src/FrostFS.SDK.ClientV2/Mappers/Object/Object.cs
Normal file
14
src/FrostFS.SDK.ClientV2/Mappers/Object/Object.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
|
public static class ObjectMapper
|
||||||
|
{
|
||||||
|
public static ModelsV2.Object ToModel(this Object.Object obj)
|
||||||
|
{
|
||||||
|
return new ModelsV2.Object(
|
||||||
|
ObjectId.FromHash(obj.ObjectId.Value.ToByteArray()),
|
||||||
|
obj.Header.ToModel(),
|
||||||
|
obj.Payload.ToByteArray());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using FrostFS.Object;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
|
public static class ObjectAttributeMapper
|
||||||
|
{
|
||||||
|
public static Header.Types.Attribute ToGrpcMessage(this ObjectAttribute attribute)
|
||||||
|
{
|
||||||
|
return new Header.Types.Attribute
|
||||||
|
{
|
||||||
|
Key = attribute.Key,
|
||||||
|
Value = attribute.Value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ObjectAttribute ToModel(this Header.Types.Attribute attribute)
|
||||||
|
{
|
||||||
|
return new ObjectAttribute(attribute.Key, attribute.Value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using FrostFS.Object;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using MatchType = FrostFS.Object.MatchType;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
|
public static class ObjectFilterMapper
|
||||||
|
{
|
||||||
|
public static SearchRequest.Types.Body.Types.Filter ToGrpcMessage(this ObjectFilter filter)
|
||||||
|
{
|
||||||
|
var objMatchTypeName = filter.MatchType switch
|
||||||
|
{
|
||||||
|
ModelsV2.Enums.ObjectMatchType.Unspecified => MatchType.Unspecified,
|
||||||
|
ModelsV2.Enums.ObjectMatchType.Equals => MatchType.StringEqual,
|
||||||
|
ModelsV2.Enums.ObjectMatchType.NotEquals => MatchType.StringNotEqual,
|
||||||
|
ModelsV2.Enums.ObjectMatchType.KeyAbsent => MatchType.NotPresent,
|
||||||
|
ModelsV2.Enums.ObjectMatchType.StartsWith => MatchType.CommonPrefix,
|
||||||
|
|
||||||
|
_ => throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.")
|
||||||
|
};
|
||||||
|
|
||||||
|
return new SearchRequest.Types.Body.Types.Filter
|
||||||
|
{
|
||||||
|
MatchType = objMatchTypeName,
|
||||||
|
Key = filter.Key,
|
||||||
|
Value = filter.Value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,52 +4,10 @@ using FrostFS.Object;
|
||||||
using FrostFS.SDK.Cryptography;
|
using FrostFS.SDK.Cryptography;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
using MatchType = FrostFS.Object.MatchType;
|
|
||||||
using ObjectType = FrostFS.Object.ObjectType;
|
using ObjectType = FrostFS.Object.ObjectType;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
public static class ObjectAttributeMapper
|
|
||||||
{
|
|
||||||
public static Header.Types.Attribute ToGrpcMessage(this ObjectAttribute attribute)
|
|
||||||
{
|
|
||||||
return new Header.Types.Attribute
|
|
||||||
{
|
|
||||||
Key = attribute.Key,
|
|
||||||
Value = attribute.Value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ObjectAttribute ToModel(this Header.Types.Attribute attribute)
|
|
||||||
{
|
|
||||||
return new ObjectAttribute(attribute.Key, attribute.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ObjectFilterMapper
|
|
||||||
{
|
|
||||||
public static SearchRequest.Types.Body.Types.Filter ToGrpcMessage(this ObjectFilter filter)
|
|
||||||
{
|
|
||||||
var objMatchTypeName = filter.MatchType switch
|
|
||||||
{
|
|
||||||
ModelsV2.Enums.ObjectMatchType.Unspecified => MatchType.Unspecified,
|
|
||||||
ModelsV2.Enums.ObjectMatchType.Equals => MatchType.StringEqual,
|
|
||||||
ModelsV2.Enums.ObjectMatchType.NotEquals => MatchType.StringNotEqual,
|
|
||||||
ModelsV2.Enums.ObjectMatchType.KeyAbsent => MatchType.NotPresent,
|
|
||||||
ModelsV2.Enums.ObjectMatchType.StartsWith => MatchType.CommonPrefix,
|
|
||||||
|
|
||||||
_ => throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.")
|
|
||||||
};
|
|
||||||
|
|
||||||
return new SearchRequest.Types.Body.Types.Filter
|
|
||||||
{
|
|
||||||
MatchType = objMatchTypeName,
|
|
||||||
Key = filter.Key,
|
|
||||||
Value = filter.Value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ObjectHeaderMapper
|
public static class ObjectHeaderMapper
|
||||||
{
|
{
|
||||||
public static Header ToGrpcMessage(this ObjectHeader header)
|
public static Header ToGrpcMessage(this ObjectHeader header)
|
||||||
|
@ -130,37 +88,3 @@ public static class ObjectHeaderMapper
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ObjectMapper
|
|
||||||
{
|
|
||||||
public static ModelsV2.Object ToModel(this Object.Object obj)
|
|
||||||
{
|
|
||||||
return new ModelsV2.Object()
|
|
||||||
{
|
|
||||||
Header = obj.Header.ToModel(),
|
|
||||||
ObjectId = ObjectId.FromHash(obj.ObjectId.Value.ToByteArray()),
|
|
||||||
Payload = obj.Payload.ToByteArray()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SignatureMapper
|
|
||||||
{
|
|
||||||
public static Refs.Signature ToGrpcMessage(this Signature signature)
|
|
||||||
{
|
|
||||||
var scheme = signature.Scheme switch
|
|
||||||
{
|
|
||||||
SignatureScheme.EcdsaRfc6979Sha256 => Refs.SignatureScheme.EcdsaRfc6979Sha256,
|
|
||||||
SignatureScheme.EcdsaRfc6979Sha256WalletConnect => Refs.SignatureScheme.EcdsaRfc6979Sha256WalletConnect,
|
|
||||||
SignatureScheme.EcdsaSha512 => Refs.SignatureScheme.EcdsaSha512,
|
|
||||||
_ => throw new ArgumentException(message: $"Unexpected enum value: {signature.Scheme}", paramName: nameof(signature.Scheme))
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Refs.Signature
|
|
||||||
{
|
|
||||||
Key = ByteString.CopyFrom(signature.Key),
|
|
||||||
Scheme = scheme,
|
|
||||||
Sign = ByteString.CopyFrom(signature.Sign)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
25
src/FrostFS.SDK.ClientV2/Mappers/Session/Session.cs
Normal file
25
src/FrostFS.SDK.ClientV2/Mappers/Session/Session.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Google.Protobuf;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
|
public static class SessionMapper
|
||||||
|
{
|
||||||
|
internal static string SerializeSessionToken(this Session.SessionToken token)
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[token.CalculateSize()];
|
||||||
|
CodedOutputStream stream = new(bytes);
|
||||||
|
token.WriteTo(stream);
|
||||||
|
|
||||||
|
return Convert.ToBase64String(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Session.SessionToken DeserializeSessionToken(this byte[] bytes)
|
||||||
|
{
|
||||||
|
Session.SessionToken token = new();
|
||||||
|
token.MergeFrom(bytes);
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
26
src/FrostFS.SDK.ClientV2/Mappers/SignatureMapper.cs
Normal file
26
src/FrostFS.SDK.ClientV2/Mappers/SignatureMapper.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using Google.Protobuf;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
|
public static class SignatureMapper
|
||||||
|
{
|
||||||
|
public static Refs.Signature ToGrpcMessage(this Signature signature)
|
||||||
|
{
|
||||||
|
var scheme = signature.Scheme switch
|
||||||
|
{
|
||||||
|
SignatureScheme.EcdsaRfc6979Sha256 => Refs.SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
SignatureScheme.EcdsaRfc6979Sha256WalletConnect => Refs.SignatureScheme.EcdsaRfc6979Sha256WalletConnect,
|
||||||
|
SignatureScheme.EcdsaSha512 => Refs.SignatureScheme.EcdsaSha512,
|
||||||
|
_ => throw new ArgumentException(message: $"Unexpected enum value: {signature.Scheme}", paramName: nameof(signature.Scheme))
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Refs.Signature
|
||||||
|
{
|
||||||
|
Key = ByteString.CopyFrom(signature.Key),
|
||||||
|
Scheme = scheme,
|
||||||
|
Sign = ByteString.CopyFrom(signature.Sign)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,85 +0,0 @@
|
||||||
using FrostFS.Container;
|
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
|
||||||
using FrostFS.SDK.Cryptography;
|
|
||||||
using FrostFS.SDK.ModelsV2;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
|
||||||
|
|
||||||
public partial class Client
|
|
||||||
{
|
|
||||||
public async Task<ModelsV2.Container> GetContainerAsync(ContainerId cid)
|
|
||||||
{
|
|
||||||
var request = new GetRequest
|
|
||||||
{
|
|
||||||
Body = new GetRequest.Types.Body
|
|
||||||
{
|
|
||||||
ContainerId = cid.ToGrpcMessage()
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
var response = await _containerServiceClient.GetAsync(request);
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
return response.Body.Container.ToModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async IAsyncEnumerable<ContainerId> ListContainersAsync()
|
|
||||||
{
|
|
||||||
var request = new ListRequest
|
|
||||||
{
|
|
||||||
Body = new ListRequest.Types.Body
|
|
||||||
{
|
|
||||||
OwnerId = OwnerId.ToGrpcMessage()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
var response = await _containerServiceClient.ListAsync(request);
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
foreach (var cid in response.Body.ContainerIds)
|
|
||||||
{
|
|
||||||
yield return new ContainerId(Base58.Encode(cid.Value.ToByteArray()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ContainerId> CreateContainerAsync(ModelsV2.Container container)
|
|
||||||
{
|
|
||||||
var cntnr = container.ToGrpcMessage();
|
|
||||||
cntnr.OwnerId = OwnerId.ToGrpcMessage();
|
|
||||||
cntnr.Version = Version.ToGrpcMessage();
|
|
||||||
|
|
||||||
var request = new PutRequest
|
|
||||||
{
|
|
||||||
Body = new PutRequest.Types.Body
|
|
||||||
{
|
|
||||||
Container = cntnr,
|
|
||||||
Signature = _key.SignRFC6979(cntnr),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
var response = await _containerServiceClient.PutAsync(request);
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
return new ContainerId(Base58.Encode(response.Body.ContainerId.Value.ToByteArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteContainerAsync(ContainerId cid)
|
|
||||||
{
|
|
||||||
var request = new DeleteRequest
|
|
||||||
{
|
|
||||||
Body = new DeleteRequest.Types.Body
|
|
||||||
{
|
|
||||||
ContainerId = cid.ToGrpcMessage(),
|
|
||||||
Signature = _key.SignRFC6979(cid.ToGrpcMessage().Value)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
var response = await _containerServiceClient.DeleteAsync(request);
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
}
|
|
||||||
}
|
|
117
src/FrostFS.SDK.ClientV2/Services/ContainerServiceProvider.cs
Normal file
117
src/FrostFS.SDK.ClientV2/Services/ContainerServiceProvider.cs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using FrostFS.Container;
|
||||||
|
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
internal class ContainerServiceProvider : ContextAccessor
|
||||||
|
{
|
||||||
|
private readonly ContainerService.ContainerServiceClient containerServiceClient;
|
||||||
|
|
||||||
|
internal ContainerServiceProvider(ContainerService.ContainerServiceClient service, ClientEnvironment context)
|
||||||
|
: base(context)
|
||||||
|
{
|
||||||
|
containerServiceClient = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<ModelsV2.Container> GetContainerAsync(ContainerId cid, Context context)
|
||||||
|
{
|
||||||
|
var request = new GetRequest
|
||||||
|
{
|
||||||
|
Body = new GetRequest.Types.Body
|
||||||
|
{
|
||||||
|
ContainerId = cid.ToGrpcMessage()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
containerServiceClient.GetAsync(request, null, context.Deadline, context.CancellationToken),
|
||||||
|
nameof(containerServiceClient.GetAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return response.Body.Container.ToModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async IAsyncEnumerable<ContainerId> ListContainersAsync(Context ctx)
|
||||||
|
{
|
||||||
|
var request = new ListRequest
|
||||||
|
{
|
||||||
|
Body = new ListRequest.Types.Body
|
||||||
|
{
|
||||||
|
OwnerId = Context.Owner.ToGrpcMessage()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
containerServiceClient.ListAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(containerServiceClient.ListAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
foreach (var cid in response.Body.ContainerIds)
|
||||||
|
{
|
||||||
|
yield return new ContainerId(Base58.Encode(cid.Value.ToByteArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<ContainerId> CreateContainerAsync(ModelsV2.Container container, Context ctx)
|
||||||
|
{
|
||||||
|
var grpcContainer = container.ToGrpcMessage();
|
||||||
|
grpcContainer.OwnerId = Context.Owner.ToGrpcMessage();
|
||||||
|
grpcContainer.Version = Context.Version.ToGrpcMessage();
|
||||||
|
|
||||||
|
var request = new PutRequest
|
||||||
|
{
|
||||||
|
Body = new PutRequest.Types.Body
|
||||||
|
{
|
||||||
|
Container = grpcContainer,
|
||||||
|
Signature = Context.Key.SignRFC6979(grpcContainer),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
containerServiceClient.PutAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(containerServiceClient.PutAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return new ContainerId(Base58.Encode(response.Body.ContainerId.Value.ToByteArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task DeleteContainerAsync(ContainerId cid, Context ctx)
|
||||||
|
{
|
||||||
|
var request = new DeleteRequest
|
||||||
|
{
|
||||||
|
Body = new DeleteRequest.Types.Body
|
||||||
|
{
|
||||||
|
ContainerId = cid.ToGrpcMessage(),
|
||||||
|
Signature = Context.Key.SignRFC6979(cid.ToGrpcMessage().Value)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
containerServiceClient.DeleteAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(containerServiceClient.DeleteAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using FrostFS.Netmap;
|
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
|
||||||
|
|
||||||
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
|
||||||
|
|
||||||
public partial class Client
|
|
||||||
{
|
|
||||||
public async Task<NodeInfo> GetLocalNodeInfoAsync()
|
|
||||||
{
|
|
||||||
var request = new LocalNodeInfoRequest
|
|
||||||
{
|
|
||||||
Body = new LocalNodeInfoRequest.Types.Body { }
|
|
||||||
};
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
var response = await _netmapServiceClient.LocalNodeInfoAsync(request);
|
|
||||||
|
|
||||||
return response.Body.ToModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<NetworkInfoResponse> GetNetworkInfoAsync()
|
|
||||||
{
|
|
||||||
var request = new NetworkInfoRequest
|
|
||||||
{
|
|
||||||
Body = new NetworkInfoRequest.Types.Body { }
|
|
||||||
};
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
|
|
||||||
return await _netmapServiceClient.NetworkInfoAsync(request);
|
|
||||||
}
|
|
||||||
}
|
|
134
src/FrostFS.SDK.ClientV2/Services/NetmapServiceProvider.cs
Normal file
134
src/FrostFS.SDK.ClientV2/Services/NetmapServiceProvider.cs
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FrostFS.Netmap;
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
||||||
|
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
using static FrostFS.Netmap.NetworkConfig.Types;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
internal class NetmapServiceProvider : ContextAccessor
|
||||||
|
{
|
||||||
|
private readonly NetmapService.NetmapServiceClient netmapServiceClient;
|
||||||
|
|
||||||
|
internal NetmapServiceProvider(NetmapService.NetmapServiceClient netmapServiceClient, ClientEnvironment context)
|
||||||
|
: base(context)
|
||||||
|
{
|
||||||
|
this.netmapServiceClient = netmapServiceClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<NetworkSettings> GetNetworkSettingsAsync(Context ctx)
|
||||||
|
{
|
||||||
|
if (Context.NetworkSettings != null)
|
||||||
|
return Context.NetworkSettings;
|
||||||
|
|
||||||
|
var info = await GetNetworkInfoAsync(ctx);
|
||||||
|
|
||||||
|
var settings = new NetworkSettings();
|
||||||
|
|
||||||
|
foreach (var param in info.Body.NetworkInfo.NetworkConfig.Parameters)
|
||||||
|
{
|
||||||
|
SetNetworksParam(param, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.NetworkSettings = settings;
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<NodeInfo> GetLocalNodeInfoAsync(Context ctx)
|
||||||
|
{
|
||||||
|
var request = new LocalNodeInfoRequest
|
||||||
|
{
|
||||||
|
Body = new LocalNodeInfoRequest.Types.Body { }
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
netmapServiceClient.LocalNodeInfoAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(netmapServiceClient.LocalNodeInfoAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return response.Body.ToModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<NetworkInfoResponse> GetNetworkInfoAsync(Context ctx)
|
||||||
|
{
|
||||||
|
var request = new NetworkInfoRequest
|
||||||
|
{
|
||||||
|
Body = new NetworkInfoRequest.Types.Body { }
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
netmapServiceClient.NetworkInfoAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(netmapServiceClient.NetworkInfoAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<NetmapSnapshot> GetNetmapSnapshotAsync(Context ctx)
|
||||||
|
{
|
||||||
|
var request = new NetmapSnapshotRequest
|
||||||
|
{
|
||||||
|
Body = new NetmapSnapshotRequest.Types.Body { }
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
netmapServiceClient.NetmapSnapshotAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(netmapServiceClient.NetmapSnapshotAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return response.ToModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool GetBoolValue(byte[] bytes)
|
||||||
|
{
|
||||||
|
return bytes.Any(b => b != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong GetLongValue(byte[] bytes)
|
||||||
|
{
|
||||||
|
ulong val = 0;
|
||||||
|
for (var i = bytes.Length - 1; i >= 0; i--)
|
||||||
|
val = (val << 8) + bytes[i];
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetNetworksParam(Parameter param, NetworkSettings settings)
|
||||||
|
{
|
||||||
|
var key = Encoding.UTF8.GetString(param.Key.ToByteArray());
|
||||||
|
|
||||||
|
var valueBytes = param.Value.ToByteArray();
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case "ContainerFee": settings.ContainerFee = GetLongValue(valueBytes); break;
|
||||||
|
case "EpochDuration": settings.EpochDuration = GetLongValue(valueBytes); break;
|
||||||
|
case "IRCandidateFee": settings.IRCandidateFee = GetLongValue(valueBytes); break;
|
||||||
|
case "MaxECDataCount": settings.MaxECDataCount = GetLongValue(valueBytes); break;
|
||||||
|
case "MaxECParityCount": settings.MaxECParityCount = GetLongValue(valueBytes); break;
|
||||||
|
case "MaxObjectSize": settings.MaxObjectSize = GetLongValue(valueBytes); break;
|
||||||
|
case "WithdrawalFee": settings.WithdrawalFee = GetLongValue(valueBytes); break;
|
||||||
|
case "HomomorphicHashingDisabled": settings.HomomorphicHashingDisabled = GetBoolValue(valueBytes); break;
|
||||||
|
case "MaintenanceModeAllowed": settings.MaintenanceModeAllowed = GetBoolValue(valueBytes); break;
|
||||||
|
default: settings.UnnamedSettings.Add(key, valueBytes); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,20 @@ using FrostFS.Object;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
internal class ObjectReader : IDisposable
|
internal class ObjectReader(AsyncServerStreamingCall<GetResponse> call) : IDisposable
|
||||||
{
|
{
|
||||||
public AsyncServerStreamingCall<GetResponse> Call { get; set; }
|
public AsyncServerStreamingCall<GetResponse> Call { get; private set; } = call;
|
||||||
|
|
||||||
public async Task<Object.Object> ReadHeader()
|
public async Task<Object.Object> ReadHeader()
|
||||||
{
|
{
|
||||||
if (!await Call.ResponseStream.MoveNext())
|
if (!await Call.ResponseStream.MoveNext())
|
||||||
throw new InvalidOperationException("unexpect end of stream");
|
throw new InvalidOperationException("unexpected end of stream");
|
||||||
|
|
||||||
var response = Call.ResponseStream.Current;
|
var response = Call.ResponseStream.Current;
|
||||||
Verifier.CheckResponse(response);
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init)
|
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init)
|
||||||
throw new InvalidOperationException("unexpect message type");
|
throw new InvalidOperationException("unexpected message type");
|
||||||
|
|
||||||
return new Object.Object
|
return new Object.Object
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,7 @@ internal class ObjectReader : IDisposable
|
||||||
Verifier.CheckResponse(response);
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk)
|
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk)
|
||||||
throw new InvalidOperationException("unexpect message type");
|
throw new InvalidOperationException("unexpected message type");
|
||||||
|
|
||||||
return response.Body.Chunk.ToByteArray();
|
return response.Body.Chunk.ToByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -11,16 +10,22 @@ 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.Session;
|
using FrostFS.Session;
|
||||||
|
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using FrostFS.SDK.ClientV2.Extensions;
|
using FrostFS.SDK.ClientV2.Extensions;
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
public partial class Client
|
internal class ObjectServiceProvider : ContextAccessor
|
||||||
{
|
{
|
||||||
public async Task<ObjectHeader> GetObjectHeadAsync(ContainerId cid, ObjectId oid)
|
private readonly ObjectService.ObjectServiceClient objectServiceClient;
|
||||||
|
|
||||||
|
internal ObjectServiceProvider(ObjectService.ObjectServiceClient objectServiceClient, ClientEnvironment context)
|
||||||
|
: base (context)
|
||||||
|
{
|
||||||
|
this.objectServiceClient = objectServiceClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<ObjectHeader> GetObjectHeadAsync(ContainerId cid, ObjectId oid, Context ctx)
|
||||||
{
|
{
|
||||||
var request = new HeadRequest
|
var request = new HeadRequest
|
||||||
{
|
{
|
||||||
|
@ -34,18 +39,22 @@ public partial class Client
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(Context.Key);
|
||||||
var response = await _objectServiceClient!.HeadAsync(request);
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
objectServiceClient!.HeadAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(objectServiceClient.HeadAsync));
|
||||||
|
|
||||||
Verifier.CheckResponse(response);
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
return response.Body.Header.Header.ToModel();
|
return response.Body.Header.Header.ToModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ModelsV2.Object> GetObjectAsync(ContainerId cid, ObjectId oid)
|
internal async Task<ModelsV2.Object> GetObjectAsync(ContainerId cid, ObjectId oid, Context ctx)
|
||||||
{
|
{
|
||||||
var sessionToken = await CreateSessionAsync(uint.MaxValue);
|
var sessionToken = await GetOrCreateSession(ctx);
|
||||||
|
|
||||||
var request = new GetRequest
|
var request = new GetRequest
|
||||||
{
|
{
|
||||||
Body = new GetRequest.Types.Body
|
Body = new GetRequest.Types.Body
|
||||||
|
@ -64,41 +73,137 @@ public partial class Client
|
||||||
cid.ToGrpcMessage(),
|
cid.ToGrpcMessage(),
|
||||||
oid.ToGrpcMessage(),
|
oid.ToGrpcMessage(),
|
||||||
ObjectSessionContext.Types.Verb.Get,
|
ObjectSessionContext.Types.Verb.Get,
|
||||||
_key
|
Context.Key
|
||||||
);
|
);
|
||||||
|
|
||||||
request.Sign(_key);
|
request.Sign(Context.Key);
|
||||||
var obj = await GetObject(request);
|
|
||||||
|
var obj = await GetObject(request, ctx);
|
||||||
|
|
||||||
return obj.ToModel();
|
return obj.ToModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ObjectId> PutObjectAsync(ObjectHeader header, Stream payload, CancellationToken cancellationToken = default)
|
internal Task<ObjectId> PutObjectAsync(PutObjectParameters parameters, Context ctx)
|
||||||
{
|
{
|
||||||
return await PutObject(header, payload, cancellationToken);
|
if (parameters.Header == null)
|
||||||
}
|
throw new ArgumentException("Value cannot be null", nameof(parameters.Header));
|
||||||
|
|
||||||
public async Task<ObjectId> PutObjectAsync(ObjectHeader header, byte[] payload, CancellationToken cancellationToken = default)
|
if (parameters.Payload == null)
|
||||||
{
|
throw new ArgumentException("Value cannot be null", nameof(parameters.Payload));
|
||||||
using var stream = new MemoryStream(payload);
|
|
||||||
return await PutObject(header, stream, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<ObjectId> PutObject(ObjectHeader header, Stream payload, CancellationToken cancellationToken)
|
if (parameters.ClientCut)
|
||||||
{
|
return PutClientCutObject(parameters, ctx);
|
||||||
if (header.ClientCut)
|
|
||||||
return PutClientCutObject(header, payload, cancellationToken);
|
|
||||||
else
|
else
|
||||||
return PutStreamObject(header, payload, cancellationToken);
|
return PutStreamObject(parameters, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ObjectId> PutClientCutObject(ObjectHeader header, Stream payloadStream, CancellationToken cancellationToken)
|
internal async Task<ObjectId> PutSingleObjectAsync(ModelsV2.Object @object, Context ctx)
|
||||||
{
|
{
|
||||||
ObjectId? objectId = null;
|
var sessionToken = await GetOrCreateSession(ctx);
|
||||||
|
|
||||||
|
var obj = CreateObject(@object);
|
||||||
|
|
||||||
|
var request = new PutSingleRequest
|
||||||
|
{
|
||||||
|
Body = new PutSingleRequest.Types.Body()
|
||||||
|
{
|
||||||
|
Object = obj
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.AddObjectSessionToken(
|
||||||
|
sessionToken,
|
||||||
|
obj.Header.ContainerId,
|
||||||
|
obj.ObjectId,
|
||||||
|
ObjectSessionContext.Types.Verb.Put,
|
||||||
|
Context.Key
|
||||||
|
);
|
||||||
|
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
objectServiceClient!.PutSingleAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(objectServiceClient.PutSingleAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return ObjectId.FromHash(obj.ObjectId.Value.ToByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ObjectId CalculateObjectId(ObjectHeader header)
|
||||||
|
{
|
||||||
|
var grpcHeader = CreateHeader(header, []);
|
||||||
|
|
||||||
|
return new ObjectID { Value = grpcHeader.Sha256() }.ToModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task DeleteObjectAsync(ContainerId cid, ObjectId oid, Context ctx)
|
||||||
|
{
|
||||||
|
var request = new DeleteRequest
|
||||||
|
{
|
||||||
|
Body = new DeleteRequest.Types.Body
|
||||||
|
{
|
||||||
|
Address = new Address
|
||||||
|
{
|
||||||
|
ContainerId = cid.ToGrpcMessage(),
|
||||||
|
ObjectId = oid.ToGrpcMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var response = await Context.InvokeAsyncUnaryWithMetrics(() =>
|
||||||
|
objectServiceClient!.DeleteAsync(request, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(objectServiceClient.DeleteAsync));
|
||||||
|
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async IAsyncEnumerable<ObjectId> SearchObjectsAsync(
|
||||||
|
ContainerId cid,
|
||||||
|
IEnumerable<ObjectFilter> filters,
|
||||||
|
Context ctx)
|
||||||
|
{
|
||||||
|
var request = new SearchRequest
|
||||||
|
{
|
||||||
|
Body = new SearchRequest.Types.Body
|
||||||
|
{
|
||||||
|
ContainerId = cid.ToGrpcMessage(),
|
||||||
|
Filters = { },
|
||||||
|
Version = 1 // TODO: clarify this param
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.Body.Filters.AddRange(filters.Select(f => f.ToGrpcMessage()));
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
|
var objectsIds = SearchObjects(request, ctx);
|
||||||
|
|
||||||
|
await foreach (var oid in objectsIds)
|
||||||
|
{
|
||||||
|
yield return ObjectId.FromHash(oid.Value.ToByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ObjectId> PutClientCutObject(PutObjectParameters parameters, Context ctx)
|
||||||
|
{
|
||||||
|
var payloadStream = parameters.Payload!;
|
||||||
|
var header = parameters.Header!;
|
||||||
|
|
||||||
|
ObjectId? objectId;
|
||||||
List<ObjectId> sentObjectIds = [];
|
List<ObjectId> sentObjectIds = [];
|
||||||
ModelsV2.Object? currentObject;
|
ModelsV2.Object? currentObject;
|
||||||
|
|
||||||
var partSize = (int)NetworkSettings["MaxObjectSize"];
|
var networkSettings = await Context.InvokeAsyncWithMetrics(() =>
|
||||||
|
Context.NetmapService!.GetNetworkSettingsAsync(ctx),
|
||||||
|
nameof(Context.NetmapService.GetNetworkSettingsAsync));
|
||||||
|
|
||||||
|
var partSize = (int)networkSettings.MaxObjectSize;
|
||||||
var buffer = new byte[partSize];
|
var buffer = new byte[partSize];
|
||||||
|
|
||||||
var largeObject = new LargeObject(header.ContainerId);
|
var largeObject = new LargeObject(header.ContainerId);
|
||||||
|
@ -109,8 +214,6 @@ public partial class Client
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var bytesCount = await payloadStream.ReadAsync(buffer, 0, partSize);
|
var bytesCount = await payloadStream.ReadAsync(buffer, 0, partSize);
|
||||||
|
|
||||||
split.Previous = sentObjectIds.LastOrDefault();
|
split.Previous = sentObjectIds.LastOrDefault();
|
||||||
|
@ -124,7 +227,7 @@ public partial class Client
|
||||||
if (largeObject.PayloadLength == fullLength)
|
if (largeObject.PayloadLength == fullLength)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
objectId = await PutSingleObjectAsync(currentObject, cancellationToken);
|
objectId = await PutSingleObjectAsync(currentObject, ctx);
|
||||||
|
|
||||||
sentObjectIds.Add(objectId!);
|
sentObjectIds.Add(objectId!);
|
||||||
}
|
}
|
||||||
|
@ -135,26 +238,30 @@ public partial class Client
|
||||||
|
|
||||||
currentObject.SetParent(largeObject);
|
currentObject.SetParent(largeObject);
|
||||||
|
|
||||||
objectId = await PutSingleObjectAsync(currentObject, cancellationToken);
|
objectId = await PutSingleObjectAsync(currentObject, ctx);
|
||||||
sentObjectIds.Add(objectId);
|
sentObjectIds.Add(objectId);
|
||||||
|
|
||||||
var linkObject = new LinkObject(header.ContainerId, split.SplitId, largeObject)
|
var linkObject = new LinkObject(header.ContainerId, split.SplitId, largeObject)
|
||||||
.AddChildren(sentObjectIds);
|
.AddChildren(sentObjectIds);
|
||||||
|
|
||||||
_ = await PutSingleObjectAsync(linkObject, cancellationToken);
|
_ = await PutSingleObjectAsync(linkObject, ctx);
|
||||||
|
|
||||||
return currentObject.GetParentId();
|
return CalculateObjectId(largeObject.Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await PutSingleObjectAsync(currentObject, cancellationToken);
|
return await PutSingleObjectAsync(currentObject, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ObjectId> PutStreamObject(ObjectHeader header, Stream payload, CancellationToken cancellationToken)
|
private async Task<ObjectId> PutStreamObject(PutObjectParameters parameters, Context ctx)
|
||||||
{
|
{
|
||||||
var sessionToken = await CreateSessionAsync(uint.MaxValue);
|
var payload = parameters.Payload!;
|
||||||
|
var header = parameters.Header!;
|
||||||
|
|
||||||
|
var sessionToken = await GetOrCreateSession(ctx);
|
||||||
|
|
||||||
var hdr = header.ToGrpcMessage();
|
var hdr = header.ToGrpcMessage();
|
||||||
hdr.OwnerId = OwnerId.ToGrpcMessage();
|
hdr.OwnerId = Context.Owner.ToGrpcMessage();
|
||||||
hdr.Version = Version.ToGrpcMessage();
|
hdr.Version = Context.Version.ToGrpcMessage();
|
||||||
|
|
||||||
var oid = new ObjectID
|
var oid = new ObjectID
|
||||||
{
|
{
|
||||||
|
@ -178,19 +285,17 @@ public partial class Client
|
||||||
hdr.ContainerId,
|
hdr.ContainerId,
|
||||||
oid,
|
oid,
|
||||||
ObjectSessionContext.Types.Verb.Put,
|
ObjectSessionContext.Types.Verb.Put,
|
||||||
_key
|
Context.Key
|
||||||
);
|
);
|
||||||
|
|
||||||
request.Sign(_key);
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
using var stream = await PutObjectInit(request);
|
using var stream = await PutObjectInit(request, ctx);
|
||||||
var buffer = new byte[Constants.ObjectChunkSize];
|
var buffer = new byte[Constants.ObjectChunkSize];
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
var bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize, ctx.CancellationToken);
|
||||||
|
|
||||||
var bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize);
|
|
||||||
|
|
||||||
if (bufferLength == 0)
|
if (bufferLength == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -201,7 +306,7 @@ public partial class Client
|
||||||
};
|
};
|
||||||
|
|
||||||
request.VerifyHeader = null;
|
request.VerifyHeader = null;
|
||||||
request.Sign(_key);
|
request.Sign(Context.Key);
|
||||||
await stream.Write(request);
|
await stream.Write(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,40 +316,98 @@ public partial class Client
|
||||||
return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray());
|
return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ObjectId> PutSingleObjectAsync(ModelsV2.Object @object, CancellationToken cancellationToken = default)
|
// TODO: add implementation with stream writer!
|
||||||
|
private async Task<Object.Object> GetObject(GetRequest request, Context ctx)
|
||||||
{
|
{
|
||||||
var sessionToken = await CreateSessionAsync(uint.MaxValue);
|
using var stream = GetObjectInit(request, ctx);
|
||||||
|
|
||||||
var obj = CreateObject(@object);
|
var obj = await stream.ReadHeader();
|
||||||
|
var payload = new byte[obj.Header.PayloadLength];
|
||||||
|
var offset = 0L;
|
||||||
|
var chunk = await stream.ReadChunk();
|
||||||
|
|
||||||
var request = new PutSingleRequest
|
while (chunk is not null && (ulong)offset < obj.Header.PayloadLength)
|
||||||
{
|
{
|
||||||
Body = new () { Object = obj }
|
var length = Math.Min((long)obj.Header.PayloadLength - offset, chunk.Length);
|
||||||
};
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
Array.Copy(chunk, 0, payload, offset, length);
|
||||||
request.AddObjectSessionToken(
|
offset += chunk.Length;
|
||||||
sessionToken,
|
chunk = await stream.ReadChunk();
|
||||||
obj.Header.ContainerId,
|
|
||||||
obj.ObjectId,
|
|
||||||
ObjectSessionContext.Types.Verb.Put,
|
|
||||||
_key
|
|
||||||
);
|
|
||||||
|
|
||||||
request.Sign(_key);
|
|
||||||
|
|
||||||
var response = await _objectServiceClient!.PutSingleAsync(request, null, null, cancellationToken);
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
|
|
||||||
return ObjectId.FromHash(obj.ObjectId.Value.ToByteArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object.Object CreateObject(ModelsV2.Object @object)
|
obj.Payload = ByteString.CopyFrom(payload);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectReader GetObjectInit(GetRequest initRequest, Context ctx)
|
||||||
|
{
|
||||||
|
if (initRequest is null)
|
||||||
|
throw new ArgumentNullException(nameof(initRequest));
|
||||||
|
|
||||||
|
var call = Context.InvokeWithMetrics(() =>
|
||||||
|
objectServiceClient!.Get(initRequest, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(objectServiceClient.Get));
|
||||||
|
|
||||||
|
return new ObjectReader(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ObjectStreamer> PutObjectInit(PutRequest initRequest, Context ctx)
|
||||||
|
{
|
||||||
|
if (initRequest is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(initRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
var call = Context.InvokeWithMetrics(() =>
|
||||||
|
objectServiceClient!.Put(null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(objectServiceClient.Put));
|
||||||
|
|
||||||
|
await call.RequestStream.WriteAsync(initRequest);
|
||||||
|
|
||||||
|
return new ObjectStreamer(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async IAsyncEnumerable<ObjectID> SearchObjects(SearchRequest request, Context ctx)
|
||||||
|
{
|
||||||
|
using var stream = GetSearchReader(request, ctx);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var ids = await Context.InvokeAsyncWithMetrics(() =>
|
||||||
|
stream.Read(ctx.CancellationToken),
|
||||||
|
"SearchObject.ReadStream");
|
||||||
|
|
||||||
|
if (ids == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
foreach (var oid in ids)
|
||||||
|
{
|
||||||
|
yield return oid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SearchReader GetSearchReader(SearchRequest initRequest, Context ctx)
|
||||||
|
{
|
||||||
|
if (initRequest is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(initRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
var call = Context.InvokeWithMetrics(() =>
|
||||||
|
objectServiceClient!.Search(initRequest, null, ctx.Deadline, ctx.CancellationToken),
|
||||||
|
nameof(objectServiceClient.Search));
|
||||||
|
|
||||||
|
return new SearchReader(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object.Object CreateObject(ModelsV2.Object @object)
|
||||||
{
|
{
|
||||||
var grpcHeader = @object.Header.ToGrpcMessage();
|
var grpcHeader = @object.Header.ToGrpcMessage();
|
||||||
|
|
||||||
grpcHeader.OwnerId = OwnerId.ToGrpcMessage();
|
grpcHeader.OwnerId = Context.Owner.ToGrpcMessage();
|
||||||
grpcHeader.Version = Version.ToGrpcMessage();
|
grpcHeader.Version = Context.Version.ToGrpcMessage();
|
||||||
|
|
||||||
if (@object.Payload != null)
|
if (@object.Payload != null)
|
||||||
{
|
{
|
||||||
|
@ -271,8 +434,8 @@ public partial class Client
|
||||||
grpcHeader.Split.ParentHeader = grpcParentHeader;
|
grpcHeader.Split.ParentHeader = grpcParentHeader;
|
||||||
grpcHeader.Split.ParentSignature = new Refs.Signature
|
grpcHeader.Split.ParentSignature = new Refs.Signature
|
||||||
{
|
{
|
||||||
Key = ByteString.CopyFrom(_key.PublicKey()),
|
Key = ByteString.CopyFrom(Context.Key.PublicKey()),
|
||||||
Sign = ByteString.CopyFrom(_key.SignData(grpcHeader.Split.Parent.ToByteArray())),
|
Sign = ByteString.CopyFrom(Context.Key.SignData(grpcHeader.Split.Parent.ToByteArray())),
|
||||||
};
|
};
|
||||||
|
|
||||||
split.Parent = grpcHeader.Split.Parent.ToModel();
|
split.Parent = grpcHeader.Split.Parent.ToModel();
|
||||||
|
@ -290,159 +453,29 @@ public partial class Client
|
||||||
|
|
||||||
obj.Signature = new Refs.Signature
|
obj.Signature = new Refs.Signature
|
||||||
{
|
{
|
||||||
Key = ByteString.CopyFrom(_key.PublicKey()),
|
Key = ByteString.CopyFrom(Context.Key.PublicKey()),
|
||||||
Sign = ByteString.CopyFrom(_key.SignData(obj.ObjectId.ToByteArray())),
|
Sign = ByteString.CopyFrom(Context.Key.SignData(obj.ObjectId.ToByteArray())),
|
||||||
};
|
};
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Header CreateHeader(ObjectHeader header, byte[]? payload)
|
private Header CreateHeader(ObjectHeader header, byte[]? payload)
|
||||||
{
|
{
|
||||||
var grpcHeader = header.ToGrpcMessage();
|
var grpcHeader = header.ToGrpcMessage();
|
||||||
|
|
||||||
grpcHeader.OwnerId = OwnerId.ToGrpcMessage();
|
grpcHeader.OwnerId = Context.Owner.ToGrpcMessage();
|
||||||
grpcHeader.Version = Version.ToGrpcMessage();
|
grpcHeader.Version = Context.Version.ToGrpcMessage();
|
||||||
|
|
||||||
if (header.PayloadCheckSum != null)
|
if (header.PayloadCheckSum != null)
|
||||||
{
|
grpcHeader.PayloadHash = Sha256Checksum(header.PayloadCheckSum);
|
||||||
grpcHeader.PayloadHash = new Checksum
|
else if (payload != null)
|
||||||
{
|
|
||||||
Type = ChecksumType.Sha256,
|
|
||||||
Sum = ByteString.CopyFrom(header.PayloadCheckSum)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (payload != null)
|
|
||||||
grpcHeader.PayloadHash = Sha256Checksum(payload);
|
grpcHeader.PayloadHash = Sha256Checksum(payload);
|
||||||
}
|
|
||||||
|
|
||||||
return grpcHeader;
|
return grpcHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteObjectAsync(ContainerId cid, ObjectId oid)
|
private Checksum Sha256Checksum(byte[] data)
|
||||||
{
|
|
||||||
var request = new DeleteRequest
|
|
||||||
{
|
|
||||||
Body = new DeleteRequest.Types.Body
|
|
||||||
{
|
|
||||||
Address = new Address
|
|
||||||
{
|
|
||||||
ContainerId = cid.ToGrpcMessage(),
|
|
||||||
ObjectId = oid.ToGrpcMessage()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
var response = await _objectServiceClient!.DeleteAsync(request);
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async IAsyncEnumerable<ObjectId> SearchObjectsAsync(ContainerId cid, params ObjectFilter[] filters)
|
|
||||||
{
|
|
||||||
var request = new SearchRequest
|
|
||||||
{
|
|
||||||
Body = new SearchRequest.Types.Body
|
|
||||||
{
|
|
||||||
ContainerId = cid.ToGrpcMessage(),
|
|
||||||
Filters = { },
|
|
||||||
Version = 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var filter in filters)
|
|
||||||
{
|
|
||||||
request.Body.Filters.Add(filter.ToGrpcMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.Sign(_key);
|
|
||||||
var objectsIds = SearchObjects(request);
|
|
||||||
|
|
||||||
|
|
||||||
await foreach (var oid in objectsIds)
|
|
||||||
{
|
|
||||||
yield return ObjectId.FromHash(oid.Value.ToByteArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Object.Object> GetObject(GetRequest request)
|
|
||||||
{
|
|
||||||
using var stream = GetObjectInit(request);
|
|
||||||
var obj = await stream.ReadHeader();
|
|
||||||
var payload = new byte[obj.Header.PayloadLength];
|
|
||||||
var offset = 0L;
|
|
||||||
var chunk = await stream.ReadChunk();
|
|
||||||
|
|
||||||
while (chunk is not null && (ulong)offset < obj.Header.PayloadLength)
|
|
||||||
{
|
|
||||||
var length = Math.Min((long)obj.Header.PayloadLength - offset, chunk.Length);
|
|
||||||
|
|
||||||
Array.Copy(chunk, 0, payload, offset, length);
|
|
||||||
offset += chunk.Length;
|
|
||||||
chunk = await stream.ReadChunk();
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.Payload = ByteString.CopyFrom(payload);
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObjectReader GetObjectInit(GetRequest initRequest)
|
|
||||||
{
|
|
||||||
if (initRequest is null)
|
|
||||||
throw new ArgumentNullException(nameof(initRequest));
|
|
||||||
|
|
||||||
|
|
||||||
return new ObjectReader
|
|
||||||
{
|
|
||||||
Call = _objectServiceClient!.Get(initRequest)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<ObjectStreamer> PutObjectInit(PutRequest initRequest)
|
|
||||||
{
|
|
||||||
if (initRequest is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(initRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
var call = _objectServiceClient!.Put();
|
|
||||||
await call.RequestStream.WriteAsync(initRequest);
|
|
||||||
|
|
||||||
return new ObjectStreamer(call);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async IAsyncEnumerable<ObjectID> SearchObjects(SearchRequest request)
|
|
||||||
{
|
|
||||||
using var stream = GetSearchReader(request);
|
|
||||||
var ids = await stream.Read();
|
|
||||||
while (ids is not null)
|
|
||||||
{
|
|
||||||
foreach (var oid in ids)
|
|
||||||
{
|
|
||||||
yield return oid;
|
|
||||||
}
|
|
||||||
|
|
||||||
ids = await stream.Read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SearchReader GetSearchReader(SearchRequest initRequest)
|
|
||||||
{
|
|
||||||
if (initRequest is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(initRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SearchReader(_objectServiceClient!.Search(initRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Checksum Sha256Checksum(byte[] data)
|
|
||||||
{
|
{
|
||||||
return new Checksum
|
return new Checksum
|
||||||
{
|
{
|
||||||
|
@ -450,8 +483,16 @@ public partial class Client
|
||||||
Sum = ByteString.CopyFrom(data.Sha256())
|
Sum = ByteString.CopyFrom(data.Sha256())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Session.SessionToken> GetOrCreateSession(Context ctx)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(ctx.SessionToken))
|
||||||
|
{
|
||||||
|
return await Context.InvokeAsyncWithMetrics(() =>
|
||||||
|
Context.SessionService!.CreateSessionAsync(uint.MaxValue, ctx),
|
||||||
|
nameof(Context.SessionService.CreateSessionAsync));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Convert.FromBase64String(ctx.SessionToken).DeserializeSessionToken();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Grpc.Core;
|
||||||
|
|
||||||
using FrostFS.Object;
|
using FrostFS.Object;
|
||||||
using FrostFS.Refs;
|
using FrostFS.Refs;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
@ -14,14 +15,13 @@ internal class SearchReader(AsyncServerStreamingCall<SearchResponse> call) : IDi
|
||||||
{
|
{
|
||||||
public AsyncServerStreamingCall<SearchResponse> Call { get; private set; } = call;
|
public AsyncServerStreamingCall<SearchResponse> Call { get; private set; } = call;
|
||||||
|
|
||||||
public async Task<List<ObjectID>?> Read()
|
public async Task<List<ObjectID>?> Read(CancellationToken cancellationToken)
|
||||||
{
|
|
||||||
if (!await Call.ResponseStream.MoveNext())
|
|
||||||
{
|
{
|
||||||
|
if (!await Call.ResponseStream.MoveNext(cancellationToken))
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
var response = Call.ResponseStream.Current;
|
var response = Call.ResponseStream.Current;
|
||||||
|
|
||||||
Verifier.CheckResponse(response);
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
return response.Body?.IdList.ToList();
|
return response.Body?.IdList.ToList();
|
||||||
|
|
|
@ -5,28 +5,38 @@ using FrostFS.Session;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
public partial class Client
|
internal class SessionServiceProvider : ContextAccessor
|
||||||
{
|
{
|
||||||
private async Task<SessionToken> CreateSessionAsync(ulong expiration)
|
private readonly SessionService.SessionServiceClient? _sessionServiceClient;
|
||||||
|
|
||||||
|
internal SessionServiceProvider(SessionService.SessionServiceClient? sessionServiceClient, ClientEnvironment context)
|
||||||
|
: base (context)
|
||||||
|
{
|
||||||
|
_sessionServiceClient = sessionServiceClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<SessionToken> CreateSessionAsync(ulong expiration, Context ctx)
|
||||||
{
|
{
|
||||||
var request = new CreateRequest
|
var request = new CreateRequest
|
||||||
{
|
{
|
||||||
Body = new CreateRequest.Types.Body
|
Body = new CreateRequest.Types.Body
|
||||||
{
|
{
|
||||||
OwnerId = OwnerId.ToGrpcMessage(),
|
OwnerId = Context.Owner.ToGrpcMessage(),
|
||||||
Expiration = expiration,
|
Expiration = expiration
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(Context.Key);
|
||||||
|
|
||||||
return await CreateSession(request);
|
var token = await CreateSession(request, ctx);
|
||||||
|
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<SessionToken> CreateSession(CreateRequest request)
|
internal async Task<SessionToken> CreateSession(CreateRequest request, Context ctx)
|
||||||
{
|
{
|
||||||
var resp = await _sessionServiceClient.CreateAsync(request);
|
var resp = await _sessionServiceClient!.CreateAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
return new SessionToken
|
return new SessionToken
|
||||||
{
|
{
|
116
src/FrostFS.SDK.ClientV2/Tools/ClientEnvironment.cs
Normal file
116
src/FrostFS.SDK.ClientV2/Tools/ClientEnvironment.cs
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Grpc.Core;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
public class ClientEnvironment(ECDsa key, OwnerId owner, GrpcChannel channel, ModelsV2.Version version) : IDisposable
|
||||||
|
{
|
||||||
|
internal OwnerId Owner { get; } = owner;
|
||||||
|
internal GrpcChannel Channel { get; private set; } = channel;
|
||||||
|
internal ECDsa Key { get; } = key;
|
||||||
|
internal ModelsV2.Version Version { get; } = version;
|
||||||
|
internal NetworkSettings? NetworkSettings { get; set; }
|
||||||
|
|
||||||
|
internal ContainerServiceProvider? ContainerService { get; set; }
|
||||||
|
internal NetmapServiceProvider? NetmapService { get; set; }
|
||||||
|
internal SessionServiceProvider? SessionService { get; set; }
|
||||||
|
internal ObjectServiceProvider? ObjectService { get; set; }
|
||||||
|
|
||||||
|
internal event EventHandler<GrpcCallInfo>? GrpcInvokedEvent;
|
||||||
|
|
||||||
|
internal bool IsEventRequested => GrpcInvokedEvent != null;
|
||||||
|
|
||||||
|
internal async Task<T> InvokeAsyncWithMetrics<T>(Func<Task<T>> func, string methodName)
|
||||||
|
{
|
||||||
|
if (!IsEventRequested)
|
||||||
|
return await func();
|
||||||
|
|
||||||
|
var watch = Stopwatch.StartNew();
|
||||||
|
bool exitWithException = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await func();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
exitWithException = true;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
watch.Stop();
|
||||||
|
GrpcInvokedEvent?.Invoke(this, new GrpcCallInfo(methodName, watch.ElapsedTicks * 1_000_000 / Stopwatch.Frequency, exitWithException));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal T InvokeWithMetrics<T>(Func<T> func, string methodName)
|
||||||
|
{
|
||||||
|
if (!IsEventRequested)
|
||||||
|
return func();
|
||||||
|
|
||||||
|
var watch = Stopwatch.StartNew();
|
||||||
|
bool exitWithException = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return func();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
exitWithException = true;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
watch.Stop();
|
||||||
|
GrpcInvokedEvent?.Invoke(this, new GrpcCallInfo(methodName, watch.ElapsedTicks * 1_000_000 / Stopwatch.Frequency, exitWithException));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<T> InvokeAsyncUnaryWithMetrics<T>(Func<AsyncUnaryCall<T>> func, string methodName)
|
||||||
|
{
|
||||||
|
if (!IsEventRequested)
|
||||||
|
return await func();
|
||||||
|
|
||||||
|
var watch = Stopwatch.StartNew();
|
||||||
|
bool exitWithException = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await func();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
exitWithException = true;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
watch.Stop();
|
||||||
|
GrpcInvokedEvent?.Invoke(this, new GrpcCallInfo(methodName, watch.ElapsedTicks * 1_000_000 / Stopwatch.Frequency, exitWithException));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool Initialized =>
|
||||||
|
ContainerService != null
|
||||||
|
&& NetmapService != null
|
||||||
|
&& SessionService != null
|
||||||
|
&& ObjectService != null;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Channel.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/FrostFS.SDK.ClientV2/Tools/ContextAccessor.cs
Normal file
8
src/FrostFS.SDK.ClientV2/Tools/ContextAccessor.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
internal class ContextAccessor(ClientEnvironment context)
|
||||||
|
{
|
||||||
|
protected ClientEnvironment Context { get; set; } = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
21
src/FrostFS.SDK.ClientV2/Tools/NetworkSettings.cs
Normal file
21
src/FrostFS.SDK.ClientV2/Tools/NetworkSettings.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
public class NetworkSettings
|
||||||
|
{
|
||||||
|
public ulong ContainerFee { get; internal set; }
|
||||||
|
public ulong ContainerAliasFee { get; internal set; }
|
||||||
|
public ulong InnerRingCandidateFee { get; internal set; }
|
||||||
|
public ulong WithdrawFee { get; internal set; }
|
||||||
|
public ulong EpochDuration { get; internal set; }
|
||||||
|
public ulong IRCandidateFee { get; internal set; }
|
||||||
|
public ulong MaxObjectSize { get; internal set; }
|
||||||
|
public ulong MaxECDataCount { get; internal set; }
|
||||||
|
public ulong MaxECParityCount { get; internal set; }
|
||||||
|
public ulong WithdrawalFee { get; internal set; }
|
||||||
|
public bool HomomorphicHashingDisabled { get; internal set; }
|
||||||
|
public bool MaintenanceModeAllowed { get; internal set; }
|
||||||
|
|
||||||
|
public Dictionary<string, object> UnnamedSettings { get; } = [];
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Extensions;
|
namespace FrostFS.SDK.ClientV2.Extensions;
|
||||||
|
|
||||||
public static class Extensions
|
public static class ObjectExtensions
|
||||||
{
|
{
|
||||||
public static ModelsV2.Object SetPayloadLength(this ModelsV2.Object obj, ulong length)
|
public static ModelsV2.Object SetPayloadLength(this ModelsV2.Object obj, ulong length)
|
||||||
{
|
{
|
||||||
|
@ -41,4 +42,15 @@ public static class Extensions
|
||||||
linkObject.Header.Split!.Children.AddRange(objectIds);
|
linkObject.Header.Split!.Children.AddRange(objectIds);
|
||||||
return linkObject;
|
return linkObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ModelsV2.Object CalculateObjectId(this ModelsV2.Object obj)
|
||||||
|
{
|
||||||
|
if (obj.Payload == null)
|
||||||
|
throw new MissingFieldException("Payload cannot be null");
|
||||||
|
|
||||||
|
if (obj.Header == null)
|
||||||
|
throw new MissingFieldException("Header cannot be null");
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -41,10 +41,10 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Create an Index pointing at first element.</summary>
|
/// <summary>Create an Index pointing at first element.</summary>
|
||||||
public static Index Start => new Index(0);
|
public static Index Start => new(0);
|
||||||
|
|
||||||
/// <summary>Create an Index pointing at beyond last element.</summary>
|
/// <summary>Create an Index pointing at beyond last element.</summary>
|
||||||
public static Index End => new Index(~0);
|
public static Index End => new(~0);
|
||||||
|
|
||||||
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
|
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
|
||||||
/// <param name="value">The index value from the start.</param>
|
/// <param name="value">The index value from the start.</param>
|
||||||
|
@ -116,7 +116,7 @@ namespace System
|
||||||
|
|
||||||
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
|
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
|
||||||
/// <param name="value">An object to compare with this object</param>
|
/// <param name="value">An object to compare with this object</param>
|
||||||
public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value;
|
public override bool Equals(object? value) => value is Index index && _value == index._value;
|
||||||
|
|
||||||
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
|
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
|
||||||
/// <param name="other">An object to compare with this object</param>
|
/// <param name="other">An object to compare with this object</param>
|
||||||
|
@ -147,22 +147,16 @@ namespace System
|
||||||
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
|
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal readonly struct Range : IEquatable<Range>
|
/// <remarks>Construct a Range object using the start and end indexes.</remarks>
|
||||||
{
|
|
||||||
/// <summary>Represent the inclusive start index of the Range.</summary>
|
|
||||||
public Index Start { get; }
|
|
||||||
|
|
||||||
/// <summary>Represent the exclusive end index of the Range.</summary>
|
|
||||||
public Index End { get; }
|
|
||||||
|
|
||||||
/// <summary>Construct a Range object using the start and end indexes.</summary>
|
|
||||||
/// <param name="start">Represent the inclusive start index of the range.</param>
|
/// <param name="start">Represent the inclusive start index of the range.</param>
|
||||||
/// <param name="end">Represent the exclusive end index of the range.</param>
|
/// <param name="end">Represent the exclusive end index of the range.</param>
|
||||||
public Range(Index start, Index end)
|
internal readonly struct Range(Index start, Index end) : IEquatable<Range>
|
||||||
{
|
{
|
||||||
Start = start;
|
/// <summary>Represent the inclusive start index of the Range.</summary>
|
||||||
End = end;
|
public Index Start { get; } = start;
|
||||||
}
|
|
||||||
|
/// <summary>Represent the exclusive end index of the Range.</summary>
|
||||||
|
public Index End { get; } = end;
|
||||||
|
|
||||||
/// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
|
/// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
|
||||||
/// <param name="value">An object to compare with this object</param>
|
/// <param name="value">An object to compare with this object</param>
|
||||||
|
@ -188,13 +182,13 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Create a Range object starting from start index to the end of the collection.</summary>
|
/// <summary>Create a Range object starting from start index to the end of the collection.</summary>
|
||||||
public static Range StartAt(Index start) => new Range(start, Index.End);
|
public static Range StartAt(Index start) => new(start, Index.End);
|
||||||
|
|
||||||
/// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
|
/// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
|
||||||
public static Range EndAt(Index end) => new Range(Index.Start, end);
|
public static Range EndAt(Index end) => new(Index.Start, end);
|
||||||
|
|
||||||
/// <summary>Create a Range object starting from first element to the end.</summary>
|
/// <summary>Create a Range object starting from first element to the end.</summary>
|
||||||
public static Range All => new Range(Index.Start, Index.End);
|
public static Range All => new(Index.Start, Index.End);
|
||||||
|
|
||||||
/// <summary>Calculate the start offset and length of range object using a collection length.</summary>
|
/// <summary>Calculate the start offset and length of range object using a collection length.</summary>
|
||||||
/// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
|
/// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
|
||||||
|
@ -252,7 +246,7 @@ namespace System.Runtime.CompilerServices
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
{
|
{
|
||||||
return Array.Empty<T>();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var dest = new T[length];
|
var dest = new T[length];
|
|
@ -10,20 +10,24 @@ public static class RequestConstructor
|
||||||
{
|
{
|
||||||
public static void AddMetaHeader(this IRequest request, RequestMetaHeader? metaHeader = null)
|
public static void AddMetaHeader(this IRequest request, RequestMetaHeader? metaHeader = null)
|
||||||
{
|
{
|
||||||
if (request.MetaHeader is not null) return;
|
if (request.MetaHeader is not null)
|
||||||
|
return;
|
||||||
|
|
||||||
metaHeader ??= MetaHeader.Default().ToGrpcMessage();
|
metaHeader ??= MetaHeader.Default().ToGrpcMessage();
|
||||||
request.MetaHeader = metaHeader;
|
request.MetaHeader = metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddObjectSessionToken(
|
public static void AddObjectSessionToken(
|
||||||
this IRequest request,
|
this IRequest request,
|
||||||
SessionToken sessionToken,
|
Session.SessionToken sessionToken,
|
||||||
ContainerID cid,
|
ContainerID cid,
|
||||||
ObjectID oid,
|
ObjectID oid,
|
||||||
ObjectSessionContext.Types.Verb verb,
|
ObjectSessionContext.Types.Verb verb,
|
||||||
ECDsa key)
|
ECDsa key)
|
||||||
{
|
{
|
||||||
if (request.MetaHeader.SessionToken is not null) return;
|
if (request.MetaHeader.SessionToken is not null)
|
||||||
|
return;
|
||||||
|
|
||||||
request.MetaHeader.SessionToken = sessionToken;
|
request.MetaHeader.SessionToken = sessionToken;
|
||||||
var ctx = new ObjectSessionContext
|
var ctx = new ObjectSessionContext
|
||||||
{
|
{
|
||||||
|
@ -34,6 +38,7 @@ public static class RequestConstructor
|
||||||
},
|
},
|
||||||
Verb = verb
|
Verb = verb
|
||||||
};
|
};
|
||||||
|
|
||||||
request.MetaHeader.SessionToken.Body.Object = ctx;
|
request.MetaHeader.SessionToken.Body.Object = ctx;
|
||||||
request.MetaHeader.SessionToken.Signature = key.SignMessagePart(request.MetaHeader.SessionToken.Body);
|
request.MetaHeader.SessionToken.Signature = key.SignMessagePart(request.MetaHeader.SessionToken.Body);
|
||||||
}
|
}
|
|
@ -84,7 +84,7 @@ public static class RequestSigner
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sign(this IVerificableMessage message, ECDsa key)
|
public static void Sign(this IVerifiableMessage message, ECDsa key)
|
||||||
{
|
{
|
||||||
var meta = message.GetMetaHeader();
|
var meta = message.GetMetaHeader();
|
||||||
IVerificationHeader verify = message switch
|
IVerificationHeader verify = message switch
|
||||||
|
@ -95,12 +95,15 @@ public static class RequestSigner
|
||||||
};
|
};
|
||||||
|
|
||||||
var verifyOrigin = message.GetVerificationHeader();
|
var verifyOrigin = message.GetVerificationHeader();
|
||||||
|
|
||||||
if (verifyOrigin is null)
|
if (verifyOrigin is null)
|
||||||
verify.BodySignature = key.SignMessagePart(message.GetBody());
|
verify.BodySignature = key.SignMessagePart(message.GetBody());
|
||||||
|
else
|
||||||
|
verify.SetOrigin(verifyOrigin);
|
||||||
|
|
||||||
verify.MetaSignature = key.SignMessagePart(meta);
|
verify.MetaSignature = key.SignMessagePart(meta);
|
||||||
verify.OriginSignature = key.SignMessagePart(verifyOrigin);
|
verify.OriginSignature = key.SignMessagePart(verifyOrigin);
|
||||||
verify.SetOrigin(verifyOrigin);
|
|
||||||
message.SetVerificationHeader(verify);
|
message.SetVerificationHeader(verify);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -68,7 +68,7 @@ public static class Verifier
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using var key = sig.Key.ToByteArray().LoadPublicKey();
|
using var key = sig.Key.ToByteArray().LoadPublicKey();
|
||||||
var data2Verify = data is null ? Array.Empty<byte>() : data.ToByteArray();
|
var data2Verify = data is null ? [] : data.ToByteArray();
|
||||||
|
|
||||||
return key.VerifyData(data2Verify, sig.Sign.ToByteArray());
|
return key.VerifyData(data2Verify, sig.Sign.ToByteArray());
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public static class Verifier
|
||||||
return verification.BodySignature is null && VerifyMatryoskaLevel(body, meta.GetOrigin(), origin);
|
return verification.BodySignature is null && VerifyMatryoskaLevel(body, meta.GetOrigin(), origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Verify(this IVerificableMessage message)
|
public static bool Verify(this IVerifiableMessage message)
|
||||||
{
|
{
|
||||||
return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader());
|
return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader());
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,17 @@ public static class Verifier
|
||||||
throw new FormatException($"invalid response, type={resp.GetType()}");
|
throw new FormatException($"invalid response, type={resp.GetType()}");
|
||||||
|
|
||||||
var status = resp.MetaHeader.Status.ToModel();
|
var status = resp.MetaHeader.Status.ToModel();
|
||||||
if (!status.IsSuccess())
|
if (!status.IsSuccess)
|
||||||
throw new ApplicationException(status.ToString());
|
throw new ApplicationException(status.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is intended for unit tests for request verification.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Created by SDK request to gRpc proxy</param>
|
||||||
|
public static void CheckRequest(IRequest request)
|
||||||
|
{
|
||||||
|
if (!request.Verify())
|
||||||
|
throw new FormatException($"invalid response, type={request.GetType()}");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -17,4 +17,4 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: Guid("08a8487e-39ce-41fb-9c24-13f73ff2bde0")]
|
[assembly: Guid("08a8487e-39ce-41fb-9c24-13f73ff2bde0")]
|
||||||
|
|
||||||
[assembly: InternalsVisibleToAttribute("FrostFS.SDK.Cryptography.Test")]
|
[assembly: InternalsVisibleTo("FrostFS.SDK.Cryptography.Test")]
|
|
@ -34,9 +34,11 @@ public static class Base58
|
||||||
byte[] checksum = data.ToArray().Sha256().Sha256();
|
byte[] checksum = data.ToArray().Sha256().Sha256();
|
||||||
Span<byte> buffer = stackalloc byte[data.Length + 4];
|
Span<byte> buffer = stackalloc byte[data.Length + 4];
|
||||||
data.CopyTo(buffer);
|
data.CopyTo(buffer);
|
||||||
|
|
||||||
checksum[..4].AsSpan().CopyTo(buffer[data.Length..]);
|
checksum[..4].AsSpan().CopyTo(buffer[data.Length..]);
|
||||||
var ret = Encode(buffer);
|
var ret = Encode(buffer);
|
||||||
buffer.Clear();
|
buffer.Clear();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography;
|
namespace FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
public static class Helper
|
public static class Extentions
|
||||||
{
|
{
|
||||||
internal static byte[] RIPEMD160(this byte[] value)
|
internal static byte[] RIPEMD160(this byte[] value)
|
||||||
{
|
{
|
|
@ -6,6 +6,10 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />
|
<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.27.0" />
|
<PackageReference Include="Google.Protobuf" Version="3.27.0" />
|
||||||
|
|
|
@ -56,7 +56,7 @@ public static class KeyExtension
|
||||||
|
|
||||||
var script = new byte[] { 0x0c, CompressedPublicKeyLength }; //PUSHDATA1 33
|
var script = new byte[] { 0x0c, CompressedPublicKeyLength }; //PUSHDATA1 33
|
||||||
script = ArrayHelper.Concat(script, publicKey);
|
script = ArrayHelper.Concat(script, publicKey);
|
||||||
script = ArrayHelper.Concat(script, new byte[] { 0x41 }); //SYSCALL
|
script = ArrayHelper.Concat(script, [0x41]); //SYSCALL
|
||||||
script = ArrayHelper.Concat(script, BitConverter.GetBytes(CheckSigDescriptor)); //Neo_Crypto_CheckSig
|
script = ArrayHelper.Concat(script, BitConverter.GetBytes(CheckSigDescriptor)); //Neo_Crypto_CheckSig
|
||||||
|
|
||||||
return script;
|
return script;
|
||||||
|
@ -80,7 +80,7 @@ public static class KeyExtension
|
||||||
private static byte[] GetPrivateKeyFromWIF(string wif)
|
private static byte[] GetPrivateKeyFromWIF(string wif)
|
||||||
{
|
{
|
||||||
if (wif == null)
|
if (wif == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException(nameof(wif));
|
||||||
|
|
||||||
var data = wif.Base58CheckDecode();
|
var data = wif.Base58CheckDecode();
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ public static class KeyExtension
|
||||||
var pos = 33 - param.Q.X.Length;
|
var pos = 33 - param.Q.X.Length;
|
||||||
|
|
||||||
param.Q.X.CopyTo(pubkey, pos);
|
param.Q.X.CopyTo(pubkey, pos);
|
||||||
if (new BigInteger(param.Q.Y.Reverse().Concat(new byte[] { 0x00 }).ToArray()).IsEven)
|
if (new BigInteger(param.Q.Y.Reverse().Concat(new byte[] { 0x0 }).ToArray()).IsEven)
|
||||||
pubkey[0] = 0x2;
|
pubkey[0] = 0x2;
|
||||||
else
|
else
|
||||||
pubkey[0] = 0x3;
|
pubkey[0] = 0x3;
|
||||||
|
|
|
@ -41,10 +41,10 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Create an Index pointing at first element.</summary>
|
/// <summary>Create an Index pointing at first element.</summary>
|
||||||
public static Index Start => new Index(0);
|
public static Index Start => new(0);
|
||||||
|
|
||||||
/// <summary>Create an Index pointing at beyond last element.</summary>
|
/// <summary>Create an Index pointing at beyond last element.</summary>
|
||||||
public static Index End => new Index(~0);
|
public static Index End => new(~0);
|
||||||
|
|
||||||
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
|
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
|
||||||
/// <param name="value">The index value from the start.</param>
|
/// <param name="value">The index value from the start.</param>
|
||||||
|
@ -116,7 +116,7 @@ namespace System
|
||||||
|
|
||||||
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
|
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
|
||||||
/// <param name="value">An object to compare with this object</param>
|
/// <param name="value">An object to compare with this object</param>
|
||||||
public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value;
|
public override bool Equals(object? value) => value is Index index && _value == index._value;
|
||||||
|
|
||||||
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
|
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
|
||||||
/// <param name="other">An object to compare with this object</param>
|
/// <param name="other">An object to compare with this object</param>
|
||||||
|
@ -147,22 +147,16 @@ namespace System
|
||||||
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
|
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal readonly struct Range : IEquatable<Range>
|
/// <remarks>Construct a Range object using the start and end indexes.</remarks>
|
||||||
{
|
|
||||||
/// <summary>Represent the inclusive start index of the Range.</summary>
|
|
||||||
public Index Start { get; }
|
|
||||||
|
|
||||||
/// <summary>Represent the exclusive end index of the Range.</summary>
|
|
||||||
public Index End { get; }
|
|
||||||
|
|
||||||
/// <summary>Construct a Range object using the start and end indexes.</summary>
|
|
||||||
/// <param name="start">Represent the inclusive start index of the range.</param>
|
/// <param name="start">Represent the inclusive start index of the range.</param>
|
||||||
/// <param name="end">Represent the exclusive end index of the range.</param>
|
/// <param name="end">Represent the exclusive end index of the range.</param>
|
||||||
public Range(Index start, Index end)
|
internal readonly struct Range (Index start, Index end) : IEquatable<Range>
|
||||||
{
|
{
|
||||||
Start = start;
|
/// <summary>Represent the inclusive start index of the Range.</summary>
|
||||||
End = end;
|
public Index Start { get; } = start;
|
||||||
}
|
|
||||||
|
/// <summary>Represent the exclusive end index of the Range.</summary>
|
||||||
|
public Index End { get; } = end;
|
||||||
|
|
||||||
/// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
|
/// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
|
||||||
/// <param name="value">An object to compare with this object</param>
|
/// <param name="value">An object to compare with this object</param>
|
||||||
|
@ -188,13 +182,13 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Create a Range object starting from start index to the end of the collection.</summary>
|
/// <summary>Create a Range object starting from start index to the end of the collection.</summary>
|
||||||
public static Range StartAt(Index start) => new Range(start, Index.End);
|
public static Range StartAt(Index start) => new(start, Index.End);
|
||||||
|
|
||||||
/// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
|
/// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
|
||||||
public static Range EndAt(Index end) => new Range(Index.Start, end);
|
public static Range EndAt(Index end) => new(Index.Start, end);
|
||||||
|
|
||||||
/// <summary>Create a Range object starting from first element to the end.</summary>
|
/// <summary>Create a Range object starting from first element to the end.</summary>
|
||||||
public static Range All => new Range(Index.Start, Index.End);
|
public static Range All => new(Index.Start, Index.End);
|
||||||
|
|
||||||
/// <summary>Calculate the start offset and length of range object using a collection length.</summary>
|
/// <summary>Calculate the start offset and length of range object using a collection length.</summary>
|
||||||
/// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
|
/// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
|
||||||
|
@ -252,7 +246,7 @@ namespace System.Runtime.CompilerServices
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
{
|
{
|
||||||
return Array.Empty<T>();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var dest = new T[length];
|
var dest = new T[length];
|
||||||
|
|
28
src/FrostFS.SDK.ModelsV2/ClientSettings.cs
Normal file
28
src/FrostFS.SDK.ModelsV2/ClientSettings.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
public class ClientSettings
|
||||||
|
{
|
||||||
|
private static readonly string errorTemplate = "{0} is required parameter";
|
||||||
|
|
||||||
|
public string Key { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string Host { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public void Validate()
|
||||||
|
{
|
||||||
|
StringBuilder? error = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Key))
|
||||||
|
(error ??= new StringBuilder()).AppendLine(string.Format(errorTemplate, nameof(Key)));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Host))
|
||||||
|
(error ??= new StringBuilder()).AppendLine(string.Format(errorTemplate, nameof(Host)));
|
||||||
|
|
||||||
|
if (error != null)
|
||||||
|
throw new ArgumentException(error.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,17 +5,10 @@ using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
public class Container
|
public class Container(BasicAcl basicAcl, PlacementPolicy placementPolicy)
|
||||||
{
|
{
|
||||||
public Guid Nonce { get; set; }
|
public Guid Nonce { get; set; } = Guid.NewGuid();
|
||||||
public BasicAcl BasicAcl { get; set; }
|
public BasicAcl BasicAcl { get; set; } = basicAcl;
|
||||||
public PlacementPolicy PlacementPolicy { get; set; }
|
public PlacementPolicy PlacementPolicy { get; set; } = placementPolicy;
|
||||||
public Version Version { get; set; }
|
public Version? Version { get; set; }
|
||||||
|
|
||||||
public Container(BasicAcl basicAcl, PlacementPolicy placementPolicy)
|
|
||||||
{
|
|
||||||
Nonce = Guid.NewGuid();
|
|
||||||
BasicAcl = basicAcl;
|
|
||||||
PlacementPolicy = placementPolicy;
|
|
||||||
}
|
|
||||||
}
|
}
|
13
src/FrostFS.SDK.ModelsV2/Context.cs
Normal file
13
src/FrostFS.SDK.ModelsV2/Context.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
public class Context()
|
||||||
|
{
|
||||||
|
public CancellationToken CancellationToken { get; set; } = default;
|
||||||
|
public TimeSpan Timeout { get; set; } = default;
|
||||||
|
public string SessionToken { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public DateTime? Deadline => Timeout.Ticks > 0 ? DateTime.UtcNow.Add(Timeout) : null;
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ namespace FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
|
||||||
public enum BasicAcl
|
public enum BasicAcl
|
||||||
{
|
{
|
||||||
|
[Description("Not defined ACL")]
|
||||||
|
NotDefined = 0x00000000,
|
||||||
|
|
||||||
[Description("Basic ACL for private container")]
|
[Description("Basic ACL for private container")]
|
||||||
Private = 0x1C8C8CCC,
|
Private = 0x1C8C8CCC,
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" />
|
<ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
8
src/FrostFS.SDK.ModelsV2/GrpcCallInfo.cs
Normal file
8
src/FrostFS.SDK.ModelsV2/GrpcCallInfo.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
public class GrpcCallInfo(string methodName, long elapsedMicroSec, bool hasError)
|
||||||
|
{
|
||||||
|
public string MethodName { get; set; } = methodName;
|
||||||
|
public long ElapsedTimeMicroSec { get; set; } = elapsedMicroSec;
|
||||||
|
public bool HasError { get; } = hasError;
|
||||||
|
}
|
|
@ -1,17 +1,10 @@
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
public class MetaHeader
|
public class MetaHeader(Version version, int epoch, int ttl)
|
||||||
{
|
{
|
||||||
public Version Version { get; set; }
|
public Version Version { get; set; } = version;
|
||||||
public int Epoch { get; set; }
|
public int Epoch { get; set; } = epoch;
|
||||||
public int Ttl { get; set; }
|
public int Ttl { get; set; } = ttl;
|
||||||
|
|
||||||
public MetaHeader(Version version, int epoch, int ttl)
|
|
||||||
{
|
|
||||||
Version = version;
|
|
||||||
Epoch = epoch;
|
|
||||||
Ttl = ttl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MetaHeader Default()
|
public static MetaHeader Default()
|
||||||
{
|
{
|
||||||
|
|
10
src/FrostFS.SDK.ModelsV2/Netmap/NetmapInfo.cs
Normal file
10
src/FrostFS.SDK.ModelsV2/Netmap/NetmapInfo.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
|
public class NetmapSnapshot(ulong epoch, IReadOnlyList<NodeInfo> nodeInfoCollection)
|
||||||
|
{
|
||||||
|
public ulong Epoch { get; private set; } = epoch;
|
||||||
|
|
||||||
|
public IReadOnlyList<NodeInfo> NodeInfoCollection { get; private set; } = nodeInfoCollection;
|
||||||
|
}
|
|
@ -1,9 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2.Netmap;
|
namespace FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
public class NodeInfo
|
public class NodeInfo
|
||||||
{
|
{
|
||||||
public NodeState State { get; set; }
|
public NodeInfo(
|
||||||
public Version? Version { get; set; }
|
Version version,
|
||||||
|
NodeState state,
|
||||||
|
IReadOnlyCollection<string> addresses,
|
||||||
|
IReadOnlyDictionary<string, string> attributes,
|
||||||
|
ReadOnlyMemory<byte> publicKey)
|
||||||
|
{
|
||||||
|
Version = version;
|
||||||
|
State = state;
|
||||||
|
Addresses = addresses;
|
||||||
|
Attributes = attributes;
|
||||||
|
PublicKey = publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeState State { get; private set; }
|
||||||
|
public Version Version { get; private set; }
|
||||||
|
public IReadOnlyCollection<string> Addresses { get; private set; }
|
||||||
|
public IReadOnlyDictionary<string, string> Attributes { get; private set; }
|
||||||
|
public ReadOnlyMemory<byte> PublicKey { get; private set; }
|
||||||
}
|
}
|
|
@ -1,13 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2.Netmap;
|
namespace FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
public class PlacementPolicy
|
public class PlacementPolicy(bool unique, params Replica[] replicas) : IComparable<PlacementPolicy>
|
||||||
{
|
{
|
||||||
public Replica[] Replicas { get; private set; }
|
public Replica[] Replicas { get; private set; } = replicas;
|
||||||
public bool Unique { get; private set; }
|
public bool Unique { get; private set; } = unique;
|
||||||
|
|
||||||
public PlacementPolicy(bool unique, params Replica[] replicas)
|
public int CompareTo(PlacementPolicy other)
|
||||||
{
|
{
|
||||||
Replicas = replicas;
|
var notEqual = other == null
|
||||||
Unique = unique;
|
|| Unique != other.Unique
|
||||||
|
|| Replicas.Length != other.Replicas.Length;
|
||||||
|
|
||||||
|
if (notEqual)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
foreach (var replica in Replicas)
|
||||||
|
{
|
||||||
|
if (!other!.Replicas.Any(r => r.Count == replica.Count && r.Selector == replica.Selector))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
|
||||||
|
@ -5,8 +6,11 @@ namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
public class Object
|
public class Object
|
||||||
{
|
{
|
||||||
public Object()
|
public Object(ObjectId objectId, ObjectHeader header, byte[] payload)
|
||||||
{
|
{
|
||||||
|
ObjectId = objectId;
|
||||||
|
Payload = payload;
|
||||||
|
Header = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object(ContainerId container, byte[] payload, ObjectType objectType = ObjectType.Regular)
|
public Object(ContainerId container, byte[] payload, ObjectType objectType = ObjectType.Regular)
|
||||||
|
@ -16,41 +20,45 @@ public class Object
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectHeader Header { get; set; }
|
public ObjectHeader Header { get; set; }
|
||||||
public ObjectId ObjectId { get; set; }
|
|
||||||
|
public ObjectId? ObjectId
|
||||||
|
{
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] Payload { get; set; }
|
public byte[] Payload { get; set; }
|
||||||
public Signature Signature { get; set; }
|
|
||||||
|
public Signature? Signature { get; set; }
|
||||||
|
|
||||||
public void SetParent(LargeObject largeObject)
|
public void SetParent(LargeObject largeObject)
|
||||||
{
|
{
|
||||||
Header.Split.ParentHeader = largeObject.Header;
|
if (Header?.Split == null)
|
||||||
}
|
throw new Exception("The object is not initialized properly");
|
||||||
|
|
||||||
public ObjectId? GetParentId()
|
Header.Split.ParentHeader = largeObject.Header;
|
||||||
{
|
|
||||||
return Header.Split?.Parent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LargeObject(ContainerId container) : Object(container, [])
|
public class LargeObject(ContainerId container) : Object(container, [])
|
||||||
{
|
{
|
||||||
private SHA256 payloadHash = SHA256.Create();
|
private readonly SHA256 payloadHash = SHA256.Create();
|
||||||
|
|
||||||
public void AppendBlock(byte[] bytes, int count)
|
public void AppendBlock(byte[] bytes, int count)
|
||||||
{
|
{
|
||||||
Header.PayloadLength += (ulong)count;
|
Header!.PayloadLength += (ulong)count;
|
||||||
this.payloadHash.TransformBlock(bytes, 0, count, bytes, 0);
|
this.payloadHash.TransformBlock(bytes, 0, count, bytes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LargeObject CalculateHash()
|
public LargeObject CalculateHash()
|
||||||
{
|
{
|
||||||
this.payloadHash.TransformFinalBlock([], 0, 0);
|
this.payloadHash.TransformFinalBlock([], 0, 0);
|
||||||
Header.PayloadCheckSum = this.payloadHash.Hash;
|
Header!.PayloadCheckSum = this.payloadHash.Hash;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong PayloadLength
|
public ulong PayloadLength
|
||||||
{
|
{
|
||||||
get { return Header.PayloadLength; }
|
get { return Header!.PayloadLength; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +66,7 @@ public class LinkObject : Object
|
||||||
{
|
{
|
||||||
public LinkObject(ContainerId containerId, SplitId splitId, LargeObject largeObject) : base (containerId, [])
|
public LinkObject(ContainerId containerId, SplitId splitId, LargeObject largeObject) : base (containerId, [])
|
||||||
{
|
{
|
||||||
Header.Split = new Split(splitId)
|
Header!.Split = new Split(splitId)
|
||||||
{
|
{
|
||||||
ParentHeader = largeObject.Header
|
ParentHeader = largeObject.Header
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,8 +22,6 @@ public class ObjectHeader
|
||||||
|
|
||||||
public Split? Split { get; set; }
|
public Split? Split { get; set; }
|
||||||
|
|
||||||
public bool ClientCut { get; set; }
|
|
||||||
|
|
||||||
public ObjectHeader(
|
public ObjectHeader(
|
||||||
ContainerId containerId,
|
ContainerId containerId,
|
||||||
ObjectType type = ObjectType.Regular,
|
ObjectType type = ObjectType.Regular,
|
||||||
|
|
|
@ -4,14 +4,9 @@ using FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
public class OwnerId
|
public class OwnerId(string id)
|
||||||
{
|
{
|
||||||
public string Value { get; }
|
public string Value { get; } = id;
|
||||||
|
|
||||||
public OwnerId(string id)
|
|
||||||
{
|
|
||||||
Value = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OwnerId FromKey(ECDsa key)
|
public static OwnerId FromKey(ECDsa key)
|
||||||
{
|
{
|
||||||
|
|
12
src/FrostFS.SDK.ModelsV2/PutObjectParameters.cs
Normal file
12
src/FrostFS.SDK.ModelsV2/PutObjectParameters.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
public class PutObjectParameters
|
||||||
|
{
|
||||||
|
public ObjectHeader? Header { get; set; }
|
||||||
|
|
||||||
|
public Stream? Payload { get; set; }
|
||||||
|
|
||||||
|
public bool ClientCut { get; set; }
|
||||||
|
}
|
8
src/FrostFS.SDK.ModelsV2/SessionToken.cs
Normal file
8
src/FrostFS.SDK.ModelsV2/SessionToken.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
public class SessionToken(byte[] sessionKey, byte[] id)
|
||||||
|
{
|
||||||
|
public byte[] Id { get; } = id;
|
||||||
|
|
||||||
|
public byte[] SessionKey { get; } = sessionKey;
|
||||||
|
}
|
8
src/FrostFS.SDK.ModelsV2/Signature.cs
Normal file
8
src/FrostFS.SDK.ModelsV2/Signature.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
public class Signature
|
||||||
|
{
|
||||||
|
public byte[]? Key { get; set; }
|
||||||
|
public byte[]? Sign { get; set; }
|
||||||
|
public SignatureScheme Scheme { get; set; }
|
||||||
|
}
|
7
src/FrostFS.SDK.ModelsV2/SignatureScheme.cs
Normal file
7
src/FrostFS.SDK.ModelsV2/SignatureScheme.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
public enum SignatureScheme {
|
||||||
|
EcdsaSha512,
|
||||||
|
EcdsaRfc6979Sha256,
|
||||||
|
EcdsaRfc6979Sha256WalletConnect
|
||||||
|
}
|
50
src/FrostFS.SDK.ModelsV2/SplitId.cs
Normal file
50
src/FrostFS.SDK.ModelsV2/SplitId.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
public class SplitId
|
||||||
|
{
|
||||||
|
private Guid id;
|
||||||
|
|
||||||
|
public SplitId()
|
||||||
|
{
|
||||||
|
this.id = Guid.NewGuid();
|
||||||
|
}
|
||||||
|
public SplitId(Guid guid)
|
||||||
|
{
|
||||||
|
this.id = guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SplitId(byte[] binary)
|
||||||
|
{
|
||||||
|
this.id = new Guid(binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SplitId(string str)
|
||||||
|
{
|
||||||
|
this.id = new Guid(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SplitId CrateFromBinary(byte[] binaryData)
|
||||||
|
{
|
||||||
|
return new SplitId(binaryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SplitId CrateFromString(string stringData)
|
||||||
|
{
|
||||||
|
return new SplitId(stringData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return this.id.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[]? ToBinary()
|
||||||
|
{
|
||||||
|
if (this.id == Guid.Empty)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this.id.ToByteArray();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,14 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
public class Split
|
public class Split(SplitId splitId)
|
||||||
{
|
{
|
||||||
public Split() : this(new SplitId())
|
public Split() : this(new SplitId())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Split(SplitId splitId)
|
public SplitId SplitId { get; private set; } = splitId;
|
||||||
{
|
|
||||||
SplitId = splitId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SplitId SplitId { get; private set; }
|
|
||||||
|
|
||||||
public ObjectId? Parent { get; set; }
|
public ObjectId? Parent { get; set; }
|
||||||
|
|
||||||
|
@ -26,63 +20,3 @@ public class Split
|
||||||
|
|
||||||
public List<ObjectId> Children { get; } = [];
|
public List<ObjectId> Children { get; } = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SignatureScheme {
|
|
||||||
EcdsaSha512,
|
|
||||||
EcdsaRfc6979Sha256,
|
|
||||||
EcdsaRfc6979Sha256WalletConnect
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Signature
|
|
||||||
{
|
|
||||||
public byte[] Key { get; set; }
|
|
||||||
public byte[] Sign { get; set; }
|
|
||||||
public SignatureScheme Scheme { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SplitId
|
|
||||||
{
|
|
||||||
private Guid id;
|
|
||||||
|
|
||||||
public SplitId()
|
|
||||||
{
|
|
||||||
this.id = Guid.NewGuid();
|
|
||||||
}
|
|
||||||
public SplitId(Guid guid)
|
|
||||||
{
|
|
||||||
this.id = guid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SplitId(byte[] binary)
|
|
||||||
{
|
|
||||||
this.id = new Guid(binary);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SplitId(string str)
|
|
||||||
{
|
|
||||||
this.id = new Guid(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SplitId CrateFromBinary(byte[] binaryData)
|
|
||||||
{
|
|
||||||
return new SplitId(binaryData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SplitId CrateFromString(string stringData)
|
|
||||||
{
|
|
||||||
return new SplitId(stringData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return this.id.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[]? ToBinary()
|
|
||||||
{
|
|
||||||
if (this.id == Guid.Empty)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return this.id.ToByteArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,21 +2,12 @@ using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
public class Status
|
public class Status(StatusCode code, string? message = null)
|
||||||
{
|
{
|
||||||
public StatusCode Code { get; set; }
|
public StatusCode Code { get; set; } = code;
|
||||||
public string Message { get; set; }
|
public string Message { get; set; } = message ?? string.Empty;
|
||||||
|
|
||||||
public Status(StatusCode code, string? message = null)
|
public bool IsSuccess => Code == StatusCode.Success;
|
||||||
{
|
|
||||||
Code = code;
|
|
||||||
Message = message ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSuccess()
|
|
||||||
{
|
|
||||||
return Code == StatusCode.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.26.1" />
|
<PackageReference Include="Google.Protobuf" Version="3.26.1" />
|
||||||
<PackageReference Include="Grpc.Net.Client" Version="2.62.0" />
|
<PackageReference Include="Grpc.Net.Client" Version="2.62.0" />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace FrostFS.Session;
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
public interface IRequest : IVerificableMessage
|
public interface IRequest : IVerifiableMessage
|
||||||
{
|
{
|
||||||
RequestMetaHeader MetaHeader { get; set; }
|
RequestMetaHeader MetaHeader { get; set; }
|
||||||
RequestVerificationHeader VerifyHeader { get; set; }
|
RequestVerificationHeader VerifyHeader { get; set; }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace FrostFS.Session;
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
public interface IResponse : IVerificableMessage
|
public interface IResponse : IVerifiableMessage
|
||||||
{
|
{
|
||||||
ResponseMetaHeader MetaHeader { get; set; }
|
ResponseMetaHeader MetaHeader { get; set; }
|
||||||
ResponseVerificationHeader VerifyHeader { get; set; }
|
ResponseVerificationHeader VerifyHeader { get; set; }
|
||||||
|
|
|
@ -2,7 +2,7 @@ using Google.Protobuf;
|
||||||
|
|
||||||
namespace FrostFS.Session;
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
public interface IVerificableMessage : IMessage
|
public interface IVerifiableMessage : IMessage
|
||||||
{
|
{
|
||||||
IMetaHeader GetMetaHeader();
|
IMetaHeader GetMetaHeader();
|
||||||
void SetMetaHeader(IMetaHeader metaHeader);
|
void SetMetaHeader(IMetaHeader metaHeader);
|
||||||
|
|
|
@ -6,22 +6,22 @@ namespace FrostFS.Container;
|
||||||
|
|
||||||
public partial class AnnounceUsedSpaceRequest : IRequest
|
public partial class AnnounceUsedSpaceRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -34,22 +34,22 @@ public partial class AnnounceUsedSpaceRequest : IRequest
|
||||||
|
|
||||||
public partial class AnnounceUsedSpaceResponse : IResponse
|
public partial class AnnounceUsedSpaceResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -62,22 +62,22 @@ public partial class AnnounceUsedSpaceResponse : IResponse
|
||||||
|
|
||||||
public partial class GetRequest : IRequest
|
public partial class GetRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -90,22 +90,22 @@ public partial class GetRequest : IRequest
|
||||||
|
|
||||||
public partial class GetResponse : IResponse
|
public partial class GetResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -118,22 +118,22 @@ public partial class GetResponse : IResponse
|
||||||
|
|
||||||
public partial class PutRequest : IRequest
|
public partial class PutRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -146,22 +146,22 @@ public partial class PutRequest : IRequest
|
||||||
|
|
||||||
public partial class PutResponse : IResponse
|
public partial class PutResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -174,22 +174,22 @@ public partial class PutResponse : IResponse
|
||||||
|
|
||||||
public partial class DeleteRequest : IRequest
|
public partial class DeleteRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -202,22 +202,22 @@ public partial class DeleteRequest : IRequest
|
||||||
|
|
||||||
public partial class DeleteResponse : IResponse
|
public partial class DeleteResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -230,22 +230,22 @@ public partial class DeleteResponse : IResponse
|
||||||
|
|
||||||
public partial class ListRequest : IRequest
|
public partial class ListRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -258,22 +258,22 @@ public partial class ListRequest : IRequest
|
||||||
|
|
||||||
public partial class ListResponse : IResponse
|
public partial class ListResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -286,22 +286,22 @@ public partial class ListResponse : IResponse
|
||||||
|
|
||||||
public partial class SetExtendedACLRequest : IRequest
|
public partial class SetExtendedACLRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -314,22 +314,22 @@ public partial class SetExtendedACLRequest : IRequest
|
||||||
|
|
||||||
public partial class SetExtendedACLResponse : IResponse
|
public partial class SetExtendedACLResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -342,22 +342,22 @@ public partial class SetExtendedACLResponse : IResponse
|
||||||
|
|
||||||
public partial class GetExtendedACLRequest : IRequest
|
public partial class GetExtendedACLRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -370,22 +370,22 @@ public partial class GetExtendedACLRequest : IRequest
|
||||||
|
|
||||||
public partial class GetExtendedACLResponse : IResponse
|
public partial class GetExtendedACLResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,22 +5,22 @@ namespace FrostFS.Netmap;
|
||||||
|
|
||||||
public partial class LocalNodeInfoRequest : IRequest
|
public partial class LocalNodeInfoRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -33,22 +33,22 @@ public partial class LocalNodeInfoRequest : IRequest
|
||||||
|
|
||||||
public partial class LocalNodeInfoResponse : IResponse
|
public partial class LocalNodeInfoResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -61,22 +61,22 @@ public partial class LocalNodeInfoResponse : IResponse
|
||||||
|
|
||||||
public partial class NetworkInfoRequest : IRequest
|
public partial class NetworkInfoRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -89,22 +89,79 @@ public partial class NetworkInfoRequest : IRequest
|
||||||
|
|
||||||
public partial class NetworkInfoResponse : IResponse
|
public partial class NetworkInfoResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public partial class NetmapSnapshotRequest : IRequest
|
||||||
|
{
|
||||||
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class NetmapSnapshotResponse : IResponse
|
||||||
|
{
|
||||||
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,22 +6,22 @@ namespace FrostFS.Object
|
||||||
{
|
{
|
||||||
public partial class GetRequest : IRequest
|
public partial class GetRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -34,22 +34,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class GetResponse : IResponse
|
public partial class GetResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -62,22 +62,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class PutRequest : IRequest
|
public partial class PutRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -90,22 +90,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class PutResponse : IResponse
|
public partial class PutResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -118,22 +118,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class PutSingleRequest : IRequest
|
public partial class PutSingleRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -146,22 +146,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class PutSingleResponse : IResponse
|
public partial class PutSingleResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -174,22 +174,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class DeleteRequest : IRequest
|
public partial class DeleteRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -203,25 +203,25 @@ namespace FrostFS.Object
|
||||||
public partial class DeleteResponse : IResponse
|
public partial class DeleteResponse : IResponse
|
||||||
{
|
{
|
||||||
[DebuggerStepThrough]
|
[DebuggerStepThrough]
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerStepThrough]
|
[DebuggerStepThrough]
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerStepThrough]
|
[DebuggerStepThrough]
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerStepThrough]
|
[DebuggerStepThrough]
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -235,22 +235,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class HeadRequest : IRequest
|
public partial class HeadRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -263,22 +263,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class HeadResponse : IResponse
|
public partial class HeadResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -290,22 +290,22 @@ namespace FrostFS.Object
|
||||||
}
|
}
|
||||||
public partial class SearchRequest : IRequest
|
public partial class SearchRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -318,22 +318,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class SearchResponse : IResponse
|
public partial class SearchResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -346,22 +346,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class GetRangeRequest : IRequest
|
public partial class GetRangeRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -374,22 +374,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class GetRangeResponse : IResponse
|
public partial class GetRangeResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -402,22 +402,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class GetRangeHashRequest : IRequest
|
public partial class GetRangeHashRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -430,22 +430,22 @@ namespace FrostFS.Object
|
||||||
|
|
||||||
public partial class GetRangeHashResponse : IResponse
|
public partial class GetRangeHashResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,22 @@ namespace FrostFS.Session;
|
||||||
|
|
||||||
public partial class CreateResponse : IResponse
|
public partial class CreateResponse : IResponse
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
@ -32,22 +32,22 @@ public partial class CreateResponse : IResponse
|
||||||
|
|
||||||
public partial class CreateRequest : IRequest
|
public partial class CreateRequest : IRequest
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
IMetaHeader IVerifiableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
return MetaHeader;
|
return MetaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
IVerificationHeader IVerifiableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return VerifyHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerifiableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
void IVerifiableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
85
src/FrostFS.SDK.Tests/ClientTest.cs
Normal file
85
src/FrostFS.SDK.Tests/ClientTest.cs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
using FrostFS.SDK.ClientV2;
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class ClientTest
|
||||||
|
{
|
||||||
|
private readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void CreateContainerTest()
|
||||||
|
{
|
||||||
|
var factory = new PutContainerMock(this.key)
|
||||||
|
{
|
||||||
|
PlacementPolicy = new PlacementPolicy(true, new Replica(1)),
|
||||||
|
Version = new ModelsV2.Version(2, 13),
|
||||||
|
ContainerGuid = Guid.NewGuid()
|
||||||
|
};
|
||||||
|
|
||||||
|
var settings = Options.Create(new ClientSettings
|
||||||
|
{
|
||||||
|
Key = key,
|
||||||
|
Host = "http://localhost:8080"
|
||||||
|
});
|
||||||
|
|
||||||
|
var fsClient = Client.GetTestInstance(
|
||||||
|
settings,
|
||||||
|
new NetmapMock(this.key).GetMock().Object,
|
||||||
|
new SessionMock(this.key).GetMock().Object,
|
||||||
|
factory.GetMock().Object,
|
||||||
|
new ObjectMock(this.key).GetMock().Object);
|
||||||
|
|
||||||
|
var result = await fsClient.CreateContainerAsync(new ModelsV2.Container(BasicAcl.PublicRW, factory.PlacementPolicy));
|
||||||
|
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.NotNull(result.Value);
|
||||||
|
Assert.True(Base58.Encode(factory.ContainerGuid.ToBytes()) == result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void GetContainerTest()
|
||||||
|
{
|
||||||
|
var factory = new GetContainerMock(this.key)
|
||||||
|
{
|
||||||
|
PlacementPolicy = new PlacementPolicy(true, new Replica(1)),
|
||||||
|
Version = new ModelsV2.Version(2, 13),
|
||||||
|
Acl = BasicAcl.PublicRO,
|
||||||
|
ContainerGuid = Guid.NewGuid(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var settings = Options.Create(new ClientSettings
|
||||||
|
{
|
||||||
|
Key = key,
|
||||||
|
Host = "http://localhost:8080"
|
||||||
|
});
|
||||||
|
|
||||||
|
var fsClient = Client.GetTestInstance(
|
||||||
|
settings,
|
||||||
|
new NetmapMock(this.key).GetMock().Object,
|
||||||
|
new SessionMock(this.key).GetMock().Object,
|
||||||
|
factory.GetMock().Object,
|
||||||
|
new ObjectMock(this.key).GetMock().Object);
|
||||||
|
|
||||||
|
var cid = new ContainerId(Base58.Encode(factory.ContainerGuid.ToBytes()));
|
||||||
|
|
||||||
|
var context = new Context();
|
||||||
|
|
||||||
|
var result = await fsClient.GetContainerAsync(cid, context);
|
||||||
|
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Equal(factory.Acl, result.BasicAcl);
|
||||||
|
Assert.Equal(factory.ContainerGuid, result.Nonce);
|
||||||
|
Assert.Equal(0, factory.PlacementPolicy.CompareTo(result.PlacementPolicy));
|
||||||
|
Assert.Equal(factory.Version.ToString(), result.Version!.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public async void DeleteObjectAsyncTest()
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
}
|
208
src/FrostFS.SDK.Tests/ClientTestLive.cs
Normal file
208
src/FrostFS.SDK.Tests/ClientTestLive.cs
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
using FrostFS.SDK.ClientV2;
|
||||||
|
using FrostFS.SDK.ClientV2.Interfaces;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class ClientTestLive
|
||||||
|
{
|
||||||
|
private readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||||
|
private readonly string url = "http://172.29.238.97:8080";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void NetworkMapTest()
|
||||||
|
{
|
||||||
|
var fsClient = Client.GetInstance(GetOptions(key, url));
|
||||||
|
|
||||||
|
var result = await fsClient.GetNetmapSnapshotAsync();
|
||||||
|
|
||||||
|
Assert.True(result.Epoch > 0);
|
||||||
|
Assert.Single(result.NodeInfoCollection);
|
||||||
|
|
||||||
|
var item = result.NodeInfoCollection[0];
|
||||||
|
Assert.Equal(2, item.Version.Major);
|
||||||
|
Assert.Equal(13, item.Version.Minor);
|
||||||
|
Assert.Equal(NodeState.Online, item.State);
|
||||||
|
Assert.True(item.PublicKey.Length > 0);
|
||||||
|
Assert.Single(item.Addresses);
|
||||||
|
Assert.Equal(9, item.Attributes.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void NodeInfoTest()
|
||||||
|
{
|
||||||
|
var fsClient = Client.GetInstance(GetOptions(this.key, this.url));
|
||||||
|
|
||||||
|
var result = await fsClient.GetNodeInfoAsync();
|
||||||
|
|
||||||
|
Assert.Equal(2, result.Version.Major);
|
||||||
|
Assert.Equal(13, result.Version.Minor);
|
||||||
|
Assert.Equal(NodeState.Online, result.State);
|
||||||
|
Assert.True(result.PublicKey.Length > 0);
|
||||||
|
Assert.Single(result.Addresses);
|
||||||
|
Assert.Equal(9, result.Attributes.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void SimpleScenarioTest()
|
||||||
|
{
|
||||||
|
var fsClient = Client.GetInstance(GetOptions(this.key, this.url));
|
||||||
|
|
||||||
|
fsClient.GrpcInvoked += (sender, info) =>
|
||||||
|
{
|
||||||
|
Assert.NotNull(info);
|
||||||
|
};
|
||||||
|
|
||||||
|
await Cleanup(fsClient);
|
||||||
|
|
||||||
|
var containerId = await fsClient.CreateContainerAsync(
|
||||||
|
new ModelsV2.Container(BasicAcl.PublicRW, new PlacementPolicy(true, new Replica(1))));
|
||||||
|
|
||||||
|
var context = new Context { Timeout = TimeSpan.FromSeconds(10) };
|
||||||
|
|
||||||
|
var container = await GetContainer(fsClient, containerId, context);
|
||||||
|
|
||||||
|
Assert.NotNull(container);
|
||||||
|
|
||||||
|
var param = new PutObjectParameters
|
||||||
|
{
|
||||||
|
Header = new ObjectHeader(
|
||||||
|
containerId: containerId,
|
||||||
|
type: ObjectType.Regular,
|
||||||
|
new ObjectAttribute("fileName", "test")),
|
||||||
|
Payload = new MemoryStream([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]),
|
||||||
|
ClientCut = false
|
||||||
|
};
|
||||||
|
|
||||||
|
var objectId = await fsClient.PutObjectAsync(param);
|
||||||
|
|
||||||
|
var filter = new ObjectFilter(ObjectMatchType.Equals, "fileName", "test");
|
||||||
|
|
||||||
|
bool hasObject = false;
|
||||||
|
await foreach (var objId in fsClient.SearchObjectsAsync(containerId, [filter]))
|
||||||
|
{
|
||||||
|
hasObject = true;
|
||||||
|
|
||||||
|
var objHeader = await fsClient.GetObjectHeadAsync(containerId, objectId);
|
||||||
|
Assert.Equal(10u, objHeader.PayloadLength);
|
||||||
|
Assert.Single(objHeader.Attributes);
|
||||||
|
Assert.Equal("fileName", objHeader.Attributes.First().Key);
|
||||||
|
Assert.Equal("test", objHeader.Attributes.First().Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.True(hasObject);
|
||||||
|
|
||||||
|
var @object = await fsClient.GetObjectAsync(containerId, objectId!);
|
||||||
|
|
||||||
|
Assert.Equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], @object.Payload);
|
||||||
|
|
||||||
|
await Cleanup(fsClient);
|
||||||
|
|
||||||
|
await Task.Delay(2000);
|
||||||
|
|
||||||
|
await foreach (var cid in fsClient.ListContainersAsync())
|
||||||
|
{
|
||||||
|
Assert.Fail("Containers exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ClientCutScenarioTest()
|
||||||
|
{
|
||||||
|
var fsClient = Client.GetInstance(GetOptions(this.key, this.url));
|
||||||
|
|
||||||
|
await Cleanup(fsClient);
|
||||||
|
|
||||||
|
var containerId = await fsClient.CreateContainerAsync(
|
||||||
|
new ModelsV2.Container(BasicAcl.PublicRW, new PlacementPolicy(true, new Replica(1))));
|
||||||
|
|
||||||
|
var context = new Context { Timeout = TimeSpan.FromSeconds(10) };
|
||||||
|
var container = await GetContainer(fsClient, containerId, context);
|
||||||
|
|
||||||
|
Assert.NotNull(container);
|
||||||
|
|
||||||
|
var param = new PutObjectParameters
|
||||||
|
{
|
||||||
|
Header = new ObjectHeader(
|
||||||
|
containerId: containerId,
|
||||||
|
type: ObjectType.Regular,
|
||||||
|
new ObjectAttribute("fileName", "test")),
|
||||||
|
Payload = new MemoryStream([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]),
|
||||||
|
ClientCut = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var objectId = await fsClient.PutObjectAsync(param);
|
||||||
|
|
||||||
|
var filter = new ObjectFilter(ObjectMatchType.Equals, "fileName", "test");
|
||||||
|
|
||||||
|
bool hasObject = false;
|
||||||
|
await foreach (var objId in fsClient.SearchObjectsAsync(containerId, [filter]))
|
||||||
|
{
|
||||||
|
hasObject = true;
|
||||||
|
|
||||||
|
var objHeader = await fsClient.GetObjectHeadAsync(containerId, objectId);
|
||||||
|
Assert.Equal(10u, objHeader.PayloadLength);
|
||||||
|
Assert.Single(objHeader.Attributes);
|
||||||
|
Assert.Equal("fileName", objHeader.Attributes.First().Key);
|
||||||
|
Assert.Equal("test", objHeader.Attributes.First().Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.True(hasObject);
|
||||||
|
|
||||||
|
var @object = await fsClient.GetObjectAsync(containerId, objectId!);
|
||||||
|
|
||||||
|
Assert.Equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], @object.Payload);
|
||||||
|
|
||||||
|
await Cleanup(fsClient);
|
||||||
|
|
||||||
|
await Task.Delay(2000);
|
||||||
|
|
||||||
|
await foreach (var _ in fsClient.ListContainersAsync())
|
||||||
|
{
|
||||||
|
Assert.Fail("Containers exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IOptions<ClientSettings> GetOptions(string key, string url)
|
||||||
|
{
|
||||||
|
var settings = new ClientSettings
|
||||||
|
{
|
||||||
|
Key = key,
|
||||||
|
Host = url
|
||||||
|
};
|
||||||
|
|
||||||
|
return Options.Create(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task Cleanup(IFrostFSClient fsClient)
|
||||||
|
{
|
||||||
|
await foreach (var cid in fsClient.ListContainersAsync())
|
||||||
|
{
|
||||||
|
await fsClient.DeleteContainerAsync(cid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task<ModelsV2.Container> GetContainer(IFrostFSClient fsClient, ContainerId id, Context ctx)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Delay(100);
|
||||||
|
return await fsClient.GetContainerAsync(id, ctx);
|
||||||
|
}
|
||||||
|
catch (ApplicationException)
|
||||||
|
{
|
||||||
|
if (DateTime.UtcNow >= ctx.Deadline)
|
||||||
|
throw new TimeoutException();
|
||||||
|
}
|
||||||
|
catch (Grpc.Core.RpcException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using FrostFS.Container;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public abstract class ServiceBase(string key)
|
||||||
|
{
|
||||||
|
public ECDsa Key { get; private set; } = key.LoadWif();
|
||||||
|
public ModelsV2.Version Version { get; set; } = DefaultVersion;
|
||||||
|
public BasicAcl Acl { get; set; } = DefaultAcl;
|
||||||
|
public PlacementPolicy PlacementPolicy { get; set; } = DefaultPlacementPolicy;
|
||||||
|
|
||||||
|
public static ModelsV2.Version DefaultVersion { get; } = new(2, 13);
|
||||||
|
public static BasicAcl DefaultAcl { get; } = BasicAcl.PublicRW;
|
||||||
|
public static PlacementPolicy DefaultPlacementPolicy { get; } = new PlacementPolicy(true, new Replica(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class ContainerServiceBase(string key) : ServiceBase (key)
|
||||||
|
{
|
||||||
|
public Guid ContainerGuid { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
|
public abstract Mock<ContainerService.ContainerServiceClient> GetMock();
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
using FrostFS.Container;
|
||||||
|
using FrostFS.Session;
|
||||||
|
using Google.Protobuf;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class DeleteContainerMock(string key) : ContainerServiceBase(key)
|
||||||
|
{
|
||||||
|
public override Mock<ContainerService.ContainerServiceClient> GetMock()
|
||||||
|
{
|
||||||
|
var mock = new Mock<ContainerService.ContainerServiceClient>();
|
||||||
|
|
||||||
|
var v = mock.Setup(x => x.DeleteAsync(
|
||||||
|
It.IsAny<DeleteRequest>(),
|
||||||
|
It.IsAny<Metadata>(),
|
||||||
|
It.IsAny<DateTime?>(),
|
||||||
|
It.IsAny<CancellationToken>()));
|
||||||
|
|
||||||
|
|
||||||
|
v.Returns((Object.DeleteRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var deleteResponse = new Object.DeleteResponse
|
||||||
|
{
|
||||||
|
Body = new Object.DeleteResponse.Types.Body
|
||||||
|
{
|
||||||
|
Tombstone = new Refs.Address
|
||||||
|
{
|
||||||
|
ContainerId = new Refs.ContainerID { Value = ByteString.CopyFrom([1, 2, 3]) },
|
||||||
|
ObjectId = new Refs.ObjectID { Value = ByteString.CopyFrom([4, 5, 6]) }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MetaHeader = new ResponseMetaHeader()
|
||||||
|
};
|
||||||
|
|
||||||
|
var metadata = new Metadata();
|
||||||
|
|
||||||
|
return new AsyncUnaryCall<Object.DeleteResponse>(
|
||||||
|
Task.FromResult(deleteResponse),
|
||||||
|
Task.FromResult(metadata),
|
||||||
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
||||||
|
() => metadata,
|
||||||
|
() => Console.WriteLine("disposed"));
|
||||||
|
});
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// objectServiceClientMock.Setup(x => x.Head(It.IsAny<Object.HeadRequest>(), It.IsAny<Metadata>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
|
||||||
|
// .Returns((Object.DeleteRequest r, Metadata m, DateTime dt, CancellationToken ct) =>
|
||||||
|
// {
|
||||||
|
// return new
|
||||||
|
// {
|
||||||
|
// Body = new Object.DeleteResponse.Types.Body
|
||||||
|
// {
|
||||||
|
// Tombstone = new Refs.Address
|
||||||
|
// {
|
||||||
|
// ContainerId = new Refs.ContainerID { Value = ByteString.CopyFrom([1, 2, 3]) },
|
||||||
|
// ObjectId = new Refs.ObjectID { Value = ByteString.CopyFrom([4, 5, 6]) }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
|
163
src/FrostFS.SDK.Tests/ContainerServiceMocks/GetContainerMock.cs
Normal file
163
src/FrostFS.SDK.Tests/ContainerServiceMocks/GetContainerMock.cs
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
using FrostFS.Container;
|
||||||
|
using FrostFS.Session;
|
||||||
|
using Google.Protobuf;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using FrostFS.SDK.ClientV2;
|
||||||
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class GetContainerMock(string key) : ContainerServiceBase(key)
|
||||||
|
{
|
||||||
|
public override Mock<ContainerService.ContainerServiceClient> GetMock()
|
||||||
|
{
|
||||||
|
var mock = new Mock<ContainerService.ContainerServiceClient>();
|
||||||
|
|
||||||
|
var grpcVersion = Version.ToGrpcMessage();
|
||||||
|
|
||||||
|
var getResponse = new GetResponse
|
||||||
|
{
|
||||||
|
Body = new GetResponse.Types.Body
|
||||||
|
{
|
||||||
|
Container = new Container.Container
|
||||||
|
{
|
||||||
|
Version = grpcVersion,
|
||||||
|
Nonce = ByteString.CopyFrom(ContainerGuid.ToBytes()),
|
||||||
|
BasicAcl = (uint)Acl,
|
||||||
|
PlacementPolicy = PlacementPolicy.ToGrpcMessage()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MetaHeader = new ResponseMetaHeader
|
||||||
|
{
|
||||||
|
Version = grpcVersion,
|
||||||
|
Epoch = 100,
|
||||||
|
Ttl = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getResponse.VerifyHeader = GetResponseVerificationHeader(getResponse);
|
||||||
|
|
||||||
|
var metadata = new Metadata();
|
||||||
|
var getContainerResponse = new AsyncUnaryCall<GetResponse>(
|
||||||
|
Task.FromResult(getResponse),
|
||||||
|
Task.FromResult(metadata),
|
||||||
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
||||||
|
() => metadata,
|
||||||
|
() => { });
|
||||||
|
|
||||||
|
mock.Setup(x => x.GetAsync(
|
||||||
|
It.IsAny<GetRequest>(),
|
||||||
|
It.IsAny<Metadata>(),
|
||||||
|
It.IsAny<DateTime?>(),
|
||||||
|
It.IsAny<CancellationToken>()))
|
||||||
|
.Returns((GetRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
Verifier.CheckRequest(r);
|
||||||
|
|
||||||
|
return getContainerResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseVerificationHeader GetResponseVerificationHeader(GetResponse response)
|
||||||
|
{
|
||||||
|
var verifyHeader = new ResponseVerificationHeader
|
||||||
|
{
|
||||||
|
MetaSignature = new Refs.Signature
|
||||||
|
{
|
||||||
|
Key = ByteString.CopyFrom(Key.PublicKey()),
|
||||||
|
Scheme = FrostFS.Refs.SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
Sign = ByteString.CopyFrom(Key.SignData(response.MetaHeader.ToByteArray()))
|
||||||
|
},
|
||||||
|
BodySignature = new Refs.Signature
|
||||||
|
{
|
||||||
|
Key = ByteString.CopyFrom(Key.PublicKey()),
|
||||||
|
Scheme = FrostFS.Refs.SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
Sign = ByteString.CopyFrom(Key.SignData(response.GetBody().ToByteArray()))
|
||||||
|
},
|
||||||
|
OriginSignature = new Refs.Signature
|
||||||
|
{
|
||||||
|
Key = ByteString.CopyFrom(Key.PublicKey()),
|
||||||
|
Scheme = FrostFS.Refs.SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
Sign = ByteString.CopyFrom(Key.SignData([]))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return verifyHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// objectServiceClientMock.Setup(
|
||||||
|
// x => x.Put(It.IsAny<Metadata>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
|
||||||
|
// .Returns((Metadata m, DateTime dt, CancellationToken ct) =>
|
||||||
|
// {
|
||||||
|
// return new AsyncClientStreamingCall<FrostFS.Object.PutRequest, FrostFS.Object.PutResponse>(null, null, null, null, null, null);
|
||||||
|
|
||||||
|
// //IClientStreamWriter<TRequest> requestStream, Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return objectServiceClientMock;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// public virtual global::FrostFS.Object.HeadResponse Head(global::FrostFS.Object.HeadRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||||
|
// {
|
||||||
|
// return Head(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// objectServiceClientMock.Setup(x => x.Head(It.IsAny<Object.HeadRequest>(), It.IsAny<Metadata>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
|
||||||
|
// .Returns((Object.DeleteRequest r, Metadata m, DateTime dt, CancellationToken ct) =>
|
||||||
|
// {
|
||||||
|
// return new
|
||||||
|
// {
|
||||||
|
// Body = new Object.DeleteResponse.Types.Body
|
||||||
|
// {
|
||||||
|
// Tombstone = new Refs.Address
|
||||||
|
// {
|
||||||
|
// ContainerId = new Refs.ContainerID { Value = ByteString.CopyFrom([1, 2, 3]) },
|
||||||
|
// ObjectId = new Refs.ObjectID { Value = ByteString.CopyFrom([4, 5, 6]) }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
// objectServiceClientMock.Setup(x => x.Delete(It.IsAny<Object.DeleteRequest>(), It.IsAny<Metadata>(), It.IsAny<DateTime?>(), It.IsAny<CancellationToken>()))
|
||||||
|
// .Returns((Object.DeleteRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
||||||
|
// {
|
||||||
|
// return new Object.DeleteResponse
|
||||||
|
// {
|
||||||
|
// Body = new Object.DeleteResponse.Types.Body
|
||||||
|
// {
|
||||||
|
// Tombstone = new Refs.Address
|
||||||
|
// {
|
||||||
|
// ContainerId = new Refs.ContainerID { Value = ByteString.CopyFrom([1, 2, 3]) },
|
||||||
|
// ObjectId = new Refs.ObjectID { Value = ByteString.CopyFrom([4, 5, 6]) }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// MetaHeader = new ResponseMetaHeader()
|
||||||
|
// {
|
||||||
|
// },
|
||||||
|
// VerifyHeader = new ResponseVerificationHeader()
|
||||||
|
// {
|
||||||
|
// MetaSignature = new Refs.Signature
|
||||||
|
// {
|
||||||
|
// Key = ByteString.CopyFrom(_key.PublicKey()),
|
||||||
|
// Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
// Sign = ByteString.CopyFrom(_key.SignData(Array.Empty<byte>()))
|
||||||
|
|
||||||
|
// // ByteString.CopyFrom(_key.SignData(grpcHeader.Split.Parent.ToByteArray())),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// };
|
||||||
|
// });
|
|
@ -0,0 +1,88 @@
|
||||||
|
using FrostFS.Container;
|
||||||
|
using FrostFS.Session;
|
||||||
|
using Google.Protobuf;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Moq;
|
||||||
|
using FrostFS.SDK.ClientV2;
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using FrostFS.Refs;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class PutContainerMock(string key) : ContainerServiceBase(key)
|
||||||
|
{
|
||||||
|
public override Mock<ContainerService.ContainerServiceClient> GetMock()
|
||||||
|
{
|
||||||
|
var mock = new Mock<ContainerService.ContainerServiceClient>();
|
||||||
|
|
||||||
|
PutResponse response = new()
|
||||||
|
{
|
||||||
|
Body = new PutResponse.Types.Body
|
||||||
|
{
|
||||||
|
ContainerId = new ContainerID
|
||||||
|
{
|
||||||
|
Value = ByteString.CopyFrom(ContainerGuid.ToBytes())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MetaHeader = new ResponseMetaHeader
|
||||||
|
{
|
||||||
|
Version = Version is null ? DefaultVersion.ToGrpcMessage() : Version.ToGrpcMessage(),
|
||||||
|
Epoch = 100,
|
||||||
|
Ttl = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
response.VerifyHeader = PutResponseVerificationHeader(response);
|
||||||
|
|
||||||
|
var metadata = new Metadata();
|
||||||
|
var putContainerResponse = new AsyncUnaryCall<PutResponse>(
|
||||||
|
Task.FromResult(response),
|
||||||
|
Task.FromResult(metadata),
|
||||||
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
||||||
|
() => metadata,
|
||||||
|
() => { });
|
||||||
|
|
||||||
|
mock.Setup(x => x.PutAsync(
|
||||||
|
It.IsAny<PutRequest>(),
|
||||||
|
It.IsAny<Metadata>(),
|
||||||
|
It.IsAny<DateTime?>(),
|
||||||
|
It.IsAny<CancellationToken>()))
|
||||||
|
.Returns((PutRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
Verifier.CheckRequest(r);
|
||||||
|
|
||||||
|
return putContainerResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseVerificationHeader PutResponseVerificationHeader(PutResponse response)
|
||||||
|
{
|
||||||
|
var verifyHeader = new ResponseVerificationHeader
|
||||||
|
{
|
||||||
|
MetaSignature = new Signature
|
||||||
|
{
|
||||||
|
Key = ByteString.CopyFrom(Key.PublicKey()),
|
||||||
|
Scheme = SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
Sign = ByteString.CopyFrom(Key.SignData(response.MetaHeader.ToByteArray()))
|
||||||
|
},
|
||||||
|
BodySignature = new Signature
|
||||||
|
{
|
||||||
|
Key = ByteString.CopyFrom(Key.PublicKey()),
|
||||||
|
Scheme = SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
Sign = ByteString.CopyFrom(Key.SignData(response.GetBody().ToByteArray()))
|
||||||
|
},
|
||||||
|
OriginSignature = new Signature
|
||||||
|
{
|
||||||
|
Key = ByteString.CopyFrom(Key.PublicKey()),
|
||||||
|
Scheme = SignatureScheme.EcdsaRfc6979Sha256,
|
||||||
|
Sign = ByteString.CopyFrom(Key.SignData([]))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return verifyHeader;
|
||||||
|
}
|
||||||
|
}
|
14
src/FrostFS.SDK.Tests/NetmapMock.cs
Normal file
14
src/FrostFS.SDK.Tests/NetmapMock.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using Moq;
|
||||||
|
using FrostFS.Netmap;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class NetmapMock(string key) : ServiceBase(key)
|
||||||
|
{
|
||||||
|
public Mock<NetmapService.NetmapServiceClient> GetMock()
|
||||||
|
{
|
||||||
|
var mock = new Mock<NetmapService.NetmapServiceClient>();
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
}
|
14
src/FrostFS.SDK.Tests/ObjectMock.cs
Normal file
14
src/FrostFS.SDK.Tests/ObjectMock.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using Moq;
|
||||||
|
using FrostFS.Object;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class ObjectMock(string key) : ServiceBase(key)
|
||||||
|
{
|
||||||
|
public Mock<ObjectService.ObjectServiceClient> GetMock()
|
||||||
|
{
|
||||||
|
var mock = new Mock<ObjectService.ObjectServiceClient>();
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
}
|
14
src/FrostFS.SDK.Tests/SessionMock.cs
Normal file
14
src/FrostFS.SDK.Tests/SessionMock.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using Moq;
|
||||||
|
using FrostFS.Session;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Tests;
|
||||||
|
|
||||||
|
public class SessionMock(string key) : ServiceBase(key)
|
||||||
|
{
|
||||||
|
public Mock<SessionService.SessionServiceClient> GetMock()
|
||||||
|
{
|
||||||
|
var mock = new Mock<SessionService.SessionServiceClient>();
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue