Skip to content

Commit

Permalink
Adds return values for PutObjectAsync api (#731)
Browse files Browse the repository at this point in the history
  • Loading branch information
ebozduman committed Apr 18, 2023
1 parent 91dc25e commit a53bbc3
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 25 deletions.
7 changes: 5 additions & 2 deletions Minio.Functional.Tests/FunctionalTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3226,6 +3226,7 @@ internal static async Task PutObject_Test1(MinioClient minio)
var bucketName = GetRandomName(15);
var objectName = GetRandomObjectName(10);
var contentType = "application/octet-stream";
var size = 1 * MB;
var args = new Dictionary<string, string>
{
{ "bucketName", bucketName },
Expand All @@ -3236,8 +3237,10 @@ internal static async Task PutObject_Test1(MinioClient minio)
try
{
await Setup_Test(minio, bucketName).ConfigureAwait(false);
await PutObject_Tester(minio, bucketName, objectName, null, contentType, 0, null,
rsg.GenerateStreamFromSeed(1 * MB)).ConfigureAwait(false);
var resp = await PutObject_Tester(minio, bucketName, objectName, null, contentType, 0, null,
rsg.GenerateStreamFromSeed(size)).ConfigureAwait(false);
Assert.AreEqual(size, resp.Size);
Assert.AreEqual(objectName, objectName);
new MintLogger(nameof(PutObject_Test1), putObjectSignature,
"Tests whether PutObject passes for small object", TestStatus.PASS, DateTime.Now - startTime,
args: args).Log();
Expand Down
2 changes: 1 addition & 1 deletion Minio/ApiEndpoints/IObjectOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public interface IObjectOperations
/// <exception cref="NotSupportedException">The file stream cannot be read from</exception>
/// <exception cref="InvalidOperationException">The file stream is currently in a read operation</exception>
/// <exception cref="AccessDeniedException">For encrypted PUT operation, Access is denied if the key is wrong</exception>
Task PutObjectAsync(PutObjectArgs args, CancellationToken cancellationToken = default);
Task<PutObjectResponse> PutObjectAsync(PutObjectArgs args, CancellationToken cancellationToken = default);

/// <summary>
/// Select an object's content. The object will be streamed to the callback given by the user.
Expand Down
26 changes: 17 additions & 9 deletions Minio/ApiEndpoints/ObjectOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,8 @@ await ExecuteTaskAsync(NoErrorHandlers, requestMessageBuilder, cancellationToken
/// <exception cref="NotSupportedException">The file stream cannot be read from</exception>
/// <exception cref="InvalidOperationException">The file stream is currently in a read operation</exception>
/// <exception cref="AccessDeniedException">For encrypted PUT operation, Access is denied if the key is wrong</exception>
public async Task PutObjectAsync(PutObjectArgs args, CancellationToken cancellationToken = default)
public async Task<PutObjectResponse> PutObjectAsync(PutObjectArgs args,
CancellationToken cancellationToken = default)
{
args?.Validate();
args.SSE?.Marshal(args.Headers);
Expand All @@ -572,8 +573,7 @@ public async Task PutObjectAsync(PutObjectArgs args, CancellationToken cancellat
args = args.WithRequestBody(bytes)
.WithStreamData(null)
.WithObjectSize(bytesRead);
await PutObjectSinglePartAsync(args, cancellationToken).ConfigureAwait(false);
return;
return await PutObjectSinglePartAsync(args, cancellationToken).ConfigureAwait(false);
}

// For all sizes greater than 5MiB do multipart.
Expand Down Expand Up @@ -622,7 +622,10 @@ public async Task PutObjectAsync(PutObjectArgs args, CancellationToken cancellat
.WithObject(args.ObjectName)
.WithUploadId(uploadId)
.WithETags(etags);
await CompleteMultipartUploadAsync(completeMultipartUploadArgs, cancellationToken).ConfigureAwait(false);
var putObjectResponse = await CompleteMultipartUploadAsync(completeMultipartUploadArgs, cancellationToken)
.ConfigureAwait(false);
putObjectResponse.Size = args.ObjectSize;
return putObjectResponse;
}

/// <summary>
Expand Down Expand Up @@ -812,16 +815,16 @@ await ExecuteTaskAsync(NoErrorHandlers, requestMessageBuilder, cancellationToken
/// <exception cref="NotSupportedException">The file stream cannot be read from</exception>
/// <exception cref="InvalidOperationException">The file stream is currently in a read operation</exception>
/// <exception cref="AccessDeniedException">For encrypted PUT operation, Access is denied if the key is wrong</exception>
private async Task<string> PutObjectSinglePartAsync(PutObjectArgs args,
private async Task<PutObjectResponse> PutObjectSinglePartAsync(PutObjectArgs args,
CancellationToken cancellationToken = default)
{
//Skipping validate as we need the case where stream sends 0 bytes
var requestMessageBuilder = await CreateRequest(args).ConfigureAwait(false);
using var response =
await ExecuteTaskAsync(NoErrorHandlers, requestMessageBuilder, cancellationToken: cancellationToken)
.ConfigureAwait(false);
var putObjectResponse = new PutObjectResponse(response.StatusCode, response.Content, response.Headers);
return putObjectResponse.Etag;
return new PutObjectResponse(response.StatusCode, response.Content, response.Headers,
args.ObjectSize, args.ObjectName);
}

/// <summary>
Expand Down Expand Up @@ -861,7 +864,10 @@ await ExecuteTaskAsync(NoErrorHandlers, requestMessageBuilder, cancellationToken
.WithRequestBody(dataToCopy)
.WithUploadId(args.UploadId)
.WithPartNumber(partNumber);
var etag = await PutObjectSinglePartAsync(putObjectArgs, cancellationToken).ConfigureAwait(false);
var putObjectResponse =
await PutObjectSinglePartAsync(putObjectArgs, cancellationToken).ConfigureAwait(false);
var etag = putObjectResponse.Etag;

numPartsUploaded++;
totalParts[partNumber - 1] = new Part
{ PartNumber = partNumber, ETag = etag, Size = (long)expectedReadSize };
Expand Down Expand Up @@ -1048,14 +1054,16 @@ await ExecuteTaskAsync(NoErrorHandlers, requestMessageBuilder, cancellationToken
/// <exception cref="BucketNotFoundException">When bucket is not found</exception>
/// <exception cref="ObjectNotFoundException">When object is not found</exception>
/// <exception cref="AccessDeniedException">For encrypted copy operation, Access is denied if the key is wrong</exception>
private async Task CompleteMultipartUploadAsync(CompleteMultipartUploadArgs args,
private async Task<PutObjectResponse> CompleteMultipartUploadAsync(CompleteMultipartUploadArgs args,
CancellationToken cancellationToken)
{
args?.Validate();
var requestMessageBuilder = await CreateRequest(args).ConfigureAwait(false);
using var response =
await ExecuteTaskAsync(NoErrorHandlers, requestMessageBuilder, cancellationToken: cancellationToken)
.ConfigureAwait(false);
return new PutObjectResponse(response.StatusCode, response.Content, response.Headers, -1,
args.ObjectName);
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion Minio/DataModel/MinioClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public interface IMinioClient : IDisposable
Task<(Uri, IDictionary<string, string>)> PresignedPostPolicyAsync(PostPolicy policy);
Task<(Uri, IDictionary<string, string>)> PresignedPostPolicyAsync(PresignedPostPolicyArgs args);
Task<string> PresignedPutObjectAsync(PresignedPutObjectArgs args);
Task PutObjectAsync(PutObjectArgs args, CancellationToken cancellationToken = default);
Task<PutObjectResponse> PutObjectAsync(PutObjectArgs args, CancellationToken cancellationToken = default);

Task RemoveAllBucketNotificationsAsync(RemoveAllBucketNotificationsArgs args,
CancellationToken cancellationToken = default);
Expand Down
22 changes: 10 additions & 12 deletions Minio/DataModel/ObjectOperationsResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,26 +192,24 @@ internal NewMultipartUploadResponse(HttpStatusCode statusCode, string responseCo
internal string UploadId { get; }
}

internal class PutObjectResponse : GenericResponse
public class PutObjectResponse : GenericResponse
{
internal string Etag;
public string Etag;
public string ObjectName;
public long Size;

internal PutObjectResponse(HttpStatusCode statusCode, string responseContent,
IDictionary<string, string> responseHeaders)
public PutObjectResponse(HttpStatusCode statusCode, string responseContent,
IDictionary<string, string> responseHeaders, long size, string name)
: base(statusCode, responseContent)
{
if (responseHeaders.ContainsKey("Etag"))
{
if (!string.IsNullOrEmpty("Etag"))
Etag = responseHeaders["ETag"];
return;
}

foreach (var parameter in responseHeaders)
if (parameter.Key.Equals("ETag", StringComparison.OrdinalIgnoreCase))
{
Etag = parameter.Value;
return;
break;
}

Size = size;
ObjectName = name;
}
}

0 comments on commit a53bbc3

Please sign in to comment.