[#3] Move to netstandard 2.0
Signed-off-by: Pavel Gross <p.gross@yadro.com>
This commit is contained in:
parent
ae3fc419a4
commit
0c4723c705
55 changed files with 2508 additions and 1818 deletions
|
@ -1,11 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Google.Protobuf;
|
||||
|
||||
using FrostFS.Object;
|
||||
using FrostFS.Refs;
|
||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.Session;
|
||||
using Google.Protobuf;
|
||||
using Grpc.Core;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2;
|
||||
|
||||
|
@ -15,19 +20,21 @@ public partial class Client
|
|||
{
|
||||
var request = new HeadRequest
|
||||
{
|
||||
Body = new HeadRequest.Types.Body
|
||||
Body = new HeadRequest.Types.Body
|
||||
{
|
||||
Address = new Address
|
||||
{
|
||||
ContainerId = cid.ToGrpcMessage(),
|
||||
ObjectId = oid.ToGrpcMessage()
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
request.AddMetaHeader();
|
||||
request.Sign(_key);
|
||||
var response = await _objectServiceClient.HeadAsync(request);
|
||||
Verifier.CheckResponse(response);
|
||||
|
||||
return response.Body.Header.Header.ToModel();
|
||||
}
|
||||
|
||||
|
@ -43,9 +50,10 @@ public partial class Client
|
|||
{
|
||||
ContainerId = cid.ToGrpcMessage(),
|
||||
ObjectId = oid.ToGrpcMessage()
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.AddMetaHeader();
|
||||
request.AddObjectSessionToken(
|
||||
sessionToken,
|
||||
|
@ -54,43 +62,13 @@ public partial class Client
|
|||
ObjectSessionContext.Types.Verb.Get,
|
||||
_key
|
||||
);
|
||||
|
||||
request.Sign(_key);
|
||||
|
||||
var obj = await GetObject(request);
|
||||
|
||||
return obj.ToModel();
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
var chunk = await stream.ReadChunk();
|
||||
while (chunk is not null)
|
||||
{
|
||||
chunk.CopyTo(payload, offset);
|
||||
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)
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<ObjectId> PutObjectAsync(ObjectHeader header, Stream payload)
|
||||
{
|
||||
return await PutObject(header, payload);
|
||||
|
@ -100,74 +78,12 @@ public partial class Client
|
|||
{
|
||||
return await PutObject(header, new MemoryStream(payload));
|
||||
}
|
||||
|
||||
private async Task<ObjectId> PutObject(ObjectHeader header, Stream payload)
|
||||
{
|
||||
var sessionToken = await CreateSessionAsync(uint.MaxValue);
|
||||
var hdr = header.ToGrpcMessage();
|
||||
hdr.OwnerId = OwnerId.ToGrpcMessage();
|
||||
hdr.Version = Version.ToGrpcMessage();
|
||||
var oid = new ObjectID
|
||||
{
|
||||
Value = hdr.Sha256()
|
||||
};
|
||||
var request = new PutRequest
|
||||
{
|
||||
Body = new PutRequest.Types.Body
|
||||
{
|
||||
Init = new PutRequest.Types.Body.Types.Init
|
||||
{
|
||||
Header = hdr
|
||||
},
|
||||
}
|
||||
};
|
||||
request.AddMetaHeader();
|
||||
request.AddObjectSessionToken(
|
||||
sessionToken,
|
||||
hdr.ContainerId,
|
||||
oid,
|
||||
ObjectSessionContext.Types.Verb.Put,
|
||||
_key
|
||||
);
|
||||
request.Sign(_key);
|
||||
|
||||
using var stream = await PutObjectInit(request);
|
||||
var buffer = new byte[Constants.ObjectChunkSize];
|
||||
var bufferLength = await payload.ReadAsync(buffer.AsMemory(0, Constants.ObjectChunkSize));
|
||||
while (bufferLength > 0)
|
||||
{
|
||||
request.Body = new PutRequest.Types.Body
|
||||
{
|
||||
Chunk = ByteString.CopyFrom(buffer[..bufferLength]),
|
||||
};
|
||||
request.VerifyHeader = null;
|
||||
request.Sign(_key);
|
||||
await stream.Write(request);
|
||||
bufferLength = await payload.ReadAsync(buffer.AsMemory(0, Constants.ObjectChunkSize));
|
||||
}
|
||||
|
||||
var response = await stream.Close();
|
||||
Verifier.CheckResponse(response);
|
||||
return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray());
|
||||
}
|
||||
|
||||
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 = call };
|
||||
}
|
||||
|
||||
public async Task DeleteObjectAsync(ContainerId cid, ObjectId oid)
|
||||
{
|
||||
var request = new DeleteRequest
|
||||
{
|
||||
Body = new DeleteRequest.Types.Body
|
||||
Body = new DeleteRequest.Types.Body
|
||||
{
|
||||
Address = new Address
|
||||
{
|
||||
|
@ -176,6 +92,7 @@ public partial class Client
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.AddMetaHeader();
|
||||
request.Sign(_key);
|
||||
var response = await _objectServiceClient.DeleteAsync(request);
|
||||
|
@ -193,24 +110,125 @@ public partial class Client
|
|||
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 = 0;
|
||||
var chunk = await stream.ReadChunk();
|
||||
|
||||
while (chunk is not null)
|
||||
{
|
||||
chunk.CopyTo(payload, offset);
|
||||
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<ObjectId> PutObject(ObjectHeader header, Stream payload)
|
||||
{
|
||||
var sessionToken = await CreateSessionAsync(uint.MaxValue);
|
||||
var hdr = header.ToGrpcMessage();
|
||||
hdr.OwnerId = OwnerId.ToGrpcMessage();
|
||||
hdr.Version = Version.ToGrpcMessage();
|
||||
|
||||
var oid = new ObjectID
|
||||
{
|
||||
Value = hdr.Sha256()
|
||||
};
|
||||
|
||||
var request = new PutRequest
|
||||
{
|
||||
Body = new PutRequest.Types.Body
|
||||
{
|
||||
Init = new PutRequest.Types.Body.Types.Init
|
||||
{
|
||||
Header = hdr
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
request.AddMetaHeader();
|
||||
request.AddObjectSessionToken(
|
||||
sessionToken,
|
||||
hdr.ContainerId,
|
||||
oid,
|
||||
ObjectSessionContext.Types.Verb.Put,
|
||||
_key
|
||||
);
|
||||
|
||||
request.Sign(_key);
|
||||
|
||||
using var stream = await PutObjectInit(request);
|
||||
var buffer = new byte[Constants.ObjectChunkSize];
|
||||
var bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize);
|
||||
|
||||
while (bufferLength > 0)
|
||||
{
|
||||
request.Body = new PutRequest.Types.Body
|
||||
{
|
||||
Chunk = ByteString.CopyFrom(buffer[..bufferLength]),
|
||||
};
|
||||
request.VerifyHeader = null;
|
||||
request.Sign(_key);
|
||||
await stream.Write(request);
|
||||
bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize);
|
||||
}
|
||||
|
||||
var response = await stream.Close();
|
||||
Verifier.CheckResponse(response);
|
||||
|
||||
return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray());
|
||||
}
|
||||
|
||||
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 = SearchObjectsInit(request);
|
||||
using var stream = GetSearchReader(request);
|
||||
var ids = await stream.Read();
|
||||
while (ids is not null)
|
||||
{
|
||||
|
@ -218,110 +236,18 @@ public partial class Client
|
|||
{
|
||||
yield return oid;
|
||||
}
|
||||
|
||||
ids = await stream.Read();
|
||||
}
|
||||
}
|
||||
|
||||
private SearchReader SearchObjectsInit(SearchRequest initRequest)
|
||||
private SearchReader GetSearchReader(SearchRequest initRequest)
|
||||
{
|
||||
if (initRequest is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(initRequest));
|
||||
}
|
||||
|
||||
return new SearchReader
|
||||
{
|
||||
Call = _objectServiceClient.Search(initRequest)
|
||||
};
|
||||
return new SearchReader(_objectServiceClient.Search(initRequest));
|
||||
}
|
||||
}
|
||||
|
||||
internal class ObjectReader : IDisposable
|
||||
{
|
||||
public AsyncServerStreamingCall<GetResponse> Call { get; init; }
|
||||
|
||||
public async Task<Object.Object> ReadHeader()
|
||||
{
|
||||
if (!await Call.ResponseStream.MoveNext())
|
||||
{
|
||||
throw new InvalidOperationException("unexpect end of stream");
|
||||
}
|
||||
|
||||
var response = Call.ResponseStream.Current;
|
||||
Verifier.CheckResponse(response);
|
||||
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init)
|
||||
throw new InvalidOperationException("unexpect message type");
|
||||
return new Object.Object
|
||||
{
|
||||
ObjectId = response.Body.Init.ObjectId,
|
||||
Header = response.Body.Init.Header,
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<byte[]?> ReadChunk()
|
||||
{
|
||||
if (!await Call.ResponseStream.MoveNext())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var response = Call.ResponseStream.Current;
|
||||
Verifier.CheckResponse(response);
|
||||
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk)
|
||||
throw new InvalidOperationException("unexpect message type");
|
||||
return response.Body.Chunk.ToByteArray();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Call.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal class ObjectStreamer : IDisposable
|
||||
{
|
||||
public AsyncClientStreamingCall<PutRequest, PutResponse> Call { get; init; }
|
||||
|
||||
public async Task Write(PutRequest request)
|
||||
{
|
||||
if (request is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
await Call.RequestStream.WriteAsync(request);
|
||||
}
|
||||
|
||||
public async Task<PutResponse> Close()
|
||||
{
|
||||
await Call.RequestStream.CompleteAsync();
|
||||
return await Call.ResponseAsync;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Call.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal class SearchReader : IDisposable
|
||||
{
|
||||
public AsyncServerStreamingCall<SearchResponse> Call { get; init; }
|
||||
|
||||
public async Task<List<ObjectID>?> Read()
|
||||
{
|
||||
if (!await Call.ResponseStream.MoveNext())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var response = Call.ResponseStream.Current;
|
||||
Verifier.CheckResponse(response);
|
||||
return response.Body?.IdList.ToList();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Call.Dispose();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue