Skip to content

Commit 4128795

Browse files
Fix getblocks long (Azure#19078)
* INCOMPLETE: retire int block size; introduce long Regenerated with new swagger to present block size on a GetBlocks call as long instead of int, while preserving backwards compatibility. Currently build error CS0282 due to a mix of generated and handwritten properties. * Updated autorest swagger pointer * Fixed build error Moved all BlobBlock properties into handwritten partial file to avoid compile error CS0282. * Ignore multi GB test * ModelFactory support * export api * Fix codegen url * Handled overflow bug * disabled long test due to timeout * fixed broken url; regenerated * Changelog Co-authored-by: jschrepp-MSFT <41338290+jschrepp-MSFT@users.noreply.github.com>
1 parent 0341734 commit 4128795

File tree

8 files changed

+92
-13
lines changed

8 files changed

+92
-13
lines changed

sdk/storage/Azure.Storage.Blobs/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Release History
22

33
## 12.9.0-beta.2 (Unreleased)
4-
- Fixed bug where `Stream` returned by `BlockBlobClient.OpenWrite` could corrupt blocks if flushed between writes.
4+
- Fixed a bug where BlockBlobClient.GetBlockList threw when dealing with extremely large blocks.
5+
- Fixed bug where `Stream` returned by `BlockBlobClient.OpenWrite` could corrupt blocks if flushed between writes.
56

67
## 12.9.0-beta.1 (2021-02-09)
78
- Added support for service version 2020-06-12.

sdk/storage/Azure.Storage.Blobs/api/Azure.Storage.Blobs.netstandard2.0.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ internal BlobAppendInfo() { }
290290
private readonly object _dummy;
291291
private readonly int _dummyPrimitive;
292292
public string Name { get { throw null; } }
293+
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
293294
public int Size { get { throw null; } }
295+
public long SizeLong { get { throw null; } }
294296
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
295297
public bool Equals(Azure.Storage.Blobs.Models.BlobBlock other) { throw null; }
296298
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
@@ -839,7 +841,9 @@ public static partial class BlobsModelFactory
839841
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
840842
public static Azure.Storage.Blobs.Models.BlobAppendInfo BlobAppendInfo(Azure.ETag eTag, System.DateTimeOffset lastModified, byte[] contentHash, byte[] contentCrc64, string blobAppendOffset, int blobCommittedBlockCount, bool isServerEncrypted, string encryptionKeySha256) { throw null; }
841843
public static Azure.Storage.Blobs.Models.BlobAppendInfo BlobAppendInfo(Azure.ETag eTag, System.DateTimeOffset lastModified, byte[] contentHash, byte[] contentCrc64, string blobAppendOffset, int blobCommittedBlockCount, bool isServerEncrypted, string encryptionKeySha256, string encryptionScope) { throw null; }
844+
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
842845
public static Azure.Storage.Blobs.Models.BlobBlock BlobBlock(string name, int size) { throw null; }
846+
public static Azure.Storage.Blobs.Models.BlobBlock BlobBlock(string name, long size) { throw null; }
843847
public static Azure.Storage.Blobs.Models.BlobContainerAccessPolicy BlobContainerAccessPolicy(Azure.Storage.Blobs.Models.PublicAccessType blobPublicAccess, Azure.ETag eTag, System.DateTimeOffset lastModified, System.Collections.Generic.IEnumerable<Azure.Storage.Blobs.Models.BlobSignedIdentifier> signedIdentifiers) { throw null; }
844848
public static Azure.Storage.Blobs.Models.BlobContainerInfo BlobContainerInfo(Azure.ETag eTag, System.DateTimeOffset lastModified) { throw null; }
845849
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]

sdk/storage/Azure.Storage.Blobs/src/Generated/Models/BlobBlock.Serialization.cs

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/storage/Azure.Storage.Blobs/src/Generated/Models/BlobBlock.cs

Lines changed: 3 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/storage/Azure.Storage.Blobs/src/Models/BlobBlock.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.ComponentModel;
56
using Azure.Core;
67

78
namespace Azure.Storage.Blobs.Models
@@ -12,6 +13,28 @@ namespace Azure.Storage.Blobs.Models
1213
[CodeGenModel("Block")]
1314
public readonly partial struct BlobBlock : IEquatable<BlobBlock>
1415
{
16+
// All properties are rebuilt by hand in this class to avoid compile error CS0282
17+
18+
/// <summary>
19+
/// The block size in bytes.
20+
/// </summary>
21+
[CodeGenMember("Size")]
22+
public long SizeLong { get; }
23+
24+
/// <summary>
25+
/// This property is a backwards-compatible facade for <see cref="SizeLong"/>,
26+
/// which supports long values. Use <see cref="SizeLong"/> for full access of
27+
/// supported values.
28+
/// </summary>
29+
[EditorBrowsable(EditorBrowsableState.Never)]
30+
public int Size => checked((int)SizeLong);
31+
32+
/// <summary>
33+
/// The base64 encoded block ID.
34+
/// </summary>
35+
[CodeGenMember("Name")]
36+
public string Name { get; }
37+
1538
/// <summary>
1639
/// Check if two BlobBlock instances are equal.
1740
/// </summary>

sdk/storage/Azure.Storage.Blobs/src/Models/BlobsModelFactory.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,12 +1416,23 @@ public static PageBlobInfo PageBlobInfo(
14161416
/// <summary>
14171417
/// Creates a new BlobBlock instance for mocking.
14181418
/// </summary>
1419+
[EditorBrowsable(EditorBrowsableState.Never)]
14191420
public static BlobBlock BlobBlock(
14201421
string name,
14211422
int size)
14221423
{
14231424
return new BlobBlock(name, size);
14241425
}
1426+
1427+
/// <summary>
1428+
/// Creates a new BlobBlock instance for mocking.
1429+
/// </summary>
1430+
public static BlobBlock BlobBlock(
1431+
string name,
1432+
long size)
1433+
{
1434+
return new BlobBlock(name, size);
1435+
}
14251436
#endregion
14261437

14271438
#region BlobGeoReplication

sdk/storage/Azure.Storage.Blobs/src/autorest.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Run `dotnet build /t:GenerateCode` to generate code.
44

55
``` yaml
66
input-file:
7-
- https://raw.githubusercontent.com/Azure/azure-rest-api-specs/011761be1285d14feb41796b5d97df1126495c5c/specification/storage/data-plane/Microsoft.BlobStorage/preview/2020-06-12/blob.json
7+
- https://raw.githubusercontent.com/Azure/azure-rest-api-specs/8c1f9b739165035d9ced32761cebb19125bce233/specification/storage/data-plane/Microsoft.BlobStorage/preview/2020-06-12/blob.json
88
```
99
1010
### Move path parameters to constructor.

sdk/storage/Azure.Storage.Blobs/tests/BlockBlobClientTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Azure.Storage.Test.Shared;
1717
using Moq;
1818
using NUnit.Framework;
19+
using static Azure.Storage.Blobs.BlobClientOptions;
1920
using Metadata = System.Collections.Generic.IDictionary<string, string>;
2021
using Tags = System.Collections.Generic.IDictionary<string, string>;
2122

@@ -1513,6 +1514,50 @@ public async Task GetBlockListAsync()
15131514
Assert.AreEqual(blockId1, response.Value.UncommittedBlocks.First().Name);
15141515
}
15151516

1517+
[Test]
1518+
[LiveOnly]
1519+
[ServiceVersion(Min = ServiceVersion.V2019_12_12)]
1520+
[Ignore("https://github.com/Azure/azure-sdk-for-net/issues/12312")]
1521+
public async Task GetBlockListAsync_LongBlock()
1522+
{
1523+
const long bigBlockSize = int.MaxValue + 1024L;
1524+
await using DisposingContainer test = await GetTestContainerAsync();
1525+
1526+
// Arrange
1527+
BlockBlobClient blob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));
1528+
var data = GetRandomBuffer(Size);
1529+
1530+
// Upload to blockBlobUri, so it exists
1531+
using (var stream = new MemoryStream(data))
1532+
{
1533+
await blob.UploadAsync(stream);
1534+
}
1535+
1536+
var blockId0 = ToBase64(GetNewBlockName());
1537+
using (var stream = new Storage.Tests.Shared.PredictableStream(length: bigBlockSize))
1538+
{
1539+
await blob.StageBlockAsync(blockId0, stream);
1540+
}
1541+
await blob.CommitBlockListAsync(new string[] { blockId0 });
1542+
1543+
var blockId1 = ToBase64(GetNewBlobName());
1544+
using (var stream = new MemoryStream(data))
1545+
{
1546+
await blob.StageBlockAsync(blockId1, stream);
1547+
}
1548+
1549+
// Act
1550+
Response<BlockList> response = await blob.GetBlockListAsync();
1551+
1552+
// Assert
1553+
Assert.AreEqual(1, response.Value.CommittedBlocks.Count());
1554+
Assert.AreEqual(blockId0, response.Value.CommittedBlocks.First().Name);
1555+
Assert.AreEqual(1, response.Value.UncommittedBlocks.Count());
1556+
Assert.AreEqual(blockId1, response.Value.UncommittedBlocks.First().Name);
1557+
Assert.AreEqual(bigBlockSize, response.Value.CommittedBlocks.First().SizeLong);
1558+
Assert.Throws<OverflowException>(() => _ = response.Value.CommittedBlocks.First().Size); // if no overflow then we didn't actually test handling of long lengths
1559+
}
1560+
15161561
[Test]
15171562
public async Task GetBlockListAsync_Type()
15181563
{

0 commit comments

Comments
 (0)