[#1] Add object mappers

Signed-off-by: Ivan Pchelintsev <i.pchelintsev@yadro.com>
This commit is contained in:
Ivan Pchelintsev 2024-05-16 12:26:32 +03:00
parent 0d83541d82
commit 6b8f8cbd4c
7 changed files with 76 additions and 46 deletions

View file

@ -14,6 +14,6 @@ public interface IFrostFSClient
Task<GetResponse> GetContainerAsync(ContainerID containerId); Task<GetResponse> GetContainerAsync(ContainerID containerId);
Task<DeleteResponse> DeleteContainerAsync(ContainerID containerId); Task<DeleteResponse> DeleteContainerAsync(ContainerID containerId);
Task<HeadResponse> GetObjectHeadAsync(ContainerID containerId, ObjectID objectId); Task<HeadResponse> GetObjectHeadAsync(ContainerID containerId, ObjectID objectId);
Task<Object.PutResponse> PutObjectAsync(ContainerID containerId, Stream data); Task<Object.PutResponse> PutObjectAsync(Object.Header header, Stream payload);
Task<Object.DeleteResponse> DeleteObjectAsync(ContainerID containerId, ObjectID objectId); Task<Object.DeleteResponse> DeleteObjectAsync(ContainerID containerId, ObjectID objectId);
} }

View file

@ -4,15 +4,35 @@ using FrostFS.SDK.ModelsV2;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC; namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class ObjectHeadMapper public static class ObjectHeadMapper
{ {
public static ObjectHead ToModel(this Header head) public static Header ToGrpcMessage(this ObjectHeader header)
{ {
// var obtype = Enum.Parse<ObjectType>(head.ObjectType.ToString()); var objTypeName = Enum.GetName(typeof(ObjectType), header.ObjectType);
return new ObjectHead if (objTypeName is null)
{ {
ContainerId = ContainerId.FromHash(head.ContainerId.Value.ToByteArray()), throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.");
Size = (long)head.PayloadLength, }
Version = head.Version.ToModel() return new Header
{
ContainerId = header.ContainerId.ToGrpcMessage(),
ObjectType = Enum.Parse<ObjectType>(objTypeName)
}; };
} }
}
public static ObjectHeader ToModel(this Header header)
{
var objTypeName = Enum.GetName(typeof(ModelsV2.Enums.ObjectType), header.ObjectType);
if (objTypeName is null)
{
throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.");
}
return new ObjectHeader(
ContainerId.FromHash(header.ContainerId.Value.ToByteArray()),
Enum.Parse<ModelsV2.Enums.ObjectType>(objTypeName)
)
{
Size = (long)header.PayloadLength,
Version = header.Version.ToModel()
};
}
}

View file

@ -29,15 +29,16 @@ public partial class Client
return await _objectServiceClient.HeadAsync(request); return await _objectServiceClient.HeadAsync(request);
} }
public async Task<PutResponse> PutObjectAsync(ContainerID cid, Stream data) // public async Task<GetResponse> GetObjectAsync(ContainerID cid, ObjectID oid)
// {
//
// }
public async Task<PutResponse> PutObjectAsync(Header header, Stream payload)
{ {
var sessionToken = await CreateSessionAsync(uint.MaxValue); var sessionToken = await CreateSessionAsync(uint.MaxValue);
var header = new Header header.OwnerId = _owner.ToGrpcMessage();
{ header.Version = Version.ToGrpcMessage();
ContainerId = cid,
OwnerId = _owner.ToGrpcMessage(),
Version = Version.ToGrpcMessage()
};
var oid = new ObjectID var oid = new ObjectID
{ {
Value = header.Sha256() Value = header.Sha256()
@ -48,17 +49,23 @@ public partial class Client
{ {
Init = new PutRequest.Types.Body.Types.Init Init = new PutRequest.Types.Body.Types.Init
{ {
Header = header, Header = header
}, },
} }
}; };
request.AddMetaHeader(); request.AddMetaHeader();
request.AddObjectSessionToken(sessionToken, cid, oid, ObjectSessionContext.Types.Verb.Put, _key); request.AddObjectSessionToken(
sessionToken,
header.ContainerId,
oid,
ObjectSessionContext.Types.Verb.Put,
_key
);
request.Sign(_key); request.Sign(_key);
using var stream = await InitObject(request); using var stream = await InitObject(request);
var buffer = new byte[Constants.ObjectChunkSize]; var buffer = new byte[Constants.ObjectChunkSize];
var bufferLength = data.Read(buffer, 0, Constants.ObjectChunkSize); var bufferLength = payload.Read(buffer, 0, Constants.ObjectChunkSize);
while (bufferLength > 0) while (bufferLength > 0)
{ {
request.Body = new PutRequest.Types.Body request.Body = new PutRequest.Types.Body
@ -68,22 +75,24 @@ public partial class Client
request.VerifyHeader = null; request.VerifyHeader = null;
request.Sign(_key); request.Sign(_key);
await stream.Write(request); await stream.Write(request);
bufferLength = data.Read(buffer, 0, Constants.ObjectChunkSize); bufferLength = payload.Read(buffer, 0, Constants.ObjectChunkSize);
} }
return await stream.Close(); return await stream.Close();
} }
private async Task<ObjectStreamer> InitObject(PutRequest initRequest) private async Task<ObjectStreamer> InitObject(PutRequest initRequest)
{ {
if (initRequest is null) if (initRequest is null)
{ {
throw new ArgumentNullException(nameof(initRequest)); throw new ArgumentNullException(nameof(initRequest));
} }
var call = _objectServiceClient.Put(); var call = _objectServiceClient.Put();
await call.RequestStream.WriteAsync(initRequest); await call.RequestStream.WriteAsync(initRequest);
return new ObjectStreamer { Call = call }; return new ObjectStreamer { Call = call };
} }
public async Task<DeleteResponse> DeleteObjectAsync(ContainerID cid, ObjectID oid) public async Task<DeleteResponse> DeleteObjectAsync(ContainerID cid, ObjectID oid)
{ {
var request = new DeleteRequest var request = new DeleteRequest
@ -118,7 +127,7 @@ internal class ObjectStreamer : IDisposable
{ {
throw new ArgumentNullException(nameof(request)); throw new ArgumentNullException(nameof(request));
} }
await Call.RequestStream.WriteAsync(request); await Call.RequestStream.WriteAsync(request);
} }

