[#69] Fix for Patch and uint types
Signed-off-by: Pavel Gross <p.gross@yadro.com>
This commit is contained in:
parent
eebba7665b
commit
0816be732a
20 changed files with 212 additions and 153 deletions
|
@ -8,7 +8,7 @@ using System.Runtime.CompilerServices;
|
||||||
"e15ab287e6239c98d5dfa91615bd77485d523a3a3f65a4e5028454cedd5ac4d9eca6da18b81985"+
|
"e15ab287e6239c98d5dfa91615bd77485d523a3a3f65a4e5028454cedd5ac4d9eca6da18b81985"+
|
||||||
"ac6905d33cc64b5a2587050c16f67b71ef8889dbd3c90ef7cc0b06bbbe09886601d195f5db179a"+
|
"ac6905d33cc64b5a2587050c16f67b71ef8889dbd3c90ef7cc0b06bbbe09886601d195f5db179a"+
|
||||||
"3c2a25b1")]
|
"3c2a25b1")]
|
||||||
[assembly: AssemblyFileVersion("1.0.6.0")]
|
[assembly: AssemblyFileVersion("1.0.7.0")]
|
||||||
[assembly: AssemblyProduct("FrostFS.SDK.Client")]
|
[assembly: AssemblyProduct("FrostFS.SDK.Client")]
|
||||||
[assembly: AssemblyTitle("FrostFS.SDK.Client")]
|
[assembly: AssemblyTitle("FrostFS.SDK.Client")]
|
||||||
[assembly: AssemblyVersion("1.0.6")]
|
[assembly: AssemblyVersion("1.0.7")]
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||||
<PackageId>FrostFS.SDK.Client</PackageId>
|
<PackageId>FrostFS.SDK.Client</PackageId>
|
||||||
<Version>1.0.6</Version>
|
<Version>1.0.7</Version>
|
||||||
<Description>
|
<Description>
|
||||||
C# SDK for FrostFS gRPC native protocol
|
C# SDK for FrostFS gRPC native protocol
|
||||||
</Description>
|
</Description>
|
||||||
|
|
|
@ -16,8 +16,8 @@ public static class MetaHeaderMapper
|
||||||
return new RequestMetaHeader
|
return new RequestMetaHeader
|
||||||
{
|
{
|
||||||
Version = metaHeader.Version.ToMessage(),
|
Version = metaHeader.Version.ToMessage(),
|
||||||
Epoch = (uint)metaHeader.Epoch,
|
Epoch = metaHeader.Epoch,
|
||||||
Ttl = (uint)metaHeader.Ttl
|
Ttl = metaHeader.Ttl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@ public static class PolicyMapper
|
||||||
{
|
{
|
||||||
return new Replica
|
return new Replica
|
||||||
{
|
{
|
||||||
Count = (uint)replica.Count,
|
Count = replica.Count,
|
||||||
Selector = replica.Selector,
|
Selector = replica.Selector,
|
||||||
EcDataCount = replica.EcDataCount,
|
EcDataCount = replica.EcDataCount,
|
||||||
EcParityCount = replica.EcParityCount
|
EcParityCount = replica.EcParityCount
|
||||||
|
@ -25,7 +25,7 @@ public static class PolicyMapper
|
||||||
throw new ArgumentNullException(nameof(replica));
|
throw new ArgumentNullException(nameof(replica));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FrostFsReplica((int)replica.Count, replica.Selector)
|
return new FrostFsReplica(replica.Count, replica.Selector)
|
||||||
{
|
{
|
||||||
EcDataCount = replica.EcDataCount,
|
EcDataCount = replica.EcDataCount,
|
||||||
EcParityCount = replica.EcParityCount
|
EcParityCount = replica.EcParityCount
|
||||||
|
|
|
@ -18,7 +18,7 @@ public static class VersionMapper
|
||||||
throw new System.ArgumentNullException(nameof(model));
|
throw new System.ArgumentNullException(nameof(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = model.Major << 16 + model.Minor;
|
var key = (int)model.Major << 16 + (int)model.Minor;
|
||||||
|
|
||||||
if (!_cacheMessages.ContainsKey(key))
|
if (!_cacheMessages.ContainsKey(key))
|
||||||
{
|
{
|
||||||
|
@ -28,8 +28,8 @@ public static class VersionMapper
|
||||||
_spinlock.Enter(ref lockTaken);
|
_spinlock.Enter(ref lockTaken);
|
||||||
var message = new Version
|
var message = new Version
|
||||||
{
|
{
|
||||||
Major = (uint)model.Major,
|
Major = model.Major,
|
||||||
Minor = (uint)model.Minor
|
Minor = model.Minor
|
||||||
};
|
};
|
||||||
|
|
||||||
_cacheMessages.Add(key, message);
|
_cacheMessages.Add(key, message);
|
||||||
|
@ -64,7 +64,7 @@ public static class VersionMapper
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_spinlock.Enter(ref lockTaken);
|
_spinlock.Enter(ref lockTaken);
|
||||||
var model = new FrostFsVersion((int)message.Major, (int)message.Minor);
|
var model = new FrostFsVersion(message.Major, message.Minor);
|
||||||
|
|
||||||
_cacheModels.Add(key, model);
|
_cacheModels.Add(key, model);
|
||||||
return model;
|
return model;
|
||||||
|
|
|
@ -4,12 +4,12 @@ namespace FrostFS.SDK;
|
||||||
|
|
||||||
public struct FrostFsReplica : IEquatable<FrostFsReplica>
|
public struct FrostFsReplica : IEquatable<FrostFsReplica>
|
||||||
{
|
{
|
||||||
public int Count { get; set; }
|
public uint Count { get; set; }
|
||||||
public string Selector { get; set; }
|
public string Selector { get; set; }
|
||||||
public uint EcDataCount { get; set; }
|
public uint EcDataCount { get; set; }
|
||||||
public uint EcParityCount { get; set; }
|
public uint EcParityCount { get; set; }
|
||||||
|
|
||||||
public FrostFsReplica(int count, string? selector = null)
|
public FrostFsReplica(uint count, string? selector = null)
|
||||||
{
|
{
|
||||||
selector ??= string.Empty;
|
selector ??= string.Empty;
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ public struct FrostFsReplica : IEquatable<FrostFsReplica>
|
||||||
|
|
||||||
public readonly uint CountNodes()
|
public readonly uint CountNodes()
|
||||||
{
|
{
|
||||||
return Count != 0 ? (uint)Count : EcDataCount + EcParityCount;
|
return Count != 0 ? Count : EcDataCount + EcParityCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override readonly int GetHashCode()
|
public override readonly int GetHashCode()
|
||||||
{
|
{
|
||||||
return (Count + Selector.GetHashCode()) ^ (int)EcDataCount ^ (int)EcParityCount;
|
return Count.GetHashCode() ^ Selector.GetHashCode() ^ (int)EcDataCount ^ (int)EcParityCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator ==(FrostFsReplica left, FrostFsReplica right)
|
public static bool operator ==(FrostFsReplica left, FrostFsReplica right)
|
||||||
|
|
|
@ -3,12 +3,12 @@ using FrostFS.SDK.Client.Mappers.GRPC;
|
||||||
|
|
||||||
namespace FrostFS.SDK;
|
namespace FrostFS.SDK;
|
||||||
|
|
||||||
public class FrostFsVersion(int major, int minor)
|
public class FrostFsVersion(uint major, uint minor)
|
||||||
{
|
{
|
||||||
private Version? version;
|
private Version? version;
|
||||||
|
|
||||||
public int Major { get; set; } = major;
|
public uint Major { get; set; } = major;
|
||||||
public int Minor { get; set; } = minor;
|
public uint Minor { get; set; } = minor;
|
||||||
|
|
||||||
internal Version VersionID
|
internal Version VersionID
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
namespace FrostFS.SDK;
|
namespace FrostFS.SDK;
|
||||||
|
|
||||||
public class MetaHeader(FrostFsVersion version, int epoch, int ttl)
|
public class MetaHeader(FrostFsVersion version, ulong epoch, uint ttl)
|
||||||
{
|
{
|
||||||
public FrostFsVersion Version { get; set; } = version;
|
public FrostFsVersion Version { get; set; } = version;
|
||||||
public int Epoch { get; set; } = epoch;
|
public ulong Epoch { get; set; } = epoch;
|
||||||
public int Ttl { get; set; } = ttl;
|
public uint Ttl { get; set; } = ttl;
|
||||||
|
|
||||||
public static MetaHeader Default()
|
public static MetaHeader Default()
|
||||||
{
|
{
|
||||||
|
|
|
@ -295,10 +295,17 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
internal async Task<FrostFsObjectId> PatchObjectAsync(PrmObjectPatch args, CallContext ctx)
|
internal async Task<FrostFsObjectId> PatchObjectAsync(PrmObjectPatch args, CallContext ctx)
|
||||||
{
|
{
|
||||||
var chunkSize = args.MaxChunkLength;
|
var chunkSize = args.MaxChunkLength;
|
||||||
Stream payload = args.Payload ?? throw new ArgumentNullException(nameof(args), "Stream parameter is null");
|
|
||||||
|
|
||||||
var call = client.Patch(null, ctx.GetDeadline(), ctx.CancellationToken);
|
var call = client.Patch(null, ctx.GetDeadline(), ctx.CancellationToken);
|
||||||
|
|
||||||
|
var address = new Address
|
||||||
|
{
|
||||||
|
ObjectId = args.Address.ObjectId,
|
||||||
|
ContainerId = args.Address.ContainerId
|
||||||
|
};
|
||||||
|
|
||||||
|
if (args.Payload != null && args.Payload.Length > 0)
|
||||||
|
{
|
||||||
byte[]? chunkBuffer = null;
|
byte[]? chunkBuffer = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -307,22 +314,32 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
bool isFirstChunk = true;
|
bool isFirstChunk = true;
|
||||||
ulong currentPos = args.Range.Offset;
|
ulong currentPos = args.Range.Offset;
|
||||||
|
|
||||||
var address = new Address
|
|
||||||
{
|
|
||||||
ObjectId = args.Address.ObjectId,
|
|
||||||
ContainerId = args.Address.ContainerId
|
|
||||||
};
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var bytesCount = await payload.ReadAsync(chunkBuffer, 0, chunkSize, ctx.CancellationToken).ConfigureAwait(false);
|
var bytesCount = await args.Payload.ReadAsync(chunkBuffer, 0, chunkSize, ctx.CancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (bytesCount == 0)
|
if (bytesCount == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = new PatchRequest()
|
PatchRequest request;
|
||||||
|
|
||||||
|
if (isFirstChunk)
|
||||||
|
{
|
||||||
|
request = await CreateFirstRequest(args, ctx, address).ConfigureAwait(false);
|
||||||
|
|
||||||
|
request.Body.Patch = new PatchRequest.Types.Body.Types.Patch
|
||||||
|
{
|
||||||
|
Chunk = UnsafeByteOperations.UnsafeWrap(chunkBuffer.AsMemory(0, bytesCount)),
|
||||||
|
SourceRange = new Range { Offset = currentPos, Length = (ulong)bytesCount }
|
||||||
|
};
|
||||||
|
|
||||||
|
isFirstChunk = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request = new PatchRequest()
|
||||||
{
|
{
|
||||||
Body = new()
|
Body = new()
|
||||||
{
|
{
|
||||||
|
@ -335,30 +352,6 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isFirstChunk)
|
|
||||||
{
|
|
||||||
var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var protoToken = sessionToken.CreateObjectTokenContext(
|
|
||||||
address,
|
|
||||||
ObjectSessionContext.Types.Verb.Patch,
|
|
||||||
ClientContext.Key);
|
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders, protoToken);
|
|
||||||
|
|
||||||
if (args.NewAttributes != null && args.NewAttributes.Length > 0)
|
|
||||||
{
|
|
||||||
foreach (var attr in args.NewAttributes)
|
|
||||||
{
|
|
||||||
request.Body.NewAttributes.Add(attr.ToMessage());
|
|
||||||
request.Body.ReplaceAttributes = args.ReplaceAttributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isFirstChunk = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
request.AddMetaHeader(args.XHeaders);
|
request.AddMetaHeader(args.XHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,6 +369,15 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
ArrayPool<byte>.Shared.Return(chunkBuffer);
|
ArrayPool<byte>.Shared.Return(chunkBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (args.NewAttributes != null && args.NewAttributes.Length > 0)
|
||||||
|
{
|
||||||
|
PatchRequest request = await CreateFirstRequest(args, ctx, address).ConfigureAwait(false);
|
||||||
|
|
||||||
|
request.Sign(ClientContext.Key);
|
||||||
|
|
||||||
|
await call.RequestStream.WriteAsync(request).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
await call.RequestStream.CompleteAsync().ConfigureAwait(false);
|
await call.RequestStream.CompleteAsync().ConfigureAwait(false);
|
||||||
var response = await call.ResponseAsync.ConfigureAwait(false);
|
var response = await call.ResponseAsync.ConfigureAwait(false);
|
||||||
|
@ -383,6 +385,33 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
Verifier.CheckResponse(response);
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
return response.Body.ObjectId.ToModel();
|
return response.Body.ObjectId.ToModel();
|
||||||
|
|
||||||
|
async Task<PatchRequest> CreateFirstRequest(PrmObjectPatch args, CallContext ctx, Address address)
|
||||||
|
{
|
||||||
|
var body = new PatchRequest.Types.Body() { Address = address };
|
||||||
|
|
||||||
|
if (args.NewAttributes != null)
|
||||||
|
{
|
||||||
|
body.ReplaceAttributes = args.ReplaceAttributes;
|
||||||
|
|
||||||
|
foreach (var attr in args.NewAttributes!)
|
||||||
|
{
|
||||||
|
body.NewAttributes.Add(attr.ToMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = new PatchRequest() { Body = body };
|
||||||
|
|
||||||
|
var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var protoToken = sessionToken.CreateObjectTokenContext(
|
||||||
|
address,
|
||||||
|
ObjectSessionContext.Types.Verb.Patch,
|
||||||
|
ClientContext.Key);
|
||||||
|
|
||||||
|
request.AddMetaHeader(args.XHeaders, protoToken);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<FrostFsObjectId> PutClientCutObjectAsync(PrmObjectClientCutPut args, CallContext ctx)
|
internal async Task<FrostFsObjectId> PutClientCutObjectAsync(PrmObjectClientCutPut args, CallContext ctx)
|
||||||
|
@ -582,8 +611,10 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
var restPart = (fullLength % (ulong)partSize) > 0 ? 1 : 0;
|
var restPart = (fullLength % (ulong)partSize) > 0 ? 1 : 0;
|
||||||
var objectsCount = fullLength > 0 ? (int)(fullLength / (ulong)partSize) + restPart : 0;
|
var objectsCount = fullLength > 0 ? (int)(fullLength / (ulong)partSize) + restPart : 0;
|
||||||
|
|
||||||
|
progressInfo ??= new UploadProgressInfo(Guid.NewGuid(), objectsCount);
|
||||||
|
|
||||||
// if the object fits one part, it can be loaded as non-complex object, but if it is not upload resuming
|
// if the object fits one part, it can be loaded as non-complex object, but if it is not upload resuming
|
||||||
if (objectsCount == 1 && progressInfo != null && progressInfo.GetLast().Length == 0)
|
if (objectsCount == 1 && progressInfo.GetLast().Length == 0)
|
||||||
{
|
{
|
||||||
args.PutObjectContext.MaxObjectSizeCache = partSize;
|
args.PutObjectContext.MaxObjectSizeCache = partSize;
|
||||||
args.PutObjectContext.FullLength = fullLength;
|
args.PutObjectContext.FullLength = fullLength;
|
||||||
|
@ -591,8 +622,6 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
return singlePartResult.ObjectId;
|
return singlePartResult.ObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
progressInfo ??= new UploadProgressInfo(Guid.NewGuid(), objectsCount);
|
|
||||||
|
|
||||||
var remain = fullLength;
|
var remain = fullLength;
|
||||||
|
|
||||||
byte[]? buffer = null;
|
byte[]? buffer = null;
|
||||||
|
@ -659,7 +688,9 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
|
||||||
offset += size;
|
offset += size;
|
||||||
|
|
||||||
if (i < objectsCount)
|
if (i < objectsCount)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Once all parts of the object are uploaded, they must be linked into a single entity
|
// Once all parts of the object are uploaded, they must be linked into a single entity
|
||||||
var linkObject = new FrostFsLinkObject(args.Header.ContainerId, progressInfo.SplitId, parentHeader!, [.. progressInfo.GetParts().Select(p => p.ObjectId)]);
|
var linkObject = new FrostFsLinkObject(args.Header.ContainerId, progressInfo.SplitId, parentHeader!, [.. progressInfo.GetParts().Select(p => p.ObjectId)]);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyCompany("TrueCloudLab")]
|
[assembly: AssemblyCompany("TrueCloudLab")]
|
||||||
[assembly: AssemblyFileVersion("1.0.6.0")]
|
[assembly: AssemblyFileVersion("1.0.7.0")]
|
||||||
[assembly: AssemblyProduct("FrostFS.SDK.Cryptography")]
|
[assembly: AssemblyProduct("FrostFS.SDK.Cryptography")]
|
||||||
[assembly: AssemblyTitle("FrostFS.SDK.Cryptography")]
|
[assembly: AssemblyTitle("FrostFS.SDK.Cryptography")]
|
||||||
[assembly: AssemblyVersion("1.0.6.0")]
|
[assembly: AssemblyVersion("1.0.7.0")]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<LangVersion>12.0</LangVersion>
|
<LangVersion>12.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<PackageId>FrostFS.SDK.Cryptography</PackageId>
|
<PackageId>FrostFS.SDK.Cryptography</PackageId>
|
||||||
<Version>1.0.6</Version>
|
<Version>1.0.7</Version>
|
||||||
<Description>
|
<Description>
|
||||||
Cryptography tools for C# SDK
|
Cryptography tools for C# SDK
|
||||||
</Description>
|
</Description>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyCompany("TrueCloudLab")]
|
[assembly: AssemblyCompany("TrueCloudLab")]
|
||||||
[assembly: AssemblyFileVersion("1.0.6.0")]
|
[assembly: AssemblyFileVersion("1.0.7.0")]
|
||||||
[assembly: AssemblyProduct("FrostFS.SDK.Protos")]
|
[assembly: AssemblyProduct("FrostFS.SDK.Protos")]
|
||||||
[assembly: AssemblyTitle("FrostFS.SDK.Protos")]
|
[assembly: AssemblyTitle("FrostFS.SDK.Protos")]
|
||||||
[assembly: AssemblyVersion("1.0.6.0")]
|
[assembly: AssemblyVersion("1.0.7.0")]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<LangVersion>12.0</LangVersion>
|
<LangVersion>12.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<PackageId>FrostFS.SDK.Protos</PackageId>
|
<PackageId>FrostFS.SDK.Protos</PackageId>
|
||||||
<Version>1.0.6</Version>
|
<Version>1.0.7</Version>
|
||||||
<Description>
|
<Description>
|
||||||
Protobuf client for C# SDK
|
Protobuf client for C# SDK
|
||||||
</Description>
|
</Description>
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class ContainerTests : SmokeTestsBase
|
||||||
Assert.Empty(container.PlacementPolicy.Value.Filters);
|
Assert.Empty(container.PlacementPolicy.Value.Filters);
|
||||||
|
|
||||||
Assert.Single(container.PlacementPolicy.Value.Replicas);
|
Assert.Single(container.PlacementPolicy.Value.Replicas);
|
||||||
Assert.Equal(3, container.PlacementPolicy.Value.Replicas[0].Count);
|
Assert.Equal(3u, container.PlacementPolicy.Value.Replicas[0].Count);
|
||||||
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcParityCount);
|
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcParityCount);
|
||||||
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcDataCount);
|
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcDataCount);
|
||||||
Assert.Equal("", container.PlacementPolicy.Value.Replicas[0].Selector);
|
Assert.Equal("", container.PlacementPolicy.Value.Replicas[0].Selector);
|
||||||
|
@ -191,7 +191,7 @@ public class ContainerTests : SmokeTestsBase
|
||||||
Assert.Empty(subFilter.Filters);
|
Assert.Empty(subFilter.Filters);
|
||||||
|
|
||||||
Assert.Single(container.PlacementPolicy.Value.Replicas);
|
Assert.Single(container.PlacementPolicy.Value.Replicas);
|
||||||
Assert.Equal(1, container.PlacementPolicy.Value.Replicas[0].Count);
|
Assert.Equal(1u, container.PlacementPolicy.Value.Replicas[0].Count);
|
||||||
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcParityCount);
|
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcParityCount);
|
||||||
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcDataCount);
|
Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcDataCount);
|
||||||
Assert.Equal("", container.PlacementPolicy.Value.Replicas[0].Selector);
|
Assert.Equal("", container.PlacementPolicy.Value.Replicas[0].Selector);
|
||||||
|
|
|
@ -29,8 +29,8 @@ public class InterceptorTests() : SmokeTestsBase
|
||||||
Assert.True(callbackInvoked);
|
Assert.True(callbackInvoked);
|
||||||
Assert.True(interceptorInvoked);
|
Assert.True(interceptorInvoked);
|
||||||
|
|
||||||
Assert.Equal(2, result.Version.Major);
|
Assert.Equal(2u, result.Version.Major);
|
||||||
Assert.Equal(13, result.Version.Minor);
|
Assert.Equal(13u, result.Version.Minor);
|
||||||
Assert.Equal(NodeState.Online, result.State);
|
Assert.Equal(NodeState.Online, result.State);
|
||||||
Assert.Equal(33, result.PublicKey.Length);
|
Assert.Equal(33, result.PublicKey.Length);
|
||||||
Assert.NotNull(result.Addresses);
|
Assert.NotNull(result.Addresses);
|
||||||
|
|
|
@ -28,8 +28,8 @@ public class SmokeClientTests : SmokeTestsBase
|
||||||
|
|
||||||
var result = await client.GetNodeInfoAsync(default);
|
var result = await client.GetNodeInfoAsync(default);
|
||||||
|
|
||||||
Assert.Equal(2, result.Version.Major);
|
Assert.Equal(2u, result.Version.Major);
|
||||||
Assert.Equal(13, result.Version.Minor);
|
Assert.Equal(13u, result.Version.Minor);
|
||||||
Assert.Equal(NodeState.Online, result.State);
|
Assert.Equal(NodeState.Online, result.State);
|
||||||
Assert.Equal(33, result.PublicKey.Length);
|
Assert.Equal(33, result.PublicKey.Length);
|
||||||
Assert.Single(result.Addresses);
|
Assert.Single(result.Addresses);
|
||||||
|
@ -103,8 +103,8 @@ public class SmokeClientTests : SmokeTestsBase
|
||||||
Assert.True(callbackInvoked);
|
Assert.True(callbackInvoked);
|
||||||
Assert.True(interceptorInvoked);
|
Assert.True(interceptorInvoked);
|
||||||
|
|
||||||
Assert.Equal(2, result.Version.Major);
|
Assert.Equal(2u, result.Version.Major);
|
||||||
Assert.Equal(13, result.Version.Minor);
|
Assert.Equal(13u, result.Version.Minor);
|
||||||
Assert.Equal(NodeState.Online, result.State);
|
Assert.Equal(NodeState.Online, result.State);
|
||||||
Assert.Equal(33, result.PublicKey.Length);
|
Assert.Equal(33, result.PublicKey.Length);
|
||||||
Assert.NotNull(result.Addresses);
|
Assert.NotNull(result.Addresses);
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
|
||||||
[InlineData(false, 2, 3)]
|
[InlineData(false, 2, 3)]
|
||||||
[InlineData(true, 2, 1)]
|
[InlineData(true, 2, 1)]
|
||||||
[InlineData(false, 2, 1)]
|
[InlineData(false, 2, 1)]
|
||||||
public async void FullScenario(bool unique, uint backupFactor, int replicas)
|
public async void FullScenario(bool unique, uint backupFactor, uint replicas)
|
||||||
{
|
{
|
||||||
var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
|
var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
|
||||||
_testOutputHelper.WriteLine("client created");
|
_testOutputHelper.WriteLine("client created");
|
||||||
|
@ -121,9 +121,16 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
|
||||||
await ValidateFilters(client, containerId, objectId, null, (ulong)bytes.Length);
|
await ValidateFilters(client, containerId, objectId, null, (ulong)bytes.Length);
|
||||||
_testOutputHelper.WriteLine($"\tfilters validated");
|
_testOutputHelper.WriteLine($"\tfilters validated");
|
||||||
|
|
||||||
if (type != clientCut)
|
if (type != clientCut && bytes.Length > 1024 + 64 && bytes.Length < 20 * 1024 * 1024)
|
||||||
{
|
{
|
||||||
await ValidatePatch(client, containerId, bytes, objectId);
|
// patch payload only
|
||||||
|
await ValidatePatch(client, containerId, bytes, true, objectId, [], false);
|
||||||
|
|
||||||
|
// patch attributes only
|
||||||
|
await ValidatePatch(client, containerId, bytes, false, objectId, [new("a1", "v1"), new("a2", "v2")], false);
|
||||||
|
|
||||||
|
// patch payload and attributes
|
||||||
|
await ValidatePatch(client, containerId, bytes, true, objectId, [new("a3", "v3"), new("a4", "v4")], true);
|
||||||
_testOutputHelper.WriteLine($"\tpatch validated");
|
_testOutputHelper.WriteLine($"\tpatch validated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,29 +206,42 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
|
||||||
_testOutputHelper.WriteLine($"\t\trange {range.Offset};{range.Length} validated");
|
_testOutputHelper.WriteLine($"\t\trange {range.Offset};{range.Length} validated");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task ValidatePatch(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes, FrostFsObjectId objectId)
|
private static async Task ValidatePatch(
|
||||||
|
IFrostFSClient client,
|
||||||
|
FrostFsContainerId containerId,
|
||||||
|
byte[] bytes,
|
||||||
|
bool patchPayload,
|
||||||
|
FrostFsObjectId objectId,
|
||||||
|
FrostFsAttributePair[] attributes,
|
||||||
|
bool replaceAttributes)
|
||||||
{
|
{
|
||||||
if (bytes.Length < 1024 + 64 || bytes.Length > 5900)
|
byte[]? patch = null;
|
||||||
return;
|
FrostFsRange range = new();
|
||||||
|
if (patchPayload)
|
||||||
var patch = new byte[1024];
|
{
|
||||||
|
patch = new byte[1024];
|
||||||
for (int i = 0; i < patch.Length; i++)
|
for (int i = 0; i < patch.Length; i++)
|
||||||
{
|
{
|
||||||
patch[i] = 32;
|
patch[i] = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
var range = new FrostFsRange(64, (ulong)patch.Length);
|
range = new FrostFsRange(64, (ulong)patch.Length);
|
||||||
|
}
|
||||||
|
|
||||||
var patchParams = new PrmObjectPatch(
|
var patchParams = new PrmObjectPatch(
|
||||||
new FrostFsAddress(containerId, objectId),
|
new FrostFsAddress(containerId, objectId),
|
||||||
payload: new MemoryStream(patch),
|
payload: new MemoryStream(patch ?? []),
|
||||||
maxChunkLength: 1024,
|
maxChunkLength: 1024,
|
||||||
range: range);
|
range: range,
|
||||||
|
replaceAttributes: replaceAttributes,
|
||||||
|
newAttributes: attributes);
|
||||||
|
|
||||||
var newIbjId = await client.PatchObjectAsync(patchParams, default);
|
var newIbjId = await client.PatchObjectAsync(patchParams, default);
|
||||||
|
|
||||||
var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, newIbjId), default);
|
var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, newIbjId), default);
|
||||||
|
|
||||||
|
if (patchPayload)
|
||||||
|
{
|
||||||
var downloadedBytes = new byte[@object.Header.PayloadLength];
|
var downloadedBytes = new byte[@object.Header.PayloadLength];
|
||||||
MemoryStream ms = new(downloadedBytes);
|
MemoryStream ms = new(downloadedBytes);
|
||||||
|
|
||||||
|
@ -243,6 +263,15 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
|
||||||
Assert.Equal(downloadedBytes[i], bytes[i]);
|
Assert.Equal(downloadedBytes[i], bytes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attributes != null && attributes.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var newAttr in attributes)
|
||||||
|
{
|
||||||
|
var i = @object!.Header!.Attributes!.Count(p => p.Key == newAttr.Key && p.Value == newAttr.Value);
|
||||||
|
Assert.Equal(1, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ValidateFilters(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId, SplitId? splitId, ulong length)
|
private async Task ValidateFilters(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId, SplitId? splitId, ulong length)
|
||||||
{
|
{
|
||||||
|
@ -338,7 +367,6 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
|
||||||
Assert.Null(objHeader.Split);
|
Assert.Null(objHeader.Split);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static async Task<FrostFsObjectId> CreateObjectServerCut(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes)
|
private static async Task<FrostFsObjectId> CreateObjectServerCut(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes)
|
||||||
{
|
{
|
||||||
var header = new FrostFsObjectHeader(
|
var header = new FrostFsObjectHeader(
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class ContainerTest : ContainerTestsBase
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(1, "test", 0, 0)]
|
[InlineData(1, "test", 0, 0)]
|
||||||
|
|
||||||
public void ReplicaToMessagelTest(int count, string selector, uint ecDataCount, uint ecParityCount)
|
public void ReplicaToMessagelTest(uint count, string selector, uint ecDataCount, uint ecParityCount)
|
||||||
{
|
{
|
||||||
FrostFsReplica replica = new()
|
FrostFsReplica replica = new()
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@ public class ContainerTest : ContainerTestsBase
|
||||||
|
|
||||||
Replica message = replica.ToMessage();
|
Replica message = replica.ToMessage();
|
||||||
|
|
||||||
Assert.Equal((uint)count, message.Count);
|
Assert.Equal(count, message.Count);
|
||||||
Assert.Equal(selector, message.Selector);
|
Assert.Equal(selector, message.Selector);
|
||||||
Assert.Equal(ecDataCount, message.EcDataCount);
|
Assert.Equal(ecDataCount, message.EcDataCount);
|
||||||
Assert.Equal(ecParityCount, message.EcParityCount);
|
Assert.Equal(ecParityCount, message.EcParityCount);
|
||||||
|
|
|
@ -69,13 +69,13 @@ public class PlacementPolicyTests : NetworkTestsBase
|
||||||
var rep0 = result.Replicas[0];
|
var rep0 = result.Replicas[0];
|
||||||
Assert.Equal(2u, rep0.EcDataCount);
|
Assert.Equal(2u, rep0.EcDataCount);
|
||||||
Assert.Equal(3u, rep0.EcParityCount);
|
Assert.Equal(3u, rep0.EcParityCount);
|
||||||
Assert.Equal(4, rep0.Count);
|
Assert.Equal(4u, rep0.Count);
|
||||||
Assert.Equal("selector1", rep0.Selector);
|
Assert.Equal("selector1", rep0.Selector);
|
||||||
|
|
||||||
var rep1 = result.Replicas[1];
|
var rep1 = result.Replicas[1];
|
||||||
Assert.Equal(5u, rep1.EcDataCount);
|
Assert.Equal(5u, rep1.EcDataCount);
|
||||||
Assert.Equal(6u, rep1.EcParityCount);
|
Assert.Equal(6u, rep1.EcParityCount);
|
||||||
Assert.Equal(7, rep1.Count);
|
Assert.Equal(7u, rep1.Count);
|
||||||
Assert.Equal("selector2", rep1.Selector);
|
Assert.Equal("selector2", rep1.Selector);
|
||||||
|
|
||||||
var f0 = result.Filters[0];
|
var f0 = result.Filters[0];
|
||||||
|
@ -126,7 +126,7 @@ public class PlacementPolicyTests : NetworkTestsBase
|
||||||
|
|
||||||
FrostFsReplica model = replica.ToModel();
|
FrostFsReplica model = replica.ToModel();
|
||||||
|
|
||||||
Assert.Equal(count, (uint)model.Count);
|
Assert.Equal(count, model.Count);
|
||||||
Assert.Equal(selector, model.Selector);
|
Assert.Equal(selector, model.Selector);
|
||||||
Assert.Equal(ecDataCount, model.EcDataCount);
|
Assert.Equal(ecDataCount, model.EcDataCount);
|
||||||
Assert.Equal(ecParityCount, model.EcParityCount);
|
Assert.Equal(ecParityCount, model.EcParityCount);
|
||||||
|
@ -140,7 +140,7 @@ public class PlacementPolicyTests : NetworkTestsBase
|
||||||
[InlineData(1, " ", 2, 3)]
|
[InlineData(1, " ", 2, 3)]
|
||||||
[InlineData(10, "!", 0, 0)]
|
[InlineData(10, "!", 0, 0)]
|
||||||
[InlineData(1, "123", 0, 0)]
|
[InlineData(1, "123", 0, 0)]
|
||||||
public void ReplicaToMessagelTest(int count, string selector, uint ecDataCount, uint ecParityCount)
|
public void ReplicaToMessagelTest(uint count, string selector, uint ecDataCount, uint ecParityCount)
|
||||||
{
|
{
|
||||||
FrostFsReplica replica = new ()
|
FrostFsReplica replica = new ()
|
||||||
{
|
{
|
||||||
|
@ -152,7 +152,7 @@ public class PlacementPolicyTests : NetworkTestsBase
|
||||||
|
|
||||||
Replica message = replica.ToMessage();
|
Replica message = replica.ToMessage();
|
||||||
|
|
||||||
Assert.Equal((uint)count, message.Count);
|
Assert.Equal(count, message.Count);
|
||||||
Assert.Equal(selector, message.Selector);
|
Assert.Equal(selector, message.Selector);
|
||||||
Assert.Equal(ecDataCount, message.EcDataCount);
|
Assert.Equal(ecDataCount, message.EcDataCount);
|
||||||
Assert.Equal(ecParityCount, message.EcParityCount);
|
Assert.Equal(ecParityCount, message.EcParityCount);
|
||||||
|
@ -235,11 +235,11 @@ public class PlacementPolicyTests : NetworkTestsBase
|
||||||
|
|
||||||
Assert.Single(message.Filters);
|
Assert.Single(message.Filters);
|
||||||
|
|
||||||
var subfilter = message.Filters[0];
|
var grpcFilter = message.Filters[0];
|
||||||
Assert.Equal(name, subfilter.Name);
|
Assert.Equal(name, grpcFilter.Name);
|
||||||
Assert.Equal(key, subfilter.Key);
|
Assert.Equal(key, grpcFilter.Key);
|
||||||
Assert.Equal(operation, (int)subfilter.Op);
|
Assert.Equal(operation, (int)grpcFilter.Op);
|
||||||
Assert.Equal(value, subfilter.Value);
|
Assert.Equal(value, grpcFilter.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -265,11 +265,11 @@ public class PlacementPolicyTests : NetworkTestsBase
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
var subfilter = message.Filters[i];
|
var grpcFilter = message.Filters[i];
|
||||||
Assert.Equal(names[i], subfilter.Name);
|
Assert.Equal(names[i], grpcFilter.Name);
|
||||||
Assert.Equal(keys[i], subfilter.Key);
|
Assert.Equal(keys[i], grpcFilter.Key);
|
||||||
Assert.Equal(operations[i], (int)subfilter.Op);
|
Assert.Equal(operations[i], (int)grpcFilter.Op);
|
||||||
Assert.Equal(values[i], subfilter.Value);
|
Assert.Equal(values[i], grpcFilter.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -248,12 +248,12 @@ public class FilterDto
|
||||||
Key ?? string.Empty,
|
Key ?? string.Empty,
|
||||||
(int)Op,
|
(int)Op,
|
||||||
Value ?? string.Empty,
|
Value ?? string.Empty,
|
||||||
Filters != null ? Filters.Select(f => f.Filter).ToArray() : []);
|
Filters != null ? [.. Filters.Select(f => f.Filter)] : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReplicaDto
|
public class ReplicaDto
|
||||||
{
|
{
|
||||||
public int Count { get; set; }
|
public uint Count { get; set; }
|
||||||
|
|
||||||
public string? Selector { get; set; }
|
public string? Selector { get; set; }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue