Skip to content

Storage STG99 Features #6622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/storage/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "cpp",
"TagPrefix": "cpp/storage",
"Tag": "cpp/storage_7bea1dff90"
"Tag": "cpp/storage_7f9ca72801"
}
8 changes: 2 additions & 6 deletions sdk/storage/azure-storage-blobs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# Release History

## 12.14.0-beta.2 (Unreleased)
## 12.15.0-beta.1 (2025-06-11)

### Features Added

### Breaking Changes

### Bugs Fixed

### Other Changes
- Added more useful error message when the SDK encounters an x-ms-version mis-match issue.

## 12.14.0-beta.1 (2025-05-13)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2264,4 +2264,20 @@ namespace Azure { namespace Storage { namespace Test {
blobProperties = versionClient.GetProperties().Value;
EXPECT_TRUE(blobProperties.HasLegalHold);
}

TEST_F(BlockBlobClientTest, InvalidVersionMessage)
{
Blobs::BlobClientOptions options;
options.ApiVersion = "3015-11-11";
auto blobClient = GetBlockBlobClientForTest(LowercaseRandomString(), options);
try
{
blobClient.Download();
}
catch (const StorageException& e)
{
EXPECT_EQ(e.ErrorCode, _internal::InvalidHeaderValueErrorCode);
EXPECT_EQ(e.Message, _internal::InvalidVersionHeaderMessage);
}
}
}}} // namespace Azure::Storage::Test
6 changes: 2 additions & 4 deletions sdk/storage/azure-storage-common/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# Release History

## 12.11.0-beta.1 (Unreleased)
## 12.12.0-beta.1 (2025-06-11)

### Features Added

### Breaking Changes

### Bugs Fixed
- Added more useful error message when the SDK encounters an x-ms-version mis-match issue.

### Other Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ namespace Azure { namespace Storage { namespace _internal {
constexpr static const char* HttpHeaderContentType = "content-type";
constexpr static const char* HttpHeaderContentLength = "content-length";
constexpr static const char* HttpHeaderContentRange = "content-range";
constexpr static const char* InvalidHeaderValueErrorCode = "InvalidHeaderValue";
constexpr static const char* InvalidVersionHeaderMessage
= "The provided service version is not enabled on this storage account. Please see "
"https://learn.microsoft.com/rest/api/storageservices/"
"versioning-for-the-azure-storage-services for additional information.";