View file

@ -8,7 +8,7 @@ public class Container
public Guid Nonce { get; set; } public Guid Nonce { get; set; }
public BasicACL BasicAcl { get; set; } public BasicACL BasicAcl { get; set; }
public PlacementPolicy PlacementPolicy { get; set; } public PlacementPolicy PlacementPolicy { get; set; }
public Version? Version { get; set; } public Version Version { get; set; }
public Container(BasicACL basicAcl, PlacementPolicy placementPolicy) public Container(BasicACL basicAcl, PlacementPolicy placementPolicy)
{ {

View file

@ -2,7 +2,7 @@ namespace FrostFS.SDK.ModelsV2.Enums;
public enum ObjectType public enum ObjectType
{ {
Regular = 1, Regular = 0,
Tombstone = 2, Tombstone = 1,
Lock = 3 Lock = 3
} }

View file

@ -1,28 +1,23 @@
using FrostFS.SDK.ModelsV2.Enums;
namespace FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ModelsV2;
public class ObjectHead public class ObjectHeader
{ {
public ContainerId ContainerId { get; set; } public ContainerId ContainerId { get; set; }
public long Size { get; set; } public long Size { get; set; }
public Version? Version { get; set; } public ObjectType ObjectType { get; set; }
public Version Version { get; set; }
public ObjectHeader(ContainerId containerId, ObjectType type = ObjectType.Regular)
{
ContainerId = containerId;
ObjectType = type;
}
} }
public class Object : ObjectHead public class Object
{ {
public ObjectHeader Header { get; set; }
public Stream Payload { get; set; } public Stream Payload { get; set; }
public Object(ContainerId containerId, Stream payload)
{
ContainerId = containerId;
Payload = payload;
Size = Payload.Length;
}
public Object(ContainerId containerId, byte[] payload)
{
ContainerId = containerId;
Payload = new MemoryStream(payload);
Size = Payload.Length;
}
} }

View file

@ -43,7 +43,7 @@ public class FrostFsService
var deleteContainerResponse = await _client.DeleteContainerAsync(containerId.ToGrpcMessage()); var deleteContainerResponse = await _client.DeleteContainerAsync(containerId.ToGrpcMessage());
} }
public async Task<ObjectHead> GetObjectHeadAsync(ContainerId containerId, ObjectId objectId) public async Task<ObjectHeader> GetObjectHeadAsync(ContainerId containerId, ObjectId objectId)
{ {
var getObjectHeadResponse = await _client.GetObjectHeadAsync( var getObjectHeadResponse = await _client.GetObjectHeadAsync(
containerId.ToGrpcMessage(), containerId.ToGrpcMessage(),
@ -52,9 +52,15 @@ public class FrostFsService
return getObjectHeadResponse.Body.Header.Header.ToModel(); return getObjectHeadResponse.Body.Header.Header.ToModel();
} }
public async Task<ObjectId> PutObjectAsync(ModelsV2.Object obj) public async Task<ObjectId> PutObjectAsync(ObjectHeader header, Stream payload)
{ {
var putObjectResponse = await _client.PutObjectAsync(obj.ContainerId.ToGrpcMessage(), obj.Payload); var putObjectResponse = await _client.PutObjectAsync(header.ToGrpcMessage(), payload);
return ObjectId.FromHash(putObjectResponse.Body.ObjectId.Value.ToByteArray());
}
public async Task<ObjectId> PutObjectAsync(ObjectHeader header, byte[] payload)
{
var putObjectResponse = await _client.PutObjectAsync(header.ToGrpcMessage(), new MemoryStream(payload));
return ObjectId.FromHash(putObjectResponse.Body.ObjectId.Value.ToByteArray()); return ObjectId.FromHash(putObjectResponse.Body.ObjectId.Value.ToByteArray());
} }