constexpr int ReliableStreamRetryCount = 3;
}}} // namespace Azure::Storage::_internal
8 changes: 8 additions & 0 deletions sdk/storage/azure-storage-common/src/storage_exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ namespace Azure { namespace Storage {
errorCode = response->GetHeaders().at("x-ms-error-code");
}

// Optimize error messages
const auto headerName = additionalInformation.find("HeaderName");
if (errorCode == _internal::InvalidHeaderValueErrorCode
&& headerName != additionalInformation.end() && headerName->second == "x-ms-version")
{
message = _internal::InvalidVersionHeaderMessage;
}

StorageException result = StorageException(
std::to_string(static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
httpStatusCode))
Expand Down
8 changes: 2 additions & 6 deletions sdk/storage/azure-storage-files-datalake/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# Release History

## 12.13.0-beta.1 (Unreleased)
## 12.13.0-beta.1 (2025-06-11)

### Features Added

### Breaking Changes

### Bugs Fixed

### Other Changes
- Added more useful error message when the SDK encounters an x-ms-version mis-match issue.

## 12.12.0 (2024-09-17)

Expand Down
9 changes: 3 additions & 6 deletions sdk/storage/azure-storage-files-shares/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
# Release History

## 12.14.0-beta.2 (Unreleased)
## 12.15.0-beta.1 (2025-06-11)

### Features Added

### Breaking Changes

### Bugs Fixed

### Other Changes
- `ShareClient::DeleteIfExists()` will return `false` when error code is `ShareSnapshotNotFound`.
- Added more useful error message when the SDK encounters an x-ms-version mis-match issue.

## 12.14.0-beta.1 (2025-05-13)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
constexpr static const char* ResourceNotFound = "ResourceNotFound";
constexpr static const char* ShareAlreadyExists = "ShareAlreadyExists";
constexpr static const char* ShareNotFound = "ShareNotFound";
constexpr static const char* ShareSnapshotNotFound = "ShareSnapshotNotFound";
constexpr static const char* ResourceAlreadyExists = "ResourceAlreadyExists";
} // namespace _detail

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
}
catch (StorageException& e)
{
if (e.ErrorCode == _detail::ShareNotFound)
if (e.ErrorCode == _detail::ShareNotFound || e.ErrorCode == _detail::ShareSnapshotNotFound)
{
Models::DeleteShareResult ret;
ret.Deleted = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ namespace Azure { namespace Storage { namespace Test {
}
}

TEST_F(FileShareClientTest, SnapshotNotFoundErrorCode)
{
auto shareSnapshot = m_shareClient->WithSnapshot("2025-02-04T10:17:47.0000000Z");

Files::Shares::Models::DeleteShareResult deleteResult;
EXPECT_NO_THROW(deleteResult = shareSnapshot.DeleteIfExists().Value);
EXPECT_FALSE(deleteResult.Deleted);
}

TEST_F(FileShareClientTest, ShareMetadata)
{
auto metadata1 = RandomMetadata();
Expand Down
8 changes: 4 additions & 4 deletions sdk/storage/azure-storage-queues/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Release History

## 12.5.0-beta.1 (Unreleased)
## 12.5.0-beta.1 (2025-06-11)

### Features Added

### Breaking Changes
- Added more useful error message when the SDK encounters an x-ms-version mis-match issue.

### Bugs Fixed
### Breaking Changes

### Other Changes
- `QueueProperties.ApproximateMessageCount` is deprecated. The value is `-1` if the value exceeds `INT32_MAX`. Use `QueueProperties.ApproximateMessageCountLong` instead.

## 12.4.0 (2024-09-17)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include "azure/storage/queues/queue_options.hpp"
#include "azure/storage/queues/queue_responses.hpp"

#include <azure/core/credentials/credentials.hpp>
#include <azure/storage/common/storage_credential.hpp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,32 @@ namespace Azure { namespace Storage { namespace Queues {

class QueueServiceClient;

namespace Models {
/**
* @brief Response type for #Azure::Storage::Queues::QueueClient::GetProperties.
*/
struct QueueProperties final
{
/**
* A set of name-value pairs associated with this queue.
*/
Core::CaseInsensitiveMap Metadata;
/**
* The approximate number of messages in the queue. This number is not lower than the actual
* number of messages in the queue, but could be higher.
*
* This field is deprecated. The value is -1 if the value exceeds
* INT32_MAX.Use ApproximateMessageCountLong instead.
*/
std::int32_t ApproximateMessageCount = std::int32_t();
/**
* The approximate number of messages in the queue. This number is not lower than the actual
* number of messages in the queue, but could be higher.
*/
std::int64_t ApproximateMessageCountLong = std::int64_t();
};
} // namespace Models

/**
* @brief Response type for #Azure::Storage::Queues::QueueServiceClient::ListQueues.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,21 +283,23 @@ namespace Azure { namespace Storage { namespace Queues {
*/
bool Deleted = true;
};
/**
* @brief Response type for #Azure::Storage::Queues::QueueClient::GetProperties.
*/
struct QueueProperties final
{
/**
* A set of name-value pairs associated with this queue.
*/
Core::CaseInsensitiveMap Metadata;
namespace _detail {
/**
* The approximate number of messages in the queue. This number is not lower than the actual
* number of messages in the queue, but could be higher.
* @brief Response type for #Azure::Storage::Queues::QueueClient::GetProperties.
*/
std::int32_t ApproximateMessageCount = std::int32_t();
};
struct QueueProperties final
{
/**
* A set of name-value pairs associated with this queue.
*/
Core::CaseInsensitiveMap Metadata;
/**
* The approximate number of messages in the queue. This number is not lower than the actual
* number of messages in the queue, but could be higher.
*/
std::int64_t ApproximateMessageCount = std::int64_t();
};
} // namespace _detail
/**
* @brief Response type for #Azure::Storage::Queues::QueueClient::SetMetadata.
*/
Expand Down Expand Up @@ -554,7 +556,7 @@ namespace Azure { namespace Storage { namespace Queues {
struct GetQueuePropertiesOptions final
{
};
static Response<Models::QueueProperties> GetProperties(
static Response<Models::_detail::QueueProperties> GetProperties(
Core::Http::_internal::HttpPipeline& pipeline,
const Core::Url& url,
const GetQueuePropertiesOptions& options,
Expand Down
16 changes: 15 additions & 1 deletion sdk/storage/azure-storage-queues/src/queue_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,22 @@ namespace Azure { namespace Storage { namespace Queues {
{
(void)options;
_detail::QueueClient::GetQueuePropertiesOptions protocolLayerOptions;
return _detail::QueueClient::GetProperties(
auto ret = _detail::QueueClient::GetProperties(
*m_pipeline, m_queueUrl, protocolLayerOptions, context);
Models::QueueProperties queueProperties;
queueProperties.Metadata = std::move(ret.Value.Metadata);
if (ret.Value.ApproximateMessageCount > static_cast<int64_t>(INT32_MAX))
{
queueProperties.ApproximateMessageCount = -1;
}
else
{
queueProperties.ApproximateMessageCount
= static_cast<std::int32_t>(ret.Value.ApproximateMessageCount);
}
queueProperties.ApproximateMessageCountLong = ret.Value.ApproximateMessageCount;
return Azure::Response<Models::QueueProperties>(
std::move(queueProperties), std::move(ret.RawResponse));
}

Azure::Response<Models::SetQueueMetadataResult> QueueClient::SetMetadata(
Expand Down
9 changes: 5 additions & 4 deletions sdk/storage/azure-storage-queues/src/rest_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ namespace Azure { namespace Storage { namespace Queues {
Models::DeleteQueueResult response;
return Response<Models::DeleteQueueResult>(std::move(response), std::move(pRawResponse));
}
Response<Models::QueueProperties> QueueClient::GetProperties(
Response<Models::_detail::QueueProperties> QueueClient::GetProperties(
Core::Http::_internal::HttpPipeline& pipeline,
const Core::Url& url,
const GetQueuePropertiesOptions& options,
Expand All @@ -714,16 +714,17 @@ namespace Azure { namespace Storage { namespace Queues {
{
throw StorageException::CreateFromResponse(std::move(pRawResponse));
}
Models::QueueProperties response;
Models::_detail::QueueProperties response;
for (auto i = pRawResponse->GetHeaders().lower_bound("x-ms-meta-");
i != pRawResponse->GetHeaders().end() && i->first.substr(0, 10) == "x-ms-meta-";
++i)
{
response.Metadata.emplace(i->first.substr(10), i->second);
}
response.ApproximateMessageCount
= std::stoi(pRawResponse->GetHeaders().at("x-ms-approximate-messages-count"));
return Response<Models::QueueProperties>(std::move(response), std::move(pRawResponse));
= std::stoll(pRawResponse->GetHeaders().at("x-ms-approximate-messages-count"));
return Response<Models::_detail::QueueProperties>(
std::move(response), std::move(pRawResponse));
}
Response<Models::SetQueueMetadataResult> QueueClient::SetMetadata(
Core::Http::_internal::HttpPipeline& pipeline,
Expand Down
1 change: 1 addition & 0 deletions sdk/storage/azure-storage-queues/swagger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ directive:
"type": "object",
"x-ms-client-name": "QueueProperties",
"x-ms-sealed": false,
"x-namespace": "_detail",
"properties": {"__placeHolder": {"type": "integer"}}
};
```
Expand Down
33 changes: 33 additions & 0 deletions sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,39 @@ namespace Azure { namespace Storage { namespace Test {
EXPECT_TRUE(properties.Metadata.empty());
}

TEST_F(QueueClientTest, ApproximateMessageCount)
{
int messageCount = 0;
m_queueClient->EnqueueMessage("test");
++messageCount;
auto res = m_queueClient->GetProperties();
EXPECT_EQ(res.Value.ApproximateMessageCount, messageCount);
EXPECT_EQ(res.Value.ApproximateMessageCountLong, messageCount);

for (; messageCount < 10; ++messageCount)
{
m_queueClient->EnqueueMessage("test");
}
res = m_queueClient->GetProperties();
EXPECT_EQ(res.Value.ApproximateMessageCount, messageCount);
EXPECT_EQ(res.Value.ApproximateMessageCountLong, messageCount);
}

TEST_F(QueueClientTest, ApproximateMessageCountLong_PLAYBACKONLY_)
{
// Hardcode the x-ms-approximate-messages-count header to INT32_MAX in recording file.
m_queueClient->EnqueueMessage("test");
// Mock the recording file to INT32_MAX
auto res = m_queueClient->GetProperties();
EXPECT_EQ(res.Value.ApproximateMessageCount, INT32_MAX);
EXPECT_EQ(res.Value.ApproximateMessageCountLong, INT32_MAX);

// Hardcode the x-ms-approximate-messages-count header to INT64_MAX in recording file.
res = m_queueClient->GetProperties();
EXPECT_EQ(res.Value.ApproximateMessageCount, -1);
EXPECT_EQ(res.Value.ApproximateMessageCountLong, INT64_MAX);
}

TEST_F(QueueClientTest, AccessControlList_LIVEONLY_)
{
auto clientOptions = InitStorageClientOptions<Queues::QueueClientOptions>();
Expand Down
Loading